Pregunta

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.

¿Fue útil?

Solución

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.

Otros consejos

Typically you would run the time domain data through a time domain filter. Another method, which is equivalent, is to take the FFT of the data and the FFT of the filter, multiply it in the frequency domain, then take the inverse FFT. For small filters the time domain approach is generally faster. You would typically do this on frames of the data, say 8192 samples passed through a filter. Then repeat for subsequent frames. Without looking at your code I'm unable to provide more help. Also, take a look at these examples using Intel's IPP. There's both time and frequency domain implementations that should help to get you going.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top