diff flattendynamics-ladspa.cpp @ 17:ca4e31d86436

The complicated long-and-short-term approach is not working any better than a simple long-term window. Revert to that, with some decay.
author Chris Cannam
date Wed, 23 Jul 2014 15:17:47 +0100
parents c12cab43141d
children d25a2e91e9d8
line wrap: on
line diff
--- a/flattendynamics-ladspa.cpp	Wed Jul 23 10:29:26 2014 +0100
+++ b/flattendynamics-ladspa.cpp	Wed Jul 23 15:17:47 2014 +0100
@@ -8,10 +8,9 @@
 using std::cerr;
 using std::endl;
 
-const float longTermSeconds = 4.f;
-const float shortTermSeconds = 1.f;
+const float historySeconds = 4.f;
 const float catchUpSeconds = 0.2f;
-const float targetMaxRMS = 0.04f;
+const float targetMaxRMS = 0.05f;
 const float rmsMaxDecay = 0.999f; // per sample
 const float maxGain = 20.f;
 
@@ -82,12 +81,9 @@
     m_histlen(0),
     m_histwrite(0),
     m_histread(0),
-    m_sumOfSquaresLongTerm(0.f),
-    m_sumOfSquaresShortTerm(0.f),
-    m_rmsLongTerm(0.f),
-    m_rmsShortTerm(0.f),
-    m_maxRmsLongTerm(0.f),
-    m_maxRmsShortTerm(0.f),
+    m_sumOfSquares(0.f),
+    m_rms(0.f),
+    m_maxRms(0.f),
     m_gain(1.f)
 {
     reset();
@@ -168,7 +164,7 @@
 FlattenDynamics::reset()
 {
     delete[] m_history;
-    m_histlen = int(round(m_sampleRate * longTermSeconds));
+    m_histlen = int(round(m_sampleRate * historySeconds));
     if (m_histlen < 1) m_histlen = 1;
     m_history = new float[m_histlen];
     for (int i = 0; i < m_histlen; ++i) {
@@ -177,12 +173,9 @@
     m_histwrite = 0;
     m_histread = 0;
 
-    m_sumOfSquaresLongTerm = 0.0;
-    m_sumOfSquaresShortTerm = 0.0;
-    m_rmsLongTerm = 0.f;
-    m_rmsShortTerm = 0.f;
-    m_maxRmsLongTerm = 0.f;
-    m_maxRmsShortTerm = 0.f;
+    m_sumOfSquares = 0.0;
+    m_rms = 0.f;
+    m_maxRms = 0.f;
     m_gain = 1.f;
 }
 
@@ -209,30 +202,17 @@
 {
     updateRMS(f);
 
-    if (m_rmsLongTerm == 0.f) {
+    if (m_rms == 0.f) {
         return f;
     }
 
-    if (m_rmsLongTerm >= m_maxRmsLongTerm) {
-        m_maxRmsLongTerm = m_rmsLongTerm;
-    } else if (m_rmsLongTerm < m_maxRmsLongTerm * rmsMaxDecay) {
-        m_maxRmsLongTerm *= rmsMaxDecay;
+    if (m_rms >= m_maxRms) {
+        m_maxRms = m_rms;
+    } else {
+        m_maxRms = m_rms + (m_maxRms - m_rms) * rmsMaxDecay;
     }
 
-    if (m_rmsShortTerm > m_maxRmsShortTerm) {
-        m_maxRmsShortTerm = m_rmsShortTerm;
-    }
-
-    float fixedGain = targetMaxRMS / m_maxRmsLongTerm;
-
-    float frac = m_rmsShortTerm / m_maxRmsShortTerm;
-
-    // push up toward top of 0,1 range
-    frac = pow(frac, 0.3);
-
-    float targetRMS = (frac * m_maxRmsShortTerm);
-
-    float targetGain = fixedGain * (targetRMS / m_rmsShortTerm);
+    float targetGain = targetMaxRMS / m_maxRms;
 
     if (targetGain > maxGain) {
         targetGain = maxGain;
@@ -262,36 +242,23 @@
 
     int nextWrite = (m_histwrite + 1) % m_histlen;
 
-    float loseLongTerm = 0.f;
-    float loseShortTerm = 0.f;
+    float lose = 0.f;
 
     if (nextWrite == m_histread) {
         // full
-        loseLongTerm = m_history[m_histread];
+        lose = m_history[m_histread];
         m_histread = (m_histread + 1) % m_histlen;
     }
 
-    int shortTermLength = round(shortTermSeconds * m_sampleRate);
-    int shortTermLoseIndex = nextWrite - shortTermLength;
-    if (shortTermLoseIndex < 0) {
-        shortTermLoseIndex += m_histlen;
-    }
-    // This depends on history being zero-initialised, to be correct at start:
-    loseShortTerm = m_history[shortTermLoseIndex];
-
     m_history[m_histwrite] = f;
     m_histwrite = nextWrite;
 
     int fill = (m_histwrite - m_histread + m_histlen) % m_histlen;
 
-    m_sumOfSquaresLongTerm -= loseLongTerm * loseLongTerm;
-    m_sumOfSquaresLongTerm += f * f;
+    m_sumOfSquares -= lose * lose;
+    m_sumOfSquares += f * f;
 
-    m_sumOfSquaresShortTerm -= loseShortTerm * loseShortTerm;
-    m_sumOfSquaresShortTerm += f * f;
-
-    m_rmsLongTerm = sqrt(m_sumOfSquaresLongTerm / fill);
-    m_rmsShortTerm = sqrt(m_sumOfSquaresShortTerm / shortTermLength);
+    m_rms = sqrt(m_sumOfSquares / fill);
 //    cerr << "rms = " << m_rms << " (from " << fill << " samples of " << m_histlen << ", latest " << f << ")" << endl;
 }