Compare commits

...
Sign in to create a new pull request.
Author SHA1 Message Date
Andy Sloane
d5c99e21e2 experimenting: linear interpolation 2015-11-03 07:18:30 -08:00

34
xm.js
View file

@ -135,7 +135,7 @@ function FilterCoeffs(f_c) {
var e = Math.exp(-wct);
var c = e * Math.cos(wct);
var s = e * Math.sin(wct);
var gain = (1 - 2*c + c*c + s*s) / 2;
var gain = (1 - 2*c + c*c + s*s);
return [gain, 2*c, -c*c - s*s];
}
@ -481,7 +481,6 @@ function MixChannelIntoBuf(ch, start, end, dataL, dataR) {
looplen = instsamp.looplen;
sample_end = loopstart + looplen;
}
var samplen = instsamp.len;
var volE = ch.volE / 64.0; // current volume envelope
var panE = 4*(ch.panE - 32); // current panning envelope
var p = panE + ch.pan - 128; // final pan
@ -530,6 +529,7 @@ function MixChannelIntoBuf(ch, start, end, dataL, dataR) {
var next_event = Math.max(1, Math.min(end, i + (sample_end - k) / dk));
// this is the inner loop of the player
/*
// unrolled 8x
for (; i + 7 < next_event; i+=8) {
var s = samp[k|0];
@ -599,20 +599,25 @@ function MixChannelIntoBuf(ch, start, end, dataL, dataR) {
vL = pf_8 * vL + (1 - pf_8) * volL;
vR = pf_8 * vR + (1 - pf_8) * volR;
}
*/
for (; i < next_event; i++) {
var s = samp[k|0];
var s0 = samp[k|0];
var s1 = samp[1+k|0];
var t = k - (k|0);
// we low-pass filter here since we are resampling some arbitrary
// frequency to f_smp; this is an anti-aliasing filter and is
// implemented as an IIR butterworth filter (usually we'd use an FIR
// brick wall filter, but this is much simpler computationally and
// sounds fine)
var y = f0 * (s + fs0) + f1*fs1 + f2*fs2;
fs2 = fs1; fs1 = y; fs0 = s;
var y = f0 * (t*s1 + (1-t) * s0) + f1*fs1 + f2*fs2;
fs2 = fs1; fs1 = y;
dataL[i] += vL * y;
dataR[i] += vR * y;
Vrms += (vL + vR) * y * y;
k += dk;
vL = popfilter_alpha * vL + (1 - popfilter_alpha) * volL;
vR = popfilter_alpha * vR + (1 - popfilter_alpha) * volR;
}
}
ch.off = k;
@ -688,26 +693,25 @@ function audio_cb(e) {
function ConvertSample(array, bits) {
var len = array.length;
var acc = 0;
var samp = new Float32Array(len+1);
if (bits == 0) { // 8 bit sample
var samp = new Float32Array(len);
for (var k = 0; k < len; k++) {
acc += array[k];
var b = acc&255;
if (b & 128) b = b-256;
samp[k] = b / 128.0;
}
return samp;
} else {
len /= 2;
var samp = new Float32Array(len);
for (var k = 0; k < len; k++) {
acc += array[k*2] + (array[k*2 + 1] << 8);
var b = acc&65535;
if (b & 32768) b = b-65536;
samp[k] = b / 32768.0;
}
return samp;
}
samp[len] = samp[len-1];
return samp;
}
// optimization: unroll short sample loops so we can run our inner mixing loop
@ -721,7 +725,7 @@ function UnrollSampleLoop(samp) {
nloops = (nloops + 1) & (~1);
}
var samplesiz = samp.loop + nloops * samp.looplen;
var data = new Float32Array(samplesiz);
var data = new Float32Array(samplesiz + 1);
for (var i = 0; i < samp.loop; i++) {
data[i] = samp.sampledata[i];
}
@ -896,7 +900,8 @@ function playXM(arrayBuf) {
'pan': samppan, 'type': samptype, 'vol': sampvol,
'fine': sampfinetune,
'sampledata': ConvertSample(
new Uint8Array(arrayBuf, sampleoffset, samplen), samptype & 16),
new Uint8Array(arrayBuf, sampleoffset, samplen),
samptype & 16),
};
// length / pointers are all specified in bytes; fixup for 16-bit samples
if (samptype & 16) {
@ -906,9 +911,14 @@ function playXM(arrayBuf) {
}
// unroll short loops and any pingpong loops
if ((samp.type & 3) && (samp.looplen < 2048 || (samp.type & 2))) {
if (samp.type & 3) {
if ((samp.looplen < 2048 || (samp.type & 2))) {
UnrollSampleLoop(samp);
}
// overwrite loop boundary sample (we always have at least one
// extra sample for interpolation)
samp.sampledata[samp.loop + samp.looplen] = samp.sampledata[samp.loop];
}
samps.push(samp);
idx += samphdrsiz;