Skip to content

Commit

Permalink
optimized envelopes
Browse files Browse the repository at this point in the history
  • Loading branch information
hsetlik committed Apr 16, 2021
1 parent 0e4bf4e commit c353ff7
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 114 deletions.
8 changes: 5 additions & 3 deletions Source/AlgorithmGraphComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,15 +204,17 @@ void AlgorithmGraph::paint(juce::Graphics &g)
int idx = 0;
for(auto i : gridRows)
{
juce::String str = "In Row " + juce::String(idx) + ": ";
//juce::String str = "In Row " + juce::String(idx) + ": ";
/*
for(auto op : i)
{
auto numStr = juce::String(op->index);
numStr += ", ";
str += numStr;
}
str += "\n";
printf("%s", str.toRawUTF8());
*/
//str += "\n";
//printf("%s", str.toRawUTF8());
if(i.size() > largestDimension)
largestDimension = (int)i.size();
++idx;
Expand Down
180 changes: 78 additions & 102 deletions Source/DAHDSR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,111 +10,87 @@

#include "DAHDSR.h"

float DAHDSR::process(float input)
float DAHDSR::factorFor(float startLevel, float endLevel, float lengthMs)
{
if(startLevel == 0.0f)
startLevel = minLevel;
if(endLevel == 0.0f)
endLevel = minLevel;
unsigned long phaseLengthSamples = lengthMs * (sampleRate / 1000);
return exp((log(endLevel) - log(startLevel)) / phaseLengthSamples);
}

void DAHDSR::enterPhase(envPhase newPhase)
{
switch(currentPhase)
currentPhase = newPhase;
samplesIntoPhase = 0;
switch(newPhase)
{
case delayPhase:
{
case delayPhase:
{
if(valueOf(delayId) > 0)
{
if(samplesIntoPhase == 0)
samplesInPhase = phaseSafe(floor(delayTime * (sampleRate / 1000)));
samplesIntoPhase += 1;
if(samplesIntoPhase >= samplesInPhase)
{
currentPhase = attackPhase;
samplesIntoPhase = 0;
samplesInPhase = phaseSafe(floor(attackTime * (sampleRate / 1000)));
factor = exp((log(1.0f) - log(minLevel)) /samplesInPhase);
}
output = 0.0f;
}
else
{
currentPhase = attackPhase;
samplesInPhase = phaseSafe(floor(attackTime * (sampleRate / 1000)));
factor = exp((log(1.0f) - log(minLevel)) /samplesInPhase);
samplesIntoPhase = 0;
}
break;
}
case attackPhase:
{
if(samplesIntoPhase == 0)
output = minLevel;
output = output * factor;
samplesIntoPhase++;
if(samplesIntoPhase >= samplesInPhase)
{
currentPhase = holdPhase;
samplesIntoPhase = 0;
samplesInPhase = valueOf(holdId) * (sampleRate / 1000);
}
break;
}
case holdPhase:
{
if(holdTime != 0)
{
samplesIntoPhase += 1;
if(samplesIntoPhase > samplesInPhase)
{
currentPhase = decayPhase;
samplesIntoPhase = 0;
samplesInPhase = phaseSafe(decayTime * (sampleRate / 1000));
factor = exp((log(sustainLevel) - log(1.0f)) /samplesInPhase);
}
output = 1.0f;
}
else
{
currentPhase = decayPhase;
samplesIntoPhase = 0;
samplesInPhase = phaseSafe(decayTime * (sampleRate / 1000));
factor = exp((log(sustainLevel) - log(1.0f)) /samplesInPhase);;
}
break;
}
case decayPhase:
{
output = output * factor;
samplesIntoPhase += 1;
if(samplesIntoPhase >= samplesInPhase)
{
currentPhase = sustainPhase;
samplesIntoPhase = 0;
output = sustainLevel;
}
break;
}
case sustainPhase:
{
output = sustainLevel;
break;
}
case releasePhase:
{
output = output * factor;
samplesIntoPhase += 1;
if(samplesIntoPhase >= samplesInPhase)
currentPhase = noteOff;
break;
}
case noteOff:
{
samplesIntoPhase = 0;
output = 0.0f;
break;
}
default:
break;
startLevel = minLevel;
endLevel = minLevel;
samplesInPhase = delayTime * (sampleRate / 1000);
factor = factorFor(startLevel, endLevel, delayTime);
break;
}
case attackPhase:
{
startLevel = minLevel;
endLevel = 1.0f;
samplesInPhase = attackTime * (sampleRate / 1000);
factor = factorFor(startLevel, endLevel, attackTime);
break;
}
case holdPhase:
{
startLevel = 1.0f;
endLevel = 1.0f;
samplesInPhase = holdTime * (sampleRate / 1000);
factor = factorFor(startLevel, endLevel, holdTime);
break;
}
case decayPhase:
{
startLevel = 1.0f;
endLevel = sustainLevel;
samplesInPhase = decayTime * sampleRate / 1000;
factor = factorFor(startLevel, endLevel, decayTime);
break;
}
case sustainPhase:
{
startLevel = sustainLevel;
endLevel = sustainLevel;
samplesInPhase = 1000000;
factor = 1.0f;
break;
}
case releasePhase:
{
startLevel = sustainLevel;
endLevel = minLevel;
samplesInPhase = releaseTime * sampleRate / 1000;
factor = factorFor(startLevel, endLevel, releaseTime);
break;
}
case noteOff:
{
startLevel = minLevel;
endLevel = minLevel;
samplesInPhase = 100000000;
factor = 0.0f;
break;
}
if(isnan(output))
{
output = 0.0f;
printf("Envelope output is nan\n");
}

output = startLevel;
updatePhase();
}

float DAHDSR::process(float input)
{
updatePhase();
++samplesIntoPhase;
output *= factor;
return input * output;
}
37 changes: 28 additions & 9 deletions Source/DAHDSR.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class DAHDSR
trigger = false;
samplesIntoPhase = 0;
currentPhase = noteOff;
output = 0.0f;
auto iStr = juce::String(ind);
delayId = "delayParam" + iStr;
attackId = "attackParam" + iStr;
Expand All @@ -42,17 +43,26 @@ class DAHDSR
releaseId = "releaseParam" + iStr;
}
~DAHDSR() {}
static envPhase nextPhase(envPhase input)
{
if(input != noteOff)
return (envPhase)(input + 1);
else
return noteOff;
}
void triggerOn()
{
trigger = true;
samplesInPhase = floor(delayTime * (sampleRate / 1000));
samplesIntoPhase = 0;
currentPhase = delayPhase;
enterPhase(delayPhase);
}
float valueOf(juce::String& str)
{
return *tree->getRawParameterValue(str);
}
std::atomic<float>* ptrValue(juce::String str)
{
return tree->getRawParameterValue(str);
}
void updateParams()
{
delayTime = valueOf(delayId);
Expand All @@ -65,11 +75,17 @@ class DAHDSR
void triggerOff()
{
trigger = false;
currentPhase = releasePhase;
samplesIntoPhase = 0;
samplesInPhase = releaseTime * (sampleRate / 1000);
factor = exp((log(minLevel) - log(sustainLevel)) /samplesInPhase);
enterPhase(releasePhase);
}
void updatePhase()
{
if(samplesIntoPhase > samplesInPhase || samplesInPhase < 1)
{
enterPhase(nextPhase(currentPhase));
}
}
void enterPhase(envPhase newPhase);
float factorFor(float startLevel, float endLevel, float lengthMs);
void setSampleRate(double value) {sampleRate = value;}
float process(float input);
envPhase getPhase() {return currentPhase;}
Expand All @@ -79,7 +95,7 @@ class DAHDSR
return false;
return true;
}
double output;
float output;
private:
//data
static unsigned long long phaseSafe(unsigned long long input) //to avoid divide-by-zero errors
Expand All @@ -91,7 +107,7 @@ class DAHDSR
envPhase currentPhase;
unsigned long long samplesIntoPhase;
unsigned long long samplesInPhase;
double factor;
float factor;
float minLevel = 0.00001f;
double sampleRate;
int index;
Expand All @@ -109,4 +125,7 @@ class DAHDSR
float decayTime = 100.0f;
float sustainLevel = 0.6f;
float releaseTime = 40.0f;

float startLevel;
float endLevel;
};

0 comments on commit c353ff7

Please sign in to comment.