diff --git a/index.html b/index.html index 7dca2ce..ad8ed09 100644 --- a/index.html +++ b/index.html @@ -74,7 +74,7 @@ todo: - missing XM effects: - E3x, E4x, E5x, E6x, E7x, E9x, EDx, EEx - 7xy - tremolo - - Hxy, Kxx, Lxx, Pxy, Txy + - Kxx, Lxx, Pxy, Txy - render pattern with the wider fonts for fewer channels - fix occasional rendering/audio hiccups when switching songs diff --git a/test/effects.js b/test/effects.js index ed147ac..40ed393 100644 --- a/test/effects.js +++ b/test/effects.js @@ -224,6 +224,55 @@ exports['test Gxx global volume'] = function(assert) { assert.equal(XMPlayer.xm.global_volume, 0x40*2, 'global volume set to 0x40'); }; +exports['test Hxy global volume slide'] = function(assert) { + var xm = testdata.resetXMData(); + xm.tempo = 6; + xm.global_volume = 128; + + xm.patterns[0] = [ + [[48, 1, -1, 17, 0x0f]], // C-4 1 -- H0f (slide down) + [[-1, -1, -1, 17, 0x90]], // --- -- -- H90 (slide up) + [[-1, -1, -1, 17, 0x00]], // --- -- -- H00 (continue same) + [[-1, -1, 0x30, 17, 0x11]], // --- -- 30 H11 (invalid, do nothing) + ]; + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 128, 'row 0 tick 0 vol 128'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 98, 'row 0 tick 1 vol 98'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 68, 'row 0 tick 2 vol 68'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 38, 'row 0 tick 3 vol 38'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 8, 'row 0 tick 4 vol 8'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 0, 'row 0 tick 5 vol 0'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 0, 'row 1 tick 0 vol 0'); + XMPlayer.nextTick(); + assert.equal(xm.global_volume, 18, 'row 1 tick 1 vol 18'); + XMPlayer.nextTick(); // row 1 tick 2 + XMPlayer.nextTick(); // tick 3 + XMPlayer.nextTick(); // tick 4 + XMPlayer.nextTick(); // tick 5 + assert.equal(xm.global_volume, 90, 'row 1 tick 5 vol 90'); + XMPlayer.nextTick(); // row 2 tick 0 + assert.equal(xm.global_volume, 90, 'row 2 tick 0 vol 90'); + XMPlayer.nextTick(); // row 2 tick 1 + assert.equal(xm.global_volume, 108, 'row 2 tick 1 vol 108'); + XMPlayer.nextTick(); // tick 2 + XMPlayer.nextTick(); // tick 3 + assert.equal(xm.global_volume, 128, 'row 2 tick 3 vol 128'); + XMPlayer.nextTick(); // tick 4 + XMPlayer.nextTick(); // tick 5 + XMPlayer.nextTick(); // row 3 tick 0 + assert.equal(xm.global_volume, 128, 'row 3 tick 0 vol 128'); + XMPlayer.nextTick(); // tick 1 + assert.equal(xm.global_volume, 128, 'row 3 tick 1 vol 128'); + XMPlayer.nextTick(); // tick 2 + assert.equal(xm.global_volume, 128, 'row 3 tick 2 vol 128'); +}; + exports['test E5x finetune override'] = function(assert) { var xm = testdata.resetXMData(); // set an initial finetune so we know we're overriding it... diff --git a/xmeffects.js b/xmeffects.js index 0976b51..45b6319 100644 --- a/xmeffects.js +++ b/xmeffects.js @@ -191,6 +191,20 @@ function eff_t0_g(ch, data) { // set global volume } } +function eff_t0_h(ch, data) { // global volume slide + if (data) { + // same as Axy but multiplied by 2 + player.xm.global_volumeslide = (-(data & 0x0f) + (data >> 4)) * 2; + } +} + +function eff_t1_h(ch) { // global volume slide + if (player.xm.global_volumeslide !== undefined) { + player.xm.global_volume = Math.max(0, Math.min(player.max_global_volume, + player.xm.global_volume + player.xm.global_volumeslide)); + } +} + function eff_t0_r(ch, data) { // retrigger if (data & 0x0f) ch.retrig = (ch.retrig & 0xf0) + (data & 0x0f); if (data & 0xf0) ch.retrig = (ch.retrig & 0x0f) + (data & 0xf0); @@ -244,7 +258,7 @@ player.effects_t0 = [ // effect functions on tick 0 eff_t0_e, // e eff_t0_f, // f eff_t0_g, // g - eff_unimplemented_t0, // h + eff_t0_h, // h eff_unimplemented_t0, // i eff_unimplemented_t0, // j eff_unimplemented_t0, // k @@ -283,7 +297,7 @@ player.effects_t1 = [ // effect functions on tick 1+ eff_t1_e, // e null, // f null, // g - eff_unimplemented, // h + eff_t1_h, // h eff_unimplemented, // i eff_unimplemented, // j eff_unimplemented, // k