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:

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!

c#audiosignal-processingfft 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:

And isolating the regular waveforms vs low-pass waveforms: