อัลกอริทึมการสังเคราะห์การปรับความถี่


9

จากสิ่งที่ฉันอ่านฉันได้สร้างอัลกอริทึมสำหรับการสังเคราะห์เสียง FM ฉันไม่แน่ใจว่าฉันทำถูก เมื่อสร้างซอร์ฟแวร์ synth เครื่องมือฟังก์ชั่นจะใช้ในการสร้าง oscillator และโมดูเลเตอร์สามารถใช้ในการโมดูลความถี่ของ oscillator นี้ ฉันไม่รู้ว่าการสังเคราะห์ FM ควรจะทำงานเพื่อปรับคลื่นไซน์หรือไม่?

อัลกอริทึมใช้ฟังก์ชั่นคลื่นเครื่องมือและดัชนีโมดูเลเตอร์และอัตราส่วนสำหรับโมดูเลเตอร์ความถี่ สำหรับแต่ละโน้ตนั้นจะใช้ความถี่และเก็บค่าเฟสสำหรับสัญญาณพาหะและออสซิลเลเตอร์ ตัวดัดแปลงจะใช้คลื่นไซน์เสมอ

นี่คืออัลกอริทึมใน pseudocode:

function ProduceSample(instrument, notes_playing)
    for each note in notes_playing
        if note.isPlaying()
            # Calculate signal
            if instrument.FMIndex != 0 # Apply FM
                FMFrequency = note.frequency*instrument.FMRatio; # FM frequency is factor of note frequency.
                note.FMPhase = note.FMPhase + FMFrequency / kGraphSampleRate # Phase of modulator.
                frequencyDeviation = sin(note.FMPhase * PI)*instrument.FMIndex*FMFrequency # Frequency deviation. Max deviation is a factor of the FM frequency. Modulation is done by a sine wave. 
                note.phase = note.phase + (note.frequency + frequencyDeviation) / kGraphSampleRate # Adjust phase with deviation
                # Reset the phase value to prevent the float from overflowing
                if note.FMPhase >= 1
                    note.FMPhase = note.FMPhase - 1
                end if
            else # No FM applied
                note.phase = note.phase + note.frequency / kGraphSampleRate # Adjust phase without deviation
            end if
            # Calculate the next sample
            signal = signal + instrument.waveFunction(note.phase,instrument.waveParameter)*note.amplitude
            # Reset the phase value to prevent the float from overflowing
            if note.phase >= 1
                note.phase = note.phase - 1
            end if
        end if
    end loop
    return signal
end function 

ดังนั้นถ้าความถี่ของโน้ตอยู่ที่ 100Hz, FMRatio จะถูกตั้งค่าไว้ที่ 0.5 และ FMIndex คือ 0.1 มันควรสร้างความถี่ที่อยู่ระหว่าง 95Hz และ 105Hz ในรอบ 50Hz นี่คือวิธีที่ถูกต้องในการทำมัน การทดสอบของฉันแสดงให้เห็นว่ามันไม่ได้เสียงที่ถูกต้องเสมอไปโดยเฉพาะเมื่อการมอดูเลตและคลื่นสี่เหลี่ยม ตกลงหรือไม่ที่จะมอดูเลตและเห็นคลื่นสี่เหลี่ยมเช่นนี้หรือว่าเป็นคลื่นไซน์เท่านั้น?

นี่คือการใช้งานใน C และ CoreAudio:

static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData){
    AudioSynthesiser * audioController = (AudioSynthesiser *)inRefCon;
    // Get a pointer to the dataBuffer of the AudioBufferList
    AudioSampleType * outA = (AudioSampleType *) ioData->mBuffers[0].mData;
    if(!audioController->playing){
        for (UInt32 i = 0; i < inNumberFrames; ++i){
            outA[i] = (SInt16)0;
        }
        return noErr;
    }
    Track * track = &audioController->tracks[inBusNumber];
    SynthInstrument * instrument = (SynthInstrument *)track;
    float frequency_deviation;
    float FMFrequency;
    // Loop through the callback buffer, generating samples
    for (UInt32 i = 0; i < inNumberFrames; ++i){
        float signal = 0;
        for (int x = 0; x < 10; x++) {
            Note * note = track->notes_playing[x];
            if(note){
                //Envelope code removed
                //Calculate signal
                if (instrument->FMIndex) { //Apply FM
                    FMFrequency = note->frequency*instrument->FMRatio; //FM frequency is factor of note frequency.
                    note->FMPhase += FMFrequency / kGraphSampleRate; //Phase of modulator.
                    frequency_deviation = sinf(note->FMPhase * M_PI)*instrument->FMIndex*FMFrequency; //Frequency deviation. Max deviation is a factor of the FM frequency. Modulation is done by a sine wave. 
                    note->phase += (note->frequency + frequency_deviation) / kGraphSampleRate; //Adjust phase with deviation
                    // Reset the phase value to prevent the float from overflowing
                    if (note->FMPhase >= 1){
                        note->FMPhase--;
                    }
                }else{
                    note->phase += note->frequency/ kGraphSampleRate; //Adjust phase without deviation
                }
                // Calculate the next sample
                signal += instrument->wave_function(note->phase,instrument->wave_parameter)*track->note_amplitude[x];
                // Reset the phase value to prevent the float from overflowing
                if (note->phase >= 1){
                    note->phase--;
                }
            } //Else nothing added
        }
        if(signal > 1.0){
            signal = 1;
        }else if(signal < -1.0){
            signal = -1.0;
        }
        audioController->wave[audioController->wave_last] = signal;
        if (audioController->wave_last == 499) {
            audioController->wave_last = 0;
        }else{
            audioController->wave_last++;
        }
        outA[i] = (SInt16)(signal * 32767.0f);
    }
    return noErr;
}

คำตอบได้รับการชื่นชมอย่างมาก


3
ฉันขอแนะนำให้คุณอ่านการอภิปรายตามคำถามนี้ ในขณะที่ที่นี่คุณไม่ได้ทำการเปลี่ยนอย่างฉับพลันในความถี่เช่นเดียวกับคำถามอื่น ๆ การรักษาความต่อเนื่องของเฟสในสัญญาณ FM มีความสำคัญมากและทำให้มั่นใจได้ว่าสัญญาณ FM นั้นต่อเนื่อง ไม่ว่าจะเป็นรูปคลื่นไซน์หรือคลื่นสั้น (มีการเปลี่ยนแปลงอย่างฉับพลันในความถี่!) จะช่วยให้คุณหลีกเลี่ยงปัญหามากมาย
Dilip Sarwate

3
หากไม่ได้อ่านโค้ดขนาดใหญ่ของคุณมันก็คุ้มค่าที่จะถามว่าปัญหาคืออะไรกันแน่ คุณบอกว่าคุณไม่แน่ใจว่ามันใช้งานได้หรือไม่ อะไรทำให้คุณคิดว่ามันใช้งานไม่ได้?
Jason R

คำตอบ:


2

สิ่งที่คุณทำที่นี่คือการปรับเฟส นี่คือวิธีการ 'FM' synths เช่น Yamaha DX-7 ทำงาน บ่อยครั้งที่ออสซิลเลเตอร์ synth ถูกปรับในระดับดนตรีไม่ใช่สเกลเชิงเส้น Hz แบบเส้นตรง ดังนั้นการปรับระดับเสียงโดยตรงส่งผลให้เกิดการเปลี่ยนระดับเสียงที่ไม่ต้องการนั่นคือเหตุผลที่การปรับเฟสเหมาะสมกว่า คุณสามารถปรับรูปทรงคลื่นใด ๆ อย่างไรก็ตามรูปร่างที่ซับซ้อนมากขึ้นจะเป็นนามแฝงได้ง่ายขึ้น แม้แต่บาปที่ได้รับการปรับก็สามารถใช้นามแฝงได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.