diff --git a/.gitignore b/.gitignore index 3c3629e..f06235c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +dist diff --git a/README.md b/README.md index fb5517c..09ddfa3 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,14 @@ ModPlayer JS makes use of the following piece of software: I also heavily used [MilkyTracker](https://milkytracker.titandemo.org/) and [webaudio-mod-player](https://mod.haxor.fi/) - which plays lot of module formats with high fidelity - to track down some timing bugs. +# Building modplayer-js + +modplayer-js only needs a webserver, which can be installed by typing `npm install` and then `http-server`. + +If you want to use modplayer-js on an Xbox One, you'll also need to type `npm run build`: this will generate an ES5 version of the `mod-processor.js` file. + +This is because for some unknown reason, on Xbox One Edge, the audioworklet polyfill refuses to execute ES6 code. + # Module background Modules are like MIDI files but with custom sound samples instead of builtin synth files. diff --git a/js/main.js b/js/main.js index 29424b6..90d8151 100644 --- a/js/main.js +++ b/js/main.js @@ -1,23 +1,23 @@ var moduleList = [ { file: 'https://api.modarchive.org/downloads.php?moduleid=91286#faggots_universe.mod', author: 'Deelite' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=168739#neurodancer_-_quasar.mod', author: 'Neurodancer' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=183672#tax_haven_dry_hump.mod', author: 'Curt Cool' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=182057#h0ffman_-_drop_the_panic.mod', author: 'h0ffman' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=168122#prodigy_-_downtown.mod', author: 'prodigy of oops' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=172266#hoffman_-_the_hunter.mod', author: 'h0ffman' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=65280#variations.mod', author: 'jogeir-liljedahl' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=166686#wiklund_-_bonfire.mod', author: 'Wiklund' }, + // { file: 'https://api.modarchive.org/downloads.php?moduleid=166686#wiklund_-_bonfire.mod', author: 'Wiklund' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=55058#pinball_illusions.mod', author: 'Olof Gustafsson' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=167668#vinnie_-_sweet_dreams.mod', author: 'vinnie/spaceballs' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=172271#subi-king_of_boggle.mod', author: 'Subi/DESiRE' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=171416#bass-1107.mod', author: 'Noiseless (cm/ao)' }, + // { file: 'https://api.modarchive.org/downloads.php?moduleid=171416#bass-1107.mod', author: 'Noiseless (cm/ao)' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=168110#punnik_-_drum_bass.mod', author: 'punnik' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=171616#dan_-_childs_philozophy.mod', author: 'dan / picco' }, + // { file: 'https://api.modarchive.org/downloads.php?moduleid=171616#dan_-_childs_philozophy.mod', author: 'dan / picco' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=119303#boesendorfer_p_s_s.mod', author: 'romeoknight' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=170637#ghost_in_the_cli.mod', author: 'h0ffman' }, - { file: 'https://api.modarchive.org/downloads.php?moduleid=158057#alf_-_no-mercy.mod', author: 'alf/vtl' }, + // { file: 'https://api.modarchive.org/downloads.php?moduleid=170637#ghost_in_the_cli.mod', author: 'h0ffman' }, + // { file: 'https://api.modarchive.org/downloads.php?moduleid=158057#alf_-_no-mercy.mod', author: 'alf/vtl' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=105709#trans_atlantic.mod', author: 'Lizardking'}, { file: 'https://api.modarchive.org/downloads.php?moduleid=124303#agony_intro.mod', author: 'Tim Wright' }, + { file: 'https://api.modarchive.org/downloads.php?moduleid=168739#neurodancer_-_quasar.mod', author: 'Neurodancer' }, + { file: 'https://api.modarchive.org/downloads.php?moduleid=183672#tax_haven_dry_hump.mod', author: 'Curt Cool' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=98051#big_time_sensuality.mod', author: 'ISO/Axis Group' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=34568#CANNONFO.MOD', author: 'John Hare' }, { file: 'https://api.modarchive.org/downloads.php?moduleid=68835#desert_strike.mod', author: 'Jason Whitley' }, diff --git a/js/mod-processor-es5.js b/js/mod-processor-es5.js index fbe4c99..a8c366b 100644 --- a/js/mod-processor-es5.js +++ b/js/mod-processor-es5.js @@ -1,2 +1,2 @@ -var t=function(t,e,s){void 0===s&&(s=0);for(var i=new Uint8Array(t),o="",a=!1,n=0;!a;++n){var r=i[s+n];(a=0===r)||(o+=String.fromCharCode(r))}return o},e=function(t,e,s){return void 0===e&&(e=0),void 0===s&&(s=!1),new DataView(t).getUint16(e,s)},s=new Array(4);s[0]=new Float32Array(64);for(var i=0;i-1&&!a.done&&this.ticks>=a.delay){var r=this.samples[a.sample];n[s]+=r.data[Math.floor(a.samplePos)]*a.volume/64,a.samplePos+=7093789.2/(2*a.period*this.mixingRate),a.done||(r.repeatLength||r.repeatStart?a.samplePos>=r.repeatStart+r.repeatLength&&(a.samplePos=r.repeatStart):a.samplePos>r.length&&(a.samplePos=0,a.done=!0))}}this.filledSamples++,this.newTick=!1}},i.prototype.tick=function(){this.filledSamples>this.samplesPerTick&&(this.newTick=!0,this.ticks++,this.filledSamples=0,this.ticks>this.speed-1&&(this.ticks=0,this.rowRepeat<=0&&this.row++,(this.row>63||this.skipPattern)&&(this.skipPattern=!1,this.jumpPattern>-1?(this.position=this.jumpPattern,this.jumpPattern=-1,this.getNextPattern()):this.getNextPattern(!0)),this.rowJump>-1&&(this.row=this.rowJump,this.rowJump=-1),this.row>63&&(this.row=0),this.decodeRow()))},i.prototype.getNextPattern=function(t){t&&this.position++,this.position>this.positions.length-1&&(console.log("Warning: last position reached, going back to 0"),this.position=0);for(var e=0;e>4)-1,a=15&t[2+s],n=t[3+s],r=this.channels[e];r.delay=0,a?14===a?(r.cmd=224+(n>>4),r.data=15&n):(r.cmd=a,r.data=n):r.cmd=0,o>-1&&(3!==r.cmd&&5!==r.cmd&&(r.samplePos=0),r.done=!1,r.sample=o,r.volume=this.samples[o].volume),i&&(r.done=!1,3!==r.cmd&&5!==r.cmd?(r.period=i,r.samplePos=0):r.slideTo=i)}},i.prototype.executeEffect=function(t){try{a[t.cmd](this,t)}catch(e){console.warn("effect not implemented: "+t.cmd.toString(16).padStart(2,"0")+"/"+t.data.toString(16).padStart(2,"0"))}},i.prototype.getInstruments=function(){this.detectMaxSamples(),this.samples=new Array;for(var s=20,i=new Uint8Array(this.buffer),o=0;oa.length&&(a.repeatLength=0,a.repeatStart=0),this.samples.push(a),s+=30}},i.prototype.getPatternData=function(){var t=new Uint8Array(this.buffer,950);this.songLength=t[0];for(var e=2,s=0,i=0;is&&(s=o)}e=this.patternOffset;for(var a=0;a<=s;++a)this.patterns.push(this.buffer.slice(e,e+this.patternLength)),e+=this.patternLength},i.prototype.getSampleData=function(){for(var t=this.patternOffset+this.patterns.length*this.patternLength,e=0;e856&&(e.period=856))},3:function(t,e,s){t.ticks?e.slideTo&&t.ticks?e.periode.slideTo&&(e.period=e.slideTo)):e.period>e.slideTo&&(e.period-=e.slideSpeed,e.period>4;o&&i&&(e.vdepth=i,e.vspeed=o),e.vform>3&&(e.vpos=0)}e.period+=e.vdepth*s[3&e.vform][e.vpos]/63,e.vpos+=e.vspeed,e.vpos>63&&(e.vpos=e.vpos-64)},5:function(t,e){this[3](t,e),this[10](t,e)},6:function(t,e){this[4](t,e),this[10](t,e)},9:function(t,e){t.ticks||(e.samplePos=256*e.data)},10:function(t,e){if(t.ticks){var s=e.data>>4,i=15&e.data;i?s||(e.volume-=i):e.volume+=s,e.volume>63?e.volume=63:e.volume<0&&(e.volume=0)}},11:function(t,e){e.data>=0&&e.data<=t.patterns.length-1&&(t.skipPattern=!0,t.jumpPattern=e.data,t.rowJump=0)},12:function(t,e){t.ticks||(e.volume=e.data,e.volume>63&&(e.volume=63))},13:function(t,e){t.ticks||(t.rowJump=10*((240&e.data)>>4)+(15&e.data),t.skipPattern=!0)},224:function(t,e){t.ticks||(console.log("need to toggle lowPass",!!e.data),t.toggleLowPass(!!e.data))},228:function(t,e){},230:function(t,e){t.ticks||(0===e.data?e.loopInitiated?e.loops===e.loopCount&&(e.loopInitiated=!1):(e.loopInitiated=!0,e.loopStart=t.row,e.loopCount=0):e.loopInitiated&&(t.rowJump=e.loopStart,e.loopCount?e.loops++:(e.loopCount=e.data,e.loops=1)))},233:function(t,e){(t.ticks+1)%e.data||(console.log("retriggering note!",t.ticks+1),e.samplePos=0,e.done=!1)},234:function(t,e){t.ticks||(e.volume+=e.data,e.volume>63&&(e.volume=63))},235:function(t,e){t.ticks||(e.volume-=e.data,e.volume<0&&(e.volume=0))},237:function(t,e){t.ticks||(e.delay=e.data)},238:function(t,e){t.ticks||(t.rowRepeat?t.rowRepeat&&t.rowRepeat--:(t.rowRepeat=e.data,console.log("setting repeat to",t.rowRepeat)))},15:function(t,e){t.ticks||(e.data<32?t.speed=e.data:(t.bpm=e.data,t.calcTickSpeed()))}}; +var t=function(t,e,s){void 0===s&&(s=0);for(var i=new Uint8Array(t),o="",a=!1,n=0;!a;++n){var r=i[s+n];(a=0===r)||(o+=String.fromCharCode(r))}return o},e=function(t,e,s){return void 0===e&&(e=0),void 0===s&&(s=!1),new DataView(t).getUint16(e,s)},s=new Array(4);s[0]=new Float32Array(64);for(var i=0;i-1&&!a.done&&this.ticks>=a.delay){var r=this.samples[a.sample];n[s]+=r.data[Math.floor(a.samplePos)]*a.volume/64,a.samplePos+=7093789.2/(2*a.period*this.mixingRate),a.done||(r.repeatLength||r.repeatStart?a.samplePos>=r.repeatStart+r.repeatLength&&(a.samplePos=r.repeatStart):a.samplePos>r.length&&(a.samplePos=0,a.done=!0))}}this.filledSamples++,this.newTick=!1}},i.prototype.tick=function(){this.filledSamples>this.samplesPerTick&&(this.newTick=!0,this.ticks++,this.filledSamples=0,this.ticks>this.speed-1&&(this.ticks=0,this.rowRepeat<=0&&this.row++,(this.row>63||this.skipPattern)&&(this.skipPattern=!1,this.jumpPattern>-1?(this.position=this.jumpPattern,this.jumpPattern=-1,this.getNextPattern()):this.getNextPattern(!0)),this.rowJump>-1&&(this.row=this.rowJump,this.rowJump=-1),this.row>63&&(this.row=0),this.decodeRow()))},i.prototype.getNextPattern=function(t){t&&this.position++,this.position>this.positions.length-1&&(console.log("Warning: last position reached, going back to 0"),this.position=0);for(var e=0;e>4)-1,a=15&t[2+s],n=t[3+s],r=this.channels[e];r.delay=0,a?14===a?(r.cmd=224+(n>>4),r.data=15&n):(r.cmd=a,r.data=n):r.cmd=0,o>-1&&(3!==r.cmd&&5!==r.cmd&&(r.samplePos=0),r.done=!1,r.sample=o,r.volume=this.samples[o].volume),i&&(r.done=!1,3!==r.cmd&&5!==r.cmd?(r.period=i,r.samplePos=0):r.slideTo=i)}},i.prototype.executeEffect=function(t){try{a[t.cmd](this,t)}catch(e){console.warn("effect not implemented: "+t.cmd.toString(16).padStart(2,"0")+"/"+t.data.toString(16).padStart(2,"0"))}},i.prototype.getInstruments=function(){this.detectMaxSamples(),this.samples=new Array;for(var s=20,i=new Uint8Array(this.buffer),o=0;oa.length&&(a.repeatLength=0,a.repeatStart=0),this.samples.push(a),s+=30}},i.prototype.getPatternData=function(){var t=new Uint8Array(this.buffer,15===this.maxSamples?470:950);this.songLength=t[0];for(var e=2,s=0,i=0;is&&(s=o)}e=this.patternOffset;for(var a=0;a<=s;++a)this.patterns.push(this.buffer.slice(e,e+this.patternLength)),e+=this.patternLength},i.prototype.getSampleData=function(){for(var t=this.patternOffset+this.patterns.length*this.patternLength,e=0;ethis.buffer.byteLength?this.buffer.byteLength-t:s,a=new Int8Array(this.buffer,t,o),n=0;n856&&(e.period=856))},3:function(t,e,s){t.ticks?e.slideTo&&t.ticks?e.periode.slideTo&&(e.period=e.slideTo)):e.period>e.slideTo&&(e.period-=e.slideSpeed,e.period>4;o&&i&&(e.vdepth=i,e.vspeed=o),e.vform>3&&(e.vpos=0)}e.period+=e.vdepth*s[3&e.vform][e.vpos]/63,e.vpos+=e.vspeed,e.vpos>63&&(e.vpos=e.vpos-64)},5:function(t,e){this[3](t,e),this[10](t,e)},6:function(t,e){this[4](t,e),this[10](t,e)},9:function(t,e){t.ticks||(e.samplePos=256*e.data)},10:function(t,e){if(t.ticks){var s=e.data>>4,i=15&e.data;i?s||(e.volume-=i):e.volume+=s,e.volume>63?e.volume=63:e.volume<0&&(e.volume=0)}},11:function(t,e){e.data>=0&&e.data<=t.patterns.length-1&&(t.skipPattern=!0,t.jumpPattern=e.data,t.rowJump=0)},12:function(t,e){t.ticks||(e.volume=e.data,e.volume>63&&(e.volume=63))},13:function(t,e){t.ticks||(t.rowJump=10*((240&e.data)>>4)+(15&e.data),t.skipPattern=!0)},224:function(t,e){t.ticks||(console.log("need to toggle lowPass",!!e.data),t.toggleLowPass(!!e.data))},228:function(t,e){},230:function(t,e){t.ticks||(0===e.data?e.loopInitiated?e.loops===e.loopCount&&(e.loopInitiated=!1):(e.loopInitiated=!0,e.loopStart=t.row,e.loopCount=0):e.loopInitiated&&(t.rowJump=e.loopStart,e.loopCount?e.loops++:(e.loopCount=e.data,e.loops=1)))},233:function(t,e){(t.ticks+1)%e.data||(console.log("retriggering note!",t.ticks+1),e.samplePos=0,e.done=!1)},234:function(t,e){t.ticks||(e.volume+=e.data,e.volume>63&&(e.volume=63))},235:function(t,e){t.ticks||(e.volume-=e.data,e.volume<0&&(e.volume=0))},237:function(t,e){t.ticks||(e.delay=e.data)},238:function(t,e){t.ticks||(t.rowRepeat?t.rowRepeat&&t.rowRepeat--:(t.rowRepeat=e.data,console.log("setting repeat to",t.rowRepeat)))},15:function(t,e){t.ticks||(e.data<32?t.speed=e.data:(t.bpm=e.data,t.calcTickSpeed()))}}; //# sourceMappingURL=modplayer-js.js.map diff --git a/js/mod-processor.js b/js/mod-processor.js index 55d4713..4d63ea7 100644 --- a/js/mod-processor.js +++ b/js/mod-processor.js @@ -46,7 +46,6 @@ class PTModuleProcessor extends AudioWorkletProcessor{ // pattern data always starts at offset 1084 super(); this.port.onmessage = this.handleMessage.bind(this); - this.patternOffset = 1084; this.patternLength = 1024; } @@ -195,7 +194,8 @@ class PTModuleProcessor extends AudioWorkletProcessor{ vspeed: 0, vpos: 0, loopInitiated: false, - id: i + id: i, + cmd: 0 }; if (!this.channels[i]) { this.channels[i] = channel; @@ -240,6 +240,12 @@ class PTModuleProcessor extends AudioWorkletProcessor{ // but we stick to good old ST/NT modules const str = BinUtils.readAscii(this.buffer, 4, 1080); this.maxSamples = str.match("M.K.") ? 31 : 15; + + if (this.maxSamples === 15) { + this.patternOffset = 1080 - 480; + } else { + this.patternOffset = 1084; + } } /** @@ -278,11 +284,12 @@ class PTModuleProcessor extends AudioWorkletProcessor{ this.tick(); for (let chan = 0; chan < this.channels.length; ++chan) { const channel = this.channels[chan]; - const buffer = this.audioWorkletSupport ? outputs[chan][0] : outputs[0][outputChannel]; // select left/right output depending on module channel: // voices 0,3 go to left channel, 1,2 go to right channel outputChannel = outputChannel ^ (chan & 1); + const buffer = this.audioWorkletSupport ? outputs[chan][0] : outputs[0][outputChannel]; + // TODO: check that no effect can be applied without a note // otherwise that will have to be moved outside this loop if (this.newTick && channel.cmd) { @@ -472,6 +479,10 @@ class PTModuleProcessor extends AudioWorkletProcessor{ // Existing mod players seem to play a sample only once if repeatLength is set to 2 if (sample.repeatLength === 2) { sample.repeatLength = 0; + // some modules seems to skip the first two bytes for length + if (sample.length === 2) { + sample.length = 0; + } } if (sample.repeatLength > sample.length) { @@ -487,7 +498,8 @@ class PTModuleProcessor extends AudioWorkletProcessor{ getPatternData() { // pattern data always starts at offset 950 - const uint8buffer = new Uint8Array(this.buffer, 950); + const offset = this.maxSamples === 15 ? 470 : 950; + const uint8buffer = new Uint8Array(this.buffer, offset); this.songLength = uint8buffer[0]; let position = 2; let max = 0; @@ -515,7 +527,8 @@ class PTModuleProcessor extends AudioWorkletProcessor{ for (let i = 0; i < this.samples.length; ++i) { const length = this.samples[i].length, data = new Float32Array(length), - pcm = new Int8Array(this.buffer, offset, length); + maxLength = (offset + length) > this.buffer.byteLength ? this.buffer.byteLength - offset : length, + pcm = new Int8Array(this.buffer, offset, maxLength); // convert 8bit pcm format to webaudio format for (let j = 0; j < length; ++j) { @@ -524,7 +537,7 @@ class PTModuleProcessor extends AudioWorkletProcessor{ this.samples[i].data = data; - offset += length; + offset += maxLength; } } diff --git a/package-lock.json b/package-lock.json index 6b4d6ca..4119764 100644 --- a/package-lock.json +++ b/package-lock.json @@ -133,6 +133,12 @@ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, "asyncro": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/asyncro/-/asyncro-3.0.0.tgz", @@ -467,6 +473,12 @@ "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", "dev": true }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true + }, "cosmiconfig": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", @@ -732,6 +744,15 @@ } } }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -759,6 +780,26 @@ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, + "ecstatic": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.0.tgz", + "integrity": "sha512-EblWYTd+wPIAMQ0U4oYJZ7QBypT9ZUIwpqli0bKDjeIIQnXDBK2dXtZ9yzRCOlkW1HkO8gn7/FxLK1yPIW17pw==", + "dev": true, + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "electron-to-chromium": { "version": "1.3.64", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.64.tgz", @@ -804,6 +845,12 @@ "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==", "dev": true }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -896,6 +943,15 @@ } } }, + "follow-redirects": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", + "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1014,12 +1070,53 @@ "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", "dev": true }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, "html-comment-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", "dev": true }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-server": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", + "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", + "dev": true, + "requires": { + "colors": "1.0.3", + "corser": "~2.0.0", + "ecstatic": "^3.0.0", + "http-proxy": "^1.8.1", + "opener": "~1.4.0", + "optimist": "0.6.x", + "portfinder": "^1.0.13", + "union": "~0.4.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, "icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", @@ -1423,6 +1520,12 @@ "regex-cache": "^0.4.2" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1459,6 +1562,12 @@ "integrity": "sha1-haom09ru7t+A3FmEr5XMXKXK2fE=", "dev": true }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "nodent-compiler": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/nodent-compiler/-/nodent-compiler-3.2.9.tgz", @@ -1540,6 +1649,22 @@ "is-extendable": "^0.1.1" } }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -1594,6 +1719,28 @@ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, + "portfinder": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", + "integrity": "sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==", + "dev": true, + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -3587,6 +3734,12 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, "query-string": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", @@ -3713,6 +3866,12 @@ "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", "dev": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "reserved-words": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", @@ -4064,6 +4223,15 @@ "source-map": "~0.6.1" } }, + "union": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", + "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "dev": true, + "requires": { + "qs": "~2.3.3" + } + }, "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", @@ -4082,6 +4250,12 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "dev": true + }, "vendors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", @@ -4106,6 +4280,12 @@ "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", "dev": true }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", diff --git a/package.json b/package.json index 894b5be..9806e70 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,9 @@ "name": "modplayer-js", "version": "1.0.0", "description": "JavaScript player for SoundTracker/Noisetracker mod files using the webaudio AudioWorklet API.", - "main": "js/modplayer.js", + "main": "js/main.js", "scripts": { - "build": "microbundle", - "dev": "microbundle watch", + "build": "microbundle -i js/mod-processor.js -o dist && cp dist/modplayer-js.js js/mod-processor-es5.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { @@ -28,6 +27,7 @@ }, "homepage": "https://github.com/warpdesign/modplayer-js#readme", "devDependencies": { + "http-server": "^0.11.1", "microbundle": "^0.6.0" } }