Skip to content

Commit 65fcc73

Browse files
committed
Tank Variance and Soft Clip
1 parent 1b4e405 commit 65fcc73

File tree

5 files changed

+114
-50
lines changed

5 files changed

+114
-50
lines changed

Plateau2/Plateau2.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Plateau2::Plateau2(const InstanceInfo& info)
3030
GetParam(kNesting1)->InitBool("Nested Tank Diffusion 1", false);
3131
GetParam(kInputNesting1)->InitBool("Nested Input Diffusion 1", false);
3232
GetParam(kDiffusionDecay1)->InitPercentage("Tank Diffusion Decay 1", 76.9230);
33+
GetParam(kVariance1)->InitDouble("Tank Variance 1", 1., 0., 1., 0.01);
34+
GetParam(kSoftClip1)->InitBool("Soft Clip 1", false);
3335
GetParam(kInput1)->InitPercentage("Input 1", 100);
3436
GetParam(kStereoSource1)->InitPercentage("Stereo Source 1", 0, -100, 100);
3537
GetParam(kWidth1)->InitPercentage("Stereo Width 1", 100, 0, 200);
@@ -62,6 +64,8 @@ Plateau2::Plateau2(const InstanceInfo& info)
6264
GetParam(kNesting2)->InitBool("Nested Tank Diffusion 2", false);
6365
GetParam(kInputNesting2)->InitBool("Nested Input Diffusion 2", false);
6466
GetParam(kDiffusionDecay2)->InitPercentage("Tank Diffusion Decay 2", 76.9230);
67+
GetParam(kVariance2)->InitDouble("Tank Variance 2", 1., 0., 1., 0.01);
68+
GetParam(kSoftClip2)->InitBool("Soft Clip 2", false);
6569
GetParam(kInput2)->InitPercentage("Input 2", 100);
6670
GetParam(kStereoSource2)->InitPercentage("Stereo Source 2", 0, -100, 100);
6771
GetParam(kWidth2)->InitPercentage("Stereo Width 2", 100, 0, 200);
@@ -146,7 +150,9 @@ Plateau2::Plateau2(const InstanceInfo& info)
146150
Knobs[kDiffusionDecayKnob] = new NeedleKnob(IRECT::MakeXYWH(233, 310, 56, 56), NeedleSVG, NeedleBGSVG, NeedleFG1PNG, NeedleFG2PNG, kDiffusionDecay1, kDiffusionDecay2);
147151
Knobs[kDiffusionDecayKnob]->Bound = 72.6923f;
148152

149-
Knobs[kModVarianceKnob] = new NeedleKnob(IRECT::MakeXYWH(233, 518, 56, 56), NeedleSVG, NeedleBGSVG, NeedleFG1PNG, NeedleFG2PNG, kModVariance1, kModVariance2);
153+
Knobs[kModVarianceKnob] = new NeedleKnob(IRECT::MakeXYWH(130, 220, 56, 56), NeedleSVG, NeedleBGSVG, NeedleFG1PNG, NeedleFG2PNG, kModVariance1, kModVariance2);
154+
155+
Knobs[kVarianceKnob] = new NeedleKnob(IRECT::MakeXYWH(26, 310, 56, 56), NeedleSVG, NeedleBGSVG, NeedleFG1PNG, NeedleFG2PNG, kVariance1, kVariance2);
150156

151157
//Routing Page Knobs
152158
Knobs[kInputKnob] = new NeedleKnob(IRECT::MakeXYWH(93, 170, 56, 56), NeedleSVG, NeedleBGSVG, NeedleFG1PNG, NeedleFG2PNG, kInput1, kInput2);
@@ -214,12 +220,14 @@ Plateau2::Plateau2(const InstanceInfo& info)
214220
Switches[5] = new LEDSwitch(IRECT::MakeXYWH(210, 170, 102, 102), LEDScale, LedOffSVG, LedOn1SVG, LedOn2SVG, kNesting1, kNesting2);
215221

216222
//DANGER switch
217-
Switches[6] = new LEDSwitch(IRECT::MakeXYWH(102, 301, 112, 112), 1, DangerOffSVG, DangerOnSVG, DangerOnSVG, kDanger, kDanger);
223+
Switches[6] = new LEDSwitch(IRECT::MakeXYWH(102, 321, 112, 112), 1, DangerOffSVG, DangerOnSVG, DangerOnSVG, kDanger, kDanger);
224+
225+
Switches[7] = new LEDSwitch(IRECT::MakeXYWH(3, 170, 102, 102), LEDScale, LedOffSVG, LedOn1SVG, LedOn2SVG, kSoftClip1, kSoftClip2);
218226

219227
//Routing page Switches
220-
Switches[7] = new LEDSwitch(IRECT::MakeXYWH(106.5, 374, 102, 102), LEDScale, LedOffSVG, LedOn1SVG, LedOn2SVG, k1to2, k2to1);
228+
Switches[8] = new LEDSwitch(IRECT::MakeXYWH(106.5, 374, 102, 102), LEDScale, LedOffSVG, LedOn1SVG, LedOn2SVG, k1to2, k2to1);
221229

222-
for (int i = 5; i <= 7; i++) {
230+
for (int i = 5; i <= 8; i++) {
223231
pGraphics->AttachControl(Switches[i]);
224232
Switches[i]->Hide(true);
225233
}
@@ -296,24 +304,24 @@ void Plateau2::UpdatePageVisibility()
296304
}
297305

298306
//Extras page
299-
for (int i = kPreDelayKnob; i <= kModVarianceKnob; i++) {
307+
for (int i = kPreDelayKnob; i <= kVarianceKnob; i++) {
300308
Knobs[i]->Hide(currentPage != 1);
301309
}
302-
for (int i = 5; i <= 6; i++) {
310+
for (int i = 5; i <= 7; i++) {
303311
Switches[i]->Hide(currentPage != 1);
304312
}
305313

306314
//Routing page
315+
Switches[8]->Hide(currentPage != 2);
316+
307317
for (int i = kInputKnob; i <= kPanKnob; i++) {
308318
Knobs[i]->Hide(currentPage != 2);
309319
}
320+
310321
UpdateSendVisibility();
311322
}
312323

313324
void Plateau2::UpdateSendVisibility() {
314-
for (int i = 7; i <= 7; i++) {
315-
Switches[i]->Hide(currentPage != 2);
316-
}
317325
bool dangerous = GetParam(kDanger)->Value();
318326
for (int i = kSendLevel; i <= kSendHighDamp; i++) {
319327
Knobs[i]->Hide(currentPage != 2 || (!dangerous && tank2Selected));
@@ -420,6 +428,9 @@ void Plateau2::OnParamChange(int index)
420428
reverb1.setTankDiffusionDecay(scaled);
421429
break;
422430
}
431+
case kVariance1:
432+
reverb1.setTankVariance(GetParam(index)->Value());
433+
break;
423434
case kStereoSource1:
424435
sourceBalance1 = balanceFactors(GetParam(kStereoSource1)->Value()/100);
425436
break;
@@ -503,6 +514,9 @@ void Plateau2::OnParamChange(int index)
503514
reverb2.setTankDiffusionDecay(scaled);
504515
break;
505516
}
517+
case kVariance2:
518+
reverb2.setTankVariance(GetParam(index)->Value());
519+
break;
506520
case kStereoSource2:
507521
sourceBalance2 = balanceFactors(GetParam(kStereoSource2)->Value()/100);
508522
break;
@@ -568,6 +582,7 @@ void Plateau2::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
568582
const double wet1Param = GetParam(kWet1)->Value() / 100;
569583
const double input1 = GetParam(kInput1)->Value() / 100;
570584
const double level2to1 = GetParam(k2to1Level)->Value() / 100;
585+
const double softClip1 = GetParam(kSoftClip1)->Value() >= 0.5;
571586

572587
if (clear1Param && !clear1 && cleared1) {
573588
cleared1 = false;
@@ -616,9 +631,16 @@ void Plateau2::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
616631

617632
outputs[0][s] += std::get<0>(out) * wet1Param;
618633

634+
if (softClip1) {
635+
outputs[0][s] = std::tanh(outputs[0][s]);
636+
}
637+
619638
if (nChans > 1)
620639
{
621640
outputs[1][s] += std::get<1>(out) * wet1Param;
641+
if (softClip1) {
642+
outputs[1][s] = std::tanh(outputs[1][s]);
643+
}
622644
}
623645

624646
if (send1to2) {
@@ -639,6 +661,7 @@ void Plateau2::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
639661
const double wet2Param = GetParam(kWet2)->Value() / 100;
640662
const double input2 = GetParam(kInput2)->Value() / 100;
641663
const double level1to2 = GetParam(k1to2Level)->Value() / 100;
664+
const double softClip2 = GetParam(kSoftClip2)->Value() >= 0.5;
642665

643666
if (clear2Param && !clear2 && cleared2) {
644667
cleared2 = false;
@@ -688,9 +711,16 @@ void Plateau2::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
688711

689712
outputs[0][s] += std::get<0>(out) * wet2Param;
690713

714+
if (softClip2) {
715+
outputs[0][s] = std::tanh(outputs[0][s]);
716+
}
717+
691718
if (nChans > 1)
692719
{
693720
outputs[1][s] += std::get<1>(out) * wet2Param;
721+
if (softClip2) {
722+
outputs[1][s] = std::tanh(outputs[1][s]);
723+
}
694724
}
695725

696726
if (send2to1) {

Plateau2/Plateau2.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ enum EParams
4040
kNesting1,
4141
kInputNesting1,
4242
kDiffusionDecay1,
43+
kVariance1,
44+
kSoftClip1,
4345
kInput1,
4446
kStereoSource1,
4547
kWidth1,
@@ -71,6 +73,8 @@ enum EParams
7173
kNesting2,
7274
kInputNesting2,
7375
kDiffusionDecay2,
76+
kVariance2,
77+
kSoftClip2,
7478
kInput2,
7579
kStereoSource2,
7680
kWidth2,
@@ -102,6 +106,7 @@ enum EKnobs {
102106
kPreDelayKnob,
103107
kDiffusionDecayKnob,
104108
kModVarianceKnob,
109+
kVarianceKnob,
105110
kInputKnob,
106111
kStereoSourceKnob,
107112
kWidthKnob,
@@ -113,7 +118,7 @@ enum EKnobs {
113118
kNumKnobs
114119
};
115120

116-
const int kNumSwitches = 8;
121+
const int kNumSwitches = 9;
117122
const int kNumButtons = 2;
118123
const int kNumPages = 3;
119124
const int kNumSVGs = 5;

Plateau2/dsp/Dattorro.cpp

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ Dattorro1997Tank::Dattorro1997Tank()
1414
lfo3.setFrequency(lfo3Freq);
1515
lfo4.setFrequency(lfo4Freq);
1616

17-
//lfo2.setPhase(0.25);
18-
//lfo3.setPhase(0.5);
19-
//lfo4.setPhase(0.75);
20-
2117
lfo1.setRevPoint(0.5);
2218
lfo2.setRevPoint(0.5);
2319
lfo3.setRevPoint(0.5);
@@ -122,6 +118,12 @@ void Dattorro1997Tank::setTimeScale(const double newTimeScale) {
122118
rescaleApfAndDelayTimes();
123119
}
124120

121+
void Dattorro1997Tank::setVariance(const double newVariance) {
122+
variance = newVariance;
123+
124+
rescaleApfAndDelayTimes();
125+
}
126+
125127
void Dattorro1997Tank::setDecay(const double newDecay) {
126128
decayParam = newDecay;
127129
}
@@ -232,14 +234,14 @@ void Dattorro1997Tank::initialiseDelaysAndApfs() {
232234
maxScaledOutputTap + timePadding));
233235
};
234236

235-
const long kLeftApf1MaxTime = calcMaxTime(leftApf1Time);
236-
const long kLeftDelay1MaxTime = calcMaxTime(leftDelay1Time);
237-
const long kLeftApf2MaxTime = calcMaxTime(leftApf2Time);
238-
const long kLeftDelay2MaxTime = calcMaxTime(leftDelay2Time);
239-
const long kRightApf1MaxTime = calcMaxTime(rightApf1Time);
240-
const long kRightDelay1MaxTime = calcMaxTime(rightDelay1Time);
241-
const long kRightApf2MaxTime = calcMaxTime(rightApf2Time);
242-
const long kRightDelay2MaxTime = calcMaxTime(rightDelay2Time);
237+
const long kLeftApf1MaxTime = calcMaxTime(std::max({ leftApf1Time, (leftApf1Time + rightApf1Time) / 2 }));
238+
const long kLeftDelay1MaxTime = calcMaxTime(std::max({ leftDelay1Time, (leftDelay1Time + rightDelay1Time) / 2 }));
239+
const long kLeftApf2MaxTime = calcMaxTime(std::max({ leftApf2Time, (leftApf2Time + rightApf2Time) / 2 }));
240+
const long kLeftDelay2MaxTime = calcMaxTime(std::max({ leftDelay2Time, (leftDelay2Time + rightDelay2Time) / 2 }));
241+
const long kRightApf1MaxTime = calcMaxTime(std::max({ rightApf1Time, (leftApf1Time + rightApf1Time) / 2 }));
242+
const long kRightDelay1MaxTime = calcMaxTime(std::max({ rightDelay1Time, (leftDelay1Time + rightDelay1Time) / 2 }));
243+
const long kRightApf2MaxTime = calcMaxTime(std::max({ rightApf2Time, (leftApf2Time + rightApf2Time) / 2 }));
244+
const long kRightDelay2MaxTime = calcMaxTime(std::max({ rightDelay2Time, (leftDelay2Time + rightDelay2Time) / 2 }));
243245

244246
leftApf1 = AllpassFilter<double>(kLeftApf1MaxTime);
245247
leftDelay1 = InterpDelay<double>(kLeftDelay1MaxTime);
@@ -253,15 +255,17 @@ void Dattorro1997Tank::initialiseDelaysAndApfs() {
253255

254256
void Dattorro1997Tank::tickApfModulation() {
255257
double scaleFactor = timeScale;
256-
leftApf1.delay1.setDelayTime(lfo1.process() * lfoExcursion * scaleFactor + scaledLeftApf1Time);
257-
leftApf2.delay1.setDelayTime(lfo2.process() * lfoExcursion * scaleFactor + scaledLeftApf2Time);
258-
rightApf1.delay1.setDelayTime(lfo3.process() * lfoExcursion * scaleFactor + scaledRightApf1Time);
259-
rightApf2.delay1.setDelayTime(lfo4.process() * lfoExcursion * scaleFactor + scaledRightApf2Time);
258+
double avg1 = (scaledLeftApf1Time + scaledRightApf1Time) / 2;
259+
double avg2 = (scaledLeftApf2Time + scaledRightApf2Time) / 2;
260+
leftApf1.delay1.setDelayTime(lfo1.process() * lfoExcursion * scaleFactor + linterp<double>(avg1, scaledLeftApf1Time, variance));
261+
leftApf2.delay1.setDelayTime(lfo2.process() * lfoExcursion * scaleFactor + linterp<double>(avg2, scaledLeftApf2Time, variance));
262+
rightApf1.delay1.setDelayTime(lfo3.process() * lfoExcursion * scaleFactor + linterp<double>(avg1, scaledRightApf1Time, variance));
263+
rightApf2.delay1.setDelayTime(lfo4.process() * lfoExcursion * scaleFactor + linterp<double>(avg2, scaledRightApf2Time, variance));
260264

261-
leftApf1.delay2.setDelayTime(lfo1.process() * lfoExcursion * scaleFactor + scaledLeftApf1Time);
262-
leftApf2.delay2.setDelayTime(lfo2.process() * lfoExcursion * scaleFactor + scaledLeftApf2Time);
263-
rightApf1.delay2.setDelayTime(lfo3.process() * lfoExcursion * scaleFactor + scaledRightApf1Time);
264-
rightApf2.delay2.setDelayTime(lfo4.process() * lfoExcursion * scaleFactor + scaledRightApf2Time);
265+
leftApf1.delay2.setDelayTime(lfo1.process() * lfoExcursion * scaleFactor + linterp<double>(avg1, scaledLeftApf1Time, variance));
266+
leftApf2.delay2.setDelayTime(lfo2.process() * lfoExcursion * scaleFactor + linterp<double>(avg2, scaledLeftApf2Time, variance));
267+
rightApf1.delay2.setDelayTime(lfo3.process() * lfoExcursion * scaleFactor + linterp<double>(avg1, scaledRightApf1Time, variance));
268+
rightApf2.delay2.setDelayTime(lfo4.process() * lfoExcursion * scaleFactor + linterp<double>(avg2, scaledRightApf2Time, variance));
265269
}
266270

267271
void Dattorro1997Tank::rescaleApfAndDelayTimes() {
@@ -277,10 +281,13 @@ void Dattorro1997Tank::rescaleApfAndDelayTimes() {
277281
scaledRightApf2Time = rightApf2Time * scaleFactor;
278282
scaledRightDelay2Time = rightDelay2Time * scaleFactor;
279283

280-
leftDelay1.setDelayTime(scaledLeftDelay1Time);
281-
leftDelay2.setDelayTime(scaledLeftDelay2Time);
282-
rightDelay1.setDelayTime(scaledRightDelay1Time);
283-
rightDelay2.setDelayTime(scaledRightDelay2Time);
284+
double avg1 = (scaledLeftDelay1Time + scaledRightDelay1Time) / 2;
285+
double avg2 = (scaledLeftDelay2Time + scaledRightDelay2Time) / 2;
286+
287+
leftDelay1.setDelayTime(linterp<double>(avg1, scaledLeftDelay1Time, variance));
288+
leftDelay2.setDelayTime(linterp<double>(avg2, scaledLeftDelay2Time, variance));
289+
rightDelay1.setDelayTime(linterp<double>(avg1, scaledRightDelay1Time, variance));
290+
rightDelay2.setDelayTime(linterp<double>(avg2, scaledRightDelay2Time, variance));
284291
}
285292

286293
void Dattorro1997Tank::rescaleTapTimes() {
@@ -333,6 +340,10 @@ void Dattorro::setTimeScale(double timeScale) {
333340
tank.setTimeScale(timeScale);
334341
}
335342

343+
void Dattorro::setTankVariance(double variance) {
344+
tank.setVariance(variance);
345+
}
346+
336347
void Dattorro::setPreDelay(double t) {
337348
preDelayTime = t;
338349
preDelay.setDelayTime(preDelayTime * sampleRate);

Plateau2/dsp/Dattorro.hpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class Dattorro1997Tank {
2020

2121
void setSampleRate(const double newSampleRate);
2222
void setTimeScale(const double newTimeScale);
23+
void setVariance(const double newVariance);
2324

2425
void setDecay(const double newDecay);
2526

@@ -48,15 +49,10 @@ class Dattorro1997Tank {
4849
static constexpr double leftApf2Time = 1800.0;
4950
static constexpr double leftDelay2Time = 3720.0;
5051

51-
//static constexpr double rightApf1Time = 908.0;
52-
//static constexpr double rightDelay1Time = 4217.0;
53-
//static constexpr double rightApf2Time = 2656.0;
54-
//static constexpr double rightDelay2Time = 3163.0;
55-
56-
static constexpr double rightApf1Time = 672.0;
57-
static constexpr double rightDelay1Time = 4453.0;
58-
static constexpr double rightApf2Time = 1800.0;
59-
static constexpr double rightDelay2Time = 3720.0;
52+
static constexpr double rightApf1Time = 908.0;
53+
static constexpr double rightDelay1Time = 4217.0;
54+
static constexpr double rightApf2Time = 2656.0;
55+
static constexpr double rightDelay2Time = 3163.0;
6056

6157
enum LeftOutTaps {
6258
L_DELAY_1_L_TAP_1,
@@ -109,6 +105,7 @@ class Dattorro1997Tank {
109105
double sampleRateScale = sampleRate / dattorroSampleRate;
110106

111107
double timeScale = 1.0;
108+
double variance = 0.0;
112109

113110
double modDepth = 0.0;
114111
double decayParam = 0.0;
@@ -165,6 +162,7 @@ class Dattorro {
165162
void clear();
166163

167164
void setTimeScale(double timeScale);
165+
void setTankVariance(double variance);
168166
void setPreDelay(double time);
169167
void setSampleRate(double sampleRate);
170168

0 commit comments

Comments
 (0)