JavaScript player for the famous Fasttracker II and Protracker module formats.
Plays modules plugin-free with low CPU usage in modern browsers.
Note: The player is in an early stage of implementation. At the moment there is no API for stopping playback. Also many effects are not implemented, yet.
ModPlayer.js
uses the HTML5 Web Audio API. See whether your browser is supported at caniuse.com.
Note: The current implementation is known not to play well in Firefox. Please use a Webkit-based browser like Chrome or Safari.
Download or install with Bower package manager:
bower install junghans-schneider/ModPlayer.js
Add a script tag:
<script src="bower_components/ModPlayer.js/modplayer.min.js"></script>
That's it!
Playback
mp.module(data).play();
data
is an ArrayBuffer
in this case. You can also use mp.loadModule()
to load a module from your server:
mp.loadModule('mymodule.xm', function (err, module) {
if (err) {
// failed to load module
} else {
module.play();
}
});
Adding another module format
There is a simple plugin mechanism for adding support for other module formats. Just register a parser function which returns null for inadequate input:
mp.format.register(parseMyModule);
function parseMyModule(data) {
if (! isMyModule()) {
return null;
}
var iter = mp.format.bytesIter(data);
var parsedData = readMyModule(iter); // magic happens here
return parsedData;
}
The generic mp.format.parseModule()
function calls each registered parser until one of them doesn't return null
, i.e. until one of them parsed the data. data
is an Int8Array
. We suggest to use the built-in bytes iterator for reading the data:
iter.str(17); // read next 17 bytes as string
iter.byte(); // read one byte as integer
iter.word(); // ... two bytes
iter.dword(); // ... four bytes
iter.step(2).byte(); // just skip the next 2 bytes, then read a byte
iter.pos(); // get the current position of the iterator
Numbers are read as little endian and by default unsigned. Pass true
to read signed:
iter.word(true);
Use iter.list()
to get a list of values:
iter.list('byte', 256);
You can also pass a custom read()
function, which gets the iterator as first argument. Add additional arguments at the end:
iter.list(readPattern, numPatterns, numChannels);
function readPattern(iter, numChannels) {
... // do complex read operations here
}
Some of the util functions in util.js
may also help you implementing your format parser.