Anton Shestakov <av6@dwimlabs.net>, Wed, 20 Jun 2018 21:38:38 +0800
recipe: add current runtime_methods.json just to track what player.js uses
player.js
Permissions: -rw-r--r--
/* Based on mozplayer.js by Daniel Svensson, dsvensson@gmail.com */ function parseMetadata(ref) { var read_int32 = function() { var value = Module.getValue(ref + offset, 'i32'); var read_string = function() { var value = Module.Pointer_stringify(Module.getValue(ref + offset, 'i8*')); res.length = read_int32(); res.intro_length = read_int32(); res.loop_length = read_int32(); res.play_length = read_int32(); offset += 4 * 12; // skip reserved fields res.system = read_string(); res.game = read_string(); res.song = read_string(); res.author = read_string(); res.copyright = read_string(); res.comment = read_string(); res.dumper = read_string(); function loadArrayBuffer(url, done, fail) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; xhr.onload = function() { if (this.status !== 200) { var Player = Backbone.Model.extend({ // libgme output is in stereo only // largest signed short integer value (16 bits), for scaling signal i16Max: Math.pow(2, 16 - 1) - 1, window.AudioContext = (window.AudioContext || window.webkitAudioContext); if (window.AudioContext) { this.ctx = new window.AudioContext(); this.bufferSize = this.ctxSize * this.channels; this.ref = Module._malloc(4); this.buffer = Module._malloc(this.bufferSize * 2); console.debug('Using Web Audio API'); console.error('Web Audio API is not supported, try another browser'); var payload = new Uint8Array(data); var error = Module.ccall('gme_open_data', 'string', ['array', 'number', 'number', 'number'], [payload, payload.length, this.ref, this.ctx.sampleRate]); console.error('gme_open_data failed: ' + error); this.emu = Module.getValue(this.ref, 'i32'); var trackCount = Module.ccall('gme_track_count', 'number', ['number'], [this.emu]); for (var i = 0; i < trackCount; i++) { var trackInfo = this.getTrackInfo(i); Module.ccall('gme_delete', 'number', ['number'], [this.emu]); this.get('track').clear(); getTrackInfo: function(track) { var error = Module.ccall('gme_track_info', 'string', ['number', 'number', 'number'], [this.emu, this.ref, track]); console.error('gme_track_info failed: ' + error); var memory = Module.getValue(this.ref, '*'); var result = parseMetadata(memory); Module.ccall('gme_free_info', 'number', ['number'], [memory]); startTrack: function(track) { var error = Module.ccall('gme_start_track', 'string', ['number', 'number'], [this.emu, track]); console.error('gme_start_track failed: ' + error); this.set('track', this.tracks.get(track)); this.get('track').set('status', 'stopped'); isTrackEnded: function() { return Module.ccall('gme_track_ended', 'number', ['number'], [this.emu]) === 1; var error = Module.ccall('gme_seek', 'string', ['number', 'number'], [this.emu, msec]); console.error('gme_seek failed: ' + error); return Module.ccall('gme_tell', 'number', ['number'], [this.emu]); return Module.ccall('gme_voice_count', 'number', ['number'], [this.emu]); this.get('track').set({'status': 'stopped', 'position': this.tell()}); this.node = this.ctx.createScriptProcessor(this.ctxSize, 0, this.channels); this.node.onaudioprocess = function(e) { if (player.isTrackEnded()) { var channels = [e.outputBuffer.getChannelData(0), e.outputBuffer.getChannelData(1)]; var error = Module.ccall('gme_play', 'string', ['number', 'number', 'number'], [player.emu, player.bufferSize, player.buffer]); console.error('gme_play failed: ' + error); for (var i = 0; i < player.bufferSize; i++) { for (var n = 0; n < e.outputBuffer.numberOfChannels; n++) { channels[n][i] = Module.getValue(player.buffer + i * e.outputBuffer.numberOfChannels * 2 + n * 2, 'i16') / limit; player.get('track').set('position', player.tell()); this.node.connect(this.ctx.destination); this.get('track').set('status', 'playing');