Алгоритм синтезу частоти модуляції


9

На основі прочитаного я склав алгоритм синтезу FM-звуку. Я не впевнений, чи правильно я це зробив. При створенні програмного приладу синтезатора програмного забезпечення використовується функція генерації генератора, а модулятор може використовуватися для модулювання частоти цього генератора. Я не знаю, чи повинен синтез FM працювати лише для модуляції синусоїд?

Алгоритм приймає функцію хвилі приладів та індекс модулятора та співвідношення для модулятора частоти. Для кожної ноти він приймає частоту і зберігає значення фази для несучих і модуляторних осциляторів. Модулятор завжди використовує синусоїду.

Це алгоритм у псевдокоді:

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 

Отже, якщо частота ноти становить 100 ГГц, FMRatio встановлюється в 0,5, а FMIndex - 0,1, він повинен виробляти частоти між 95 Гц і 105 Гц в циклі 50 ГГц. Це правильний спосіб зробити це. Мої тести показують, що це не завжди звучить правильно, особливо при модулюванні пилки та квадратних хвиль. Чи добре модулювати пилу та квадратні хвилі, як це, чи це тільки для синусоїд?

Це реалізація в 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 є фазовим безперервно, незалежно від модулюючої форми хвилі, синусоїдальної чи пилоподібної чи квадратної хвилі (там різка зміна частоти!), допоможе вам уникнути безлічі проблем.
Діліп Сарват

3
Не читаючи вашої великої купи коду, варто запитати: у чому саме проблема? Ви кажете, що не впевнені, працює він чи ні. Що конкретно змушує вас думати, що це не працює?
Джейсон R

Відповіді:


2

Що ви тут робите - це фазова модуляція. Ось так працюють «FM» синтезатори, як Yamaha DX-7. Часто генератори синтезаторів налаштовуються на музичну шкалу, а не на пряму лінійну шкалу Гц. Таким чином, модуляція висоти безпосередньо призводить до небажаного зміщення кроку, тому фазова модуляція є більш підходящою. Ви можете модулювати будь-яку форму хвилі, однак складніші форми будуть псевдоніми легшими. Навіть модульований гріх може бути псевдонімом, тому це не заборонено.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.