annotate dsp/onsets/DetectionFunction.cpp @ 483:fdaa63607c15

Untabify, indent, tidy
author Chris Cannam <cannam@all-day-breakfast.com>
date Fri, 31 May 2019 11:54:32 +0100
parents c5e1b25d5177
children af5b7ef02aa7
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@309 7 This file 2005-2006 Christian Landone.
c@309 8
c@309 9 This program is free software; you can redistribute it and/or
c@309 10 modify it under the terms of the GNU General Public License as
c@309 11 published by the Free Software Foundation; either version 2 of the
c@309 12 License, or (at your option) any later version. See the file
c@309 13 COPYING included with this distribution for more information.
c@225 14 */
c@225 15
c@225 16 #include "DetectionFunction.h"
c@272 17 #include <cstring>
c@225 18
c@225 19 //////////////////////////////////////////////////////////////////////
c@225 20 // Construction/Destruction
c@225 21 //////////////////////////////////////////////////////////////////////
c@225 22
c@225 23 DetectionFunction::DetectionFunction( DFConfig Config ) :
c@225 24 m_window(0)
c@225 25 {
c@227 26 m_magHistory = NULL;
c@227 27 m_phaseHistory = NULL;
c@227 28 m_phaseHistoryOld = NULL;
c@239 29 m_magPeaks = NULL;
c@225 30
c@225 31 initialise( Config );
c@225 32 }
c@225 33
c@225 34 DetectionFunction::~DetectionFunction()
c@225 35 {
c@225 36 deInitialise();
c@225 37 }
c@225 38
c@225 39
c@225 40 void DetectionFunction::initialise( DFConfig Config )
c@225 41 {
c@225 42 m_dataLength = Config.frameLength;
c@340 43 m_halfLength = m_dataLength/2 + 1;
c@239 44
c@225 45 m_DFType = Config.DFType;
c@238 46 m_stepSize = Config.stepSize;
c@410 47 m_dbRise = Config.dbRise;
c@225 48
c@239 49 m_whiten = Config.adaptiveWhitening;
c@239 50 m_whitenRelaxCoeff = Config.whiteningRelaxCoeff;
c@239 51 m_whitenFloor = Config.whiteningFloor;
c@239 52 if (m_whitenRelaxCoeff < 0) m_whitenRelaxCoeff = 0.9997;
c@239 53 if (m_whitenFloor < 0) m_whitenFloor = 0.01;
c@239 54
c@227 55 m_magHistory = new double[ m_halfLength ];
c@227 56 memset(m_magHistory,0, m_halfLength*sizeof(double));
cannam@483 57
c@227 58 m_phaseHistory = new double[ m_halfLength ];
c@227 59 memset(m_phaseHistory,0, m_halfLength*sizeof(double));
c@225 60
c@227 61 m_phaseHistoryOld = new double[ m_halfLength ];
c@227 62 memset(m_phaseHistoryOld,0, m_halfLength*sizeof(double));
c@225 63
c@239 64 m_magPeaks = new double[ m_halfLength ];
c@239 65 memset(m_magPeaks,0, m_halfLength*sizeof(double));
c@239 66
c@356 67 m_phaseVoc = new PhaseVocoder(m_dataLength, m_stepSize);
c@225 68
c@225 69 m_magnitude = new double[ m_halfLength ];
c@225 70 m_thetaAngle = new double[ m_halfLength ];
c@340 71 m_unwrapped = new double[ m_halfLength ];
c@225 72
c@225 73 m_window = new Window<double>(HanningWindow, m_dataLength);
c@344 74 m_windowed = new double[ m_dataLength ];
c@225 75 }
c@225 76
c@225 77 void DetectionFunction::deInitialise()
c@225 78 {
c@227 79 delete [] m_magHistory ;
c@227 80 delete [] m_phaseHistory ;
c@227 81 delete [] m_phaseHistoryOld ;
c@239 82 delete [] m_magPeaks ;
c@225 83
c@225 84 delete m_phaseVoc;
c@225 85
c@225 86 delete [] m_magnitude;
c@225 87 delete [] m_thetaAngle;
c@344 88 delete [] m_windowed;
c@344 89 delete [] m_unwrapped;
c@225 90
c@225 91 delete m_window;
c@225 92 }
c@225 93
c@344 94 double DetectionFunction::processTimeDomain(const double *samples)
c@225 95 {
c@344 96 m_window->cut(samples, m_windowed);
c@280 97
c@344 98 m_phaseVoc->processTimeDomain(m_windowed,
c@344 99 m_magnitude, m_thetaAngle, m_unwrapped);
c@225 100
c@239 101 if (m_whiten) whiten();
c@239 102
c@227 103 return runDF();
c@227 104 }
c@227 105
c@344 106 double DetectionFunction::processFrequencyDomain(const double *reals,
c@344 107 const double *imags)
c@227 108 {
c@344 109 m_phaseVoc->processFrequencyDomain(reals, imags,
c@344 110 m_magnitude, m_thetaAngle, m_unwrapped);
c@227 111
c@239 112 if (m_whiten) whiten();
c@239 113
c@227 114 return runDF();
c@227 115 }
c@227 116
c@239 117 void DetectionFunction::whiten()
c@239 118 {
c@239 119 for (unsigned int i = 0; i < m_halfLength; ++i) {
c@239 120 double m = m_magnitude[i];
c@239 121 if (m < m_magPeaks[i]) {
c@239 122 m = m + (m_magPeaks[i] - m) * m_whitenRelaxCoeff;
c@239 123 }
c@239 124 if (m < m_whitenFloor) m = m_whitenFloor;
c@239 125 m_magPeaks[i] = m;
c@239 126 m_magnitude[i] /= m;
c@239 127 }
c@239 128 }
c@239 129
c@227 130 double DetectionFunction::runDF()
c@227 131 {
c@227 132 double retVal = 0;
c@227 133
c@225 134 switch( m_DFType )
c@225 135 {
c@225 136 case DF_HFC:
cannam@483 137 retVal = HFC( m_halfLength, m_magnitude);
cannam@483 138 break;
cannam@483 139
c@238 140 case DF_SPECDIFF:
cannam@483 141 retVal = specDiff( m_halfLength, m_magnitude);
cannam@483 142 break;
cannam@483 143
c@225 144 case DF_PHASEDEV:
c@345 145 // Using the instantaneous phases here actually provides the
c@345 146 // same results (for these calculations) as if we had used
c@345 147 // unwrapped phases, but without the possible accumulation of
c@345 148 // phase error over time
cannam@483 149 retVal = phaseDev( m_halfLength, m_thetaAngle);
cannam@483 150 break;
cannam@483 151
c@225 152 case DF_COMPLEXSD:
cannam@483 153 retVal = complexSD( m_halfLength, m_magnitude, m_thetaAngle);
cannam@483 154 break;
c@237 155
c@237 156 case DF_BROADBAND:
c@239 157 retVal = broadband( m_halfLength, m_magnitude);
c@239 158 break;
c@225 159 }
cannam@483 160
c@225 161 return retVal;
c@225 162 }
c@225 163
c@225 164 double DetectionFunction::HFC(unsigned int length, double *src)
c@225 165 {
c@225 166 unsigned int i;
c@225 167 double val = 0;
c@225 168
cannam@483 169 for( i = 0; i < length; i++) {
cannam@483 170 val += src[ i ] * ( i + 1);
c@225 171 }
c@225 172 return val;
c@225 173 }
c@225 174
c@225 175 double DetectionFunction::specDiff(unsigned int length, double *src)
c@225 176 {
c@225 177 unsigned int i;
c@225 178 double val = 0.0;
c@225 179 double temp = 0.0;
c@225 180 double diff = 0.0;
c@225 181
cannam@483 182 for( i = 0; i < length; i++) {
cannam@483 183
cannam@483 184 temp = fabs( (src[ i ] * src[ i ]) - (m_magHistory[ i ] * m_magHistory[ i ]) );
cannam@483 185
cannam@483 186 diff= sqrt(temp);
c@225 187
c@238 188 // (See note in phaseDev below.)
c@238 189
c@238 190 val += diff;
c@225 191
cannam@483 192 m_magHistory[ i ] = src[ i ];
c@225 193 }
c@225 194
c@225 195 return val;
c@225 196 }
c@225 197
c@225 198
c@239 199 double DetectionFunction::phaseDev(unsigned int length, double *srcPhase)
c@225 200 {
c@225 201 unsigned int i;
c@225 202 double tmpPhase = 0;
c@225 203 double tmpVal = 0;
c@225 204 double val = 0;
c@225 205
c@225 206 double dev = 0;
c@225 207
cannam@483 208 for( i = 0; i < length; i++) {
cannam@483 209 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
cannam@483 210 dev = MathUtilities::princarg( tmpPhase );
c@238 211
c@238 212 // A previous version of this code only counted the value here
c@238 213 // if the magnitude exceeded 0.1. My impression is that
c@238 214 // doesn't greatly improve the results for "loud" music (so
c@238 215 // long as the peak picker is reasonably sophisticated), but
c@238 216 // does significantly damage its ability to work with quieter
c@238 217 // music, so I'm removing it and counting the result always.
c@238 218 // Same goes for the spectral difference measure above.
cannam@483 219
c@238 220 tmpVal = fabs(dev);
c@238 221 val += tmpVal ;
c@225 222
cannam@483 223 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
cannam@483 224 m_phaseHistory[ i ] = srcPhase[ i ];
c@225 225 }
cannam@483 226
c@225 227 return val;
c@225 228 }
c@225 229
c@225 230
c@225 231 double DetectionFunction::complexSD(unsigned int length, double *srcMagnitude, double *srcPhase)
c@225 232 {
c@225 233 unsigned int i;
c@225 234 double val = 0;
c@225 235 double tmpPhase = 0;
c@225 236 double tmpReal = 0;
c@225 237 double tmpImag = 0;
c@225 238
c@225 239 double dev = 0;
c@225 240 ComplexData meas = ComplexData( 0, 0 );
c@227 241 ComplexData j = ComplexData( 0, 1 );
c@225 242
cannam@483 243 for( i = 0; i < length; i++) {
cannam@483 244
cannam@483 245 tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
cannam@483 246 dev= MathUtilities::princarg( tmpPhase );
cannam@483 247
cannam@483 248 meas = m_magHistory[i] - ( srcMagnitude[ i ] * exp( j * dev) );
c@225 249
cannam@483 250 tmpReal = real( meas );
cannam@483 251 tmpImag = imag( meas );
c@225 252
cannam@483 253 val += sqrt( (tmpReal * tmpReal) + (tmpImag * tmpImag) );
cannam@483 254
cannam@483 255 m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
cannam@483 256 m_phaseHistory[ i ] = srcPhase[ i ];
cannam@483 257 m_magHistory[ i ] = srcMagnitude[ i ];
c@225 258 }
c@225 259
c@225 260 return val;
c@225 261 }
c@225 262
c@239 263 double DetectionFunction::broadband(unsigned int length, double *src)
c@237 264 {
c@237 265 double val = 0;
c@237 266 for (unsigned int i = 0; i < length; ++i) {
c@239 267 double sqrmag = src[i] * src[i];
c@237 268 if (m_magHistory[i] > 0.0) {
c@237 269 double diff = 10.0 * log10(sqrmag / m_magHistory[i]);
c@237 270 if (diff > m_dbRise) val = val + 1;
c@237 271 }
c@237 272 m_magHistory[i] = sqrmag;
c@237 273 }
c@237 274 return val;
c@237 275 }
c@237 276
c@225 277 double* DetectionFunction::getSpectrumMagnitude()
c@225 278 {
c@225 279 return m_magnitude;
c@225 280 }
c@225 281