acid
1 loop, 1 filter (1 worker, 1 AudioWorklet) tick: 0.000, time: 0.000 (138 bpm)
DT303
silver box
DT303 (variation)
DT303 (variation)
DT303 (variation)
Log in to post a comment.
reinder
· 2026/01/02
FYI: I added Learn Midi to the input sliders (click on the icon at the right of each slider). Still very WIP, but let me know if you have any feedback or ideas to improve this.
ollerich
· 2024/06/07
Damnit, I somehow never played with this. Awesome ditty and the randomizer is such a great addition!
niko14
· 2023/03/04
nice acid!
thkrypt
· 2023/01/08
Perfetc!
paulofalcao
· 2022/12/29
Wow! Nice sound!
srtuss
· 2022/12/12
Some new features added: gate duration slider, tune slider, bandlimited morphing waveform, anti-aliasing for distortion
newagegods
· 2022/11/28
So fresh! … love this. Thanks for making it! 🙌
joris
· 2022/10/24
Very nice! That’s that proper acid sound 👌
gate
0.58
tune
-18.0
pattern
1.00
waveform
0.00
cutoff
0.28
resonance
0.60
envmod
0.00
decay
0.00
overdrive
0.00
echo
0.80
// TB303-like synth.// 2022/12/4, srtuss// patterns are encoded as 4 values per step: note,rest,slide,accent (rests are not implemented)var patterns = [[f3,1,1,0,f2,1,0,0,ds2,1,1,0,c2,1,0,0,f2,1,1,0,f3,1,1,0,f3,1,0,0,f3,1,0,0,f2,1,0,0,f3,1,1,0,c2,1,0,0,ds3,1,0,0,f3,1,1,0,c3,1,0,0,ds3,1,0,0,f3,1,0,0],[a3,1,1,1,a3,1,0,0,a3,1,0,0,a3,1,1,0,a2,1,0,0,a4,1,0,0,a3,1,1,0,a2,1,0,0,a3,1,0,1,a3,1,1,0,a2,1,0,0,c4,1,1,0,a2,1,0,0,c3,1,0,0,a2,1,0,0,a3,1,0,0],[c2,1,1,0,c3,1,0,0,c4,1,0,0,c3,1,0,0,c2,1,0,0,c4,1,1,0,c3,1,1,0,c3,1,0,0],[c3,1,1,1,c3,1,0,0,c4,1,0,0,c3,1,1,1,c4,1,0,0,c3,1,0,0,c4,1,1,0,c3,1,0,0]];const pblep = (t, dt) => {if(t < dt) {t /= dt;return t + t - t * t - 1;}else if (t > 1 - dt) {t = (t - 1) / dt;return t * t + t + t + 1;}return 0;}input.gate=.58; // min=.1,max=1,step=.02input.tune=-18; // min=-24,max=24,step=.01input.waveform=0;input.cutoff=0.28;input.resonance=0.6;input.envmod=0;input.decay=0;input.overdrive=0;input.pattern = 1; // min=0, max=3, step=1 (bad square, synthetic b*tch, chainsaw, flying)input.echo = .8; // value=.8ditty.bpm = 138;class SVFilter {constructor() {this.lastLp = 0;this.lastHp = 0;this.lastBp = 0;this.kf = 0.1;this.kq = .1;}process(input) {var lp = this.lastLp + this.kf * this.lastBp;var hp = input - lp - this.kq * this.lastBp;var bp = this.lastBp + this.kf * hp;this.lastLp = lp;this.lastHp = hp;this.lastBp = bp;return lp;}}class SVFilter2 {constructor() {this.f = [new SVFilter(), new SVFilter()];this.lastLp = 0;this.kf = 0.1;this.kq = .3;}process(input) {this.f[0].kf = this.kf;this.f[0].kq = this.kq;this.f[1].kf = this.kf;this.f[1].kq = this.kq;this.f[0].process(input);this.f[1].process(this.f[0].lastLp);this.lastLp = this.f[1].lastLp;return this.lastLp;}}class Convol {constructor() {this.kernel = [0.013475, 0.097598, 0.235621, 0.306612, 0.235621, 0.097598, 0.013475];this.taps = new Float32Array(this.kernel.length);}process(v) {var n = this.kernel.length;var t = this.taps;for(var i = n-1; i > 0; --i)t[i] = t[i-1];t[0] = v;var o = 0;for(var i = 0; i < n; ++i)o += this.kernel[i] * t[i];return o;}}class TbVoice {constructor(opt) {this.ph = 0;this.dtph = .001;this.flt = new SVFilter2();this.tclk = 0;this.dtclk = ditty.bpm / 60 * 4 * ditty.dt;this.clkidx = 0;this.sqidx = 0;this.lastgate = 0;this.venv = 0;this.fenv = 0;this.slide = 0;this.note = 0;this.notecap = 0;this.att = 0;this.accent = 0;this.aenv = 0;this.us = new Convol();this.ds = new Convol();}seqstep() {var patdata = patterns[input.pattern];var pl = patdata.length>>2;this.sqidx %= pl;this.slide = patdata[this.sqidx*4+2];this.xslide = patdata[((this.sqidx+pl-1)%pl)*4+2];this.note = patdata[this.sqidx*4] + input.tune;this.accent = patdata[this.sqidx*4+3];this.sqidx++;this.sqidx %= pl;}process(note, env, tick, opt) {while(this.tclk >= 1) {this.tclk -= 1;this.seqstep();}var gate = this.tclk < input.gate || this.slide;this.tclk += this.dtclk;if(gate) {if(!this.lastgate) {this.fenv = 1;this.att = 0;this.aenv = this.accent;}this.venv = 1;this.att = Math.min(this.att+ditty.dt/.0005, 1);}this.lastgate = gate;if(this.xslide) {this.notecap += (this.note - this.notecap) * .0005;}else {this.notecap = this.note;}this.dtph = midi_to_hz(this.notecap) * ditty.dt;this.venv *= .995;this.fenv *= Math.exp(-(1-input.decay) * .004);var blep0 = pblep(this.ph, this.dtph);var saw = this.ph * 2 - 1 - blep0;var pw = Math.max(.5, input.waveform)*.95;var square = (this.ph > pw ? 1 : -1) + pblep((this.ph-pw+1)%1, this.dtph) - blep0;var v = lerp(saw, square, clamp01(input.waveform * 2));this.flt.kq = 1 - input.resonance * .9 - this.aenv * .1;this.flt.kf = 2 ** Math.min(0, input.cutoff * 7 - 7 + this.fenv * input.envmod * 5 + this.aenv * .4);this.flt.process(v);v = this.flt.process(v);this.ph += this.dtph;while(this.ph >= 1) {this.ph -= 1;}v = v * this.venv * this.att * (this.aenv + 1);this.aenv *= .9995;v *= .5;if(input.overdrive > 0) {var e = [0, 0, 0, 0];e[0] = this.us.process(v*4);e[1] = this.us.process(0);e[2] = this.us.process(0);e[3] = this.us.process(0);for(var i = 0; i < 4; ++i) {
4571 chars