diff dsp/onsets/DetectionFunction.cpp @ 14:68801ecbab6a

* add adaptive whitening and simple power metric
author cannam
date Thu, 09 Aug 2007 16:30:26 +0000
parents f2b5c4251bf3
children 2e3f5d2d62c1
line wrap: on
line diff
--- a/dsp/onsets/DetectionFunction.cpp	Wed May 23 15:22:10 2007 +0000
+++ b/dsp/onsets/DetectionFunction.cpp	Thu Aug 09 16:30:26 2007 +0000
@@ -20,6 +20,7 @@
     m_magHistory = NULL;
     m_phaseHistory = NULL;
     m_phaseHistoryOld = NULL;
+    m_magPeaks = NULL;
 
     initialise( Config );
 }
@@ -34,10 +35,17 @@
 {
     m_dataLength = Config.frameLength;
     m_halfLength = m_dataLength/2;
+
     m_DFType = Config.DFType;
     m_stepSecs = Config.stepSecs;
     m_stepSize = Config.stepSize;
 
+    m_whiten = Config.adaptiveWhitening;
+    m_whitenRelaxCoeff = Config.whiteningRelaxCoeff;
+    m_whitenFloor = Config.whiteningFloor;
+    if (m_whitenRelaxCoeff < 0) m_whitenRelaxCoeff = 0.9997;
+    if (m_whitenFloor < 0) m_whitenFloor = 0.01;
+
     m_magHistory = new double[ m_halfLength ];
     memset(m_magHistory,0, m_halfLength*sizeof(double));
 		
@@ -47,6 +55,9 @@
     m_phaseHistoryOld = new double[ m_halfLength ];
     memset(m_phaseHistoryOld,0, m_halfLength*sizeof(double));
 
+    m_magPeaks = new double[ m_halfLength ];
+    memset(m_magPeaks,0, m_halfLength*sizeof(double));
+
     m_phaseVoc = new PhaseVocoder;
 
     m_DFWindowedFrame = new double[ m_dataLength ];
@@ -61,6 +72,7 @@
     delete [] m_magHistory ;
     delete [] m_phaseHistory ;
     delete [] m_phaseHistoryOld ;
+    delete [] m_magPeaks ;
 
     delete m_phaseVoc;
 
@@ -77,6 +89,8 @@
 	
     m_phaseVoc->process( m_dataLength, m_DFWindowedFrame, m_magnitude, m_thetaAngle );
 
+    if (m_whiten) whiten();
+
     return runDF();
 }
 
@@ -87,9 +101,24 @@
         m_thetaAngle[i] = phases[i];
     }
 
+    if (m_whiten) whiten();
+
     return runDF();
 }
 
+void DetectionFunction::whiten()
+{
+    for (unsigned int i = 0; i < m_halfLength; ++i) {
+        double m = m_magnitude[i];
+        if (m < m_magPeaks[i]) {
+            m = m + (m_magPeaks[i] - m) * m_whitenRelaxCoeff;
+        }
+        if (m < m_whitenFloor) m = m_whitenFloor;
+        m_magPeaks[i] = m;
+        m_magnitude[i] /= m;
+    }
+}
+
 double DetectionFunction::runDF()
 {
     double retVal = 0;
@@ -105,7 +134,7 @@
 	break;
 	
     case DF_PHASEDEV:
-	retVal = phaseDev( m_halfLength, m_magnitude, m_thetaAngle);
+	retVal = phaseDev( m_halfLength, m_thetaAngle);
 	break;
 	
     case DF_COMPLEXSD:
@@ -113,7 +142,12 @@
 	break;
 
     case DF_BROADBAND:
-        retVal = broadband( m_halfLength, m_magnitude, m_thetaAngle);
+        retVal = broadband( m_halfLength, m_magnitude);
+        break;
+
+    case DF_POWER:
+        retVal = power( m_halfLength, m_magnitude );
+        break;
     }
 	
     return retVal;
@@ -155,7 +189,7 @@
 }
 
 
-double DetectionFunction::phaseDev(unsigned int length, double *srcMagnitude, double *srcPhase)
+double DetectionFunction::phaseDev(unsigned int length, double *srcPhase)
 {
     unsigned int i;
     double tmpPhase = 0;
@@ -221,11 +255,11 @@
     return val;
 }
 
-double DetectionFunction::broadband(unsigned int length, double *srcMagnitude, double *srcPhase)
+double DetectionFunction::broadband(unsigned int length, double *src)
 {
     double val = 0;
     for (unsigned int i = 0; i < length; ++i) {
-        double sqrmag = srcMagnitude[i] * srcMagnitude[i];
+        double sqrmag = src[i] * src[i];
         if (m_magHistory[i] > 0.0) {
             double diff = 10.0 * log10(sqrmag / m_magHistory[i]);
             if (diff > m_dbRise) val = val + 1;
@@ -235,6 +269,15 @@
     return val;
 }        
 
+double DetectionFunction::power(unsigned int length, double *src)
+{
+    double val = 0;
+    for (unsigned int i = 0; i < length; ++i) {
+        val += src[i];
+    }
+    return val;
+}        
+
 double* DetectionFunction::getSpectrumMagnitude()
 {
     return m_magnitude;