diff --git a/audio/algo/chunkware/Compressor.cpp b/audio/algo/chunkware/Compressor.cpp new file mode 100644 index 0000000..ac3c80e --- /dev/null +++ b/audio/algo/chunkware/Compressor.cpp @@ -0,0 +1,140 @@ +/* + * Simple Compressor (source) + * + * File : SimpleComp.cpp + * Library : SimpleSource + * Version : 1.12 + * Implements : SimpleComp, SimpleCompRms + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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. + */ + + +#include "Compressor.h" + +//------------------------------------------------------------- +// simple compressor +//------------------------------------------------------------- +audio::algo::chunkware::Compresssor::Compresssor() : + AttRelEnvelope(10.0, 100.0), + threshdB_(0.0), + ratio_(1.0), + envdB_(DC_OFFSET) { + +} + +//------------------------------------------------------------- +void audio::algo::chunkware::Compresssor::setThresh(double dB) { + threshdB_ = dB; +} + +//------------------------------------------------------------- +void audio::algo::chunkware::Compresssor::setRatio(double ratio) { + assert(ratio > 0.0); + ratio_ = ratio; +} + +//------------------------------------------------------------- +void audio::algo::chunkware::Compresssor::initRuntime() { + envdB_ = DC_OFFSET; +} + +void audio::algo::chunkware::Compresssor::process(double &in1, double &in2) { + // create sidechain + double rect1 = fabs(in1); // rectify input + double rect2 = fabs(in2); + /* if desired, one could use another EnvelopeDetector to smooth + * the rectified signal. + */ + double link = std::max(rect1, rect2); // link channels with greater of 2 + process(in1, in2, link); // rest of process +} + +void audio::algo::chunkware::Compresssor::process(double &in1, double &in2, double keyLinked) { + keyLinked = fabs(keyLinked); // rectify (just in case) + // convert key to dB + keyLinked += DC_OFFSET; // add DC offset to avoid log(0) + double keydB = lin2dB(keyLinked); // convert linear -> dB + // threshold + double overdB = keydB - threshdB_; // delta over threshold + if (overdB < 0.0) + overdB = 0.0; + // attack/release + overdB += DC_OFFSET; // add DC offset to avoid denormal + AttRelEnvelope::run(overdB, envdB_); // run attack/release envelope + overdB = envdB_ - DC_OFFSET; // subtract DC offset + /* 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, + * thereby avoiding denormals. However, to prevent the offset from causing + * constant gain reduction, we must subtract it from the envelope, yielding + * a minimum value of 0dB. + */ + // transfer function + double gr = overdB * (ratio_ - 1.0); // gain reduction (dB) + gr = dB2lin(gr); // convert dB -> linear + // output gain + in1 *= gr; // apply gain reduction to input + in2 *= gr; +} + +//------------------------------------------------------------- +// simple compressor with RMS detection +//------------------------------------------------------------- +audio::algo::chunkware::CompresssorRms::CompresssorRms() : + ave_(5.0), + aveOfSqrs_(DC_OFFSET) { + +} + +//------------------------------------------------------------- +void audio::algo::chunkware::CompresssorRms::setSampleRate(double sampleRate) { + audio::algo::chunkware::Compresssor::setSampleRate(sampleRate); + ave_.setSampleRate(sampleRate); +} + +//------------------------------------------------------------- +void audio::algo::chunkware::CompresssorRms::setWindow(double ms) { + ave_.setTc(ms); +} + +//------------------------------------------------------------- +void audio::algo::chunkware::CompresssorRms::initRuntime() { + audio::algo::chunkware::Compresssor::initRuntime(); + aveOfSqrs_ = DC_OFFSET; +} + +void audio::algo::chunkware::CompresssorRms::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. + */ + // rest of process + Compresssor::process(in1, in2, rms); +} diff --git a/audio/algo/chunkware/Compressor.h b/audio/algo/chunkware/Compressor.h new file mode 100644 index 0000000..0de5c7a --- /dev/null +++ b/audio/algo/chunkware/Compressor.h @@ -0,0 +1,94 @@ +/* + * Simple Compressor (header) + * + * File : SimpleComp.h + * Library : SimpleSource + * Version : 1.12 + * Class : SimpleComp, SimpleCompRms + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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_COMP_H__ +#define __SIMPLE_COMP_H__ + +#include "header.h" +#include "Envelope.h" +#include "Gain.h" + +namespace audio { + namespace algo { + namespace chunkware { + //------------------------------------------------------------- + // compressor + //------------------------------------------------------------- + class Compresssor : public AttRelEnvelope { + public: + Compresssor(); + virtual ~Compresssor() {} + // parameters + virtual void setThresh(double dB); + virtual void setRatio(double dB); + virtual double getThresh() const { + return threshdB_; + } + virtual double getRatio() const { + return ratio_; + } + // runtime + // call before runtime (in resume()) + virtual void initRuntime(); + // compressor runtime process + void process(double &in1, double &in2); + // with stereo-linked key in + void process(double &in1, double &in2, double keyLinked); + private: + // transfer function + double threshdB_;//!< threshold (dB) + double ratio_; //!< ratio (compression: < 1 ; expansion: > 1) + // runtime variables + double envdB_; //!< over-threshold envelope (dB) + }; + //------------------------------------------------------------- + // compressor with RMS detection + //------------------------------------------------------------- + class CompresssorRms : public Compresssor { + public: + CompresssorRms(); + virtual ~CompresssorRms() {} + // sample rate + virtual void setSampleRate(double sampleRate); + // RMS window + virtual void setWindow(double ms); + virtual double getWindow() const { return ave_.getTc(); } + // runtime process + virtual void initRuntime(); // call before runtime (in resume()) + void process(double &in1, double &in2); // compressor runtime process + protected: + EnvelopeDetector ave_; //!< averager + double aveOfSqrs_; //!< average of squares + }; + } + } +} + +#endif diff --git a/audio/algo/chunkware/Envelope.cpp b/audio/algo/chunkware/Envelope.cpp new file mode 100644 index 0000000..7f36271 --- /dev/null +++ b/audio/algo/chunkware/Envelope.cpp @@ -0,0 +1,81 @@ +/* + * Simple Envelope Detectors (source) + * + * File : SimpleEnvelope.cpp + * Library : SimpleSource + * Version : 1.12 + * Implements : EnvelopeDetector, AttRelEnvelope + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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. + */ + + +#include "Envelope.h" + +audio::algo::chunkware::EnvelopeDetector::EnvelopeDetector(double ms, double sampleRate) { + assert(sampleRate > 0.0); + assert(ms > 0.0); + sampleRate_ = sampleRate; + ms_ = ms; + setCoef(); +} + +void audio::algo::chunkware::EnvelopeDetector::setTc(double ms) { + assert(ms > 0.0); + ms_ = ms; + setCoef(); +} + +void audio::algo::chunkware::EnvelopeDetector::setSampleRate(double sampleRate) { + assert(sampleRate > 0.0); + sampleRate_ = sampleRate; + setCoef(); +} + +void audio::algo::chunkware::EnvelopeDetector::setCoef() { + coef_ = exp(-1000.0 / (ms_ * sampleRate_)); +} + + + + +audio::algo::chunkware::AttRelEnvelope::AttRelEnvelope(double att_ms, double rel_ms, double sampleRate) : + att_(att_ms, sampleRate), + rel_(rel_ms, sampleRate) { + +} + +//------------------------------------------------------------- +void audio::algo::chunkware::AttRelEnvelope::setAttack(double ms) { + att_.setTc(ms); +} + +//------------------------------------------------------------- +void audio::algo::chunkware::AttRelEnvelope::setRelease(double ms) { + rel_.setTc(ms); +} + +//------------------------------------------------------------- +void audio::algo::chunkware::AttRelEnvelope::setSampleRate(double sampleRate) { + att_.setSampleRate(sampleRate); + rel_.setSampleRate(sampleRate); +} + diff --git a/audio/algo/chunkware/Envelope.h b/audio/algo/chunkware/Envelope.h new file mode 100644 index 0000000..8f45e45 --- /dev/null +++ b/audio/algo/chunkware/Envelope.h @@ -0,0 +1,121 @@ +/* + * Simple Envelope Detectors (header) + * + * File : SimpleEnvelope.h + * Library : SimpleSource + * Version : 1.12 + * Class : EnvelopeDetector, AttRelEnvelope + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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_ENVELOPE_H__ +#define __SIMPLE_ENVELOPE_H__ + +#include "header.h" + +namespace audio { + namespace algo { + namespace chunkware { + //------------------------------------------------------------- + // DC offset (to prevent denormal) + //------------------------------------------------------------- + // USE: + // 1. init envelope state to DC_OFFSET before processing + // 2. add to input before envelope runtime function + static const double DC_OFFSET = 1.0E-25; + //------------------------------------------------------------- + // envelope detector + //------------------------------------------------------------- + class EnvelopeDetector { + public: + EnvelopeDetector(double ms = 1.0, + double sampleRate = 44100.0); + virtual ~EnvelopeDetector() {} + // time constant + virtual void setTc(double ms); + virtual double getTc() const { + return ms_; + } + // sample rate + virtual void setSampleRate(double sampleRate); + virtual double getSampleRate() const { + return sampleRate_; + } + // runtime function + void run(double in, double &state) { + state = in + coef_ * (state - in); + } + protected: + double sampleRate_; //!< sample rate + double ms_; //!< time constant in ms + double coef_; //!< runtime coefficient + virtual void setCoef(); //!< coef calculation + }; + //------------------------------------------------------------- + // attack/release envelope + //------------------------------------------------------------- + class AttRelEnvelope { + public: + AttRelEnvelope(double att_ms = 10.0, + double rel_ms = 100.0, + double sampleRate = 44100.0); + virtual ~AttRelEnvelope() {} + // attack time constant + virtual void setAttack(double ms); + virtual double getAttack() const { + return att_.getTc(); + } + // release time constant + virtual void setRelease(double ms); + virtual double getRelease() const { + return rel_.getTc(); + } + // sample rate dependencies + virtual void setSampleRate(double sampleRate); + virtual double getSampleRate() const { + return att_.getSampleRate(); + } + // runtime function + void run(double in, double &state) { + /* assumes that: + * positive delta = attack + * negative delta = release + * good for linear & log values + */ + if (in > state) { + // attack + att_.run(in, state); + } else { + // release + rel_.run(in, state); + } + } + private: + EnvelopeDetector att_; + EnvelopeDetector rel_; + }; + } + } +} + +#endif diff --git a/simpleSource/SimpleGain.h b/audio/algo/chunkware/Gain.h old mode 100755 new mode 100644 similarity index 64% rename from simpleSource/SimpleGain.h rename to audio/algo/chunkware/Gain.h index 1a695cd..b96e070 --- a/simpleSource/SimpleGain.h +++ b/audio/algo/chunkware/Gain.h @@ -1,56 +1,57 @@ -/* - * Gain Functions (header) - * - * File : SimpleGain.h - * Library : SimpleSource - * Version : 1.12 - * Class : - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_GAIN_H__ -#define __SIMPLE_GAIN_H__ - -#include "SimpleHeader.h" // common header - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // gain functions - //------------------------------------------------------------- - - // linear -> dB conversion - static INLINE double lin2dB( double lin ) { - static const double LOG_2_DB = 8.6858896380650365530225783783321; // 20 / ln( 10 ) - return log( lin ) * LOG_2_DB; - } - - // dB -> linear conversion - static INLINE double dB2lin( double dB ) { - static const double DB_2_LOG = 0.11512925464970228420089957273422; // ln( 10 ) / 20 - return exp( dB * DB_2_LOG ); - } - -} // end namespace chunkware_simple - -#endif // end __SIMPLE_GAIN_H__ +/* + * Gain Functions (header) + * + * File : SimpleGain.h + * Library : SimpleSource + * Version : 1.12 + * Class : + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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_GAIN_H__ +#define __SIMPLE_GAIN_H__ + +#include "header.h" + + +namespace audio { + namespace algo { + namespace chunkware { + //------------------------------------------------------------- + // gain functions + //------------------------------------------------------------- + // linear -> dB conversion + static inline double lin2dB(double lin) { + static const double LOG_2_DB = 8.6858896380650365530225783783321; // 20 / ln(10) + return log(lin) * LOG_2_DB; + } + // dB -> linear conversion + static inline double dB2lin(double dB) { + static const double DB_2_LOG = 0.11512925464970228420089957273422; // ln(10) / 20 + return exp(dB * DB_2_LOG); + } + } + } +} + +#endif diff --git a/audio/algo/chunkware/Gate.cpp b/audio/algo/chunkware/Gate.cpp new file mode 100644 index 0000000..76fae13 --- /dev/null +++ b/audio/algo/chunkware/Gate.cpp @@ -0,0 +1,119 @@ +/* + * Simple Gate (source) + * + * File : SimpleGate.cpp + * Library : SimpleSource + * Version : 1.12 + * Implements : SimpleGate, SimpleGateRms + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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. + */ + + +#include "Gate.h" + +audio::algo::chunkware::Gate::Gate() : + AttRelEnvelope(1.0, 100.0), + threshdB_(0.0), + thresh_(1.0), + env_(DC_OFFSET) { + +} + +void audio::algo::chunkware::Gate::setThresh(double dB) { + threshdB_ = dB; + thresh_ = dB2lin(dB); +} + +void audio::algo::chunkware::Gate::initRuntime() { + env_ = DC_OFFSET; +} + + +void audio::algo::chunkware::Gate::process(double &in1, double &in2) { + // create sidechain + double rect1 = fabs(in1); // rectify input + double rect2 = fabs(in2); + /* if desired, one could use another EnvelopeDetector to smooth + * the rectified signal. + */ + double link = std::max(rect1, rect2); // link channels with greater of 2 + process(in1, in2, link); // rest of process +} + +void audio::algo::chunkware::Gate::process(double &in1, double &in2, double keyLinked) { + keyLinked = fabs(keyLinked); // rectify (just in case) + // threshold + // key over threshold (0.0 or 1.0) + double over = double(keyLinked > thresh_); + // attack/release + over += DC_OFFSET; // add DC offset to avoid denormal + AttRelEnvelope::run(over, env_); // run attack/release + over = env_ - DC_OFFSET; // subtract DC offset + /* 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, + * thereby avoiding denormals. However, to prevent the offset from causing + * constant gain reduction, we must subtract it from the envelope, yielding + * a minimum value of 0dB. + */ + // output gain + in1 *= over; // apply gain reduction to input + 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 +} diff --git a/audio/algo/chunkware/Gate.h b/audio/algo/chunkware/Gate.h new file mode 100644 index 0000000..58807f2 --- /dev/null +++ b/audio/algo/chunkware/Gate.h @@ -0,0 +1,94 @@ +/* + * Simple Gate (header) + * + * File : SimpleGate.h + * Library : SimpleSource + * Version : 1.12 + * Class : SimpleGate, SimpleGateRms + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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_GATE_H__ +#define __SIMPLE_GATE_H__ + +#include "header.h" +#include "Envelope.h" +#include "Gain.h" + +namespace audio { + namespace algo { + namespace chunkware { + //------------------------------------------------------------- + // simple gate + //------------------------------------------------------------- + class Gate : public AttRelEnvelope { + public: + Gate(); + virtual ~Gate() {} + // parameters + virtual void setThresh(double dB); + virtual double getThresh() const { + return threshdB_; + } + // runtime + // call before runtime (in resume()) + virtual void initRuntime(); + // gate runtime process + void process(double &in1, double &in2); + // with stereo-linked key in + void process(double &in1, double &in2, double keyLinked); + private: + // transfer function + double threshdB_; //!< threshold (dB) + double thresh_; //!< threshold (linear) + // runtime variables + double env_; //!< 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 + }; + } + } +} + +#endif diff --git a/audio/algo/chunkware/Limiter.cpp b/audio/algo/chunkware/Limiter.cpp new file mode 100644 index 0000000..31c1c96 --- /dev/null +++ b/audio/algo/chunkware/Limiter.cpp @@ -0,0 +1,172 @@ +/* + * Simple Limiter (source) + * + * File : SimpleLimit.cpp + * Library : SimpleSource + * Version : 1.12 + * Implements : SimpleLimit + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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. + */ + + +#include "Limiter.h" + +audio::algo::chunkware::Limiter::Limiter() : + threshdB_(0.0), + thresh_(1.0), + peakHold_(0), + peakTimer_(0), + maxPeak_(1.0), + att_(1.0), + rel_(10.0), + env_(1.0), + mask_(BUFFER_SIZE-1), + cur_(0) { + setAttack(1.0); + outBuffer_[ 0 ].resize(BUFFER_SIZE, 0.0); + outBuffer_[ 1 ].resize(BUFFER_SIZE, 0.0); +} + +void audio::algo::chunkware::Limiter::setThresh(double dB) { + threshdB_ = dB; + thresh_ = dB2lin(dB); +} + +void audio::algo::chunkware::Limiter::setAttack(double ms) { + unsigned int samp = int(0.001 * ms * att_.getSampleRate()); + assert(samp < BUFFER_SIZE); + peakHold_ = samp; + att_.setTc(ms); +} + +void audio::algo::chunkware::Limiter::setRelease(double ms) { + rel_.setTc(ms); +} + +void audio::algo::chunkware::Limiter::setSampleRate(double sampleRate) { + att_.setSampleRate(sampleRate); + rel_.setSampleRate(sampleRate); +} + +void audio::algo::chunkware::Limiter::initRuntime() { + peakTimer_ = 0; + maxPeak_ = thresh_; + env_ = thresh_; + cur_ = 0; + outBuffer_[ 0 ].assign(BUFFER_SIZE, 0.0); + outBuffer_[ 1 ].assign(BUFFER_SIZE, 0.0); +} + +void audio::algo::chunkware::Limiter::FastEnvelope::setCoef() { + // rises to 99% of in value over duration of time constant + coef_ = pow(0.01, (1000.0 / (ms_ * sampleRate_))); +} + + +void audio::algo::chunkware::Limiter::process(double &in1, double &in2) { + // create sidechain + double rect1 = fabs(in1); // rectify input + double rect2 = fabs(in2); + double keyLink = std::max(rect1, rect2); // link channels with greater of 2 + // threshold + // we always want to feed the sidechain AT LEATS the threshold value + if (keyLink < thresh_) + keyLink = thresh_; + // test: + // a) whether peak timer has "expired" + // b) whether new peak is greater than previous max peak + if ((++peakTimer_ >= peakHold_) || (keyLink > maxPeak_)) { + // if either condition is met: + peakTimer_ = 0; // reset peak timer + maxPeak_ = keyLink; // assign new peak to max peak + } + /* REGARDING THE MAX PEAK: This method assumes that the only important + * sample in a look-ahead buffer would be the highest peak. As such, + * instead of storing all samples in a look-ahead buffer, it only stores + * the max peak, and compares all incoming samples to that one. + * The max peak has a hold time equal to what the look-ahead buffer + * would have been, which is tracked by a timer (counter). When this + * timer expires, the sample would have exited from the buffer. Therefore, + * a new sample must be assigned to the max peak. We assume that the next + * highest sample in our theoretical buffer is the current input sample. + * In reality, we know this is probably NOT the case, and that there has + * been another sample, slightly lower than the one before it, that has + * passed the input. If we do not account for this possibility, our gain + * reduction could be insufficient, resulting in an "over" at the output. + * To remedy this, we simply apply a suitably long release stage in the + * envelope follower. + */ + // attack/release + if (maxPeak_ > env_) { + // run attack phase + att_.run(maxPeak_, env_); + } else { + // run release phase + rel_.run(maxPeak_, env_); + } + /* REGARDING THE ATTACK: This limiter achieves "look-ahead" detection + * by allowing the envelope follower to attack the max peak, which is + * held for the duration of the attack phase -- unless a new, higher + * peak is detected. The output signal is buffered so that the gain + * reduction is applied in advance of the "offending" sample. + */ + /* NOTE: a DC offset is not necessary for the envelope follower, + * as neither the max peak nor envelope should fall below the + * threshold (which is assumed to be around 1.0 linear). + */ + // gain reduction + double gR = thresh_ / env_; + // unload current buffer index + // (cur_ - delay) & mask_ gets sample from [delay] samples ago + // mask_ variable wraps index + unsigned int delayIndex = (cur_ - peakHold_) & mask_; + double delay1 = outBuffer_[ 0 ][ delayIndex ]; + double delay2 = outBuffer_[ 1 ][ delayIndex ]; + // load current buffer index and advance current index + // mask_ wraps cur_ index + outBuffer_[ 0 ][ cur_ ] = in1; + outBuffer_[ 1 ][ cur_ ] = in2; + ++cur_ &= mask_; + // output gain + in1 = delay1 * gR; // apply gain reduction to input + in2 = delay2 * gR; + /* REGARDING THE GAIN REDUCTION: Due to the logarithmic nature + * of the attack phase, the sidechain will never achieve "full" + * attack. (Actually, it is only guaranteed to achieve 99% of + * the input value over the given time constant.) As such, the + * limiter cannot achieve "brick-wall" limiting. There are 2 + * workarounds: + * + * 1) Set the threshold slightly lower than the desired threshold. + * i.e. 0.0dB -> -0.1dB or even -0.5dB + * + * 2) Clip the output at the threshold, as such: + * + * if (in1 > thresh_) in1 = thresh_; + * else if (in1 < -thresh_) in1 = -thresh_; + * + * if (in2 > thresh_) in2 = thresh_; + * else if (in2 < -thresh_) in2 = -thresh_; + * + * (... or replace with your favorite branchless clipper ...) + */ +} \ No newline at end of file diff --git a/audio/algo/chunkware/Limiter.h b/audio/algo/chunkware/Limiter.h new file mode 100644 index 0000000..1f71c89 --- /dev/null +++ b/audio/algo/chunkware/Limiter.h @@ -0,0 +1,112 @@ +/* + * Simple Limiter (header) + * + * File : SimpleLimit.h + * Library : SimpleSource + * Version : 1.12 + * Class : SimpleLimit + * + * © 2006, ChunkWare Music Software, OPEN-SOURCE + * + * 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_LIMIT_H__ +#define __SIMPLE_LIMIT_H__ + +#include "header.h" +#include "Envelope.h" +#include "Gain.h" +#include + +namespace audio { + namespace algo { + namespace chunkware { + //------------------------------------------------------------- + // simple limiter + //------------------------------------------------------------- + class Limiter { + public: + Limiter(); + virtual ~Limiter() {} + // parameters + virtual void setThresh(double dB); + virtual void setAttack(double ms); + virtual void setRelease(double ms); + virtual double getThresh() const { + return threshdB_; + } + virtual double getAttack() const { + return att_.getTc(); + } + virtual double getRelease() const { + return rel_.getTc(); + } + // latency + virtual const unsigned int getLatency() const { + return peakHold_; + } + // sample rate dependencies + virtual void setSampleRate(double sampleRate); + virtual double getSampleRate() { + return att_.getSampleRate(); + } + // runtime + // call before runtime (in resume()) + virtual void initRuntime(); + // limiter runtime process + void process(double &in1, double &in2); + protected: + // class for faster attack/release + class FastEnvelope : public EnvelopeDetector { + public: + FastEnvelope(double ms = 1.0, double sampleRate = 44100.0) + : EnvelopeDetector(ms, sampleRate) + {} + virtual ~FastEnvelope() {} + protected: + // override setCoef() - coefficient calculation + virtual void setCoef(); + }; + private: + // transfer function + double threshdB_; // threshold (dB) + double thresh_; // threshold (linear) + // max peak + unsigned int peakHold_; // peak hold (samples) + unsigned int peakTimer_; // peak hold timer + double maxPeak_; // max peak + // attack/release envelope + FastEnvelope att_; // attack + FastEnvelope rel_; // release + double env_; // over-threshold envelope (linear) + // buffer + // BUFFER_SIZE default can handle up to ~10ms at 96kHz + // change this if you require more + static const int BUFFER_SIZE = 1024; //!< buffer size (always a power of 2!) + unsigned int mask_; //!< buffer mask + unsigned int cur_; //!< cursor + std::vector< double > outBuffer_[ 2 ]; //!< output buffer + }; + } + } +} + +#endif diff --git a/audio/algo/chunkware/debug.cpp b/audio/algo/chunkware/debug.cpp new file mode 100644 index 0000000..d96ac27 --- /dev/null +++ b/audio/algo/chunkware/debug.cpp @@ -0,0 +1,14 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include "debug.h" + + +int32_t audio::algo::aec::getLogId() { + static int32_t g_val = etk::log::registerInstance("audio-algo-aec"); + return g_val; +} + diff --git a/audio/algo/chunkware/debug.h b/audio/algo/chunkware/debug.h new file mode 100644 index 0000000..e6284e4 --- /dev/null +++ b/audio/algo/chunkware/debug.h @@ -0,0 +1,45 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#ifndef __APPL_DEBUG_H__ +#define __APPL_DEBUG_H__ + +#include + +namespace audio { + namespace algo { + namespace aec { + int32_t getLogId(); + } + } +} + +#define AA_AEC_BASE(info,data) TK_LOG_BASE(audio::algo::aec::getLogId(),info,data) + +#define AA_AEC_CRITICAL(data) AA_AEC_BASE(1, data) +#define AA_AEC_ERROR(data) AA_AEC_BASE(2, data) +#define AA_AEC_WARNING(data) AA_AEC_BASE(3, data) +#ifdef DEBUG + #define AA_AEC_INFO(data) AA_AEC_BASE(4, data) + #define AA_AEC_DEBUG(data) AA_AEC_BASE(5, data) + #define AA_AEC_VERBOSE(data) AA_AEC_BASE(6, data) + #define AA_AEC_TODO(data) AA_AEC_BASE(4, "TODO : " << data) +#else + #define AA_AEC_INFO(data) do { } while(false) + #define AA_AEC_DEBUG(data) do { } while(false) + #define AA_AEC_VERBOSE(data) do { } while(false) + #define AA_AEC_TODO(data) do { } while(false) +#endif + +#define AA_AEC_ASSERT(cond,data) \ + do { \ + if (!(cond)) { \ + APPL_CRITICAL(data); \ + assert(!#cond); \ + } \ + } while (0) + +#endif diff --git a/simpleSource/SimpleHeader.h b/audio/algo/chunkware/header.h old mode 100755 new mode 100644 similarity index 79% rename from simpleSource/SimpleHeader.h rename to audio/algo/chunkware/header.h index 6103a08..2eb7ed1 --- a/simpleSource/SimpleHeader.h +++ b/audio/algo/chunkware/header.h @@ -30,16 +30,16 @@ #ifndef __SIMPLE_HEADER_H__ #define __SIMPLE_HEADER_H__ -#if _MSC_VER > 1000 // MS Visual Studio -#define INLINE __forceinline // forces inline -#define NOMINMAX // for standard library min(), max() -#define _USE_MATH_DEFINES // for math constants -#else // other IDE's -#define INLINE inline +#if _MSC_VER > 1000 + // MS Visual Studio + // for standard library min(), max() + #define NOMINMAX + // for math constants + #define _USE_MATH_DEFINES #endif -#include // for min(), max() -#include // for assert() +#include +#include #include -#endif // end __SIMPLE_HEADER_H__ +#endif diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..5c740be --- /dev/null +++ b/license.txt @@ -0,0 +1,19 @@ +Copyright audio-algo-chunkware Edouard DUPIN + +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. diff --git a/lutin_audio_algo_chunkware.py b/lutin_audio_algo_chunkware.py new file mode 100644 index 0000000..c730f94 --- /dev/null +++ b/lutin_audio_algo_chunkware.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +import lutinModule as module +import lutinTools as tools +import lutinDebug as debug + +def get_desc(): + return "audio_algo_aec : AEC basic algo" + + +def create(target): + myModule = module.Module(__file__, 'audio_algo_chunkware', 'LIBRARY') + myModule.add_src_file([ + 'audio/algo/chunkware/debug.cpp', + 'audio/algo/chunkware/Compressor.cpp', + 'audio/algo/chunkware/debug.cpp', + 'audio/algo/chunkware/Envelope.cpp', + 'audio/algo/chunkware/Gate.cpp', + 'audio/algo/chunkware/Limiter.cpp' + ]) + myModule.add_module_depend(['etk']) + myModule.add_export_path(tools.get_current_path(__file__)) + # return module + return myModule + + + + + + + + + diff --git a/simpleSource/SimpleComp.cpp b/simpleSource/SimpleComp.cpp deleted file mode 100755 index d875c8e..0000000 --- a/simpleSource/SimpleComp.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Simple Compressor (source) - * - * File : SimpleComp.cpp - * Library : SimpleSource - * Version : 1.12 - * Implements : SimpleComp, SimpleCompRms - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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. - */ - - -#include "SimpleComp.h" - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // simple compressor - //------------------------------------------------------------- - SimpleComp::SimpleComp() - : AttRelEnvelope( 10.0, 100.0 ) - , threshdB_( 0.0 ) - , ratio_( 1.0 ) - , envdB_( DC_OFFSET ) - { - } - - //------------------------------------------------------------- - void SimpleComp::setThresh( double dB ) - { - threshdB_ = dB; - } - - //------------------------------------------------------------- - void SimpleComp::setRatio( double ratio ) - { - assert( ratio > 0.0 ); - ratio_ = ratio; - } - - //------------------------------------------------------------- - void SimpleComp::initRuntime( void ) - { - envdB_ = DC_OFFSET; - } - - //------------------------------------------------------------- - // simple compressor with RMS detection - //------------------------------------------------------------- - SimpleCompRms::SimpleCompRms() - : ave_( 5.0 ) - , aveOfSqrs_( DC_OFFSET ) - { - } - - //------------------------------------------------------------- - void SimpleCompRms::setSampleRate( double sampleRate ) - { - SimpleComp::setSampleRate( sampleRate ); - ave_.setSampleRate( sampleRate ); - } - - //------------------------------------------------------------- - void SimpleCompRms::setWindow( double ms ) - { - ave_.setTc( ms ); - } - - //------------------------------------------------------------- - void SimpleCompRms::initRuntime( void ) - { - SimpleComp::initRuntime(); - aveOfSqrs_ = DC_OFFSET; - } - -} // end namespace chunkware_simple diff --git a/simpleSource/SimpleComp.h b/simpleSource/SimpleComp.h deleted file mode 100755 index 28dea64..0000000 --- a/simpleSource/SimpleComp.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Simple Compressor (header) - * - * File : SimpleComp.h - * Library : SimpleSource - * Version : 1.12 - * Class : SimpleComp, SimpleCompRms - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_COMP_H__ -#define __SIMPLE_COMP_H__ - -#include "SimpleHeader.h" // common header -#include "SimpleEnvelope.h" // for base class -#include "SimpleGain.h" // for gain functions - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // simple compressor - //------------------------------------------------------------- - class SimpleComp : public AttRelEnvelope - { - public: - SimpleComp(); - virtual ~SimpleComp() {} - - // parameters - virtual void setThresh( double dB ); - virtual void setRatio( double dB ); - - virtual double getThresh( void ) const { return threshdB_; } - virtual double getRatio( void ) const { return ratio_; } - - // runtime - virtual void initRuntime( void ); // call before runtime (in resume()) - void process( double &in1, double &in2 ); // compressor runtime process - void process( double &in1, double &in2, double keyLinked ); // with stereo-linked key in - - private: - - // transfer function - double threshdB_; // threshold (dB) - double ratio_; // ratio (compression: < 1 ; expansion: > 1) - - // runtime variables - double envdB_; // over-threshold envelope (dB) - - }; // end SimpleComp class - - //------------------------------------------------------------- - // simple compressor with RMS detection - //------------------------------------------------------------- - class SimpleCompRms : public SimpleComp - { - public: - SimpleCompRms(); - virtual ~SimpleCompRms() {} - - // sample rate - virtual void setSampleRate( double sampleRate ); - - // RMS window - virtual void setWindow( double ms ); - virtual double getWindow( void ) const { return ave_.getTc(); } - - // runtime process - virtual void initRuntime( void ); // call before runtime (in resume()) - void process( double &in1, double &in2 ); // compressor runtime process - - private: - - EnvelopeDetector ave_; // averager - double aveOfSqrs_; // average of squares - - }; // end SimpleCompRms class - -} // end namespace chunkware_simple - -// include inlined process function -#include "SimpleCompProcess.inl" - -#endif // end __SIMPLE_COMP_H__ diff --git a/simpleSource/SimpleCompProcess.inl b/simpleSource/SimpleCompProcess.inl deleted file mode 100755 index 192a499..0000000 --- a/simpleSource/SimpleCompProcess.inl +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Simple Compressor (runtime function) - * - * File : SimpleCompProcess.inl - * Library : SimpleSource - * Version : 1.12 - * Implements : void SimpleComp::process( double &in1, double &in2 ) - * void SimpleComp::process( double &in1, double &in2, double keyLinked ) - * void SimpleCompRms::process( double &in1, double &in2 ) - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_COMP_PROCESS_INL__ -#define __SIMPLE_COMP_PROCESS_INL__ - -namespace chunkware_simple -{ - //------------------------------------------------------------- - INLINE void SimpleComp::process( double &in1, double &in2 ) - { - // create sidechain - - double rect1 = fabs( in1 ); // rectify input - double rect2 = fabs( in2 ); - - /* if desired, one could use another EnvelopeDetector to smooth - * the rectified signal. - */ - - double link = std::max( rect1, rect2 ); // link channels with greater of 2 - - process( in1, in2, link ); // rest of process - } - - //------------------------------------------------------------- - INLINE void SimpleComp::process( double &in1, double &in2, double keyLinked ) - { - keyLinked = fabs( keyLinked ); // rectify (just in case) - - // convert key to dB - keyLinked += DC_OFFSET; // add DC offset to avoid log( 0 ) - double keydB = lin2dB( keyLinked ); // convert linear -> dB - - // threshold - double overdB = keydB - threshdB_; // delta over threshold - if ( overdB < 0.0 ) - overdB = 0.0; - - // attack/release - - overdB += DC_OFFSET; // add DC offset to avoid denormal - AttRelEnvelope::run( overdB, envdB_ ); // run attack/release envelope - overdB = envdB_ - DC_OFFSET; // subtract DC offset - - /* 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, - * thereby avoiding denormals. However, to prevent the offset from causing - * constant gain reduction, we must subtract it from the envelope, yielding - * a minimum value of 0dB. - */ - - // transfer function - double gr = overdB * ( ratio_ - 1.0 ); // gain reduction (dB) - gr = dB2lin( gr ); // convert dB -> linear - - // output gain - in1 *= gr; // apply gain reduction to input - in2 *= gr; - } - - //------------------------------------------------------------- - INLINE void SimpleCompRms::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. - */ - - SimpleComp::process( in1, in2, rms ); // rest of process - } - -} // end namespace chunkware_simple - -#endif // end __SIMPLE_COMP_PROCESS_INL__ diff --git a/simpleSource/SimpleEnvelope.cpp b/simpleSource/SimpleEnvelope.cpp deleted file mode 100755 index d507756..0000000 --- a/simpleSource/SimpleEnvelope.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Simple Envelope Detectors (source) - * - * File : SimpleEnvelope.cpp - * Library : SimpleSource - * Version : 1.12 - * Implements : EnvelopeDetector, AttRelEnvelope - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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. - */ - - -#include "SimpleEnvelope.h" - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // envelope detector - //------------------------------------------------------------- - EnvelopeDetector::EnvelopeDetector( double ms, double sampleRate ) - { - assert( sampleRate > 0.0 ); - assert( ms > 0.0 ); - sampleRate_ = sampleRate; - ms_ = ms; - setCoef(); - } - - //------------------------------------------------------------- - void EnvelopeDetector::setTc( double ms ) - { - assert( ms > 0.0 ); - ms_ = ms; - setCoef(); - } - - //------------------------------------------------------------- - void EnvelopeDetector::setSampleRate( double sampleRate ) - { - assert( sampleRate > 0.0 ); - sampleRate_ = sampleRate; - setCoef(); - } - - //------------------------------------------------------------- - void EnvelopeDetector::setCoef( void ) - { - coef_ = exp( -1000.0 / ( ms_ * sampleRate_ ) ); - } - - //------------------------------------------------------------- - // attack/release envelope - //------------------------------------------------------------- - AttRelEnvelope::AttRelEnvelope( double att_ms, double rel_ms, double sampleRate ) - : att_( att_ms, sampleRate ) - , rel_( rel_ms, sampleRate ) - { - } - - //------------------------------------------------------------- - void AttRelEnvelope::setAttack( double ms ) - { - att_.setTc( ms ); - } - - //------------------------------------------------------------- - void AttRelEnvelope::setRelease( double ms ) - { - rel_.setTc( ms ); - } - - //------------------------------------------------------------- - void AttRelEnvelope::setSampleRate( double sampleRate ) - { - att_.setSampleRate( sampleRate ); - rel_.setSampleRate( sampleRate ); - } - -} // end namespace chunkware_simple diff --git a/simpleSource/SimpleEnvelope.h b/simpleSource/SimpleEnvelope.h deleted file mode 100755 index c1e151c..0000000 --- a/simpleSource/SimpleEnvelope.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Simple Envelope Detectors (header) - * - * File : SimpleEnvelope.h - * Library : SimpleSource - * Version : 1.12 - * Class : EnvelopeDetector, AttRelEnvelope - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_ENVELOPE_H__ -#define __SIMPLE_ENVELOPE_H__ - -#include "SimpleHeader.h" // common header - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // DC offset (to prevent denormal) - //------------------------------------------------------------- - - // USE: - // 1. init envelope state to DC_OFFSET before processing - // 2. add to input before envelope runtime function - static const double DC_OFFSET = 1.0E-25; - - //------------------------------------------------------------- - // envelope detector - //------------------------------------------------------------- - class EnvelopeDetector - { - public: - EnvelopeDetector( - double ms = 1.0 - , double sampleRate = 44100.0 - ); - virtual ~EnvelopeDetector() {} - - // time constant - virtual void setTc( double ms ); - virtual double getTc( void ) const { return ms_; } - - // sample rate - virtual void setSampleRate( double sampleRate ); - virtual double getSampleRate( void ) const { return sampleRate_; } - - // runtime function - INLINE void run( double in, double &state ) { - state = in + coef_ * ( state - in ); - } - - protected: - - double sampleRate_; // sample rate - double ms_; // time constant in ms - double coef_; // runtime coefficient - virtual void setCoef( void ); // coef calculation - - }; // end SimpleComp class - - //------------------------------------------------------------- - // attack/release envelope - //------------------------------------------------------------- - class AttRelEnvelope - { - public: - AttRelEnvelope( - double att_ms = 10.0 - , double rel_ms = 100.0 - , double sampleRate = 44100.0 - ); - virtual ~AttRelEnvelope() {} - - // attack time constant - virtual void setAttack( double ms ); - virtual double getAttack( void ) const { return att_.getTc(); } - - // release time constant - virtual void setRelease( double ms ); - virtual double getRelease( void ) const { return rel_.getTc(); } - - // sample rate dependencies - virtual void setSampleRate( double sampleRate ); - virtual double getSampleRate( void ) const { return att_.getSampleRate(); } - - // runtime function - INLINE void run( double in, double &state ) { - - /* assumes that: - * positive delta = attack - * negative delta = release - * good for linear & log values - */ - - if ( in > state ) - att_.run( in, state ); // attack - else - rel_.run( in, state ); // release - } - - private: - - EnvelopeDetector att_; - EnvelopeDetector rel_; - - }; // end AttRelEnvelope class - -} // end namespace chunkware_simple - -#endif // end __SIMPLE_ENVELOPE_H__ diff --git a/simpleSource/SimpleGate.cpp b/simpleSource/SimpleGate.cpp deleted file mode 100755 index 31c3a08..0000000 --- a/simpleSource/SimpleGate.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Simple Gate (source) - * - * File : SimpleGate.cpp - * Library : SimpleSource - * Version : 1.12 - * Implements : SimpleGate, SimpleGateRms - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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. - */ - - -#include "SimpleGate.h" - -namespace chunkware_simple -{ - //------------------------------------------------------------- - SimpleGate::SimpleGate() - : AttRelEnvelope( 1.0, 100.0 ) - , threshdB_( 0.0 ) - , thresh_( 1.0 ) - , env_( DC_OFFSET ) - { - } - - //------------------------------------------------------------- - void SimpleGate::setThresh( double dB ) - { - threshdB_ = dB; - thresh_ = dB2lin( dB ); - } - - //------------------------------------------------------------- - void SimpleGate::initRuntime( void ) - { - env_ = DC_OFFSET; - } - - //------------------------------------------------------------- - // simple gate with RMS detection - //------------------------------------------------------------- - SimpleGateRms::SimpleGateRms() - : ave_( 5.0 ) - , aveOfSqrs_( DC_OFFSET ) - { - } - - //------------------------------------------------------------- - void SimpleGateRms::setSampleRate( double sampleRate ) - { - SimpleGate::setSampleRate( sampleRate ); - ave_.setSampleRate( sampleRate ); - } - - //------------------------------------------------------------- - void SimpleGateRms::setWindow( double ms ) - { - ave_.setTc( ms ); - } - - //------------------------------------------------------------- - void SimpleGateRms::initRuntime( void ) - { - SimpleGate::initRuntime(); - aveOfSqrs_ = DC_OFFSET; - } - -} // end namespace chunkware_simple diff --git a/simpleSource/SimpleGate.h b/simpleSource/SimpleGate.h deleted file mode 100755 index 4a28138..0000000 --- a/simpleSource/SimpleGate.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Simple Gate (header) - * - * File : SimpleGate.h - * Library : SimpleSource - * Version : 1.12 - * Class : SimpleGate, SimpleGateRms - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_GATE_H__ -#define __SIMPLE_GATE_H__ - -#include "SimpleHeader.h" // common header -#include "SimpleEnvelope.h" // for base class -#include "SimpleGain.h" // for gain functions - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // simple gate - //------------------------------------------------------------- - class SimpleGate : public AttRelEnvelope - { - public: - SimpleGate(); - virtual ~SimpleGate() {} - - // parameters - virtual void setThresh( double dB ); - virtual double getThresh( void ) const { return threshdB_; } - - // runtime - virtual void initRuntime( void ); // call before runtime (in resume()) - void process( double &in1, double &in2 ); // gate runtime process - void process( double &in1, double &in2, double keyLinked ); // with stereo-linked key in - - private: - - // transfer function - double threshdB_; // threshold (dB) - double thresh_; // threshold (linear) - - // runtime variables - double env_; // over-threshold envelope (linear) - - }; // end SimpleGate class - - //------------------------------------------------------------- - // simple gate with RMS detection - //------------------------------------------------------------- - class SimpleGateRms : public SimpleGate - { - public: - SimpleGateRms(); - virtual ~SimpleGateRms() {} - - // sample rate - virtual void setSampleRate( double sampleRate ); - - // RMS window - virtual void setWindow( double ms ); - virtual double getWindow( void ) const { return ave_.getTc(); } - - // runtime process - virtual void initRuntime( void ); // call before runtime (in resume()) - void process( double &in1, double &in2 ); // gate runtime process - - private: - - EnvelopeDetector ave_; // averager - double aveOfSqrs_; // average of squares - - }; // end SimpleGateRms class - -} // end namespace chunkware_simple - -// include inlined process function -#include "SimpleGateProcess.inl" - -#endif // end __SIMPLE_GATE_H__ diff --git a/simpleSource/SimpleGateProcess.inl b/simpleSource/SimpleGateProcess.inl deleted file mode 100755 index daa6e3a..0000000 --- a/simpleSource/SimpleGateProcess.inl +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Simple Gate (runtime function) - * - * File : SimpleGateProcess.inl - * Library : SimpleSource - * Version : 1.12 - * Implements : void SimpleGate::process( double &in1, double &in2 ) - * void SimpleGate::process( double &in1, double &in2, double keyLinked ) - * void SimpleGateRms::process( double &in1, double &in2 ) - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_GATE_PROCESS_INL__ -#define __SIMPLE_GATE_PROCESS_INL__ - -namespace chunkware_simple -{ - //------------------------------------------------------------- - INLINE void SimpleGate::process( double &in1, double &in2 ) - { - // create sidechain - - double rect1 = fabs( in1 ); // rectify input - double rect2 = fabs( in2 ); - - /* if desired, one could use another EnvelopeDetector to smooth - * the rectified signal. - */ - - double link = std::max( rect1, rect2 ); // link channels with greater of 2 - - process( in1, in2, link ); // rest of process - } - - //------------------------------------------------------------- - INLINE void SimpleGate::process( double &in1, double &in2, double keyLinked ) - { - keyLinked = fabs( keyLinked ); // rectify (just in case) - - // threshold - // key over threshold ( 0.0 or 1.0 ) - double over = double( keyLinked > thresh_ ); - - // attack/release - over += DC_OFFSET; // add DC offset to avoid denormal - AttRelEnvelope::run( over, env_ ); // run attack/release - over = env_ - DC_OFFSET; // subtract DC offset - - /* 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, - * thereby avoiding denormals. However, to prevent the offset from causing - * constant gain reduction, we must subtract it from the envelope, yielding - * a minimum value of 0dB. - */ - - // output gain - in1 *= over; // apply gain reduction to input - in2 *= over; - } - - //------------------------------------------------------------- - INLINE void SimpleGateRms::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. - */ - - SimpleGate::process( in1, in2, rms ); // rest of process - } - -} // end namespace chunkware_simple - -#endif // end __SIMPLE_GATE_PROCESS_INL__ diff --git a/simpleSource/SimpleLimit.cpp b/simpleSource/SimpleLimit.cpp deleted file mode 100755 index 9d320fd..0000000 --- a/simpleSource/SimpleLimit.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Simple Limiter (source) - * - * File : SimpleLimit.cpp - * Library : SimpleSource - * Version : 1.12 - * Implements : SimpleLimit - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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. - */ - - -#include "SimpleLimit.h" - -namespace chunkware_simple -{ - //------------------------------------------------------------- - SimpleLimit::SimpleLimit() - : threshdB_( 0.0 ) - , thresh_( 1.0 ) - , peakHold_( 0 ) - , peakTimer_( 0 ) - , maxPeak_( 1.0 ) - , att_( 1.0 ) - , rel_( 10.0 ) - , env_( 1.0 ) - , mask_( BUFFER_SIZE - 1 ) - , cur_( 0 ) - { - setAttack( 1.0 ); - outBuffer_[ 0 ].resize( BUFFER_SIZE, 0.0 ); - outBuffer_[ 1 ].resize( BUFFER_SIZE, 0.0 ); - } - - //------------------------------------------------------------- - void SimpleLimit::setThresh( double dB ) - { - threshdB_ = dB; - thresh_ = dB2lin( dB ); - } - - //------------------------------------------------------------- - void SimpleLimit::setAttack( double ms ) - { - unsigned int samp = int( 0.001 * ms * att_.getSampleRate() ); - - assert( samp < BUFFER_SIZE ); - - peakHold_ = samp; - att_.setTc( ms ); - } - - //------------------------------------------------------------- - void SimpleLimit::setRelease( double ms ) - { - rel_.setTc( ms ); - } - - //------------------------------------------------------------- - void SimpleLimit::setSampleRate( double sampleRate ) - { - att_.setSampleRate( sampleRate ); - rel_.setSampleRate( sampleRate ); - } - - //------------------------------------------------------------- - void SimpleLimit::initRuntime( void ) - { - peakTimer_ = 0; - maxPeak_ = thresh_; - env_ = thresh_; - cur_ = 0; - outBuffer_[ 0 ].assign( BUFFER_SIZE, 0.0 ); - outBuffer_[ 1 ].assign( BUFFER_SIZE, 0.0 ); - } - - //------------------------------------------------------------- - void SimpleLimit::FastEnvelope::setCoef( void ) - { - // rises to 99% of in value over duration of time constant - coef_ = pow( 0.01, (1000.0 / (ms_ * sampleRate_) ) ); - } - -} // end namespace chunkware_simple diff --git a/simpleSource/SimpleLimit.h b/simpleSource/SimpleLimit.h deleted file mode 100755 index eec57ea..0000000 --- a/simpleSource/SimpleLimit.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Simple Limiter (header) - * - * File : SimpleLimit.h - * Library : SimpleSource - * Version : 1.12 - * Class : SimpleLimit - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_LIMIT_H__ -#define __SIMPLE_LIMIT_H__ - -#include "SimpleHeader.h" // common header -#include "SimpleEnvelope.h" // for base class of FastEnvelope -#include "SimpleGain.h" // for gain functions -#include - -namespace chunkware_simple -{ - //------------------------------------------------------------- - // simple limiter - //------------------------------------------------------------- - class SimpleLimit - { - public: - SimpleLimit(); - virtual ~SimpleLimit() {} - - // parameters - virtual void setThresh( double dB ); - virtual void setAttack( double ms ); - virtual void setRelease( double ms ); - - virtual double getThresh( void ) const { return threshdB_; } - virtual double getAttack( void ) const { return att_.getTc(); } - virtual double getRelease( void ) const { return rel_.getTc(); } - - // latency - virtual const unsigned int getLatency( void ) const { return peakHold_; } - - // sample rate dependencies - virtual void setSampleRate( double sampleRate ); - virtual double getSampleRate( void ) { return att_.getSampleRate(); } - - // runtime - virtual void initRuntime( void ); // call before runtime (in resume()) - void process( double &in1, double &in2 ); // limiter runtime process - - protected: - - // class for faster attack/release - class FastEnvelope : public EnvelopeDetector - { - public: - FastEnvelope( double ms = 1.0, double sampleRate = 44100.0 ) - : EnvelopeDetector( ms, sampleRate ) - {} - virtual ~FastEnvelope() {} - - protected: - // override setCoef() - coefficient calculation - virtual void setCoef( void ); - }; - - private: - - // transfer function - double threshdB_; // threshold (dB) - double thresh_; // threshold (linear) - - // max peak - unsigned int peakHold_; // peak hold (samples) - unsigned int peakTimer_; // peak hold timer - double maxPeak_; // max peak - - // attack/release envelope - FastEnvelope att_; // attack - FastEnvelope rel_; // release - double env_; // over-threshold envelope (linear) - - // buffer - // BUFFER_SIZE default can handle up to ~10ms at 96kHz - // change this if you require more - static const int BUFFER_SIZE = 1024; // buffer size (always a power of 2!) - unsigned int mask_; // buffer mask - unsigned int cur_; // cursor - std::vector< double > outBuffer_[ 2 ]; // output buffer - - }; // end SimpleLimit class - -} // end namespace chunkware_simple - -// include inlined process function -#include "SimpleLimitProcess.inl" - -#endif // end __SIMPLE_LIMIT_H__ diff --git a/simpleSource/SimpleLimitProcess.inl b/simpleSource/SimpleLimitProcess.inl deleted file mode 100755 index c5afcf3..0000000 --- a/simpleSource/SimpleLimitProcess.inl +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Simple Limiter (runtime function) - * - * File : SimpleLimitProcess.inl - * Library : SimpleSource - * Version : 1.12 - * Implements : void SimpleLimit::process( double &in1, double &in2 ) - * - * © 2006, ChunkWare Music Software, OPEN-SOURCE - * - * 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_LIMIT_PROCESS_INL__ -#define __SIMPLE_LIMIT_PROCESS_INL__ - -namespace chunkware_simple -{ - //------------------------------------------------------------- - INLINE void SimpleLimit::process( double &in1, double &in2 ) - { - // create sidechain - - double rect1 = fabs( in1 ); // rectify input - double rect2 = fabs( in2 ); - - double keyLink = std::max( rect1, rect2 ); // link channels with greater of 2 - - // threshold - // we always want to feed the sidechain AT LEATS the threshold value - if ( keyLink < thresh_ ) - keyLink = thresh_; - - // test: - // a) whether peak timer has "expired" - // b) whether new peak is greater than previous max peak - if ( (++peakTimer_ >= peakHold_) || (keyLink > maxPeak_) ) { - // if either condition is met: - peakTimer_ = 0; // reset peak timer - maxPeak_ = keyLink; // assign new peak to max peak - } - - /* REGARDING THE MAX PEAK: This method assumes that the only important - * sample in a look-ahead buffer would be the highest peak. As such, - * instead of storing all samples in a look-ahead buffer, it only stores - * the max peak, and compares all incoming samples to that one. - * The max peak has a hold time equal to what the look-ahead buffer - * would have been, which is tracked by a timer (counter). When this - * timer expires, the sample would have exited from the buffer. Therefore, - * a new sample must be assigned to the max peak. We assume that the next - * highest sample in our theoretical buffer is the current input sample. - * In reality, we know this is probably NOT the case, and that there has - * been another sample, slightly lower than the one before it, that has - * passed the input. If we do not account for this possibility, our gain - * reduction could be insufficient, resulting in an "over" at the output. - * To remedy this, we simply apply a suitably long release stage in the - * envelope follower. - */ - - // attack/release - if ( maxPeak_ > env_ ) - att_.run( maxPeak_, env_ ); // run attack phase - else - rel_.run( maxPeak_, env_ ); // run release phase - - /* REGARDING THE ATTACK: This limiter achieves "look-ahead" detection - * by allowing the envelope follower to attack the max peak, which is - * held for the duration of the attack phase -- unless a new, higher - * peak is detected. The output signal is buffered so that the gain - * reduction is applied in advance of the "offending" sample. - */ - - /* NOTE: a DC offset is not necessary for the envelope follower, - * as neither the max peak nor envelope should fall below the - * threshold (which is assumed to be around 1.0 linear). - */ - - // gain reduction - double gR = thresh_ / env_; - - // unload current buffer index - // ( cur_ - delay ) & mask_ gets sample from [delay] samples ago - // mask_ variable wraps index - unsigned int delayIndex = ( cur_ - peakHold_ ) & mask_; - double delay1 = outBuffer_[ 0 ][ delayIndex ]; - double delay2 = outBuffer_[ 1 ][ delayIndex ]; - - // load current buffer index and advance current index - // mask_ wraps cur_ index - outBuffer_[ 0 ][ cur_ ] = in1; - outBuffer_[ 1 ][ cur_ ] = in2; - ++cur_ &= mask_; - - // output gain - in1 = delay1 * gR; // apply gain reduction to input - in2 = delay2 * gR; - - /* REGARDING THE GAIN REDUCTION: Due to the logarithmic nature - * of the attack phase, the sidechain will never achieve "full" - * attack. (Actually, it is only guaranteed to achieve 99% of - * the input value over the given time constant.) As such, the - * limiter cannot achieve "brick-wall" limiting. There are 2 - * workarounds: - * - * 1) Set the threshold slightly lower than the desired threshold. - * i.e. 0.0dB -> -0.1dB or even -0.5dB - * - * 2) Clip the output at the threshold, as such: - * - * if ( in1 > thresh_ ) in1 = thresh_; - * else if ( in1 < -thresh_ ) in1 = -thresh_; - * - * if ( in2 > thresh_ ) in2 = thresh_; - * else if ( in2 < -thresh_ ) in2 = -thresh_; - * - * (... or replace with your favorite branchless clipper ...) - */ - } - -} // end namespace chunkware_simple - -#endif // end __SIMPLE_LIMIT_PROCESS_INL__