inlined all filters

This commit is contained in:
Andy Sloane 2015-10-25 09:20:12 -07:00
commit 4a0efd648d

41
xm.js
View file

@ -75,14 +75,7 @@ function FilterCoeffs(f_c) {
} }
popfilter = FilterCoeffs(200.0 / 44100.0); popfilter = FilterCoeffs(200.0 / 44100.0);
popfilter_alpha = 0.9837;
function Filter(x, coef, state) {
var y = coef[0] * (x + state[0]) + coef[1]*state[1] + coef[2]*state[2];
state[0] = x;
state[2] = state[1];
state[1] = y;
return y;
}
function UpdateChannelPeriod(ch, period, f_smp) { function UpdateChannelPeriod(ch, period, f_smp) {
var freq = 8363 * Math.pow(2, (4608 - period) / 768); var freq = 8363 * Math.pow(2, (4608 - period) / 768);
@ -213,15 +206,15 @@ function next_tick(f_smp) {
var note = ch.note + arpeggio[cur_tick % 3]; var note = ch.note + arpeggio[cur_tick % 3];
UpdateChannelNote(ch, note, f_smp); UpdateChannelNote(ch, note, f_smp);
} }
if (ch.effect == 1 && ch.slideupspeed !== undefined) { if (ch.effect == 1 && cur_tick != 0 && ch.slideupspeed !== undefined) {
ch.period -= ch.slideupspeed; ch.period -= ch.slideupspeed;
UpdateChannelPeriod(ch, ch.period, f_smp); UpdateChannelPeriod(ch, ch.period, f_smp);
} }
if (ch.effect == 2 && ch.slidedownspeed !== undefined) { if (ch.effect == 2 && cur_tick != 0 && ch.slidedownspeed !== undefined) {
ch.period += ch.slidedownspeed; ch.period += ch.slidedownspeed;
UpdateChannelPeriod(ch, ch.period, f_smp); UpdateChannelPeriod(ch, ch.period, f_smp);
} }
if (ch.effect == 3 && ch.periodtarget !== undefined && ch.portaspeed !== undefined) { if (ch.effect == 3 && cur_tick != 0 && ch.periodtarget !== undefined && ch.portaspeed !== undefined) {
if (ch.period > ch.periodtarget) { if (ch.period > ch.periodtarget) {
ch.period = Math.max(ch.periodtarget, ch.period - ch.portaspeed); ch.period = Math.max(ch.periodtarget, ch.period - ch.portaspeed);
} else { } else {
@ -292,12 +285,15 @@ function audio_cb(e) {
var dk = ch.doff; var dk = ch.doff;
// console.log(j, offset, ch); // console.log(j, offset, ch);
for (var i = offset; i < offset+tickduration; i++) { for (var i = offset; i < offset+tickduration; i++) {
var si = samp[k|0]; var s = samp[k|0];
si = Filter(si, ch.filter, ch.filterstate); var si = ch.filter[0] * (s + ch.filterstate[0]) + ch.filter[1]*ch.filterstate[1] + ch.filter[2]*ch.filterstate[2];
var vl = Filter(volL, popfilter, ch.popfilterstate[0]); ch.filterstate[2] = ch.filterstate[1]; ch.filterstate[1] = si; ch.filterstate[0] = s;
var vr = Filter(volR, popfilter, ch.popfilterstate[1]); ch.vL = popfilter_alpha * ch.vL + (1 - popfilter_alpha) * (volL + ch.vLprev) * 0.5;
dataL[i] += vl * si; ch.vR = popfilter_alpha * ch.vR + (1 - popfilter_alpha) * (volR + ch.vRprev) * 0.5;
dataR[i] += vr * si; ch.vLprev = volL;
ch.vRprev = volR;
dataL[i] += ch.vL * si;
dataR[i] += ch.vR * si;
k += dk; k += dk;
if (k >= sample_end) { // TODO: implement pingpong looping if (k >= sample_end) { // TODO: implement pingpong looping
if (loop) { if (loop) {
@ -309,9 +305,10 @@ function audio_cb(e) {
var rampend = Math.min(offset+tickduration, i+200); var rampend = Math.min(offset+tickduration, i+200);
for (i++; i < rampend; i++) { for (i++; i < rampend; i++) {
// fill rest of buffer with filtered silence to avoid a pop // fill rest of buffer with filtered silence to avoid a pop
var s = Filter(0, popfilter, ch.filterstate); var si = popfilter[0] * (ch.filterstate[0]) + popfilter[1]*ch.filterstate[1] + popfilter[2]*ch.filterstate[2];
dataL[i] += vl * s; ch.filterstate[2] = ch.filterstate[1]; ch.filterstate[1] = si; ch.filterstate[0] = 0;
dataR[i] += vr * s; dataL[i] += ch.vL * si;
dataR[i] += ch.vR * si;
} }
break; break;
} }
@ -371,7 +368,9 @@ function playXM(arrayBuf) {
popfilter: FilterCoeffs(200.0 / 44100.0), popfilter: FilterCoeffs(200.0 / 44100.0),
popfilterstate: [new Float32Array(3), new Float32Array(3)], popfilterstate: [new Float32Array(3), new Float32Array(3)],
vol: 0, vol: 0,
pan: 128 pan: 128,
vL: 0, vR: 0, // left right volume envelope followers (changes per sample)
vLprev: 0, vRprev: 0,
}) })
} }
console.log("header len " + hlen); console.log("header len " + hlen);