improve filter performance making it accept hz directly
This commit is contained in:
parent
bbd7ed0f27
commit
5cbd38a3e8
1 changed files with 13 additions and 20 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
// this is dough, the superdough without dependencies
|
// this is dough, the superdough without dependencies
|
||||||
const SAMPLE_RATE = typeof sampleRate !== 'undefined' ? sampleRate : 48000;
|
const SAMPLE_RATE = typeof sampleRate !== 'undefined' ? sampleRate : 48000;
|
||||||
|
const PI_DIV_SR = Math.PI / SAMPLE_RATE;
|
||||||
const ISR = 1 / SAMPLE_RATE;
|
const ISR = 1 / SAMPLE_RATE;
|
||||||
|
|
||||||
let gainCurveFunc = (val) => Math.pow(val, 2);
|
let gainCurveFunc = (val) => Math.pow(val, 2);
|
||||||
|
|
@ -145,11 +146,13 @@ export class TwoPoleFilter {
|
||||||
s1 = 0;
|
s1 = 0;
|
||||||
update(s, cutoff, resonance = 0) {
|
update(s, cutoff, resonance = 0) {
|
||||||
// Out of bound values can produce NaNs
|
// Out of bound values can produce NaNs
|
||||||
cutoff = Math.min(cutoff, 1);
|
|
||||||
resonance = Math.max(resonance, 0);
|
resonance = Math.max(resonance, 0);
|
||||||
var c = Math.pow(0.5, (1 - cutoff) / 0.125);
|
|
||||||
var r = Math.pow(0.5, (resonance + 0.125) / 0.125);
|
cutoff = Math.min(cutoff, 20000);
|
||||||
var mrc = 1 - r * c;
|
const c = 2 * Math.sin(cutoff * PI_DIV_SR);
|
||||||
|
|
||||||
|
const r = Math.pow(0.5, (resonance + 0.125) / 0.125);
|
||||||
|
const mrc = 1 - r * c;
|
||||||
|
|
||||||
this.s0 = mrc * this.s0 - c * this.s1 + c * s; // bpf
|
this.s0 = mrc * this.s0 - c * this.s1 + c * s; // bpf
|
||||||
this.s1 = mrc * this.s1 + c * this.s0; // lpf
|
this.s1 = mrc * this.s1 + c * this.s0; // lpf
|
||||||
|
|
@ -591,6 +594,7 @@ const defaultDefaultValues = {
|
||||||
chorus: 0,
|
chorus: 0,
|
||||||
note: 48,
|
note: 48,
|
||||||
s: 'triangle',
|
s: 'triangle',
|
||||||
|
bank: '',
|
||||||
gain: 1,
|
gain: 1,
|
||||||
postgain: 1,
|
postgain: 1,
|
||||||
velocity: 1,
|
velocity: 1,
|
||||||
|
|
@ -620,6 +624,7 @@ const defaultDefaultValues = {
|
||||||
fmh: 1,
|
fmh: 1,
|
||||||
fmenv: 0, // differs from superdough
|
fmenv: 0, // differs from superdough
|
||||||
speed: 1,
|
speed: 1,
|
||||||
|
pw: 0.5,
|
||||||
};
|
};
|
||||||
|
|
||||||
let getDefaultValue = (key) => defaultDefaultValues[key];
|
let getDefaultValue = (key) => defaultDefaultValues[key];
|
||||||
|
|
@ -674,14 +679,14 @@ export class DoughVoice {
|
||||||
$.hresonance = $.hresonance ?? getDefaultValue('hresonance');
|
$.hresonance = $.hresonance ?? getDefaultValue('hresonance');
|
||||||
$.bandq = $.bandq ?? getDefaultValue('bandq');
|
$.bandq = $.bandq ?? getDefaultValue('bandq');
|
||||||
$.speed = $.speed ?? getDefaultValue('speed');
|
$.speed = $.speed ?? getDefaultValue('speed');
|
||||||
|
$.pw = $.pw ?? getDefaultValue('pw');
|
||||||
|
|
||||||
[$.attack, $.decay, $.sustain, $.release] = getADSR([$.attack, $.decay, $.sustain, $.release]);
|
[$.attack, $.decay, $.sustain, $.release] = getADSR([$.attack, $.decay, $.sustain, $.release]);
|
||||||
|
|
||||||
$._holdEnd = $._begin + $._duration; // needed for gate
|
$._holdEnd = $._begin + $._duration; // needed for gate
|
||||||
$._end = $._holdEnd + $.release + 0.01; // needed for despawn
|
$._end = $._holdEnd + $.release + 0.01; // needed for despawn
|
||||||
|
|
||||||
$.s ??= 'triangle';
|
if ($.fmi && ($.s === 'saw' || $.s === 'sawtooth')) {
|
||||||
if ($.s === 'saw' || $.s === 'sawtooth') {
|
|
||||||
$.s = 'zaw'; // polyblepped saw when fm is applied
|
$.s = 'zaw'; // polyblepped saw when fm is applied
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -697,7 +702,7 @@ export class DoughVoice {
|
||||||
$._buffers.push(new BufferPlayer(sample.channels[i], sample.sampleRate, $.unit === 'c')); // tbd unit === 'c'
|
$._buffers.push(new BufferPlayer(sample.channels[i], sample.sampleRate, $.unit === 'c')); // tbd unit === 'c'
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.warn('sound not found', $.s);
|
console.warn('sound not loaded', $.s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($.penv) {
|
if ($.penv) {
|
||||||
|
|
@ -727,10 +732,6 @@ export class DoughVoice {
|
||||||
$.delayspeed = $.delayspeed ?? getDefaultValue('delayspeed');
|
$.delayspeed = $.delayspeed ?? getDefaultValue('delayspeed');
|
||||||
$.delaytime = $.delaytime ?? getDefaultValue('delaytime');
|
$.delaytime = $.delaytime ?? getDefaultValue('delaytime');
|
||||||
|
|
||||||
// precalculated values
|
|
||||||
$.piOverSr = Math.PI / value.sampleRate;
|
|
||||||
$.eighthOverLogHalf = 0.125 / Math.log(0.5);
|
|
||||||
|
|
||||||
// filter setup
|
// filter setup
|
||||||
if ($.lpenv) {
|
if ($.lpenv) {
|
||||||
$._lpenv = new ADSR({ decayCurve: 4 });
|
$._lpenv = new ADSR({ decayCurve: 4 });
|
||||||
|
|
@ -763,11 +764,6 @@ export class DoughVoice {
|
||||||
$._distort?.push(new Distort());
|
$._distort?.push(new Distort());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// credits to pulu: https://github.com/felixroos/kabelsalat/issues/35
|
|
||||||
freq2cutoff(freq) {
|
|
||||||
const c = 2 * Math.sin(freq * this.piOverSr);
|
|
||||||
return 1 - Math.log(c) * this.eighthOverLogHalf;
|
|
||||||
}
|
|
||||||
update(t) {
|
update(t) {
|
||||||
if (!this._sound && !this._buffers) {
|
if (!this._sound && !this._buffers) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -806,7 +802,6 @@ export class DoughVoice {
|
||||||
const env = this._lpenv.update(t, gate, this.lpattack, this.lpdecay, this.lpsustain, this.lprelease);
|
const env = this._lpenv.update(t, gate, this.lpattack, this.lpdecay, this.lpsustain, this.lprelease);
|
||||||
lpf = this.lpenv * env * lpf + lpf;
|
lpf = this.lpenv * env * lpf + lpf;
|
||||||
}
|
}
|
||||||
lpf = this.freq2cutoff(lpf);
|
|
||||||
}
|
}
|
||||||
let hpf = this.hcutoff;
|
let hpf = this.hcutoff;
|
||||||
if (this._hpf) {
|
if (this._hpf) {
|
||||||
|
|
@ -814,7 +809,6 @@ export class DoughVoice {
|
||||||
const env = this._hpenv.update(t, gate, this.hpattack, this.hpdecay, this.hpsustain, this.hprelease);
|
const env = this._hpenv.update(t, gate, this.hpattack, this.hpdecay, this.hpsustain, this.hprelease);
|
||||||
hpf = 2 ** this.hpenv * env * hpf + hpf;
|
hpf = 2 ** this.hpenv * env * hpf + hpf;
|
||||||
}
|
}
|
||||||
hpf = this.freq2cutoff(hpf);
|
|
||||||
}
|
}
|
||||||
let bpf = this.bandf;
|
let bpf = this.bandf;
|
||||||
if (this._bpf) {
|
if (this._bpf) {
|
||||||
|
|
@ -822,7 +816,6 @@ export class DoughVoice {
|
||||||
const env = this._bpenv.update(t, gate, this.bpattack, this.bpdecay, this.bpsustain, this.bprelease);
|
const env = this._bpenv.update(t, gate, this.bpattack, this.bpdecay, this.bpsustain, this.bprelease);
|
||||||
bpf = 2 ** this.bpenv * env * bpf + bpf;
|
bpf = 2 ** this.bpenv * env * bpf + bpf;
|
||||||
}
|
}
|
||||||
bpf = this.freq2cutoff(bpf);
|
|
||||||
}
|
}
|
||||||
// gain envelope
|
// gain envelope
|
||||||
const env = this._adsr.update(t, gate, this.attack, this.decay, this.sustain, this.release);
|
const env = this._adsr.update(t, gate, this.attack, this.decay, this.sustain, this.release);
|
||||||
|
|
@ -831,7 +824,7 @@ export class DoughVoice {
|
||||||
for (let i = 0; i < this._channels; i++) {
|
for (let i = 0; i < this._channels; i++) {
|
||||||
// sound source
|
// sound source
|
||||||
if (this._sound && this.s === 'pulse') {
|
if (this._sound && this.s === 'pulse') {
|
||||||
this.out[i] = this._sound.update(freq, this.pw ?? 0.5);
|
this.out[i] = this._sound.update(freq, this.pw);
|
||||||
} else if (this._sound) {
|
} else if (this._sound) {
|
||||||
this.out[i] = this._sound.update(freq);
|
this.out[i] = this._sound.update(freq);
|
||||||
} else if (this._buffers) {
|
} else if (this._buffers) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue