1 /* Calf DSP Library
2  * Reusable audio effect classes.
3  *
4  * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
5  *
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.
10  *
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.
15  *
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
20  */
21 #ifndef CALF_AUDIOFX_H
22 #define CALF_AUDIOFX_H
23 
24 #include "biquad.h"
25 #include "delay.h"
26 #include "fixed_point.h"
27 #include "inertia.h"
28 #include "giface.h"
29 #include "onepole.h"
30 #include <complex>
31 
32 namespace calf_plugins {
33     struct cairo_iface;
34 };
35 
36 namespace dsp {
37 #if 0
38 }; to keep editor happy
39 #endif
40 
41 /**
42  * Audio effect base class. Not really useful until it gets more developed.
43  */
44 class audio_effect
45 {
46 public:
47     virtual void setup(int sample_rate)=0;
~audio_effect()48     virtual ~audio_effect() {}
49 };
50 
51 class modulation_effect: public audio_effect
52 {
53 protected:
54     int sample_rate, lfo_active;
55     float rate, wet, dry, odsr;
56     gain_smoothing gs_wet, gs_dry;
57 public:
58     fixed_point<unsigned int, 20> phase, dphase;
get_rate()59     float get_rate() const {
60         return rate;
61     }
set_rate(float rate)62     void set_rate(float rate) {
63         this->rate = rate;
64         dphase = rate/sample_rate*4096;
65     }
get_wet()66     float get_wet() const {
67         return wet;
68     }
set_wet(float wet)69     void set_wet(float wet) {
70         this->wet = wet;
71         gs_wet.set_inertia(wet);
72     }
get_dry()73     float get_dry() const {
74         return dry;
75     }
set_dry(float dry)76     void set_dry(float dry) {
77         this->dry = dry;
78         gs_dry.set_inertia(dry);
79     }
reset_phase(float req_phase)80     void reset_phase(float req_phase)
81     {
82         phase = req_phase * 4096.0;
83     }
inc_phase(float req_phase)84     void inc_phase(float req_phase)
85     {
86         phase += fixed_point<unsigned int, 20>(req_phase * 4096.0);
87     }
setup(int sample_rate)88     void setup(int sample_rate)
89     {
90         this->sample_rate = sample_rate;
91         this->odsr = 1.0 / sample_rate;
92         phase = 0;
93         lfo_active = 1;
94         set_rate(get_rate());
95     }
get_lfo_active()96     int get_lfo_active() const {
97         return lfo_active;
98     }
set_lfo_active(int i)99     void set_lfo_active(int i) {
100         this->lfo_active = i;
101     }
102 };
103 
104 /**
105  * A monophonic phaser. If you want stereo, combine two :)
106  * Also, gave up on using template args for signal type.
107  */
108 class simple_phaser: public modulation_effect
109 {
110 protected:
111     float base_frq, mod_depth, fb;
112     float state;
113     int cnt, stages, max_stages;
114     dsp::onepole<float, float> stage1;
115     float *x1, *y1;
116 public:
117     simple_phaser(int _max_stages, float *x1vals, float *y1vals);
118 
get_base_frq()119     float get_base_frq() const {
120         return base_frq;
121     }
set_base_frq(float _base_frq)122     void set_base_frq(float _base_frq) {
123         base_frq = _base_frq;
124     }
get_stages()125     int get_stages() const {
126         return stages;
127     }
128     void set_stages(int _stages);
129 
get_mod_depth()130     float get_mod_depth() const {
131         return mod_depth;
132     }
set_mod_depth(float _mod_depth)133     void set_mod_depth(float _mod_depth) {
134         mod_depth = _mod_depth;
135     }
136 
get_fb()137     float get_fb() const {
138         return fb;
139     }
set_fb(float fb)140     void set_fb(float fb) {
141         this->fb = fb;
142     }
143 
setup(int sample_rate)144     virtual void setup(int sample_rate) {
145         modulation_effect::setup(sample_rate);
146         reset();
147     }
148     void reset();
149     void control_step();
150     void process(float *buf_out, float *buf_in, int nsamples, bool active, float level_in = 1., float level_out = 1.);
151     float freq_gain(float freq, float sr) const;
152 };
153 
154 /**
155  * Base class for chorus and flanger. Wouldn't be needed if it wasn't
156  * for odd behaviour of GCC when deriving templates from template
157  * base classes (not seeing fields from base classes!).
158  */
159 class chorus_base: public modulation_effect
160 {
161 protected:
162     int min_delay_samples, mod_depth_samples;
163     float min_delay, mod_depth;
164     sine_table<int, 4096, 65536> sine;
165 public:
get_min_delay()166     float get_min_delay() const {
167         return min_delay;
168     }
set_min_delay(float min_delay)169     void set_min_delay(float min_delay) {
170         this->min_delay = min_delay;
171         this->min_delay_samples = (int)(min_delay * 65536.0 * sample_rate);
172     }
get_mod_depth()173     float get_mod_depth() const {
174         return mod_depth;
175     }
set_mod_depth(float mod_depth)176     void set_mod_depth(float mod_depth) {
177         this->mod_depth = mod_depth;
178         // 128 because it's then multiplied by (hopefully) a value of 32768..-32767
179         this->mod_depth_samples = (int)(mod_depth * 32.0 * sample_rate);
180     }
181 };
182 
183 /**
184  * Single-tap chorus without feedback.
185  * Perhaps MaxDelay should be a bit longer!
186  */
187 template<class T, int MaxDelay=512>
188 class simple_chorus: public chorus_base
189 {
190 protected:
191     simple_delay<MaxDelay,T> delay;
192 public:
simple_chorus()193     simple_chorus() {
194         rate = 0.63f;
195         dry = 0.5f;
196         wet = 0.5f;
197         min_delay = 0.005f;
198         mod_depth = 0.0025f;
199         setup(44100);
200     }
reset()201     void reset() {
202         delay.reset();
203     }
setup(int sample_rate)204     virtual void setup(int sample_rate) {
205         modulation_effect::setup(sample_rate);
206         delay.reset();
207         set_min_delay(get_min_delay());
208         set_mod_depth(get_mod_depth());
209     }
210     template<class OutIter, class InIter>
211     void process(OutIter buf_out, InIter buf_in, int nsamples, bool active, float level_in = 1., float level_out = 1.) {
212         int mds = min_delay_samples + mod_depth_samples * 1024 + 2*65536;
213         int mdepth = mod_depth_samples;
214         for (int i=0; i<nsamples; i++) {
215             if (lfo_active)
216                 phase += dphase;
217             unsigned int ipart = phase.ipart();
218 
219             float in = *buf_in++ * level_in;
220             int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]);
221             int v = mds + (mdepth * lfo >> 6);
222             // if (!(i & 7)) printf("%d\n", v);
223             int ifv = v >> 16;
224             delay.put(in);
225             T fd; // signal from delay's output
226             delay.get_interp(fd, ifv, (v & 0xFFFF)*(1.0/65536.0));
227             T sdry = in * gs_dry.get();
228             T swet = fd * gs_wet.get();
229             *buf_out++ = (sdry + (active ? swet : 0)) * level_out;
230         }
231     }
232 };
233 
234 /**
235  * Single-tap flanger (chorus plus feedback).
236  */
237 template<class T, int MaxDelay=1024>
238 class simple_flanger: public chorus_base
239 {
240 protected:
241     simple_delay<MaxDelay,T> delay;
242     float fb;
243     int last_delay_pos, last_actual_delay_pos;
244     int ramp_pos, ramp_delay_pos, lfo;
245 public:
simple_flanger()246     simple_flanger()
247     : fb(0) {}
reset()248     void reset() {
249         delay.reset();
250         last_delay_pos = last_actual_delay_pos = ramp_delay_pos = 0;
251         ramp_pos = 1024;
252     }
setup(int sample_rate)253     virtual void setup(int sample_rate) {
254         this->sample_rate = sample_rate;
255         this->odsr = 1.0 / sample_rate;
256         delay.reset();
257         phase = 0;
258         set_rate(get_rate());
259         set_min_delay(get_min_delay());
260     }
get_fb()261     float get_fb() const {
262         return fb;
263     }
set_fb(float fb)264     void set_fb(float fb) {
265         this->fb = fb;
266     }
267     template<class OutIter, class InIter>
268     void process(OutIter buf_out, InIter buf_in, int nsamples, bool active, float level_in = 1., float level_out = 1.) {
269         if (!nsamples)
270             return;
271         int mds = this->min_delay_samples + this->mod_depth_samples * 1024 + 2 * 65536;
272         int mdepth = this->mod_depth_samples;
273         int delay_pos;
274         unsigned int ipart = this->phase.ipart();
275         int lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
276         delay_pos = mds + (mdepth * lfo >> 6);
277 
278         if (delay_pos != last_delay_pos || ramp_pos < 1024)
279         {
280             if (delay_pos != last_delay_pos) {
281                 // we need to ramp from what the delay tap length actually was,
282                 // not from old (ramp_delay_pos) or desired (delay_pos) tap length
283                 ramp_delay_pos = last_actual_delay_pos;
284                 ramp_pos = 0;
285             }
286 
287             int64_t dp = 0;
288             for (int i=0; i<nsamples; i++) {
289                 float in = *buf_in++ * level_in;
290                 T fd; // signal from delay's output
291                 dp = (((int64_t)ramp_delay_pos) * (1024 - ramp_pos) + ((int64_t)delay_pos) * ramp_pos) >> 10;
292                 ramp_pos++;
293                 if (ramp_pos > 1024) ramp_pos = 1024;
294                 this->delay.get_interp(fd, dp >> 16, (dp & 0xFFFF)*(1.0/65536.0));
295                 sanitize(fd);
296                 T sdry = in * this->dry;
297                 T swet = fd * this->wet;
298                 *buf_out++ = (sdry + (active ? swet : 0)) * level_out;
299                 this->delay.put(in+fb*fd);
300 
301                 if (this->lfo_active)
302                     this->phase += this->dphase;
303                 ipart = this->phase.ipart();
304                 lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
305                 delay_pos = mds + (mdepth * lfo >> 6);
306             }
307             last_actual_delay_pos = dp;
308         }
309         else {
310             for (int i=0; i<nsamples; i++) {
311                 float in = *buf_in++ * level_in;
312                 T fd; // signal from delay's output
313                 this->delay.get_interp(fd, delay_pos >> 16, (delay_pos & 0xFFFF)*(1.0/65536.0));
314                 sanitize(fd);
315                 T sdry = in * this->gs_dry.get();
316                 T swet = fd * this->gs_wet.get();
317                 *buf_out++ = (sdry + (active ? swet : 0)) * level_out;
318                 this->delay.put(in+fb*fd);
319 
320                 if (this->lfo_active)
321                     this->phase += this->dphase;
322                 ipart = this->phase.ipart();
323                 lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
324                 delay_pos = mds + (mdepth * lfo >> 6);
325             }
326             last_actual_delay_pos = delay_pos;
327         }
328         last_delay_pos = delay_pos;
329     }
freq_gain(float freq,float sr)330     float freq_gain(float freq, float sr) const
331     {
332         typedef std::complex<double> cfloat;
333         freq *= 2.0 * M_PI / sr;
334         cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
335 
336         float ldp = last_delay_pos / 65536.0;
337         float fldp = floor(ldp);
338         cfloat zn = std::pow(z, fldp); // z^-N
339         cfloat zn1 = zn * z; // z^-(N+1)
340         // simulate a lerped comb filter - H(z) = 1 / (1 + fb * (lerp(z^-N, z^-(N+1), fracpos))), N = int(pos), fracpos = pos - int(pos)
341         cfloat delayed = zn + (zn1 - zn) * cfloat(ldp - fldp);
342         cfloat h = cfloat(delayed) / (cfloat(1.0) - cfloat(fb) * delayed);
343         // mix with dry signal
344         float v = std::abs(cfloat(gs_dry.get_last()) + cfloat(gs_wet.get_last()) * h);
345         return v;
346     }
347 };
348 
349 /**
350  * A classic allpass loop reverb with modulated allpass filter.
351  * Just started implementing it, so there is no control over many
352  * parameters.
353  */
354 class reverb: public audio_effect
355 {
356     simple_delay<2048, float> apL1, apL2, apL3, apL4, apL5, apL6;
357     simple_delay<2048, float> apR1, apR2, apR3, apR4, apR5, apR6;
358     fixed_point<unsigned int, 25> phase, dphase;
359     sine_table<int, 128, 10000> sine;
360     onepole<float> lp_left, lp_right;
361     float old_left, old_right;
362     int type;
363     float time, fb, cutoff, diffusion;
364     int tl[6], tr[6];
365     float ldec[6], rdec[6];
366 
367     int sr;
368 public:
reverb()369     reverb()
370     {
371         phase = 0.0;
372         time = 1.0;
373         cutoff = 9000;
374         type = 2;
375         diffusion = 1.f;
376         setup(44100);
377     }
setup(int sample_rate)378     virtual void setup(int sample_rate) {
379         sr = sample_rate;
380         set_time(time);
381         set_cutoff(cutoff);
382         phase = 0.0;
383         dphase = 0.5*128/sr;
384         update_times();
385     }
386     void update_times();
get_time()387     float get_time() const {
388         return time;
389     }
set_time(float time)390     void set_time(float time) {
391         this->time = time;
392         // fb = pow(1.0f/4096.0f, (float)(1700/(time*sr)));
393         fb = 1.0 - 0.3 / (time * sr / 44100.0);
394     }
get_type()395     float get_type() const {
396         return type;
397     }
set_type(int type)398     void set_type(int type) {
399         this->type = type;
400         update_times();
401     }
get_diffusion()402     float get_diffusion() const {
403         return diffusion;
404     }
set_diffusion(float diffusion)405     void set_diffusion(float diffusion) {
406         this->diffusion = diffusion;
407         update_times();
408     }
set_type_and_diffusion(int type,float diffusion)409     void set_type_and_diffusion(int type, float diffusion) {
410         this->type = type;
411         this->diffusion = diffusion;
412         update_times();
413     }
get_fb()414     float get_fb() const
415     {
416         return this->fb;
417     }
set_fb(float fb)418     void set_fb(float fb)
419     {
420         this->fb = fb;
421     }
get_cutoff()422     float get_cutoff() const {
423         return cutoff;
424     }
set_cutoff(float cutoff)425     void set_cutoff(float cutoff) {
426         this->cutoff = cutoff;
427         lp_left.set_lp(cutoff,sr);
428         lp_right.set_lp(cutoff,sr);
429     }
430     void reset();
431     void process(float &left, float &right);
extra_sanitize()432     void extra_sanitize()
433     {
434         lp_left.sanitize();
435         lp_right.sanitize();
436     }
437 };
438 
439 class filter_module_iface
440 {
441 public:
442     virtual void  calculate_filter(float freq, float q, int mode, float gain = 1.0) = 0;
443     virtual void  filter_activate() = 0;
444     virtual void  sanitize() = 0;
445     virtual int   process_channel(uint16_t channel_no, const float *in, float *out, uint32_t numsamples, int inmask, float lvl_in = 1., float lvl_out = 1.) = 0;
446     virtual float freq_gain(int subindex, float freq, float srate) const = 0;
447 
~filter_module_iface()448     virtual ~filter_module_iface() {}
449 };
450 
451 
452 class biquad_filter_module: public filter_module_iface
453 {
454 private:
455     dsp::biquad_d1 left[3], right[3];
456     int order;
457 
458 public:
459     uint32_t srate;
460 
461     enum { mode_12db_lp = 0, mode_24db_lp = 1, mode_36db_lp = 2,
462            mode_12db_hp = 3, mode_24db_hp = 4, mode_36db_hp = 5,
463            mode_6db_bp  = 6, mode_12db_bp = 7, mode_18db_bp = 8,
464            mode_6db_br  = 9, mode_12db_br = 10, mode_18db_br = 11,
465            mode_allpass = 12,
466            mode_count
467     };
468 
469 public:
biquad_filter_module()470     biquad_filter_module()
471     : order(0) {}
472     /// Calculate filter coefficients based on parameters - cutoff/center frequency, q, filter type, output gain
473     void calculate_filter(float freq, float q, int mode, float gain = 1.0);
474     /// Reset filter state
475     void filter_activate();
476     /// Remove denormals
477     void sanitize();
478     /// Process a single channel (float buffer) of data
479     int process_channel(uint16_t channel_no, const float *in, float *out, uint32_t numsamples, int inmask, float lvl_in = 1., float lvl_out = 1.);
480     /// Determine gain (|H(z)|) for a given frequency
481     float freq_gain(int subindex, float freq, float srate) const;
482 };
483 
484 class two_band_eq
485 {
486 private:
487     dsp::onepole<float> lowcut, highcut;
488     float low_gain, high_gain;
489 
490 public:
reset()491     void reset()
492     {
493         lowcut.reset();
494         highcut.reset();
495     }
496 
process(float v)497     inline float process(float v)
498     {
499         v = dsp::lerp(lowcut.process_hp(v), v, low_gain);
500         v = dsp::lerp(highcut.process_lp(v), v, high_gain);
501         return v;
502     }
503 
copy_coeffs(const two_band_eq & src)504     inline void copy_coeffs(const two_band_eq &src)
505     {
506         lowcut.copy_coeffs(src.lowcut);
507         highcut.copy_coeffs(src.highcut);
508         low_gain = src.low_gain;
509         high_gain = src.high_gain;
510     }
511 
sanitize()512     void sanitize()
513     {
514         lowcut.sanitize();
515         highcut.sanitize();
516     }
517 
set(float _low_freq,float _low_gain,float _high_freq,float _high_gain,float sr)518     void set(float _low_freq, float _low_gain, float _high_freq, float _high_gain, float sr)
519     {
520         lowcut.set_hp(_low_freq, sr);
521         highcut.set_lp(_high_freq, sr);
522         low_gain = _low_gain;
523         high_gain = _high_gain;
524     }
525 };
526 
527 /// LFO module by Markus
528 /// This module provides simple LFO's (sine=0, triangle=1, square=2, saw_up=3, saw_down=4)
529 /// get_value() returns a value between -1 and 1
530 class simple_lfo {
531 private:
532     float phase, freq, offset, amount, pwidth;
533     int mode;
534     uint32_t srate;
535     bool is_active;
536 public:
537     simple_lfo();
538     void set_params(float f, int m, float o, uint32_t sr, float amount = 1.f, float pwidth = 1.f);
539     void set_freq(float f);
540     void set_mode(int m);
541     void set_amount(float a);
542     void set_offset(float o);
543     void set_pwidth(float p);
544     float get_value();
545     void advance(uint32_t count);
546     void set_phase(float ph);
547     void activate();
548     void deactivate();
549     float get_value_from_phase(float ph) const;
550     bool get_graph(float *data, int points, calf_plugins::cairo_iface *context, int *mode) const;
551     bool get_dot(float &x, float &y, int &size, calf_plugins::cairo_iface *context) const;
552 };
553 
554 
555 /// Lookahead Limiter by Markus Schmidt and Christian Holschuh
556 class lookahead_limiter {
557 private:
558 public:
559     float limit, attack, release, weight;
560     uint32_t srate;
561     float att; // a coefficient the output is multiplied with
562     float att_max; // a memory for the highest attenuation - used for display
563     int pos; // where we are actually in our sample buffer
564     int buffer_size;
565     int overall_buffer_size;
566     bool is_active;
567     bool debug;
568     bool auto_release;
569     bool asc_active;
570     float *buffer;
571     int channels;
572     float delta;
573     float _delta;
574     float peak;
575     unsigned int over_s;
576     float over_c;
577     bool use_multi;
578     unsigned int id;
579     bool _sanitize;
580     int nextiter;
581     int nextlen;
582     int * nextpos;
583     float * nextdelta;
584     int asc_c;
585     float asc;
586     int asc_pos;
587     bool asc_changed;
588     float asc_coeff;
589     bool _asc_used;
denormal(volatile float * f)590     static inline void denormal(volatile float *f) {
591         *f += 1e-18;
592         *f -= 1e-18;
593     }
594     inline float get_rdelta(float peak, float _limit, float _att, bool _asc = true);
595     void reset();
596     void reset_asc();
597     bool get_asc();
598     lookahead_limiter();
599     ~lookahead_limiter();
600     void set_multi(bool set);
601     void process(float &left, float &right, float *multi_buffer);
602     void set_sample_rate(uint32_t sr);
603     void set_params(float l, float a, float r, float weight = 1.f, bool ar = false, float arc = 1.f, bool d = false);
604     float get_attenuation();
605     void activate();
606     void deactivate();
607 };
608 
609 class transients {
610 private:
611     double attack_coef, release_coef;
612 public:
613     double envelope, attack, release;
614     bool sustain_ended;
615     double old_return, new_return, maxdelta, relfac;
616     float att_time, att_level, rel_time, rel_level, sust_thres;
617     static const int looksize = 101;
618     int lookahead, lookpos;
619     float *lookbuf;
620     int channels;
621     uint32_t srate;
622     transients();
623     ~transients();
624     void calc_relfac();
625     void process(float *in, float s);
626     void waveshape(float *in);
627     void set_channels(int ch);
628     void set_sample_rate(uint32_t sr);
629     void set_params(float att_t, float att_l, float rel_t, float rel_l, float sust_th, int look);
630     int cnt;
631 };
632 
633 
634 class crossover {
635 private:
636 public:
637     int channels, bands, mode;
638     float freq[8], active[8], level[8], out[8][8];
639     dsp::biquad_d2 lp[8][8][4], hp[8][8][4];
640     mutable int redraw_graph;
641     uint32_t srate;
642     crossover();
643     void process(float *data);
644     float get_value(int c, int b);
645     void set_sample_rate(uint32_t sr);
646     float set_filter(int b, float f, bool force = false);
647     void set_level(int b, float l);
648     void set_active(int b, bool a);
649     void set_mode(int m);
650     int get_filter_count() const;
651     void init(int c, int b, uint32_t sr);
652     virtual bool get_graph(int subindex, int phase, float *data, int points, calf_plugins::cairo_iface *context, int *mode) const;
653     bool get_layers(int index, int generation, unsigned int &layers) const;
654 };
655 
656 class bitreduction
657 {
658 private:
659 public:
660     float morph, coeff, dc, sqr, aa, aa1;
661     bool bypass;
662     uint32_t mode, srate;
663     mutable bool redraw_graph;
664     bitreduction();
665     void set_sample_rate(uint32_t sr);
666     float add_dc(float s, float dc) const;
667     float remove_dc(float s, float dc) const;
668     void set_params(float b, float m, bool bp, uint32_t mode, float dc, float aa);
669     float waveshape(float in) const;
670     float process(float in);
671     virtual bool get_graph(int subindex, int phase, float *data, int points, calf_plugins::cairo_iface *context, int *mode) const;
672     bool get_layers(int index, int generation, unsigned int &layers) const;
673     bool get_gridline(int subindex, int phase, float &pos, bool &vertical, std::string &legend, calf_plugins::cairo_iface *context) const;
674 };
675 
676 class resampleN
677 {
678 private:
679 public:
680     uint32_t srate; // sample rate; source for upsampling, target for downsampling
681     int factor; // number of added/removed samples, max 16
682     int filters; // how many lowpasses should be used, max 4
683     double tmp[16];
684     dsp::biquad_d2 filter[2][4];
685     resampleN();
686     ~resampleN();
687     void set_params(uint32_t sr, int factor, int filters);
688     double *upsample(double sample);
689     double downsample(double *sample);
690 };
691 
692 class samplereduction
693 {
694 private:
695 public:
696     float target, real, amount;
697     unsigned int samples, round, cnt;
698     double last;
699     samplereduction();
700     void set_params(float am);
701     double process(double in);
702 };
703 
704 
705 /// Tom Szilagyi's distortion code, used with permission
706 /// KF: I'm not 100% sure how this is supposed to work, but it does.
707 /// I'm planning to rewrite it using more modular approach when I have more time.
708 class tap_distortion {
709 private:
710     float blend_old, drive_old;
711     float meter;
712     float rdrive, rbdr, kpa, kpb, kna, knb, ap, an, imr, kc, srct, sq, pwrq;
713     int over;
714     float prev_med, prev_out;
715     resampleN resampler;
716 public:
717     uint32_t srate;
718     bool is_active;
719     tap_distortion();
720     void activate();
721     void deactivate();
722     void set_params(float blend, float drive);
723     void set_sample_rate(uint32_t sr);
724     float process(float in);
725     float get_distortion_level();
M(float x)726     static inline float M(float x)
727     {
728         return (fabs(x) > 0.00000001f) ? x : 0.0f;
729     }
730 
D(float x)731     static inline float D(float x)
732     {
733         x = fabs(x);
734         return (x > 0.00000001f) ? sqrtf(x) : 0.0f;
735     }
736 };
737 
738 /*
739    Class for warping clicks avoiding between chunks
740    Used in reverse delay
741 */
742 class overlap_window
743 {
744 private:
745     float val;
746     float step;
747     float acc;
748     unsigned int active_samples;
749     unsigned int full_samples;
750     unsigned int counter;
751 
752 public:
overlap_window()753     overlap_window() {
754         val = 0;
755         step = 0;
756         acc = 0;
757         active_samples = 0;
758         full_samples = 0;
759         counter = 0;
760     }
set_coef(float t,unsigned int full_samples)761     void set_coef(float t /* 0..1 */, unsigned int full_samples) {
762         set_full(0, full_samples, t*full_samples);
763     }
set_full(float min_val,unsigned int full_samples,unsigned int active_samples)764     bool set_full(float min_val, unsigned int full_samples, unsigned int active_samples) {
765         if(active_samples >= full_samples) return false;
766 
767         acc = min_val;
768         val = min_val;
769         this->full_samples = full_samples;
770         this->active_samples = active_samples;
771         counter = 0;
772         step = (1 - min_val)/(active_samples/2);
773 
774         return true;
775     }
get()776     float get() {
777         if(counter < active_samples/2) {
778             acc += step;
779             counter++;
780             return acc;
781         }
782         else if(counter >= active_samples/2 && counter <= full_samples - active_samples/2) {
783             counter++;
784             return 1;
785         }
786         else if(counter > full_samples - active_samples/2 && counter < full_samples) {
787             acc -= step;
788             counter++;
789             return acc;
790         }
791         else if(counter >= full_samples) {
792             float ret_val = acc;
793             acc = val;
794             counter = 0;
795             return ret_val;
796         }
797         return 1;
798     }
799 };
800 
801 #if 0
802 { to keep editor happy
803 #endif
804 }
805 
806 #endif
807