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