20

私は、WAV ファイルをさまざまな速度で再生するコードを書いているので、波形が遅くてピッチが低くなるか、または速くてピッチが高くなります。私は現在、次のように単純な線形補間を使用しています。

            int newlength = (int)Math.Round(rawdata.Length * lengthMultiplier);
            float[] output = new float[newlength];

            for (int i = 0; i < newlength; i++)
            {
                float realPos = i / lengthMultiplier;
                int iLow = (int)realPos;
                int iHigh = iLow + 1;
                float remainder = realPos - (float)iLow;

                float lowval = 0;
                float highval = 0;
                if ((iLow >= 0) && (iLow < rawdata.Length))
                {
                    lowval = rawdata[iLow];
                }
                if ((iHigh >= 0) && (iHigh < rawdata.Length))
                {
                    highval = rawdata[iHigh];
                }

                output[i] = (highval * remainder) + (lowval * (1 - remainder));
            }

これは問題なく動作しますが、再生周波数を下げた場合 (つまり、速度を落とした場合) にのみ問題なく聞こえる傾向があります。再生時にピッチを上げると、おそらくサンプル情報が失われるため、この方法では高周波のアーティファクトが生成される傾向があります。

バイキュービック法やその他の補間法は、私のコード例のように最も近い 2 つのサンプル値以外を使用してリサンプリングすることは知っていますが、ここで線形補間法を置き換えるためにプラグインできる適切なコード サンプル (できれば C#) が見つかりません。 .

誰かが良い例を知っていますか、または単純なバイキュービック補間法を書くことができますか? 必要に応じて、これに報奨金を出します。:)

更新: 補間メソッドの C# 実装をいくつか示します (最初のものは Donnie DeBoer に、2 番目のものは nosredna に感謝します)。

    public static float InterpolateCubic(float x0, float x1, float x2, float x3, float t)
    {
        float a0, a1, a2, a3;
        a0 = x3 - x2 - x0 + x1;
        a1 = x0 - x1 - a0;
        a2 = x2 - x0;
        a3 = x1;
        return (a0 * (t * t * t)) + (a1 * (t * t)) + (a2 * t) + (a3);
    }

    public static float InterpolateHermite4pt3oX(float x0, float x1, float x2, float x3, float t)
    {
        float c0 = x1;
        float c1 = .5F * (x2 - x0);
        float c2 = x0 - (2.5F * x1) + (2 * x2) - (.5F * x3);
        float c3 = (.5F * (x3 - x0)) + (1.5F * (x1 - x2));
        return (((((c3 * t) + c2) * t) + c1) * t) + c0;
    }

これらの関数では、x1 は推定しようとしているポイントの前のサンプル値であり、x2 はポイントの後のサンプル値です。x0 は x1 の左側、x3 は x2 の右側です。t は 0 から 1 になり、推定しているポイントと x1 ポイントの間の距離です。

Hermite 法はかなりうまく機能しているようで、ノイズがいくらか減少しているように見えます。さらに重要なことは、波をスピードアップすると、音が良くなるように見えることです。

4

4 に答える 4

20

オーディオ補間に関する私のお気に入りのリソース (特にリサンプリング アプリケーション) は、Olli Niemitalo の「Elephant」論文です。

私はこれらのいくつかを使用しましたが、それらは素晴らしい音です (比較的ノイズの多いストレート キュービック ソリューションよりもはるかに優れています)。スプライン形式、エルミート形式、ワッテ、放物線などがあります。それらをオーディオの観点から説明します。これは、典型的な単純な多項式フィッティングだけではありません。

しかもコード付き!

どちらを使用するかを決定するには、アルゴリズムを演算子の複雑さ (乗算の数と加算の数) にグループ化した 60 ページの表から始めることをお勧めします。次に、最適な S/N ソリューションの中から選択してください。最終的な選択を行うためのガイドとして耳を使用してください。注: 一般に、SNRが高いほど優れています。

于 2009-07-14T15:26:40.723 に答える
7
double InterpCubic(double x0, double x1, double x2, double x3, double t)
{
   double a0, a1, a2, a3;

   a0 = x3 - x2 - x0 + x1;
   a1 = x0 - x1 - a0;
   a2 = x2 - x0;
   a3 = x1;

   return a0*(t^3) + a1*(t^2) + a2*t + a3;
}

ここで、x1 と x2 は補間されるサンプルで、x0 は x1 の左隣、x3 は x2 の右隣です。t は [0, 1] で、x1 と x2 の間の補間位置を示します。

于 2009-07-14T15:18:54.470 に答える
3

正直なところ、キュービック補間は一般に、線形よりもオーディオに優れているわけではありません。線形補間を改善するための簡単な提案は、アンチエイリアシング フィルタを使用することです (信号を短くするか長くするかに応じて、補間の前または後に)。もう 1 つのオプション (計算コストは​​高くなりますが) は、非常に高品質で実行できる sinc-interpolation です。

これらの両方をWDLの一部として実行できる単純な LGPL リサンプリング コードをいくつかリリースしました(resample.h を参照)。

于 2010-07-02T04:08:16.663 に答える