Skip to content

Commit

Permalink
maxiDynamics v1
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskiefer committed Jan 6, 2023
1 parent 3d4fe12 commit 43e61d4
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 38 deletions.
13 changes: 9 additions & 4 deletions cpp/commandline/maximilian_examples/17.Compressor/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 9,25 @@ void setup() {//some inits

beats.load("../../../beat2.wav");//load in your samples. Provide the full path to a wav file.

dyn.setAttack(400);
dyn.setRelease(400);
dyn.setAttackHigh(20);
dyn.setReleaseHigh(10);
dyn.setAttackLow(1);
dyn.setReleaseLow(1);
dyn.setLookAhead(2);

}

void play(double *output) {//this is where the magic happens. Very slow magic.


//here, we're just compressing the file in real-time
//arguments are input,ratio,threshold,attack,release

double out=beats.play();
double oscs = osc1.saw(300);// * (osc2.phasor(0.5) > 0.5);
out = dyn.play(oscs, out, -12, 4, 10);
out = dyn.play(out, out,
0, 0, 0, // above high thresh
-30, 100, 1 //below low thresh
);


output[0]=out;
Expand Down
138 changes: 104 additions & 34 deletions src/maximilian.h
Original file line number Diff line number Diff line change
Expand Up @@ -2301,8 2301,12 @@ class CHEERP_EXPORT maxiDynamics {
};

inputAnalyser = inputRMS;
arEnv.setupASR(10,10);
arEnv.setRetrigger(false);
arEnvHigh.setupASR(10,10);
arEnvHigh.setRetrigger(false);
arEnvLow.setupASR(10,10);
arEnvLow.setRetrigger(false);

lookAheadDelay.setup(maxiSettings::sampleRate * 1); //max 1s
}

double envToRatio(double envVal, double ratio) {
Expand All @@ -2315,70 2319,136 @@ class CHEERP_EXPORT maxiDynamics {
return envRatio;
}

double play(double sig, double control, double threshold, double ratio, double knee) {
double play(double sig, double control,
double thresholdHigh, double ratioHigh, double kneeHigh,
double thresholdLow, double ratioLow, double kneeLow
) {
double controlDB = maxiConvert::ampToDbs(inputAnalyser(control));
double outDB = maxiConvert::ampToDbs(sig);
if (ratio > 0) {
if (knee > 0) {
double lowKnee = threshold - (knee/2.0);
double highKnee = threshold (knee/2.0);
if (ratioHigh > 0) {
if (kneeHigh > 0) {
double lowerKnee = thresholdHigh - (kneeHigh/2.0);
double higherKnee = thresholdHigh (kneeHigh/2.0);
//attack/release
double envRatio = 1;
if (controlDB >= lowKnee) {
double envVal = arEnv.play(1);
envRatio = envToRatio(envVal, ratio);
if (controlDB >= lowerKnee) {
double envVal = arEnvHigh.play(1);
envRatio = envToRatio(envVal, ratioHigh);
cout << "on: " << envVal << endl;
}else {
double envVal = arEnv.play(-1);
double envVal = arEnvHigh.play(-1);
cout << "off: " << envVal << endl;
}
if ((controlDB >= lowKnee) && (controlDB < highKnee)) {
double kneeHighOut = ((highKnee - threshold) / envRatio) threshold;
double kneeRange = (kneeHighOut - lowKnee);
double t = (controlDB - lowKnee) / knee;
if ((controlDB >= lowerKnee) && (controlDB < higherKnee)) {
double kneeHighOut = ((higherKnee - thresholdHigh) / envRatio) thresholdHigh;
double kneeRange = (kneeHighOut - lowerKnee);
double t = (controlDB - lowerKnee) / kneeHigh;
//bezier on x only
double kneex = (2 * (1-t) * t * 0.85) (t*t);
outDB = lowKnee (kneex * kneeRange);
double curve = ratioHigh > 1 ? 0.8 : 0.2;
double kneex = (2 * (1-t) * t * curve) (t*t);
outDB = lowerKnee (kneex * kneeRange);
cout << "k";
}
else if (controlDB >= highKnee) {
outDB = ((controlDB - threshold) / envRatio) threshold;
else if (controlDB >= higherKnee) {
outDB = ((controlDB - thresholdHigh) / envRatio) thresholdHigh;
cout << "o";
}
}
else {
//no knee
if (controlDB > threshold) {
if (controlDB > thresholdHigh) {
cout << "c";
double envVal = arEnv.play(1);
double envRatio = envToRatio(envVal, ratio);
double envVal = arEnvHigh.play(1);
double envRatio = envToRatio(envVal, ratioHigh);
cout << "on: " << envVal << endl;
outDB = ((controlDB - threshold) / envRatio) threshold;
outDB = ((controlDB - thresholdHigh) / envRatio) thresholdHigh;
}else {
double envVal = arEnv.play(-1);
double envVal = arEnvHigh.play(-1);
cout << "off: " << envVal << endl;
}
}
}
if (ratioLow > 0) {
if (kneeLow > 0) {
double lowerKnee = thresholdLow - (kneeLow/2.0);
double higherKnee = thresholdLow (kneeLow/2.0);
//attack/release
double envRatio = 1;
if (controlDB < lowerKnee) {
double envVal = arEnvLow.play(1);
envRatio = envToRatio(envVal, ratioLow);
cout << "on: " << envVal << endl;
}else {
double envVal = arEnvLow.play(-1);
cout << "off: " << envVal << endl;
}
if ((controlDB >= lowerKnee) && (controlDB < higherKnee)) {
double kneeLowOut = thresholdLow - ((thresholdLow-lowerKnee) / ratioLow);
double kneeRange = (higherKnee - kneeLowOut);
double t = (controlDB - lowerKnee) / kneeLow;
//bezier on x only
double curve = ratioLow > 1 ? 0.2 : 0.8;
double kneex = (2 * (1-t) * t * curve) (t*t);
outDB = kneeLowOut (kneex * kneeRange);
cout << "k";
}
else if (controlDB < lowerKnee) {
outDB = thresholdLow - ((thresholdLow-controlDB) / ratioLow);
cout << "o";
}
}
else {
//no knee
if (controlDB < thresholdLow) {
cout << "c";
double envVal = arEnvLow.play(1);
double envRatio = envToRatio(envVal, ratioLow);
cout << "on: " << envVal << endl;
outDB = thresholdLow - ((thresholdLow-controlDB) / ratioLow);
}else {
double envVal = arEnvLow.play(-1);
cout << "off: " << envVal << endl;
}
}
}
double outAmp = maxiConvert::dbsToAmp(outDB);
double sigOut = 0;
if (outAmp > 0) {
sig = sig * (control / outAmp);
}else{
sig = 0.0;
if (lookAheadSize > 0) {
lookAheadDelay.push(sig);
sigOut = lookAheadDelay.tail(lookAheadSize);
}else{
sigOut = sig;
}
sigOut = sigOut * (control / outAmp);
}
return sig;
return sigOut;
}

void setAttack(double attack) {
arEnv.setTime(0, attack);
void setAttackHigh(double attack) {
arEnvHigh.setTime(0, attack);
}
void setReleaseHigh(double release) {
arEnvHigh.setTime(2, release);
}
void setAttackLow(double attack) {
arEnvLow.setTime(0, attack);
}
void setReleaseLow(double release) {
arEnvLow.setTime(2, release);
}
void setLookAhead(double length) {
lookAheadSize = maxiConvert::msToSamps(length);
lookAheadSize = min(lookAheadSize, lookAheadDelay.size());
}
void setRelease(double attack) {
arEnv.setTime(2, attack);
double getLookAhead() {
return maxiConvert::sampsToMs(lookAheadSize);
}

private:
maxiEnvGen arEnv;
maxiDelayline lookAheadDelay;
maxiEnvGen arEnvHigh, arEnvLow;
maxiRingBuf lookAheadDelay;
size_t lookAheadSize = 0;
maxiRMS rms;
std::function<double(double)> inputPeak;
std::function<double(double)> inputRMS;
Expand Down

0 comments on commit 43e61d4

Please sign in to comment.