changeset 14:68801ecbab6a

* add adaptive whitening and simple power metric
author cannam
date Thu, 09 Aug 2007 16:30:26 +0000
parents f2b5c4251bf3
children 10c3f9df4a07
files dsp/onsets/DetectionFunction.cpp dsp/onsets/DetectionFunction.h
diffstat 2 files changed, 60 insertions(+), 7 deletions(-) [+]
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;
--- a/dsp/onsets/DetectionFunction.h	Wed May 23 15:22:10 2007 +0000
+++ b/dsp/onsets/DetectionFunction.h	Thu Aug 09 16:30:26 2007 +0000
@@ -21,6 +21,7 @@
 #define DF_PHASEDEV (3)
 #define DF_COMPLEXSD (4)
 #define DF_BROADBAND (5)
+#define DF_POWER (6)
 
 struct DFConfig{
     double stepSecs; // DF step in seconds
@@ -28,6 +29,9 @@
     unsigned int frameLength; // DF analysis window - usually 2*step
     int DFType; // type of detection function ( see defines )
     double dbRise; // only used for broadband df (and required for it)
+    bool adaptiveWhitening; // perform adaptive whitening
+    double whiteningRelaxCoeff; // if < 0, a sensible default will be used
+    double whiteningFloor; // if < 0, a sensible default will be used
 };
 
 class DetectionFunction  
@@ -40,13 +44,15 @@
     double process( double* magnitudes, double* phases );
 
 private:
+    void whiten();
     double runDF();
 
     double HFC( unsigned int length, double* src);
     double specDiff( unsigned int length, double* src);
-    double phaseDev(unsigned int length, double *srcMagnitude, double *srcPhase);
+    double phaseDev(unsigned int length, double *srcPhase);
     double complexSD(unsigned int length, double *srcMagnitude, double *srcPhase);
-    double broadband(unsigned int length, double *srcMagnitude, double *srcPhase);
+    double broadband(unsigned int length, double *srcMagnitude);
+    double power(unsigned int length, double *src);
 	
 private:
     void initialise( DFConfig Config );
@@ -58,10 +64,14 @@
     double m_stepSecs;
     unsigned int m_stepSize;
     double m_dbRise;
+    bool m_whiten;
+    double m_whitenRelaxCoeff;
+    double m_whitenFloor;
 
     double* m_magHistory;
     double* m_phaseHistory;
     double* m_phaseHistoryOld;
+    double* m_magPeaks;
 
     double* m_DFWindowedFrame; // Array for windowed analysis frame
     double* m_magnitude; // Magnitude of analysis frame ( frequency domain )