1

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.

Legoless
  • 10,942
  • 7
  • 48
  • 68
  • This might have a better time getting answered on http://dsp.stackexchange.com/. – earlNameless Jun 15 '12 at 03:11
  • Thanks, but I figured this is a programming error, because theoretically it should work. – Legoless Jun 15 '12 at 03:17
  • do you let the float values go above 1.0? if so there will be distortion when converting to 16 bit to send to the soundcard – Mark Heath Jun 15 '12 at 12:23
  • The float values do not go over 1.0 or -1.0, I actually have those checks implemented just to be sure (but were stripped from the code in this post). – Legoless Jun 16 '12 at 04:26
  • this one should work 2: http://stackoverflow.com/questions/22018898/sound-with-equalizer – Florian May 04 '14 at 14:17

1 Answers1

2

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;
    }
Legoless
  • 10,942
  • 7
  • 48
  • 68