annotate dsp/transforms/FFT.cpp @ 216:0307327a3869

Merge from branch msvc
author Chris Cannam
date Thu, 08 Feb 2018 15:41:27 +0000
parents 7ab3539e92e3 a41bea655151
children
rev   line source
Chris@211 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@211 2
Chris@211 3 /*
Chris@211 4 QM DSP Library
Chris@211 5
Chris@211 6 Centre for Digital Music, Queen Mary, University of London.
Chris@211 7 */
Chris@211 8
Chris@211 9 #include "FFT.h"
Chris@211 10
Chris@211 11 #include "maths/MathUtilities.h"
Chris@211 12
Chris@211 13 #include "kiss_fft.h"
Chris@211 14 #include "kiss_fftr.h"
Chris@211 15
Chris@211 16 #include <cmath>
Chris@211 17
Chris@211 18 #include <iostream>
Chris@211 19
Chris@211 20 #include <stdexcept>
Chris@211 21
Chris@211 22 class FFT::D
Chris@211 23 {
Chris@211 24 public:
Chris@211 25 D(int n) : m_n(n) {
Chris@211 26 m_planf = kiss_fft_alloc(m_n, 0, NULL, NULL);
Chris@211 27 m_plani = kiss_fft_alloc(m_n, 1, NULL, NULL);
Chris@211 28 m_kin = new kiss_fft_cpx[m_n];
Chris@211 29 m_kout = new kiss_fft_cpx[m_n];
Chris@211 30 }
Chris@211 31
Chris@211 32 ~D() {
Chris@211 33 kiss_fft_free(m_planf);
Chris@211 34 kiss_fft_free(m_plani);
Chris@211 35 delete[] m_kin;
Chris@211 36 delete[] m_kout;
Chris@211 37 }
Chris@211 38
Chris@211 39 void process(bool inverse,
Chris@211 40 const double *ri,
Chris@211 41 const double *ii,
Chris@211 42 double *ro,
Chris@211 43 double *io) {
Chris@211 44
Chris@211 45 for (int i = 0; i < m_n; ++i) {
Chris@211 46 m_kin[i].r = ri[i];
Chris@211 47 m_kin[i].i = (ii ? ii[i] : 0.0);
Chris@211 48 }
Chris@211 49
Chris@211 50 if (!inverse) {
Chris@211 51
Chris@211 52 kiss_fft(m_planf, m_kin, m_kout);
Chris@211 53
Chris@211 54 for (int i = 0; i < m_n; ++i) {
Chris@211 55 ro[i] = m_kout[i].r;
Chris@211 56 io[i] = m_kout[i].i;
Chris@211 57 }
Chris@211 58
Chris@211 59 } else {
Chris@211 60
Chris@211 61 kiss_fft(m_plani, m_kin, m_kout);
Chris@211 62
Chris@211 63 double scale = 1.0 / m_n;
Chris@211 64
Chris@211 65 for (int i = 0; i < m_n; ++i) {
Chris@211 66 ro[i] = m_kout[i].r * scale;
Chris@211 67 io[i] = m_kout[i].i * scale;
Chris@211 68 }
Chris@211 69 }
Chris@211 70 }
Chris@211 71
Chris@211 72 private:
Chris@211 73 int m_n;
Chris@211 74 kiss_fft_cfg m_planf;
Chris@211 75 kiss_fft_cfg m_plani;
Chris@211 76 kiss_fft_cpx *m_kin;
Chris@211 77 kiss_fft_cpx *m_kout;
Chris@211 78 };
Chris@211 79
Chris@211 80 FFT::FFT(int n) :
Chris@211 81 m_d(new D(n))
Chris@211 82 {
Chris@211 83 }
Chris@211 84
Chris@211 85 FFT::~FFT()
Chris@211 86 {
Chris@211 87 delete m_d;
Chris@211 88 }
Chris@211 89
Chris@211 90 void
Chris@211 91 FFT::process(bool inverse,
Chris@211 92 const double *p_lpRealIn, const double *p_lpImagIn,
Chris@211 93 double *p_lpRealOut, double *p_lpImagOut)
Chris@211 94 {
Chris@211 95 m_d->process(inverse,
Chris@211 96 p_lpRealIn, p_lpImagIn,
Chris@211 97 p_lpRealOut, p_lpImagOut);
Chris@211 98 }
Chris@211 99
Chris@211 100 class FFTReal::D
Chris@211 101 {
Chris@211 102 public:
Chris@211 103 D(int n) : m_n(n) {
Chris@211 104 if (n % 2) {
Chris@211 105 throw std::invalid_argument
Chris@211 106 ("nsamples must be even in FFTReal constructor");
Chris@211 107 }
Chris@211 108 m_planf = kiss_fftr_alloc(m_n, 0, NULL, NULL);
Chris@211 109 m_plani = kiss_fftr_alloc(m_n, 1, NULL, NULL);
Chris@211 110 m_c = new kiss_fft_cpx[m_n];
Chris@211 111 }
Chris@211 112
Chris@211 113 ~D() {
Chris@211 114 kiss_fftr_free(m_planf);
Chris@211 115 kiss_fftr_free(m_plani);
Chris@211 116 delete[] m_c;
Chris@211 117 }
Chris@211 118
Chris@211 119 void forward(const double *ri, double *ro, double *io) {
Chris@211 120
Chris@211 121 kiss_fftr(m_planf, ri, m_c);
Chris@211 122
Chris@211 123 for (int i = 0; i <= m_n/2; ++i) {
Chris@211 124 ro[i] = m_c[i].r;
Chris@211 125 io[i] = m_c[i].i;
Chris@211 126 }
Chris@211 127
Chris@211 128 for (int i = 0; i + 1 < m_n/2; ++i) {
Chris@211 129 ro[m_n - i - 1] = ro[i + 1];
Chris@211 130 io[m_n - i - 1] = -io[i + 1];
Chris@211 131 }
Chris@211 132 }
Chris@211 133
Chris@211 134 void forwardMagnitude(const double *ri, double *mo) {
Chris@211 135
Chris@211 136 double *io = new double[m_n];
Chris@211 137
Chris@211 138 forward(ri, mo, io);
Chris@211 139
Chris@211 140 for (int i = 0; i < m_n; ++i) {
Chris@211 141 mo[i] = sqrt(mo[i] * mo[i] + io[i] * io[i]);
Chris@211 142 }
Chris@211 143
Chris@211 144 delete[] io;
Chris@211 145 }
Chris@211 146
Chris@211 147 void inverse(const double *ri, const double *ii, double *ro) {
Chris@211 148
Chris@211 149 // kiss_fftr.h says
Chris@211 150 // "input freqdata has nfft/2+1 complex points"
Chris@211 151
Chris@211 152 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@211 153 m_c[i].r = ri[i];
Chris@211 154 m_c[i].i = ii[i];
Chris@211 155 }
Chris@211 156
Chris@211 157 kiss_fftri(m_plani, m_c, ro);
Chris@211 158
Chris@211 159 double scale = 1.0 / m_n;
Chris@211 160
Chris@211 161 for (int i = 0; i < m_n; ++i) {
Chris@211 162 ro[i] *= scale;
Chris@211 163 }
Chris@211 164 }
Chris@211 165
Chris@211 166 private:
Chris@211 167 int m_n;
Chris@211 168 kiss_fftr_cfg m_planf;
Chris@211 169 kiss_fftr_cfg m_plani;
Chris@211 170 kiss_fft_cpx *m_c;
Chris@211 171 };
Chris@211 172
Chris@211 173 FFTReal::FFTReal(int n) :
Chris@211 174 m_d(new D(n))
Chris@211 175 {
Chris@211 176 }
Chris@211 177
Chris@211 178 FFTReal::~FFTReal()
Chris@211 179 {
Chris@211 180 delete m_d;
Chris@211 181 }
Chris@211 182
Chris@211 183 void
Chris@211 184 FFTReal::forward(const double *ri, double *ro, double *io)
Chris@211 185 {
Chris@211 186 m_d->forward(ri, ro, io);
Chris@211 187 }
Chris@211 188
Chris@211 189 void
Chris@211 190 FFTReal::forwardMagnitude(const double *ri, double *mo)
Chris@211 191 {
Chris@211 192 m_d->forwardMagnitude(ri, mo);
Chris@211 193 }
Chris@211 194
Chris@211 195 void
Chris@211 196 FFTReal::inverse(const double *ri, const double *ii, double *ro)
Chris@211 197 {
Chris@211 198 m_d->inverse(ri, ii, ro);
Chris@211 199 }
Chris@211 200
Chris@211 201
Chris@211 202