2 * Reusable audio effect classes.
4 * Copyright (C) 2001-2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #ifndef __CALF_AUDIOFX_H
22 #define __CALF_AUDIOFX_H
26 #include <calf/biquad.h>
27 #include "primitives.h"
29 #include "fixed_point.h"
34 }; to keep editor happy
38 * Audio effect base class. Not really useful until it gets more developed.
43 virtual void setup(int sample_rate
)=0;
44 virtual ~audio_effect() {}
47 class modulation_effect
: public audio_effect
51 float rate
, wet
, dry
, odsr
;
52 gain_smoothing gs_wet
, gs_dry
;
54 fixed_point
<unsigned int, 20> phase
, dphase
;
58 void set_rate(float rate
) {
60 dphase
= rate
/sample_rate
*4096;
65 void set_wet(float wet
) {
67 gs_wet
.set_inertia(wet
);
72 void set_dry(float dry
) {
74 gs_dry
.set_inertia(dry
);
76 void reset_phase(float req_phase
)
78 phase
= req_phase
* 4096.0;
80 void inc_phase(float req_phase
)
82 phase
+= fixed_point
<unsigned int, 20>(req_phase
* 4096.0);
84 void setup(int sample_rate
)
86 this->sample_rate
= sample_rate
;
87 this->odsr
= 1.0 / sample_rate
;
94 * A monophonic phaser. If you want stereo, combine two :)
95 * Also, gave up on using template args for signal type.
97 template<int MaxStages
>
98 class simple_phaser
: public modulation_effect
101 float base_frq
, mod_depth
, fb
;
104 dsp::onepole
<float, float> stage1
;
105 float x1
[MaxStages
], y1
[MaxStages
];
117 float get_base_frq() {
120 void set_base_frq(float _base_frq
) {
121 base_frq
= _base_frq
;
126 void set_stages(int _stages
) {
127 if (_stages
> stages
)
129 for (int i
= stages
; i
< _stages
; i
++)
131 x1
[i
] = x1
[stages
-1];
132 y1
[i
] = y1
[stages
-1];
137 float get_mod_depth() {
140 void set_mod_depth(float _mod_depth
) {
141 mod_depth
= _mod_depth
;
146 void set_fb(float fb
) {
149 virtual void setup(int sample_rate
) {
150 modulation_effect::setup(sample_rate
);
158 for (int i
= 0; i
< MaxStages
; i
++)
162 inline void control_step()
165 int v
= phase
.get() + 0x40000000;
168 // triangle wave, range from 0 to INT_MAX
169 double vf
= (double)((v
>> 16) * (1.0 / 16384.0) - 1);
171 float freq
= base_frq
* pow(2.0, vf
* mod_depth
/ 1200.0);
172 freq
= dsp::clip
<float>(freq
, 10.0, 0.49 * sample_rate
);
173 stage1
.set_ap_w(freq
* (M_PI
/ 2.0) * odsr
);
174 phase
+= dphase
* 32;
175 for (int i
= 0; i
< stages
; i
++)
177 dsp::sanitize(x1
[i
]);
178 dsp::sanitize(y1
[i
]);
180 dsp::sanitize(state
);
182 void process(float *buf_out
, float *buf_in
, int nsamples
) {
183 for (int i
=0; i
<nsamples
; i
++) {
187 float in
= *buf_in
++;
188 float fd
= in
+ state
* fb
;
189 for (int j
= 0; j
< stages
; j
++)
190 fd
= stage1
.process_ap(fd
, x1
[j
], y1
[j
]);
193 float sdry
= in
* gs_dry
.get();
194 float swet
= fd
* gs_wet
.get();
195 *buf_out
++ = sdry
+ swet
;
198 float freq_gain(float freq
, float sr
)
200 typedef std::complex<double> cfloat
;
201 freq
*= 2.0 * M_PI
/ sr
;
202 cfloat z
= 1.0 / exp(cfloat(0.0, freq
)); // z^-1
204 cfloat p
= cfloat(1.0);
205 cfloat stg
= stage1
.h_z(z
);
207 for (int i
= 0; i
< stages
; i
++)
210 p
= p
/ (cfloat(1.0) - cfloat(fb
) * p
);
211 return std::abs(cfloat(gs_dry
.get_last()) + cfloat(gs_wet
.get_last()) * p
);
216 * Base class for chorus and flanger. Wouldn't be needed if it wasn't
217 * for odd behaviour of GCC when deriving templates from template
218 * base classes (not seeing fields from base classes!).
220 class chorus_base
: public modulation_effect
223 int min_delay_samples
, mod_depth_samples
;
224 float min_delay
, mod_depth
;
225 sine_table
<int, 4096, 65536> sine
;
227 float get_min_delay() {
230 void set_min_delay(float min_delay
) {
231 this->min_delay
= min_delay
;
232 this->min_delay_samples
= (int)(min_delay
* 65536.0 * sample_rate
);
234 float get_mod_depth() {
237 void set_mod_depth(float mod_depth
) {
238 this->mod_depth
= mod_depth
;
239 // 128 because it's then multiplied by (hopefully) a value of 32768..-32767
240 this->mod_depth_samples
= (int)(mod_depth
* 32.0 * sample_rate
);
245 * Single-tap chorus without feedback.
246 * Perhaps MaxDelay should be a bit longer!
248 template<class T
, int MaxDelay
=512>
249 class simple_chorus
: public chorus_base
252 simple_delay
<MaxDelay
,T
> delay
;
265 virtual void setup(int sample_rate
) {
266 modulation_effect::setup(sample_rate
);
268 set_min_delay(get_min_delay());
269 set_mod_depth(get_mod_depth());
271 template<class OutIter
, class InIter
>
272 void process(OutIter buf_out
, InIter buf_in
, int nsamples
) {
273 int mds
= min_delay_samples
+ mod_depth_samples
* 1024 + 2*65536;
274 int mdepth
= mod_depth_samples
;
275 for (int i
=0; i
<nsamples
; i
++) {
277 unsigned int ipart
= phase
.ipart();
279 float in
= *buf_in
++;
280 int lfo
= phase
.lerp_by_fract_int
<int, 14, int>(sine
.data
[ipart
], sine
.data
[ipart
+1]);
281 int v
= mds
+ (mdepth
* lfo
>> 6);
282 // if (!(i & 7)) printf("%d\n", v);
285 T fd
; // signal from delay's output
286 delay
.get_interp(fd
, ifv
, (v
& 0xFFFF)*(1.0/65536.0));
287 T sdry
= in
* gs_dry
.get();
288 T swet
= fd
* gs_wet
.get();
289 *buf_out
++ = sdry
+ swet
;
295 * Single-tap flanger (chorus plus feedback).
297 template<class T
, int MaxDelay
=1024>
298 class simple_flanger
: public chorus_base
301 simple_delay
<MaxDelay
,T
> delay
;
303 int last_delay_pos
, last_actual_delay_pos
;
304 int ramp_pos
, ramp_delay_pos
;
313 virtual void setup(int sample_rate
) {
314 this->sample_rate
= sample_rate
;
315 this->odsr
= 1.0 / sample_rate
;
318 set_rate(get_rate());
319 set_min_delay(get_min_delay());
324 void set_fb(float fb
) {
327 template<class OutIter
, class InIter
>
328 void process(OutIter buf_out
, InIter buf_in
, int nsamples
) {
331 int mds
= this->min_delay_samples
+ this->mod_depth_samples
* 1024 + 2 * 65536;
332 int mdepth
= this->mod_depth_samples
;
334 unsigned int ipart
= this->phase
.ipart();
335 int lfo
= phase
.lerp_by_fract_int
<int, 14, int>(this->sine
.data
[ipart
], this->sine
.data
[ipart
+1]);
336 delay_pos
= mds
+ (mdepth
* lfo
>> 6);
338 if (delay_pos
!= last_delay_pos
|| ramp_pos
< 1024)
340 if (delay_pos
!= last_delay_pos
) {
341 // we need to ramp from what the delay tap length actually was,
342 // not from old (ramp_delay_pos) or desired (delay_pos) tap length
343 ramp_delay_pos
= last_actual_delay_pos
;
348 for (int i
=0; i
<nsamples
; i
++) {
349 float in
= *buf_in
++;
350 T fd
; // signal from delay's output
351 dp
= (((int64_t)ramp_delay_pos
) * (1024 - ramp_pos
) + ((int64_t)delay_pos
) * ramp_pos
) >> 10;
353 if (ramp_pos
> 1024) ramp_pos
= 1024;
354 this->delay
.get_interp(fd
, dp
>> 16, (dp
& 0xFFFF)*(1.0/65536.0));
356 T sdry
= in
* this->dry
;
357 T swet
= fd
* this->wet
;
358 *buf_out
++ = sdry
+ swet
;
359 this->delay
.put(in
+fb
*fd
);
361 this->phase
+= this->dphase
;
362 ipart
= this->phase
.ipart();
363 lfo
= phase
.lerp_by_fract_int
<int, 14, int>(this->sine
.data
[ipart
], this->sine
.data
[ipart
+1]);
364 delay_pos
= mds
+ (mdepth
* lfo
>> 6);
366 last_actual_delay_pos
= dp
;
369 for (int i
=0; i
<nsamples
; i
++) {
370 float in
= *buf_in
++;
371 T fd
; // signal from delay's output
372 this->delay
.get_interp(fd
, delay_pos
>> 16, (delay_pos
& 0xFFFF)*(1.0/65536.0));
374 T sdry
= in
* this->gs_dry
.get();
375 T swet
= fd
* this->gs_wet
.get();
376 *buf_out
++ = sdry
+ swet
;
377 this->delay
.put(in
+fb
*fd
);
379 this->phase
+= this->dphase
;
380 ipart
= this->phase
.ipart();
381 lfo
= phase
.lerp_by_fract_int
<int, 14, int>(this->sine
.data
[ipart
], this->sine
.data
[ipart
+1]);
382 delay_pos
= mds
+ (mdepth
* lfo
>> 6);
384 last_actual_delay_pos
= delay_pos
;
386 last_delay_pos
= delay_pos
;
388 float freq_gain(float freq
, float sr
)
390 typedef std::complex<double> cfloat
;
391 freq
*= 2.0 * M_PI
/ sr
;
392 cfloat z
= 1.0 / exp(cfloat(0.0, freq
)); // z^-1
394 float ldp
= last_delay_pos
/ 65536.0;
395 float fldp
= floor(ldp
);
396 cfloat zn
= std::pow(z
, fldp
); // z^-N
397 cfloat zn1
= zn
* z
; // z^-(N+1)
398 // simulate a lerped comb filter - H(z) = 1 / (1 + fb * (lerp(z^-N, z^-(N+1), fracpos))), N = int(pos), fracpos = pos - int(pos)
399 cfloat delayed
= zn
+ (zn1
- zn
) * cfloat(ldp
- fldp
);
400 cfloat h
= cfloat(delayed
) / (cfloat(1.0) - cfloat(fb
) * delayed
);
401 // mix with dry signal
402 float v
= std::abs(cfloat(gs_dry
.get_last()) + cfloat(gs_wet
.get_last()) * h
);
408 * A classic allpass loop reverb with modulated allpass filter.
409 * Just started implementing it, so there is no control over many
413 class reverb
: public audio_effect
415 simple_delay
<2048, T
> apL1
, apL2
, apL3
, apL4
, apL5
, apL6
;
416 simple_delay
<2048, T
> apR1
, apR2
, apR3
, apR4
, apR5
, apR6
;
417 fixed_point
<unsigned int, 25> phase
, dphase
;
418 sine_table
<int, 128, 10000> sine
;
419 onepole
<T
> lp_left
, lp_right
;
420 T old_left
, old_right
;
422 float time
, fb
, cutoff
, diffusion
;
424 float ldec
[6], rdec
[6];
437 virtual void setup(int sample_rate
) {
450 tl
[0] = 397 << 16, tr
[0] = 383 << 16;
451 tl
[1] = 457 << 16, tr
[1] = 429 << 16;
452 tl
[2] = 549 << 16, tr
[2] = 631 << 16;
453 tl
[3] = 649 << 16, tr
[3] = 756 << 16;
454 tl
[4] = 773 << 16, tr
[4] = 803 << 16;
455 tl
[5] = 877 << 16, tr
[5] = 901 << 16;
458 tl
[0] = 697 << 16, tr
[0] = 783 << 16;
459 tl
[1] = 957 << 16, tr
[1] = 929 << 16;
460 tl
[2] = 649 << 16, tr
[2] = 531 << 16;
461 tl
[3] = 1049 << 16, tr
[3] = 1177 << 16;
462 tl
[4] = 473 << 16, tr
[4] = 501 << 16;
463 tl
[5] = 587 << 16, tr
[5] = 681 << 16;
467 tl
[0] = 697 << 16, tr
[0] = 783 << 16;
468 tl
[1] = 957 << 16, tr
[1] = 929 << 16;
469 tl
[2] = 649 << 16, tr
[2] = 531 << 16;
470 tl
[3] = 1249 << 16, tr
[3] = 1377 << 16;
471 tl
[4] = 1573 << 16, tr
[4] = 1671 << 16;
472 tl
[5] = 1877 << 16, tr
[5] = 1781 << 16;
475 tl
[0] = 1097 << 16, tr
[0] = 1087 << 16;
476 tl
[1] = 1057 << 16, tr
[1] = 1031 << 16;
477 tl
[2] = 1049 << 16, tr
[2] = 1039 << 16;
478 tl
[3] = 1083 << 16, tr
[3] = 1055 << 16;
479 tl
[4] = 1075 << 16, tr
[4] = 1099 << 16;
480 tl
[5] = 1003 << 16, tr
[5] = 1073 << 16;
483 tl
[0] = 197 << 16, tr
[0] = 133 << 16;
484 tl
[1] = 357 << 16, tr
[1] = 229 << 16;
485 tl
[2] = 549 << 16, tr
[2] = 431 << 16;
486 tl
[3] = 949 << 16, tr
[3] = 1277 << 16;
487 tl
[4] = 1173 << 16, tr
[4] = 1671 << 16;
488 tl
[5] = 1477 << 16, tr
[5] = 1881 << 16;
491 tl
[0] = 197 << 16, tr
[0] = 133 << 16;
492 tl
[1] = 257 << 16, tr
[1] = 179 << 16;
493 tl
[2] = 549 << 16, tr
[2] = 431 << 16;
494 tl
[3] = 619 << 16, tr
[3] = 497 << 16;
495 tl
[4] = 1173 << 16, tr
[4] = 1371 << 16;
496 tl
[5] = 1577 << 16, tr
[5] = 1881 << 16;
500 float fDec
=1000 + 2400.f
* diffusion
;
501 for (int i
= 0 ; i
< 6; i
++) {
502 ldec
[i
]=exp(-float(tl
[i
] >> 16) / fDec
),
503 rdec
[i
]=exp(-float(tr
[i
] >> 16) / fDec
);
509 void set_time(float time
) {
511 // fb = pow(1.0f/4096.0f, (float)(1700/(time*sr)));
512 fb
= 1.0 - 0.3 / (time
* sr
/ 44100.0);
517 void set_type(int type
) {
521 float get_diffusion() {
524 void set_diffusion(float diffusion
) {
525 this->diffusion
= diffusion
;
528 void set_type_and_diffusion(int type
, float diffusion
) {
530 this->diffusion
= diffusion
;
537 void set_fb(float fb
)
544 void set_cutoff(float cutoff
) {
545 this->cutoff
= cutoff
;
546 lp_left
.set_lp(cutoff
,sr
);
547 lp_right
.set_lp(cutoff
,sr
);
551 apL1
.reset();apR1
.reset();
552 apL2
.reset();apR2
.reset();
553 apL3
.reset();apR3
.reset();
554 apL4
.reset();apR4
.reset();
555 apL5
.reset();apR5
.reset();
556 apL6
.reset();apR6
.reset();
557 lp_left
.reset();lp_right
.reset();
558 old_left
= 0; old_right
= 0;
560 void process(T
&left
, T
&right
)
562 unsigned int ipart
= phase
.ipart();
564 // the interpolated LFO might be an overkill here
565 int lfo
= phase
.lerp_by_fract_int
<int, 14, int>(sine
.data
[ipart
], sine
.data
[ipart
+1]) >> 2;
569 left
= apL1
.process_allpass_comb_lerp16(left
, tl
[0] - 45*lfo
, ldec
[0]);
570 left
= apL2
.process_allpass_comb_lerp16(left
, tl
[1] + 47*lfo
, ldec
[1]);
571 float out_left
= left
;
572 left
= apL3
.process_allpass_comb_lerp16(left
, tl
[2] + 54*lfo
, ldec
[2]);
573 left
= apL4
.process_allpass_comb_lerp16(left
, tl
[3] - 69*lfo
, ldec
[3]);
574 left
= apL5
.process_allpass_comb_lerp16(left
, tl
[4] + 69*lfo
, ldec
[4]);
575 left
= apL6
.process_allpass_comb_lerp16(left
, tl
[5] - 46*lfo
, ldec
[5]);
576 old_left
= lp_left
.process(left
* fb
);
580 right
= apR1
.process_allpass_comb_lerp16(right
, tr
[0] - 45*lfo
, rdec
[0]);
581 right
= apR2
.process_allpass_comb_lerp16(right
, tr
[1] + 47*lfo
, rdec
[1]);
582 float out_right
= right
;
583 right
= apR3
.process_allpass_comb_lerp16(right
, tr
[2] + 54*lfo
, rdec
[2]);
584 right
= apR4
.process_allpass_comb_lerp16(right
, tr
[3] - 69*lfo
, rdec
[3]);
585 right
= apR5
.process_allpass_comb_lerp16(right
, tr
[4] + 69*lfo
, rdec
[4]);
586 right
= apR6
.process_allpass_comb_lerp16(right
, tr
[5] - 46*lfo
, rdec
[5]);
587 old_right
= lp_right
.process(right
* fb
);
590 left
= out_left
, right
= out_right
;
592 void extra_sanitize()
599 class filter_module_iface
602 virtual void calculate_filter(float freq
, float q
, int mode
, float gain
= 1.0) = 0;
603 virtual void filter_activate() = 0;
604 virtual void sanitize() = 0;
605 virtual int process_channel(uint16_t channel_no
, float *in
, float *out
, uint32_t numsamples
, int inmask
) = 0;
606 virtual float freq_gain(int subindex
, float freq
, float srate
) = 0;
608 virtual ~filter_module_iface() {}
612 class biquad_filter_module
: public filter_module_iface
615 dsp::biquad_d1
<float> left
[3], right
[3];
621 enum { mode_12db_lp
= 0, mode_24db_lp
= 1, mode_36db_lp
= 2,
622 mode_12db_hp
= 3, mode_24db_hp
= 4, mode_36db_hp
= 5,
623 mode_6db_bp
= 6, mode_12db_bp
= 7, mode_18db_bp
= 8,
624 mode_6db_br
= 9, mode_12db_br
= 10, mode_18db_br
= 11,
629 biquad_filter_module() : order(0) {}
631 void calculate_filter(float freq
, float q
, int mode
, float gain
= 1.0)
633 if (mode
<= mode_36db_lp
) {
635 left
[0].set_lp_rbj(freq
, pow(q
, 1.0 / order
), srate
, gain
);
636 } else if ( mode_12db_hp
<= mode
&& mode
<= mode_36db_hp
) {
637 order
= mode
- mode_12db_hp
+ 1;
638 left
[0].set_hp_rbj(freq
, pow(q
, 1.0 / order
), srate
, gain
);
639 } else if ( mode_6db_bp
<= mode
&& mode
<= mode_18db_bp
) {
640 order
= mode
- mode_6db_bp
+ 1;
641 left
[0].set_bp_rbj(freq
, pow(q
, 1.0 / order
), srate
, gain
);
642 } else { // mode_6db_br <= mode <= mode_18db_br
643 order
= mode
- mode_6db_br
+ 1;
644 left
[0].set_br_rbj(freq
, order
* 0.1 * q
, srate
, gain
);
647 right
[0].copy_coeffs(left
[0]);
648 for (int i
= 1; i
< order
; i
++) {
649 left
[i
].copy_coeffs(left
[0]);
650 right
[i
].copy_coeffs(left
[0]);
654 void filter_activate()
656 for (int i
=0; i
< order
; i
++) {
664 for (int i
=0; i
< order
; i
++) {
670 inline int process_channel(uint16_t channel_no
, float *in
, float *out
, uint32_t numsamples
, int inmask
) {
671 dsp::biquad_d1
<float> *filter
;
672 switch (channel_no
) {
689 for (uint32_t i
= 0; i
< numsamples
; i
++)
690 out
[i
] = filter
[0].process(in
[i
]);
693 for (uint32_t i
= 0; i
< numsamples
; i
++)
694 out
[i
] = filter
[1].process(filter
[0].process(in
[i
]));
697 for (uint32_t i
= 0; i
< numsamples
; i
++)
698 out
[i
] = filter
[2].process(filter
[1].process(filter
[0].process(in
[i
])));
702 if (filter
[order
- 1].empty())
706 for (uint32_t i
= 0; i
< numsamples
; i
++)
707 out
[i
] = filter
[0].process_zeroin();
710 if (filter
[0].empty())
711 for (uint32_t i
= 0; i
< numsamples
; i
++)
712 out
[i
] = filter
[1].process_zeroin();
714 for (uint32_t i
= 0; i
< numsamples
; i
++)
715 out
[i
] = filter
[1].process(filter
[0].process_zeroin());
718 if (filter
[1].empty())
719 for (uint32_t i
= 0; i
< numsamples
; i
++)
720 out
[i
] = filter
[2].process_zeroin();
722 for (uint32_t i
= 0; i
< numsamples
; i
++)
723 out
[i
] = filter
[2].process(filter
[1].process(filter
[0].process_zeroin()));
727 for (int i
= 0; i
< order
; i
++)
728 filter
[i
].sanitize();
729 return filter
[order
- 1].empty() ? 0 : inmask
;
732 float freq_gain(int subindex
, float freq
, float srate
)
735 for (int j
= 0; j
< order
; j
++)
736 level
*= left
[j
].freq_gain(freq
, srate
);
742 { to keep editor happy