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