1

NAudio を使用して C# でシンセサイザーを作成しています。周波数間をスムーズにスライドさせようとしています。しかし、関連する数学について何かを理解していないと感じています。正しい次のピッチに切り替える前に、高いピッチで激しくスライドします。

あるピッチから別のピッチにスライドする数学的に正しい方法は?

コードは次のとおりです。

public override int Read(float[] buffer, int offset, int sampleCount) { int sampleRate = WaveFormat.SampleRate;

        for (int n = 0; n < sampleCount; n++)
        {
            if (nextFrequencyQueue.Count > 0)
            {                    
                nextFrequency = nextFrequencyQueue.Dequeue();
            }

            if (nextFrequency > 0 && Frequency != nextFrequency)
            {
                if (Frequency == 0) //special case for first note
                {
                    Frequency = nextFrequency;
                }
                else //slide up or down to next frequency
                {
                    if (Frequency < nextFrequency)
                    {
                        Frequency = Clamp(Frequency + frequencyStep, nextFrequency, Frequency);
                    }
                    if (Frequency > nextFrequency)
                    {
                        Frequency = Clamp(Frequency - frequencyStep, Frequency, nextFrequency);
                    }
                }
            }

            buffer[n + offset] = (float)(Amplitude * Math.Sin(2 * Math.PI * time * Frequency));
            try
            {
                time += (double)1 / (double)sampleRate;
            }
            catch
            {
                time = 0;
            }
        }
        return sampleCount;
    }
4

3 に答える 3

2

波動関数を決定するために絶対時間を使用しているため、周波数をごくわずかに変更すると、次のサンプルは、その新しい周波数で実行を開始した場合のサンプルになります。

確立された最良のアプローチはわかりませんが、おそらく十分な単純なアプローチは、位相を計算し (φ = t mod 1/f old )、t を調整して新しい周波数の下で位相を維持することです (t = φ/f新しい)。

よりスムーズなアプローチは、一次導関数を保持することです。波自体とは異なり、一次導関数の振幅は周波数によって変化するため、これはより困難です。つまり、位相を維持するだけでは不十分です。いずれにせよ、周波数をスムーズに変化させていることを考えると、この追加された複雑さはほぼ間違いなくやり過ぎです。

于 2012-12-26T04:21:50.567 に答える
2

1 つのアプローチは、ウェーブテーブルを使用することです。配列内に正弦波の完全なサイクルを作成すると、Read 関数で単純に検索できます。読み取る各サンプルは、目的の出力周波数から計算された量だけ進みます。次に、新しい周波数にグライドしたい場合は、テーブルへのルックアップの新しいデルタを計算し、そこに直行する代わりに、デルタを段階的に調整して、設定された期間にわたって新しい値に移動します (「グライド' またはポルタメント タイム)。

于 2012-12-26T08:36:45.210 に答える