annotate dsp/transforms/FFTqm.cpp @ 434:7461bf03194e

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