Skip to content

Commit

Permalink
Modfile fixes (#6)
Browse files Browse the repository at this point in the history
- REMOVED: modules that do not play correctly yet from the playlist
- FIXED: channel.cmd wasn't reset after loading a new mod
- FIXED: if channel.length == 2 length seems to be ignored by players (Agony)
- FIXED: very old mod files with 15 samples had wrong offsets for patterns/positions (Silkworm)
- FIXED: oops, fixed channel swapping in compatibility mode

- ADDED: build instructions
- ADDED: note about Xbox One special case
  • Loading branch information
warpdesign authored Sep 18, 2018
1 parent 547fe36 commit ae3f316
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
dist
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
14 changes: 7 additions & 7 deletions js/main.js
Original file line number Diff line number Diff line change
@@ -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' },
Expand Down
2 changes: 1 addition & 1 deletion js/mod-processor-es5.js

Large diffs are not rendered by default.

25 changes: 19 additions & 6 deletions js/mod-processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -524,7 +537,7 @@ class PTModuleProcessor extends AudioWorkletProcessor{

this.samples[i].data = data;

offset += length;
offset += maxLength;
}
}

Expand Down
Loading

0 comments on commit ae3f316

Please sign in to comment.