andrewm@0: //
andrewm@0: //  ADSR.cpp
andrewm@0: //
andrewm@0: //  Created by Nigel Redmon on 12/18/12.
andrewm@0: //  EarLevel Engineering: earlevel.com
andrewm@0: //  Copyright 2012 Nigel Redmon
andrewm@0: //
andrewm@0: //  For a complete explanation of the ADSR envelope generator and code,
andrewm@0: //  read the series of articles by the author, starting here:
andrewm@0: //  http://www.earlevel.com/main/2013/06/01/envelope-generators/
andrewm@0: //
andrewm@0: //  License:
andrewm@0: //
andrewm@0: //  This source code is provided as is, without warranty.
andrewm@0: //  You may copy and distribute verbatim copies of this document.
andrewm@0: //  You may modify and use this source code to create binary code for your own purposes, free or commercial.
andrewm@0: //
andrewm@0: 
andrewm@0: #include "ADSR.h"
andrewm@0: #include <math.h>
andrewm@0: 
andrewm@0: 
andrewm@0: ADSR::ADSR(void) {
andrewm@0:     reset();
andrewm@0:     setAttackRate(0);
andrewm@0:     setDecayRate(0);
andrewm@0:     setReleaseRate(0);
andrewm@0:     setSustainLevel(1.0);
andrewm@0:     setTargetRatioA(0.3);
andrewm@0:     setTargetRatioDR(0.0001);
andrewm@0: }
andrewm@0: 
andrewm@0: ADSR::~ADSR(void) {
andrewm@0: }
andrewm@0: 
andrewm@0: void ADSR::setAttackRate(float rate) {
andrewm@0:     attackRate = rate;
andrewm@0:     attackCoef = calcCoef(rate, targetRatioA);
andrewm@0:     attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
andrewm@0: }
andrewm@0: 
andrewm@0: void ADSR::setDecayRate(float rate) {
andrewm@0:     decayRate = rate;
andrewm@0:     decayCoef = calcCoef(rate, targetRatioDR);
andrewm@0:     decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
andrewm@0: }
andrewm@0: 
andrewm@0: void ADSR::setReleaseRate(float rate) {
andrewm@0:     releaseRate = rate;
andrewm@0:     releaseCoef = calcCoef(rate, targetRatioDR);
andrewm@0:     releaseBase = -targetRatioDR * (1.0 - releaseCoef);
andrewm@0: }
andrewm@0: 
andrewm@0: float ADSR::calcCoef(float rate, float targetRatio) {
andrewm@0:     return exp(-log((1.0 + targetRatio) / targetRatio) / rate);
andrewm@0: }
andrewm@0: 
andrewm@0: void ADSR::setSustainLevel(float level) {
andrewm@0:     sustainLevel = level;
andrewm@0:     decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
andrewm@0: }
andrewm@0: 
andrewm@0: void ADSR::setTargetRatioA(float targetRatio) {
andrewm@0:     if (targetRatio < 0.000000001)
andrewm@0:         targetRatio = 0.000000001;  // -180 dB
andrewm@0:     targetRatioA = targetRatio;
andrewm@0:     attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
andrewm@0: }
andrewm@0: 
andrewm@0: void ADSR::setTargetRatioDR(float targetRatio) {
andrewm@0:     if (targetRatio < 0.000000001)
andrewm@0:         targetRatio = 0.000000001;  // -180 dB
andrewm@0:     targetRatioDR = targetRatio;
andrewm@0:     decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
andrewm@0:     releaseBase = -targetRatioDR * (1.0 - releaseCoef);
andrewm@0: }