annotate dsp/onsets/DetectionFunction.cpp @ 12:da277e8b5244

* Some fixes to peak picker * Add broadband energy rise detection function (same as the percussive onset detector in the Vamp example plugins)
author cannam
date Fri, 18 May 2007 16:43:17 +0000
parents c539af5259da
children f2b5c4251bf3
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 QM DSP Library
cannam@0 5
cannam@0 6 Centre for Digital Music, Queen Mary, University of London.
cannam@0 7 This file copyright 2005-2006 Christian Landone.
cannam@0 8 All rights reserved.
cannam@0 9 */
cannam@0 10
cannam@0 11 #include "DetectionFunction.h"
cannam@0 12
cannam@0 13 //////////////////////////////////////////////////////////////////////
cannam@0 14 // Construction/Destruction
cannam@0 15 //////////////////////////////////////////////////////////////////////
cannam@0 16
cannam@0 17 DetectionFunction::DetectionFunction( DFConfig Config ) :
cannam@0 18 m_window(0)
cannam@0 19 {
cannam@2 20 m_magHistory = NULL;
cannam@2 21 m_phaseHistory = NULL;
cannam@2 22 m_phaseHistoryOld = NULL;
cannam@0 23
cannam@0 24 initialise( Config );
cannam@0 25 }
cannam@0 26
cannam@0 27 DetectionFunction::~DetectionFunction()
cannam@0 28 {
cannam@0 29 deInitialise();
cannam@0 30 }
cannam@0 31
cannam@0 32
cannam@0 33 void DetectionFunction::initialise( DFConfig Config )
cannam@0 34 {
cannam@0 35 m_dataLength = Config.frameLength;
cannam@0 36 m_halfLength = m_dataLength/2;
cannam@0 37 m_DFType = Config.DFType;
cannam@0 38
cannam@2 39 m_magHistory = new double[ m_halfLength ];
cannam@2 40 memset(m_magHistory,0, m_halfLength*sizeof(double));
cannam@0 41
cannam@2 42 m_phaseHistory = new double[ m_halfLength ];
cannam@2 43 memset(m_phaseHistory,0, m_halfLength*sizeof(double));
cannam@0 44
cannam@2 45 m_phaseHistoryOld = new double[ m_halfLength ];
cannam@2 46 memset(m_phaseHistoryOld,0, m_halfLength*sizeof(double));
cannam@0 47
cannam@0 48 m_phaseVoc = new PhaseVocoder;
cannam@0 49
cannam@0 50 m_DFWindowedFrame = new double[ m_dataLength ];
cannam@0 51 m_magnitude = new double[ m_halfLength ];
cannam@0 52 m_thetaAngle = new double[ m_halfLength ];
cannam@0 53
cannam@0 54 m_window = new Window<double>(HanningWindow, m_dataLength);
cannam@0 55 }
cannam@0 56
cannam@0 57 void DetectionFunction::deInitialise()
cannam@0 58 {
cannam@2 59 delete [] m_magHistory ;
cannam@2 60 delete [] m_phaseHistory ;
cannam@2 61 delete [] m_phaseHistoryOld ;
cannam@0 62
cannam@0 63 delete m_phaseVoc;
cannam@0 64
cannam@0 65 delete [] m_DFWindowedFrame;
cannam@0 66 delete [] m_magnitude;
cannam@0 67 delete [] m_thetaAngle;
cannam@0 68
cannam@0 69 delete m_window;
cannam@0 70 }
cannam@0 71
cannam@0 72 double DetectionFunction::process( double *TDomain )
cannam@0 73 {
cannam@0 74 m_window->cut( TDomain, m_DFWindowedFrame );
cannam@0 75
cannam@0 76 m_phaseVoc->process( m_dataLength, m_DFWindowedFrame, m_magnitude, m_thetaAngle );
cannam@0 77
cannam@2 78 return runDF();
cannam@2 79 }
cannam@2 80
cannam@2 81 double DetectionFunction::process( double *magnitudes, double *phases )
cannam@2 82 {
cannam@2 83 for (size_t i = 0; i < m_halfLength; ++i) {
cannam@2 84 m_magnitude[i] = magnitudes[i];
cannam@2 85 m_thetaAngle[i] = phases[i];
cannam@2 86 }
cannam@2 87
cannam@2 88 return runDF();
cannam@2 89 }
cannam@2 90
cannam@2 91 double DetectionFunction::runDF()
cannam@2 92 {
cannam@2 93 double retVal = 0;
cannam@2 94
cannam@0 95 switch( m_DFType )
cannam@0 96 {
cannam@0 97 case DF_HFC:
cannam@0 98 retVal = HFC( m_halfLength, m_magnitude);
cannam@0 99 break;
cannam@0 100
cannam@0 101 case DF_SPECDIFF:
cannam@0 102 retVal = specDiff( m_halfLength, m_magnitude);
cannam@0 103 break;
cannam@0 104
cannam@0 105 case DF_PHASEDEV:
cannam@0 106 retVal = phaseDev( m_halfLength, m_magnitude, m_thetaAngle);
cannam@0 107 break;
cannam@0 108
cannam@0 109 case DF_COMPLEXSD:
cannam@0 110 retVal = complexSD( m_halfLength, m_magnitude, m_thetaAngle);
cannam@0 111 break;
cannam@12 112
cannam@12 113 case DF_BROADBAND:
cannam@12 114 retVal = broadband( m_halfLength, m_magnitude, m_thetaAngle);
cannam@0 115 }
cannam@0 116
cannam@0 117 return retVal;
cannam@0 118 }
cannam@0 119
cannam@0 120 double DetectionFunction::HFC(unsigned int length, double *src)
cannam@0 121 {
cannam@0 122 unsigned int i;
cannam@0 123 double val = 0;
cannam@0 124
cannam@0 125 for( i = 0; i < length; i++)
cannam@0 126 {
cannam@0 127 val += src[ i ] * ( i + 1);
cannam@0 128 }
cannam@0 129 return val;
cannam@0 130 }
cannam@0 131
cannam@0 132 double DetectionFunction::specDiff(unsigned int length, double *src)
cannam@0 133 {
cannam@0 134 unsigned int i;
cannam@0 135 double val = 0.0;
cannam@0 136 double temp = 0.0;
cannam@0 137 double diff = 0.0;
cannam@0 138
cannam@0 139 for( i = 0; i < length; i++)
cannam@0 140 {
cannam@2 141 temp = fabs( (src[ i ] * src[ i ]) - (m_magHistory[ i ] * m_magHistory[ i ]) );
cannam@0 142
cannam@0 143 diff= sqrt(temp);
cannam@0 144
cannam@0 145 if( src[ i ] > 0.1)
cannam@0 146 {
cannam@0 147 val += diff;
cannam@0 148 }
cannam@0 149
cannam@2 150 m_magHistory[ i ] = src[ i ];
cannam@0 151 }
cannam@0 152
cannam@0 153 return val;
cannam@0 154 }
cannam@0 155
cannam@0 156
cannam@0 157 double DetectionFunction::phaseDev(unsigned int length, double *srcMagnitude, double *srcPhase)
cannam@0 158 {
cannam@0 159 unsigned int i;
cannam@0 160 double tmpPhase = 0;
cannam@0 161 double tmpVal = 0;
cannam@0 162 double val = 0;
cannam@0 163
cannam@0 164 double dev = 0;
cannam@0 165
cannam@0 166 for( i = 0; i < length; i++)
cannam@0 167 {
cannam@2 168 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
cannam@0 169 dev = MathUtilities::princarg( tmpPhase );
cannam@0 170
cannam@0 171 if( srcMagnitude[ i ] > 0.1)
cannam@0 172 {
cannam@0 173 tmpVal = fabs( dev);
cannam@0 174 val += tmpVal ;
cannam@0 175 }
cannam@0 176
cannam@2 177 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
cannam@2 178 m_phaseHistory[ i ] = srcPhase[ i ];
cannam@0 179 }
cannam@0 180
cannam@0 181
cannam@0 182 return val;
cannam@0 183 }
cannam@0 184
cannam@0 185
cannam@0 186 double DetectionFunction::complexSD(unsigned int length, double *srcMagnitude, double *srcPhase)
cannam@0 187 {
cannam@0 188 unsigned int i;
cannam@0 189 double val = 0;
cannam@0 190 double tmpPhase = 0;
cannam@0 191 double tmpReal = 0;
cannam@0 192 double tmpImag = 0;
cannam@0 193
cannam@0 194 double dev = 0;
cannam@0 195 ComplexData meas = ComplexData( 0, 0 );
cannam@2 196 ComplexData j = ComplexData( 0, 1 );
cannam@0 197
cannam@0 198 for( i = 0; i < length; i++)
cannam@0 199 {
cannam@2 200 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
cannam@0 201 dev= MathUtilities::princarg( tmpPhase );
cannam@0 202
cannam@2 203 meas = m_magHistory[i] - ( srcMagnitude[ i ] * exp( j * dev) );
cannam@0 204
cannam@0 205 tmpReal = real( meas );
cannam@0 206 tmpImag = imag( meas );
cannam@0 207
cannam@0 208 val += sqrt( (tmpReal * tmpReal) + (tmpImag * tmpImag) );
cannam@0 209
cannam@2 210 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
cannam@2 211 m_phaseHistory[ i ] = srcPhase[ i ];
cannam@2 212 m_magHistory[ i ] = srcMagnitude[ i ];
cannam@0 213 }
cannam@0 214
cannam@0 215 return val;
cannam@0 216 }
cannam@0 217
cannam@12 218 double DetectionFunction::broadband(unsigned int length, double *srcMagnitude, double *srcPhase)
cannam@12 219 {
cannam@12 220 double val = 0;
cannam@12 221 for (unsigned int i = 0; i < length; ++i) {
cannam@12 222 double sqrmag = srcMagnitude[i] * srcMagnitude[i];
cannam@12 223 if (m_magHistory[i] > 0.0) {
cannam@12 224 double diff = 10.0 * log10(sqrmag / m_magHistory[i]);
cannam@12 225 if (diff > m_dbRise) val = val + 1;
cannam@12 226 }
cannam@12 227 m_magHistory[i] = sqrmag;
cannam@12 228 }
cannam@12 229 return val;
cannam@12 230 }
cannam@12 231
cannam@0 232 double* DetectionFunction::getSpectrumMagnitude()
cannam@0 233 {
cannam@0 234 return m_magnitude;
cannam@0 235 }
cannam@0 236