7

私が読んだものに基づいて、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 

したがって、ノートの周波数が100Hzの場合、FMRatioは0.5に設定され、FMIndexは0.1であり、50Hzサイクルで95Hzから105Hzの間の周波数を生成するはずです。これは正しい方法ですか。私のテストでは、特にのこぎり波や方形波を変調する場合は、必ずしも正しく聞こえるとは限りません。このように鋸波と方形波を変調しても大丈夫ですか、それとも正弦波のみですか?

これは、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;
}

回答は大歓迎です。

4

3 に答える 3

8

赤眼:

あなたの主な質問に答えるには、はい、正弦波以外の波形を変調することはまったく問題ありません。実際、それが FM の得意分野です。正弦波を変調すると、非常に退屈なサウンドの出力が得られますが、同じ変調でより複雑な波形を入力すると、はるかに興味深い結果が得られます。

これはせいぜい過度の単純化であり、おそらく完全に誤りです。正弦波を正弦波で変調することで、複雑で「退屈」ではない幅広いサウンドを完全に作成できます。

対照的に、複雑な波形は結果として生じる側波帯の数を大幅に増やし、予測可能な結果を​​達成することをはるかに困難にします。FM に関するほとんどのドキュメンテーション (実際には、ヤマハの「FM」を含む多くの一般的なケースでほぼ同等の PHASE 変調 (PM) です) は、正弦波のみに関係しています。

参考までに (ご存じない方のために)、最も有名な FM シンセはおそらくヤマハ DX7 で、当時は革新的でした (また、MIDI を備えた最初のシンセの 1 つでもありました)。

言及すべきもう 1 つのことは、FM 合成がデジタル時代の始まりであったため、波形がデジタルで生成されたため、正弦波、方形波、三角波よりも洗練された波形を使用して興味深いサウンドを作成したことです。」

これは間違いなく完全に誤りです。ヤマハの DX7 と多くの初期の FM (実際には PM) シンセは正弦波のみを提供していましたが、上で示したように、それらは依然として非常に多くの非「退屈な」音を出すことができます。「より洗練された波形」は関係ありませんでした。

ヤマハが他の波形を追加したのは後になってからであり、上で述べたように、正弦波によって作成される側波帯の予測可能性と比較すると、それらの有用性はいくぶん疑わしい.

これは、より良いサウンドを得るために必要なことかもしれません - 正弦波を生成して変調するだけでなく、複雑な波形を使用してください。」

または、パラメータ(比率、インデックスなど)の適切な配置と組み合わせで正弦波を使用するだけです。

正弦波を使用した FM/PM が、多くのユーザーにとってスタジオ品質 (または単にアナログのようなもの) の結果をすぐに生成しないという事実は、そうすることができないことを示すものではありません。

于 2013-09-07T13:10:59.343 に答える
4

最終的に、位相変調を使用することにしました。多くのシンセサイザーは、FM とラベル付けされていても、位相変調を使用していることがわかりました。

実装は簡単でした:

signal += wave_function(note_phase * note_frequency / sample_rate + fm_index * sin(note_phase * fm_frequency * pi / sample_rate))*note_amplitude
于 2012-01-20T20:01:47.027 に答える
3

良い質問です。いくつかの考え/アイデアを提供しようと思います...

あなたの主な質問に答えるには、はい、正弦波以外の波形を変調することはまったく問題ありません。実際、それが FM の得意分野です。正弦波を変調すると、非常に退屈なサウンドの出力が得られますが、同じ変調でより複雑な波形を入力すると、はるかに興味深い結果が得られます。参考までに (ご存じない方のために)、最も有名な FM シンセはおそらくヤマハ DX7で、当時は革新的でした (また、MIDI を備えた最初のシンセの 1 つでもあります)。

言及すべきもう1つのことは、FM合成がデジタル時代の始まりであったため、波形がデジタルで生成されたため、正弦波/方形波/三角波よりも洗練された波形を使用して興味深い音を作成したことです. これは、より良いサウンドを得るために必要なことかもしれません - 単にサイン波を生成して変調するのではなく、複雑な波形を使用してください。

コードを見ると、FM を正しく実行しているように見えます。ただし、変調周波数は通常、コードのようにノート周波数の一部ではなく固定されていると思います。これを試して、探しているものに近いかどうかを確認する価値があるかもしれません.

それが少し役立つことを願っています。

于 2011-12-23T21:51:56.950 に答える