diff --git a/Amp.cc b/Amp.cc index 4403747..dd2aec9 100644 --- a/Amp.cc +++ b/Amp.cc @@ -1,7 +1,7 @@ /* Amp.cc - Copyright 2003-14 Tim Goetze + Copyright 2003-18 Tim Goetze http://quitte.de/dsp/ @@ -48,7 +48,7 @@ AmpVTS::activate() lp.reset(); remain = 0; - compress.init (fs); + compress.init(fs,16); compress.set_threshold(0); compress.set_release(.0); @@ -188,18 +188,18 @@ AmpVTS::port_info [] = { "power", CTRL_IN, {DEFAULT_MID, 0, 1} }, /* 4 */ - { "tonestack", CTRL_IN | GROUP, {DEFAULT_1 | INTEGER, 0, 8}, DSP::ToneStack::presetdict}, + { "tonestack", CTRL_IN | GROUP, {DEFAULT_0 | INTEGER, 0, 8}, DSP::ToneStack::presetdict}, { "bass", CTRL_IN | GROUP, {DEFAULT_LOW, 0, 1} }, - { "mid", CTRL_IN, {DEFAULT_1, 0, 1} }, - { "treble", CTRL_IN, {DEFAULT_HIGH, 0, 1} }, + { "mid", CTRL_IN, {DEFAULT_HIGH, 0, 1} }, + { "treble", CTRL_IN, {DEFAULT_1, 0, 1} }, /* 8 */ - { "attack", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, - { "squash", CTRL_IN, {DEFAULT_LOW, 0, 1} }, + { "attack", CTRL_IN | GROUP, {DEFAULT_LOW, 0, 1} }, + { "squash", CTRL_IN, {DEFAULT_HIGH, 0, 1} }, /* 10 */ - { "lowcut", CTRL_IN | GROUP, {DEFAULT_MID, 0, 1} }, + { "lowcut", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, { "in", INPUT | AUDIO }, { "out", OUTPUT | AUDIO }, @@ -209,12 +209,9 @@ template <> void Descriptor::setup() { Label = "AmpVTS"; - Name = CAPS "AmpVTS - Idealised guitar amplification"; - Maker = "Tim Goetze , David Yeh "; - Copyright = "2002-14"; - - /* fill port info and vtable */ autogen(); + + Maker = "Tim Goetze , David Yeh "; } diff --git a/Amp.h b/Amp.h index 5d2a9f3..6bbc33c 100644 --- a/Amp.h +++ b/Amp.h @@ -51,7 +51,7 @@ class AmpVTS DSP::Oversampler<8,64> over8; DSP::IIR2 lp, biaslp; - DSP::HP1 hp1, dc1, dc2; /* dc blockers */ + DSP::HP1b hp1, dc1, dc2; /* dc blockers */ int model; DSP::ToneStack tonestack; diff --git a/AutoFilter.cc b/AutoFilter.cc index bd6b12f..4c3c838 100644 --- a/AutoFilter.cc +++ b/AutoFilter.cc @@ -1,7 +1,7 @@ /* AutoFilter.cc - Copyright 2002-12 Tim Goetze + Copyright 2002-18 Tim Goetze http://quitte.de/dsp/ @@ -86,10 +86,9 @@ AutoFilter::cycle (uint frames) float range = getport(4); float env = getport(5); - lorenz.set_rate (2.268e-05*fs * .6*sq (getport(6))); + lorenz.set_rate (2.268e-05*fs*.3*sq(getport(6))); float x = getport(7), z = 1-x; - sample_t * s = ports[8]; sample_t * d = ports[9]; @@ -122,14 +121,14 @@ AutoFilter::cycle (uint frames) /* filter it */ if (svf == 1) { - svf1.set_f_Q (fmod, Q); + svf1.set_f_Q(fmod, Q); double g = 1.8; for (uint i = 0; i < n; ++i) d[i] = svf1.process(s[i]+normal,g); } else if (svf == 2) { - svf2.set_f_Q (fmod, Q); + svf2.set_f_Q(fmod, Q); double g = .84*(1-Q) + .21; for (uint i = 0; i < n; ++i) d[i] = svf2.process(s[i]+normal,g); @@ -154,13 +153,13 @@ AutoFilter::port_info [] = { "filter", CTRL_IN | GROUP, {DEFAULT_1 | INTEGER, 0, 1}, "{0:'breathy',1:'fat'}", }, /* 2 */ - { "f (Hz)", CTRL_IN | GROUP, {LOG | DEFAULT_HIGH, 20, 3400} }, + { "f (Hz)", CTRL_IN | GROUP, {LOG | DEFAULT_HIGH, 20, 3800} }, { "Q", CTRL_IN, {DEFAULT_LOW, 0, 1} }, /* 4 */ { "depth", CTRL_IN | GROUP, {DEFAULT_1, 0, 1} }, { "lfo/env", CTRL_IN, {DEFAULT_LOW, 0, 1} }, { "rate", CTRL_IN | GROUP, {DEFAULT_LOW, 0, 1} }, - { "x/z", CTRL_IN, {DEFAULT_1, 0, 1} }, + { "shape", CTRL_IN, {DEFAULT_1, 0, 1} }, /* 8 */ { "in", AUDIO_IN}, @@ -171,12 +170,7 @@ template <> void Descriptor::setup() { Label = "AutoFilter"; - Name = CAPS "AutoFilter - Self-modulating resonant filter"; - Maker = "Tim Goetze "; - Copyright = "2004-14"; - - /* fill port info and vtable */ autogen(); } diff --git a/CHANGES b/CHANGES index 6948990..ccdff15 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,25 @@ +0.9.26 + * documentation updates + * DDDelay removed, needs more work + +0.9.25 + * potential gcc overoptimisation resulting in NaN in Kaiser window setup eliminated + (fix contributed by Jean Pierre Cimalando) + * updated to reflect changes to the div() and pow10f() functions in libc + * tonestack coefficient update reverted to original Yeh implementation + * Compress default measurement mode switched to RMS, attack range doubled + * Compress power and gain filter cutoff lowered to lessen intermodulation distortion + * Plate defaults changed + * volume control added to Spice hi and lo circuits, max gain reduced on both + * Wider output channels swapped + * AutoFilter rate lowered + * Scape parameters cleaned up and remapped, tune control removed + * Noisegate hysteresis increased to 180 ms + * dc-30 tonestack R3 20k -> 10k + * Eq10 Q changed to render optimally flat response at all zero band gain settings + * div port added to Click + * new plugin DDDelay + 0.9.24 * documentation updates including switch to 48k for all spectra * "twin" and "stanford" tonestack models swap places diff --git a/CabIII.cc b/CabIII.cc index 782e5d3..0d3dc1a 100644 --- a/CabIII.cc +++ b/CabIII.cc @@ -1,7 +1,7 @@ /* CabIII.cc - Copyright 2002-14 Tim Goetze + Copyright 2002-18 Tim Goetze http://quitte.de/dsp/ @@ -115,12 +115,7 @@ template <> void Descriptor::setup() { Label = "CabinetIII"; - Name = CAPS "CabinetIII - Simplistic loudspeaker cabinet emulation"; - Maker = "Tim Goetze "; - Copyright = "2002-14"; - - /* fill port info and vtable */ autogen(); } diff --git a/CabIV.cc b/CabIV.cc index 8032eda..d80d248 100644 --- a/CabIV.cc +++ b/CabIV.cc @@ -1,7 +1,7 @@ /* CabIV.cc - Copyright 2002-14 Tim Goetze + Copyright 2002-18 Tim Goetze http://quitte.de/dsp/ @@ -196,12 +196,7 @@ template <> void Descriptor::setup() { Label = "CabinetIV"; - Name = CAPS "CabinetIV - Idealised loudspeaker cabinet"; - Maker = "Tim Goetze "; - Copyright = "2012"; - - /* fill port info and vtable */ autogen(); } diff --git a/Chorus.cc b/Chorus.cc index d096827..9d333a7 100644 --- a/Chorus.cc +++ b/Chorus.cc @@ -117,12 +117,7 @@ template <> void Descriptor::setup() { Label = "ChorusI"; - Name = CAPS "ChorusI - Mono chorus/flanger"; - Maker = "Tim Goetze "; - Copyright = "GPL, 2004-13"; - - /* fill port info and vtable */ autogen(); } diff --git a/Click.cc b/Click.cc index 2a159a2..bad5b46 100644 --- a/Click.cc +++ b/Click.cc @@ -1,7 +1,7 @@ /* Click.cc - Copyright 2002-14 Tim Goetze + Copyright 2002-18 Tim Goetze http://quitte.de/dsp/ @@ -34,7 +34,7 @@ template void -ClickStub::initwave (int i, int16 * _wave, uint _N) +ClickStub::initwave(int i, int16 * _wave, uint _N) { wave[i].data = _wave; wave[i].N = _N; @@ -42,36 +42,38 @@ ClickStub::initwave (int i, int16 * _wave, uint _N) template void -ClickStub::cycle (uint frames) +ClickStub::cycle(uint frames) { static double scale16 = 1./32768; - int p = Waves > 1 ? 1 : 0; /* port */ + int p = Waves>1 ? 1 : 0; /* port */ int w = p ? getport(0) : 0; /* wave */ bpm = getport(p); - sample_t gain = getport(p+1); + int div = Waves>1 ? (int) getport(p+1) : 1; + div = div>0 ? div : 1; + sample_t gain = getport(p+p+1); gain *= scale16 * gain; - lp.set (1 - getport (p+2)); + lp.set(1 - getport(p+p+2)); - sample_t * d = ports[p+3]; + sample_t * d = ports[p+p+3]; - while (frames) + while(frames) { - if (period == 0) + if(period == 0) { - period = (int) (fs * 60 / bpm); + period = (int) (fs * 60 / (div*bpm)); played = 0; } - uint n = min (frames, period); + uint n = min(frames, period); - if (played < wave[w].N) + if(played < wave[w].N) { - n = min (n, wave[w].N - played); + n = min(n, wave[w].N - played); - for (uint i = 0; i < n; ++i) + for(uint i = 0; i < n; ++i) { double x = gain * wave[w].data[played+i]; - x = lp.process (x); + x = lp.process(x); d[i] = x; } @@ -79,7 +81,7 @@ ClickStub::cycle (uint frames) } else { - for (uint i = 0; i < n; ++i) + for(uint i = 0; i < n; ++i) d[i] = lp.process(normal); } @@ -108,48 +110,48 @@ Click::initsimple() }; DSP::LP1 lp1; - lp1.set_f (800*over_fs); + lp1.set_f(800*over_fs); DSP::IIR2 lp; - DSP::RBJ::LP (8000*over_fs, .2, lp); + DSP::RBJ::LP(8000*over_fs, .2, lp); DSP::IIR2 peaks[Peaks]; - for (int i = 0; i < Peaks; ++i) + for(int i = 0; i < Peaks; ++i) { /* tune to g' = 784 Hz */ float f = .8740245*_peaks[i][0]*over_fs; float g = _peaks[i][1]; - DSP::RBJ::BP (f, 22*g, peaks[i]); + DSP::RBJ::BP(f, 22*g, peaks[i]); } DSP::IIR2 bp; - DSP::RBJ::BP (150*over_fs, 3.8, bp); + DSP::RBJ::BP(150*over_fs, 3.8, bp); DSP::IIR2 post; - DSP::RBJ::PeakingEQ (1000*over_fs, 1.8, 24, post); + DSP::RBJ::PeakingEQ(1000*over_fs, 1.8, 24, post); int n = (int) (fs * 2800. / 44100.); - int16 * click = new int16 [n]; + int16 * click = new int16[n]; DSP::White white; int m = 8; sample_t mi = 1./m; sample_t x; - for (int i = 0; i < n; ++i) + for(int i = 0; i < n; ++i) { - if (i < m) /* simplistic noise excitation signal */ + if(i < m) /* simplistic noise excitation signal */ x = .5 * white.get() * (m-i)*mi; - x = lp.process (x); + x = lp.process(x); double a = x; - for (int j = 0; j < Peaks; ++j) - a += peaks[j].process_bp (x); - a = post.process (a); + for(int j = 0; j < Peaks; ++j) + a += peaks[j].process_bp(x); + a = post.process(a); /* add some ring-modulated noisz */ a += a*bp.process(white.get()); click[i] = (int16) (a * 32767.); x = 0; } - initwave (0, click, n); + initwave(0, click, n); } /* using parfilt models to generate the click */ @@ -162,66 +164,66 @@ Click::initparfilt() DSP::IIR2v4Bank<128> bank; ParModel<128,1> * model; - if (fs > 120000) model = &waves_click_wav_176000; - else if (fs > 60000) model = &waves_click_wav_88200; + if(fs > 120000) model = &waves_click_wav_176000; + else if(fs > 60000) model = &waves_click_wav_88200; else model = &waves_click_wav_44100; - bank.set_a (1, model->a1); - bank.set_a (2, model->a2); - bank.set_b (1, model->b1); - bank.set_b (2, model->b2); + bank.set_a(1, model->a1); + bank.set_a(2, model->a2); + bank.set_b(1, model->b1); + bank.set_b(2, model->b2); bank.reset(); int n = (int) (fs*2800/44100); - int16 * click = new int16 [n]; + int16 * click = new int16[n]; DSP::IIR2 hp; - DSP::RBJ::HP (1520*over_fs, .7, hp); + DSP::RBJ::HP(1520*over_fs, .7, hp); DSP::White white; int m = 3; sample_t mi = 1./m; sample_t x; - for (int i = 0; i < n; ++i) + for(int i = 0; i < n; ++i) { - if (i < m) /* simplistic noise excitation signal */ + if(i < m) /* simplistic noise excitation signal */ x = .5 * white.get() * (m-i)*mi; - x = v4f_sum (bank.process_bp(v4f(x))); + x = v4f_sum(bank.process_bp(v4f(x))); x = hp.process(x); click[i] = (int16) (x * 32767.); x = 0; } - initwave (1, click, n); + initwave(1, click, n); } void Click::initsine() { float f = 2*784; - DSP::Sine sin (2*M_PI*f*over_fs); + DSP::Sine sin(2*M_PI*f*over_fs); int n = (int) (12*fs/f); int m = 6*n/4; - int16 * click = new int16 [m]; + int16 * click = new int16[m]; DSP::IIR2 lp; - DSP::RBJ::BP (f*over_fs,2.5,lp); + DSP::RBJ::BP(f*over_fs,2.5,lp); float a = .4 * 32767; - for (int i = 0; i < n; ++i) + for(int i = 0; i < n; ++i) { sample_t x = a*sin.get(); x = lp.process(x); click[i] = (int16) (x); } - for (int i = n; i < m; ++i) + for(int i = n; i < m; ++i) { sample_t x = lp.process(NOISE_FLOOR); click[i] = (int16) (x); } - initwave (2, click, m); + initwave(2, click, m); } void @@ -229,32 +231,29 @@ Click::initdirac() { int16 * dirac = new int16[1]; *dirac = 32767; - initwave (3, dirac, 1); + initwave(3, dirac, 1); } template <> void Descriptor::setup() { Label = "Click"; - Name = CAPS "Click - Metronome"; - Maker = "Tim Goetze "; - Copyright = "2004-14"; - - /* fill port info and vtable */ autogen(); } /* //////////////////////////////////////////////////////////////////////// */ PortInfo -Click::port_info [] = +Click::port_info[] = { { "model", CTRL_IN, {INTEGER | DEFAULT_1, 0, 3}, "{0:'box',1:'stick',2:'beep',3:'dirac'}" }, - { "bpm", CTRL_IN | GROUP, {DEFAULT_LOW, 4, 240} }, - { "volume", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, - { "damping", CTRL_IN, {DEFAULT_HIGH, 0, 1} }, + { "bpm", CTRL_IN | GROUP, {DEFAULT_LOW, 4, 240}, }, + { "div", CTRL_IN | GROUP, {INTEGER | DEFAULT_MIN, 1, 4}, + "{1:'♩',2:'♪♪',3:'♪♪♪',4:'♬♬'}" }, + { "vol", CTRL_IN | GROUP, {DEFAULT_LOW, 0, 1} }, + { "tone", CTRL_IN, {DEFAULT_HIGH, 0, 1} }, { "out", OUTPUT | AUDIO} }; @@ -262,7 +261,7 @@ Click::port_info [] = /* //////////////////////////////////////////////////////////////////////// */ PortInfo -CEO::port_info [] = +CEO::port_info[] = { { "ppm", CTRL_IN, {DEFAULT_LOW, 30, 232} }, { "volume", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1}}, @@ -281,14 +280,14 @@ CEO::init() float s = fs/8000., dx = 1/s; int n = (int) (s*m); - int16 * wave = new int16 [n]; + int16 * wave = new int16[n]; DSP::IIR2 lp; /* suppress aliasing with an additional lowpass; also slight gain at 3 kHz */ - DSP::RBJ::LP (3000*over_fs,1.5,lp); + DSP::RBJ::LP(3000*over_fs,1.5,lp); #if 1 /* linear */ float x = 0; - for (int i = 0; i < n-1; ++i) + for(int i = 0; i < n-1; ++i) { int j = (int) x; float a = x-j; @@ -299,7 +298,7 @@ CEO::init() } #else /* cubic, unneeded */ float x = 0; - for (int i=0; i < n; ++i, x+=dx) + for(int i=0; i < n; ++i, x+=dx) { int j = (int) x; float f = x-j; @@ -320,19 +319,14 @@ CEO::init() } #endif - initwave (0, wave, n-1); + initwave(0, wave, n-1); } template <> void Descriptor::setup() { Label = "CEO"; - Name = CAPS "CEO - Chief Executive Oscillator"; - Maker = "Tim Goetze "; - Copyright = "2004-12"; - - /* fill port info and vtable */ autogen(); } diff --git a/Compress.cc b/Compress.cc index 582a05c..5d5f5fb 100644 --- a/Compress.cc +++ b/Compress.cc @@ -1,7 +1,7 @@ /* Compress.cc - Copyright 2011-14 Tim Goetze + Copyright 2011-18 Tim Goetze http://quitte.de/dsp/ @@ -32,17 +32,17 @@ template void CompressStub::activate() { - compress.peak.init (fs); - compress.rms.init (fs); + compress.peak.init(fs,4); + compress.rms.init(fs,4); remain = 0; } template void -CompressStub::cycle (uint frames) +CompressStub::cycle(uint frames) { int c = getport(0); - if (c == 0) subcycle (frames, compress.peak); + if(c == 0) subcycle (frames, compress.peak); else subcycle (frames, compress.rms); } @@ -52,17 +52,17 @@ struct NoSat { sample_t process(sample_t x) { return x; } }; template template void -CompressStub::subcycle (uint frames, Comp & comp) +CompressStub::subcycle(uint frames, Comp & comp) { static NoSat none; int s = getport(1); - if (s == 1) subsubcycle + if(s == 1) subsubcycle (frames, comp, saturate[0].two, saturate[1].two); - else if (s == 2) subsubcycle + else if(s == 2) subsubcycle (frames, comp, saturate[0].four, saturate[1].four); #if 0 - else if (s == 3) subsubcycle + else if(s == 3) subsubcycle (frames, comp, saturate[0].eight, saturate[1].eight); #endif else subsubcycle @@ -72,13 +72,13 @@ CompressStub::subcycle (uint frames, Comp & comp) template template void -CompressStub::subsubcycle (uint frames, Comp & comp, Sat & satl, Sat & satr) +CompressStub::subsubcycle(uint frames, Comp & comp, Sat & satl, Sat & satr) { - comp.set_threshold (pow(getport(2), 1.6)); + comp.set_threshold(pow(getport(2), 1.6)); sample_t strength = pow(getport(3), 1.4); /* more resolution in lower range */ - comp.set_attack (getport(4)); - comp.set_release (getport(5)); - sample_t gain_out = db2lin (getport (6)); + comp.set_attack(getport(4)); + comp.set_release(getport(5)); + sample_t gain_out = db2lin(getport(6)); sample_t * sl = ports[Stereo ? 8 : 8]; /* ;) */ sample_t * sr = ports[Stereo ? 9 : 8]; @@ -88,22 +88,22 @@ CompressStub::subsubcycle (uint frames, Comp & comp, Sat & satl, Sat & sample_t state = 1; - while (frames) + while(frames) { - if (remain == 0) + if(remain == 0) { remain = comp.blocksize; comp.start_block(strength); state = min(state,comp.gain.state); } - uint n = min (frames, remain); + uint n = min(frames, remain); - for (uint i=0; i::subsubcycle (uint frames, Comp & comp, Sat & satl, Sat & sample_t gain = gain_out*comp.get(); xl = satl.process(xl*gain); - if (Stereo) + if(Stereo) xr = satr.process(xr*gain); dl[i] = xl; - if (Stereo) + if(Stereo) dr[i] = xr; } @@ -134,7 +134,7 @@ CompressStub::subsubcycle (uint frames, Comp & comp, Sat & satl, Sat & PortInfo Compress::port_info [] = { - { "measure", CTRL_IN, {INTEGER | DEFAULT_0, 0, 1}, "{0:'peak',1:'rms'}" }, + { "measure", CTRL_IN, {INTEGER | DEFAULT_1, 0, 1}, "{0:'peak',1:'rms'}" }, { "mode", CTRL_IN | GROUP, {INTEGER | DEFAULT_1, 0, 2}, "{0:'no limiting',1:'saturating 2x',2:'saturating 4x',3:'saturating 4x128'}" }, /* 2 */ @@ -143,7 +143,7 @@ Compress::port_info [] = { "attack", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, { "release", CTRL_IN, {DEFAULT_MID, 0, 1} }, /* 6 */ - { "gain (dB)", CTRL_IN | GROUP, {DEFAULT_MID, -12, 18} }, + { "gain (dB)", CTRL_IN | GROUP, {DEFAULT_MID, -12, 36} }, { "state (dB)", CONTROL|OUTPUT| GROUP, {DEFAULT_0,-144,0} }, { "in", INPUT | AUDIO, {BOUNDED, -1, 1} }, @@ -154,12 +154,7 @@ template <> void Descriptor::setup() { Label = "Compress"; - Name = CAPS "Compress - Compressor and saturating limiter"; - Maker = "Tim Goetze "; - Copyright = "2011-14"; - - /* fill port info and vtable */ autogen(); } @@ -168,7 +163,7 @@ Descriptor::setup() PortInfo CompressX2::port_info [] = { - { "measure", CTRL_IN, {INTEGER | DEFAULT_0, 0, 1}, + { "measure", CTRL_IN, {INTEGER | DEFAULT_1, 0, 1}, "{0:'peak',1:'rms'}" }, { "mode", CTRL_IN | GROUP, {INTEGER | DEFAULT_1, 0, 2}, "{0:'linear',1:'saturating 2x',2:'saturating 4x',3:'saturating 4x128'}" }, @@ -176,7 +171,7 @@ CompressX2::port_info [] = { "strength", CTRL_IN, {DEFAULT_LOW, 0, 1} }, { "attack", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, { "release", CTRL_IN, {DEFAULT_MID, 0, 1} }, - { "gain (dB)", CTRL_IN | GROUP, {DEFAULT_MID, -12, 18} }, + { "gain (dB)", CTRL_IN | GROUP, {DEFAULT_MID, -12, 36} }, { "state (dB)", CONTROL|OUTPUT| GROUP, {DEFAULT_0,-144,0} }, { "in.l", INPUT | AUDIO }, { "in.r", INPUT | AUDIO }, @@ -188,12 +183,7 @@ template <> void Descriptor::setup() { Label = "CompressX2"; - Name = CAPS "CompressX2 - Stereo compressor and saturating limiter"; - Maker = "Tim Goetze "; - Copyright = "2011-14"; - - /* fill port info and vtable */ autogen(); } diff --git a/Compress.h b/Compress.h index 074dffb..ad37d2d 100644 --- a/Compress.h +++ b/Compress.h @@ -1,7 +1,7 @@ /* Compress.h - Copyright 2013 Tim Goetze + Copyright 2013-18 Tim Goetze http://quitte.de/dsp/ @@ -42,42 +42,46 @@ class CompSaturate /* antialias filters */ DSP::FIRUpsampler up; DSP::FIRn down; + /* take off some edge */ + DSP::LP1 lp; public: - void init (double fs) + void init(double fs) { - /* going a bit lower than nominal with fc */ - double f = .7 * M_PI/Over; + /* going a bit lower than half fs with fc */ + double f = .7*M_PI/Over; - DSP::sinc (f, up.c, FIRSize); + DSP::sinc(f, up.c, FIRSize); DSP::kaiser (up.c, FIRSize, 6.4); + lp.set_f(5000/fs); /* copy upsampler filter kernel for downsampler, make sum */ double s = 0; - for (uint i = 0; i < FIRSize; ++i) + for(uint i = 0; i < FIRSize; ++i) down.c[i] = up.c[i], s += up.c[i]; s = 1/s; /* scale kernels for unity gain */ - for (uint i=0; i - void subcycle (uint frames, Comp & comp); + void subcycle(uint frames, Comp & comp); template - void subsubcycle (uint frames, Comp & comp, Sat & satl, Sat & satr); + void subsubcycle(uint frames, Comp & comp, Sat & satl, Sat & satr); public: static PortInfo port_info []; void init() { - for (int i=0; i < Channels; ++i) + for(int i=0; i < Channels; ++i) { saturate[i].two.init(fs); saturate[i].four.init(fs); diff --git a/Descriptor.h b/Descriptor.h index dab9963..b2352dd 100644 --- a/Descriptor.h +++ b/Descriptor.h @@ -100,6 +100,9 @@ class Descriptor * function: */ void autogen() { + Maker = "Tim Goetze "; + Copyright = "GPLv3"; + Properties = HARD_RT; PortCount = (sizeof (T::port_info) / sizeof (PortInfo)); diff --git a/Eq.cc b/Eq.cc index 8d9ec72..4cf406e 100644 --- a/Eq.cc +++ b/Eq.cc @@ -36,7 +36,7 @@ /* slight adjustments to gain to keep response optimally flat at * 0 dB gain in all bands */ inline static double -adjust_gain (int i, double g) +adjust_gain(int i, double g) { static float adjust[] = { 0.69238604707174034, 0.67282771124180096, @@ -49,36 +49,36 @@ adjust_gain (int i, double g) return g * adjust[i]; } -#define Eq10Q 1.2 +#define Eq10Q .707 void Eq10::init() { - eq.init (fs, Eq10Q); + eq.init(fs, Eq10Q); } void Eq10::activate() { - for (int i = 0; i < 10; ++i) + for(int i = 0; i < 10; ++i) { gain[i] = getport(i); - eq.gain[i] = adjust_gain (i, db2lin (gain[i])); + eq.gain[i] = adjust_gain(i, db2lin(gain[i])); eq.gf[i] = 1; } } void -Eq10::cycle (uint frames) +Eq10::cycle(uint frames) { /* evaluate band gain changes and compute recursion factor to prevent * zipper noise */ double one_over_n = frames > 0 ? 1. / frames : 1; - for (int i = 0; i < 10; ++i) + for(int i = 0; i < 10; ++i) { sample_t g = getport(i); - if (g == gain[i]) + if(g == gain[i]) { /* no gain factoring */ eq.gf[i] = 1; @@ -86,17 +86,17 @@ Eq10::cycle (uint frames) } gain[i] = g; - double want = adjust_gain (i, db2lin (g)); - eq.gf[i] = pow (want / eq.gain[i], one_over_n); + double want = adjust_gain(i, db2lin(g)); + eq.gf[i] = pow(want / eq.gain[i], one_over_n); } sample_t * s = ports[10]; sample_t * d = ports[11]; - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i]; - x = eq.process (x); + x = eq.process(x); d[i] = x; } @@ -128,12 +128,7 @@ template <> void Descriptor::setup() { Label = "Eq10"; - Name = CAPS "Eq10 - 10-band equaliser"; - Maker = "Tim Goetze "; - Copyright = "2004-13"; - - /* fill port info and vtable */ autogen(); } @@ -142,8 +137,8 @@ Descriptor::setup() void Eq10X2::init() { - for (int c = 0; c < 2; ++c) - eq[c].init (fs, Eq10Q); + for(int c = 0; c < 2; ++c) + eq[c].init(fs, Eq10Q); } void @@ -152,28 +147,28 @@ Eq10X2::activate() /* Fetch current parameter settings so we won't sweep band gains in the * first block to process. */ - for (int i = 0; i < 10; ++i) + for(int i = 0; i < 10; ++i) { gain[i] = getport(i); - double a = adjust_gain (i, db2lin (gain[i])); - for (int c = 0; c < 2; ++c) + double a = adjust_gain(i, db2lin(gain[i])); + for(int c = 0; c < 2; ++c) eq[c].gf[i] = 1, eq[c].gain[i] = a; } } void -Eq10X2::cycle (uint frames) +Eq10X2::cycle(uint frames) { /* evaluate band gain changes and compute recursion factor to prevent * zipper noise */ double one_over_n = frames > 0 ? 1. / frames : 1; - for (int i = 0; i < 10; ++i) + for(int i = 0; i < 10; ++i) { double a; - if (*ports[i] == gain[i]) + if(*ports[i] == gain[i]) /* still same value, no gain fade */ a = 1; else @@ -181,30 +176,30 @@ Eq10X2::cycle (uint frames) gain[i] = getport(i); /* prepare factor for logarithmic gain fade */ - a = adjust_gain (i, db2lin (gain[i])); - a = pow (a / eq[0].gain[i], one_over_n); + a = adjust_gain(i, db2lin(gain[i])); + a = pow(a / eq[0].gain[i], one_over_n); } - for (int c = 0; c < 2; ++c) + for(int c = 0; c < 2; ++c) eq[c].gf[i] = a; } - for (int c = 0; c < 2; ++c) + for(int c = 0; c < 2; ++c) { sample_t * s = ports[10 + c], * d = ports[12 + c]; - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i]; - x = eq[c].process (x); + x = eq[c].process(x); d[i] = x; } } /* flip 'renormal' values */ - for (int c = 0; c < 2; ++c) + for(int c = 0; c < 2; ++c) { eq[c].normal = normal; eq[c].flush_0(); @@ -235,12 +230,7 @@ template <> void Descriptor::setup() { Label = "Eq10X2"; - Name = CAPS "Eq10X2 - Stereo 10-band equaliser"; - Maker = "Tim Goetze "; - Copyright = "2004-13"; - - /* fill port info and vtable */ autogen(); } @@ -251,7 +241,7 @@ Eq4p::init() { /* limit filter frequency to slightly under Nyquist to be on the safe side */ float limit = .48*fs; - for (int i = 0; i < 4; ++i) + for(int i = 0; i < 4; ++i) { state[i].f = -1; /* ensure all coefficients updated */ ranges[4*i + 1].UpperBound = min(ranges[4*i + 1].UpperBound, limit); @@ -274,14 +264,14 @@ typedef struct {sample_t a[3], b[3];} IIR2_ab; void Eq4p::updatestate() { - for (int i=0; i<4; ++i) + for(int i=0; i<4; ++i) { sample_t mode = getport(i*4); sample_t f = getport(i*4 + 1); sample_t Q = getport(i*4 + 2); sample_t gain = getport(i*4 + 3); - if (mode==state[i].mode && gain==state[i].gain && f==state[i].f && Q==state[i].Q) + if(mode==state[i].mode && gain==state[i].gain && f==state[i].f && Q==state[i].Q) continue; xfade = true; @@ -297,21 +287,21 @@ Eq4p::updatestate() /* Zoelzer shelve: H(s) = (A*s^2 + s*(sqrt(A)/Q) + 1) / (s^2 + s/Q + 1) */ /* maxima: solve([a/(1-b*0)=.5,a/(1-b)=50,a/(1-b*x)=.707],[a,b,x]); */ Q = .5/(1-.99*Q); - if (mode < 0) + if(mode < 0) c.a[0]=1,c.a[1]=0,c.a[2]=0,c.b[1]=0,c.b[2]=0; /* off = identity filter */ - else if (mode < 0.5) - DSP::RBJ::LoShelve (f,Q,gain,c); - else if (mode < 1.5) - DSP::RBJ::PeakingEQ (f,Q,gain,c); - else /* if (mode < 2.5) */ - DSP::RBJ::HiShelve (f,Q,gain,c); - - filter[1].set_ab (i, c.a, c.b); + else if(mode < 0.5) + DSP::RBJ::LoShelve(f,Q,gain,c); + else if(mode < 1.5) + DSP::RBJ::PeakingEQ(f,Q,gain,c); + else /* if(mode < 2.5) */ + DSP::RBJ::HiShelve(f,Q,gain,c); + + filter[1].set_ab(i, c.a, c.b); } } void -Eq4p::cycle (uint frames) +Eq4p::cycle(uint frames) { *ports[16] = 3; /* _latency */ @@ -320,9 +310,9 @@ Eq4p::cycle (uint frames) updatestate(); - if (!xfade) + if(!xfade) { - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i] + normal; x = filter[0].seriesprocess(x); @@ -334,7 +324,7 @@ Eq4p::cycle (uint frames) float over_n = frames ? 1./frames : 1; DSP::Sine gf0 (.5*M_PI*over_n,.5*M_PI); DSP::Sine gf1 (.5*M_PI*over_n,0); - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i]; sample_t g0 = gf0.get(); @@ -391,12 +381,7 @@ template <> void Descriptor::setup() { Label = "Eq4p"; - Name = CAPS "Eq4p - 4-band parametric shelving equaliser"; - Maker = "Tim Goetze "; - Copyright = "2013-14"; - - /* fill port info and vtable */ autogen(); } @@ -407,7 +392,7 @@ EqFA4p::init() { /* limit filter frequency to slightly under Nyquist to be on the safe side */ float limit = .48*fs; - for (int i = 0; i < 4; ++i) + for(int i = 0; i < 4; ++i) { state[i].f = -1; /* ensure all coefficients updated */ ranges[4*i + 1].UpperBound = min(ranges[4*i + 1].UpperBound, limit); @@ -429,14 +414,14 @@ EqFA4p::activate() void EqFA4p::updatestate() { - for (int i=0; i<4; ++i) + for(int i=0; i<4; ++i) { sample_t mode = getport(i*4 + 0); sample_t f = getport(i*4 + 1); sample_t bw = getport(i*4 + 2); sample_t gain = getport(i*4 + 3); - if (mode==state[i].mode && gain==state[i].gain && f==state[i].f && bw==state[i].bw) + if(mode==state[i].mode && gain==state[i].gain && f==state[i].f && bw==state[i].bw) continue; xfade = true; @@ -446,7 +431,7 @@ EqFA4p::updatestate() state[i].f = f; state[i].gain = gain; - if (!mode) + if(!mode) filter[1].unity(i); else filter[1].set(i, f*over_fs, bw, db2lin(gain)); @@ -454,7 +439,7 @@ EqFA4p::updatestate() } void -EqFA4p::cycle (uint frames) +EqFA4p::cycle(uint frames) { updatestate(); @@ -466,9 +451,9 @@ EqFA4p::cycle (uint frames) sample_t * s = ports[18]; sample_t * d = ports[19]; - if (!xfade) + if(!xfade) { - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i]; x = filter[0].seriesprocess(x); @@ -481,7 +466,7 @@ EqFA4p::cycle (uint frames) { DSP::Sine gf0 (.5*M_PI*over_n,.5*M_PI); DSP::Sine gf1 (.5*M_PI*over_n,0); - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i]; sample_t g0 = gf0.get(); @@ -543,12 +528,7 @@ template <> void Descriptor::setup() { Label = "EqFA4p"; - Name = CAPS "EqFA4p - 4-band parametric eq"; - Maker = "Tim Goetze "; - Copyright = "2014"; - - /* fill port info and vtable */ autogen(); } diff --git a/Fractals.cc b/Fractals.cc index 8844bd3..298146d 100644 --- a/Fractals.cc +++ b/Fractals.cc @@ -118,12 +118,7 @@ template <> void Descriptor::setup() { Label = "Fractal"; - Name = CAPS "Fractal - Audio stream from deterministic chaos"; - Maker = "Tim Goetze "; - Copyright = "2004-13"; - - /* fill port info and vtable */ autogen(); } diff --git a/Noisegate.cc b/Noisegate.cc index 0d5e52c..dc2483c 100644 --- a/Noisegate.cc +++ b/Noisegate.cc @@ -1,7 +1,7 @@ /* Noisegate.cc - Copyright 2011-13 Tim Goetze + Copyright 2011-16 Tim Goetze http://quitte.de/dsp/ @@ -34,9 +34,9 @@ void Noisegate::init() { - N = 3*882*fs/44100; /* 60 ms RMS accumulation when open */ + N = 3*960*fs/48000; /* 60 ms RMS accumulation when open */ over_N = 1./N; - hysteresis.threshold = (uint) (.130*fs); /* opening for at least 130 ms */ + hysteresis.threshold = (uint) (.180*fs); /* opening for at least 180 ms */ gain.quiet = db2lin (-60); gain.lp.set_f (120*over_fs); } @@ -154,7 +154,7 @@ Noisegate::cycle (uint frames) PortInfo Noisegate::port_info [] = { - { "open (dB)", CTRL_IN, {DEFAULT_LOW, -60, 0} }, + { "open (dB)", CTRL_IN, {DEFAULT_LOW, -55, 0} }, { "attack (ms)", CTRL_IN, {DEFAULT_0, 0, 5} }, { "close (dB)", CTRL_IN, {DEFAULT_LOW, -80, 0} }, @@ -170,12 +170,7 @@ template <> void Descriptor::setup() { Label = "Noisegate"; - Name = CAPS "Noisegate - Attenuating hum and noise"; - Maker = "Tim Goetze "; - Copyright = "2011-13"; - - /* fill port info and vtable */ autogen(); } diff --git a/Pan.cc b/Pan.cc index 40b9faf..4b04e92 100644 --- a/Pan.cc +++ b/Pan.cc @@ -1,7 +1,7 @@ /* Pan.cc - Copyright 2002-11 Tim Goetze + Copyright 2002-15 Tim Goetze http://quitte.de/dsp/ @@ -88,8 +88,8 @@ Wider::cycle (uint frames) s *= width; - sample_t l = m - s; - sample_t r = m + s; + sample_t l = m + s; + sample_t r = m - s; dl[i] = gain_l*l; dr[i] = gain_r*r; } @@ -112,12 +112,7 @@ template <> void Descriptor::setup() { Label = "Wider"; - Name = CAPS "Wider - Stereo image synthesis"; - Maker = "Tim Goetze "; - Copyright = "2011-13"; - - /* fill port info and vtable */ autogen(); } @@ -195,11 +190,6 @@ template <> void Descriptor::setup() { Label = "Narrower"; - Name = CAPS "Narrower - Stereo image width reduction"; - Maker = "Tim Goetze "; - Copyright = "2011-12"; - - /* fill port info and vtable */ autogen(); } diff --git a/Phaser.cc b/Phaser.cc index d50c2b0..2a77d3f 100644 --- a/Phaser.cc +++ b/Phaser.cc @@ -109,12 +109,7 @@ template <> void Descriptor::setup() { Label = "PhaserII"; - Name = CAPS "PhaserII - Mono phaser"; - Maker = "Tim Goetze "; - Copyright = "2002-13"; - - /* fill port info and vtable */ autogen(); } diff --git a/README.md b/README.md index c86da76..2c8c7f0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -caps-lv2 0.9.24 +caps-lv2 0.9.26 =============== LV2 port for the [CAPS Audio Plugin Suite](http://quitte.de/dsp/caps.html) diff --git a/Reverb.cc b/Reverb.cc index 2a57275..88b7d97 100644 --- a/Reverb.cc +++ b/Reverb.cc @@ -1,7 +1,7 @@ /* Reverb.cc - Copyright 2002-14 Tim Goetze + Copyright 2002-16 Tim Goetze http://quitte.de/dsp/ @@ -55,23 +55,23 @@ JVRev::init() { double s = fs/44100.; - for (int i = 0; i < 9; ++i) + for(int i = 0; i < 9; ++i) { int v = (int) (s * JVRev_length[i]); v |= 1; - while (!DSP::isprime(v)) + while(!DSP::isprime(v)) v += 2; length[i] = v; } - for (int i = 0; i < 4; ++i) - comb[i].init (length[i]); + for(int i = 0; i < 4; ++i) + comb[i].init(length[i]); - for (int i = 0; i < 3; ++i) - allpass[i].init (length[i+4]); + for(int i = 0; i < 3; ++i) + allpass[i].init(length[i+4]); - left.init (length[7]); - right.init (length[8]); + left.init(length[7]); + right.init(length[8]); /* such a simple number, yet I couldn't find a better one. */ apc = .7; @@ -85,8 +85,8 @@ JVRev::set_t60 (sample_t t) t = max(.00001, t); t = -3/(t*fs); - for (int i=0; i<4; ++i) - comb[i].c = pow (10, t*length[i]); + for(int i=0; i<4; ++i) + comb[i].c = pow(10, t*length[i]); } void @@ -95,10 +95,10 @@ JVRev::activate() bandwidth.reset(); tone.reset(); - for (int i=0; i<3; ++i) + for(int i=0; i<3; ++i) allpass[i].reset(); - for (int i=0; i<4; ++i) + for(int i=0; i<4; ++i) comb[i].reset(); left.reset(); @@ -109,12 +109,12 @@ JVRev::activate() } void -JVRev::cycle (uint frames) +JVRev::cycle(uint frames) { sample_t bw = .005 + .994*getport(0); bandwidth.set(exp(-M_PI*(1. - bw))); - if (t60 != *ports[1]) + if(t60 != *ports[1]) set_t60(getport(1)); double wet = getport(2); @@ -126,7 +126,7 @@ JVRev::cycle (uint frames) sample_t * dl = ports[4]; sample_t * dr = ports[5]; - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i], a = x + normal; @@ -142,7 +142,7 @@ JVRev::cycle (uint frames) sample_t t = 0; a -= normal; - for (int j=0; j<4; ++j) + for(int j=0; j<4; ++j) t += comb[j].process(a); t = tone.process(t); @@ -170,12 +170,7 @@ template <> void Descriptor::setup() { Label = "JVRev"; - Name = CAPS "JVRev - Stanford-style reverb from STK"; - Maker = "Tim Goetze "; - Copyright = "2004-12"; - - /* fill port info and vtable */ autogen(); } @@ -196,26 +191,26 @@ PlateStub::init() }; /* lh */ - input.lattice[0].init (L(0)); - input.lattice[1].init (L(1)); + input.lattice[0].init(L(0)); + input.lattice[1].init(L(1)); /* rh */ - input.lattice[2].init (L(2)); - input.lattice[3].init (L(3)); + input.lattice[2].init(L(2)); + input.lattice[3].init(L(3)); /* modulated, width about 12 samples @ 44.1 */ - tank.mlattice[0].init (L(4), (int) (0.000403221 * fs)); - tank.mlattice[1].init (L(5), (int) (0.000403221 * fs)); + tank.mlattice[0].init(L(4), (int) (0.000403221 * fs)); + tank.mlattice[1].init(L(5), (int) (0.000403221 * fs)); /* lh */ - tank.delay[0].init (L(6)); - tank.lattice[0].init (L(7)); - tank.delay[1].init (L(8)); + tank.delay[0].init(L(6)); + tank.lattice[0].init(L(7)); + tank.delay[1].init(L(8)); /* rh */ - tank.delay[2].init (L(9)); - tank.lattice[1].init (L(10)); - tank.delay[3].init (L(11)); + tank.delay[2].init(L(9)); + tank.lattice[1].init(L(10)); + tank.delay[3].init(L(11)); # undef L # define T(i) ((int) (t[i] * fs)) @@ -226,7 +221,7 @@ PlateStub::init() 0.089815530392123921, 0.070931756325392295, 0.011256342192802662 }; - for (int i = 0; i < 12; ++i) + for(int i = 0; i < 12; ++i) tank.taps[i] = T(i); # undef T @@ -239,37 +234,37 @@ PlateStub::init() } inline void -PlateStub::process (sample_t x, sample_t decay, sample_t * _xl, sample_t * _xr) +PlateStub::process(sample_t x, sample_t decay, sample_t * _xl, sample_t * _xr) { - x = input.bandwidth.process (x); + x = input.bandwidth.process(x); /* lh */ - x = input.lattice[0].process (x, indiff1); - x = input.lattice[1].process (x, indiff1); + x = input.lattice[0].process(x, indiff1); + x = input.lattice[1].process(x, indiff1); /* rh */ - x = input.lattice[2].process (x, indiff2); - x = input.lattice[3].process (x, indiff2); + x = input.lattice[2].process(x, indiff2); + x = input.lattice[3].process(x, indiff2); /* summation point */ - register double xl = x + decay * tank.delay[3].get(); - register double xr = x + decay * tank.delay[1].get(); + register double xl = x + decay*tank.delay[3].get(); + register double xr = x + decay*tank.delay[1].get(); /* lh */ - xl = tank.mlattice[0].process (xl, dediff1); - xl = tank.delay[0].putget (xl); - xl = tank.damping[0].process (xl); + xl = tank.mlattice[0].process(xl, dediff1); + xl = tank.delay[0].putget(xl); + xl = tank.damping[0].process(xl); xl *= decay; - xl = tank.lattice[0].process (xl, dediff2); - tank.delay[1].put (xl); + xl = tank.lattice[0].process(xl, dediff2); + tank.delay[1].put(xl); /* rh */ - xr = tank.mlattice[1].process (xr, dediff1); - xr = tank.delay[2].putget (xr); - xr = tank.damping[1].process (xr); + xr = tank.mlattice[1].process(xr, dediff1); + xr = tank.delay[2].putget(xr); + xr = tank.damping[1].process(xr); xr *= decay; - xr = tank.lattice[1].process (xr, dediff2); - tank.delay[3].put (xr); + xr = tank.lattice[1].process(xr, dediff2); + tank.delay[3].put(xr); /* gather output */ xl = .6 * tank.delay[2] [tank.taps[0]]; @@ -293,19 +288,19 @@ PlateStub::process (sample_t x, sample_t decay, sample_t * _xl, sample_t * _xr) /* //////////////////////////////////////////////////////////////////////// */ void -Plate::cycle (uint frames) +Plate::cycle(uint frames) { sample_t bw = .005 + .994*getport(0); - input.bandwidth.set (exp (-M_PI * (1. - bw))); + input.bandwidth.set(exp (-M_PI * (1. - bw))); sample_t decay = .749*getport(1); - double damp = exp (-M_PI * (.0005+.9995*getport(2))); - tank.damping[0].set (damp); - tank.damping[1].set (damp); + double damp = exp(-M_PI * (.0005+.9995*getport(2))); + tank.damping[0].set(damp); + tank.damping[1].set(damp); sample_t blend = getport(3); - blend = pow (blend, 1.6); /* linear is not a good choice for this pot */ + blend = pow(blend, 1.6); /* linear is not a good choice for this pot */ sample_t dry = 1 - blend; sample_t * s = ports[4]; @@ -316,14 +311,14 @@ Plate::cycle (uint frames) /* modulated lattice interpolation needs float truncation */ DSP::FPTruncateMode _truncate; - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { normal = -normal; sample_t x = s[i] + normal; sample_t xl, xr; - PlateStub::process (x, decay, &xl, &xr); + PlateStub::process(x, decay, &xl, &xr); x = dry * s[i]; @@ -337,9 +332,9 @@ Plate::cycle (uint frames) PortInfo Plate::port_info [] = { - {"bandwidth", INPUT | CONTROL, {DEFAULT_HIGH, 0, 1} /* .9995 */ }, - {"tail", INPUT | CONTROL | GROUP, {DEFAULT_MID, 0, 1} /* .5 */ }, - {"damping", INPUT | CONTROL, {DEFAULT_LOW, 0, 1} /* .0005 */ }, + {"bandwidth", INPUT | CONTROL, {DEFAULT_MID, 0, 1} }, + {"tail", INPUT | CONTROL | GROUP, {DEFAULT_HIGH, 0, 1} }, + {"damping", INPUT | CONTROL, {DEFAULT_MID, 0, 1} }, {"blend", INPUT | CONTROL | GROUP, {DEFAULT_LOW, 0, 1} }, {"in", INPUT | AUDIO}, @@ -351,31 +346,26 @@ template <> void Descriptor::setup() { Label = "Plate"; - Name = CAPS "Plate - Versatile plate reverb"; - Maker = "Tim Goetze "; - Copyright = "2004-11"; - - /* fill port info and vtable */ autogen(); } /* //////////////////////////////////////////////////////////////////////// */ void -PlateX2::cycle (uint frames) +PlateX2::cycle(uint frames) { sample_t bw = .005 + .994*getport(0); - input.bandwidth.set (exp (-M_PI * (1. - bw))); + input.bandwidth.set(exp (-M_PI * (1. - bw))); sample_t decay = .749*getport(1); - double damp = exp (-M_PI * (.0005+.9995*getport(2))); - tank.damping[0].set (damp); - tank.damping[1].set (damp); + double damp = exp(-M_PI * (.0005+.9995*getport(2))); + tank.damping[0].set(damp); + tank.damping[1].set(damp); sample_t blend = getport(3); - blend = pow (blend, 1.53); + blend = pow(blend, 1.53); sample_t dry = 1 - blend; sample_t * sl = ports[4]; @@ -386,13 +376,13 @@ PlateX2::cycle (uint frames) /* the modulated lattices interpolate, which needs truncated float */ DSP::FPTruncateMode _truncate; - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { normal = -normal; sample_t x = (sl[i] + sr[i] + normal) * .5; sample_t xl, xr; - PlateStub::process (x, decay, &xl, &xr); + PlateStub::process(x, decay, &xl, &xr); dl[i] = blend*xl + dry*sl[i]; dr[i] = blend*xr + dry*sr[i]; @@ -404,9 +394,9 @@ PlateX2::cycle (uint frames) PortInfo PlateX2::port_info [] = { - {"bandwidth", INPUT | CONTROL, {DEFAULT_HIGH, 0, 1} /* .9995 */ }, + {"bandwidth", INPUT | CONTROL, {DEFAULT_MID, 0, 1} /* .9995 */ }, {"tail", INPUT | CONTROL | GROUP, {DEFAULT_MID, 0, 1} /* .5 */ }, - {"damping", INPUT | CONTROL, {DEFAULT_LOW, 0, 1} /* .0005 */ }, + {"damping", INPUT | CONTROL, {DEFAULT_HIGH, 0, 1} /* .0005 */ }, {"blend", INPUT | CONTROL | GROUP, {DEFAULT_LOW, 0, 1} }, {"in.l", INPUT | AUDIO}, @@ -419,12 +409,7 @@ template <> void Descriptor::setup() { Label = "PlateX2"; - Name = CAPS "PlateX2 - Versatile plate reverb, stereo inputs"; - Maker = "Tim Goetze "; - Copyright = "2004-11"; - - /* fill port info and vtable */ autogen(); } diff --git a/Saturate.cc b/Saturate.cc index 2b329a6..6889d82 100644 --- a/Saturate.cc +++ b/Saturate.cc @@ -1,7 +1,7 @@ /* Saturate.cc - Copyright 2003-13 Tim Goetze + Copyright 2003-16 Tim Goetze http://quitte.de/dsp/ @@ -37,7 +37,7 @@ /* a few clipping functions in addition to those provided in * dsp/polynomials.cc */ inline sample_t -_noclip (sample_t a) +_noclip(sample_t a) { return a; } @@ -45,15 +45,15 @@ _noclip (sample_t a) #if 0 /* branchless clamping, works but is slower than the branching version */ inline int -getsign (float x, int shift = 31) +getsign(float x, int shift = 31) { union { float f; uint32 i; } u; u.f = x; - return (u.i & 0x80000000) >> shift; + return(u.i & 0x80000000) >> shift; } inline sample_t -_hardclip (sample_t a) +_hardclip(sample_t a) { /* set bit 1 if a < -.9 and bit 2 if a > .9 */ int i = getsign(a+.9,31) | getsign(.9-a,30); @@ -62,10 +62,10 @@ _hardclip (sample_t a) } #else inline sample_t -_hardclip (sample_t a) +_hardclip(sample_t a) { - if (a < -.9) return -.9; - if (a > +.9) return +.9; + if(a < -.9) return -.9; + if(a > +.9) return +.9; return a; } #endif @@ -93,7 +93,7 @@ float _power_clip_7 (float x) void Saturate::init() { - hp.set_f (40*over_fs); + hp.set_f(40*over_fs); gain.linear = 1; } @@ -108,7 +108,7 @@ Saturate::activate() /* templated for waveshaping function */ template void -Saturate::subcycle (uint frames) +Saturate::subcycle(uint frames) { sample_t * s = ports[3]; sample_t * d = ports[4]; @@ -122,14 +122,14 @@ Saturate::subcycle (uint frames) /* we have tried a chebyshev-poly added first harmonic instead of the * DC bias and it wasn't as useful. */ - for (uint i = 0; i < frames; ++i) + for(uint i = 0; i < frames; ++i) { sample_t x = s[i] + bias; x *= gain.linear; - x = over.downsample (C (over.upsample (x))); + x = over.downsample(C(over.upsample(x))); - for (int o=1; o < over.Ratio; ++o) - over.downstore (C (over.uppad (o))); + for(int o=1; o < over.Ratio; ++o) + over.downstore(C(over.uppad(o))); d[i] = ig*hp.process(x); @@ -148,12 +148,12 @@ static float preamp[] = {0.998, 1.195, 1.142, 0.998, -1.092, -1.092, -0.446, -0.165, -0.696, 1.250, 1.195, 1}; void -Saturate::cycle (uint frames) +Saturate::cycle(uint frames) { int mode = (int) getport(0); double g = getport(1); - if (!mode || mode == 11) + if(!mode || mode == 11) g = 0; g = preamp[mode] * db2lin(g); @@ -162,27 +162,27 @@ Saturate::cycle (uint frames) bias = .5*getport(2); bias = bias*bias; - if (mode == 1) + if(mode == 1) subcycle (frames); - else if (mode == 2) + else if(mode == 2) subcycle (frames); - else if (mode == 3) + else if(mode == 3) subcycle<_hardclip> (frames); - else if (mode == 4) + else if(mode == 4) subcycle (frames); - else if (mode == 5) + else if(mode == 5) subcycle (frames); - else if (mode == 6) + else if(mode == 6) subcycle (frames); - else if (mode == 7) + else if(mode == 7) subcycle (frames); - else if (mode == 8) + else if(mode == 8) subcycle (frames); - else if (mode == 9) + else if(mode == 9) subcycle (frames); - else if (mode == 10) + else if(mode == 10) subcycle (frames); - else if (mode == 11) + else if(mode == 11) subcycle (frames); else subcycle<_noclip> (frames); @@ -205,12 +205,7 @@ template <> void Descriptor::setup() { Label = "Saturate"; - Name = CAPS "Saturate - Various static nonlinearities, 8x oversampled"; - Maker = "Tim Goetze "; - Copyright = "2003-12"; - - /* fill port info and vtable */ autogen(); } @@ -222,7 +217,7 @@ void Spice::init() { float amps[] = {0,0,1,.3,.01}; - cheby.calculate (amps); + cheby.calculate(amps); } void @@ -230,53 +225,57 @@ Spice::activate() { remain = 0; - for (int i=0; i < 2; ++i) + for(int i=0; i < 2; ++i) { split[i].reset(); shape[i].reset(); } - compress.init(fs); + compress.init(fs,32); compress.set_threshold(0); compress.set_attack(0); compress.set_release(0); } void -Spice::cycle (uint frames) +Spice::cycle(uint frames) { - struct { float f, squash, gain; } - lo = {getport(0)*over_fs, getport(1), getport(2)}, - hi = {getport(3)*over_fs, 0, getport(4)}; + struct { float f, squash, gain, vol; } + lo = {getport(0)*over_fs, getport(1), getport(2), getport(3)}, + hi = {getport(4)*over_fs, 0, getport(5), getport(6)}; - if (split[0].f != lo.f) + if(split[0].f != lo.f || lo.vol != vol.lo) { + vol.lo = lo.vol; split[0].set_f(lo.f); - DSP::RBJ::BP (2*lo.f,.7,shape[0]); + DSP::RBJ::BP(2*lo.f,.7,shape[0]); + shape[0].scale(db2lin(vol.lo)); } - if (split[1].f != hi.f) + if(split[1].f != hi.f || hi.vol != vol.hi) { + vol.hi = hi.vol; split[1].set_f(hi.f); - DSP::RBJ::HP (2*hi.f,.7,shape[1]); + DSP::RBJ::HP(2*hi.f,.7,shape[1]); + shape[1].scale(db2lin(vol.hi)); } - lo.gain = pow (24,lo.gain) - 1; - hi.gain = pow (8,hi.gain) - 1; + lo.gain = pow(8,lo.gain) - 1; + hi.gain = pow(3,hi.gain) - 1; sample_t dc = cheby.process(0); - sample_t * s = ports[5]; - sample_t * d = ports[6]; + sample_t * s = ports[7]; + sample_t * d = ports[8]; - while (frames) + while(frames) { - if (remain == 0) + if(remain == 0) { remain = compress.blocksize; - compress.start_block (lo.squash); + compress.start_block(lo.squash); } - uint n = min (frames, remain); - for (uint i = 0; i < n; ++i) + uint n = min(frames, remain); + for(uint i = 0; i < n; ++i) { sample_t x,a,b,c; @@ -289,7 +288,7 @@ Spice::cycle (uint frames) x *= lo.gain; x = cheby.process(x)-dc; x = shape[0].process(x); - compress.store (x); + compress.store(x); c = x; /* hi */ @@ -299,7 +298,7 @@ Spice::cycle (uint frames) x = b; x = cheby.process(x)-dc; x *= hi.gain; - x = shape[1].process (x); + x = shape[1].process(x); x = x+a+b+c; d[i] = x; @@ -315,11 +314,13 @@ Spice::cycle (uint frames) PortInfo Spice::port_info [] = { - { "lo.f (Hz)", CTRL_IN, {LOG | DEFAULT_MID, 50, 400}}, + { "lo.f (Hz)", CTRL_IN, {LOG | DEFAULT_LOW, 50, 800}}, { "lo.compress", CTRL_IN, {DEFAULT_MID, 0, 1}}, { "lo.gain", CTRL_IN, {DEFAULT_LOW, 0, 1}}, - { "hi.f (Hz)", CTRL_IN | GROUP, {LOG | DEFAULT_MID, 400, 5000}}, + { "lo.vol (dB)", CTRL_IN, {DEFAULT_0, -60, 60}}, + { "hi.f (Hz)", CTRL_IN | GROUP, {LOG | DEFAULT_LOW, 400, 5000}}, { "hi.gain", CTRL_IN, {DEFAULT_LOW, 0, 1}}, + { "hi.vol (dB)", CTRL_IN, {DEFAULT_0, -60, 60}}, { "in", INPUT | AUDIO }, { "out", OUTPUT | AUDIO }, @@ -329,12 +330,7 @@ template <> void Descriptor::setup() { Label = "Spice"; - Name = CAPS "Spice - Not an exciter"; - Maker = "Tim Goetze "; - Copyright = "2012-13"; - - /* fill port info and vtable */ autogen(); } @@ -344,7 +340,7 @@ void SpiceX2::init() { float amp[] = {0,0,1,.3,.01}; - cheby.calculate (amp); + cheby.calculate(amp); } void @@ -352,65 +348,69 @@ SpiceX2::activate() { remain = 0; - for (int c=0; c < 2; ++c) - for (int i=0; i < 2; ++i) + for(int c=0; c < 2; ++c) + for(int i=0; i < 2; ++i) { chan[c].split[i].reset(); chan[c].shape[i].reset(); } - compress.init(fs); + compress.init(fs,64); compress.set_threshold(0); compress.set_attack(0); compress.set_release(0); } void -SpiceX2::cycle (uint frames) +SpiceX2::cycle(uint frames) { - struct { float f, squash, gain; } - lo = {getport(0)*over_fs, getport(1), getport(2)}, - hi = {getport(3)*over_fs, 0, getport(4)}; + struct { float f, squash, gain, vol; } + lo = {getport(0)*over_fs, getport(1), getport(2), getport(3)}, + hi = {getport(4)*over_fs, 0, getport(5), getport(6)}; - if (chan[0].split[0].f != lo.f) + if(chan[0].split[0].f != lo.f || lo.vol != vol.lo) { - for (int c=0; c<2; ++c) + vol.lo = lo.vol; + for(int c=0; c<2; ++c) { chan[c].split[0].set_f(lo.f); - DSP::RBJ::BP (2*lo.f,.7,chan[c].shape[0]); + DSP::RBJ::BP(2*lo.f,.7,chan[c].shape[0]); + chan[c].shape[0].scale(db2lin(vol.lo)); } } - if (chan[0].split[1].f != hi.f) + if(chan[0].split[1].f != hi.f || hi.vol != vol.hi) { - for (int c=0; c<2; ++c) + vol.hi = hi.vol; + for(int c=0; c<2; ++c) { chan[c].split[1].set_f(hi.f); - DSP::RBJ::BP (2*hi.f,.7,chan[c].shape[1]); + DSP::RBJ::BP(2*hi.f,.7,chan[c].shape[1]); + chan[c].shape[1].scale(db2lin(vol.hi)); } } - lo.gain = pow (24,lo.gain) - 1; - hi.gain = pow (8,hi.gain) - 1; + lo.gain = pow(8,lo.gain) - 1; + hi.gain = pow(3,hi.gain) - 1; sample_t dc = cheby.process(0); - sample_t * s[2] = {ports[5],ports[6]}; - sample_t * d[2] = {ports[7],ports[8]}; + sample_t * s[2] = {ports[7],ports[8]}; + sample_t * d[2] = {ports[9],ports[10]}; - while (frames) + while(frames) { - if (remain == 0) + if(remain == 0) { remain = compress.blocksize; - compress.start_block (lo.squash); + compress.start_block(lo.squash); } - uint n = min (frames, remain); - for (uint i = 0; i < n; ++i) + uint n = min(frames, remain); + for(uint i = 0; i < n; ++i) { sample_t x,a,b,bass[2]; float comp = compress.get(); - for (int c=0; c<2; ++c) + for(int c=0; c<2; ++c) { /* lo */ x = s[c][i]; @@ -430,15 +430,15 @@ SpiceX2::cycle (uint frames) x = b; x *= hi.gain; x = DSP::Polynomial::atan(x); - x = chan[c].shape[1].process (x); + x = chan[c].shape[1].process(x); x = x+a+b+bass[c]; d[c][i] = x; } - compress.store (bass[0],bass[1]); + compress.store(bass[0],bass[1]); } - for (int c=0; c<2; ++c) + for(int c=0; c<2; ++c) s[c]+=n, d[c]+=n; remain-=n, frames-=n; } @@ -452,8 +452,10 @@ SpiceX2::port_info [] = { "lo.f (Hz)", CTRL_IN, {LOG | DEFAULT_LOW, 50, 800}}, { "lo.compress", CTRL_IN, {DEFAULT_MID, 0, 1}}, { "lo.gain", CTRL_IN, {DEFAULT_LOW, 0, 1}}, + { "lo.vol (dB)", CTRL_IN, {DEFAULT_0, -60, 60}}, { "hi.f (Hz)", CTRL_IN | GROUP, {LOG | DEFAULT_LOW, 400, 5000}}, { "hi.gain", CTRL_IN, {DEFAULT_LOW, 0, 1}}, + { "hi.vol (dB)", CTRL_IN, {DEFAULT_0, -60, 60}}, { "in:l", INPUT | AUDIO }, { "in:r", INPUT | AUDIO }, @@ -465,12 +467,7 @@ template <> void Descriptor::setup() { Label = "SpiceX2"; - Name = CAPS "SpiceX2 - Not an exciter either"; - Maker = "Tim Goetze "; - Copyright = "2012-2013"; - - /* fill port info and vtable */ autogen(); } diff --git a/Saturate.h b/Saturate.h index 47bec01..8a88558 100644 --- a/Saturate.h +++ b/Saturate.h @@ -1,7 +1,7 @@ /* Saturate.h - Copyright 2004-13 Tim Goetze + Copyright 2004-16 Tim Goetze http://quitte.de/dsp/ @@ -90,6 +90,8 @@ class Spice public: Splitter split[2]; DSP::IIR2 shape[2]; + struct {float lo, hi;} vol; + DSP::ChebPoly<5> cheby; uint remain; @@ -112,6 +114,8 @@ class SpiceX2 Splitter split[2]; DSP::IIR2 shape[2]; } chan[2]; + struct {float lo, hi;} vol; + DSP::ChebPoly<5> cheby; uint remain; diff --git a/Scape.cc b/Scape.cc index 952ae0d..4019757 100644 --- a/Scape.cc +++ b/Scape.cc @@ -63,7 +63,6 @@ Scape::activate() svf[i].reset(), svf[i].set_out (1), /* band pass */ hipass[i].set_f (250*over_fs); - svf[3].set_out (0); /* low pass */ delay.reset(); period = 0; @@ -72,9 +71,9 @@ Scape::activate() inline double pick_f (float range, float tune) { - static double over_12 = 1./12; + static float over_12 = 1./12; int n = 48 + (int) (4*12*range*frandom()); - return tune * pow (2, (n - 69) * over_12); + return tune*pow(2,(n-69)*over_12); } @@ -82,20 +81,21 @@ void Scape::cycle (uint frames) { /* delay times */ - double t1 = fs * 60. / getport(0); + double t1 = 60*fs/getport(0); int div = (int) getport(1); - double t2 = t1 * dividers[div]; + double t2 = t1*dividers[div]; - fb = .94*getport(2); - double dry = getport(3); - dry = dry * dry; - double blend = getport(4); - float tune = getport(5); + float q = .99*getport(2); + float blend = pow(getport(3),.2); + float dry = sqrt(1-blend*blend); + fb = .94*getport(4); - sample_t * s = ports[6]; - sample_t * dl = ports[7]; - sample_t * dr = ports[8]; + float tune = 440; + + sample_t * s = ports[5]; + sample_t * dl = ports[6]; + sample_t * dr = ports[7]; DSP::FPTruncateMode truncate; @@ -104,16 +104,16 @@ Scape::cycle (uint frames) /* retune filters */ if (period <= 1) { - period = t2 * .5; + period = .5*t2; float f; f = frandom2(); - svf[0].set_f_Q (pick_f(.3,tune)*over_fs, .3); - svf[3].set_f_Q (pick_f(.5,tune)*over_fs, .6); /* LP */ + svf[0].set_f_Q (pick_f(.3,tune)*over_fs, q); + svf[3].set_f_Q (pick_f(.5,tune)*over_fs, q); /* LP */ f = frandom2(); - svf[1].set_f_Q (pick_f(.8,tune)*over_fs, .9*f); - svf[2].set_f_Q (pick_f(.9,tune)*over_fs, .5*f); + svf[1].set_f_Q (pick_f(.8,tune)*over_fs, f*q); + svf[2].set_f_Q (pick_f(.9,tune)*over_fs, .5*f*q); } uint n = min((uint) period, frames); @@ -125,18 +125,18 @@ Scape::cycle (uint frames) sample_t x2 = delay.get_linear (t2); delay.put (x + fb*x1); - x = dry*x + .2*svf[0].process (x) + .6*svf[3].process(x); + x = dry*x + .1*svf[0].process (x) + .2*svf[3].process(x); - x1 = svf[1].process (x1 - normal); - x2 = svf[2].process (x2 - normal); + x1 = svf[1].process(x1 - normal); + x2 = svf[2].process(x2 - normal); - x1 = hipass[1].process (x1); - x2 = hipass[2].process (x2); + x1 = hipass[1].process(x1); + x2 = hipass[2].process(x2); sample_t x1l, x1r, x2l, x2r; - x1l = fabs (lfo[0].lp.process(lfo[0].lorenz.get())); + x1l = .7*fabs(lfo[0].get()); x1r = 1 - x1l; - x2r = fabs (lfo[1].lp.process(lfo[1].lorenz.get())); + x2r = .7*fabs(lfo[1].get()); x2l = 1 - x2r; dl[i] = x + blend*(x1*x1l + x2*x2l); @@ -156,13 +156,13 @@ Scape::cycle (uint frames) PortInfo Scape::port_info [] = { - { "bpm", CTRL_IN, {DEFAULT_MID, 30, 164} }, - { "divider", CTRL_IN, {INTEGER | DEFAULT_MID, 2, 4}, - "{2:'eighths',3:'triplets',4:'sixteenths'}" }, - { "feedback", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, - { "dry", CTRL_IN | GROUP, {DEFAULT_MID, 0, 1} }, - { "blend", CTRL_IN, {DEFAULT_1, 0, 1} }, - { "tune (Hz)", CTRL_IN | GROUP, {DEFAULT_440, 415, 467} }, + { "bpm", CTRL_IN, {DEFAULT_MID, 30, 182} }, + { "div", CTRL_IN, {INTEGER | DEFAULT_MIN, 2, 4}, + "{2:'♪♪',3:'♪♪♪',4:'♬♬'}" }, + + { "Q", CTRL_IN | GROUP, {DEFAULT_HIGH, 0, 1} }, + { "blend", CTRL_IN, {DEFAULT_MID, 0, 1} }, + { "feedback", CTRL_IN, {DEFAULT_LOW, 0, 1} }, { "in", AUDIO_IN }, { "out.l", AUDIO_OUT }, @@ -173,12 +173,77 @@ template <> void Descriptor::setup() { Label = "Scape"; - Name = CAPS "Scape - Stereo delay with chromatic resonances"; - Maker = "Tim Goetze "; - Copyright = "2004-12"; + autogen(); +} + +/* //////////////////////////////////////////////////////////////////////// */ + +void +DDDelay::init() +{ + float l = 2*fs; /* one beat at 30 bpm */ + for(int i=0; i<4; ++i) + { + step[i].delay.init((int) (l + .5)); + step[i].lp.set(.001); + } +} - /* fill port info and vtable */ +void +DDDelay::activate() +{ + for(int i=0; i<4; ++i) + { + step[i].delay.reset(); + step[i].lp.reset(); + } +} + +void +DDDelay::cycle (uint frames) +{ + /* delay times */ + int div = (int) getport(1); + int t = -1 + (int) (60*fs/getport(0)); + + sample_t * s = ports[2]; + sample_t * d = ports[3]; + + sample_t g[4] = {.4,.7,.8,.7}; + for(uint i=0; i void +Descriptor::setup() +{ + Label = "DDDelay"; + Name = CAPS "DDDelay - Delay with fixed repetition count"; autogen(); } diff --git a/Scape.h b/Scape.h index e1b02ca..abc0341 100644 --- a/Scape.h +++ b/Scape.h @@ -1,7 +1,7 @@ /* Scape.h - Copyright 2004-5 Tim Goetze + Copyright 2004-16 Tim Goetze http://quitte.de/dsp/ @@ -45,6 +45,7 @@ class Scape struct { DSP::Lorenz lorenz; DSP::LP1 lp; + sample_t get() { return lp.process(lorenz.get()); } } lfo[2]; DSP::Delay delay; @@ -60,4 +61,21 @@ class Scape void activate(); }; +class DDDelay +: public Plugin +{ + public: + struct { + DSP::Delay delay; + DSP::LP1 lp; + } step[4]; + void cycle (uint frames); + + public: + static PortInfo port_info []; + + void init(); + void activate(); +}; + #endif /* SCAPE_H */ diff --git a/Sin.cc b/Sin.cc index c97da29..e728a67 100644 --- a/Sin.cc +++ b/Sin.cc @@ -86,12 +86,7 @@ template <> void Descriptor::setup() { Label = "Sin"; - Name = CAPS "Sin - Sine wave generator"; - Maker = "Tim Goetze "; - Copyright = "2004-13"; - - /* fill port info and vtable */ autogen(); } diff --git a/ToneStack.cc b/ToneStack.cc index c80ee04..7e56977 100644 --- a/ToneStack.cc +++ b/ToneStack.cc @@ -53,7 +53,7 @@ DSP::ToneStack::presets[] = { {250 k, 250 k, 4.8 k, 100 k, 250 pF, 100 nF, 47 nF}, /* 64 Princeton AA1164 */ {250 k, 1 M, 25 k, 47 k, 600 pF, 20 nF, 20 nF}, /* Mesa Dual Rect. 'Orange' */ /* Vox -- R3 is fixed (circuit differs anyway) */ - {1 M, 1 M, 20 k, 100 k, 50 pF, 22 nF, 22 nF}, /* 59/86 Vox AC-30 */ + {1 M, 1 M, 10 k, 100 k, 50 pF, 22 nF, 22 nF}, /* Vox "top boost" */ {220 k, 1 M, 22 k, 33 k, 470 pF, 22 nF, 22 nF}, /* 59/81 JCM-800 Lead 100 2203 */ {250 k, 250 k, 10 k, 100 k, 120 pF, 100 nF, 47 nF}, /* 69 Twin Reverb AA270 */ @@ -121,13 +121,9 @@ template <> void Descriptor::setup() { Label = "ToneStack"; - Name = CAPS "ToneStack - Classic amplifier tone stack emulation"; - Maker = "David T. Yeh "; - Copyright = "2006-12"; - - /* fill port info and vtable */ autogen(); + Maker = "David T. Yeh "; } diff --git a/White.cc b/White.cc index 381d73b..db51d24 100644 --- a/White.cc +++ b/White.cc @@ -71,12 +71,7 @@ template <> void Descriptor::setup() { Label = "White"; - Name = CAPS "White - Noise generator"; - Maker = "Tim Goetze "; - Copyright = "2004-13"; - - /* fill port info and vtable */ autogen(); } diff --git a/caps.rdf b/caps.rdf index 64c927a..3271de0 100644 --- a/caps.rdf +++ b/caps.rdf @@ -310,7 +310,7 @@ - + ladspa:hasLabel="div"> + ladspa:hasLabel="♪♪" /> + ladspa:hasLabel="♪♪♪" /> + ladspa:hasLabel="♬♬" /> @@ -988,6 +988,29 @@ + + + + + + + + + + + + + + diff --git a/dsp/Compress.h b/dsp/Compress.h index 65fb728..158dcc9 100644 --- a/dsp/Compress.h +++ b/dsp/Compress.h @@ -47,13 +47,13 @@ class Compress DSP::LP1 lp; } gain; - void init (float fs) + void init(float fs, int blockscale) { - if (fs > 120000) blocksize = 4; - else if (fs > 60000) blocksize = 2; + if(fs > 120000) blocksize = 4; + else if(fs > 60000) blocksize = 2; else blocksize = 1; - blocksize *= 4; + blocksize *= blockscale; over_block = 1./blocksize; set_threshold(0); @@ -65,28 +65,28 @@ class Compress gain.state = 1; gain.step = 0; - gain.lp.set (.4); + gain.lp.set(.1); /* prevent immediate drop from 0 sample in filter history */ gain.lp.y1 = gain.current; } - void set_threshold (float t) { threshold = pow2 (t); } - void set_directgain (float d) { gain.direct = 4*d; } + void set_threshold(float t) { threshold = pow2 (t); } + void set_directgain(float d) { gain.direct = 4*d; } - void set_attack (float a) + void set_attack(float a) { - attack = pow2 (2*a); + attack = pow2(4*a); attack = (.001 + attack)*over_block; } - void set_release (float r) + void set_release(float r) { release = pow2 (2*r); release = (.001 + release)*over_block; } - void start_block (sample_t powa, float strength) + void start_block(sample_t powa, float strength) { - if (powa < threshold) + if(powa < threshold) gain.target = gain.direct; else { @@ -95,10 +95,10 @@ class Compress gain.target = pow(4, (1 - strength) + strength*t); } - if (gain.target < gain.current) - gain.step = -min (attack, (gain.current - gain.target)*over_block); - else if (gain.target > gain.current) - gain.step = min (release, (gain.target - gain.current)*over_block); + if(gain.target < gain.current) + gain.step = -min(attack, (gain.current - gain.target)*over_block); + else if(gain.target > gain.current) + gain.step = min(release, (gain.target - gain.current)*over_block); else gain.step = 0; } @@ -121,33 +121,33 @@ class CompressRMS sample_t current; } power; - void init (float fs) + void init(float fs, int blockscale) { - Compress::init (fs); + Compress::init(fs, blockscale); power.current = 0; - power.lp.set (.96); + power.lp.set(.9); power.rms.reset(); } - inline void start_block (float strength) + inline void start_block(float strength) { power.current = power.rms.get(); /* add a small constant to prevent denormals in recursion tail */ sample_t powa = power.current = - power.lp.process (power.current + 1e-24); + power.lp.process(power.current + 1e-24); - Compress::start_block (powa, strength); + Compress::start_block(powa, strength); } - void store (sample_t x) + void store(sample_t x) { - power.rms.store (x*x); + power.rms.store(x*x); } - void store (sample_t xl, sample_t xr) + void store(sample_t xl, sample_t xr) { - power.rms.store (.5*(xl*xl + xr*xr)); + power.rms.store(.5*(xl*xl + xr*xr)); } }; @@ -160,37 +160,37 @@ class CompressPeak sample_t current; } peak; - void init (float fs) + void init(float fs, int blockscale) { - Compress::init (fs); + Compress::init(fs, blockscale); peak.current = 0; - peak.lp.set (.1); + peak.lp.set(.1); } - inline void start_block (float strength) + inline void start_block(float strength) { /* add a small constant to prevent denormals in recursion tail */ peak.current = peak.current * .9 + 1e-24; - sample_t p = peak.lp.process (peak.current); + sample_t p = peak.lp.process(peak.current); - Compress::start_block (p, strength); + Compress::start_block(p, strength); } - void store (sample_t x) + void store(sample_t x) { - x = fabs (x); - if (x > peak.current) + x = fabs(x); + if(x > peak.current) peak.current = x; } - void store (sample_t xl, sample_t xr) + void store(sample_t xl, sample_t xr) { - xl = fabs (xl); - xr = fabs (xr); - if (xl > peak.current) + xl = fabs(xl); + xr = fabs(xr); + if(xl > peak.current) peak.current = xl; - if (xr > peak.current) + if(xr > peak.current) peak.current = xr; } }; diff --git a/dsp/Delay.h b/dsp/Delay.h index 3be9972..2260bf6 100644 --- a/dsp/Delay.h +++ b/dsp/Delay.h @@ -1,12 +1,11 @@ /* dsp/Delay.h - Copyright 2003-13 Tim Goetze + Copyright 2003-17 Tim Goetze http://quitte.de/dsp/ delay lines with fractional (linear or cubic interpolation) lookup - and an allpass interpolating tap (which needs more work). delay line storage is aligned to powers of two for simplified wrapping checks (no conditional or modulo, binary 'and' suffices instead). @@ -48,23 +47,23 @@ class Delay ~Delay() { free (data); } - void init (uint n) + void init(uint n) { - size = next_power_of_2 (n); - assert (size <= (1 << 20)); - data = (sample_t *) calloc (sizeof (sample_t), size); + size = next_power_of_2(n); + assert(size <= (1 << 20)); + data = (sample_t *) calloc(sizeof (sample_t), size); --size; /* used as mask for confining access */ write = n; } void reset() { - memset (data, 0, (size + 1) * sizeof (sample_t)); + memset(data, 0, (size + 1) * sizeof (sample_t)); } sample_t & operator [] (int i) { return data [(write - i) & size]; } - inline void put (sample_t x) + inline void put(sample_t x) { data [write] = x; write = (write + 1) & size; diff --git a/dsp/IIR1.h b/dsp/IIR1.h index f29668e..b3516c7 100644 --- a/dsp/IIR1.h +++ b/dsp/IIR1.h @@ -35,8 +35,9 @@ class LP1 { public: T a0, b1, y1; + inline T process(T x) { return y1 = a0*x + b1*y1; } - LP1 (double d = 1.) + LP1(double d = 1.) { set (d); y1 = 0.; @@ -45,23 +46,21 @@ class LP1 sample_t last() {return y1;} inline void reset() { y1 = 0.; } - inline void decay (T d) + inline void decay(T d) { a0 *= d; b1 = 1. - a0; } - inline void set_f (T fc) + inline void set_f(T fc) { - set (1 - exp(-2*M_PI*fc)); + set(1 - exp(-2*M_PI*fc)); } - inline void set (T d) + inline void set(T d) { a0 = d; b1 = 1 - d; } - - inline T process (T x) { return y1 = a0*x + b1*y1; } }; template @@ -69,19 +68,19 @@ class HP1 { public: T a0, a1, b1, x1, y1; - - HP1 (T d = 1.) + T process (T x) { - set (d); - reset(); + y1 = a0*x + a1*x1 + b1*y1; + x1 = x; + return y1; } + HP1 (T d = 1.) { set (d); reset(); } + void reset() { x1 = y1 = 0; } + sample_t last() {return y1;} - void set_f (T f) - { - set (exp (-2*M_PI*f)); - } + void set_f (T f) { set(exp(-2*M_PI*f)); } inline void set (T d) { @@ -90,23 +89,26 @@ class HP1 b1 = d; } - inline T process (T x) + void identity() { a0=1; a1=b1=0; } +}; + +template +class HP1b +{ + public: + T a,x1,y; + T process (T x) { - y1 = a0*x + a1*x1 + b1*y1; + y = a*(y + x - x1); x1 = x; - return y1; + return y; } - void identity() - { - a0=1; - a1=b1=0; - } + HP1b (T d = 1.) { set (d); reset(); } + void reset() { x1 = y = 0; } - void reset() - { - x1 = y1 = 0; - } + void set_f (T f) { set(exp(-2*M_PI*f)); } + inline void set (T d) { a = d; } }; } /* namespace DSP */ diff --git a/dsp/IIR2.h b/dsp/IIR2.h index 4d99707..1931dec 100644 --- a/dsp/IIR2.h +++ b/dsp/IIR2.h @@ -1,7 +1,7 @@ /* dsp/IIR2.h - Copyright 2003-14 Tim Goetze + Copyright 2003-16 Tim Goetze http://quitte.de/dsp/ @@ -71,7 +71,11 @@ class IIR2 double is = gain(f); if (!is) /* I'm afraid I can't do that, Dave */ return; - g /= is; + scale(g/is); + } + + void scale(double g) + { a[0] *= g; a[1] *= g; a[2] *= g; diff --git a/dsp/RBJ.h b/dsp/RBJ.h index 7f0acb9..899ba7e 100644 --- a/dsp/RBJ.h +++ b/dsp/RBJ.h @@ -85,9 +85,9 @@ class LP template void ab (T * ca, T * cb) { - b[0] = (1 - cos) * .5; + b[0] = (1 - cos)*.5; b[1] = (1 - cos); - b[2] = (1 - cos) * .5; + b[2] = (1 - cos)*.5; a[0] = 1 + alpha; a[1] = -2 * cos; diff --git a/dsp/ToneStack.h b/dsp/ToneStack.h index 82e3002..f45d2c5 100644 --- a/dsp/ToneStack.h +++ b/dsp/ToneStack.h @@ -137,33 +137,24 @@ class ToneStack acoef.a1 = a1d + m*a1m + b*a1l; acoef.a2 = m*a2m + b*m*a2lm + m*m*a2m2 + b*a2l + a2d; acoef.a3 = b*m*a3lm + m*m*a3m2 + m*a3m + b*a3l + a3d; - - double c2 = c*c, c3 = c2*c; - - acoef.a1 *= c, acoef.a2 *= c2, acoef.a3 *= c3; - - dcoef_a[0] = -1 - acoef.a1 - acoef.a2 - acoef.a3; // sets scale - dcoef_a[1] = -3 - acoef.a1 + acoef.a2 + 3*acoef.a3; - dcoef_a[2] = -3 + acoef.a1 + acoef.a2 - 3*acoef.a3; - dcoef_a[3] = -1 + acoef.a1 - acoef.a2 + acoef.a3; + dcoef_a[0] = -1 - acoef.a1*c - acoef.a2*c*c - acoef.a3*c*c*c; // sets scale + dcoef_a[1] = -3 - acoef.a1*c + acoef.a2*c*c + 3*acoef.a3*c*c*c; + dcoef_a[2] = -3 + acoef.a1*c + acoef.a2*c*c - 3*acoef.a3*c*c*c; + dcoef_a[3] = -1 + acoef.a1*c - acoef.a2*c*c + acoef.a3*c*c*c; acoef.b1 = t*b1t + m*b1m + b*b1l + b1d; acoef.b2 = t*b2t + m*m*b2m2 + m*b2m + b*b2l + b*m*b2lm + b2d; acoef.b3 = b*m*b3lm + m*m*b3m2 + m*b3m + t*b3t + t*m*b3tm + t*b*b3tl; - - acoef.b1 *= c, acoef.b2 *= c2, acoef.b3 *= c3; - - dcoef_b[0] = - acoef.b1 - acoef.b2 - acoef.b3; - dcoef_b[1] = - acoef.b1 + acoef.b2 + 3*acoef.b3; - dcoef_b[2] = acoef.b1 + acoef.b2 - 3*acoef.b3; - dcoef_b[3] = acoef.b1 - acoef.b2 + acoef.b3; + dcoef_b[0] = - acoef.b1*c - acoef.b2*c*c - acoef.b3*c*c*c; + dcoef_b[1] = - acoef.b1*c + acoef.b2*c*c + 3*acoef.b3*c*c*c; + dcoef_b[2] = acoef.b1*c + acoef.b2*c*c - 3*acoef.b3*c*c*c; + dcoef_b[3] = acoef.b1*c - acoef.b2*c*c + acoef.b3*c*c*c; - double a0i = 1. / dcoef_a[0]; for (int i=1; i<=3; ++i) - filter.a[i] = dcoef_a[i] * a0i; + filter.a[i] = dcoef_a[i] / dcoef_a[0]; for (int i=0; i<=3; ++i) - filter.b[i] = dcoef_b[i] * a0i; + filter.b[i] = dcoef_b[i] / dcoef_a[0]; } /* actually do the DFII filtering, one sample at a time */ diff --git a/dsp/White.h b/dsp/White.h index bc55061..3aef29c 100644 --- a/dsp/White.h +++ b/dsp/White.h @@ -39,25 +39,19 @@ class White uint32 b; White() - { - b = 0x1fff7777; - } + { b = 0x1fff7777; } void init (float f) - { - b = (uint32) (f * (float) 0x1fff7777); - } + { b = (uint32) (f * (float) 0x1fff7777); } sample_t abs() - { - return fabs (get()); - } + { return fabs (get()); } /* 32-bit version */ sample_t get() { #define BIT(y) ((b << (31 - y)) & 0x80000000) - b = ((BIT (28) ^ BIT (27) ^ BIT (1) ^ BIT (0))) | (b >> 1); + b = ((BIT(28) ^ BIT(27) ^ BIT(1) ^ BIT(0))) | (b >> 1); return (4.6566128730773926e-10 * (sample_t) b) - 1; #undef BIT } @@ -67,7 +61,7 @@ class White sample_t get_31() { #define BIT(y) ((b << (30 - y)) & 0x40000000) - b = ((BIT (3) ^ BIT (0))) | (b >> 1); + b = ((BIT(3) ^ BIT(0))) | (b >> 1); return (9.3132257461547852e-10 * (sample_t) b) - 1; #undef BIT } diff --git a/dsp/v4f.h b/dsp/v4f.h index ac3e1cc..9aeea28 100644 --- a/dsp/v4f.h +++ b/dsp/v4f.h @@ -1,7 +1,7 @@ /* v4f.h - Copyright 2011-13 Tim Goetze + Copyright 2011-14 Tim Goetze http://quitte.de/dsp/ @@ -35,7 +35,7 @@ #endif /* caution, gcc apparently doesnt always honour the alignment: segfault */ -typedef float v4f_t __attribute__ ((vector_size (16), aligned(16))); +typedef float v4f_t __attribute__ ((vector_size(16), aligned(16))); inline v4f_t v4f (float x) { v4f_t v = {x,x,x,x}; return v; } @@ -51,6 +51,10 @@ inline v4f_t v4f (float *x) #ifdef __SSE__ #define v4f_shuffle(x,s3,s2,s1,s0) \ _mm_shuffle_ps(x,x,((s0)<<6|(s1)<<4|(s2)<<2|s3)) +#define v4f_shuffle2(x,y,s3,s2,s1,s0) \ + _mm_shuffle_ps(x,y,((s0)<<6|(s1)<<4|(s2)<<2|s3)) +#define v4f_max(x,y) _mm_max_ps(x,y) +#define v4f_min(x,y) _mm_min_ps(x,y) #else inline v4f_t v4f_shuffle(v4f_t x, int s3, int s2, int s1, int s0) { @@ -85,6 +89,7 @@ v4f_t v4f_map (v4f_t x) #define v4f_half ((v4f_t) {.5, .5, .5, .5}) #define v4f_1 ((v4f_t) {1, 1, 1, 1}) #define v4f_2 ((v4f_t) {2, 2, 2, 2}) +#define v4f_halfpi ((v4f_t) {.5*M_PI, .5*M_PI, .5*M_PI, .5*M_PI}) #define v4f_pi ((v4f_t) {M_PI, M_PI, M_PI, M_PI}) #define v4f_2pi ((v4f_t) {2*M_PI, 2*M_PI, 2*M_PI, 2*M_PI}) diff --git a/dsp/v4f_FIR.h b/dsp/v4f_FIR.h index a577f72..2edee59 100644 --- a/dsp/v4f_FIR.h +++ b/dsp/v4f_FIR.h @@ -1,7 +1,7 @@ /* dsp/v4f_FIR.h - Copyright 2003-12 Tim Goetze + Copyright 2003-14 Tim Goetze http://quitte.de/dsp/ @@ -165,6 +165,77 @@ class FIRv4 } }; +#if 0 +template +struct FIRv4b +{ + enum {M=(N*4)-1}; + v4f_t x4[N]; + v4f_t c4[4][N]; + int z; + + FIRv4b() + { + z = 0; + reset(); + } + + void halfband() + { + float *c0 = (float*) c4[0]; + for(int i=0; i<2*N; ++i) + { + double x = i-2*N+.5; + double w = 1; + c0[i] = c0[M-i] = w*w*sin(3*x*M_PI)/(x*M_PI); + } + DSP::kaiser (c0, 4*N, 6.4); + double s = 0; + for(int i=0; i<4*N; ++i) + s += c0[i]; + s = 1./s; /* normalise */ + for(int i=0; i<4*N; ++i) + c0[i] = 0 ? i : s*c0[i]; + setkernel(c0); + reset(); + } + + void setkernel(float *k) + { + float *c0 = (float*) c4[0]; + for(int i=0; i<4*N; ++i) + c0[i] = k[i]; + for(int j=1; j<4; ++j) + { + float *c = (float*) c4[j]; + for (int i=0; i<4*N; ++i) + c[i] = c0[(j+i)&M]; + } + } + + void reset() {for(int i=0; i>2; + for(int j=0; j (A); + A = v4f_map (A); RBJv4 p (f, Q); @@ -429,7 +429,7 @@ class IIR2v4Bank /* A = pow (10, gain / 40) */ v4f_t A = (v4f_t) {.025,.025,.025,.025}; A *= gain[i]; - A = v4f_map (A); + A = v4f_map (A); RBJv4 p (f[i], Q[i]); @@ -737,7 +737,7 @@ class MREqv4 c[3] = y; return v4fa(x)[3]; } -}; /* class IIR2v4 */ +}; } /* namespace DSP */ diff --git a/dsp/windows.h b/dsp/windows.h index b0b61b8..ed12b4a 100644 --- a/dsp/windows.h +++ b/dsp/windows.h @@ -1,7 +1,7 @@ /* dsp/windows.h - Copyright 2004-12 Tim Goetze + Copyright 2004-14 Tim Goetze http://quitte.de/dsp/ @@ -28,63 +28,73 @@ #ifndef DSP_WINDOWS_H #define DSP_WINDOWS_H +#include "Sine.h" + namespace DSP { /* prototypes for window value application ... */ typedef void (*window_sample_func_t) (sample_t &, sample_t); /* ... which go as template parameters for the window calculation below */ -inline void -store_sample (sample_t & d, sample_t s) -{ - d = s; -} +inline void store_sample (sample_t &d, sample_t s) { d = s; } +inline void apply_window (sample_t &d, sample_t s) { d *= s; } -inline void -apply_window (sample_t &d, sample_t s) +template +void +hann (sample_t * s, int n, double step = 1) { - d *= s; + step = M_PI*step/n; + + double f = 0; + for (int i=0; i void -hann (sample_t * s, int n, double step = 1) +hann2 (sample_t *s, int n) { - step = step / n; - - for (int i = 0; i < n; ++i) + double phi = M_PI/(n-1); + DSP::Sine sin(phi, 0); + for (int i=0; i void hamming (sample_t * s, int n) { - register float in = 1. / n; + float in = 1. / n; for (int i = 0; i < n; ++i) { - register double f = i * in; - F (s[i], .54 - .46 * cos (2 * M_PI * f)); + double f = i*in; + F (s[i], .54 - .46*cos (2*M_PI*f)); } } template void -blackman (sample_t * s, int n) +blackman (sample_t *s, int n) { - register float in = 1. / n; + float in = 1. / n; for (int i = 0; i < n; ++i) { - register float f = (float) i; + float f = (float) i; - register double b = .42f - - .5f * cos (2.f * f * M_PI * in) + - .08 * cos (4.f * f * M_PI * in); + double b = .42f - + .5f*cos (2.f*f*M_PI*in) + + .08*cos (4.f*f*M_PI*in); F (s[i], b); } @@ -92,92 +102,69 @@ blackman (sample_t * s, int n) template void -blackman_harris (sample_t * s, int n) +blackman_harris (sample_t *s, int n) { - register double w1 = 2.f * M_PI / (n - 1); - register double w2 = 2.f * w1; - register double w3 = 3.f * w1; + double w1 = 2.f*M_PI / (n - 1); + double w2 = 2.f*w1; + double w3 = 3.f*w1; for (int i = 0; i < n; ++i) { - register double f = (double) i; + double f = (double) i; - register double bh = .35875f - - .48829f * cos (w1 * f) + - .14128f * cos (w2 * f) - - .01168f * cos (w3 * f); + double bh = .35875f - + .48829f*cos (w1*f) + + .14128f*cos (w2*f) - + .01168f*cos (w3*f); F (s[i], bh); } } -/* helper for the kaiser window, courtesy of R. Dobson, courtesy of csound */ +/* by way of dobson and csound */ inline double besseli (double x) { - double ax, ans; - double y; - - if ((ax = fabs (x)) < 3.75) + double a = fabs(x); + if (a < 3.75) { - y = x / 3.75; + double y = x/3.75; y *= y; - ans = (1.0 + y * (3.5156229 + - y * (3.0899424 + - y * (1.2067492 + - y * (0.2659732 + - y * (0.360768e-1 + - y * 0.45813e-2)))))); - } - else - { - y = 3.75 / ax; - ans = ((exp (ax) / sqrt (ax)) - * (0.39894228 + - y * (0.1328592e-1 + - y * (0.225319e-2 + - y * (-0.157565e-2 + - y * (0.916281e-2 + - y * (-0.2057706e-1 + - y * (0.2635537e-1 + - y * (-0.1647633e-1 + - y * 0.392377e-2))))))))); + return 1. + y*(3.5156229 + y*(3.0899424 + y*(1.2067492 + + y*(.2659732 + y*(.0360768 + y*.0045813))))); } - - return ans; + double y = 3.75/a; + return (exp(a)/sqrt(a)) * (.39894228 + y*(.01328592 + + y*(.00225319 + y*(-.00157565 + y*(.00916281 + y*(-.02057706 + + y*(.02635537 + y*(-.01647633 + y*.00392377)))))))); } /* step = .5 : window [-n to 0] */ template void -kaiser (sample_t * s, int n, double beta, double step = 1) +kaiser (sample_t *s, int n, double beta, double step = 1) { - double bb = besseli (beta); + double bb = besseli(beta); int si = 0; - for (double i = -n / 2 + .1; si < n; ++si, i += step) + for(double i = -n/2.+.5; si < n; ++si, i += step) { - double k = besseli ((beta * sqrt (1 - pow ((2 * i / (n - 1)), 2)))) / bb; - - /* can you spell hack */ - if (!finite (k) || isnan(k)) - k = 0; - - F (s[si], k); + double a = 1 - pow((2*i / (n - 1)), 2); + double k = besseli((beta*(a < 0 ? 0 : sqrt(a))) / bb); + F(s[si], k); } } template void -xfade (sample_t * s, int n, int dir) /* dir [-1,1] */ +xfade (sample_t *s, int n, int dir) /* dir [-1,1] */ { - DSP::Sine cos(.5*M_PI/n, 0); - if (dir > 0) - for (int i=0; i=0; ) - s[i] *= cos.get(); + DSP::Sine cos(.5*M_PI/n, dir>0 ? .5*M_PI : 0); + for (int i=0; i(2593); *d++ = new Descriptor(2588); + #if 0 + *d++ = new Descriptor(2610); + #endif *d++ = new Descriptor(1773); *d++ = new Descriptor(2594);