diff --git a/index.html b/index.html
index ab59860..6feddac 100644
--- a/index.html
+++ b/index.html
@@ -7,9 +7,7 @@
code: github.com/a1k0n/jsxm
tune: my dirty old kamel - Zalza
todo:
- - unroll short sample loops
- unroll mixer code loops
- - pingpong loops
- multi-sample instruments
- instrument fadeout
- missing XM effects (in rough order of priority):
diff --git a/xm.js b/xm.js
index 188bbe9..514ed2c 100644
--- a/xm.js
+++ b/xm.js
@@ -34,7 +34,7 @@ function prettify_notedata(note, inst, vol, efftype, effparam) {
}
function getstring(dv, offset, len) {
- var str = []
+ var str = [];
for (var i = offset; i < offset+len; i++) {
var c = dv.getUint8(i);
if (c == 0) break;
@@ -669,6 +669,34 @@ function ConvertSample(array, bits) {
}
}
+function UnrollSampleLoop(inst) {
+ var nloops = ((2048 + inst.looplen - 1) / inst.looplen) | 0;
+ var pingpong = inst.type & 2;
+ if (pingpong) {
+ // make sure we have an even number of loops if we are pingponging
+ nloops = (nloops + 1) & (~1);
+ }
+ var samplesiz = inst.loop + nloops * inst.looplen;
+ var samp = new Float32Array(samplesiz);
+ for (var i = 0; i < inst.loop; i++) {
+ samp[i] = inst.sampledata[i];
+ }
+ for (var j = 0; j < nloops; j++) {
+ if (j&1 && pingpong) {
+ for (var k = inst.looplen - 1; k >= 0; k--) {
+ samp[i++] = inst.sampledata[inst.loop + k];
+ }
+ } else {
+ for (var k = 0; k < inst.looplen; k++) {
+ samp[i++] = inst.sampledata[inst.loop + k];
+ }
+ }
+ }
+ inst.sampledata = samp;
+ inst.looplen = nloops * inst.looplen;
+ inst.type &= ~2;
+}
+
function playXM(arrayBuf) {
var dv = new DataView(arrayBuf);
window.dv = dv;
@@ -713,7 +741,7 @@ function playXM(arrayBuf) {
var idx = hlen;
patterns = [];
for (var i = 0; i < npat; i++) {
- var pattern = []
+ var pattern = [];
var patheaderlen = dv.getUint32(idx, true);
var patrows = dv.getUint16(idx + 5, true);
var patsize = dv.getUint16(idx + 7, true);
@@ -825,6 +853,12 @@ function playXM(arrayBuf) {
inst.loop /= 2;
inst.looplen /= 2;
}
+
+ // unroll short loops and any pingpong loops
+ if ((inst.type & 1) && (inst.looplen < 2048 || (inst.type & 2))) {
+ UnrollSampleLoop(inst);
+ }
+
if (env_vol_type) {
inst.env_vol = new Envelope(
env_vol,