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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #ifndef __CALF_AUDIOFX_H
22 #define __CALF_AUDIOFX_H
26 #include <calf/biquad.h>
27 #include <calf/onepole.h>
28 #include "primitives.h"
30 #include "fixed_point.h"
35 }; to keep editor happy
39 * Audio effect base class. Not really useful until it gets more developed.
44 virtual void setup(int sample_rate
)=0;
45 virtual ~audio_effect() {}
48 class modulation_effect
: public audio_effect
52 float rate
, wet
, dry
, odsr
;
53 gain_smoothing gs_wet
, gs_dry
;
55 fixed_point
<unsigned int, 20> phase
, dphase
;
59 void set_rate(float rate
) {
61 dphase
= rate
/sample_rate
*4096;
66 void set_wet(float wet
) {
68 gs_wet
.set_inertia(wet
);
73 void set_dry(float dry
) {
75 gs_dry
.set_inertia(dry
);
77 void reset_phase(float req_phase
)
79 phase
= req_phase
* 4096.0;
81 void inc_phase(float req_phase
)
83 phase
+= fixed_point
<unsigned int, 20>(req_phase
* 4096.0);
85 void setup(int sample_rate
)
87 this->sample_rate
= sample_rate
;
88 this->odsr
= 1.0 / sample_rate
;
95 * A monophonic phaser. If you want stereo, combine two :)
96 * Also, gave up on using template args for signal type.
98 template<int MaxStages
>
99 class simple_phaser
: public modulation_effect
102 float base_frq
, mod_depth
, fb
;
105 dsp::onepole
<float, float> stage1
;
106 float x1
[MaxStages
], y1
[MaxStages
];
118 float get_base_frq() {
121 void set_base_frq(float _base_frq
) {
122 base_frq
= _base_frq
;
127 void set_stages(int _stages
) {
128 if (_stages
> stages
)
130 for (int i
= stages
; i
< _stages
; i
++)
132 x1
[i
] = x1
[stages
-1];
133 y1
[i
] = y1
[stages
-1];
138 float get_mod_depth() {
141 void set_mod_depth(float _mod_depth
) {
142 mod_depth
= _mod_depth
;
147 void set_fb(float fb
) {
150 virtual void setup(int sample_rate
) {
151 modulation_effect::setup(sample_rate
);
159 for (int i
= 0; i
< MaxStages
; i
++)
163 inline void control_step()
166 int v
= phase
.get() + 0x40000000;
169 // triangle wave, range from 0 to INT_MAX
170 double vf
= (double)((v
>> 16) * (1.0 / 16384.0) - 1);
172 float freq
= base_frq
* pow(2.0, vf
* mod_depth
/ 1200.0);
173 freq
= dsp::clip
<float>(freq
, 10.0, 0.49 * sample_rate
);
174 stage1
.set_ap_w(freq
* (M_PI
/ 2.0) * odsr
);
175 phase
+= dphase
* 32;
176 for (int i
= 0; i
< stages
; i
++)
178 dsp::sanitize(x1
[i
]);
179 dsp::sanitize(y1
[i
]);
181 dsp::sanitize(state
);
183 void process(float *buf_out
, float *buf_in
, int nsamples
) {
184 for (int i
=0; i
<nsamples
; i
++) {
188 float in
= *buf_in
++;
189 float fd
= in
+ state
* fb
;
190 for (int j
= 0; j
< stages
; j
++)
191 fd
= stage1
.process_ap(fd
, x1
[j
], y1
[j
]);
194 float sdry
= in
* gs_dry
.get();
195 float swet
= fd
* gs_wet
.get();
196 *buf_out
++ = sdry
+ swet
;
199 float freq_gain(float freq
, float sr
)
201 typedef std::complex<double> cfloat
;
202 freq
*= 2.0 * M_PI
/ sr
;
203 cfloat z
= 1.0 / exp(cfloat(0.0, freq
)); // z^-1
205 cfloat p
= cfloat(1.0);
206 cfloat stg
= stage1
.h_z(z
);
208 for (int i
= 0; i
< stages
; i
++)
211 p
= p
/ (cfloat(1.0) - cfloat(fb
) * p
);
212 return std::abs(cfloat(gs_dry
.get_last()) + cfloat(gs_wet
.get_last()) * p
);
217 * Base class for chorus and flanger. Wouldn't be needed if it wasn't
218 * for odd behaviour of GCC when deriving templates from template
219 * base classes (not seeing fields from base classes!).
221 class chorus_base
: public modulation_effect
224 int min_delay_samples
, mod_depth_samples
;
225 float min_delay
, mod_depth
;
226 sine_table
<int, 4096, 65536> sine
;
228 float get_min_delay() {
231 void set_min_delay(float min_delay
) {
232 this->min_delay
= min_delay
;
233 this->min_delay_samples
= (int)(min_delay
* 65536.0 * sample_rate
);
235 float get_mod_depth() {
238 void set_mod_depth(float mod_depth
) {
239 this->mod_depth
= mod_depth
;
240 // 128 because it's then multiplied by (hopefully) a value of 32768..-32767
241 this->mod_depth_samples
= (int)(mod_depth
* 32.0 * sample_rate
);
246 * Single-tap chorus without feedback.
247 * Perhaps MaxDelay should be a bit longer!
249 template<class T
, int MaxDelay
=512>
250 class simple_chorus
: public chorus_base
253 simple_delay
<MaxDelay
,T
> delay
;
266 virtual void setup(int sample_rate
) {
267 modulation_effect::setup(sample_rate
);
269 set_min_delay(get_min_delay());
270 set_mod_depth(get_mod_depth());
272 template<class OutIter
, class InIter
>
273 void process(OutIter buf_out
, InIter buf_in
, int nsamples
) {
274 int mds
= min_delay_samples
+ mod_depth_samples
* 1024 + 2*65536;
275 int mdepth
= mod_depth_samples
;
276 for (int i
=0; i
<nsamples
; i
++) {
278 unsigned int ipart
= phase
.ipart();
280 float in
= *buf_in
++;
281 int lfo
= phase
.lerp_by_fract_int
<int, 14, int>(sine
.data
[ipart
], sine
.data
[ipart
+1]);
282 int v
= mds
+ (mdepth
* lfo
>> 6);
283 // if (!(i & 7)) printf("%d\n", v);
286 T fd
; // signal from delay's output
287 delay
.get_interp(fd
, ifv
, (v
& 0xFFFF)*(1.0/65536.0));
288 T sdry
= in
* gs_dry
.get();
289 T swet
= fd
* gs_wet
.get();
290 *buf_out
++ = sdry
+ swet
;
296 * Single-tap flanger (chorus plus feedback).
298 template<class T
, int MaxDelay
=1024>
299 class simple_flanger
: public chorus_base
302 simple_delay
<MaxDelay
,T
> delay
;
304 int last_delay_pos
, last_actual_delay_pos
;
305 int ramp_pos
, ramp_delay_pos
;
314 virtual void setup(int sample_rate
) {
315 this->sample_rate
= sample_rate
;
316 this->odsr
= 1.0 / sample_rate
;
319 set_rate(get_rate());
320 set_min_delay(get_min_delay());
325 void set_fb(float fb
) {
328 template<class OutIter
, class InIter
>
329 void process(OutIter buf_out
, InIter buf_in
, int nsamples
) {
332 int mds
= this->min_delay_samples
+ this->mod_depth_samples
* 1024 + 2 * 65536;
333 int mdepth
= this->mod_depth_samples
;
335 unsigned int ipart
= this->phase
.ipart();
336 int lfo
= phase
.lerp_by_fract_int
<int, 14, int>(this->sine
.data
[ipart
], this->sine
.data
[ipart
+1]);
337 delay_pos
= mds
+ (mdepth
* lfo
>> 6);
339 if (delay_pos
!= last_delay_pos
|| ramp_pos
< 1024)
341 if (delay_pos
!= last_delay_pos
) {
342 // we need to ramp from what the delay tap length actually was,
343 // not from old (ramp_delay_pos) or desired (delay_pos) tap length
344 ramp_delay_pos
= last_actual_delay_pos
;
349 for (int i
=0; i
<nsamples
; i
++) {
350 float in
= *buf_in
++;
351 T fd
; // signal from delay's output
352 dp
= (((int64_t)ramp_delay_pos
) * (1024 - ramp_pos
) + ((int64_t)delay_pos
) * ramp_pos
) >> 10;
354 if (ramp_pos
> 1024) ramp_pos
= 1024;
355 this->delay
.get_interp(fd
, dp
>> 16, (dp
& 0xFFFF)*(1.0/65536.0));
357 T sdry
= in
* this->dry
;
358 T swet
= fd
* this->wet
;
359 *buf_out
++ = sdry
+ swet
;
360 this->delay
.put(in
+fb
*fd
);
362 this->phase
+= this->dphase
;
363 ipart
= this->phase
.ipart();
364 lfo
= phase
.lerp_by_fract_int
<int, 14, int>(this->sine
.data
[ipart
], this->sine
.data
[ipart
+1]);
365 delay_pos
= mds
+ (mdepth
* lfo
>> 6);
367 last_actual_delay_pos
= dp
;
370 for (int i
=0; i
<nsamples
; i
++) {
371 float in
= *buf_in
++;
372 T fd
; // signal from delay's output
373 this->delay
.get_interp(fd
, delay_pos
>> 16, (delay_pos
& 0xFFFF)*(1.0/65536.0));
375 T sdry
= in
* this->gs_dry
.get();
376 T swet
= fd
* this->gs_wet
.get();
377 *buf_out
++ = sdry
+ swet
;
378 this->delay
.put(in
+fb
*fd
);
380 this->phase
+= this->dphase
;
381 ipart
= this->phase
.ipart();
382 lfo
= phase
.lerp_by_fract_int
<int, 14, int>(this->sine
.data
[ipart
], this->sine
.data
[ipart
+1]);
383 delay_pos
= mds
+ (mdepth
* lfo
>> 6);
385 last_actual_delay_pos
= delay_pos
;
387 last_delay_pos
= delay_pos
;
389 float freq_gain(float freq
, float sr
)
391 typedef std::complex<double> cfloat
;
392 freq
*= 2.0 * M_PI
/ sr
;
393 cfloat z
= 1.0 / exp(cfloat(0.0, freq
)); // z^-1
395 float ldp
= last_delay_pos
/ 65536.0;
396 float fldp
= floor(ldp
);
397 cfloat zn
= std::pow(z
, fldp
); // z^-N
398 cfloat zn1
= zn
* z
; // z^-(N+1)
399 // simulate a lerped comb filter - H(z) = 1 / (1 + fb * (lerp(z^-N, z^-(N+1), fracpos))), N = int(pos), fracpos = pos - int(pos)
400 cfloat delayed
= zn
+ (zn1
- zn
) * cfloat(ldp
- fldp
);
401 cfloat h
= cfloat(delayed
) / (cfloat(1.0) - cfloat(fb
) * delayed
);
402 // mix with dry signal
403 float v
= std::abs(cfloat(gs_dry
.get_last()) + cfloat(gs_wet
.get_last()) * h
);
409 * A classic allpass loop reverb with modulated allpass filter.
410 * Just started implementing it, so there is no control over many
414 class reverb
: public audio_effect
416 simple_delay
<2048, T
> apL1
, apL2
, apL3
, apL4
, apL5
, apL6
;
417 simple_delay
<2048, T
> apR1
, apR2
, apR3
, apR4
, apR5
, apR6
;
418 fixed_point
<unsigned int, 25> phase
, dphase
;
419 sine_table
<int, 128, 10000> sine
;
420 onepole
<T
> lp_left
, lp_right
;
421 T old_left
, old_right
;
423 float time
, fb
, cutoff
, diffusion
;
425 float ldec
[6], rdec
[6];
438 virtual void setup(int sample_rate
) {
451 tl
[0] = 397 << 16, tr
[0] = 383 << 16;
452 tl
[1] = 457 << 16, tr
[1] = 429 << 16;
453 tl
[2] = 549 << 16, tr
[2] = 631 << 16;
454 tl
[3] = 649 << 16, tr
[3] = 756 << 16;
455 tl
[4] = 773 << 16, tr
[4] = 803 << 16;
456 tl
[5] = 877 << 16, tr
[5] = 901 << 16;
459 tl
[0] = 697 << 16, tr
[0] = 783 << 16;
460 tl
[1] = 957 << 16, tr
[1] = 929 << 16;
461 tl
[2] = 649 << 16, tr
[2] = 531 << 16;
462 tl
[3] = 1049 << 16, tr
[3] = 1177 << 16;
463 tl
[4] = 473 << 16, tr
[4] = 501 << 16;
464 tl
[5] = 587 << 16, tr
[5] = 681 << 16;
468 tl
[0] = 697 << 16, tr
[0] = 783 << 16;
469 tl
[1] = 957 << 16, tr
[1] = 929 << 16;
470 tl
[2] = 649 << 16, tr
[2] = 531 << 16;
471 tl
[3] = 1249 << 16, tr
[3] = 1377 << 16;
472 tl
[4] = 1573 << 16, tr
[4] = 1671 << 16;
473 tl
[5] = 1877 << 16, tr
[5] = 1781 << 16;
476 tl
[0] = 1097 << 16, tr
[0] = 1087 << 16;
477 tl
[1] = 1057 << 16, tr
[1] = 1031 << 16;
478 tl
[2] = 1049 << 16, tr
[2] = 1039 << 16;
479 tl
[3] = 1083 << 16, tr
[3] = 1055 << 16;
480 tl
[4] = 1075 << 16, tr
[4] = 1099 << 16;
481 tl
[5] = 1003 << 16, tr
[5] = 1073 << 16;
484 tl
[0] = 197 << 16, tr
[0] = 133 << 16;
485 tl
[1] = 357 << 16, tr
[1] = 229 << 16;
486 tl
[2] = 549 << 16, tr
[2] = 431 << 16;
487 tl
[3] = 949 << 16, tr
[3] = 1277 << 16;
488 tl
[4] = 1173 << 16, tr
[4] = 1671 << 16;
489 tl
[5] = 1477 << 16, tr
[5] = 1881 << 16;
492 tl
[0] = 197 << 16, tr
[0] = 133 << 16;
493 tl
[1] = 257 << 16, tr
[1] = 179 << 16;
494 tl
[2] = 549 << 16, tr
[2] = 431 << 16;
495 tl
[3] = 619 << 16, tr
[3] = 497 << 16;
496 tl
[4] = 1173 << 16, tr
[4] = 1371 << 16;
497 tl
[5] = 1577 << 16, tr
[5] = 1881 << 16;
501 float fDec
=1000 + 2400.f
* diffusion
;
502 for (int i
= 0 ; i
< 6; i
++) {
503 ldec
[i
]=exp(-float(tl
[i
] >> 16) / fDec
),
504 rdec
[i
]=exp(-float(tr
[i
] >> 16) / fDec
);
510 void set_time(float time
) {
512 // fb = pow(1.0f/4096.0f, (float)(1700/(time*sr)));
513 fb
= 1.0 - 0.3 / (time
* sr
/ 44100.0);
518 void set_type(int type
) {
522 float get_diffusion() {
525 void set_diffusion(float diffusion
) {
526 this->diffusion
= diffusion
;
529 void set_type_and_diffusion(int type
, float diffusion
) {
531 this->diffusion
= diffusion
;
538 void set_fb(float fb
)
545 void set_cutoff(float cutoff
) {
546 this->cutoff
= cutoff
;
547 lp_left
.set_lp(cutoff
,sr
);
548 lp_right
.set_lp(cutoff
,sr
);
552 apL1
.reset();apR1
.reset();
553 apL2
.reset();apR2
.reset();
554 apL3
.reset();apR3
.reset();
555 apL4
.reset();apR4
.reset();
556 apL5
.reset();apR5
.reset();
557 apL6
.reset();apR6
.reset();
558 lp_left
.reset();lp_right
.reset();
559 old_left
= 0; old_right
= 0;
561 void process(T
&left
, T
&right
)
563 unsigned int ipart
= phase
.ipart();
565 // the interpolated LFO might be an overkill here
566 int lfo
= phase
.lerp_by_fract_int
<int, 14, int>(sine
.data
[ipart
], sine
.data
[ipart
+1]) >> 2;
570 left
= apL1
.process_allpass_comb_lerp16(left
, tl
[0] - 45*lfo
, ldec
[0]);
571 left
= apL2
.process_allpass_comb_lerp16(left
, tl
[1] + 47*lfo
, ldec
[1]);
572 float out_left
= left
;
573 left
= apL3
.process_allpass_comb_lerp16(left
, tl
[2] + 54*lfo
, ldec
[2]);
574 left
= apL4
.process_allpass_comb_lerp16(left
, tl
[3] - 69*lfo
, ldec
[3]);
575 left
= apL5
.process_allpass_comb_lerp16(left
, tl
[4] + 69*lfo
, ldec
[4]);
576 left
= apL6
.process_allpass_comb_lerp16(left
, tl
[5] - 46*lfo
, ldec
[5]);
577 old_left
= lp_left
.process(left
* fb
);
581 right
= apR1
.process_allpass_comb_lerp16(right
, tr
[0] - 45*lfo
, rdec
[0]);
582 right
= apR2
.process_allpass_comb_lerp16(right
, tr
[1] + 47*lfo
, rdec
[1]);
583 float out_right
= right
;
584 right
= apR3
.process_allpass_comb_lerp16(right
, tr
[2] + 54*lfo
, rdec
[2]);
585 right
= apR4
.process_allpass_comb_lerp16(right
, tr
[3] - 69*lfo
, rdec
[3]);
586 right
= apR5
.process_allpass_comb_lerp16(right
, tr
[4] + 69*lfo
, rdec
[4]);
587 right
= apR6
.process_allpass_comb_lerp16(right
, tr
[5] - 46*lfo
, rdec
[5]);
588 old_right
= lp_right
.process(right
* fb
);
591 left
= out_left
, right
= out_right
;
593 void extra_sanitize()
600 class filter_module_iface
603 virtual void calculate_filter(float freq
, float q
, int mode
, float gain
= 1.0) = 0;
604 virtual void filter_activate() = 0;
605 virtual void sanitize() = 0;
606 virtual int process_channel(uint16_t channel_no
, float *in
, float *out
, uint32_t numsamples
, int inmask
) = 0;
607 virtual float freq_gain(int subindex
, float freq
, float srate
) = 0;
609 virtual ~filter_module_iface() {}
613 class biquad_filter_module
: public filter_module_iface
616 dsp::biquad_d1
<float> left
[3], right
[3];
622 enum { mode_12db_lp
= 0, mode_24db_lp
= 1, mode_36db_lp
= 2,
623 mode_12db_hp
= 3, mode_24db_hp
= 4, mode_36db_hp
= 5,
624 mode_6db_bp
= 6, mode_12db_bp
= 7, mode_18db_bp
= 8,
625 mode_6db_br
= 9, mode_12db_br
= 10, mode_18db_br
= 11,
630 biquad_filter_module() : order(0) {}
632 void calculate_filter(float freq
, float q
, int mode
, float gain
= 1.0)
634 if (mode
<= mode_36db_lp
) {
636 left
[0].set_lp_rbj(freq
, pow(q
, 1.0 / order
), srate
, gain
);
637 } else if ( mode_12db_hp
<= mode
&& mode
<= mode_36db_hp
) {
638 order
= mode
- mode_12db_hp
+ 1;
639 left
[0].set_hp_rbj(freq
, pow(q
, 1.0 / order
), srate
, gain
);
640 } else if ( mode_6db_bp
<= mode
&& mode
<= mode_18db_bp
) {
641 order
= mode
- mode_6db_bp
+ 1;
642 left
[0].set_bp_rbj(freq
, pow(q
, 1.0 / order
), srate
, gain
);
643 } else { // mode_6db_br <= mode <= mode_18db_br
644 order
= mode
- mode_6db_br
+ 1;
645 left
[0].set_br_rbj(freq
, order
* 0.1 * q
, srate
, gain
);
648 right
[0].copy_coeffs(left
[0]);
649 for (int i
= 1; i
< order
; i
++) {
650 left
[i
].copy_coeffs(left
[0]);
651 right
[i
].copy_coeffs(left
[0]);
655 void filter_activate()
657 for (int i
=0; i
< order
; i
++) {
665 for (int i
=0; i
< order
; i
++) {
671 inline int process_channel(uint16_t channel_no
, float *in
, float *out
, uint32_t numsamples
, int inmask
) {
672 dsp::biquad_d1
<float> *filter
;
673 switch (channel_no
) {
690 for (uint32_t i
= 0; i
< numsamples
; i
++)
691 out
[i
] = filter
[0].process(in
[i
]);
694 for (uint32_t i
= 0; i
< numsamples
; i
++)
695 out
[i
] = filter
[1].process(filter
[0].process(in
[i
]));
698 for (uint32_t i
= 0; i
< numsamples
; i
++)
699 out
[i
] = filter
[2].process(filter
[1].process(filter
[0].process(in
[i
])));
703 if (filter
[order
- 1].empty())
707 for (uint32_t i
= 0; i
< numsamples
; i
++)
708 out
[i
] = filter
[0].process_zeroin();
711 if (filter
[0].empty())
712 for (uint32_t i
= 0; i
< numsamples
; i
++)
713 out
[i
] = filter
[1].process_zeroin();
715 for (uint32_t i
= 0; i
< numsamples
; i
++)
716 out
[i
] = filter
[1].process(filter
[0].process_zeroin());
719 if (filter
[1].empty())
720 for (uint32_t i
= 0; i
< numsamples
; i
++)
721 out
[i
] = filter
[2].process_zeroin();
723 for (uint32_t i
= 0; i
< numsamples
; i
++)
724 out
[i
] = filter
[2].process(filter
[1].process(filter
[0].process_zeroin()));
728 for (int i
= 0; i
< order
; i
++)
729 filter
[i
].sanitize();
730 return filter
[order
- 1].empty() ? 0 : inmask
;
733 float freq_gain(int subindex
, float freq
, float srate
)
736 for (int j
= 0; j
< order
; j
++)
737 level
*= left
[j
].freq_gain(freq
, srate
);
745 dsp::onepole
<float> lowcut
, highcut
;
746 float low_gain
, high_gain
;
755 inline float process(float v
)
757 v
= dsp::lerp(lowcut
.process_hp(v
), v
, low_gain
);
758 v
= dsp::lerp(highcut
.process_lp(v
), v
, high_gain
);
762 inline void copy_coeffs(const two_band_eq
&src
)
764 lowcut
.copy_coeffs(src
.lowcut
);
765 highcut
.copy_coeffs(src
.highcut
);
766 low_gain
= src
.low_gain
;
767 high_gain
= src
.high_gain
;
776 void set(float _low_freq
, float _low_gain
, float _high_freq
, float _high_gain
, float sr
)
778 lowcut
.set_hp(_low_freq
, sr
);
779 highcut
.set_lp(_high_freq
, sr
);
780 low_gain
= _low_gain
;
781 high_gain
= _high_gain
;
786 { to keep editor happy