summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2020-12-01 20:34:35 +1100
committerDamien Zammit <damien@zamaudio.com>2020-12-01 20:34:35 +1100
commitf18d83b4f5caba9a846558e9b266629617adc1c2 (patch)
tree39bcf8017b3753b566d206cb22df2a0769dd84f3
parent30ac8e0de1ad650edfa068cde562f6b613dd2fb9 (diff)
ZamTube: Introduce two modes of operation toggled by the insane switch
-rw-r--r--plugins/ZamTube/ZamTubePlugin.cpp20
-rw-r--r--plugins/ZamTube/ZamTubePlugin.hpp3
-rw-r--r--plugins/ZamTube/wdfcircuits.h143
3 files changed, 137 insertions, 29 deletions
diff --git a/plugins/ZamTube/ZamTubePlugin.cpp b/plugins/ZamTube/ZamTubePlugin.cpp
index b47186b..40349c4 100644
--- a/plugins/ZamTube/ZamTubePlugin.cpp
+++ b/plugins/ZamTube/ZamTubePlugin.cpp
@@ -299,6 +299,7 @@ void ZamTubePlugin::activate()
// Passive components
/* Original WDF preamp
+ ci[0] = 100e-9;
rg[0] = 20e+3;
rk[0] = 1e+3;
ck[0] = 10e-6;
@@ -309,6 +310,7 @@ void ZamTubePlugin::activate()
*/
/* Matt's preamp */
+ ci[0] = 100e-9;
rg[0] = 1e-3;
rk[0] = 1200.; // 820 originally
ck[0] = 50e-6;
@@ -318,6 +320,7 @@ void ZamTubePlugin::activate()
ro[0] = 470e+3;
/* CLA's preamp
+ ci[0] = 100e-9;
rg[0] = 5.6e+3;
rk[0] = 1.5e+3;
ck[0] = 4.7e-6;
@@ -329,9 +332,7 @@ void ZamTubePlugin::activate()
int pre = 0;
float volumepot = 800e+3; // 100 good at low gain, 1000 good at high gain
- ckt.on = false;
- ckt.updateRValues(ck[pre], co[pre], e[pre], er[pre], rg[pre], volumepot, rk[pre], 1e+3, ro[pre], Fs);
- ckt.warmup_tubes();
+ ckt.updateRValues(ci[pre], ck[pre], co[pre], e[pre], er[pre], rg[pre], volumepot, rk[pre], 1e+3, ro[pre], Fs);
fSamplingFreq = Fs;
@@ -346,7 +347,6 @@ void ZamTubePlugin::activate()
void ZamTubePlugin::deactivate()
{
- ckt.warmup_tubes();
fRec0[3] = 0.f;
fRec0[2] = 0.f;
fRec0[1] = 0.f;
@@ -407,20 +407,26 @@ void ZamTubePlugin::run(const float** inputs, float** outputs, uint32_t frames)
float toneout = 0.f;
- float cut = insane ? 0. : 15.;
+ float cut = 15.;
float pregain = from_dB(tubedrive*3.6364 - cut + mastergain);
float postgain = from_dB(cut + 42. * (1. - log1p(tubedrive/11.)));
+
+ if (insaneold != (int)insane) {
+ insaneold = (int)insane;
+ ckt.set_mode(insane > 0.5 ? ckt.TUBE_MODE_GRIDLEAK : ckt.TUBE_MODE_SIXTIES);
+ ZamTubePlugin::deactivate();
+ }
for (uint32_t i = 0; i < frames; ++i) {
//Step 1: read input sample as voltage for the source
float in = inputs[0][i] * pregain;
- //Tone Stack (post tube)
+ //Tone Stack (pre tube)
fRec0[0] = (in - (fSlow31 * (((fSlow30 * fRec0[1]) + (fSlow29 * fRec0[2])) + (fSlow27 * fRec0[3])))) + 1e-20f;
toneout = sanitize_denormal((float)(fSlow31 * ((((fSlow46 * fRec0[0]) + (fSlow45 * fRec0[1])) + (fSlow43 * fRec0[2])) + (fSlow41 * fRec0[3]))));
- outputs[0][i] = ckt.advanc(toneout) * postgain / 10000.;
+ outputs[0][i] = ckt.run(toneout) * postgain / 10000.;
// update filter states
fRec0[3] = fRec0[2];
diff --git a/plugins/ZamTube/ZamTubePlugin.hpp b/plugins/ZamTube/ZamTubePlugin.hpp
index 55df704..cf838d1 100644
--- a/plugins/ZamTube/ZamTubePlugin.hpp
+++ b/plugins/ZamTube/ZamTubePlugin.hpp
@@ -157,7 +157,8 @@ Wave digital filter physical model of a triode tube amplifier stage, with modell
// -------------------------------------------------------------------
private:
- float tubedrive,bass,middle,treble,tonestack,mastergain,insane,insaneold; //parameters
+ float tubedrive,bass,middle,treble,tonestack,mastergain,insane; //parameters
+ int insaneold;
float ts[25][7];
diff --git a/plugins/ZamTube/wdfcircuits.h b/plugins/ZamTube/wdfcircuits.h
index 5bf2e93..5f99367 100644
--- a/plugins/ZamTube/wdfcircuits.h
+++ b/plugins/ZamTube/wdfcircuits.h
@@ -3,23 +3,37 @@
#include "glue.h"
#include "triode.h"
+#define WARMUP_SAMPLES 48000
+
class TubeStageCircuit {
/*Tube Preamp*/
public:
Triode t;
bool on;
+ int mode;
+ int counter;
TubeStageCircuit() {
reset_tubes();
+ P3_3Gamma1 = 1.;
+ P0_3Gamma1 = 1.;
+ S1_3Gamma1 = 1.;
+ S3_3Gamma1 = 1.;
+ P1_3Gamma1 = 1.;
+ S0_3Gamma1 = 1.;
+ S2_3Gamma1 = 1.;
+ P2_3Gamma1 = 1.;
+ E500E = 0.;
+ ViE = 0.;
}
+ enum tube_mode {
+ TUBE_MODE_SIXTIES = 0,
+ TUBE_MODE_GRIDLEAK,
+ };
+
void warmup_tubes(void) {
- int i;
- on = false;
- for (i = 0; i < 5000; i++) {
- advanc(0.0);
- }
- on = true;
+ counter = WARMUP_SAMPLES;
}
void reset_tubes(void) {
@@ -28,21 +42,12 @@ public:
Coa = 0.0;
Vg = 0.0;
Vk = 0.0;
- P3_3Gamma1 = 1.;
- P0_3Gamma1 = 1.;
- S1_3Gamma1 = 1.;
- S3_3Gamma1 = 1.;
- P1_3Gamma1 = 1.;
- ViE = 0.;
- S0_3Gamma1 = 1.;
- S2_3Gamma1 = 1.;
- P2_3Gamma1 = 1.;
- E500E = 0.;
}
- void updateRValues(Real C_Ck, Real C_Co, Real E_E500, Real R_E500, Real R_Rg, Real R_Ri, Real R_Rk, Real R_Vi, Real R_Ro, Real sampleRate) {
-
+ void updateRValues(Real C_Ci, Real C_Ck, Real C_Co, Real E_E500, Real R_E500, Real R_Rg, Real R_Ri, Real R_Rk, Real R_Vi, Real R_Ro, Real sampleRate) {
+ warmup_tubes();
Real ViR = R_Vi;
+ Real CiR = 1.0 / (2.0*C_Ci*sampleRate);
Real RiR = R_Ri;
Real RgR = R_Rg;
Real RoR = R_Ro;
@@ -51,7 +56,10 @@ public:
Real E500R = R_E500;
E500E = E_E500;
Real CoR = 1.0 / (2.0*C_Co*sampleRate);
- Real P0_1R = ViR;
+ Real S0_3R = (CiR + ViR);
+ S0_3Gamma1 = CiR/(CiR + ViR);
+ Assert(S0_3Gamma1 >= 0.0 && S0_3Gamma1 <= 1.0);
+ Real P0_1R = S0_3R;
Real P0_2R = RiR;
Real P0_3R = 1.0 /(1.0 / P0_1R + 1.0 / P0_2R);
P0_3Gamma1 = 1.0 / P0_1R/(1.0 / P0_1R + 1.0 / P0_2R);
@@ -75,7 +83,85 @@ public:
Assert(S2_3Gamma1 >= 0.0 && S2_3Gamma1 <= 1.0);
}
- Real advanc(Real ViE) {
+ Real advanc_gridleak(Real ViE) {
+ //Get Bs
+ //S2_3GetB
+ //P2_3GetB
+ //S3_3GetB
+ Real Cob = Coa;
+ //S3_1SetA
+ //RoGetB
+ //S3_2SetA
+ Real S3_3b3 = -(Cob);
+ //P2_1SetA
+ //E500GetB
+ //P2_2SetA
+ Real P2_3b3 = E500E - P2_3Gamma1*(E500E - S3_3b3);
+ //S2_1SetA
+ //P1_3GetB
+ Real Ckb = Cka;
+ //P1_1SetA
+ //RkGetB
+ //P1_2SetA
+ Real P1_3b3 = P1_3Gamma1*(-Ckb);
+ //S2_2SetA
+ Real S2_3b3 = (P2_3b3 + P1_3b3);
+ //S1_3GetB
+ //RgGetB
+ //S1_1SetA
+ //P0_3GetB
+ //S0_3GetB
+ Real Cib = Cia;
+ //S0_1SetA
+ //ViGetB
+ //S0_2SetA
+ Real S0_3b3 = -(Cib + ViE);
+ //P0_1SetA
+ //RiGetB
+ //P0_2SetA
+ Real P0_3b3 = -P0_3Gamma1*(-S0_3b3);
+ //S1_2SetA
+ Real S1_3b3 = -(P0_3b3);
+ //P1_3GetB
+ //P1_1SetA
+ //RkGetB
+ //P1_2SetA
+ //Call tube model
+ Vg = (S1_3b3);
+ Real Vd = Vk+Vg;
+ Real Rd = (Vd > 0.) ? 2.7e+3 : 100e+9;
+ Real b = t.compute(S2_3b3, S2_3Gamma1, Vg, Vk);
+ Vk = -(P1_3b3 + Vd * S1_3Gamma1 / Rd);
+ //Set As
+ //S2_3SetA
+ Real S2_3b1 = P2_3b3 - S2_3Gamma1*(P2_3b3 - (Vk+Vg) + b);
+ //P2_3SetA
+ Real P2_3b1 = S2_3b1 + E500E - S3_3b3 - P2_3Gamma1*(E500E - S3_3b3);
+ //S3_3SetA
+ Real S3_3b1 = Cob - S3_3Gamma1*(Cob + P2_3b1);
+ Coa = S3_3b1;
+ Real S3_3b2 = Cob + P2_3b1 - S3_3Gamma1*(Cob + P2_3b1);
+ //RoSetA
+ Real Roa = S3_3b2;
+ Real S2_3b2 = P2_3b3 + b - S2_3Gamma1*(P2_3b3 - (Vk+Vg) + b);
+ //P1_3SetA
+ Real P1_3b1 = S2_3b2 - Ckb - P1_3Gamma1*(-Ckb);
+ Cka = P1_3b1;
+ //RkSetA
+ //S1_3SetA
+ //RgSetA
+ Real S1_3b2 = Vg - S1_3Gamma1*(P0_3b3 + Vg);
+ //P0_3SetA
+ Real P0_3b1 = S1_3b2 - S0_3b3 - P0_3Gamma1*(-S0_3b3);
+ //S0_3SetA
+ Real S0_3b1 = Cib - S0_3Gamma1*(Cib + ViE + P0_3b1);
+ Cia = S0_3b1;
+ //RiSetA
+ //printf("Vk=%f Vg=%f Vd=%f in=%f out=%f\n", Vk,Vg,Vd, ViE,Roa);
+ return -Roa;
+ }
+
+ Real advanc_sixties(Real ViE) {
//Get Bs
//S2_3GetB
//P2_3GetB
@@ -144,7 +230,22 @@ public:
//Cia = S0_3b1;
//RiSetA
//printf("Vk=%f Vg=%f Vpk=%f in=%f out=%f\n", Vk,Vg,S2_3b3, ViE,Roa);
- return Roa;
+ return -Roa;
+ }
+
+ void set_mode(enum tube_mode newmode) {
+ warmup_tubes();
+ mode = newmode;
+ }
+
+ Real run(Real input) {
+ Real output = (mode == TUBE_MODE_SIXTIES) ? advanc_sixties(input) : advanc_gridleak(input);
+ if (counter > 0) {
+ counter--;
+ return 0.;
+ } else {
+ return output;
+ }
}
private: