NAudio(.net)的时域均衡器

时间:2012-06-15 03:04:52

标签: c# .net signal-processing naudio equalizer

我希望为我正在开发的开源项目创建一个6(或更多)波段均衡器(iStudio)。我已经实现了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;
    }

这个功能非常简单。在缓冲区I中存储实时样本,filter是具有2个具有AR和MA系数的阵列的类。该函数由一个进程函数调用,该函数只通过缓冲区通过所有可用的过滤器并将结果汇​​总在一起:

    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));
            }
        }
    }

代码稍微缩短了,但它应该足够了。 均衡器有点工作,但它有两个问题,第一个是它产生的滞后(可能需要优化)和声音失真。每个过滤的缓冲区之间都有小爆炸。

所以我的问题是:为什么声音失真以及如何解决?

感谢。

1 个答案:

答案 0 :(得分:2)

我自己通过缓存几个值并在等式中使用它们来解决问题,当下一个缓冲区到达并且值超出当前缓冲区的索引时(在Filter函数中添加IF)。每个过滤器都需要自己的缓存,因此值来自相同的过滤器。

    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;
    }