Вопрос

I am looking to create a 6 (or more) band equalizer for a open source project I am working on (iStudio). I already implemented the SkypeFx equalizer, but it only has 3 band equalizer, but I want a more professional one. So I went onto designing few filters myself using Matlab and I designed 6 ARMA filters for a sample equalizer. I need to filter output in real time of course. So I went on with implementing a differential equation for this purpoise.

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

This function is pretty straightforward. In buffer I am storing the real time samples, filter is a class with 2 arrays with AR and MA coefficients. The function is called by a process function, which only pass the buffer through all available filters and sum the result together:

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

The code was a little shortened, but it should be enough. The equalizer somewhat works, but it has two problems, first one being the lag it creates (probably needs optimization) and the sound distortion. There are little bangs between each filtered buffer.

So my question is this: Why is the sound distorted and how to fix it?

Thanks.

Это было полезно?

Решение

I solved the problem myself by caching few values and using them in the equation, when the next buffer arrives and the values go out of index of current buffer (adds else to the IF in Filter function). Each filter requires own cache, so the values are from same filter.

    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;
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top