annotate dsp/onsets/DetectionFunction.cpp @ 240:1a406914b3a9

Change GetKeyMode to number bins with 1 = C, and shift chroma so that notes are centred correctly.
author chriss <devnull@localhost>
date Wed, 21 Nov 2007 16:53:51 +0000
parents 135f16b49065
children 2e3f5d2d62c1
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@239 23 m_magPeaks = NULL;
c@225 24
c@225 25 initialise( Config );
c@225 26 }
c@225 27
c@225 28 DetectionFunction::~DetectionFunction()
c@225 29 {
c@225 30 deInitialise();
c@225 31 }
c@225 32
c@225 33
c@225 34 void DetectionFunction::initialise( DFConfig Config )
c@225 35 {
c@225 36 m_dataLength = Config.frameLength;
c@225 37 m_halfLength = m_dataLength/2;
c@239 38
c@225 39 m_DFType = Config.DFType;
c@238 40 m_stepSecs = Config.stepSecs;
c@238 41 m_stepSize = Config.stepSize;
c@225 42
c@239 43 m_whiten = Config.adaptiveWhitening;
c@239 44 m_whitenRelaxCoeff = Config.whiteningRelaxCoeff;
c@239 45 m_whitenFloor = Config.whiteningFloor;
c@239 46 if (m_whitenRelaxCoeff < 0) m_whitenRelaxCoeff = 0.9997;
c@239 47 if (m_whitenFloor < 0) m_whitenFloor = 0.01;
c@239 48
c@227 49 m_magHistory = new double[ m_halfLength ];
c@227 50 memset(m_magHistory,0, m_halfLength*sizeof(double));
c@225 51
c@227 52 m_phaseHistory = new double[ m_halfLength ];
c@227 53 memset(m_phaseHistory,0, m_halfLength*sizeof(double));
c@225 54
c@227 55 m_phaseHistoryOld = new double[ m_halfLength ];
c@227 56 memset(m_phaseHistoryOld,0, m_halfLength*sizeof(double));
c@225 57
c@239 58 m_magPeaks = new double[ m_halfLength ];
c@239 59 memset(m_magPeaks,0, m_halfLength*sizeof(double));
c@239 60
c@225 61 m_phaseVoc = new PhaseVocoder;
c@225 62
c@225 63 m_DFWindowedFrame = new double[ m_dataLength ];
c@225 64 m_magnitude = new double[ m_halfLength ];
c@225 65 m_thetaAngle = new double[ m_halfLength ];
c@225 66
c@225 67 m_window = new Window<double>(HanningWindow, m_dataLength);
c@225 68 }
c@225 69
c@225 70 void DetectionFunction::deInitialise()
c@225 71 {
c@227 72 delete [] m_magHistory ;
c@227 73 delete [] m_phaseHistory ;
c@227 74 delete [] m_phaseHistoryOld ;
c@239 75 delete [] m_magPeaks ;
c@225 76
c@225 77 delete m_phaseVoc;
c@225 78
c@225 79 delete [] m_DFWindowedFrame;
c@225 80 delete [] m_magnitude;
c@225 81 delete [] m_thetaAngle;
c@225 82
c@225 83 delete m_window;
c@225 84 }
c@225 85
c@225 86 double DetectionFunction::process( double *TDomain )
c@225 87 {
c@225 88 m_window->cut( TDomain, m_DFWindowedFrame );
c@225 89
c@225 90 m_phaseVoc->process( m_dataLength, m_DFWindowedFrame, m_magnitude, m_thetaAngle );
c@225 91
c@239 92 if (m_whiten) whiten();
c@239 93
c@227 94 return runDF();
c@227 95 }
c@227 96
c@227 97 double DetectionFunction::process( double *magnitudes, double *phases )
c@227 98 {
c@227 99 for (size_t i = 0; i < m_halfLength; ++i) {
c@227 100 m_magnitude[i] = magnitudes[i];
c@227 101 m_thetaAngle[i] = phases[i];
c@227 102 }
c@227 103
c@239 104 if (m_whiten) whiten();
c@239 105
c@227 106 return runDF();
c@227 107 }
c@227 108
c@239 109 void DetectionFunction::whiten()
c@239 110 {
c@239 111 for (unsigned int i = 0; i < m_halfLength; ++i) {
c@239 112 double m = m_magnitude[i];
c@239 113 if (m < m_magPeaks[i]) {
c@239 114 m = m + (m_magPeaks[i] - m) * m_whitenRelaxCoeff;
c@239 115 }
c@239 116 if (m < m_whitenFloor) m = m_whitenFloor;
c@239 117 m_magPeaks[i] = m;
c@239 118 m_magnitude[i] /= m;
c@239 119 }
c@239 120 }
c@239 121
c@227 122 double DetectionFunction::runDF()
c@227 123 {
c@227 124 double retVal = 0;
c@227 125
c@225 126 switch( m_DFType )
c@225 127 {
c@225 128 case DF_HFC:
c@225 129 retVal = HFC( m_halfLength, m_magnitude);
c@225 130 break;
c@225 131
c@238 132 case DF_SPECDIFF:
c@225 133 retVal = specDiff( m_halfLength, m_magnitude);
c@225 134 break;
c@225 135
c@225 136 case DF_PHASEDEV:
c@239 137 retVal = phaseDev( m_halfLength, m_thetaAngle);
c@225 138 break;
c@225 139
c@225 140 case DF_COMPLEXSD:
c@225 141 retVal = complexSD( m_halfLength, m_magnitude, m_thetaAngle);
c@225 142 break;
c@237 143
c@237 144 case DF_BROADBAND:
c@239 145 retVal = broadband( m_halfLength, m_magnitude);
c@239 146 break;
c@239 147
c@239 148 case DF_POWER:
c@239 149 retVal = power( m_halfLength, m_magnitude );
c@239 150 break;
c@225 151 }
c@225 152
c@225 153 return retVal;
c@225 154 }
c@225 155
c@225 156 double DetectionFunction::HFC(unsigned int length, double *src)
c@225 157 {
c@225 158 unsigned int i;
c@225 159 double val = 0;
c@225 160
c@225 161 for( i = 0; i < length; i++)
c@225 162 {
c@225 163 val += src[ i ] * ( i + 1);
c@225 164 }
c@225 165 return val;
c@225 166 }
c@225 167
c@225 168 double DetectionFunction::specDiff(unsigned int length, double *src)
c@225 169 {
c@225 170 unsigned int i;
c@225 171 double val = 0.0;
c@225 172 double temp = 0.0;
c@225 173 double diff = 0.0;
c@225 174
c@225 175 for( i = 0; i < length; i++)
c@225 176 {
c@227 177 temp = fabs( (src[ i ] * src[ i ]) - (m_magHistory[ i ] * m_magHistory[ i ]) );
c@225 178
c@225 179 diff= sqrt(temp);
c@225 180
c@238 181 // (See note in phaseDev below.)
c@238 182
c@238 183 val += diff;
c@225 184
c@227 185 m_magHistory[ i ] = src[ i ];
c@225 186 }
c@225 187
c@225 188 return val;
c@225 189 }
c@225 190
c@225 191
c@239 192 double DetectionFunction::phaseDev(unsigned int length, double *srcPhase)
c@225 193 {
c@225 194 unsigned int i;
c@225 195 double tmpPhase = 0;
c@225 196 double tmpVal = 0;
c@225 197 double val = 0;
c@225 198
c@225 199 double dev = 0;
c@225 200
c@225 201 for( i = 0; i < length; i++)
c@225 202 {
c@227 203 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
c@225 204 dev = MathUtilities::princarg( tmpPhase );
c@238 205
c@238 206 // A previous version of this code only counted the value here
c@238 207 // if the magnitude exceeded 0.1. My impression is that
c@238 208 // doesn't greatly improve the results for "loud" music (so
c@238 209 // long as the peak picker is reasonably sophisticated), but
c@238 210 // does significantly damage its ability to work with quieter
c@238 211 // music, so I'm removing it and counting the result always.
c@238 212 // Same goes for the spectral difference measure above.
c@225 213
c@238 214 tmpVal = fabs(dev);
c@238 215 val += tmpVal ;
c@225 216
c@227 217 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
c@227 218 m_phaseHistory[ i ] = srcPhase[ i ];
c@225 219 }
c@225 220
c@225 221
c@225 222 return val;
c@225 223 }
c@225 224
c@225 225
c@225 226 double DetectionFunction::complexSD(unsigned int length, double *srcMagnitude, double *srcPhase)
c@225 227 {
c@225 228 unsigned int i;
c@225 229 double val = 0;
c@225 230 double tmpPhase = 0;
c@225 231 double tmpReal = 0;
c@225 232 double tmpImag = 0;
c@225 233
c@225 234 double dev = 0;
c@225 235 ComplexData meas = ComplexData( 0, 0 );
c@227 236 ComplexData j = ComplexData( 0, 1 );
c@225 237
c@225 238 for( i = 0; i < length; i++)
c@225 239 {
c@227 240 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
c@225 241 dev= MathUtilities::princarg( tmpPhase );
c@225 242
c@227 243 meas = m_magHistory[i] - ( srcMagnitude[ i ] * exp( j * dev) );
c@225 244
c@225 245 tmpReal = real( meas );
c@225 246 tmpImag = imag( meas );
c@225 247
c@225 248 val += sqrt( (tmpReal * tmpReal) + (tmpImag * tmpImag) );
c@225 249
c@227 250 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
c@227 251 m_phaseHistory[ i ] = srcPhase[ i ];
c@227 252 m_magHistory[ i ] = srcMagnitude[ i ];
c@225 253 }
c@225 254
c@225 255 return val;
c@225 256 }
c@225 257
c@239 258 double DetectionFunction::broadband(unsigned int length, double *src)
c@237 259 {
c@237 260 double val = 0;
c@237 261 for (unsigned int i = 0; i < length; ++i) {
c@239 262 double sqrmag = src[i] * src[i];
c@237 263 if (m_magHistory[i] > 0.0) {
c@237 264 double diff = 10.0 * log10(sqrmag / m_magHistory[i]);
c@237 265 if (diff > m_dbRise) val = val + 1;
c@237 266 }
c@237 267 m_magHistory[i] = sqrmag;
c@237 268 }
c@237 269 return val;
c@237 270 }
c@237 271
c@239 272 double DetectionFunction::power(unsigned int length, double *src)
c@239 273 {
c@239 274 double val = 0;
c@239 275 for (unsigned int i = 0; i < length; ++i) {
c@239 276 val += src[i];
c@239 277 }
c@239 278 return val;
c@239 279 }
c@239 280
c@225 281 double* DetectionFunction::getSpectrumMagnitude()
c@225 282 {
c@225 283 return m_magnitude;
c@225 284 }
c@225 285