Frequency-domain filtering with FFT

29 kwietnia 2010 01:47 tags:

Signal filtering can be expressed in two (equivalent) approaches.

  1. convolution of the signal and impulse response of the filter - in time domain
  2. multiplication of signal spectrum and filter's transfer function (filter spectrum) - in frequency domain

This example illustrates the second approach. Signal spectrum is calculated using FFT. The filter is represented as it's transfer function - it is a pretty simple low-pass filter. The two complex arrays are multiplied and the result is plotted. Inverse FFT is used to return to a time-domain signal.

#include "aquila/global.h"
#include "aquila/source/generator/SineGenerator.h"
#include "aquila/transform/FftFactory.h"
#include "aquila/tools/TextPlot.h"
#include <algorithm>
#include <functional>
#include <memory>

int main()
{
    // input signal parameters
    const std::size_t SIZE = 64;
    const Aquila::FrequencyType sampleFreq = 2000;
    const Aquila::FrequencyType f1 = 96, f2 = 813;
    const Aquila::FrequencyType f_lp = 500;

    Aquila::SineGenerator sineGenerator1(sampleFreq);
    sineGenerator1.setAmplitude(32).setFrequency(f1).generate(SIZE);
    Aquila::SineGenerator sineGenerator2(sampleFreq);
    sineGenerator2.setAmplitude(8).setFrequency(f2).setPhase(0.75).generate(SIZE);
    auto sum = sineGenerator1 + sineGenerator2;

    Aquila::TextPlot plt("Signal waveform before filtration");
    plt.plot(sum);

    // calculate the FFT
    auto fft = Aquila::FftFactory::getFft(SIZE);
    Aquila::SpectrumType spectrum = fft->fft(sum.toArray());
    plt.setTitle("Signal spectrum before filtration");
    plt.plotSpectrum(spectrum);

    // generate a low-pass filter spectrum
    Aquila::SpectrumType filterSpectrum(SIZE);
    for (std::size_t i = 0; i < SIZE; ++i)
    {
        if (i < (SIZE * f_lp / sampleFreq))
        {
            // passband
            filterSpectrum[i] = 1.0;
        }
        else
        {
            // stopband
            filterSpectrum[i] = 0.0;
        }
    }
    plt.setTitle("Filter spectrum");
    plt.plotSpectrum(filterSpectrum);

    // the following call does the multiplication of two spectra
    // (which is complementary to convolution in time domain)
    std::transform(
        std::begin(spectrum),
        std::end(spectrum),
        std::begin(filterSpectrum),
        std::begin(spectrum),
        [] (Aquila::ComplexType x, Aquila::ComplexType y) { return x * y; }
    );
    plt.setTitle("Signal spectrum after filtration");
    plt.plotSpectrum(spectrum);

    // Inverse FFT moves us back to time domain
    double x1[SIZE];
    fft->ifft(spectrum, x1);
    plt.setTitle("Signal waveform after filtration");
    plt.plot(x1, SIZE);

    return 0;
}

The output should resemble something like this:

Signal waveform before filtration
     * *                   *                  ** *              
    *                   ***                 *                   
  *   *                      *                  *               
   *                        *                *                  
        **            *                            *            
                       *                          *             
*         *                   *           **                    
 *                             *                    *          *
                     *          *        *                      
            *       *                                        ** 
           *       *                                 **         
                                  *    *                        
                 *                      *                  *    
              *                  *   *                  *       
             * *  *                 *                  *    *   
                *                  *  *                  **

Signal spectrum before filtration
   *











                          *

    *                           
***  ********************* *****

Filter spectrum
****************














                ****************

Signal spectrum after filtration
   *













    *                           
***  ***************************

Signal waveform after filtration
    ***                  ***                  ***               
   *   *                *   *                *   *              
        *                    *              *                   
  *                    *                          *             
         *                                 *                    
 *                    *       *                    *

*         *          *         *          *         *          *

           *        *           *        *                    * 
                                                     *          
            *                           *                    *  
                   *             *                    *         
             *                         *                    *   
                  *               *                    *        
              ****                 ****                 ****
« Return to list