annotate dsp/onsets/DetectionFunction.cpp @ 13:f2b5c4251bf3

...
author cannam
date Wed, 23 May 2007 15:22:10 +0000
parents da277e8b5244
children 68801ecbab6a
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@13 38 m_stepSecs = Config.stepSecs;
cannam@13 39 m_stepSize = Config.stepSize;
cannam@0 40
cannam@2 41 m_magHistory = new double[ m_halfLength ];
cannam@2 42 memset(m_magHistory,0, m_halfLength*sizeof(double));
cannam@0 43
cannam@2 44 m_phaseHistory = new double[ m_halfLength ];
cannam@2 45 memset(m_phaseHistory,0, m_halfLength*sizeof(double));
cannam@0 46
cannam@2 47 m_phaseHistoryOld = new double[ m_halfLength ];
cannam@2 48 memset(m_phaseHistoryOld,0, m_halfLength*sizeof(double));
cannam@0 49
cannam@0 50 m_phaseVoc = new PhaseVocoder;
cannam@0 51
cannam@0 52 m_DFWindowedFrame = new double[ m_dataLength ];
cannam@0 53 m_magnitude = new double[ m_halfLength ];
cannam@0 54 m_thetaAngle = new double[ m_halfLength ];
cannam@0 55
cannam@0 56 m_window = new Window<double>(HanningWindow, m_dataLength);
cannam@0 57 }
cannam@0 58
cannam@0 59 void DetectionFunction::deInitialise()
cannam@0 60 {
cannam@2 61 delete [] m_magHistory ;
cannam@2 62 delete [] m_phaseHistory ;
cannam@2 63 delete [] m_phaseHistoryOld ;
cannam@0 64
cannam@0 65 delete m_phaseVoc;
cannam@0 66
cannam@0 67 delete [] m_DFWindowedFrame;
cannam@0 68 delete [] m_magnitude;
cannam@0 69 delete [] m_thetaAngle;
cannam@0 70
cannam@0 71 delete m_window;
cannam@0 72 }
cannam@0 73
cannam@0 74 double DetectionFunction::process( double *TDomain )
cannam@0 75 {
cannam@0 76 m_window->cut( TDomain, m_DFWindowedFrame );
cannam@0 77
cannam@0 78 m_phaseVoc->process( m_dataLength, m_DFWindowedFrame, m_magnitude, m_thetaAngle );
cannam@0 79
cannam@2 80 return runDF();
cannam@2 81 }
cannam@2 82
cannam@2 83 double DetectionFunction::process( double *magnitudes, double *phases )
cannam@2 84 {
cannam@2 85 for (size_t i = 0; i < m_halfLength; ++i) {
cannam@2 86 m_magnitude[i] = magnitudes[i];
cannam@2 87 m_thetaAngle[i] = phases[i];
cannam@2 88 }
cannam@2 89
cannam@2 90 return runDF();
cannam@2 91 }
cannam@2 92
cannam@2 93 double DetectionFunction::runDF()
cannam@2 94 {
cannam@2 95 double retVal = 0;
cannam@2 96
cannam@0 97 switch( m_DFType )
cannam@0 98 {
cannam@0 99 case DF_HFC:
cannam@0 100 retVal = HFC( m_halfLength, m_magnitude);
cannam@0 101 break;
cannam@0 102
cannam@13 103 case DF_SPECDIFF:
cannam@0 104 retVal = specDiff( m_halfLength, m_magnitude);
cannam@0 105 break;
cannam@0 106
cannam@0 107 case DF_PHASEDEV:
cannam@0 108 retVal = phaseDev( m_halfLength, m_magnitude, m_thetaAngle);
cannam@0 109 break;
cannam@0 110
cannam@0 111 case DF_COMPLEXSD:
cannam@0 112 retVal = complexSD( m_halfLength, m_magnitude, m_thetaAngle);
cannam@0 113 break;
cannam@12 114
cannam@12 115 case DF_BROADBAND:
cannam@12 116 retVal = broadband( m_halfLength, m_magnitude, m_thetaAngle);
cannam@0 117 }
cannam@0 118
cannam@0 119 return retVal;
cannam@0 120 }
cannam@0 121
cannam@0 122 double DetectionFunction::HFC(unsigned int length, double *src)
cannam@0 123 {
cannam@0 124 unsigned int i;
cannam@0 125 double val = 0;
cannam@0 126
cannam@0 127 for( i = 0; i < length; i++)
cannam@0 128 {
cannam@0 129 val += src[ i ] * ( i + 1);
cannam@0 130 }
cannam@0 131 return val;
cannam@0 132 }
cannam@0 133
cannam@0 134 double DetectionFunction::specDiff(unsigned int length, double *src)
cannam@0 135 {
cannam@0 136 unsigned int i;
cannam@0 137 double val = 0.0;
cannam@0 138 double temp = 0.0;
cannam@0 139 double diff = 0.0;
cannam@0 140
cannam@0 141 for( i = 0; i < length; i++)
cannam@0 142 {
cannam@2 143 temp = fabs( (src[ i ] * src[ i ]) - (m_magHistory[ i ] * m_magHistory[ i ]) );
cannam@0 144
cannam@0 145 diff= sqrt(temp);
cannam@0 146
cannam@13 147 // (See note in phaseDev below.)
cannam@13 148
cannam@13 149 val += diff;
cannam@0 150
cannam@2 151 m_magHistory[ i ] = src[ i ];
cannam@0 152 }
cannam@0 153
cannam@0 154 return val;
cannam@0 155 }
cannam@0 156
cannam@0 157
cannam@0 158 double DetectionFunction::phaseDev(unsigned int length, double *srcMagnitude, double *srcPhase)
cannam@0 159 {
cannam@0 160 unsigned int i;
cannam@0 161 double tmpPhase = 0;
cannam@0 162 double tmpVal = 0;
cannam@0 163 double val = 0;
cannam@0 164
cannam@0 165 double dev = 0;
cannam@0 166
cannam@0 167 for( i = 0; i < length; i++)
cannam@0 168 {
cannam@2 169 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
cannam@0 170 dev = MathUtilities::princarg( tmpPhase );
cannam@13 171
cannam@13 172 // A previous version of this code only counted the value here
cannam@13 173 // if the magnitude exceeded 0.1. My impression is that
cannam@13 174 // doesn't greatly improve the results for "loud" music (so
cannam@13 175 // long as the peak picker is reasonably sophisticated), but
cannam@13 176 // does significantly damage its ability to work with quieter
cannam@13 177 // music, so I'm removing it and counting the result always.
cannam@13 178 // Same goes for the spectral difference measure above.
cannam@0 179
cannam@13 180 tmpVal = fabs(dev);
cannam@13 181 val += tmpVal ;
cannam@0 182
cannam@2 183 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
cannam@2 184 m_phaseHistory[ i ] = srcPhase[ i ];
cannam@0 185 }
cannam@0 186
cannam@0 187
cannam@0 188 return val;
cannam@0 189 }
cannam@0 190
cannam@0 191
cannam@0 192 double DetectionFunction::complexSD(unsigned int length, double *srcMagnitude, double *srcPhase)
cannam@0 193 {
cannam@0 194 unsigned int i;
cannam@0 195 double val = 0;
cannam@0 196 double tmpPhase = 0;
cannam@0 197 double tmpReal = 0;
cannam@0 198 double tmpImag = 0;
cannam@0 199
cannam@0 200 double dev = 0;
cannam@0 201 ComplexData meas = ComplexData( 0, 0 );
cannam@2 202 ComplexData j = ComplexData( 0, 1 );
cannam@0 203
cannam@0 204 for( i = 0; i < length; i++)
cannam@0 205 {
cannam@2 206 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
cannam@0 207 dev= MathUtilities::princarg( tmpPhase );
cannam@0 208
cannam@2 209 meas = m_magHistory[i] - ( srcMagnitude[ i ] * exp( j * dev) );
cannam@0 210
cannam@0 211 tmpReal = real( meas );
cannam@0 212 tmpImag = imag( meas );
cannam@0 213
cannam@0 214 val += sqrt( (tmpReal * tmpReal) + (tmpImag * tmpImag) );
cannam@0 215
cannam@2 216 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
cannam@2 217 m_phaseHistory[ i ] = srcPhase[ i ];
cannam@2 218 m_magHistory[ i ] = srcMagnitude[ i ];
cannam@0 219 }
cannam@0 220
cannam@0 221 return val;
cannam@0 222 }
cannam@0 223
cannam@12 224 double DetectionFunction::broadband(unsigned int length, double *srcMagnitude, double *srcPhase)
cannam@12 225 {
cannam@12 226 double val = 0;
cannam@12 227 for (unsigned int i = 0; i < length; ++i) {
cannam@12 228 double sqrmag = srcMagnitude[i] * srcMagnitude[i];
cannam@12 229 if (m_magHistory[i] > 0.0) {
cannam@12 230 double diff = 10.0 * log10(sqrmag / m_magHistory[i]);
cannam@12 231 if (diff > m_dbRise) val = val + 1;
cannam@12 232 }
cannam@12 233 m_magHistory[i] = sqrmag;
cannam@12 234 }
cannam@12 235 return val;
cannam@12 236 }
cannam@12 237
cannam@0 238 double* DetectionFunction::getSpectrumMagnitude()
cannam@0 239 {
cannam@0 240 return m_magnitude;
cannam@0 241 }
cannam@0 242