annotate src/dsp/FFT.cpp @ 196:da283326bcd3 tip master

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