[DEV] rename internal menber of class

This commit is contained in:
Edouard DUPIN 2015-04-03 21:48:21 +02:00
parent 942a9cf67b
commit 4d3296a9e1
16 changed files with 161 additions and 256 deletions

View File

@ -24,27 +24,27 @@
*/ */
#include "AttRelEnvelope.h" #include <audio/algo/chunkware/AttRelEnvelope.h>
audio::algo::chunkware::AttRelEnvelope::AttRelEnvelope(double att_ms, double rel_ms, double sampleRate) : audio::algo::chunkware::AttRelEnvelope::AttRelEnvelope(double m_attackms, double m_releasems, double sampleRate) :
att_(att_ms, sampleRate), m_attack(m_attackms, sampleRate),
rel_(rel_ms, sampleRate) { m_release(m_releasems, sampleRate) {
} }
//------------------------------------------------------------- //-------------------------------------------------------------
void audio::algo::chunkware::AttRelEnvelope::setAttack(double ms) { void audio::algo::chunkware::AttRelEnvelope::setAttack(double ms) {
att_.setTc(ms); m_attack.setTc(ms);
} }
//------------------------------------------------------------- //-------------------------------------------------------------
void audio::algo::chunkware::AttRelEnvelope::setRelease(double ms) { void audio::algo::chunkware::AttRelEnvelope::setRelease(double ms) {
rel_.setTc(ms); m_release.setTc(ms);
} }
//------------------------------------------------------------- //-------------------------------------------------------------
void audio::algo::chunkware::AttRelEnvelope::setSampleRate(double sampleRate) { void audio::algo::chunkware::AttRelEnvelope::setSampleRate(double sampleRate) {
att_.setSampleRate(sampleRate); m_attack.setSampleRate(sampleRate);
rel_.setSampleRate(sampleRate); m_release.setSampleRate(sampleRate);
} }

View File

@ -27,7 +27,7 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_ATT_REL_ENVELOPE_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_ATT_REL_ENVELOPE_H__
#define __AUDIO_ALGO_CHUNKWARE_ATT_REL_ENVELOPE_H__ #define __AUDIO_ALGO_CHUNKWARE_ATT_REL_ENVELOPE_H__
#include "EnvelopeDetector.h" #include <audio/algo/chunkware/EnvelopeDetector.h>
namespace audio { namespace audio {
namespace algo { namespace algo {
@ -37,24 +37,24 @@ namespace audio {
//------------------------------------------------------------- //-------------------------------------------------------------
class AttRelEnvelope { class AttRelEnvelope {
public: public:
AttRelEnvelope(double att_ms = 10.0, AttRelEnvelope(double m_attackms = 10.0,
double rel_ms = 100.0, double m_releasems = 100.0,
double sampleRate = 44100.0); double sampleRate = 44100.0);
virtual ~AttRelEnvelope() {} virtual ~AttRelEnvelope() {}
// attack time constant // attack time constant
virtual void setAttack(double ms); virtual void setAttack(double ms);
virtual double getAttack() const { virtual double getAttack() const {
return att_.getTc(); return m_attack.getTc();
} }
// release time constant // release time constant
virtual void setRelease(double ms); virtual void setRelease(double ms);
virtual double getRelease() const { virtual double getRelease() const {
return rel_.getTc(); return m_release.getTc();
} }
// sample rate dependencies // sample rate dependencies
virtual void setSampleRate(double sampleRate); virtual void setSampleRate(double sampleRate);
virtual double getSampleRate() const { virtual double getSampleRate() const {
return att_.getSampleRate(); return m_attack.getSampleRate();
} }
// runtime function // runtime function
void run(double in, double &state) { void run(double in, double &state) {
@ -65,15 +65,15 @@ namespace audio {
*/ */
if (in > state) { if (in > state) {
// attack // attack
att_.run(in, state); m_attack.run(in, state);
} else { } else {
// release // release
rel_.run(in, state); m_release.run(in, state);
} }
} }
private: private:
EnvelopeDetector att_; EnvelopeDetector m_attack;
EnvelopeDetector rel_; EnvelopeDetector m_release;
}; };
} }
} }

View File

@ -23,27 +23,28 @@
* DEALINGS IN THE SOFTWARE. * DEALINGS IN THE SOFTWARE.
*/ */
#include "Compressor.h" #include <audio/algo/chunkware/Compressor.h>
#include <audio/algo/chunkware/debug.h>
audio::algo::chunkware::Compresssor::Compresssor() : audio::algo::chunkware::Compresssor::Compresssor() :
AttRelEnvelope(10.0, 100.0), AttRelEnvelope(10.0, 100.0),
threshdB_(0.0), m_threshdB(0.0),
ratio_(1.0), m_ratio(1.0),
envdB_(DC_OFFSET) { m_overThresholdEnvelopeDB(DC_OFFSET) {
} }
void audio::algo::chunkware::Compresssor::setThresh(double dB) { void audio::algo::chunkware::Compresssor::setThresh(double dB) {
threshdB_ = dB; m_threshdB = dB;
} }
void audio::algo::chunkware::Compresssor::setRatio(double ratio) { void audio::algo::chunkware::Compresssor::setRatio(double ratio) {
assert(ratio > 0.0); AA_CHUNK_ASSERT(ratio > 0.0, "input function error");
ratio_ = ratio; m_ratio = ratio;
} }
void audio::algo::chunkware::Compresssor::initRuntime() { void audio::algo::chunkware::Compresssor::initRuntime() {
envdB_ = DC_OFFSET; m_overThresholdEnvelopeDB = DC_OFFSET;
} }
void audio::algo::chunkware::Compresssor::process(double &in1, double &in2) { void audio::algo::chunkware::Compresssor::process(double &in1, double &in2) {
@ -63,13 +64,13 @@ void audio::algo::chunkware::Compresssor::process(double &in1, double &in2, doub
keyLinked += DC_OFFSET; // add DC offset to avoid log(0) keyLinked += DC_OFFSET; // add DC offset to avoid log(0)
double keydB = lin2dB(keyLinked); // convert linear -> dB double keydB = lin2dB(keyLinked); // convert linear -> dB
// threshold // threshold
double overdB = keydB - threshdB_; // delta over threshold double overdB = keydB - m_threshdB; // delta over threshold
if (overdB < 0.0) if (overdB < 0.0)
overdB = 0.0; overdB = 0.0;
// attack/release // attack/release
overdB += DC_OFFSET; // add DC offset to avoid denormal overdB += DC_OFFSET; // add DC offset to avoid denormal
AttRelEnvelope::run(overdB, envdB_); // run attack/release envelope AttRelEnvelope::run(overdB, m_overThresholdEnvelopeDB); // run attack/release envelope
overdB = envdB_ - DC_OFFSET; // subtract DC offset overdB = m_overThresholdEnvelopeDB - DC_OFFSET; // subtract DC offset
/* REGARDING THE DC OFFSET: In this case, since the offset is added before /* REGARDING THE DC OFFSET: In this case, since the offset is added before
* the attack/release processes, the envelope will never fall below the offset, * the attack/release processes, the envelope will never fall below the offset,
* thereby avoiding denormals. However, to prevent the offset from causing * thereby avoiding denormals. However, to prevent the offset from causing
@ -77,7 +78,7 @@ void audio::algo::chunkware::Compresssor::process(double &in1, double &in2, doub
* a minimum value of 0dB. * a minimum value of 0dB.
*/ */
// transfer function // transfer function
double gr = overdB * (ratio_ - 1.0); // gain reduction (dB) double gr = overdB * (m_ratio - 1.0); // gain reduction (dB)
gr = dB2lin(gr); // convert dB -> linear gr = dB2lin(gr); // convert dB -> linear
// output gain // output gain
in1 *= gr; // apply gain reduction to input in1 *= gr; // apply gain reduction to input

View File

@ -27,9 +27,9 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_H__
#define __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_H__ #define __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_H__
#include "header.h" #include <etk/types.h>
#include "AttRelEnvelope.h" #include <audio/algo/chunkware/AttRelEnvelope.h>
#include "Gain.h" #include <audio/algo/chunkware/Gain.h>
namespace audio { namespace audio {
namespace algo { namespace algo {
@ -42,10 +42,10 @@ namespace audio {
virtual void setThresh(double dB); virtual void setThresh(double dB);
virtual void setRatio(double dB); virtual void setRatio(double dB);
virtual double getThresh() const { virtual double getThresh() const {
return threshdB_; return m_threshdB;
} }
virtual double getRatio() const { virtual double getRatio() const {
return ratio_; return m_ratio;
} }
// runtime // runtime
// call before runtime (in resume()) // call before runtime (in resume())
@ -56,10 +56,10 @@ namespace audio {
void process(double &in1, double &in2, double keyLinked); void process(double &in1, double &in2, double keyLinked);
private: private:
// transfer function // transfer function
double threshdB_;//!< threshold (dB) double m_threshdB;//!< threshold (dB)
double ratio_; //!< ratio (compression: < 1 ; expansion: > 1) double m_ratio; //!< ratio (compression: < 1 ; expansion: > 1)
// runtime variables // runtime variables
double envdB_; //!< over-threshold envelope (dB) double m_overThresholdEnvelopeDB; //!< over-threshold envelope (dB)
}; };
} }
} }

View File

@ -24,27 +24,27 @@
*/ */
#include "CompressorRms.h" #include <audio/algo/chunkware/CompressorRms.h>
audio::algo::chunkware::CompresssorRms::CompresssorRms() : audio::algo::chunkware::CompresssorRms::CompresssorRms() :
ave_(5.0), m_averager(5.0),
aveOfSqrs_(DC_OFFSET) { m_averageSuares(DC_OFFSET) {
} }
void audio::algo::chunkware::CompresssorRms::setSampleRate(double sampleRate) { void audio::algo::chunkware::CompresssorRms::setSampleRate(double sampleRate) {
audio::algo::chunkware::Compresssor::setSampleRate(sampleRate); audio::algo::chunkware::Compresssor::setSampleRate(sampleRate);
ave_.setSampleRate(sampleRate); m_averager.setSampleRate(sampleRate);
} }
void audio::algo::chunkware::CompresssorRms::setWindow(double ms) { void audio::algo::chunkware::CompresssorRms::setWindow(double ms) {
ave_.setTc(ms); m_averager.setTc(ms);
} }
void audio::algo::chunkware::CompresssorRms::initRuntime() { void audio::algo::chunkware::CompresssorRms::initRuntime() {
audio::algo::chunkware::Compresssor::initRuntime(); audio::algo::chunkware::Compresssor::initRuntime();
aveOfSqrs_ = DC_OFFSET; m_averageSuares = DC_OFFSET;
} }
void audio::algo::chunkware::CompresssorRms::process(double &in1, double &in2) { void audio::algo::chunkware::CompresssorRms::process(double &in1, double &in2) {
@ -53,8 +53,8 @@ void audio::algo::chunkware::CompresssorRms::process(double &in1, double &in2) {
double inSq2 = in2 * in2; double inSq2 = in2 * in2;
double sum = inSq1 + inSq2; // power summing double sum = inSq1 + inSq2; // power summing
sum += DC_OFFSET; // DC offset, to prevent denormal sum += DC_OFFSET; // DC offset, to prevent denormal
ave_.run(sum, aveOfSqrs_); // average of squares m_averager.run(sum, m_averageSuares); // average of squares
double rms = sqrt(aveOfSqrs_); // rms (sort of ...) double rms = sqrt(m_averageSuares); // rms (sort of ...)
/* REGARDING THE RMS AVERAGER: Ok, so this isn't a REAL RMS /* REGARDING THE RMS AVERAGER: Ok, so this isn't a REAL RMS
* calculation. A true RMS is an FIR moving average. This * calculation. A true RMS is an FIR moving average. This
* approximation is a 1-pole IIR. Nonetheless, in practice, * approximation is a 1-pole IIR. Nonetheless, in practice,

View File

@ -27,7 +27,7 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_RMS_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_RMS_H__
#define __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_RMS_H__ #define __AUDIO_ALGO_CHUNKWARE_COMPRESSOR_RMS_H__
#include "Compressor.h" #include <audio/algo/chunkware/Compressor.h>
namespace audio { namespace audio {
namespace algo { namespace algo {
@ -40,13 +40,13 @@ namespace audio {
virtual void setSampleRate(double sampleRate); virtual void setSampleRate(double sampleRate);
// RMS window // RMS window
virtual void setWindow(double ms); virtual void setWindow(double ms);
virtual double getWindow() const { return ave_.getTc(); } virtual double getWindow() const { return m_averager.getTc(); }
// runtime process // runtime process
virtual void initRuntime(); // call before runtime (in resume()) virtual void initRuntime(); // call before runtime (in resume())
void process(double &in1, double &in2); // compressor runtime process void process(double &in1, double &in2); // compressor runtime process
protected: protected:
EnvelopeDetector ave_; //!< averager EnvelopeDetector m_averager; //!< averager
double aveOfSqrs_; //!< average of squares double m_averageSuares; //!< average of squares
}; };
} }
} }

View File

@ -24,28 +24,29 @@
*/ */
#include "EnvelopeDetector.h" #include <audio/algo/chunkware/debug.h>
#include <audio/algo/chunkware/EnvelopeDetector.h>
audio::algo::chunkware::EnvelopeDetector::EnvelopeDetector(double ms, double sampleRate) { audio::algo::chunkware::EnvelopeDetector::EnvelopeDetector(double ms, double sampleRate) {
assert(sampleRate > 0.0); AA_CHUNK_ASSERT(sampleRate > 0.0, "input function error");
assert(ms > 0.0); AA_CHUNK_ASSERT(ms > 0.0, "input function error");
sampleRate_ = sampleRate; m_sampleRate = sampleRate;
ms_ = ms; m_timeMs = ms;
setCoef(); setCoef();
} }
void audio::algo::chunkware::EnvelopeDetector::setTc(double ms) { void audio::algo::chunkware::EnvelopeDetector::setTc(double ms) {
assert(ms > 0.0); AA_CHUNK_ASSERT(ms > 0.0, "input function error");
ms_ = ms; m_timeMs = ms;
setCoef(); setCoef();
} }
void audio::algo::chunkware::EnvelopeDetector::setSampleRate(double sampleRate) { void audio::algo::chunkware::EnvelopeDetector::setSampleRate(double sampleRate) {
assert(sampleRate > 0.0); AA_CHUNK_ASSERT(sampleRate > 0.0, "input function error");
sampleRate_ = sampleRate; m_sampleRate = sampleRate;
setCoef(); setCoef();
} }
void audio::algo::chunkware::EnvelopeDetector::setCoef() { void audio::algo::chunkware::EnvelopeDetector::setCoef() {
coef_ = exp(-1000.0 / (ms_ * sampleRate_)); m_coefficient = exp(-1000.0 / (m_timeMs * m_sampleRate));
} }

View File

@ -27,7 +27,7 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_ENVELOPE_DETECTOR_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_ENVELOPE_DETECTOR_H__
#define __AUDIO_ALGO_CHUNKWARE_ENVELOPE_DETECTOR_H__ #define __AUDIO_ALGO_CHUNKWARE_ENVELOPE_DETECTOR_H__
#include "header.h" #include <etk/types.h>
namespace audio { namespace audio {
namespace algo { namespace algo {
@ -50,21 +50,21 @@ namespace audio {
// time constant // time constant
virtual void setTc(double ms); virtual void setTc(double ms);
virtual double getTc() const { virtual double getTc() const {
return ms_; return m_timeMs;
} }
// sample rate // sample rate
virtual void setSampleRate(double sampleRate); virtual void setSampleRate(double sampleRate);
virtual double getSampleRate() const { virtual double getSampleRate() const {
return sampleRate_; return m_sampleRate;
} }
// runtime function // runtime function
void run(double in, double &state) { void run(double in, double &state) {
state = in + coef_ * (state - in); state = in + m_coefficient * (state - in);
} }
protected: protected:
double sampleRate_; //!< sample rate double m_sampleRate; //!< sample rate
double ms_; //!< time constant in ms double m_timeMs; //!< time constant in ms
double coef_; //!< runtime coefficient double m_coefficient; //!< runtime coefficient
virtual void setCoef(); //!< coef calculation virtual void setCoef(); //!< coef calculation
}; };
} }

View File

@ -27,7 +27,7 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_GAIN_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_GAIN_H__
#define __AUDIO_ALGO_CHUNKWARE_GAIN_H__ #define __AUDIO_ALGO_CHUNKWARE_GAIN_H__
#include "header.h" #include <etk/types.h>
namespace audio { namespace audio {

View File

@ -24,23 +24,23 @@
*/ */
#include "Gate.h" #include <audio/algo/chunkware/Gate.h>
audio::algo::chunkware::Gate::Gate() : audio::algo::chunkware::Gate::Gate() :
AttRelEnvelope(1.0, 100.0), AttRelEnvelope(1.0, 100.0),
threshdB_(0.0), m_threshdB(0.0),
thresh_(1.0), m_threshold(1.0),
env_(DC_OFFSET) { m_overThresholdEnvelope(DC_OFFSET) {
} }
void audio::algo::chunkware::Gate::setThresh(double dB) { void audio::algo::chunkware::Gate::setThresh(double dB) {
threshdB_ = dB; m_threshdB = dB;
thresh_ = dB2lin(dB); m_threshold = dB2lin(dB);
} }
void audio::algo::chunkware::Gate::initRuntime() { void audio::algo::chunkware::Gate::initRuntime() {
env_ = DC_OFFSET; m_overThresholdEnvelope = DC_OFFSET;
} }
@ -59,11 +59,11 @@ void audio::algo::chunkware::Gate::process(double &in1, double &in2, double keyL
keyLinked = fabs(keyLinked); // rectify (just in case) keyLinked = fabs(keyLinked); // rectify (just in case)
// threshold // threshold
// key over threshold (0.0 or 1.0) // key over threshold (0.0 or 1.0)
double over = double(keyLinked > thresh_); double over = double(keyLinked > m_threshold);
// attack/release // attack/release
over += DC_OFFSET; // add DC offset to avoid denormal over += DC_OFFSET; // add DC offset to avoid denormal
AttRelEnvelope::run(over, env_); // run attack/release AttRelEnvelope::run(over, m_overThresholdEnvelope); // run attack/release
over = env_ - DC_OFFSET; // subtract DC offset over = m_overThresholdEnvelope - DC_OFFSET; // subtract DC offset
/* REGARDING THE DC OFFSET: In this case, since the offset is added before /* REGARDING THE DC OFFSET: In this case, since the offset is added before
* the attack/release processes, the envelope will never fall below the offset, * the attack/release processes, the envelope will never fall below the offset,
* thereby avoiding denormals. However, to prevent the offset from causing * thereby avoiding denormals. However, to prevent the offset from causing
@ -74,42 +74,3 @@ void audio::algo::chunkware::Gate::process(double &in1, double &in2, double keyL
in1 *= over; // apply gain reduction to input in1 *= over; // apply gain reduction to input
in2 *= over; in2 *= over;
} }
audio::algo::chunkware::GateRms::GateRms() :
ave_(5.0),
aveOfSqrs_(DC_OFFSET) {
}
void audio::algo::chunkware::GateRms::setSampleRate(double sampleRate) {
audio::algo::chunkware::Gate::setSampleRate(sampleRate);
ave_.setSampleRate(sampleRate);
}
void audio::algo::chunkware::GateRms::setWindow(double ms) {
ave_.setTc(ms);
}
void audio::algo::chunkware::GateRms::initRuntime() {
audio::algo::chunkware::Gate::initRuntime();
aveOfSqrs_ = DC_OFFSET;
}
void audio::algo::chunkware::GateRms::process(double &in1, double &in2) {
// create sidechain
double inSq1 = in1 * in1; // square input
double inSq2 = in2 * in2;
double sum = inSq1 + inSq2; // power summing
sum += DC_OFFSET; // DC offset, to prevent denormal
ave_.run(sum, aveOfSqrs_); // average of squares
double rms = sqrt(aveOfSqrs_); // rms (sort of ...)
/* REGARDING THE RMS AVERAGER: Ok, so this isn't a REAL RMS
* calculation. A true RMS is an FIR moving average. This
* approximation is a 1-pole IIR. Nonetheless, in practice,
* and in the interest of simplicity, this method will suffice,
* giving comparable results.
*/
Gate::process(in1, in2, rms); // rest of process
}

View File

@ -27,16 +27,13 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_GATE_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_GATE_H__
#define __AUDIO_ALGO_CHUNKWARE_GATE_H__ #define __AUDIO_ALGO_CHUNKWARE_GATE_H__
#include "header.h" #include <etk/types.h>
#include "AttRelEnvelope.h" #include <audio/algo/chunkware/AttRelEnvelope.h>
#include "Gain.h" #include <audio/algo/chunkware/Gain.h>
namespace audio { namespace audio {
namespace algo { namespace algo {
namespace chunkware { namespace chunkware {
//-------------------------------------------------------------
// simple gate
//-------------------------------------------------------------
class Gate : public AttRelEnvelope { class Gate : public AttRelEnvelope {
public: public:
Gate(); Gate();
@ -44,7 +41,7 @@ namespace audio {
// parameters // parameters
virtual void setThresh(double dB); virtual void setThresh(double dB);
virtual double getThresh() const { virtual double getThresh() const {
return threshdB_; return m_threshdB;
} }
// runtime // runtime
// call before runtime (in resume()) // call before runtime (in resume())
@ -55,33 +52,10 @@ namespace audio {
void process(double &in1, double &in2, double keyLinked); void process(double &in1, double &in2, double keyLinked);
private: private:
// transfer function // transfer function
double threshdB_; //!< threshold (dB) double m_threshdB; //!< threshold (dB)
double thresh_; //!< threshold (linear) double m_threshold; //!< threshold (linear)
// runtime variables // runtime variables
double env_; //!< over-threshold envelope (linear) double m_overThresholdEnvelope; //!< over-threshold envelope (linear)
};
//-------------------------------------------------------------
// simple gate with RMS detection
//-------------------------------------------------------------
class GateRms : public Gate {
public:
GateRms();
virtual ~GateRms() {}
// sample rate
virtual void setSampleRate(double sampleRate);
// RMS window
virtual void setWindow(double ms);
virtual double getWindow() const {
return ave_.getTc();
}
// runtime process
// call before runtime (in resume())
virtual void initRuntime();
// gate runtime process
void process(double &in1, double &in2);
private:
EnvelopeDetector ave_; //!< averager
double aveOfSqrs_; //!< average of squares
}; };
} }
} }

View File

@ -24,57 +24,58 @@
*/ */
#include "Limiter.h" #include <audio/algo/chunkware/Limiter.h>
#include <audio/algo/chunkware/debug.h>
audio::algo::chunkware::Limiter::Limiter() : audio::algo::chunkware::Limiter::Limiter() :
threshdB_(0.0), m_threshdB(0.0),
thresh_(1.0), m_threshold(1.0),
peakHold_(0), m_peakHold(0),
peakTimer_(0), m_peakTimer(0),
maxPeak_(1.0), m_maxPeak(1.0),
att_(1.0), m_attack(1.0),
rel_(10.0), m_release(10.0),
env_(1.0), m_overThresholdEnvelope(1.0),
mask_(BUFFER_SIZE-1), m_bufferMask(BUFFER_SIZE-1),
cur_(0) { m_cursor(0) {
setAttack(1.0); setAttack(1.0);
outBuffer_[ 0 ].resize(BUFFER_SIZE, 0.0); m_outputBuffer[ 0 ].resize(BUFFER_SIZE, 0.0);
outBuffer_[ 1 ].resize(BUFFER_SIZE, 0.0); m_outputBuffer[ 1 ].resize(BUFFER_SIZE, 0.0);
} }
void audio::algo::chunkware::Limiter::setThresh(double dB) { void audio::algo::chunkware::Limiter::setThresh(double dB) {
threshdB_ = dB; m_threshdB = dB;
thresh_ = dB2lin(dB); m_threshold = dB2lin(dB);
} }
void audio::algo::chunkware::Limiter::setAttack(double ms) { void audio::algo::chunkware::Limiter::setAttack(double ms) {
unsigned int samp = int(0.001 * ms * att_.getSampleRate()); unsigned int samp = int(0.001 * ms * m_attack.getSampleRate());
assert(samp < BUFFER_SIZE); AA_CHUNK_ASSERT(samp < BUFFER_SIZE, "input function error");
peakHold_ = samp; m_peakHold = samp;
att_.setTc(ms); m_attack.setTc(ms);
} }
void audio::algo::chunkware::Limiter::setRelease(double ms) { void audio::algo::chunkware::Limiter::setRelease(double ms) {
rel_.setTc(ms); m_release.setTc(ms);
} }
void audio::algo::chunkware::Limiter::setSampleRate(double sampleRate) { void audio::algo::chunkware::Limiter::setSampleRate(double sampleRate) {
att_.setSampleRate(sampleRate); m_attack.setSampleRate(sampleRate);
rel_.setSampleRate(sampleRate); m_release.setSampleRate(sampleRate);
} }
void audio::algo::chunkware::Limiter::initRuntime() { void audio::algo::chunkware::Limiter::initRuntime() {
peakTimer_ = 0; m_peakTimer = 0;
maxPeak_ = thresh_; m_maxPeak = m_threshold;
env_ = thresh_; m_overThresholdEnvelope = m_threshold;
cur_ = 0; m_cursor = 0;
outBuffer_[ 0 ].assign(BUFFER_SIZE, 0.0); m_outputBuffer[ 0 ].assign(BUFFER_SIZE, 0.0);
outBuffer_[ 1 ].assign(BUFFER_SIZE, 0.0); m_outputBuffer[ 1 ].assign(BUFFER_SIZE, 0.0);
} }
void audio::algo::chunkware::Limiter::FastEnvelope::setCoef() { void audio::algo::chunkware::Limiter::FastEnvelope::setCoef() {
// rises to 99% of in value over duration of time constant // rises to 99% of in value over duration of time constant
coef_ = pow(0.01, (1000.0 / (ms_ * sampleRate_))); m_coefficient = pow(0.01, (1000.0 / (m_timeMs * m_sampleRate)));
} }
@ -85,15 +86,15 @@ void audio::algo::chunkware::Limiter::process(double &in1, double &in2) {
double keyLink = std::max(rect1, rect2); // link channels with greater of 2 double keyLink = std::max(rect1, rect2); // link channels with greater of 2
// threshold // threshold
// we always want to feed the sidechain AT LEATS the threshold value // we always want to feed the sidechain AT LEATS the threshold value
if (keyLink < thresh_) if (keyLink < m_threshold)
keyLink = thresh_; keyLink = m_threshold;
// test: // test:
// a) whether peak timer has "expired" // a) whether peak timer has "expired"
// b) whether new peak is greater than previous max peak // b) whether new peak is greater than previous max peak
if ((++peakTimer_ >= peakHold_) || (keyLink > maxPeak_)) { if ((++m_peakTimer >= m_peakHold) || (keyLink > m_maxPeak)) {
// if either condition is met: // if either condition is met:
peakTimer_ = 0; // reset peak timer m_peakTimer = 0; // reset peak timer
maxPeak_ = keyLink; // assign new peak to max peak m_maxPeak = keyLink; // assign new peak to max peak
} }
/* REGARDING THE MAX PEAK: This method assumes that the only important /* REGARDING THE MAX PEAK: This method assumes that the only important
* sample in a look-ahead buffer would be the highest peak. As such, * sample in a look-ahead buffer would be the highest peak. As such,
@ -112,12 +113,12 @@ void audio::algo::chunkware::Limiter::process(double &in1, double &in2) {
* envelope follower. * envelope follower.
*/ */
// attack/release // attack/release
if (maxPeak_ > env_) { if (m_maxPeak > m_overThresholdEnvelope) {
// run attack phase // run attack phase
att_.run(maxPeak_, env_); m_attack.run(m_maxPeak, m_overThresholdEnvelope);
} else { } else {
// run release phase // run release phase
rel_.run(maxPeak_, env_); m_release.run(m_maxPeak, m_overThresholdEnvelope);
} }
/* REGARDING THE ATTACK: This limiter achieves "look-ahead" detection /* REGARDING THE ATTACK: This limiter achieves "look-ahead" detection
* by allowing the envelope follower to attack the max peak, which is * by allowing the envelope follower to attack the max peak, which is
@ -130,18 +131,18 @@ void audio::algo::chunkware::Limiter::process(double &in1, double &in2) {
* threshold (which is assumed to be around 1.0 linear). * threshold (which is assumed to be around 1.0 linear).
*/ */
// gain reduction // gain reduction
double gR = thresh_ / env_; double gR = m_threshold / m_overThresholdEnvelope;
// unload current buffer index // unload current buffer index
// (cur_ - delay) & mask_ gets sample from [delay] samples ago // (m_cursor - delay) & m_bufferMask gets sample from [delay] samples ago
// mask_ variable wraps index // m_bufferMask variable wraps index
unsigned int delayIndex = (cur_ - peakHold_) & mask_; unsigned int delayIndex = (m_cursor - m_peakHold) & m_bufferMask;
double delay1 = outBuffer_[ 0 ][ delayIndex ]; double delay1 = m_outputBuffer[ 0 ][ delayIndex ];
double delay2 = outBuffer_[ 1 ][ delayIndex ]; double delay2 = m_outputBuffer[ 1 ][ delayIndex ];
// load current buffer index and advance current index // load current buffer index and advance current index
// mask_ wraps cur_ index // m_bufferMask wraps m_cursor index
outBuffer_[ 0 ][ cur_ ] = in1; m_outputBuffer[ 0 ][ m_cursor ] = in1;
outBuffer_[ 1 ][ cur_ ] = in2; m_outputBuffer[ 1 ][ m_cursor ] = in2;
++cur_ &= mask_; ++m_cursor &= m_bufferMask;
// output gain // output gain
in1 = delay1 * gR; // apply gain reduction to input in1 = delay1 * gR; // apply gain reduction to input
in2 = delay2 * gR; in2 = delay2 * gR;
@ -157,11 +158,11 @@ void audio::algo::chunkware::Limiter::process(double &in1, double &in2) {
* *
* 2) Clip the output at the threshold, as such: * 2) Clip the output at the threshold, as such:
* *
* if (in1 > thresh_) in1 = thresh_; * if (in1 > m_threshold) in1 = m_threshold;
* else if (in1 < -thresh_) in1 = -thresh_; * else if (in1 < -m_threshold) in1 = -m_threshold;
* *
* if (in2 > thresh_) in2 = thresh_; * if (in2 > m_threshold) in2 = m_threshold;
* else if (in2 < -thresh_) in2 = -thresh_; * else if (in2 < -m_threshold) in2 = -m_threshold;
* *
* (... or replace with your favorite branchless clipper ...) * (... or replace with your favorite branchless clipper ...)
*/ */

View File

@ -27,9 +27,9 @@
#ifndef __AUDIO_ALGO_CHUNKWARE_LIMITER_H__ #ifndef __AUDIO_ALGO_CHUNKWARE_LIMITER_H__
#define __AUDIO_ALGO_CHUNKWARE_LIMITER_H__ #define __AUDIO_ALGO_CHUNKWARE_LIMITER_H__
#include "header.h" #include <etk/types.h>
#include "AttRelEnvelope.h" #include <audio/algo/chunkware/AttRelEnvelope.h>
#include "Gain.h" #include <audio/algo/chunkware/Gain.h>
#include <vector> #include <vector>
namespace audio { namespace audio {
@ -47,22 +47,22 @@ namespace audio {
virtual void setAttack(double ms); virtual void setAttack(double ms);
virtual void setRelease(double ms); virtual void setRelease(double ms);
virtual double getThresh() const { virtual double getThresh() const {
return threshdB_; return m_threshdB;
} }
virtual double getAttack() const { virtual double getAttack() const {
return att_.getTc(); return m_attack.getTc();
} }
virtual double getRelease() const { virtual double getRelease() const {
return rel_.getTc(); return m_release.getTc();
} }
// latency // latency
virtual const unsigned int getLatency() const { virtual const unsigned int getLatency() const {
return peakHold_; return m_peakHold;
} }
// sample rate dependencies // sample rate dependencies
virtual void setSampleRate(double sampleRate); virtual void setSampleRate(double sampleRate);
virtual double getSampleRate() { virtual double getSampleRate() {
return att_.getSampleRate(); return m_attack.getSampleRate();
} }
// runtime // runtime
// call before runtime (in resume()) // call before runtime (in resume())
@ -84,23 +84,23 @@ namespace audio {
}; };
private: private:
// transfer function // transfer function
double threshdB_; // threshold (dB) double m_threshdB; //!< threshold (dB)
double thresh_; // threshold (linear) double m_threshold; //!< threshold (linear)
// max peak // max peak
unsigned int peakHold_; // peak hold (samples) unsigned int m_peakHold; //!< peak hold (samples)
unsigned int peakTimer_; // peak hold timer unsigned int m_peakTimer; //!< peak hold timer
double maxPeak_; // max peak double m_maxPeak; //!< max peak
// attack/release envelope // attack/release envelope
FastEnvelope att_; // attack FastEnvelope m_attack; //!< attack
FastEnvelope rel_; // release FastEnvelope m_release; //!< release
double env_; // over-threshold envelope (linear) double m_overThresholdEnvelope; //!< over-threshold envelope (linear)
// buffer // buffer
// BUFFER_SIZE default can handle up to ~10ms at 96kHz // BUFFER_SIZE default can handle up to ~10ms at 96kHz
// change this if you require more // change this if you require more
static const int BUFFER_SIZE = 1024; //!< buffer size (always a power of 2!) static const int BUFFER_SIZE = 1024; //!< buffer size (always a power of 2!)
unsigned int mask_; //!< buffer mask unsigned int m_bufferMask; //!< buffer mask
unsigned int cur_; //!< cursor unsigned int m_cursor; //!< cursor
std::vector< double > outBuffer_[ 2 ]; //!< output buffer std::vector< double > m_outputBuffer[2]; //!< output buffer
}; };
} }
} }

View File

@ -56,7 +56,7 @@ namespace audio {
#define AA_CHUNK_ASSERT(cond,data) \ #define AA_CHUNK_ASSERT(cond,data) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
APPL_CRITICAL(data); \ AA_CHUNK_CRITICAL(data); \
assert(!#cond); \ assert(!#cond); \
} \ } \
} while (0) } while (0)

View File

@ -1,34 +0,0 @@
/**
* @author Bojan MARKOVIC
* @author Edouard DUPIN
* @copyright 2006, ChunkWare Music Software, OPEN-SOURCE
* @license BSD-1 (see license file)
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __SIMPLE_HEADER_H__
#define __SIMPLE_HEADER_H__
#include <algorithm>
#include <cassert>
#include <cmath>
#endif

View File

@ -16,6 +16,7 @@ def create(target):
'audio/algo/chunkware/EnvelopeDetector.cpp', 'audio/algo/chunkware/EnvelopeDetector.cpp',
'audio/algo/chunkware/AttRelEnvelope.cpp', 'audio/algo/chunkware/AttRelEnvelope.cpp',
'audio/algo/chunkware/Gate.cpp', 'audio/algo/chunkware/Gate.cpp',
'audio/algo/chunkware/GateRms.cpp',
'audio/algo/chunkware/Limiter.cpp' 'audio/algo/chunkware/Limiter.cpp'
]) ])
myModule.add_module_depend(['etk']) myModule.add_module_depend(['etk'])