annotate constant-q-cpp/src/dsp/FFT.cpp @ 372:af71cbdab621 tip

Update bqvec code
author Chris Cannam
date Tue, 19 Nov 2019 10:13:32 +0000
parents 5d0a2ebb4d17
children
rev   line source
Chris@366 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@366 2 /*
Chris@366 3 Constant-Q library
Chris@366 4 Copyright (c) 2013-2014 Queen Mary, University of London
Chris@366 5
Chris@366 6 Permission is hereby granted, free of charge, to any person
Chris@366 7 obtaining a copy of this software and associated documentation
Chris@366 8 files (the "Software"), to deal in the Software without
Chris@366 9 restriction, including without limitation the rights to use, copy,
Chris@366 10 modify, merge, publish, distribute, sublicense, and/or sell copies
Chris@366 11 of the Software, and to permit persons to whom the Software is
Chris@366 12 furnished to do so, subject to the following conditions:
Chris@366 13
Chris@366 14 The above copyright notice and this permission notice shall be
Chris@366 15 included in all copies or substantial portions of the Software.
Chris@366 16
Chris@366 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@366 18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@366 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Chris@366 20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
Chris@366 21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@366 22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@366 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@366 24
Chris@366 25 Except as contained in this notice, the names of the Centre for
Chris@366 26 Digital Music; Queen Mary, University of London; and Chris Cannam
Chris@366 27 shall not be used in advertising or otherwise to promote the sale,
Chris@366 28 use or other dealings in this Software without prior written
Chris@366 29 authorization.
Chris@366 30 */
Chris@366 31
Chris@366 32 #include "FFT.h"
Chris@366 33
Chris@366 34 #include "MathUtilities.h"
Chris@366 35
Chris@366 36 #include "kiss_fft.h"
Chris@366 37 #include "kiss_fftr.h"
Chris@366 38
Chris@366 39 #include <cmath>
Chris@366 40
Chris@366 41 #include <iostream>
Chris@366 42
Chris@366 43 #include <stdexcept>
Chris@366 44
Chris@366 45 class FFT::D
Chris@366 46 {
Chris@366 47 public:
Chris@366 48 D(int n) : m_n(n) {
Chris@366 49 m_planf = kiss_fft_alloc(m_n, 0, NULL, NULL);
Chris@366 50 m_plani = kiss_fft_alloc(m_n, 1, NULL, NULL);
Chris@366 51 m_kin = new kiss_fft_cpx[m_n];
Chris@366 52 m_kout = new kiss_fft_cpx[m_n];
Chris@366 53 }
Chris@366 54
Chris@366 55 ~D() {
Chris@366 56 kiss_fft_free(m_planf);
Chris@366 57 kiss_fft_free(m_plani);
Chris@366 58 delete[] m_kin;
Chris@366 59 delete[] m_kout;
Chris@366 60 }
Chris@366 61
Chris@366 62 void process(bool inverse,
Chris@366 63 const double *ri,
Chris@366 64 const double *ii,
Chris@366 65 double *ro,
Chris@366 66 double *io) {
Chris@366 67
Chris@366 68 for (int i = 0; i < m_n; ++i) {
Chris@366 69 m_kin[i].r = ri[i];
Chris@366 70 m_kin[i].i = (ii ? ii[i] : 0.0);
Chris@366 71 }
Chris@366 72
Chris@366 73 if (!inverse) {
Chris@366 74
Chris@366 75 kiss_fft(m_planf, m_kin, m_kout);
Chris@366 76
Chris@366 77 for (int i = 0; i < m_n; ++i) {
Chris@366 78 ro[i] = m_kout[i].r;
Chris@366 79 io[i] = m_kout[i].i;
Chris@366 80 }
Chris@366 81
Chris@366 82 } else {
Chris@366 83
Chris@366 84 kiss_fft(m_plani, m_kin, m_kout);
Chris@366 85
Chris@366 86 double scale = 1.0 / m_n;
Chris@366 87
Chris@366 88 for (int i = 0; i < m_n; ++i) {
Chris@366 89 ro[i] = m_kout[i].r * scale;
Chris@366 90 io[i] = m_kout[i].i * scale;
Chris@366 91 }
Chris@366 92 }
Chris@366 93 }
Chris@366 94
Chris@366 95 private:
Chris@366 96 int m_n;
Chris@366 97 kiss_fft_cfg m_planf;
Chris@366 98 kiss_fft_cfg m_plani;
Chris@366 99 kiss_fft_cpx *m_kin;
Chris@366 100 kiss_fft_cpx *m_kout;
Chris@366 101 };
Chris@366 102
Chris@366 103 FFT::FFT(int n) :
Chris@366 104 m_d(new D(n))
Chris@366 105 {
Chris@366 106 }
Chris@366 107
Chris@366 108 FFT::~FFT()
Chris@366 109 {
Chris@366 110 delete m_d;
Chris@366 111 }
Chris@366 112
Chris@366 113 void
Chris@366 114 FFT::process(bool inverse,
Chris@366 115 const double *p_lpRealIn, const double *p_lpImagIn,
Chris@366 116 double *p_lpRealOut, double *p_lpImagOut)
Chris@366 117 {
Chris@366 118 m_d->process(inverse,
Chris@366 119 p_lpRealIn, p_lpImagIn,
Chris@366 120 p_lpRealOut, p_lpImagOut);
Chris@366 121 }
Chris@366 122
Chris@366 123 class FFTReal::D
Chris@366 124 {
Chris@366 125 public:
Chris@366 126 D(int n) : m_n(n) {
Chris@366 127 if (n % 2) {
Chris@366 128 throw std::invalid_argument
Chris@366 129 ("nsamples must be even in FFTReal constructor");
Chris@366 130 }
Chris@366 131 m_planf = kiss_fftr_alloc(m_n, 0, NULL, NULL);
Chris@366 132 m_plani = kiss_fftr_alloc(m_n, 1, NULL, NULL);
Chris@366 133 m_c = new kiss_fft_cpx[m_n];
Chris@366 134 }
Chris@366 135
Chris@366 136 ~D() {
Chris@366 137 kiss_fftr_free(m_planf);
Chris@366 138 kiss_fftr_free(m_plani);
Chris@366 139 delete[] m_c;
Chris@366 140 }
Chris@366 141
Chris@366 142 void forward(const double *ri, double *ro, double *io) {
Chris@366 143
Chris@366 144 kiss_fftr(m_planf, ri, m_c);
Chris@366 145
Chris@366 146 for (int i = 0; i <= m_n/2; ++i) {
Chris@366 147 ro[i] = m_c[i].r;
Chris@366 148 io[i] = m_c[i].i;
Chris@366 149 }
Chris@366 150
Chris@366 151 for (int i = 0; i + 1 < m_n/2; ++i) {
Chris@366 152 ro[m_n - i - 1] = ro[i + 1];
Chris@366 153 io[m_n - i - 1] = -io[i + 1];
Chris@366 154 }
Chris@366 155 }
Chris@366 156
Chris@366 157 void forwardMagnitude(const double *ri, double *mo) {
Chris@366 158
Chris@366 159 double *io = new double[m_n];
Chris@366 160
Chris@366 161 forward(ri, mo, io);
Chris@366 162
Chris@366 163 for (int i = 0; i < m_n; ++i) {
Chris@366 164 mo[i] = sqrt(mo[i] * mo[i] + io[i] * io[i]);
Chris@366 165 }
Chris@366 166
Chris@366 167 delete[] io;
Chris@366 168 }
Chris@366 169
Chris@366 170 void inverse(const double *ri, const double *ii, double *ro) {
Chris@366 171
Chris@366 172 // kiss_fftr.h says
Chris@366 173 // "input freqdata has nfft/2+1 complex points"
Chris@366 174
Chris@366 175 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@366 176 m_c[i].r = ri[i];
Chris@366 177 m_c[i].i = ii[i];
Chris@366 178 }
Chris@366 179
Chris@366 180 kiss_fftri(m_plani, m_c, ro);
Chris@366 181
Chris@366 182 double scale = 1.0 / m_n;
Chris@366 183
Chris@366 184 for (int i = 0; i < m_n; ++i) {
Chris@366 185 ro[i] *= scale;
Chris@366 186 }
Chris@366 187 }
Chris@366 188
Chris@366 189 private:
Chris@366 190 int m_n;
Chris@366 191 kiss_fftr_cfg m_planf;
Chris@366 192 kiss_fftr_cfg m_plani;
Chris@366 193 kiss_fft_cpx *m_c;
Chris@366 194 };
Chris@366 195
Chris@366 196 FFTReal::FFTReal(int n) :
Chris@366 197 m_d(new D(n))
Chris@366 198 {
Chris@366 199 }
Chris@366 200
Chris@366 201 FFTReal::~FFTReal()
Chris@366 202 {
Chris@366 203 delete m_d;
Chris@366 204 }
Chris@366 205
Chris@366 206 void
Chris@366 207 FFTReal::forward(const double *ri, double *ro, double *io)
Chris@366 208 {
Chris@366 209 m_d->forward(ri, ro, io);
Chris@366 210 }
Chris@366 211
Chris@366 212 void
Chris@366 213 FFTReal::forwardMagnitude(const double *ri, double *mo)
Chris@366 214 {
Chris@366 215 m_d->forwardMagnitude(ri, mo);
Chris@366 216 }
Chris@366 217
Chris@366 218 void
Chris@366 219 FFTReal::inverse(const double *ri, const double *ii, double *ro)
Chris@366 220 {
Chris@366 221 m_d->inverse(ri, ii, ro);
Chris@366 222 }
Chris@366 223
Chris@366 224
Chris@366 225