11

私はソフトウェア シンセサイザーを作成しており、44.1 kHz のサンプルレートで帯域制限されたエイリアスのない波形をリアルタイムで生成する必要があります。のこぎり波を 2 つ混ぜ合わせることでパルス波を生成できるので、現時点ではのこぎり波で十分です。

これまでのところ、次のアプローチを試しました。

  1. 起動時に異なる帯域制限周波数で 1 サイクルの完全に帯域制限された波形サンプルを事前計算し、次に最も近い 2 つのサンプルを混合して再生します。大丈夫だと思いますが、あまりエレガントではありません。多くのサンプルが必要です。そうしないと、それらの間の「ギャップ」が聞こえます。補間とミキシングも、かなり CPU を集中的に使用します。

  2. のこぎり波を得るために、一連の DC 補償 sinc パルスを統合します。DC補償を正確に行わないと、波がゼロから離れてドリフトすることを除いて、素晴らしい音です(これは本当に難しいことがわかりました)。DC の問題は、積分器に少し漏れを追加することで軽減できますが、低周波数が失われます。

だから、私の質問は:これが行われる通常の方法は何ですか?提案されたソリューションは、一度に多くのボイスに対してリアルタイムで実行する必要があるため、CPU の点で効率的でなければなりません。

4

4 に答える 4

8

帯域制限された波形を生成する高速な方法の 1 つは、帯域制限ステップ (BLEP) を使用することです。帯域制限されたステップ自体を生成します。

ここに画像の説明を入力

それをウェーブテーブルに保存し、各トランジションを帯域制限されたステップに置き換えて、次のような波形を作成します。

ここに画像の説明を入力

Band-Limited Sound Synthesisのウォークスルーを参照してください。

この BLEP は因果関係がないため (未来に拡張することを意味します)、リアルタイム波形を生成するには、MinBLEPと呼ばれる最小位相帯域制限ステップを使用することをお勧めします。過去に:

MinBLEP はこのアイデアをさらに発展させ、ウィンドウ化された sinc を取得し、最小位相再構成を実行してから、結果を統合してテーブルに保存します。オシレータを作成するには、波形の各不連続点に MinBLEP を挿入するだけです。したがって、方形波の場合は波形が反転する場所に MinBLEP を挿入し、のこぎり波の場合は値が反転する場所に MinBLEP を挿入しますが、通常どおりランプを生成します。

于 2010-04-28T19:10:14.233 に答える
5

帯域制限された波形生成にアプローチする方法はたくさんあります。いつものように、品質に対して計算コストをトレードすることになります。

こちらのサイトをご覧になることをお勧めします:

http://www.musicdsp.org/

アーカイブをチェック!いい素材がいっぱいです。「帯域制限」というキーワードで検索しました。少なくとも 1 週間忙しくしていれば、ポップアップする資料です。

ところで-それがあなたが探しているものかどうかはわかりませんが、数年前にエイリアスを減らした(実際には帯域制限されていない)波形生成を行いました。最後のサンプル位置と現在のサンプル位置の間の積分を計算しました。従来のシンセ波形の場合、統合間隔を特異点で分割すると(たとえば、のこぎり波がリセットされるとき)、かなり簡単に行うことができます。CPU の負荷は低く、品質は私のニーズに適していました。

私は同じドリフトの問題を抱えていましたが、積分に非常に低いカットオフ周波数のハイパスを適用すると、その影響が取り除かれました. とにかく、本物のアナログシンセはサブヘルツ領域に下がらないので、多くを見逃すことはありません。

于 2008-10-06T17:49:42.677 に答える
2

これは私が思いついたもので、ニルスのアイデアに触発されました。他の人に役立つ場合に備えて、ここに貼り付けます。最後のサンプルからの位相の変化をカーネルサイズ(またはカットオフ)として使用して、のこぎり波を分析的にボックスフィルター処理するだけです。それはかなりうまく機能し、非常に高い音にいくつかの可聴エイリアシングがありますが、通常の使用法では素晴らしい音になります。

エイリアシングをさらに減らすには、カーネルサイズを少し大きくして、たとえば2 * phaseChangeにすることもできますが、最高周波数が少し失われます。

また、SPを参照して同様のトピックを探したときに見つけたもう1つの優れたDSPリソースは次のとおりです。C++のSynthesis ToolKit(STK)。これは、便利なDSPツールがたくさんあるクラスライブラリです。帯域制限された波形ジェネレーターを使用する準備もできています。彼らが使用する方法は、私が最初の投稿で説明したようにsincを統合することです(私よりもうまくいくと思いますが...)。

float getSaw(float phaseChange)
{
    static float phase = 0.0f;
    phase = fmod(phase + phaseChange, 1.0f);
    return getBoxFilteredSaw(phase, phaseChange);
}

float getPulse(float phaseChange, float pulseWidth)
{
    static float phase = 0.0f;
    phase = fmod(phase + phaseChange, 1.0f);
    return getBoxFilteredSaw(phase, phaseChange) - getBoxFilteredSaw(fmod(phase + pulseWidth, 1.0f), phaseChange);
}

float getBoxFilteredSaw(float phase, float kernelSize)
{
    float a, b;

    // Check if kernel is longer that one cycle
    if (kernelSize >= 1.0f) {
        return 0.0f;
    }

    // Remap phase and kernelSize from [0.0, 1.0] to [-1.0, 1.0]
    kernelSize *= 2.0f;
    phase = phase * 2.0f - 1.0f;

    if (phase + kernelSize > 1.0f)
    {
        // Kernel wraps around edge of [-1.0, 1.0]
        a = phase;
        b = phase + kernelSize - 2.0f;
    }
    else
    {
        // Kernel fits nicely in [-1.0, 1.0]
        a = phase;
        b = phase + kernelSize;
    }

    // Integrate and divide with kernelSize
    return (b * b - a * a) / (2.0f * kernelSize);
}
于 2008-10-06T19:29:26.360 に答える