annotate dsp/onsets/DetectionFunction.cpp @ 238:e8e5f9130b49

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