Find file
Fetching contributors…
Cannot retrieve contributors at this time
149 lines (135 sloc) 5.48 KB
<!DOCTYPE html>
<html>
<head>
<script src="src/modfile.js"></script>
<script src="src/xmfile.js"></script>
<script src="src/modplayer.js"></script>
<script src="src/support.js"></script>
<style>
p { margin-top: 8px; margin-bottom: 8px}
</style>
<script>
var modPlayer;
var playing = false;
var channels = 2; //stereo
var sampleRate = 44100;
var bufferSize = 2048 * channels;
var prebufferSize = 12 * channels * 1024; // defines the latency
var outputAudio = new Audio();
//writeAudio thanks to: http://www.toverlamp.org/static/HTML5-Guitar-Tab-Player/
// function that describes the audio chain
var currentWritePosition = 0;
var lastSampleOffset = 0;
function writeAudio() {
if (!playing) { return; }
var currentSampleOffset = outputAudio.mozCurrentSampleOffset();
var playHasStopped = currentSampleOffset == lastSampleOffset; // if audio stopped playing, just send data to trigger it to play again.
while (currentSampleOffset + prebufferSize >= currentWritePosition || playHasStopped ) {
// generate audio
var audioData = modPlayer.getSamples(bufferSize);
// write audio
var written = outputAudio.mozWriteAudio(audioData);
currentWritePosition += written; //portionSize;
currentSampleOffset = outputAudio.mozCurrentSampleOffset();
playHasStopped = 0;
if (written < audioData.length) { // firefox buffer is full, stop writing
return;
}
}
lastSampleOffset = outputAudio.mozCurrentSampleOffset();
}
function play() {
status.innerHTML = "Playing (<a href='#' onclick='stop(); return false;'>stop</a>)";
playing = true;
}
function stop() {
status.innerHTML = "Paused (<a href='#' onclick='play(); return false;'>play</a>)";
playing = false;
}
/* load from harddrive using HTML5 File API */
function loadLocal(file) {
var reader = new FileReader();
/* ugly-ass closure nonsense */
reader.onload = (function(theFile) {
return function(e) {
/* actually load mod once we're passed the file data */
theFile = e.target.result; /* get the data string out of the blob object */
var modFile = new ModFile(theFile);
modPlayer = new ModPlayer(modFile, 44100);
play();
document.getElementById('status').innerText = '';
};
})(file);
reader.readAsBinaryString(file);
document.getElementById('status').innerText = '';
}
function loadRemote(path) {
var fetch = new XMLHttpRequest();
fetch.open('GET', path);
fetch.overrideMimeType("text/plain; charset=x-user-defined");
fetch.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
/* munge response into a binary string */
var t = this.responseText || "" ;
var ff = [];
var mx = t.length;
var scc= String.fromCharCode;
for (var z = 0; z < mx; z++) {
ff[z] = scc(t.charCodeAt(z) & 255);
}
var binString = ff.join("");
var modFile = new ModFile(binString);
modPlayer = new ModPlayer(modFile, 44100);
play();
document.getElementById('status').innerText = '';
}
}
document.getElementById('status').innerText = 'loading...';
fetch.send();
}
// setup audio output
function init() {
status = document.getElementById("status");
if(outputAudio.mozSetup) {
outputAudio.mozSetup(2, sampleRate);
writeAudio(); // initial write
var writeInterval = Math.floor(1000 * bufferSize / sampleRate);
setInterval(writeAudio, writeInterval);
}
}
</script>
</head>
<body onload="init()">
<h1>JSModPlayer</h1>
<h2>The imaginatively named Javascript .mod player by Gasman</h2>
<p>This is a work in progress - not all effects are implemented yet.</p>
<ul>
<li><a href="javascript:loadRemote('mods/ambpower.mod')">Ambient Power (Vogue / Triton)</a></li>
<li><a href="javascript:loadRemote('mods/dope.mod')">Dope / Onward Ride (Jugi / Complex)</a></li>
<li><a href="javascript:loadRemote('mods/frust.mod')">Mental Frustration (Nugget / Rebels)</a></li>
<li><a href="javascript:loadRemote('mods/mindkick.mod')">Mindkick (Mindfuck / Mentasm)</a></li>
<li><a href="javascript:loadRemote('mods/sundance.mod')">Sundance (Purple Motion / Future Crew)</a></li>
<!-- These are benchmark modules. Not for public consumption....yet :) -->
<!--<li><a href="javascript:loadRemote('mods/ode_to_protracker.mod')">Ode to Protracker (Asle / Sylvain Chipaux)</a></li>-->
<li><a href="javascript:loadRemote('mods/RandomVoice-Monday.mod')">Monday (Edvin Fladen a.k.a "Random Voice")</a></li>
<li>From harddrive: <input type="file" id="input" multiple="true" onchange="loadLocal(this.files[0])"></li>
</ul>
<div id="status">Not started</div>
<h3>Credits</h3>
<p>Original by Gasman.
<a href="http://twitter.com/westdotcodottt">@westdotcodottt</a> -
<a href="http://matt.west.co.tt/">matt.west.co.tt</a> -
<a href="mailto:gasman@raww.org">gasman@raww.org</a> - 22 May 2010
</p>
<p>Forked and improved by
<a href="http://billy.wenge-murphy.com/">Billy Wenge-Murphy</a> -
<a href="http://twitter.com/billywm">@BillyWM</a> -
<a href="mailto:iamthebilly@gmail.com">iamthebilly@gmail.com</a> - April 2011.<br>
Added local file loading (HTML5 File API), implemented more effects, fixes to playback
</p>
<p>Source code on Github:
<a href="http://github.com/gasman/jsmodplayer">Gasman</a> (original)
<a href="https://github.com/BillyWM/jsmodplayer">BillyWM</a> (fork)
</p>
</body>
</html>