Skip to content

Commit

Permalink
switched control flow to private members updated once per buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
hsetlik committed Apr 12, 2021
1 parent f7734e3 commit 1bc0fde
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 84 deletions.
26 changes: 13 additions & 13 deletions Source/DAHDSR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ float DAHDSR::process(float input)
{
case delayPhase:
{
if(ParamStatic::opDelayTime[index] > 0)
if(valueOf(delayId) > 0)
{
if(samplesIntoPhase == 0)
samplesInPhase = phaseSafe(floor(ParamStatic::opDelayTime[index].get() * (sampleRate / 1000)));
samplesInPhase = phaseSafe(floor(delayTime * (sampleRate / 1000)));
samplesIntoPhase += 1;
if(samplesIntoPhase >= samplesInPhase)
{
currentPhase = attackPhase;
samplesIntoPhase = 0;
samplesInPhase = phaseSafe(floor(ParamStatic::opAttackTime[index].get() * (sampleRate / 1000)));
samplesInPhase = phaseSafe(floor(attackTime * (sampleRate / 1000)));
factor = exp((log(1.0f) - log(minLevel)) /samplesInPhase);
}
output = 0.0f;
}
else
{
currentPhase = attackPhase;
samplesInPhase = phaseSafe(floor(ParamStatic::opAttackTime[index].get() * (sampleRate / 1000)));
samplesInPhase = phaseSafe(floor(attackTime * (sampleRate / 1000)));
factor = exp((log(1.0f) - log(minLevel)) /samplesInPhase);
samplesIntoPhase = 0;
}
Expand All @@ -49,30 +49,30 @@ float DAHDSR::process(float input)
{
currentPhase = holdPhase;
samplesIntoPhase = 0;
samplesInPhase = ParamStatic::opHoldTime[index].get() * (sampleRate / 1000);
samplesInPhase = valueOf(holdId) * (sampleRate / 1000);
}
break;
}
case holdPhase:
{
if(ParamStatic::opHoldTime[index].get() != 0)
if(holdTime != 0)
{
samplesIntoPhase += 1;
if(samplesIntoPhase > samplesInPhase)
{
currentPhase = decayPhase;
samplesIntoPhase = 0;
samplesInPhase = phaseSafe(ParamStatic::opDecayTime[index].get() * (sampleRate / 1000));
factor = exp((log(ParamStatic::opSustainLevel[index].get()) - log(1.0f)) /samplesInPhase);
samplesInPhase = phaseSafe(decayTime * (sampleRate / 1000));
factor = exp((log(sustainLevel) - log(1.0f)) /samplesInPhase);
}
output = 1.0f;
}
}
else
{
currentPhase = decayPhase;
samplesIntoPhase = 0;
samplesInPhase = phaseSafe(ParamStatic::opDecayTime[index].get() * (sampleRate / 1000));
factor = exp((log(ParamStatic::opSustainLevel[index].get()) - log(1.0f)) /samplesInPhase);;
samplesInPhase = phaseSafe(decayTime * (sampleRate / 1000));
factor = exp((log(sustainLevel) - log(1.0f)) /samplesInPhase);;
}
break;
}
Expand All @@ -84,13 +84,13 @@ float DAHDSR::process(float input)
{
currentPhase = sustainPhase;
samplesIntoPhase = 0;
output = ParamStatic::opSustainLevel[index].get();
output = sustainLevel;
}
break;
}
case sustainPhase:
{
output = ParamStatic::opSustainLevel[index].get();
output = sustainLevel;
break;
}
case releasePhase:
Expand Down
42 changes: 38 additions & 4 deletions Source/DAHDSR.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,49 @@ class DAHDSR
releasePhase,
noteOff
};
juce::AudioProcessorValueTreeState* tree;
//functions
DAHDSR(int ind) : factor(1.0f), sampleRate(44100), index(ind)
DAHDSR(int ind, juce::AudioProcessorValueTreeState* t) : tree(t), factor(1.0f), sampleRate(44100), index(ind)
{
trigger = false;
samplesIntoPhase = 0;
currentPhase = noteOff;
auto iStr = juce::String(ind);
delayId = "delayParam" + iStr;
attackId = "attackParam" + iStr;
holdId = "holdParam" + iStr;
decayId = "decayParam" + iStr;
sustainId = "sustainParam" + iStr;
releaseId = "releaseParam" + iStr;
}
~DAHDSR() {}
void triggerOn()
{
trigger = true;
samplesInPhase = floor(ParamStatic::opDelayTime[index].get() * (sampleRate / 1000));
samplesInPhase = floor(delayTime * (sampleRate / 1000));
samplesIntoPhase = 0;
currentPhase = delayPhase;
}
float valueOf(juce::String& str)
{
return *tree->getRawParameterValue(str);
}
void updateParams()
{
delayTime = valueOf(delayId);
attackTime = valueOf(attackId);
holdTime = valueOf(holdId);
decayTime = valueOf(decayId);
sustainLevel = valueOf(sustainId);
releaseTime = valueOf(releaseId);
}
void triggerOff()
{
trigger = false;
currentPhase = releasePhase;
samplesIntoPhase = 0;
samplesInPhase = ParamStatic::opReleaseTime[index].get() * (sampleRate / 1000);
factor = exp((log(minLevel) - log(ParamStatic::opSustainLevel[index].get())) /samplesInPhase);
samplesInPhase = releaseTime * (sampleRate / 1000);
factor = exp((log(minLevel) - log(sustainLevel)) /samplesInPhase);
}
void setSampleRate(double value) {sampleRate = value;}
float process(float input);
Expand All @@ -70,4 +91,17 @@ class DAHDSR
double sampleRate;
int index;
bool trigger;
juce::String delayId;
juce::String attackId;
juce::String holdId;
juce::String decayId;
juce::String sustainId;
juce::String releaseId;
private:
float delayTime = 0.0f;
float attackTime = 20.0f;
float holdTime = 0.0f;
float decayTime = 100.0f;
float sustainLevel = 0.6f;
float releaseTime = 40.0f;
};
63 changes: 39 additions & 24 deletions Source/FmVoice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,44 @@



FmVoice::FmVoice(int numOperators, int index) : voiceIndex(index), operatorCount(numOperators), fundamental(1.0f)
FmVoice::FmVoice(int numOperators, int index, juce::AudioProcessorValueTreeState* t) : tree(t), voiceIndex(index), operatorCount(numOperators), fundamental(1.0f)
{
lfoMax = std::numeric_limits<float>::min();
lfoMin = std::numeric_limits<float>::max();
numJumps = 0;
for(int i = 0; i < numOperators; ++i)
for(int o = 0; o < numOperators; ++o)
{
operators.add(new Operator(i, voiceIndex));
std::vector<int> ints;
for(int n = 0; n < numOperators; ++n)
operators.add(new Operator(o, voiceIndex, tree));
auto oStr = juce::String(o);
opAudibleIds[o] = "audibleParam" + oStr;
for(int i = 0; i < numOperators; ++i)
{
int newVal = 0;
ints.push_back(newVal);
auto iStr = juce::String(i);
opRoutingIds[o][i] = oStr + "to" + iStr + "Param";
}
routingParams.push_back(ints);
}
for(int n = 0; n < totalLfos; ++n)
{
lfoBank.add(new LfoProcessor(n));
lfoBank.add(new LfoProcessor(n, tree));
}

}
void FmVoice::updateParams()
{
for(op1Index = 0; op1Index < TOTAL_OPERATORS; ++op1Index)
{
operators[op1Index]->updateParams();
opAudible[op1Index] = getValue(opAudibleIds[op1Index]);
if(op1Index < TOTAL_LFOS)
lfoBank[op1Index]->updateParams();
for(op2Index = 0; op2Index < TOTAL_OPERATORS; ++op2Index)
{
opRouting[op1Index][op2Index] = (int)getValue(opRoutingIds[op1Index][op2Index]);
}
}
}
float lastSample = 0.0f;
int numBuffers = 0;
int op1Index = 0;
int op2Index = 0;
void FmVoice::renderNextBlock(juce::AudioBuffer<float> &outputBuffer, int startSample, int numSamples)
{
ParamStatic::workingFundamental = fundamental;
for(int i = startSample; i < (startSample + numSamples); ++i)
{
for(int lfo = 0; lfo < 4; ++ lfo)
Expand All @@ -57,12 +67,12 @@ void FmVoice::renderNextBlock(juce::AudioBuffer<float> &outputBuffer, int startS
op2Index = 0;
for(Operator* d : operators)
{
if(ParamStatic::opRouting[op1Index][op2Index].get())
if(opRouting[op1Index][op2Index])
{ d->modOffset += o->lastOutputSample;}
++op2Index;
}
opSample = o->sample(fundamental);
if(ParamStatic::opAudible[o->getIndex()].get())
if(opAudible[o->getIndex()])
{
opSum += opSample;
sumL += o->lastOutputL;
Expand All @@ -72,10 +82,9 @@ void FmVoice::renderNextBlock(juce::AudioBuffer<float> &outputBuffer, int startS
++op1Index;
}
outputBuffer.addSample(0, i, sumL);
if(outputBuffer.getNumChannels() > 0)
outputBuffer.addSample(1, i, sumR);
outputBuffer.addSample(1, i, sumR);

if(fabs(opSum - lastOpSample) > 0.3f)
if(fabs(opSum - lastOpSample) > 0.2f)
++numJumps;
lastOpSample = opSum;
}
Expand All @@ -84,14 +93,20 @@ void FmVoice::applyLfo(int index)
{
LfoProcessor* thisLfo = lfoBank[index];
lfoValue = thisLfo->getSampleValue();
if(ParamStatic::lfoTarget[index] > 0)
/*
if(lfoValue < lfoMin)
lfoMin = lfoValue;
if(lfoValue > lfoMax)
lfoMax = lfoValue;
*/
if(thisLfo->target > 0)
{
if(ParamStatic::lfoTarget[index].get() % 2 != 0)
ParamStatic::opAmplitudeMod[(ParamStatic::lfoTarget[index].get() / 2)] = ((1.0f + lfoValue) / 2.0f);
if(thisLfo->target % 2 != 0)
operators[(thisLfo->target / 2)]->setAM((1.0f + lfoValue) / 2.0f);
else
{
auto targetOp = ParamStatic::lfoTarget[index].get() / 2;
operators[targetOp - 1]->modulateRatio(lfoValue, ParamStatic::lfoRatioMode[index].get());
auto targetOp = thisLfo->target / 2;
operators[targetOp - 1]->modulateRatio(lfoValue, thisLfo->ratioModType);
}
}
}
47 changes: 26 additions & 21 deletions Source/FmVoice.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class FmSound : public juce::SynthesiserSound
class FmVoice : public juce::SynthesiserVoice
{
public:
FmVoice(int numOperators, int index);
juce::AudioProcessorValueTreeState* tree;
FmVoice(int numOperators, int index, juce::AudioProcessorValueTreeState* t);
~FmVoice()
{
printf("Voice #: %d -- %d total jumps\n", voiceIndex, numJumps);
Expand Down Expand Up @@ -70,22 +71,6 @@ class FmVoice : public juce::SynthesiserVoice
if(velocity == 0)
clearCurrentNote();
}
void updateLfoTarget(std::atomic<float>* value, int lfo)
{
lfoBank[lfo]->currentTarget = *value;
}
void updateLfoRate(std::atomic<float>* value, int lfo)
{
lfoBank[lfo]->currentRate = *value;
}
void updateLfoWave(std::atomic<float>* value, int lfo)
{
lfoBank[lfo]->currentWaveType = *value;
}
void updateLfoLevel(std::atomic<float>* value, int lfo)
{
lfoBank[lfo]->currentLevel = *value;
}
void applyLfo(int index);
void setRoutingFromGrid(juce::AudioProcessorValueTreeState* pTree, std::vector<std::vector<juce::String>> grid);
void setSampleRate(double newRate)
Expand All @@ -109,8 +94,12 @@ class FmVoice : public juce::SynthesiserVoice
{
setSampleRate(newRate);
}
float getValue(juce::String str)
{
return *tree->getRawParameterValue(str);
}
void updateParams();
int voiceIndex;
std::vector<std::vector<int>> routingParams;
int numJumps;
int operatorCount;
float fundamental;
Expand All @@ -125,29 +114,45 @@ class FmVoice : public juce::SynthesiserVoice
float lfoValue;
float lfoMax;
float lfoMin;
private:
int op1Index, op2Index;
juce::String opRoutingIds[TOTAL_OPERATORS][TOTAL_OPERATORS];
juce::String opAudibleIds[TOTAL_OPERATORS];
int opRouting[TOTAL_OPERATORS][TOTAL_OPERATORS];
int opAudible[TOTAL_OPERATORS];
};


class FmSynth : public juce::Synthesiser
{
public:
FmSynth(int operators, int lfos, int numVoices) : juce::Synthesiser(), numOperators(operators), numLfos(lfos)
juce::AudioProcessorValueTreeState* tree;
FmSynth(int operators, int lfos, int nVoices, juce::AudioProcessorValueTreeState* t) : juce::Synthesiser(), tree(t), numOperators(operators), numLfos(lfos), numVoices(nVoices)
{
for(int i = 0; i < numVoices; ++i)
{
addVoice(new FmVoice(numOperators, i));
addVoice(new FmVoice(numOperators, i, tree));
}
addSound(new FmSound());
}
FmVoice* getFmVoice(int i)
FmVoice* getFmVoice(int& i)
{
return dynamic_cast<FmVoice*>(voices.getUnchecked(i));
}
juce::OwnedArray<juce::SynthesiserVoice>* voiceArray()
{
return &voices;
}
void updateParams()
{
for(idx = 0; idx < numVoices; ++idx)
{
getFmVoice(idx)->updateParams();
}
}
private:
int idx;
int numOperators;
int numLfos;
int numVoices;
};

0 comments on commit 1bc0fde

Please sign in to comment.