1 // ------------------------------------------------------------------------
2 // audiofx_filter.cpp: Routines for filter effects.
3 // Copyright (C) 1999,2004,2012 Kai Vehmanen
4 //
5 // Attributes:
6 // eca-style-version: 3
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 // ------------------------------------------------------------------------
22
23 #include <cmath>
24
25 #include <kvu_utils.h>
26
27 #include "samplebuffer_iterators.h"
28 #include "sample-ops_impl.h"
29 #include "eca-logger.h"
30 #include "audiofx_filter.h"
31
priv_resize_buffer(std::vector<SAMPLE_SPECS::sample_t> * buffer,int count)32 static void priv_resize_buffer(std::vector<SAMPLE_SPECS::sample_t> *buffer, int count)
33 {
34 buffer->resize(count);
35 for(int i = 0; i < count; i++)
36 (*buffer)[i] = 0.0;
37 }
38
~EFFECT_FILTER(void)39 EFFECT_FILTER::~EFFECT_FILTER(void)
40 {
41 }
42
EFFECT_BANDPASS(CHAIN_OPERATOR::parameter_t centerf,CHAIN_OPERATOR::parameter_t w)43 EFFECT_BANDPASS::EFFECT_BANDPASS (CHAIN_OPERATOR::parameter_t centerf, CHAIN_OPERATOR::parameter_t w)
44 {
45 /* to avoid accessing uninitialized data */
46 width = 1;
47 center = 1;
48 C = 1;
49
50 set_parameter(1, centerf);
51 set_parameter(2, w);
52 }
53
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)54 void EFFECT_BANDPASS::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
55 {
56 switch (param) {
57 case 1:
58 center = value;
59 D = 2 * cos(2 * M_PI * center / (CHAIN_OPERATOR::parameter_t)samples_per_second());
60 b[0] = -C * D * a[0];
61 break;
62 case 2:
63 if (value != 0) width = value;
64 else width = center / 2;
65 C = 1.0 / tan(M_PI * width / (CHAIN_OPERATOR::parameter_t)samples_per_second());
66 D = 2 * cos(2 * M_PI * center / (CHAIN_OPERATOR::parameter_t)samples_per_second());
67 a[0] = 1.0 / (1.0 + C);
68 a[1] = 0.0;
69 a[2] = -a[0];
70 b[0] = -C * D * a[0];
71 b[1] = (C - 1.0) * a[0];
72 break;
73 }
74 }
75
get_parameter(int param) const76 CHAIN_OPERATOR::parameter_t EFFECT_BANDPASS::get_parameter(int param) const
77 {
78 switch (param) {
79 case 1:
80 return center;
81 case 2:
82 return width;
83 }
84 return 0.0;
85 }
86
EFFECT_BANDREJECT(CHAIN_OPERATOR::parameter_t centerf,CHAIN_OPERATOR::parameter_t w)87 EFFECT_BANDREJECT::EFFECT_BANDREJECT (CHAIN_OPERATOR::parameter_t centerf, CHAIN_OPERATOR::parameter_t w)
88 {
89 set_parameter(1, centerf);
90 set_parameter(2, w);
91 }
92
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)93 void EFFECT_BANDREJECT::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
94 {
95 switch (param) {
96 case 1:
97 center = value;
98 D = 2 * cos(2 * M_PI * center / (CHAIN_OPERATOR::parameter_t)samples_per_second());
99 a[1] = -D * a[0];
100 b[0] = a[1];
101 break;
102 case 2:
103 if (value != 0) width = value;
104 else width = center / 2;
105 C = tan(M_PI * width / (CHAIN_OPERATOR::parameter_t)samples_per_second());
106 a[0] = 1.0 / (1.0 + C);
107 a[1] = -D * a[0];
108 a[2] = a[0];
109 b[0] = a[1];
110 b[1] = (1.0 - C) * a[0];
111 break;
112 }
113 }
114
get_parameter(int param) const115 CHAIN_OPERATOR::parameter_t EFFECT_BANDREJECT::get_parameter(int param) const
116 {
117 switch (param) {
118 case 1:
119 return center;
120 case 2:
121 return width;
122 }
123 return 0.0;
124 }
125
init(SAMPLE_BUFFER * insample)126 void EFFECT_BW_FILTER::init(SAMPLE_BUFFER *insample)
127 {
128 i.init(insample);
129
130 set_channels(insample->number_of_channels());
131
132 const size_t buflen = 2;
133
134 sin.resize(insample->number_of_channels(), std::vector<SAMPLE_SPECS::sample_t> (buflen));
135 sout.resize(insample->number_of_channels(), std::vector<SAMPLE_SPECS::sample_t> (buflen));
136
137 for(int i = 0; i < insample->number_of_channels(); i++) {
138 for(size_t j = 0; j < buflen; j++) {
139 sin[i][j] = 0.0f;
140 sout[i][j] = 0.0f;
141 }
142 }
143 }
144
process(void)145 void EFFECT_BW_FILTER::process(void)
146 {
147 i.begin();
148 while(!i.end()) {
149 outputSample = ecaops_flush_to_zero(a[0] * (*i.current()) +
150 a[1] * sin[i.channel()][0] +
151 a[2] * sin[i.channel()][1] -
152 b[0] * sout[i.channel()][0] -
153 b[1] * sout[i.channel()][1]);
154 sin[i.channel()][1] = sin[i.channel()][0];
155 sin[i.channel()][0] = *i.current();
156
157 sout[i.channel()][1] = sout[i.channel()][0];
158 sout[i.channel()][0] = outputSample;
159
160 *i.current() = outputSample;
161 i.next();
162 }
163 }
164
process_notused(SAMPLE_BUFFER * sbuf)165 void EFFECT_BW_FILTER::process_notused(SAMPLE_BUFFER* sbuf)
166 {
167 // sbuf->first();
168 // while(sbuf->is_readable()) {
169 // outputSample = *sbuf->current_sample() * a[0]
170 // + sin[0] * a[1]
171 // + sin[1] * a[2]
172 // - sout[0] * b[0]
173 // - sout[1] * b[1];
174
175 // sin[1] = sin[0];
176 // sin[0] = *(sbuf->current_sample());
177
178 // sout[1] = sout[0];
179 // sout[0] = outputSample;
180
181 // sbuf->current_sample()->operator=(outputSample);
182 // sbuf->next();
183 // }
184 }
185
init_values(void)186 void EFFECT_BW_FILTER::init_values(void)
187 {
188 // for(int j = 0; j < 2;j++) {
189 // sin[j].sample[SAMPLE_BUFFER::ch_left] = 0.0;
190 // sin[j].sample[SAMPLE_BUFFER::ch_right] = 0.0;
191 // sout[j].sample[SAMPLE_BUFFER::ch_left] = 0.0;
192 // sout[j].sample[SAMPLE_BUFFER::ch_right] = 0.0;
193 // }
194 }
195
EFFECT_HIGHPASS(CHAIN_OPERATOR::parameter_t cutoff)196 EFFECT_HIGHPASS::EFFECT_HIGHPASS (CHAIN_OPERATOR::parameter_t cutoff)
197 {
198 set_parameter(1, cutoff);
199 }
200
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)201 void EFFECT_HIGHPASS::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
202 {
203 switch (param) {
204 case 1:
205 cutOffFreq = value;
206 C = tan(M_PI * cutOffFreq / (CHAIN_OPERATOR::parameter_t)samples_per_second());
207 a[0] = 1.0 / (1.0 + sqrt(2.0) * C + C * C);
208 a[1] = -2.0 * a[0];
209 a[2] = a[0];
210 b[0] = 2 * (C * C - 1.0) * a[0];
211 b[1] = (1.0 - sqrt(2.0) * C + C * C) * a[0];
212 break;
213 }
214 }
215
get_parameter(int param) const216 CHAIN_OPERATOR::parameter_t EFFECT_HIGHPASS::get_parameter(int param) const
217 {
218 switch (param) {
219 case 1:
220 return cutOffFreq;
221 }
222 return 0.0;
223 }
224
EFFECT_ALLPASS_FILTER(void)225 EFFECT_ALLPASS_FILTER::EFFECT_ALLPASS_FILTER (void)
226 : feedback_gain(0.0),
227 D(0.0)
228 {
229
230 }
231
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)232 void EFFECT_ALLPASS_FILTER::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
233 {
234 switch (param) {
235 case 1:
236 D = value;
237 // assert(inbuf.size() == outbuf.size());
238 for(int n = 0; n < static_cast<int>(inbuf.size()); n++) {
239 if (inbuf[n].size() > D) inbuf[n].resize(static_cast<unsigned int>(D));
240 // if (outbuf[n].size() > D) inbuf[n].resize(D);
241 }
242 break;
243 case 2:
244 feedback_gain = value / 100.0;
245 break;
246 }
247 }
248
get_parameter(int param) const249 CHAIN_OPERATOR::parameter_t EFFECT_ALLPASS_FILTER::get_parameter(int param) const
250 {
251 switch (param) {
252 case 1:
253 return D;
254 case 2:
255 return feedback_gain * 100.0;
256 }
257 return 0.0;
258 }
259
init(SAMPLE_BUFFER * insample)260 void EFFECT_ALLPASS_FILTER::init(SAMPLE_BUFFER* insample)
261 {
262 i.init(insample);
263
264 set_channels(insample->number_of_channels());
265
266 inbuf.resize(insample->number_of_channels());
267 for(size_t i = 0; i < inbuf.size(); i++)
268 inbuf[i].clear();
269 }
270
process(void)271 void EFFECT_ALLPASS_FILTER::process(void)
272 {
273 i.begin();
274 while(!i.end()) {
275 if (inbuf[i.channel()].size() >= D) {
276 inbuf[i.channel()].push_back(*i.current());
277
278 // *i.current() = -feedback_gain * (*i.current()) +
279 // inbuf[i.channel()].front() +
280 // feedback_gain * outbuf[i.channel()].front();
281
282 *i.current() = ecaops_flush_to_zero(-feedback_gain * (*i.current()) +
283 (feedback_gain * inbuf[i.channel()].front() +
284 *i.current()) *
285 (1.0 - feedback_gain * feedback_gain));
286
287 // feedback_gain * outbuf[i.channel()].front();
288 // outbuf[i.channel()].push_back(*i.current());
289
290 inbuf[i.channel()].pop_front();
291 // outbuf[i.channel()].pop_front();
292 }
293 else {
294 inbuf[i.channel()].push_back(*i.current());
295 *i.current() = ecaops_flush_to_zero(*i.current() * (1.0 - feedback_gain));
296 // outbuf[i.channel()].push_back(*i.current());
297 }
298 i.next();
299 }
300 }
301
EFFECT_COMB_FILTER(int delay_in_samples,CHAIN_OPERATOR::parameter_t radius)302 EFFECT_COMB_FILTER::EFFECT_COMB_FILTER (int delay_in_samples, CHAIN_OPERATOR::parameter_t radius)
303 {
304 set_parameter(1, (CHAIN_OPERATOR::parameter_t)delay_in_samples);
305 set_parameter(2, radius);
306 }
307
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)308 void EFFECT_COMB_FILTER::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
309 {
310 switch (param) {
311 case 1:
312 {
313 C = value;
314 std::vector<std::deque<SAMPLE_SPECS::sample_t> >::iterator p = buffer.begin();
315 while(p != buffer.end()) {
316 if (p->size() > C) {
317 p->resize(static_cast<unsigned int>(C));
318 }
319 ++p;
320 }
321 break;
322 }
323
324 case 2:
325 D = value;
326 break;
327 }
328 }
329
get_parameter(int param) const330 CHAIN_OPERATOR::parameter_t EFFECT_COMB_FILTER::get_parameter(int param) const
331 {
332 switch (param) {
333 case 1:
334 return C;
335 case 2:
336 return D;
337 }
338 return 0.0;
339 }
340
init(SAMPLE_BUFFER * insample)341 void EFFECT_COMB_FILTER::init(SAMPLE_BUFFER* insample)
342 {
343 i.init(insample);
344
345 set_channels(insample->number_of_channels());
346
347 buffer.resize(insample->number_of_channels());
348 for(size_t i = 0; i < buffer.size(); i++)
349 buffer[i].clear();
350
351 }
352
process(void)353 void EFFECT_COMB_FILTER::process(void)
354 {
355 i.begin();
356 while(!i.end()) {
357 if (buffer[i.channel()].size() >= C) {
358 *i.current() = (*i.current()) + (pow(D, C) *
359 buffer[i.channel()].front());
360 buffer[i.channel()].push_back(*i.current());
361 buffer[i.channel()].pop_front();
362 }
363 else {
364 buffer[i.channel()].push_back(*i.current());
365 }
366 i.next();
367 }
368 }
369
EFFECT_INVERSE_COMB_FILTER(int delay_in_samples,CHAIN_OPERATOR::parameter_t radius)370 EFFECT_INVERSE_COMB_FILTER::EFFECT_INVERSE_COMB_FILTER (int delay_in_samples, CHAIN_OPERATOR::parameter_t radius)
371 {
372 //
373 // delay in number of samples
374 // circle radius
375 //
376 set_parameter(1, (CHAIN_OPERATOR::parameter_t)delay_in_samples);
377 set_parameter(2, radius);
378 }
379
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)380 void EFFECT_INVERSE_COMB_FILTER::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
381 {
382 switch (param) {
383 case 1:
384 C = value;
385 break;
386 case 2:
387 D = value;
388 break;
389 }
390 }
391
get_parameter(int param) const392 CHAIN_OPERATOR::parameter_t EFFECT_INVERSE_COMB_FILTER::get_parameter(int param) const
393 {
394 switch (param) {
395 case 1:
396 return C;
397 case 2:
398 return D;
399 }
400 return 0.0;
401 }
402
init(SAMPLE_BUFFER * insample)403 void EFFECT_INVERSE_COMB_FILTER::init(SAMPLE_BUFFER* insample)
404 {
405 i.init(insample);
406
407 set_channels(insample->number_of_channels());
408
409 buffer.resize(insample->number_of_channels());
410 for(size_t i = 0; i < buffer.size(); i++)
411 buffer[i].clear();
412
413 priv_resize_buffer(&laskuri, insample->number_of_channels());
414 }
415
process(void)416 void EFFECT_INVERSE_COMB_FILTER::process(void)
417 {
418 i.begin();
419 while(!i.end()) {
420 buffer[i.channel()].push_back(*i.current());
421
422 if (laskuri[i.channel()] >= C) {
423 *i.current() = (*i.current()) - (pow(D, C) *
424 buffer[i.channel()].front());
425 buffer[i.channel()].pop_front();
426 }
427 else {
428 laskuri[i.channel()]++;
429 }
430 i.next();
431 }
432 }
433
EFFECT_LOWPASS(CHAIN_OPERATOR::parameter_t cutoff)434 EFFECT_LOWPASS::EFFECT_LOWPASS (CHAIN_OPERATOR::parameter_t cutoff)
435 {
436 set_parameter(1, cutoff);
437 }
438
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)439 void EFFECT_LOWPASS::set_parameter(int param, CHAIN_OPERATOR::parameter_t value) {
440 switch (param) {
441 case 1:
442 set_cutoff(value, samples_per_second());
443 break;
444 }
445 }
446
get_parameter(int param) const447 CHAIN_OPERATOR::parameter_t EFFECT_LOWPASS::get_parameter(int param) const
448 {
449 switch (param) {
450 case 1:
451 return cutOffFreq;
452 }
453 return 0.0;
454 }
455
set_cutoff(CHAIN_OPERATOR::parameter_t value,long int srate)456 void EFFECT_LOWPASS::set_cutoff(CHAIN_OPERATOR::parameter_t value, long int srate)
457 {
458 cutOffFreq = value;
459 C = 1.0 / tan(M_PI * cutOffFreq / (CHAIN_OPERATOR::parameter_t)srate);
460 a[0] = 1.0 / (1.0 + sqrt(2.0) * C + C * C);
461 a[1] = 2.0 * a[0];
462 a[2] = a[0];
463 b[0] = 2 * (1.0 - C * C) * a[0];
464 b[1] = (1.0 - sqrt(2.0) * C + C * C) * a[0];
465 }
466
EFFECT_LOWPASS_SIMPLE(CHAIN_OPERATOR::parameter_t cutoff)467 EFFECT_LOWPASS_SIMPLE::EFFECT_LOWPASS_SIMPLE (CHAIN_OPERATOR::parameter_t cutoff)
468 {
469 set_parameter(1, cutoff);
470 }
471
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)472 void EFFECT_LOWPASS_SIMPLE::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
473 {
474 switch (param) {
475 case 1:
476 cutOffFreq = value;
477 A = 2.0 * M_PI * cutOffFreq / samples_per_second();
478 B = exp(-A / samples_per_second());
479 break;
480 }
481 }
482
get_parameter(int param) const483 CHAIN_OPERATOR::parameter_t EFFECT_LOWPASS_SIMPLE::get_parameter(int param) const
484 {
485 switch (param) {
486 case 1:
487 return cutOffFreq;
488 }
489 return 0.0;
490 }
491
init(SAMPLE_BUFFER * insample)492 void EFFECT_LOWPASS_SIMPLE::init(SAMPLE_BUFFER *insample)
493 {
494 i.init(insample);
495
496 set_channels(insample->number_of_channels());
497
498 priv_resize_buffer(&outhist, insample->number_of_channels());
499 priv_resize_buffer(&tempin, insample->number_of_channels());
500 priv_resize_buffer(&temphist, insample->number_of_channels());
501 }
502
process(void)503 void EFFECT_LOWPASS_SIMPLE::process(void)
504 {
505 i.begin();
506 while(!i.end()) {
507 tempin[i.channel()] = *i.current();
508 temphist[i.channel()] = outhist[i.channel()];
509 outhist[i.channel()] = tempin[i.channel()];
510
511 tempin[i.channel()] *= A * 0.5;
512 temphist[i.channel()] *= B * 0.5;
513
514 *i.current() = ecaops_flush_to_zero(tempin[i.channel()] + temphist[i.channel()]);
515
516 i.next();
517 }
518 }
519
EFFECT_RESONANT_BANDPASS(CHAIN_OPERATOR::parameter_t centerf,CHAIN_OPERATOR::parameter_t w)520 EFFECT_RESONANT_BANDPASS::EFFECT_RESONANT_BANDPASS (CHAIN_OPERATOR::parameter_t centerf,
521 CHAIN_OPERATOR::parameter_t w)
522 {
523 /* to avoid accessing uninitialized data */
524 width = 1;
525 center = 1;
526
527 set_parameter(1, centerf);
528 set_parameter(2, w);
529 }
530
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)531 void EFFECT_RESONANT_BANDPASS::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
532 {
533 switch (param) {
534 case 1:
535 center = value;
536 break;
537 case 2:
538 if (value != 0) width = value;
539 else width = center / 2.0;
540 break;
541 }
542 // R = 1.0 - M_PI * width / (CHAIN_OPERATOR::parameter_t)samples_per_second();
543 // R = 1.0 - ((width / (CHAIN_OPERATOR::parameter_t)samples_per_second()) / 2.0);
544 R = 1.0 - M_PI * (width / (CHAIN_OPERATOR::parameter_t)samples_per_second());
545 c = R * R;
546 pole_angle = (((2.0 * R) / (1.0 + c)) * cos((center /
547 (CHAIN_OPERATOR::parameter_t)samples_per_second() * 2.0 * M_PI)));
548 pole_angle = acos(pole_angle);
549 a = (1.0 - c) * sin(pole_angle);
550 b = 2.0 * R * cos(pole_angle);
551 }
552
get_parameter(int param) const553 CHAIN_OPERATOR::parameter_t EFFECT_RESONANT_BANDPASS::get_parameter(int param) const
554 {
555 switch (param) {
556 case 1:
557 return center;
558 case 2:
559 return width;
560 }
561 return 0.0;
562 }
563
init(SAMPLE_BUFFER * insample)564 void EFFECT_RESONANT_BANDPASS::init(SAMPLE_BUFFER* insample)
565 {
566 i.init(insample);
567
568 set_channels(insample->number_of_channels());
569
570 priv_resize_buffer(&outhist1, insample->number_of_channels());
571 priv_resize_buffer(&outhist2, insample->number_of_channels());
572 }
573
process(void)574 void EFFECT_RESONANT_BANDPASS::process(void)
575 {
576 i.begin();
577 while(!i.end()) {
578 *i.current() = ecaops_flush_to_zero(a * (*i.current()) +
579 b * outhist1[i.channel()] -
580 c * outhist2[i.channel()]);
581
582 outhist2[i.channel()] = outhist1[i.channel()];
583 outhist1[i.channel()] = *i.current();
584
585 i.next();
586 }
587 }
588
EFFECT_RESONANT_LOWPASS(CHAIN_OPERATOR::parameter_t co,CHAIN_OPERATOR::parameter_t res,CHAIN_OPERATOR::parameter_t g)589 EFFECT_RESONANT_LOWPASS::EFFECT_RESONANT_LOWPASS (CHAIN_OPERATOR::parameter_t co, CHAIN_OPERATOR::parameter_t
590 res, CHAIN_OPERATOR::parameter_t g)
591 : ProtoCoef(2), Coef(2)
592 {
593 cutoff = co;
594 Q = res;
595
596 gain_orig = gain = g;
597
598 laskuri = 0.0;
599
600 pi = 4.0 * atan(1.0);
601
602 // ---
603 // Setup filter s-domain coefficients
604 // ---
605
606 ProtoCoef[0].a0 = 1.0;
607 ProtoCoef[0].a1 = 0;
608 ProtoCoef[0].a2 = 0;
609 ProtoCoef[0].b0 = 1.0;
610 ProtoCoef[0].b1 = 0.765367 / Q; // Divide by resonance or Q
611 ProtoCoef[0].b2 = 1.0;
612
613 ProtoCoef[1].a0 = 1.0;
614 ProtoCoef[1].a1 = 0;
615 ProtoCoef[1].a2 = 0;
616 ProtoCoef[1].b0 = 1.0;
617 ProtoCoef[1].b1 = 1.847759 / Q; // Divide by resonance or Q
618 ProtoCoef[1].b2 = 1.0;
619
620 szxform(0);
621 szxform(1);
622 }
623
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)624 void EFFECT_RESONANT_LOWPASS::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
625 {
626 switch (param) {
627 case 1:
628 cutoff = value;
629 break;
630 case 2:
631 Q = value;
632 break;
633 case 3:
634 gain_orig = value;
635 break;
636 }
637 refresh_values();
638 }
639
get_parameter(int param) const640 CHAIN_OPERATOR::parameter_t EFFECT_RESONANT_LOWPASS::get_parameter(int param) const
641 {
642 switch (param) {
643 case 1:
644 return cutoff;
645 case 2:
646 return Q;
647 case 3:
648 return gain_orig;
649 }
650 return 0.0;
651 }
652
refresh_values(void)653 void EFFECT_RESONANT_LOWPASS::refresh_values(void)
654 {
655 if (cutoff == 0.0) cutoff = 0.1;
656
657 gain = gain_orig;
658
659 // ProtoCoef[0].a0 = 1.0;
660 ProtoCoef[0].a1 = 0;
661 ProtoCoef[0].a2 = 0;
662 // ProtoCoef[0].b0 = 1.0;
663 ProtoCoef[0].b1 = 0.765367 / Q; // Divide by resonance or Q
664 ProtoCoef[0].b2 = 1.0;
665
666 // ProtoCoef[1].a0 = 1.0;
667 ProtoCoef[1].a1 = 0;
668 ProtoCoef[1].a2 = 0;
669 // ProtoCoef[1].b0 = 1.0;
670 ProtoCoef[1].b1 = 1.847759 / Q; // Divide by resonance or Q
671 ProtoCoef[1].b2 = 1.0;
672
673 szxform(0);
674 szxform(1);
675 }
676
szxform(int section)677 void EFFECT_RESONANT_LOWPASS::szxform(int section)
678 {
679 wp = 2.0 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * tan(pi * cutoff / (CHAIN_OPERATOR::parameter_t)samples_per_second());
680
681 // ---
682 // a0 and b0 are presumed to be 1, so...
683
684 ProtoCoef[section].a2 = ProtoCoef[section].a2 / (wp * wp);
685 ProtoCoef[section].a1 = ProtoCoef[section].a1 / wp;
686
687 ProtoCoef[section].b2 = ProtoCoef[section].b2 / (wp * wp);
688 ProtoCoef[section].b1 = ProtoCoef[section].b1 / wp;
689
690 // ---
691 // alpha (Numerator in s-domain)
692 ad = 4.0 * ProtoCoef[section].a2 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * (CHAIN_OPERATOR::parameter_t)samples_per_second() + 2.0 * ProtoCoef[section].a1
693 * (CHAIN_OPERATOR::parameter_t)samples_per_second() + ProtoCoef[section].a0;
694 // ---
695 // beta (Denominator in s-domain)
696 bd = 4.0 * ProtoCoef[section].b2 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * (CHAIN_OPERATOR::parameter_t)samples_per_second() + 2.0 * ProtoCoef[section].b1
697 * (CHAIN_OPERATOR::parameter_t)samples_per_second() + ProtoCoef[section].b0;
698
699 // ---
700 /* update gain constant for this section */
701 gain *= ad/bd;
702
703 // ---
704 // Denominator
705 Coef[section].A = (2.0 * ProtoCoef[section].b0 - 8.0 * ProtoCoef[section].b2
706 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * (CHAIN_OPERATOR::parameter_t)samples_per_second()) / bd;
707 // ---
708 // beta1
709 Coef[section].B = (4.0 * ProtoCoef[section].b2 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * (CHAIN_OPERATOR::parameter_t)samples_per_second() - 2.0 * ProtoCoef[section].b1
710 * (CHAIN_OPERATOR::parameter_t)samples_per_second() + ProtoCoef[section].b0) / bd;
711 // ---
712 // beta2
713
714 // ---
715 // Nominator
716 Coef[section].C = (2.0 * ProtoCoef[section].a0 - 8.0 * ProtoCoef[section].a2
717 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * (CHAIN_OPERATOR::parameter_t)samples_per_second()) / ad;
718 // ---
719 // alpha1
720 Coef[section].D = (4.0 * ProtoCoef[section].a2 * (CHAIN_OPERATOR::parameter_t)samples_per_second() * (CHAIN_OPERATOR::parameter_t)samples_per_second() - 2.0
721 * ProtoCoef[section].a1 * (CHAIN_OPERATOR::parameter_t)samples_per_second() + ProtoCoef[section].a0) / ad;
722 // ---
723 // alpha2
724 }
725
init(SAMPLE_BUFFER * insample)726 void EFFECT_RESONANT_LOWPASS::init(SAMPLE_BUFFER* insample)
727 {
728 i.init(insample);
729
730 set_channels(insample->number_of_channels());
731
732 priv_resize_buffer(&outhist0, insample->number_of_channels());
733 priv_resize_buffer(&outhist1, insample->number_of_channels());
734 priv_resize_buffer(&outhist2, insample->number_of_channels());
735 priv_resize_buffer(&outhist3, insample->number_of_channels());
736 priv_resize_buffer(&newhist0, insample->number_of_channels());
737 priv_resize_buffer(&newhist1, insample->number_of_channels());
738 }
739
process(void)740 void EFFECT_RESONANT_LOWPASS::process(void)
741 {
742 i.begin();
743 while(!i.end()) {
744 *i.current() = (*i.current()) * gain;
745
746 // first section:
747 // --------------
748
749 // poles:
750 *i.current() = (*i.current()) - outhist0[i.channel()] * Coef[0].A;
751 newhist0[i.channel()] = ecaops_flush_to_zero((*i.current()) - outhist1[i.channel()] * Coef[0].B);
752
753 // zeros:
754 *i.current() = newhist0[i.channel()] + outhist0[i.channel()] * Coef[0].C;
755 *i.current() = (*i.current()) + outhist1[i.channel()] * Coef[0].D;
756
757 outhist1[i.channel()] = outhist0[i.channel()];
758 outhist0[i.channel()] = newhist0[i.channel()];
759
760 // second section:
761 // --------------
762
763 // poles:
764 *i.current() = (*i.current()) - outhist2[i.channel()] * Coef[1].A;
765 newhist1[i.channel()] = ecaops_flush_to_zero((*i.current()) - outhist3[i.channel()] * Coef[1].B);
766
767 // zeros:
768 *i.current() = newhist1[i.channel()] + outhist2[i.channel()] * Coef[1].C;
769 *i.current() = (*i.current()) + outhist3[i.channel()] * Coef[1].D;
770
771 outhist3[i.channel()] = outhist2[i.channel()];
772 outhist2[i.channel()] = newhist1[i.channel()];
773
774 i.next();
775 }
776 }
777
778 // EFFECT_RESONANT_LOWPASS::EFFECT_RESONANT_LOWPASS (const
779 // EFFECT_RESONANT_LOWPASS& x)
780 // : outhist(4), newhist(2), ProtoCoef(2), Coef(2)
781 // {
782 // outhist = x.outhist;
783 // newhist = x.newhist;
784 // for(vector<BIQUAD>::size_type p = 0; p != x.ProtoCoef.size(); p++) {
785 // ProtoCoef[p].a0 = x.ProtoCoef[p].a0;
786 // ProtoCoef[p].a1 = x.ProtoCoef[p].a1;
787 // ProtoCoef[p].a2 = x.ProtoCoef[p].a2;
788 // ProtoCoef[p].b0 = x.ProtoCoef[p].b0;
789 // ProtoCoef[p].b1 = x.ProtoCoef[p].b1;
790 // ProtoCoef[p].b2 = x.ProtoCoef[p].b2;
791 // ++p;
792 // }
793 // for(vector<BIQUAD>::size_type p = 0; p != x.Coef.size(); p++) {
794 // Coef[p].A = x.Coef[p].A;
795 // Coef[p].B = x.Coef[p].B;
796 // Coef[p].C = x.Coef[p].C;
797 // Coef[p].D = x.Coef[p].D;
798 // ++p;
799 // }
800 // cutoff = x.cutoff;
801 // Q = x.Q;
802 // gain = x.gain;
803 // gain_orig = x.gain_orig;
804 // pi = x.pi;
805 // laskuri = x.laskuri;
806 // ad = x.ad;
807 // bd = x.bd;
808 // wp = x.wp;
809 // }
810
EFFECT_RESONATOR(CHAIN_OPERATOR::parameter_t centerf,CHAIN_OPERATOR::parameter_t w)811 EFFECT_RESONATOR::EFFECT_RESONATOR (CHAIN_OPERATOR::parameter_t centerf, CHAIN_OPERATOR::parameter_t w)
812 : cona(1), conb(2)
813 {
814 /* to avoid accessing uninitialized data */
815 width = 1;
816 center = 1;
817
818 set_parameter(1, centerf);
819 set_parameter(2, w);
820 }
821
set_parameter(int param,CHAIN_OPERATOR::parameter_t value)822 void EFFECT_RESONATOR::set_parameter(int param, CHAIN_OPERATOR::parameter_t value)
823 {
824 switch (param) {
825 case 1:
826 center = value;
827 break;
828 case 2:
829 if (value != 0) width = value;
830 else width = center / 2;
831 break;
832 }
833 conb[1] = exp(-(2 * M_PI) * (width / (CHAIN_OPERATOR::parameter_t)samples_per_second()));
834 conb[0] = (-4.0 * conb[1]) / (1.0 + conb[1]) * cos(2 * M_PI * (center / (CHAIN_OPERATOR::parameter_t)samples_per_second()));
835 cona[0] = (1.0 - conb[1]) * sqrt(1.0 - (conb[0] * conb[0]) / (4.0 * conb[1]));
836 }
837
get_parameter(int param) const838 CHAIN_OPERATOR::parameter_t EFFECT_RESONATOR::get_parameter(int param) const {
839 switch (param) {
840 case 1:
841 return center;
842 case 2:
843 return width;
844 }
845 return 0.0;
846 }
847
init(SAMPLE_BUFFER * insample)848 void EFFECT_RESONATOR::init(SAMPLE_BUFFER* insample) {
849 i.init(insample);
850
851 set_channels(insample->number_of_channels());
852
853 priv_resize_buffer(&saout0, insample->number_of_channels());
854 priv_resize_buffer(&saout1, insample->number_of_channels());
855 }
856
process(void)857 void EFFECT_RESONATOR::process(void)
858 {
859 i.begin();
860 while(!i.end()) {
861 *i.current() = cona[0] * (*i.current()) -
862 conb[0] * saout0[i.channel()] -
863 conb[1] * saout1[i.channel()];
864
865 saout1[i.channel()] = saout0[i.channel()];
866 saout0[i.channel()] = ecaops_flush_to_zero(*i.current());
867
868 i.next();
869 }
870 }
871