Search code examples
c#audiofftnaudiolowpass-filter

Using a low pass filter on audio


I am VERY new in the world of DSP and filtering. Like I started a week ago. Anyway, I have been looking for ways to use filters (low-pass, high-pass, notch, etc.) on some data I am getting. The data comes in an array of doubles and I can get more than 1 million points in this array. I am trying to filter out sound given a certain cutoff frequency but cannot get any algorithm to work. I have been up and down the internet and tried a bunch of different libraries and methods but I can't get any results. I am partial to the NAudio library because it seems to have everything I need (FFT and filtering by the BiQuadFilter class). I am pretty sure my problem is my extreme lack of the knowledge and math to get the desired output. Judging from what I have read, here is how I believe the process should go:

  1. Insert data into FFT to put data into frequency domain
  2. Pass resulting data into a filter (low, high, notch)
  3. Do IFFT from results in step 2 to get back into time domain
  4. Play sound

Is this the right way to filter audio? Can I shove the entire array into the FFT or do I have to break it up in smaller chunks? What do I do with the complex numbers that I get in the FFT result (ie just use the real part and throw away the imaginary, or use the magnitude and phase)? I really have no idea what the "right way" is.

EDIT

I finally got it working! Here is what I did:

        byte[] data = doubleArray.SelectMany(value => BitConverter.GetBytes(value)).ToArray();
        wms = new WaveMemoryStream(data, sampleRate, (ushort)audioBitsPerSample, (ushort)channels);
        WaveFileReader wfr = new WaveFileReader(wms);
        SampleChannel sample = new SampleChannel(wfr, false);
        LowPassSampleProvider sampleProvider = new LowPassSampleProvider(sample);
        WaveOutEvent player = new WaveOutEvent();
        player.Init(sampleProvider);
        player.Play();

doubleArray is the array of my accelerometer data, which currently holds 1 million points with each one somewhere around 1.84...

WaveMemoryStream is a class I found on another post here

LowPassSampleProvider is a class I made that implements ISampleProvider and passes the samples to the BiQuadFilter.LowPassFilter function.


Solution

  • The BiQuadFilter in NAudio operates in the time domain. You don't need to use FFT with it. Pass each sample into the Transform method to get the output sample. Use two filters one for left and one for right if you have stereo audio.

    I typically make an ISampleProvider implementation that in the Read method reads from a source ISampleProvider (such as an AudioFileReader) and passes the samples through the filter.