Determine amplitude of low frequency signals using FFT

ose Source

I am totally new to signal processing and am trying to make a program that shows the amplitude of low frequency signals in a PCM (WAV) file.

So far, I've been able to read in the WAV file and populate an array (actually a multi-dimensional array, one for each channel, but let's consider only on a channel-by-channel basis) of float with the data points of the sound file taken from the WAV. Each data point is an amplitude. In short, I have the time-domain representation of the sound wave. I use this to draw a graph of the amplitude of the wave with respect to time, which looks like:

Amplitude with respect to time

My goal is to do exactly the same, but only display frequencies below a certain value (eg. 350Hz). To be clear, it's not that I want to display a graph in the frequency domain (ie. after a Fast Fourier Transform). I want to display the same amplitude vs. time graph, but for frequencies in the range [0, 350Hz].

I'm looking for a function that can do:

// Returns an array of data points that contains
// amplitude data points, after a low pass filter
float[] low_pass_filter(float[] original_data, float low_pass_freq=350.0)

I've read up on the FFT, read Chris Lomont's code for the FFT and understand the "theory" behind a low-pass filter, but I'm finding it difficult to get my head around how to actually implement this specific function (above). Any help (+ explanations) would be greatly appreciated!



answered 3 years ago ose #1

I ended up using this example which works really well. I wrapped it a bit nicer and ended up with:

    /// <summary>
    /// Returns a low-pass filter of the data
    /// </summary>
    /// <param name="data">Data to filter</param>
    /// <param name="cutoff_freq">The frequency below which data will be preserved</param>
    private float[] lowPassFilter(ref float[] data, float cutoff_freq, int sample_rate, float quality_factor=1.0f)
        // Calculate filter parameters
        float O = (float)(2.0 * Math.PI * cutoff_freq / sample_rate);
        float C = quality_factor / O;
        float L = 1 / quality_factor / O;

        // Loop through and apply the filter
        float[] output = new float[data.Length];
        float V = 0, I = 0, T;
        for (int s = 0; s < data.Length; s++)
            T = (I - V) / C;
            I += (data[s] * O - V) / L;
            V += T;
            output[s] = V / O;

        return output;

The output of both regular and low-pass waveforms:

Both waveforms

And isolating the regular waveforms vs low-pass waveforms:

Regular only

Low-pass only

comments powered by Disqus