changeset 1:f21753c504e1

Add gain output port, update rms values
author Chris Cannam
date Thu, 17 Jul 2014 13:27:07 +0100
parents 7632b9bf0cff
children 57990edc441b
files flattendynamics-ladspa.cpp flattendynamics-ladspa.h
diffstat 2 files changed, 84 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/flattendynamics-ladspa.cpp	Thu Jul 17 12:16:02 2014 +0100
+++ b/flattendynamics-ladspa.cpp	Thu Jul 17 13:27:07 2014 +0100
@@ -6,11 +6,14 @@
 #include <iostream>
 #include <cmath>
 
+const float historySeconds = 4.f;
+
 const char *const
 FlattenDynamics::portNames[PortCount] =
 {
     "Input",
     "Output",
+    "Gain",
 };
 
 const LADSPA_PortDescriptor 
@@ -18,6 +21,7 @@
 {
     LADSPA_PORT_INPUT  | LADSPA_PORT_AUDIO,
     LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
+    LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL,
 };
 
 const LADSPA_PortRangeHint 
@@ -25,6 +29,7 @@
 {
     { 0, 0, 0 },
     { 0, 0, 0 },
+    { 0, 0, 0 },
 };
 
 const LADSPA_Properties
@@ -64,13 +69,22 @@
 FlattenDynamics::FlattenDynamics(int sampleRate) :
     m_sampleRate(sampleRate),
     m_input(0),
-    m_output(0)
+    m_output(0),
+    m_pgain(0),
+    m_history(0),
+    m_histlen(0),
+    m_histwrite(0),
+    m_histread(0),
+    m_sumOfSquares(0),
+    m_rms(0),
+    m_gain(1.f)
 {
     reset();
 }
 
 FlattenDynamics::~FlattenDynamics()
 {
+    delete m_history;
 }
     
 LADSPA_Handle
@@ -89,6 +103,7 @@
     float **ports[PortCount] = {
 	&flatten->m_input,
 	&flatten->m_output,
+        &flatten->m_pgain,
     };
 
     *ports[port] = (float *)location;
@@ -123,11 +138,21 @@
 void
 FlattenDynamics::reset()
 {
+    delete m_history;
+    m_histlen = int(round(m_sampleRate * historySeconds));
+    m_history = new float(m_histlen);
+    m_histwrite = 0;
+    m_histread = 0;
+
+    m_sumOfSquares = 0.0;
+    m_rms = 0.0;
+    m_gain = 1.f;
 }
 
 void
 FlattenDynamics::updateParameters()
 {
+    if (m_pgain) *m_pgain = m_gain;
 }
 
 void
@@ -136,15 +161,53 @@
     if (!m_input || !m_output) return;
     updateParameters();
 
-    int ii = 0;
-    int oi = 0;
+    // Adjust gain so that
+    // * RMS level of the past N seconds is some fixed R, but
+    // * peak level does not clip
+    // We aim to take M seconds to move to our target gain
+
+    int i = 0;
     const int sc = sampleCount;
 
-    while (ii < sc) {
-        //!!!
+    while (i < sc) {
+        m_output[i] = process(m_input[i]);
     }
 }
 
+float
+FlattenDynamics::process(float f)
+{
+    updateRMS(f);
+}
+
+void
+FlattenDynamics::updateRMS(float f)
+{
+    int nextWrite = (m_histwrite + 1) % m_histlen;
+
+    float lose;
+    int fill;
+
+    if (nextWrite == m_histread) {
+        // full
+        lose = m_history[m_histread];
+        m_histread = (m_histread + 1) % m_histlen;
+        fill = m_histlen;
+    } else {
+        // not full
+        lose = 0.f;
+        fill = (m_histwrite - m_histread + m_histlen) % m_histlen;
+    }
+
+    m_history[m_histwrite] = f;
+    m_histwrite = nextWrite;
+
+    m_sumOfSquares -= lose * lose;
+    m_sumOfSquares += f * f;
+
+    m_rms = sqrt(m_sumOfSquares / fill);
+}
+
 const LADSPA_Descriptor *
 ladspa_descriptor(unsigned long ix)
 {
--- a/flattendynamics-ladspa.h	Thu Jul 17 12:16:02 2014 +0100
+++ b/flattendynamics-ladspa.h	Thu Jul 17 13:27:07 2014 +0100
@@ -15,9 +15,10 @@
     ~FlattenDynamics();
 
     enum {
-        InputPort     = 0,
-	OutputPort    = 1,
-	PortCount     = 2,
+        AudioInputPort     = 0,
+	AudioOutputPort    = 1,
+        GainOutputPort     = 2,
+	PortCount          = 3,
     };
 
     static const char *const portNames[PortCount];
@@ -35,11 +36,23 @@
 
     void reset();
     void runImpl(unsigned long);
+    float process(float);
+    void updateRMS(float);
     void updateParameters();
 
     int m_sampleRate;
     float *m_input;
     float *m_output;
+    float *m_pgain;
+
+    float *m_history;
+    int m_histlen;
+    int m_histwrite;
+    int m_histread;
+
+    double m_sumOfSquares;
+    float m_rms;
+    float m_gain;
 };
 
 #endif