Mercurial > hg > flattendynamics
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