@@ -21,12 +21,17 @@ struct TRSBBD : Module {
2121 NUM_LIGHTS
2222 };
2323
24- Delay<float_4> delays[2 ][2 ];
25-
26- BBD<float > bbds[2 ][2 ];
24+ BBD<float > bbds[2 ];
2725
2826 float sr = 44100 .f;
2927
28+ #define BBD_OVERSAMPLE 4
29+
30+ UpsamplePow2<BBD_OVERSAMPLE, float > upsamplers[2 ];
31+ DecimatePow2<BBD_OVERSAMPLE, float > decimators[2 ];
32+
33+ float work[BBD_OVERSAMPLE];
34+
3035 StereoInHandler fbIn;
3136 StereoInHandler timeIn;
3237 StereoInHandler signalIn;
@@ -45,12 +50,6 @@ struct TRSBBD : Module {
4550
4651 signalOut.configure (&outputs[SIGNAL_OUTPUT]);
4752
48-
49-
50- delays[0 ][0 ].init (48000 );
51- delays[0 ][1 ].init (48000 );
52- delays[1 ][0 ].init (48000 );
53- delays[1 ][1 ].init (48000 );
5453 onSampleRateChange ();
5554
5655 }
@@ -67,68 +66,193 @@ struct TRSBBD : Module {
6766 timeCV /= 10 .f ;
6867 timeCV = clamp (timeCV, 0 .f , 1 .f );
6968 timeCV += params[TIME_PARAM].getValue ();
70- timeCV *= 400000 .f ;
71- timeCV += 14000 .f ;
69+ timeCV = 14000 .f * dsp::approxExp2_taylor5 (timeCV * 3 .f );
7270
7371 float fb = clamp (params[FEEDBACK_PARAM].getValue () + fbIn.getLeft ()/15 .f , 0 .f , .75f );
74- float out = bbds[0 ][0 ].process (signalIn.getLeft () + lastL * fb, timeCV);
75- lastL= out;
72+ float in = signalIn.getLeft () + lastL * fb;
73+ upsamplers[0 ].process (in);
74+ work[0 ] = bbds[0 ].process (upsamplers[0 ].output [0 ], timeCV);
75+ work[1 ] = bbds[0 ].process (upsamplers[0 ].output [1 ], timeCV);
76+ work[2 ] = bbds[0 ].process (upsamplers[0 ].output [2 ], timeCV);
77+ work[3 ] = bbds[0 ].process (upsamplers[0 ].output [3 ], timeCV);
78+ float out = decimators[0 ].process (work);
79+ // float out = bbds[0].process(in, timeCV);
80+ lastL = out;
7681 signalOut.setLeft (lastL);
7782
7883 timeCV = timeIn.getRight ();
7984 timeCV += 5 .f ;
8085 timeCV /= 10 .f ;
8186 timeCV = clamp (timeCV, 0 .f , 1 .f );
8287 timeCV += params[TIME_PARAM].getValue ();
83- timeCV *= 400000 .f ;
84- timeCV += 14000 .f ;
85-
86- fb = clamp (params[FEEDBACK_PARAM].getValue () + fbIn.getRight ()/10 .f , 0 .f , .99999f );
87- out = bbds[0 ][1 ].process (signalIn.getRight () + lastR * fb, timeCV);
88- lastR= out;
88+ timeCV = 14000 .f * dsp::approxExp2_taylor5 (timeCV * 3 .f );
89+
90+ fb = clamp (params[FEEDBACK_PARAM].getValue () + fbIn.getRight ()/15 .f , 0 .f , .75f );
91+ in = signalIn.getRight () + lastR * fb;
92+ upsamplers[1 ].process (in);
93+ work[0 ] = bbds[1 ].process (upsamplers[0 ].output [0 ], timeCV);
94+ work[1 ] = bbds[1 ].process (upsamplers[0 ].output [1 ], timeCV);
95+ work[2 ] = bbds[1 ].process (upsamplers[0 ].output [2 ], timeCV);
96+ work[3 ] = bbds[1 ].process (upsamplers[0 ].output [3 ], timeCV);
97+ out = decimators[1 ].process (work);
98+ // out = bbds[1].process(in, timeCV);
99+ lastR = out;
89100 signalOut.setRight (lastR);
90101
91- // outputs[SIGNAL_OUTPUT].setChannels(16);
102+ }
103+
104+ void onSampleRateChange () override {
105+
106+ sr = APP->engine ->getSampleTime ();
107+
108+ bbds[0 ].reformFilters (sr / 4 .f );
109+ bbds[1 ].reformFilters (sr / 4 .f );
110+
111+ }
112+
113+ };
114+
115+
116+ struct TRSBBDWidget : ModuleWidget {
117+ TRSBBDWidget (TRSBBD *module ) {
118+ setModule (module );
119+ setPanel (APP->window ->loadSvg (asset::plugin (pluginInstance, " res/TRSBBD.svg" )));
120+
121+ addChild (createWidget<ScrewSilver>(Vec (box.size .x - 2 * RACK_GRID_WIDTH, 0 )));
122+ addChild (createWidget<ScrewSilver>(Vec (box.size .x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
123+
124+ addParam (createParamCentered<SifamGrey>(mm2px (Vec (10.76 , 23.241 )), module , TRSBBD::TIME_PARAM));
125+ addParam (createParamCentered<SifamGrey>(mm2px (Vec (10.76 , 46.741 )), module , TRSBBD::FEEDBACK_PARAM));
126+
127+ addInput (createInputCentered<HexJack>(mm2px (Vec (10.127 , 71.508 )), module , TRSBBD::FEEDBACK_INPUT));
128+ addInput (createInputCentered<HexJack>(mm2px (Vec (10.126 , 85.506 )), module , TRSBBD::TIME_INPUT));
129+ addInput (createInputCentered<HexJack>(mm2px (Vec (10.16 , 99.499 )), module , TRSBBD::SIGNAL_INPUT));
130+
131+ addOutput (createOutputCentered<HexJack>(mm2px (Vec (10.16 , 113.501 )), module , TRSBBD::SIGNAL_OUTPUT));
132+ }
133+ };
134+
135+
136+ Model *modelTRSBBD = createModel<TRSBBD, TRSBBDWidget>(" TRSBBD" );
137+
138+ // echo
139+
140+ struct TRSBBDLONG : Module {
141+ enum ParamIds {
142+ TIME_PARAM,
143+ FEEDBACK_PARAM,
144+ NUM_PARAMS
145+ };
146+ enum InputIds {
147+ FEEDBACK_INPUT,
148+ TIME_INPUT,
149+ SIGNAL_INPUT,
150+ NUM_INPUTS
151+ };
152+ enum OutputIds {
153+ SIGNAL_OUTPUT,
154+ NUM_OUTPUTS
155+ };
156+ enum LightIds {
157+ NUM_LIGHTS
158+ };
159+
160+ BBD<float , 20000 > bbds[2 ];
92161
93- // for (int polyChunk = 0; polyChunk < 2; polyChunk ++) {
162+ float sr = 44100 .f;
94163
95- // float ms = 0.03f + params[TIME_PARAM].getValue() * 50.f;
96- // // no poly rate CV yet (hard to vectorize), temporary hardcoded mono channel for l (0) and r (8)
97- // float_4 leftTap = delays[0][polyChunk].readLinear(ms + clamp(inputs[TIME_INPUT].getVoltage(0), 0.f, 5.f) * 10.f);
98- // float_4 rightTap = delays[1][polyChunk].readLinear(ms + clamp(inputs[TIME_INPUT].getVoltage(8), 0.f, 5.f) * 10.f);
164+ #define BBD_OVERSAMPLE 4
99165
100- // float_4 fbL = clamp(float_4(params[FEEDBACK_PARAM].getValue()) + fbIn.getLeft(polyChunk) / float_4(5.f), 0.f, 0.99f) ;
101- // float_4 fbR = clamp(float_4(params[FEEDBACK_PARAM].getValue()) + fbIn.getLeft(polyChunk) / float_4(5.f), 0.f, 0.99f) ;
166+ UpsamplePow2<BBD_OVERSAMPLE, float > upsamplers[ 2 ] ;
167+ DecimatePow2<BBD_OVERSAMPLE, float > decimators[ 2 ] ;
102168
103- // // add dc blockaz
104- // delays[0][polyChunk].writeDCBlock(signalIn.getLeft(polyChunk) + leftTap * fbL);
105- // delays[1][polyChunk].writeDCBlock(signalIn.getRight(polyChunk) + rightTap * fbR);
169+ float work[BBD_OVERSAMPLE];
106170
107- // signalOut.setLeft(leftTap, polyChunk);
108- // signalOut.setRight(rightTap, polyChunk);
171+ StereoInHandler fbIn;
172+ StereoInHandler timeIn;
173+ StereoInHandler signalIn;
109174
110- // }
175+ StereoOutHandler signalOut;
176+
177+ TRSBBDLONG () {
178+
179+ config (NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
180+ configParam (TIME_PARAM, 0 .f , 1 .f , 0 .f , " " );
181+ configParam (FEEDBACK_PARAM, 0 .f , .75f , 0 .f , " " );
182+
183+ fbIn.configure (&inputs[FEEDBACK_INPUT]);
184+ timeIn.configure (&inputs[TIME_INPUT]);
185+ signalIn.configure (&inputs[SIGNAL_INPUT]);
186+
187+ signalOut.configure (&outputs[SIGNAL_OUTPUT]);
188+
189+ onSampleRateChange ();
190+
191+ }
192+
193+ float lastL = 0 .f;
194+ float lastR = 0 .f;
195+
196+ void process (const ProcessArgs &args) override {
197+
198+ outputs[SIGNAL_OUTPUT].setChannels (16 );
199+
200+ float timeCV = timeIn.getLeft ();
201+ timeCV += 5 .f ;
202+ timeCV /= 10 .f ;
203+ timeCV = clamp (timeCV, 0 .f , 1 .f );
204+ timeCV += params[TIME_PARAM].getValue ();
205+ timeCV = 14000 .f * dsp::approxExp2_taylor5 (timeCV * 3 .f );
206+
207+ float fb = clamp (params[FEEDBACK_PARAM].getValue () + fbIn.getLeft ()/15 .f , 0 .f , .75f );
208+ float in = signalIn.getLeft () + lastL * fb;
209+ upsamplers[0 ].process (in);
210+ work[0 ] = bbds[0 ].process (upsamplers[0 ].output [0 ], timeCV);
211+ work[1 ] = bbds[0 ].process (upsamplers[0 ].output [1 ], timeCV);
212+ work[2 ] = bbds[0 ].process (upsamplers[0 ].output [2 ], timeCV);
213+ work[3 ] = bbds[0 ].process (upsamplers[0 ].output [3 ], timeCV);
214+ float out = decimators[0 ].process (work);
215+ // float out = bbds[0].process(in, timeCV);
216+ lastL = out;
217+ signalOut.setLeft (lastL);
218+
219+ timeCV = timeIn.getRight ();
220+ timeCV += 5 .f ;
221+ timeCV /= 10 .f ;
222+ timeCV = clamp (timeCV, 0 .f , 1 .f );
223+ timeCV += params[TIME_PARAM].getValue ();
224+ timeCV = 14000 .f * dsp::approxExp2_taylor5 (timeCV * 3 .f );
225+
226+ fb = clamp (params[FEEDBACK_PARAM].getValue () + fbIn.getRight ()/15 .f , 0 .f , .75f );
227+ in = signalIn.getRight () + lastR * fb;
228+ upsamplers[1 ].process (in);
229+ work[0 ] = bbds[1 ].process (upsamplers[0 ].output [0 ], timeCV);
230+ work[1 ] = bbds[1 ].process (upsamplers[0 ].output [1 ], timeCV);
231+ work[2 ] = bbds[1 ].process (upsamplers[0 ].output [2 ], timeCV);
232+ work[3 ] = bbds[1 ].process (upsamplers[0 ].output [3 ], timeCV);
233+ out = decimators[1 ].process (work);
234+ // out = bbds[1].process(in, timeCV);
235+ lastR = out;
236+ signalOut.setRight (lastR);
111237
112238 }
113239
114240 void onSampleRateChange () override {
115241
116242 sr = APP->engine ->getSampleTime ();
117243
118- bbds[0 ][0 ].reformFilters (sr);
119- bbds[0 ][1 ].reformFilters (sr);
120- bbds[1 ][0 ].reformFilters (sr);
121- bbds[1 ][1 ].reformFilters (sr);
244+ bbds[0 ].reformFilters (sr / 4 .f );
245+ bbds[1 ].reformFilters (sr / 4 .f );
122246
123247 }
124248
125249};
126250
127251
128- struct TRSBBDWidget : ModuleWidget {
129- TRSBBDWidget (TRSBBD *module ) {
252+ struct TRSBBDLONGWidget : ModuleWidget {
253+ TRSBBDLONGWidget (TRSBBDLONG *module ) {
130254 setModule (module );
131- setPanel (APP->window ->loadSvg (asset::plugin (pluginInstance, " res/TRSBBD .svg" )));
255+ setPanel (APP->window ->loadSvg (asset::plugin (pluginInstance, " res/TRSBBDLONG .svg" )));
132256
133257 addChild (createWidget<ScrewSilver>(Vec (box.size .x - 2 * RACK_GRID_WIDTH, 0 )));
134258 addChild (createWidget<ScrewSilver>(Vec (box.size .x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
@@ -145,4 +269,4 @@ struct TRSBBDWidget : ModuleWidget {
145269};
146270
147271
148- Model *modelTRSBBD = createModel<TRSBBD, TRSBBDWidget >(" TRSBBD " );
272+ Model *modelTRSBBDLONG = createModel<TRSBBDLONG, TRSBBDLONGWidget >(" TRSBBDLONG " );
0 commit comments