~ubuntu-branches/ubuntu/wily/ecasound/wily-proposed

« back to all changes in this revision

Viewing changes to libecasound/audiofx_filter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghedini
  • Date: 2011-05-12 17:58:03 UTC
  • Revision ID: james.westby@ubuntu.com-20110512175803-zy3lodjecabt9r3v
Tags: upstream-2.8.0
ImportĀ upstreamĀ versionĀ 2.8.0

Show diffs side-by-side

added added

removed removed

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