1

私が取り組んでいるオープンソースプロジェクト(iStudio)用に6(またはそれ以上)のバンドイコライザーを作成しようとしています。すでにSkypeFxイコライザーを実装しましたが、3バンドイコライザーしかありませんが、もっとプロフェッショナルなものが欲しいです。そこで、Matlabを使用して自分でいくつかのフィルターを設計し、サンプルイコライザー用に6つのARMAフィルターを設計しました。もちろん、出力をリアルタイムでフィルタリングする必要があります。それで、私はこの目的のために微分方程式を実行し続けました。

    private double[] Filter(float[] buffer, SignalFilter filter, float filterWeight, int count)
    {
        double[] y = new double[buffer.Length];
        for (int n = 0; n < count; n++)
        {
            y[n] = 0.0f;
            for (int k = 0; k < filter.B.Count; k++)
            {
                if (n - k >= 0)
                {
                    y[n] = y[n] + filter.B[k] * (double)buffer[n - k];
                }
            }

            for (int k = 1; k < filter.A.Count; k++)
            {
                if (n - k >= 0)
                {
                    y[n] = y[n] - filter.A[k] * y[n - k];
                }
            }
        }

        return y;
    }

この関数は非常に簡単です。リアルタイムサンプルを格納しているバッファーでは、フィルターはAR係数とMA係数を持つ2つの配列を持つクラスです。この関数はプロセス関数によって呼び出されます。プロセス関数は、使用可能なすべてのフィルターにバッファーを渡し、結果を合計するだけです。

    public void Process(float[] buffer, int offset, int count)
    {
        List<double[]> filtered = new List<double[]>();

        for (int i = 0; i < _filters.Count - 5; i++)
        {
            filtered.Add(Filter(buffer, _filters[i], Values[i], count));
        }
        for (int i = 0; i < count; i++)
        {
            buffer[i] = 0.0f;
            for (int x = 0; x < filtered.Count; x++)
            {
                buffer[i] += (float)(filtered[x][i] * ((Values[x] + 1) / 2));
            }
        }
    }

コードは少し短縮されましたが、それで十分です。イコライザーはある程度機能しますが、2つの問題があります。1つは、イコライザーが作成するラグ(おそらく最適化が必要)とサウンドの歪みです。フィルタリングされた各バッファ間には少し前髪があります。

だから私の質問はこれです:なぜ音が歪むのですか、そしてそれを修正する方法は?

ありがとう。

4

1 に答える 1

2

次のバッファが到着し、値が現在のバッファのインデックスから外れたときに、いくつかの値をキャッシュして方程式で使用することにより、問題を自分で解決しました(Filter関数のIFにelseを追加します)。各フィルターには独自のキャッシュが必要なため、値は同じフィルターからのものです。

    private double[] Filter(float[] buffer, SignalFilter filter, int count, int index)
    {
        double[] y = new double[count];
        for (int n = 0; n < count; n++)
        {
            for (int k = 0; k < filter.B.Count; k++)
            {
                if (n - k >= 0)
                {
                    y[n] = y[n] + filter.B[k] * buffer[n - k];
                }
                else if (_cache.GetRawCache ().Count > 0)
                {
                    double cached =  _cache.GetRawCache ()[_cache.GetRawCache().Count + (n - k)];
                    y[n] = y[n] + filter.B[k] * cached;
                }
            }

            for (int k = 1; k < filter.A.Count; k++)
            {
                if (n - k >= 0)
                {
                    y[n] = y[n] - filter.A[k] * y[n - k];
                }
                else if (_cache.GetCache(index).Count > 0)
                {
                    double cached =  _cache.GetCache(index)[_cache.GetCache(index).Count + (n - k)];
                    y[n] = y[n] - filter.A[k] * cached;
                }
            }
        }

        return y;
    }
于 2012-06-16T22:02:57.347 に答える