annotate dsp/transforms/FFT.cpp @ 441:3994516c1199

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