10namespace tracktion {
inline namespace engine
16 inline float saturate (
float input,
float drive,
float lowclip,
float highclip)
19 return input - drive * input *
std::fabs (input);
22 inline void distortion (
float* data,
int count,
float drive,
float lowclip,
float highclip)
27 float gain = drive < 0.5f ? 2.0f * drive + 1.0f : drive * 4.0f;
31 *
data = saturate (*data, drive, lowclip, highclip) * gain;
37inline void clip (
float* data,
int numSamples)
39 while (--numSamples >= 0)
50 FODelayLine (
float maximumDelay = 0.001f,
float sr = 44100.0f)
52 resize (maximumDelay, sr);
55 void resize (
float maximumDelay,
float sr)
58 numSamples = (
int)
std::ceil (maximumDelay * sampleRate);
59 sampleBuffer.
resize ((
size_t) numSamples);
60 const auto num = (
size_t) numSamples;
61 memset (sampleBuffer.
data(), 0,
sizeof(
float) * num);
67 const auto num = (
size_t) numSamples;
68 memset (sampleBuffer.
data(), 0,
sizeof(
float) * num);
71 inline float samplesToSeconds (
float numSamplesIn,
float sampleRateIn)
73 return numSamplesIn / sampleRateIn;
76 inline float read (
float atTime)
78 jassert (atTime >= 0.0f && atTime < samplesToSeconds (
float (numSamples), sampleRate));
80 float pos =
std::max (1.0f, atTime * (sampleRate - 1));
83 float f = pos - intPos;
85 int n1 = currentPos - intPos;
88 while (n1 >= numSamples)
95 jassert (n1 >= 0 && n1 < numSamples);
96 jassert (n2 >= 0 && n2 < numSamples);
98 return (1.0f - f) * sampleBuffer[(
size_t) n1] + f * sampleBuffer[(
size_t) n2];
101 inline void write (
const float input)
103 sampleBuffer[(
size_t) currentPos] = input;
106 if (currentPos >= numSamples)
112 float sampleRate {44100};
131 juce::FloatVectorOperations::copy (lWork, lOut, numSamples);
132 juce::FloatVectorOperations::copy (rWork, rOut, numSamples);
134 for (
int i = 0; i < numSamples; i++)
136 const float lVal = leftDelay.read (delay);
137 const float rVal = rightDelay.read (delay);
139 leftDelay.write (lWork[i] + (feedback * lVal) + (crossfeed * rVal));
140 rightDelay.write (rWork[i] + (feedback * rVal) + (crossfeed * lVal));
147 for (
int i = 0; i < numSamples; i++)
151 lOut[i] = (wetDry.gain2 * lOut[i]) + (wetDry.gain1 * lWork[i]);
152 rOut[i] = (wetDry.gain2 * rOut[i]) + (wetDry.gain1 * rWork[i]);
156 void setSampleRate (
double sr)
158 leftDelay.resize (5.1f,
float (sr));
159 rightDelay.resize (5.1f,
float (sr));
162 void setParams (
float delayIn,
float feedbackIn,
float crossfeedIn,
float mixIn)
165 feedback =
std::min (0.99f, feedbackIn);
166 crossfeed =
std::min (0.99f, crossfeedIn);
179 float mix = 0, feedback = 0, delay = 0, crossfeed = 0;
191 const float delayMs = 20.0f;
192 const float minSweepSamples = (
float) ((delayMs * sampleRate) / 1000.0);
193 const float maxSweepSamples = (
float) (((delayMs + depthMs) * sampleRate) / 1000.0);
196 const int lengthInSamples =
juce::roundToInt ((maxLengthMs * sampleRate) / 1000.0);
198 delayBuffer.ensureMaxBufferSize (lengthInSamples);
200 const float lfoFactor = 0.5f * (maxSweepSamples - minSweepSamples);
201 const float lfoOffset = minSweepSamples + lfoFactor;
208 float*
const buf = (
float*) delayBuffer.buffers[chan].
getData();
214 bufPos = delayBuffer.bufferPos;
216 for (
int i = 0; i < numSamples; ++i)
218 const float in = d[i];
220 const float sweep = lfoOffset + lfoFactor *
sinf (ph);
224 const float interp = sweep - intSweepPos;
225 intSweepPos = bufPos + lengthInSamples - intSweepPos;
227 const float out = buf[(intSweepPos - 1) % lengthInSamples] * interp + buf[intSweepPos % lengthInSamples] * (1.0f - interp);
234 d[i] = out * wetDry.gain1 + in * wetDry.gain2;
235 bufPos = (bufPos + 1) % lengthInSamples;
239 jassert (! hasFloatingPointDenormaliseOccurred());
240 zeroDenormalisedValuesIfNeeded (buffer);
246 delayBuffer.bufferPos = bufPos;
249 void setSampleRate (
double sr)
253 const float delayMs = 20.0f;
256 delayBuffer.ensureMaxBufferSize (bufferSizeSamples);
257 delayBuffer.clearBuffer();
261 void setParams (
float speedIn,
float depthIn,
float widthIn,
float mixIn)
271 delayBuffer.clearBuffer();
276 double sampleRate = 0;
278 float phase = 0, speedHz = 1.0f, depthMs = 3.0f, width = 0.5f, mix = 0;
287 for (
auto p : synth.getAutomatableParameters())
291 void noteStarted()
override
295 if (synth.isLegato())
297 activeNote.setTargetValue (currentlyPlayingNote.initialNote);
313 activeNote.setCurrentAndTargetValue (currentlyPlayingNote.initialNote);
341 for (
auto& o : oscillators)
344 filterFrequencySmoother.snapToValue();
350 void noteStopped (
bool allowTailOff)
override
355 filterAdsr.noteOff();
371 void setCurrentSampleRate (
double newRate)
override
375 MPESynthesiserVoice::setCurrentSampleRate (newRate);
377 for (
auto& o : oscillators)
378 o.setSampleRate (newRate);
380 ampAdsr.setSampleRate (newRate);
381 filterAdsr.setSampleRate (newRate);
382 modAdsr1.setSampleRate (newRate);
383 modAdsr2.setSampleRate (newRate);
384 lfo1.setSampleRate (newRate);
385 lfo2.setSampleRate (newRate);
387 lastLegato = paramValue (synth.legato);
388 activeNote.reset (newRate, paramValue (synth.legato) / 1000.0f);
389 filterFrequencySmoother.reset (newRate, 0.05f);
391 for (
auto& itr : smoothers)
392 itr.second.reset (newRate, 0.01f);
396 float velocityToGain (
float velocity,
float velocitySensitivity = 1.0f)
398 float v = velocity * velocitySensitivity + 1.0f - velocitySensitivity;
399 return v *
std::pow (25.0f, v) * 0.04f;
402 using MPESynthesiserVoice::renderNextBlock;
407 updateParams (numSamples);
411 filterFrequencySmoother.snapToValue();
416 renderBuffer.
setSize (2, numSamples,
false,
false,
true);
418 renderBuffer.
clear();
421 for (
auto& o : oscillators)
422 o.process (renderBuffer, 0, numSamples);
425 float velocityGain = velocityToGain (currentlyPlayingNote.noteOnVelocity.asUnsignedFloat(), paramValue (synth.ampVelocity) / 100.0f);
430 if (synth.filterTypeValue != 0)
435 if (synth.filterSlopeValue == 24)
451 outputBuffer.
addFrom (0, startSample, renderBuffer, 0, 0, numSamples, 0.5f);
452 outputBuffer.
addFrom (0, startSample, renderBuffer, 1, 0, numSamples, 0.5f);
456 outputBuffer.
addFrom (0, startSample, renderBuffer, 0, 0, numSamples);
457 outputBuffer.
addFrom (1, startSample, renderBuffer, 1, 0, numSamples);
475 for (
auto& itr : smoothers)
476 itr.second.process (numSamples);
484 while (--numSamples >= 0)
497 positions.
add (param->valueRange.convertTo0to1 (paramValue (param)));
503 positions.
add ((12.0f *
std::log2 (lastFilterFreq / 440.0f) + 69.0f) / 135.076232f);
506 void updateParams (
int numSamples)
509 currentModValue[(
int)FourOscPlugin::lfo1] = lfo1.getCurrentValue();
510 currentModValue[(
int)FourOscPlugin::lfo2] = lfo2.getCurrentValue();
511 currentModValue[(
int)FourOscPlugin::env1] = modAdsr1.getEnvelopeValue();
512 currentModValue[(
int)FourOscPlugin::env2] = modAdsr2.getEnvelopeValue();
514 currentModValue[FourOscPlugin::mpePressure] = currentlyPlayingNote.pressure.asUnsignedFloat();
515 currentModValue[FourOscPlugin::mpeTimbre] = currentlyPlayingNote.timbre.asUnsignedFloat();
516 currentModValue[FourOscPlugin::midiNoteNum] = currentlyPlayingNote.initialNote / 127.0f;
517 currentModValue[FourOscPlugin::midiVelocity] = currentlyPlayingNote.noteOnVelocity.asUnsignedFloat();
519 for (
int i = 0; i <= 127; i++)
520 currentModValue[FourOscPlugin::ccBankSelect + i] = synth.controllerValues[i];
523 lfo1.process (numSamples);
524 lfo2.process (numSamples);
525 for (
int i = 0; i < numSamples; i++)
533 paramValue (synth.modEnvParams[0]->modAttack),
534 paramValue (synth.modEnvParams[0]->modDecay),
535 paramValue (synth.modEnvParams[0]->modSustain) / 100.0f,
536 paramValue (synth.modEnvParams[0]->modRelease),
540 paramValue (synth.modEnvParams[1]->modAttack),
541 paramValue (synth.modEnvParams[1]->modDecay),
542 paramValue (synth.modEnvParams[1]->modSustain) / 100.0f,
543 paramValue (synth.modEnvParams[1]->modRelease),
547 if (synth.lfoParams[0]->syncValue)
548 lfoFreq1 = 1.0f / ((synth.lfoParams[0]->beatValue.get()) / (synth.getCurrentTempo() / 60.0f));
550 lfoFreq1 = paramValue (synth.lfoParams[0]->rate);
552 lfo1.setParameters ({
556 paramValue (synth.lfoParams[0]->depth),
557 (SimpleLFO::WaveShape) synth.lfoParams[0]->waveShapeValue.get(),
562 if (synth.lfoParams[1]->syncValue)
563 lfoFreq2 = 1.0f / ((synth.lfoParams[1]->beatValue.get()) / (synth.getCurrentTempo() / 60.0f));
565 lfoFreq2 = paramValue (synth.lfoParams[1]->rate);
567 lfo2.setParameters ({
571 paramValue (synth.lfoParams[1]->depth) / 2,
572 (SimpleLFO::WaveShape) synth.lfoParams[1]->waveShapeValue.get(),
577 ampAdsr.setAnalog (synth.ampAnalogValue);
580 paramValue (synth.ampAttack),
581 paramValue (synth.ampDecay),
582 paramValue (synth.ampSustain) / 100.0f,
583 isQuickStop ?
std::min (0.01f, paramValue (synth.ampRelease))
584 : paramValue (synth.ampRelease)
589 paramValue (synth.filterAttack),
590 paramValue (synth.filterDecay),
591 paramValue (synth.filterSustain) / 100.0f,
592 paramValue (synth.filterRelease)
595 int type = synth.filterTypeValue;
596 float filterEnv = filterAdsr.getEnvelopeValue();
597 float filterSens = paramValue (synth.filterVelocity) / 100.0f;
598 filterSens = currentlyPlayingNote.noteOnVelocity.asUnsignedFloat() * filterSens + 1.0f - filterSens;
599 filterEnv *= filterSens;
601 for (
int i = 0; i < numSamples; i++)
604 auto getMidiNoteInHertz = [](
float noteNumber)
606 return 440.0f *
std::pow (2.0f, (noteNumber - 69) / 12.0f);
609 float freqNote = paramValue (synth.filterFreq);
610 freqNote += (currentlyPlayingNote.initialNote - 60) * paramValue (synth.filterKey) / 100.0f;
611 freqNote += filterEnv * (paramValue (synth.filterAmount) * 137);
613 filterFrequencySmoother.setValue (freqNote / 135.076232f);
615 filterFrequencySmoother.snapToValue();
617 freqNote = filterFrequencySmoother.getCurrentValue() * 135.076232f;
618 filterFrequencySmoother.process (numSamples);
621 std::min (20000.0f,
float (currentSampleRate) / 2.0f),
622 getMidiNoteInHertz (freqNote));
624 float q = 0.70710678118655f / (1.0f - (paramValue (synth.filterResonance) / 100.0f) * 0.99f);
659 double activeNoteSmoothed = activeNote.getNextValue();
660 activeNote.skip (numSamples);
663 for (
auto& o : oscillators)
665 double note = activeNoteSmoothed + currentlyPlayingNote.totalPitchbendInSemitones;
667 + paramValue (synth.oscParams[idx]->fineTune) / 100.0;
669 o.setNote (
float (note));
671 o.setWave ((Oscillator::Waves)(
int (synth.oscParams[idx]->waveShapeValue.get())));
672 o.setPulseWidth (paramValue (synth.oscParams[idx]->pulseWidth));
673 o.setNumVoices (synth.oscParams[idx]->voicesValue);
674 o.setDetune (paramValue (synth.oscParams[idx]->detune));
675 o.setSpread (paramValue (synth.oscParams[idx]->spread) / 100.0f);
676 o.setPan (paramValue (synth.oscParams[idx]->pan));
681 if (lastLegato != paramValue (synth.legato) && ! activeNote.isSmoothing())
683 lastLegato = paramValue (synth.legato);
684 activeNote.reset (currentSampleRate, lastLegato / 1000.0f);
688 void notePressureChanged()
override {}
689 void notePitchbendChanged()
override {}
690 void noteTimbreChanged()
override {}
691 void noteKeyStateChanged()
override {}
697 if (param ==
nullptr)
700 auto smoothItr = smoothers.find (param.get());
701 if (smoothItr == smoothers.end())
702 return param->getCurrentValue();
704 auto modItr = synth.modMatrix.find (param.get());
705 if (modItr == synth.modMatrix.end() || ! modItr->second.isModulated())
707 smoothItr->second.setValue (param->getCurrentNormalisedValue());
710 smoothItr->second.snapToValue();
712 return param->valueRange.convertFrom0to1 (smoothItr->second.getCurrentValue());
716 float val = param->getCurrentNormalisedValue();
718 auto& mod = modItr->second;
722 float d = mod.depths[i];
725 val += currentModValue[i] * d;
730 smoothItr->second.setValue (val);
733 smoothItr->second.snapToValue();
735 return param->valueRange.convertFrom0to1 (smoothItr->second.getCurrentValue());
750 bool retrigger =
false, isPlaying =
false, isQuickStop =
false, snapAllValues =
false, firstBlock =
false;
751 juce::LinearSmoothedValue<float> activeNote;
752 float lastLegato = -1.0f, lastFilterFreq = 0;
754 float currentModValue[FourOscPlugin::numModSources] = {0};
760FourOscPlugin::OscParams::OscParams (
FourOscPlugin& plugin,
int oscNum)
762 auto um = plugin.getUndoManager();
769 waveShapeValue.
referTo (plugin.state, oscID (IDs::waveShape, oscNum), um, oscNum == 1 ? 1 : 0);
770 tuneValue.
referTo (plugin.state, oscID (IDs::tune, oscNum), um, 0);
771 fineTuneValue.
referTo (plugin.state, oscID (IDs::fineTune, oscNum), um, 0);
772 levelValue.
referTo (plugin.state, oscID (IDs::level, oscNum), um, 0);
773 pulseWidthValue.
referTo (plugin.state, oscID (IDs::pulseWidth, oscNum), um, 0.5);
774 voicesValue.
referTo (plugin.state, oscID (IDs::voices, oscNum), um, 1);
775 detuneValue.
referTo (plugin.state, oscID (IDs::detune, oscNum), um, 0);
776 spreadValue.
referTo (plugin.state, oscID (IDs::spread, oscNum), um, 0);
777 panValue.
referTo (plugin.state, oscID (IDs::pan, oscNum), um, 0);
784 tune = plugin.addParam (paramID (IDs::tune, oscNum),
TRANS(
"Tune") +
" " +
juce::String (oscNum), {-36.0f, 36.0f, 1.0f},
"st");
785 fineTune = plugin.addParam (paramID (IDs::fineTune, oscNum),
TRANS(
"Fine Tune") +
" " +
juce::String (oscNum), {-100.0f, 100.0f});
786 level = plugin.addParam (paramID (IDs::level, oscNum),
TRANS(
"Level") +
" " +
juce::String (oscNum), {-100.0f, 0.0f, 0.0f, 4.0f},
"dB");
787 pulseWidth = plugin.addParam (paramID (IDs::pulseWidth, oscNum),
TRANS(
"Pulse Width") +
" " +
juce::String (oscNum), {0.01f, 0.99f});
788 detune = plugin.addParam (paramID (IDs::detune, oscNum),
TRANS(
"Detune") +
" " +
juce::String (oscNum), {0.0f, 0.5f});
789 spread = plugin.addParam (paramID (IDs::spread, oscNum),
TRANS(
"Spread") +
" " +
juce::String (oscNum), {-100.0f, 100.0f},
"%");
790 pan = plugin.addParam (paramID (IDs::pan, oscNum),
TRANS(
"Pan") +
" " +
juce::String (oscNum), {-1.0f, 1.0f});
793void FourOscPlugin::OscParams::attach()
795 tune->attachToCurrentValue (tuneValue);
796 fineTune->attachToCurrentValue (fineTuneValue);
797 level->attachToCurrentValue (levelValue);
798 pulseWidth->attachToCurrentValue (pulseWidthValue);
799 detune->attachToCurrentValue (detuneValue);
800 spread->attachToCurrentValue (spreadValue);
801 pan->attachToCurrentValue (panValue);
804void FourOscPlugin::OscParams::detach()
806 tune->detachFromCurrentValue();
807 fineTune->detachFromCurrentValue();
808 level->detachFromCurrentValue();
809 pulseWidth->detachFromCurrentValue();
810 detune->detachFromCurrentValue();
811 spread->detachFromCurrentValue();
812 pan->detachFromCurrentValue();
816FourOscPlugin::LFOParams::LFOParams (FourOscPlugin& plugin,
int lfoNum)
818 auto um = plugin.getUndoManager();
825 waveShapeValue.referTo (plugin.state, lfoID (IDs::lfoWaveShape, lfoNum), um, lfoNum == 1 ? 1 : 0);
826 syncValue.referTo (plugin.state, lfoID (IDs::lfoSync, lfoNum), um,
false);
827 rateValue.referTo (plugin.state, lfoID (IDs::lfoRate, lfoNum), um, 1);
828 depthValue.referTo (plugin.state, lfoID (IDs::lfoDepth, lfoNum), um, 1.0f);
829 beatValue.referTo (plugin.state, lfoID (IDs::lfoBeat, lfoNum), um, 1);
836 rate = plugin.addParam (paramID (IDs::lfoRate, lfoNum),
TRANS(
"Rate") +
" " +
juce::String (lfoNum), {0.0f, 500.0f, 0.0f, 0.3f},
"Hz");
837 depth = plugin.addParam (paramID (IDs::lfoDepth, lfoNum),
TRANS(
"Depth") +
" " +
juce::String (lfoNum), {0.0f, 1.0f});
840void FourOscPlugin::LFOParams::attach()
842 depth->attachToCurrentValue (depthValue);
843 rate->attachToCurrentValue (rateValue);
846void FourOscPlugin::LFOParams::detach()
848 depth->detachFromCurrentValue();
849 rate->detachFromCurrentValue();
853FourOscPlugin::MODEnvParams::MODEnvParams (FourOscPlugin& plugin,
int modNum)
855 auto um = plugin.getUndoManager();
862 modAttackValue.referTo (plugin.state, modID (IDs::modAttack, modNum), um, 0.1f);
863 modDecayValue.referTo (plugin.state, modID (IDs::modDecay, modNum), um, 0.1f);
864 modSustainValue.referTo (plugin.state, modID (IDs::modSustain, modNum), um, 80.0f);
865 modReleaseValue.referTo (plugin.state, modID (IDs::modRelease, modNum), um, 0.1f);
872 modAttack = plugin.addParam (paramID (IDs::modAttack, modNum),
TRANS(
"Mod Attack") +
" " +
juce::String (modNum), {0.0f, 60.0f, 0.0f, 0.2f});
873 modDecay = plugin.addParam (paramID (IDs::modDecay, modNum),
TRANS(
"Mod Decay") +
" " +
juce::String (modNum), {0.0f, 60.0f, 0.0f, 0.2f});
874 modSustain = plugin.addParam (paramID (IDs::modSustain, modNum),
TRANS(
"Mod Sustain") +
" " +
juce::String (modNum), {0.0f, 100.0f},
"%");
875 modRelease = plugin.addParam (paramID (IDs::modRelease, modNum),
TRANS(
"Mod Release") +
" " +
juce::String (modNum), {0.001f, 60.0f, 0.0f, 0.2f});
878void FourOscPlugin::MODEnvParams::attach()
880 modAttack->attachToCurrentValue (modAttackValue);
881 modDecay->attachToCurrentValue (modDecayValue);
882 modSustain->attachToCurrentValue (modSustainValue);
883 modRelease->attachToCurrentValue (modReleaseValue);
886void FourOscPlugin::MODEnvParams::detach()
888 modAttack->detachFromCurrentValue();
889 modDecay->detachFromCurrentValue();
890 modSustain->detachFromCurrentValue();
891 modRelease->detachFromCurrentValue();
895FourOscPlugin::FourOscPlugin (PluginCreationInfo info) : Plugin (info)
897 auto um = getUndoManager();
899 levelMeasurer.addClient (*
this);
901 instrument.enableLegacyMode();
902 setPitchbendTrackingMode (juce::MPEInstrument::allNotesOnChannel);
904 setVoiceStealingEnabled (
true);
909 for (
int i = 0; i < 4; i++) oscParams.add (
new OscParams (*
this, i + 1));
910 for (
int i = 0; i < 2; i++) lfoParams.add (
new LFOParams (*
this, i + 1));
911 for (
int i = 0; i < 2; i++) modEnvParams.add (
new MODEnvParams (*
this, i + 1));
914 ampAttackValue.referTo (state, IDs::ampAttack, um, 0.1f);
915 ampDecayValue.referTo (state, IDs::ampDecay, um, 0.1f);
916 ampSustainValue.referTo (state, IDs::ampSustain, um, 80.0f);
917 ampReleaseValue.referTo (state, IDs::ampRelease, um, 0.1f);
918 ampVelocityValue.referTo (state, IDs::ampVelocity, um, 100.0f);
919 ampAnalogValue.referTo (state, IDs::ampAnalog, um,
true);
921 ampAttack = addParam (
"ampAttack",
TRANS(
"Amp Attack"), {0.001f, 60.0f, 0.0f, 0.2f});
922 ampDecay = addParam (
"ampDecay",
TRANS(
"Amp Decay"), {0.001f, 60.0f, 0.0f, 0.2f});
923 ampSustain = addParam (
"ampSustain",
TRANS(
"Amp Sustain"), {0.0f, 100.0f},
"%");
924 ampRelease = addParam (
"ampRelease",
TRANS(
"Amp Release"), {0.001f, 60.0f, 0.0f, 0.2f});
925 ampVelocity = addParam (
"ampVelocity",
TRANS(
"Amp Velocity"), {0.0f, 100.0f},
"%");
927 ampAttack->attachToCurrentValue (ampAttackValue);
928 ampDecay->attachToCurrentValue (ampDecayValue);
929 ampSustain->attachToCurrentValue (ampSustainValue);
930 ampRelease->attachToCurrentValue (ampReleaseValue);
931 ampVelocity->attachToCurrentValue (ampVelocityValue);
934 filterAttackValue.referTo (state, IDs::filterAttack, um, 0.1f);
935 filterDecayValue.referTo (state, IDs::filterDecay, um, 0.1f);
936 filterSustainValue.referTo (state, IDs::filterSustain, um, 80.0f);
937 filterReleaseValue.referTo (state, IDs::filterRelease, um, 0.1f);
938 filterFreqValue.referTo (state, IDs::filterFreq, um, 69.0f);
939 filterResonanceValue.referTo (state, IDs::filterResonance, um, 0.5f);
940 filterAmountValue.referTo (state, IDs::filterAmount, um, 0.0f);
941 filterKeyValue.referTo (state, IDs::filterKey, um, 0.0f);
942 filterVelocityValue.referTo (state, IDs::filterVelocity, um, 0.0f);
943 filterTypeValue.referTo (state, IDs::filterType, um, 0);
944 filterSlopeValue.referTo (state, IDs::filterSlope, um, 12);
946 filterAttack = addParam (
"filterAttack",
TRANS(
"Filter Attack"), {0.0f, 60.0f, 0.0f, 0.2f});
947 filterDecay = addParam (
"filterDecay",
TRANS(
"Filter Decay"), {0.0f, 60.0f, 0.0f, 0.2f});
948 filterSustain = addParam (
"filterSustain",
TRANS(
"Filter Sustain"), {0.0f, 100.0f},
"%");
949 filterRelease = addParam (
"filterRelease",
TRANS(
"Filter Release"), {0.0f, 60.0f, 0.0f, 0.2f});
950 filterFreq = addParam (
"filterFreq",
TRANS(
"Filter Freq"), {0.0f, 135.076232f});
951 filterResonance = addParam (
"filterResonance",
TRANS(
"Filter Resonance"), {0.0f, 100.0f},
"%");
952 filterAmount = addParam (
"filterAmount",
TRANS(
"Filter Amount"), {-1.0f, 1.0f});
953 filterKey = addParam (
"filterKey",
TRANS(
"Filter Key"), {0.0f, 100.0f},
"%");
954 filterVelocity = addParam (
"filterVelocity",
TRANS(
"Filter Velocity"), {0.0f, 100.0f},
"%");
956 filterAttack->attachToCurrentValue (filterAttackValue);
957 filterDecay->attachToCurrentValue (filterDecayValue);
958 filterSustain->attachToCurrentValue (filterSustainValue);
959 filterRelease->attachToCurrentValue (filterReleaseValue);
960 filterFreq->attachToCurrentValue (filterFreqValue);
961 filterResonance->attachToCurrentValue (filterResonanceValue);
962 filterAmount->attachToCurrentValue (filterAmountValue);
963 filterKey->attachToCurrentValue (filterKeyValue);
964 filterVelocity->attachToCurrentValue (filterVelocityValue);
967 for (
auto p : getAutomatableParameters())
968 modMatrix[p] = ModAssign();
971 distortionOnValue.referTo (state, IDs::distortionOn, um);
972 distortionValue.referTo (state, IDs::distortion, um, 0.0f);
974 distortion = addParam (
"distortion",
TRANS(
"Distortion"), {0.0f, 1.0f});
976 distortion->attachToCurrentValue (distortionValue);
979 reverbOnValue.referTo (state, IDs::reverbOn, um);
980 reverbSizeValue.referTo (state, IDs::reverbSize, um, 0.0f);
981 reverbDampingValue.referTo (state, IDs::reverbDamping, um, 0.0f);
982 reverbWidthValue.referTo (state, IDs::reverbWidth, um, 0.0f);
983 reverbMixValue.referTo (state, IDs::reverbMix, um, 0.0);
985 reverbSize = addParam (
"reverbSize",
TRANS(
"Size"), {0.0f, 1.0f});
986 reverbDamping = addParam (
"reverbDamping",
TRANS(
"Damping"), {0.0f, 1.0f});
987 reverbWidth = addParam (
"reverbWidth",
TRANS(
"Width"), {0.0f, 1.0f});
988 reverbMix = addParam (
"reverbMix",
TRANS(
"Mix"), {0.0f, 1.0f});
990 reverbSize->attachToCurrentValue (reverbSizeValue);
991 reverbDamping->attachToCurrentValue (reverbDampingValue);
992 reverbWidth->attachToCurrentValue (reverbWidthValue);
993 reverbMix->attachToCurrentValue (reverbMixValue);
996 delayOnValue.referTo (state, IDs::delayOn, um);
997 delayFeedbackValue.referTo (state, IDs::delayFeedback, um, -10.0f);
998 delayCrossfeedValue.referTo (state, IDs::delayCrossfeed, um, -100.0f);
999 delayMixValue.referTo (state, IDs::delayMix, um, 0.0f);
1000 delayValue.referTo (state, IDs::delay, um, 1.0f);
1002 delayFeedback = addParam (
"delayFeedback",
TRANS(
"Feedback"), {-100.0f, 0.0f, 0.0f, 4.0f},
"dB");
1003 delayCrossfeed = addParam (
"delayCrossfeed",
TRANS(
"Crossfeed"), {-100.0f, 0.0f, 0.0f, 4.0f},
"dB");
1004 delayMix = addParam (
"delayMix",
TRANS(
"Mix"), {0.0f, 1.0f});
1006 delayFeedback->attachToCurrentValue (delayFeedbackValue);
1007 delayCrossfeed->attachToCurrentValue (delayCrossfeedValue);
1008 delayMix->attachToCurrentValue (delayMixValue);
1011 chorusOnValue.referTo (state, IDs::chorusOn, um);
1012 chorusSpeedValue.referTo (state, IDs::chosusSpeed, um, 1.0f);
1013 chorusDepthValue.referTo (state, IDs::chorusDepth, um, 3.0f);
1014 chorusWidthValue.referTo (state, IDs::chrousWidth, um, 0.5f);
1015 chorusMixValue.referTo (state, IDs::chorusMix, um, 0.0f);
1017 chorusSpeed = addParam (
"chorusSpeed",
TRANS(
"Speed"), {0.1f, 10.0f},
"Hz");
1018 chorusDepth = addParam (
"chorusDepth",
TRANS(
"Depth"), {0.1f, 20.0f},
"ms");
1019 chorusWidth = addParam (
"chorusWidth",
TRANS(
"Width"), {0.0f, 1.0f});
1020 chorusMix = addParam (
"chorusMix",
TRANS(
"Mix"), {0.0f, 1.0f});
1022 chorusSpeed->attachToCurrentValue (chorusSpeedValue);
1023 chorusDepth->attachToCurrentValue (chorusDepthValue);
1024 chorusWidth->attachToCurrentValue (chorusWidthValue);
1025 chorusMix->attachToCurrentValue (chorusMixValue);
1028 voiceModeValue.referTo (state, IDs::voiceMode, um, 2);
1029 voicesValue.referTo (state, IDs::voices, um, 32);
1030 legatoValue.referTo (state, IDs::legato, um, 0);
1031 masterLevelValue.referTo (state, IDs::masterLevel, um, 0);
1033 legato = addParam (
"legato",
TRANS(
"Legato"), {0.0f, 500.0f},
"ms");
1034 masterLevel = addParam (
"masterLevel",
TRANS(
"Level"), {-100.0f, 0.0f, 0.0f, 4.0f});
1036 legato->attachToCurrentValue (legatoValue);
1037 masterLevel->attachToCurrentValue (masterLevelValue);
1040 for (
auto o : oscParams)
1044 for (
auto l : lfoParams)
1047 for (
auto e : modEnvParams)
1050 for (
auto p : getAutomatableParameters())
1054 setupTextFunctions();
1056 valueTreePropertyChanged (state, IDs::voiceMode);
1057 valueTreePropertyChanged (state, IDs::mpe);
1062FourOscPlugin::~FourOscPlugin()
1064 notifyListenersOfDeletion();
1067 for (
auto o : oscParams)
1071 for (
auto l : lfoParams)
1074 for (
auto e : modEnvParams)
1078 ampAttack->detachFromCurrentValue();
1079 ampDecay->detachFromCurrentValue();
1080 ampSustain->detachFromCurrentValue();
1081 ampRelease->detachFromCurrentValue();
1082 ampVelocity->detachFromCurrentValue();
1085 filterAttack->detachFromCurrentValue();
1086 filterDecay->detachFromCurrentValue();
1087 filterSustain->detachFromCurrentValue();
1088 filterRelease->detachFromCurrentValue();
1089 filterFreq->detachFromCurrentValue();
1090 filterResonance->detachFromCurrentValue();
1091 filterAmount->detachFromCurrentValue();
1092 filterKey->detachFromCurrentValue();
1093 filterVelocity->detachFromCurrentValue();
1096 distortion->detachFromCurrentValue();
1099 reverbSize->detachFromCurrentValue();
1100 reverbDamping->detachFromCurrentValue();
1101 reverbWidth->detachFromCurrentValue();
1102 reverbMix->detachFromCurrentValue();
1105 delayFeedback->detachFromCurrentValue();
1106 delayCrossfeed->detachFromCurrentValue();
1107 delayMix->detachFromCurrentValue();
1110 chorusSpeed->detachFromCurrentValue();
1111 chorusDepth->detachFromCurrentValue();
1112 chorusWidth->detachFromCurrentValue();
1113 chorusMix->detachFromCurrentValue();
1116 legato->detachFromCurrentValue();
1117 masterLevel->detachFromCurrentValue();
1120const char* FourOscPlugin::xmlTypeName =
"4osc";
1124 auto p = Plugin::addParam (paramID, name, valueRange);
1127 labels[paramID] = label;
1132void FourOscPlugin::setupTextFunctions()
1135 for (
auto p : getAutomatableParameters())
1138 auto itr = labels.
find (p->paramID);
1139 if (itr != labels.
end())
1140 label = itr->second;
1142 auto basicValueToTextFunction = [label] (
float value)
1145 float v = std::abs (value);
1161 p->valueToStringFunction = basicValueToTextFunction;
1164 auto timeValueToTextFunction = [] (
float value)
1171 auto panValueToTextFunction = [] (
float value)
1178 auto percentValueToTextFunction = [] (
float value)
1183 auto tuneValueToTextFunction = [] (
float value)
1188 auto freqValueToTextFunction = [] (
float value)
1190 float freq = 440.0f *
std::pow (2.0f, (value - 69) / 12.0f);
1197 return 12.0f *
std::log2 (freq / 440.0f) + 69.0f;
1206 for (
auto p : oscParams)
1208 p->pulseWidth->valueToStringFunction = percentValueToTextFunction;
1209 p->tune->valueToStringFunction = tuneValueToTextFunction;
1210 p->detune->valueToStringFunction = percentValueToTextFunction;
1211 p->pan->valueToStringFunction = panValueToTextFunction;
1214 for (
auto p : lfoParams)
1216 p->depth->valueToStringFunction = percentValueToTextFunction;
1219 for (
auto p : modEnvParams)
1221 p->modAttack->valueToStringFunction = timeValueToTextFunction;
1222 p->modAttack->stringToValueFunction = textToTimeValueFunction;
1223 p->modDecay->valueToStringFunction = timeValueToTextFunction;
1224 p->modDecay->stringToValueFunction = textToTimeValueFunction;
1225 p->modRelease->valueToStringFunction = timeValueToTextFunction;
1226 p->modRelease->stringToValueFunction = textToTimeValueFunction;
1229 ampAttack->valueToStringFunction = timeValueToTextFunction;
1230 ampAttack->stringToValueFunction = textToTimeValueFunction;
1231 ampDecay->valueToStringFunction = timeValueToTextFunction;
1232 ampDecay->stringToValueFunction = textToTimeValueFunction;
1233 ampRelease->valueToStringFunction = timeValueToTextFunction;
1234 ampRelease->stringToValueFunction = textToTimeValueFunction;
1236 filterAttack->valueToStringFunction = timeValueToTextFunction;
1237 filterAttack->stringToValueFunction = textToTimeValueFunction;
1238 filterDecay->valueToStringFunction = timeValueToTextFunction;
1239 filterDecay->stringToValueFunction = textToTimeValueFunction;
1240 filterRelease->valueToStringFunction = timeValueToTextFunction;
1241 filterRelease->stringToValueFunction = textToTimeValueFunction;
1242 filterFreq->valueToStringFunction = freqValueToTextFunction;
1243 filterFreq->stringToValueFunction = textToFreqValueFunction;
1244 filterAmount->valueToStringFunction = percentValueToTextFunction;
1246 distortion->valueToStringFunction = percentValueToTextFunction;
1248 delayMix->valueToStringFunction = percentValueToTextFunction;
1250 chorusWidth->valueToStringFunction = percentValueToTextFunction;
1251 chorusMix->valueToStringFunction = percentValueToTextFunction;
1253 reverbSize->valueToStringFunction = percentValueToTextFunction;
1254 reverbWidth->valueToStringFunction = percentValueToTextFunction;
1255 reverbDamping->valueToStringFunction = percentValueToTextFunction;
1256 reverbMix->valueToStringFunction = percentValueToTextFunction;
1259float FourOscPlugin::getLevel (
int channel)
1261 auto& peak = levels[channel];
1264 float currentLevel = peak.dB - (48.0f * elapsedMilliseconds / 1000.0f);
1266 auto latest = getAndClearAudioLevel (channel);
1268 if (latest.dB > currentLevel)
1277void FourOscPlugin::valueTreeChanged()
1279 Plugin::valueTreeChanged();
1284 Plugin::valueTreePropertyChanged (v, i);
1286 if (v.hasType (IDs::PLUGIN))
1288 if (i == IDs::voiceMode
1289 || i == IDs::voices)
1292 if (voiceModeValue == 2)
1296 addVoice (
new FourOscVoice (*
this));
1301 addVoice (
new FourOscVoice (*
this));
1306 else if (i == IDs::mpe)
1308 if ((
bool) state[IDs::mpe])
1312 instrument.setZoneLayout (zones);
1317 instrument.enableLegacyMode();
1322 else if (v.hasType (IDs::MODMATRIX) || v.hasType (IDs::MODMATRIXITEM))
1324 if (! flushingState)
1331 Plugin::valueTreeChildAdded (v, c);
1333 if (c.hasType (IDs::MODMATRIX) || c.hasType (IDs::MODMATRIXITEM))
1334 if (! flushingState)
1340 Plugin::valueTreeChildRemoved (v, c, i);
1342 if (c.hasType (IDs::MODMATRIX) || c.hasType (IDs::MODMATRIXITEM))
1343 if (! flushingState)
1347void FourOscPlugin::handleController (
int,
int controllerNumber,
int controllerValue)
1349 controllerValues[controllerNumber] = controllerValue / 127.0f;
1352void FourOscPlugin::handleAsyncUpdate()
1357void FourOscPlugin::loadModMatrix()
1360 for (
auto& itr : modMatrix)
1361 for (
int s = lfo1; s < numModSources; s++)
1362 itr.second.depths[s] = -1000.0f;
1371 auto paramId = mmi.
getProperty (IDs::modParam).toString();
1372 auto src = idToModulationSource (mmi.getProperty (IDs::modItem).toString());
1373 float depth = (
float) mmi.getProperty (IDs::modDepth);
1377 if (
auto p = getAutomatableParameterByID (paramId))
1379 auto itr = modMatrix.find (p.get());
1380 if (itr != modMatrix.end())
1381 itr->second.depths[src] = depth;
1389 for (
auto& itr : modMatrix)
1390 itr.second.updateCachedInfo();
1393void FourOscPlugin::flushPluginStateToValueTree()
1397 auto um = getUndoManager();
1405 for (
const auto& itr : modMatrix)
1407 for (
int s = lfo1; s < numModSources; s++)
1409 if (itr.second.depths[s] >= -1.0f)
1412 mmi.setProperty (IDs::modParam, itr.first->paramID, um);
1413 mmi.setProperty (IDs::modItem, modulationSourceToID ((ModSource)s), um);
1414 mmi.setProperty (IDs::modDepth, itr.second.depths[s], um);
1416 mm.addChild (mmi, -1, um);
1423 Plugin::flushPluginStateToValueTree();
1431 delay->setSampleRate (info.sampleRate);
1432 chorus->setSampleRate (info.sampleRate);
1438 for (
auto& itr : smoothers)
1439 itr.second.reset (info.sampleRate, 0.01f);
1458 SCOPED_REALTIME_CHECK
1475 int thisBlock =
std::min (32, todo);
1485 int midiPos =
int (m.getTimeStamp());
1486 if (midiPos >= pos && midiPos < pos + thisBlock)
1487 midi.addEvent (m, midiPos - pos);
1503 levelMeasurer.processBuffer (workBuffer.
buffer, 0, thisBlock);
1516 updateParams (buffer);
1518 applyEffects (buffer);
1520 for (
auto& itr : smoothers)
1521 itr.second.process (buffer.getNumSamples());
1529 if (distortionOnValue)
1531 float drive = paramValue (distortion);
1532 float clip = 1.0f / (2.0f * drive);
1533 Distortion::distortion (buffer.
getWritePointer (0), numSamples, drive, -clip, clip);
1534 Distortion::distortion (buffer.
getWritePointer (1), numSamples, drive, -clip, clip);
1539 chorus->process (buffer, numSamples);
1543 delay->process (buffer, numSamples);
1558 AudioFadeCurve::CrossfadeLevels wetDry (paramValue (reverbMix));
1561 params.
roomSize = paramValue (reverbSize);
1562 params.
damping = paramValue (reverbDamping);
1563 params.
width = paramValue (reverbWidth);
1571 float delayTime = (delayValue.
get()) / (currentTempo / 60.0f);
1572 delay->setParams (delayTime,
1575 paramValue (delayMix));
1578 chorus->setParams (paramValue (chorusSpeed),
1579 paramValue (chorusDepth),
1580 paramValue (chorusWidth),
1581 paramValue (chorusMix));
1585void FourOscPlugin::restorePluginStateFromValueTree (
const juce::ValueTree& v)
1587 copyPropertiesToCachedValues (v, ampAttackValue, ampDecayValue, ampSustainValue, ampReleaseValue, ampVelocityValue, filterAttackValue,
1588 filterDecayValue, filterSustainValue, filterReleaseValue, filterFreqValue, filterResonanceValue,
1589 filterAmountValue, filterKeyValue, filterVelocityValue, distortionValue, reverbSizeValue,
1590 reverbDampingValue, reverbWidthValue, reverbMixValue, delayValue, delayFeedbackValue, delayCrossfeedValue,
1591 delayMixValue, chorusSpeedValue, chorusDepthValue, chorusWidthValue, chorusMixValue, legatoValue,
1592 masterLevelValue, voiceModeValue, voicesValue, filterTypeValue, filterSlopeValue,
1593 ampAnalogValue, distortionOnValue, reverbOnValue, delayOnValue, chorusOnValue);
1595 auto um = getUndoManager();
1597 for (
auto p : oscParams)
1598 p->restorePluginStateFromValueTree (v);
1600 for (
auto p : lfoParams)
1601 p->restorePluginStateFromValueTree (v);
1603 for (
auto p : modEnvParams)
1604 p->restorePluginStateFromValueTree (v);
1610 mm = v.getChildWithName (IDs::MODMATRIX);
1613 state.
addChild (mm.createCopy(), -1, um);
1615 valueTreePropertyChanged (state, IDs::voiceMode);
1617 for (
auto p : getAutomatableParameters())
1618 p->updateFromAttachedValue();
1621juce::String FourOscPlugin::modulationSourceToName (ModSource src)
1625 case lfo1:
return TRANS(
"LFO 1");
1626 case lfo2:
return TRANS(
"LFO 2");
1627 case env1:
return TRANS(
"Envelope 1");
1628 case env2:
return TRANS(
"Envelope 2");
1629 case mpePressure:
return TRANS(
"MPE Pressure");
1630 case mpeTimbre:
return TRANS(
"MPE Timbre");
1631 case midiNoteNum:
return TRANS(
"MIDI Note Number");
1632 case midiVelocity:
return TRANS(
"MIDI Velocity");
1639 if (src >= ccBankSelect && src <= ccPolyMode)
1647 return prefix +
" " + name;
1656juce::String FourOscPlugin::modulationSourceToID (FourOscPlugin::ModSource src)
1660 case lfo1:
return "lfo1";
1661 case lfo2:
return "lfo2";
1662 case env1:
return "env1";
1663 case env2:
return "env2";
1664 case mpePressure:
return "mpePressure";
1665 case mpeTimbre:
return "mpeTimbre";
1666 case midiNoteNum:
return "midiNote";
1667 case midiVelocity:
return "midiVelocity";
1674 if (src >= ccBankSelect && src <= ccPolyMode)
1683FourOscPlugin::ModSource FourOscPlugin::idToModulationSource (
juce::String idStr)
1685 if (idStr ==
"lfo1")
return lfo1;
1686 if (idStr ==
"lfo2")
return lfo2;
1687 if (idStr ==
"env1")
return env1;
1688 if (idStr ==
"env2")
return env2;
1689 if (idStr ==
"mpePressure")
return mpePressure;
1690 if (idStr ==
"mpeTimbre")
return mpeTimbre;
1691 if (idStr ==
"midiNote")
return midiNoteNum;
1692 if (idStr ==
"midiVelocity")
return midiVelocity;
1700juce::Array<float> FourOscPlugin::getLiveModulationPositions (AutomatableParameter::Ptr param)
1706 if (param->paramID ==
"filterFreq" && isModulated (param))
1709 if (
auto fov =
dynamic_cast<FourOscVoice*
> (
getVoice (i)))
1710 fov->getLiveFilterFrequency (positions);
1712 else if (isModulated (param))
1715 if (
auto fov =
dynamic_cast<FourOscVoice*
> (
getVoice (i)))
1716 fov->getLiveModulationPositions (param, positions);
1721bool FourOscPlugin::isModulated (AutomatableParameter::Ptr param)
1723 if (param->paramID ==
"filterFreq" && (filterKeyValue.
get() != 0 || filterAmountValue.
get() != 0 ))
1726 auto itr = modMatrix.find (param.get());
1727 if (itr != modMatrix.end())
1729 for (
auto d : itr->second.depths)
1741 auto itr = modMatrix.find (param.get());
1742 if (itr != modMatrix.end())
1745 for (
int s = lfo1; s < numModSources; s++)
1746 if (itr->second.depths[s] >= -1.0f)
1747 res.
add ((ModSource) s);
1755float FourOscPlugin::getModulationDepth (FourOscPlugin::ModSource src, AutomatableParameter::Ptr param)
1757 auto itr = modMatrix.find (param.get());
1758 if (itr != modMatrix.end())
1759 return itr->second.depths[src];
1764void FourOscPlugin::setModulationDepth (FourOscPlugin::ModSource src, AutomatableParameter::Ptr param,
float depth)
1766 auto itr = modMatrix.find (param.get());
1767 if (itr != modMatrix.end())
1769 itr->second.depths[src] = depth;
1770 itr->second.updateCachedInfo();
1776void FourOscPlugin::clearModulation (ModSource src, AutomatableParameter::Ptr param)
1778 auto itr = modMatrix.find (param.get());
1779 if (itr != modMatrix.end())
1781 itr->second.depths[src] = -1000.0f;
1782 itr->second.updateCachedInfo();
1788float FourOscPlugin::paramValue (AutomatableParameter::Ptr param)
1791 if (param ==
nullptr)
1794 auto smoothItr = smoothers.find (param.get());
1795 if (smoothItr == smoothers.end())
1796 return param->getCurrentValue();
1798 float val = param->getCurrentNormalisedValue();
1799 smoothItr->second.setValue (val);
1800 return param->valueRange.convertFrom0to1 (smoothItr->second.getCurrentValue());
float getNextSample() noexcept
void add(const ElementType &newElement)
void triggerAsyncUpdate()
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Type * getWritePointer(int channelNumber) noexcept
int getNumChannels() const noexcept
int getNumSamples() const noexcept
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
void addFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
void referTo(ValueTree &tree, const Identifier &property, UndoManager *um)
Type get() const noexcept
static Type decibelsToGain(Type decibels, Type minusInfinityDb=Type(defaultMinusInfinitydB))
static IIRCoefficients makeLowPass(double sampleRate, double frequency) noexcept
static IIRCoefficients makeNotchFilter(double sampleRate, double frequency) noexcept
static IIRCoefficients makeBandPass(double sampleRate, double frequency) noexcept
static IIRCoefficients makeHighPass(double sampleRate, double frequency) noexcept
void setCoefficients(const IIRCoefficients &newCoefficients) noexcept
void processSamples(float *samples, int numSamples) noexcept
const String & toString() const noexcept
void clearCurrentNote() noexcept
virtual bool isActive() const
void reduceNumVoices(int newNumVoices)
void setCurrentPlaybackSampleRate(double newRate) override
void addVoice(MPESynthesiserVoice *newVoice)
int getNumVoices() const noexcept
MPESynthesiserVoice * getVoice(int index) const
virtual void turnOffAllVoices(bool allowTailOff)
void setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
void * getData() noexcept
static const char * getControllerName(int controllerNumber)
void processStereo(float *const left, float *const right, const int numSamples) noexcept
void setParameters(const Parameters &newParams)
void setSampleRate(const double sampleRate)
float getFloatValue() const noexcept
bool startsWith(StringRef text) const noexcept
bool contains(StringRef text) const noexcept
int getTrailingIntValue() const noexcept
bool isNotEmpty() const noexcept
static uint32 getApproximateMillisecondCounter() noexcept
void removeChild(const ValueTree &child, UndoManager *undoManager)
void addChild(const ValueTree &child, int index, UndoManager *undoManager)
const var & getProperty(const Identifier &name) const noexcept
ValueTree getChildWithName(const Identifier &type) const
An audio scratch buffer that has pooled storage.
juce::AudioBuffer< float > & buffer
The buffer to use.
void noteOff()
Starts the release phase of the envelope.
void reset()
Resets the envelope to an idle state.
bool isActive() const
Returns true if the envelope is in its attack, decay, sustain or release stage.
void noteOn()
Starts the attack phase of the envelope.
void applyEnvelopeToBuffer(juce::AudioBuffer< FloatType > &buffer, int startSample, int numSamples)
This method will conveniently apply the next numSamples number of envelope values to an AudioBuffer.
void setParameters(const Parameters &newParameters)
Sets the parameters that will be used by an ADSR object.
void applyToBuffer(const PluginRenderContext &) override
Process the next block of data.
void deinitialise() override
Called after play stops to release resources.
void reset() override
Should reset synth voices, tails, clear delay buffers, etc.
void setParameters(const Parameters &newParameters)
Sets the parameters that will be used by an ADSR object.
float getNextSample()
Returns the next sample value for an ADSR object.
Smooths a value between 0 and 1 at a constant rate.
#define TRANS(stringLiteral)
#define JUCE_UNDENORMALISE(x)
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
void ignoreUnused(Types &&...) noexcept
int roundToInt(const FloatType value) noexcept
constexpr int numElementsInArray(Type(&)[N]) noexcept
Passed into Plugins when they are being initialised, to give them useful contextual information that ...
void setPitchbendTrackingMode(TrackingMode modeToUse)
void renderNextBlock(AudioBuffer< floatType > &outputAudio, const MidiBuffer &inputMidi, int startSample, int numSamples)
void set(TimePosition)
Sets the Position to a new time.
double getTempo() const
Returns the current tempo of the Position.
Calculates the two gain multipliers to use for mixing between two sources, given a position alpha fro...
The context passed to plugin render methods to provide it with buffers to fill.
int bufferNumSamples
The number of samples to write into the audio buffer.
MidiMessageArray * bufferForMidiMessages
A buffer of MIDI events to process.
juce::AudioBuffer< float > * destBuffer
The target audio buffer which needs to be filled.
int bufferStartSample
The index of the start point in the audio buffer from which data must be written.
TimeRange editTime
The edit time range this context represents.