naudio / NAudio

Audio and MIDI library for .NET
MIT License
5.55k stars 1.1k forks source link

Low pass filter not working #895

Open dipincluster opened 2 years ago

dipincluster commented 2 years ago

I am trying to use low pass filter to remove anything above 500 Hz, to test the implementation I have created a sign wave at 4kHz using Signal Generator. This is my sample provider implementation

public class FilterSampleProvider : ISampleProvider
    {
        private ISampleProvider sourceProvider;
        private float cutOffFreq;
        private float bandWidth;
        private BiQuadFilter filter;
        public FilterSampleProvider(ISampleProvider sourceProvider, int cutOffFreq, int bandWidth)
        {
            this.sourceProvider = sourceProvider;
            this.cutOffFreq = cutOffFreq;
            this.bandWidth = bandWidth;

            filter = BiQuadFilter.LowPassFilter(sourceProvider.WaveFormat.SampleRate, this.cutOffFreq, this.bandWidth);

        }
        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] = filter.Transform(buffer[offset + i]);

            return samplesRead;
        }
    }

I am generating a sin wave at 4000 hz frequency using the below code

            var sine20Seconds = new SignalGenerator(44100, 1)
            {
                Gain = 1,
                Frequency = 4000,
                Type = SignalGeneratorType.Sin,
            }.Take(TimeSpan.FromSeconds(60));

Then I am creating a file and again reading the file because i want the original file to compare with the output.

WaveFileWriter.CreateWaveFile("filteroutput.wav", sine20Seconds.ToWaveProvider());

var reader = new WaveFileReader(File.OpenRead("filteroutput.wav"));

Then creating my filter sample provider with a cutoff frequency of 500, output I am expecting is a file without the sin wave hum

 filterSampleProvider = new FilterSampleProvider(reader.ToSampleProvider(),500,1);

 filteredWaveProvider = filterSampleProvider.ToWaveProvider();

I believe the q is for Quality Factor so I am passing 1

WaveFileWriter.CreateWaveFile("filteroutput1.wav", filteredWaveProvider);

Then I am create a new output file.

the output file after going through LFT is still having the sin wave at 4000Hz

Is there anything I am doing wrong?

After going through the Github Code repo of NAudio I am confused about the q value, is it quality factor or bandwidth? why would you have a bandwidth for low pass filter?

markheath commented 2 years ago

Q is bandwidth - not sure how that translates to decibels per octave for a low pass filter. The technical explanation is available here: https://www.w3.org/TR/audio-eq-cookbook/ Does the volume of the sin wave get attenuated at all in the output? Also, bear in mind that you should use the filter on a mono source, although looks like you're doing that