annotate dsp/transforms/FFT.cpp @ 355:3c7338aff6a8

Drop in kissfft to replace the "old" fft, and add tests for newly-supported sizes
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 15 Oct 2013 11:38:18 +0100
parents 9c8ee77db9de
children a586888bc06c
rev   line source
c@225 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@225 2
c@225 3 /*
c@225 4 QM DSP Library
c@225 5
c@225 6 Centre for Digital Music, Queen Mary, University of London.
c@225 7 This file is based on Don Cross's public domain FFT implementation.
c@225 8 */
c@225 9
c@225 10 #include "FFT.h"
c@280 11
c@280 12 #include "maths/MathUtilities.h"
c@280 13
c@355 14 #include "kiss_fft.h"
c@355 15 #include "kiss_fftr.h"
c@355 16
c@225 17 #include <cmath>
c@225 18
c@280 19 #include <iostream>
c@280 20
c@355 21 #include <stdexcept>
c@355 22
c@355 23 class FFT::D
c@355 24 {
c@355 25 public:
c@355 26 D(int n) : m_n(n) {
c@355 27 m_planf = kiss_fft_alloc(m_n, 0, NULL, NULL);
c@355 28 m_plani = kiss_fft_alloc(m_n, 1, NULL, NULL);
c@355 29 m_kin = new kiss_fft_cpx[m_n];
c@355 30 m_kout = new kiss_fft_cpx[m_n];
c@355 31 }
c@355 32
c@355 33 ~D() {
c@355 34 kiss_fft_free(m_planf);
c@355 35 kiss_fft_free(m_plani);
c@355 36 delete[] m_kin;
c@355 37 delete[] m_kout;
c@355 38 }
c@355 39
c@355 40 void process(bool inverse,
c@355 41 const double *ri,
c@355 42 const double *ii,
c@355 43 double *ro,
c@355 44 double *io) {
c@355 45
c@355 46 for (int i = 0; i < m_n; ++i) {
c@355 47 m_kin[i].r = ri[i];
c@355 48 m_kin[i].i = (ii ? ii[i] : 0.0);
c@355 49 }
c@355 50
c@355 51 if (!inverse) {
c@355 52
c@355 53 kiss_fft(m_planf, m_kin, m_kout);
c@355 54
c@355 55 for (int i = 0; i < m_n; ++i) {
c@355 56 ro[i] = m_kout[i].r;
c@355 57 io[i] = m_kout[i].i;
c@355 58 }
c@355 59
c@355 60 } else {
c@355 61
c@355 62 kiss_fft(m_plani, m_kin, m_kout);
c@355 63
c@355 64 double scale = 1.0 / m_n;
c@355 65
c@355 66 for (int i = 0; i < m_n; ++i) {
c@355 67 ro[i] = m_kout[i].r * scale;
c@355 68 io[i] = m_kout[i].i * scale;
c@355 69 }
c@355 70 }
c@355 71 }
c@355 72
c@355 73 private:
c@355 74 int m_n;
c@355 75 kiss_fft_cfg m_planf;
c@355 76 kiss_fft_cfg m_plani;
c@355 77 kiss_fft_cpx *m_kin;
c@355 78 kiss_fft_cpx *m_kout;
c@355 79 };
c@355 80
c@339 81 FFT::FFT(int n) :
c@355 82 m_d(new D(n))
c@225 83 {
c@225 84 }
c@225 85
c@225 86 FFT::~FFT()
c@225 87 {
c@355 88 delete m_d;
c@225 89 }
c@225 90
c@355 91 void
c@355 92 FFT::process(bool inverse,
c@355 93 const double *p_lpRealIn, const double *p_lpImagIn,
c@355 94 double *p_lpRealOut, double *p_lpImagOut)
c@355 95 {
c@355 96 m_d->process(inverse,
c@355 97 p_lpRealIn, p_lpImagIn,
c@355 98 p_lpRealOut, p_lpImagOut);
c@355 99 }
c@355 100
c@355 101 class FFTReal::D
c@355 102 {
c@355 103 public:
c@355 104 D(int n) : m_n(n) {
c@355 105 if (n % 2) {
c@355 106 throw std::invalid_argument
c@355 107 ("nsamples must be even in FFTReal constructor");
c@355 108 }
c@355 109 m_planf = kiss_fftr_alloc(m_n, 0, NULL, NULL);
c@355 110 m_plani = kiss_fftr_alloc(m_n, 1, NULL, NULL);
c@355 111 m_c = new kiss_fft_cpx[m_n];
c@355 112 }
c@355 113
c@355 114 ~D() {
c@355 115 kiss_fftr_free(m_planf);
c@355 116 kiss_fftr_free(m_plani);
c@355 117 delete[] m_c;
c@355 118 }
c@355 119
c@355 120 void forward(const double *ri, double *ro, double *io) {
c@355 121
c@355 122 kiss_fftr(m_planf, ri, m_c);
c@355 123
c@355 124 for (int i = 0; i <= m_n/2; ++i) {
c@355 125 ro[i] = m_c[i].r;
c@355 126 io[i] = m_c[i].i;
c@355 127 }
c@355 128
c@355 129 for (int i = 0; i + 1 < m_n/2; ++i) {
c@355 130 ro[m_n - i - 1] = ro[i + 1];
c@355 131 io[m_n - i - 1] = -io[i + 1];
c@355 132 }
c@355 133 }
c@355 134
c@355 135 void inverse(const double *ri, const double *ii, double *ro) {
c@355 136
c@355 137 for (int i = 0; i < m_n; ++i) {
c@355 138 m_c[i].r = ri[i];
c@355 139 m_c[i].i = ii[i];
c@355 140 }
c@355 141
c@355 142 kiss_fftri(m_plani, m_c, ro);
c@355 143
c@355 144 double scale = 1.0 / m_n;
c@355 145
c@355 146 for (int i = 0; i < m_n; ++i) {
c@355 147 ro[i] *= scale;
c@355 148 }
c@355 149 }
c@355 150
c@355 151 private:
c@355 152 int m_n;
c@355 153 kiss_fftr_cfg m_planf;
c@355 154 kiss_fftr_cfg m_plani;
c@355 155 kiss_fft_cpx *m_c;
c@355 156 };
c@355 157
c@339 158 FFTReal::FFTReal(int n) :
c@355 159 m_d(new D(n))
c@225 160 {
c@289 161 }
c@225 162
c@289 163 FFTReal::~FFTReal()
c@289 164 {
c@355 165 delete m_d;
c@289 166 }
c@289 167
c@289 168 void
c@355 169 FFTReal::forward(const double *ri, double *ro, double *io)
c@289 170 {
c@355 171 m_d->forward(ri, ro, io);
c@289 172 }
c@289 173
c@339 174 void
c@355 175 FFTReal::inverse(const double *ri, const double *ii, double *ro)
c@339 176 {
c@355 177 m_d->inverse(ri, ii, ro);
c@339 178 }
c@339 179
c@289 180
c@355 181