From 7a4c3af4e532fb5ce9eb6c049659d1f1edc23c1e Mon Sep 17 00:00:00 2001 From: Jon Heard Date: Thu, 31 Aug 2023 04:11:59 -0400 Subject: [PATCH 1/2] - Events added to react to rowChange, patternChange, songEnd and effect --- js/ft2.js | 11 ++++++++++- js/player.js | 10 +++++++--- js/pt.js | 19 +++++++++++++++---- js/st3.js | 11 ++++++++++- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/js/ft2.js b/js/ft2.js index cd4d57a..e127c53 100644 --- a/js/ft2.js +++ b/js/ft2.js @@ -15,8 +15,10 @@ Greets to Guru, Alfred and CCR for their work figuring out the .xm format. :) */ -function Fasttracker() +function Fasttracker(songEventListener) { + this.songEventListener = songEventListener; + var i, t; this.clearsong(); @@ -587,6 +589,7 @@ Fasttracker.prototype.advance = function(mod) { mod.row++; mod.tick=0; mod.flags|=2; } } + this.songEventListener.onSongRowChange?.(); } // step to new pattern? @@ -594,14 +597,17 @@ Fasttracker.prototype.advance = function(mod) { mod.position++; mod.row=0; mod.flags|=4; + this.songEventListener.onSongPatternChange?.(); } // end of song? if (mod.position>=mod.songlen) { if (mod.repeat) { mod.position=0; + this.songEventListener.onSongEnd?.(true); } else { this.endofsong=true; + this.songEventListener.onSongEnd?.(false); } return; } @@ -742,6 +748,9 @@ Fasttracker.prototype.process_tick = function(mod) { if (!mod.tick) { // process only on tick 0 mod.effects_t0[mod.channel[ch].command](mod, ch); + if (this.songEventListener.onSongEffect && (mod.channel[ch].command > 0 || mod.channel[ch].data > 0)) { + this.songEventListener.onSongEffect(ch, mod.channel[ch].command, mod.channel[ch].data); + } } else { mod.effects_t1[mod.channel[ch].command](mod, ch); } diff --git a/js/player.js b/js/player.js index 4c9968d..4b9720d 100644 --- a/js/player.js +++ b/js/player.js @@ -38,6 +38,10 @@ function Modplayer() this.onReady=function(){}; this.onPlay=function(){}; this.onStop=function(){}; + this.onSongPatternChange = null; + this.onSongEnd = null; // params = isRepeating + this.onSongRowChange = null; + this.onSongEffect = null; // params = channel, command, command-data this.buffer=0; this.mixerNode=0; @@ -80,13 +84,13 @@ Modplayer.prototype.load = function(url) switch (ext) { case 'mod': - this.player=new Protracker(); + this.player=new Protracker(this); break; case 's3m': - this.player=new Screamtracker(); + this.player=new Screamtracker(this); break; case 'xm': - this.player=new Fasttracker(); + this.player=new Fasttracker(this); break; } diff --git a/js/pt.js b/js/pt.js index feaf580..12125ce 100644 --- a/js/pt.js +++ b/js/pt.js @@ -12,8 +12,10 @@ */ // constructor for protracker player object -function Protracker() +function Protracker(songEventListener) { + this.songEventListener = songEventListener; + var i, t; this.clearsong(); @@ -320,7 +322,6 @@ Protracker.prototype.advance = function(mod) { // advance player if (mod.offset>spd) { mod.tick++; mod.offset=0; mod.flags|=1; } if (mod.tick>=mod.speed) { - if (mod.patterndelay) { // delay pattern if (mod.tick < ((mod.patternwait+1)*mod.speed)) { mod.patternwait++; @@ -350,14 +351,22 @@ Protracker.prototype.advance = function(mod) { mod.row++; mod.tick=0; mod.flags|=2; } } + this.songEventListener.onSongRowChange?.(); + } + if (mod.row>=64) { + mod.position++; + mod.row=0; + mod.flags|=4; + this.songEventListener.onSongPatternChange?.(); } - if (mod.row>=64) { mod.position++; mod.row=0; mod.flags|=4; } if (mod.position>=mod.songlen) { if (mod.repeat) { mod.position=0; + this.songEventListener.onSongEnd?.(true); } else { this.endofsong=true; //mod.stop(); + this.songEventListener.onSongEnd?.(false); } return; } @@ -417,12 +426,14 @@ Protracker.prototype.mix = function(mod, bufs, buflen) { // kill empty samples if (!mod.sample[mod.channel[ch].sample].length) mod.channel[ch].noteon=0; - // effects if (mod.flags&1) { if (!mod.tick) { // process only on tick 0 mod.effects_t0[mod.channel[ch].command](mod, ch); + if (this.songEventListener.onSongEffect && (mod.channel[ch].command > 0 || mod.channel[ch].data > 0)) { + this.songEventListener.onSongEffect(ch, mod.channel[ch].command, mod.channel[ch].data); + } } else { mod.effects_t1[mod.channel[ch].command](mod, ch); } diff --git a/js/st3.js b/js/st3.js index ed636f8..2ecfc31 100644 --- a/js/st3.js +++ b/js/st3.js @@ -11,8 +11,10 @@ command data memory? */ -function Screamtracker() +function Screamtracker(songEventListener) { + this.songEventListener = songEventListener; + var i, t; this.clearsong(); @@ -440,6 +442,7 @@ Screamtracker.prototype.advance = function(mod) { mod.row++; mod.tick=0; mod.flags|=2; } } + this.songEventListener.onSongRowChange?.(); } // step to new pattern? @@ -448,14 +451,17 @@ Screamtracker.prototype.advance = function(mod) { mod.row=0; mod.flags|=4; while (mod.patterntable[mod.position]==254) mod.position++; // skip markers + this.songEventListener.onSongPatternChange?.(); } // end of song? if (mod.position>=mod.songlen || mod.patterntable[mod.position]==255) { if (mod.repeat) { mod.position=0; + this.songEventListener.onSongEnd?.(true); } else { this.endofsong=true; + this.songEventListener.onSongEnd?.(false); } return; } @@ -547,6 +553,9 @@ Screamtracker.prototype.process_tick = function(mod) { if (!mod.tick) { // process only on tick 0 effects mod.effects_t0[mod.channel[ch].command](mod, ch); + if (this.songEventListener.onSongEffect && (mod.channel[ch].command > 0 || mod.channel[ch].data > 0)) { + this.songEventListener.onSongEffect(ch, mod.channel[ch].command, mod.channel[ch].data); + } } else { mod.effects_t1[mod.channel[ch].command](mod, ch); } From 5348135b6b655d633c4b1bfcb2518542a689bf4c Mon Sep 17 00:00:00 2001 From: Jon Heard Date: Thu, 31 Aug 2023 04:36:38 -0400 Subject: [PATCH 2/2] Undid some unnecessary newline removal from prior commit. --- js/pt.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/pt.js b/js/pt.js index 12125ce..ada0e18 100644 --- a/js/pt.js +++ b/js/pt.js @@ -322,6 +322,7 @@ Protracker.prototype.advance = function(mod) { // advance player if (mod.offset>spd) { mod.tick++; mod.offset=0; mod.flags|=1; } if (mod.tick>=mod.speed) { + if (mod.patterndelay) { // delay pattern if (mod.tick < ((mod.patternwait+1)*mod.speed)) { mod.patternwait++; @@ -426,6 +427,7 @@ Protracker.prototype.mix = function(mod, bufs, buflen) { // kill empty samples if (!mod.sample[mod.channel[ch].sample].length) mod.channel[ch].noteon=0; + // effects if (mod.flags&1) { if (!mod.tick) {