annotate dsp/transforms/FFT.cpp @ 321:f1e6be2de9a5

A threshold (delta) is added in the peak picking parameters structure (PPickParams). It is used as an offset when computing the smoothed detection function. A constructor for the structure PPickParams is also added to set the parameters to 0 when a structure instance is created. Hence programmes using the peak picking parameter structure and which do not set the delta parameter (e.g. QM Vamp note onset detector) won't be affected by the modifications. Functions modified: - dsp/onsets/PeakPicking.cpp - dsp/onsets/PeakPicking.h - dsp/signalconditioning/DFProcess.cpp - dsp/signalconditioning/DFProcess.h
author mathieub <mathieu.barthet@eecs.qmul.ac.uk>
date Mon, 20 Jun 2011 19:01:48 +0100
parents d5014ab8b0e5
children f6ccde089491
rev   line source
c@225 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@225 2
c@225 3 /*
c@225 4 QM DSP Library
c@225 5
c@225 6 Centre for Digital Music, Queen Mary, University of London.
c@225 7 This file is based on Don Cross's public domain FFT implementation.
c@225 8 */
c@225 9
c@225 10 #include "FFT.h"
c@280 11
c@280 12 #include "maths/MathUtilities.h"
c@280 13
c@225 14 #include <cmath>
c@225 15
c@280 16 #include <iostream>
c@280 17
c@289 18 FFT::FFT(unsigned int n) :
c@289 19 m_n(n),
c@289 20 m_private(0)
c@225 21 {
c@289 22 if( !MathUtilities::isPowerOfTwo(m_n) )
c@289 23 {
c@289 24 std::cerr << "ERROR: FFT: Non-power-of-two FFT size "
c@289 25 << m_n << " not supported in this implementation"
c@289 26 << std::endl;
c@289 27 return;
c@289 28 }
c@225 29 }
c@225 30
c@225 31 FFT::~FFT()
c@225 32 {
c@225 33
c@225 34 }
c@225 35
c@289 36 FFTReal::FFTReal(unsigned int n) :
c@289 37 m_n(n),
c@289 38 m_private(0)
c@225 39 {
c@289 40 m_private = new FFT(m_n);
c@289 41 }
c@225 42
c@289 43 FFTReal::~FFTReal()
c@289 44 {
c@289 45 delete (FFT *)m_private;
c@289 46 }
c@289 47
c@289 48 void
c@289 49 FFTReal::process(bool inverse,
c@289 50 const double *realIn,
c@289 51 double *realOut, double *imagOut)
c@289 52 {
c@289 53 ((FFT *)m_private)->process(inverse, realIn, 0, realOut, imagOut);
c@289 54 }
c@289 55
c@289 56 static unsigned int numberOfBitsNeeded(unsigned int p_nSamples)
c@289 57 {
c@289 58 int i;
c@289 59
c@289 60 if( p_nSamples < 2 )
c@289 61 {
c@289 62 return 0;
c@289 63 }
c@289 64
c@289 65 for ( i=0; ; i++ )
c@289 66 {
c@289 67 if( p_nSamples & (1 << i) ) return i;
c@289 68 }
c@289 69 }
c@289 70
c@289 71 static unsigned int reverseBits(unsigned int p_nIndex, unsigned int p_nBits)
c@289 72 {
c@289 73 unsigned int i, rev;
c@289 74
c@289 75 for(i=rev=0; i < p_nBits; i++)
c@289 76 {
c@289 77 rev = (rev << 1) | (p_nIndex & 1);
c@289 78 p_nIndex >>= 1;
c@289 79 }
c@289 80
c@289 81 return rev;
c@289 82 }
c@289 83
c@289 84 void
c@289 85 FFT::process(bool p_bInverseTransform,
c@289 86 const double *p_lpRealIn, const double *p_lpImagIn,
c@289 87 double *p_lpRealOut, double *p_lpImagOut)
c@289 88 {
c@291 89 if (!p_lpRealIn || !p_lpRealOut || !p_lpImagOut) return;
c@291 90
c@291 91 // std::cerr << "FFT::process(" << m_n << "," << p_bInverseTransform << ")" << std::endl;
c@225 92
c@225 93 unsigned int NumBits;
c@225 94 unsigned int i, j, k, n;
c@225 95 unsigned int BlockSize, BlockEnd;
c@225 96
c@225 97 double angle_numerator = 2.0 * M_PI;
c@225 98 double tr, ti;
c@225 99
c@289 100 if( !MathUtilities::isPowerOfTwo(m_n) )
c@225 101 {
c@280 102 std::cerr << "ERROR: FFT::process: Non-power-of-two FFT size "
c@289 103 << m_n << " not supported in this implementation"
c@280 104 << std::endl;
c@225 105 return;
c@225 106 }
c@225 107
c@225 108 if( p_bInverseTransform ) angle_numerator = -angle_numerator;
c@225 109
c@289 110 NumBits = numberOfBitsNeeded ( m_n );
c@225 111
c@225 112
c@289 113 for( i=0; i < m_n; i++ )
c@225 114 {
c@225 115 j = reverseBits ( i, NumBits );
c@225 116 p_lpRealOut[j] = p_lpRealIn[i];
c@225 117 p_lpImagOut[j] = (p_lpImagIn == 0) ? 0.0 : p_lpImagIn[i];
c@225 118 }
c@225 119
c@225 120
c@225 121 BlockEnd = 1;
c@289 122 for( BlockSize = 2; BlockSize <= m_n; BlockSize <<= 1 )
c@225 123 {
c@225 124 double delta_angle = angle_numerator / (double)BlockSize;
c@225 125 double sm2 = -sin ( -2 * delta_angle );
c@225 126 double sm1 = -sin ( -delta_angle );
c@225 127 double cm2 = cos ( -2 * delta_angle );
c@225 128 double cm1 = cos ( -delta_angle );
c@225 129 double w = 2 * cm1;
c@225 130 double ar[3], ai[3];
c@225 131
c@289 132 for( i=0; i < m_n; i += BlockSize )
c@225 133 {
c@225 134
c@225 135 ar[2] = cm2;
c@225 136 ar[1] = cm1;
c@225 137
c@225 138 ai[2] = sm2;
c@225 139 ai[1] = sm1;
c@225 140
c@225 141 for ( j=i, n=0; n < BlockEnd; j++, n++ )
c@225 142 {
c@225 143
c@225 144 ar[0] = w*ar[1] - ar[2];
c@225 145 ar[2] = ar[1];
c@225 146 ar[1] = ar[0];
c@225 147
c@225 148 ai[0] = w*ai[1] - ai[2];
c@225 149 ai[2] = ai[1];
c@225 150 ai[1] = ai[0];
c@225 151
c@225 152 k = j + BlockEnd;
c@225 153 tr = ar[0]*p_lpRealOut[k] - ai[0]*p_lpImagOut[k];
c@225 154 ti = ar[0]*p_lpImagOut[k] + ai[0]*p_lpRealOut[k];
c@225 155
c@225 156 p_lpRealOut[k] = p_lpRealOut[j] - tr;
c@225 157 p_lpImagOut[k] = p_lpImagOut[j] - ti;
c@225 158
c@225 159 p_lpRealOut[j] += tr;
c@225 160 p_lpImagOut[j] += ti;
c@225 161
c@225 162 }
c@225 163 }
c@225 164
c@225 165 BlockEnd = BlockSize;
c@225 166
c@225 167 }
c@225 168
c@225 169
c@225 170 if( p_bInverseTransform )
c@225 171 {
c@289 172 double denom = (double)m_n;
c@225 173
c@289 174 for ( i=0; i < m_n; i++ )
c@225 175 {
c@225 176 p_lpRealOut[i] /= denom;
c@225 177 p_lpImagOut[i] /= denom;
c@225 178 }
c@225 179 }
c@225 180 }
c@225 181