Search code examples
c#naudiolowpass-filter

Integrate Audio and Filter Method


Hi I have an Audio track which i want to play after passing it through a low pass filter. I am using NAudio's BiQuadFilter class for the filter part. It has an Inbuilt method for it. The first parameter is sample rate, second is the cutoff frequency and third is Quality factor Q. I am not being able to integrate the Filter method with my audio part. Here is my code:

        var r = BiQuadFilter.LowPassFilter(44100, 1500, 1);
        var reader = new WaveFileReader(File.OpenRead(@"D:1.wav"));
        var waveOut=new WaveOut();
        waveOut.Init(reader);
        waveOut.Play();

I Managed to finally get it working. Don't know if it's correct. Here's what I did:

    public MyFilter(ISampleProvider sourceProvider,int cutOffFreq)
    {
        this.sourceProvider = sourceProvider;
        this.cutOffFreq = cutOffFreq;

        channels = sourceProvider.WaveFormat.Channels;
        filters = new BiQuadFilter[channels];
        CreateFilters();
    }

    private void CreateFilters()
    {
        for (int n = 0; n < channels; n++)
            if (filters[n] == null)
                filters[n] = BiQuadFilter.LowPassFilter(44100, cutOffFreq, 1);
            else
                filters[n].SetLowPassFilter(44100, cutOffFreq, 1);
    }

    public WaveFormat WaveFormat { get { return sourceProvider.WaveFormat; } }

    public int Read(float[] buffer, int offset, int count)
    {
        int samplesRead = sourceProvider.Read(buffer, offset, count);

        for (int i = 0; i < samplesRead; i++)
            buffer[offset + i] = filters[(i % channels)].Transform(buffer[offset + i]);

        return samplesRead;
    }

is this correct?


Solution

  • The BiQuadFilter has a method Transform(float[] inBuffer, float[] outBuffer) which might work out for you. To do the conversion I would create an IWaveProvider which calls the method.

    An IWaveProvider is a class which provides audio data. I recommend to set the source of the audio data in the constructor:

    public class MyWaveProvider : NAudio.Wave.IWaveProvider
    {
        private readonly NAudio.Wave.IWaveProvider inWaveProvider;
    
        public MyWaveProvider(NAudio.Wave.IWaveProvider inWaveProvider)
        {
            this.inWaveProvider = inWaveProvider;
            this.WaveFormat = inWaveProvider.WaveFormat;
        }
    
        public NAudio.Wave.WaveFormat WaveFormat { get; private set; }
    
        public int Read(byte[] outBuffer, int offset, int count)
        {
            return this.inWaveProvider.Read(outBuffer, offset, count);
        }
    }
    

    You see in the Read() method that the bytes are read from the source and written into the destination buffer. At that point you can manipulate the data using BiQuadFilter.Transform(float[] inBuffer, float[] outBuffer). I leave the type inconsistency as an exercise for you. I really don't know.

    When you pimped the Read() method to use your BiQuadFilter.Transfrom() method, you can call the following code:

    var r = BiQuadFilter.LowPassFilter(44100, 1500, 1);
    var reader = new WaveFileReader(File.OpenRead(@"D:1.wav"));
    var filter = new MyWaveProvider(reader, r); // reader is the source for filter
    var waveOut = new WaveOut();
    waveOut.Init(filter); // filter is the source for waveOut
    waveOut.Play();
    

    Good Luck!