-
Notifications
You must be signed in to change notification settings - Fork 11
/
notes
65 lines (37 loc) · 3.29 KB
/
notes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
These are my notes (Liam Wilson). I gave MrRio's js-snes-player a go, but it failed to work in both Firefox 31 and Chrome 36.0.1985.143.[3~
Error messages:
Firefox: Error: No audio sink available. sink.js:412
Chrome: Uncaught [object Object] sink.js:35
Seems to be using a project called sink.js to play back audio. sink.js seems to be broken in both FF and Chrome.
I'll concentrate on Firefox for now. Strangely it fails in different places in FF and Chrome.
Looking at the code:
Emscripten generated code in snes_spc-0.9.0/snes_spc.js . This looks like old Emscripten code (pre-asm.js ). From the comments at the top:
// Note: Some Emscripten settings will significantly limit the speed of the generated code.
// Note: Some Emscripten settings may limit the speed of the generated code.
// TODO: " u s e s t r i c t ";
Last commit by MrRio is Aug 2012. This explains it (that's about 6 months before asm.js was available). Will need to regenerate the code at some point. Shouldn't affect fixing the audio bug.
Web Audio was also a mess in 2012 (and still is in 2014 really). This probably explains why sink.js just fails.
Looks like last commit to sink.js was https://github.com/jussi-kalliokoski/sink.js/commits/master in October 2012. Maybe abandoned.
Anyway, back to the audio bug...
Next it loads js/js-snes-player.js
Module pattern. jsSNESPlayer created then init function called. init sets up a bunch of stuff (I assume it's twitter bootstrap bumpf). In the end, when you click the play button play gets called on line 111.
From debugger, play defined on js-snes-player.js:22 .
Had a look through play function. It fails when it tries to initialize the Sink. sink.js is totally broken. 2 years old, overly complicated and unmaintained. I'll need a new way to play back the audio.
The business end of the play function is on line 67:
proxy.on('audioprocess', function(buffer, channelCount){
var retval = _spc_play(snes_spc, bufferSize / 2, buf);
_spc_filter_run(filter, buf, bufferSize);
for (i = 0; i < bufferSize; i ++) {
// Take a mono stream
if ((i - 1) % 2 == 0) {
buffer[i] = HEAP8[i + buf] / 120;
} else {
buffer[i] = HEAP8[i + buf - 1] / 120;
}
}
console.log('Send audio to buffer... Memory points from HEAP ' + i + ' to ' + (i + buf));
}, 2, null, 12000);
This is the audio callback. The buffer "buffer" is the output buffer for the Web Audio API. bufferSize is the number of samples to generate. buf is an offset in to the Emscripten heap. It is where the audio data is calculated and stored by the Emscripten code.
Plan of attack: disable sink.js and turn the audio generation in to a normal function
That worked. I took https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode example code and increased the buffer size. I also had to tweak things slightly as the original code interlieves stereo channels. I had to generate tiwce as much audio data and then extract one channel for playback.
Rebuilt with new Emscripten. Sprinkled a bunch of EMSCRIPTEN_KEEPALIVE over the relevant functions in spc.cpp and compiled using emcc -O1. It seems that O2 doesn't work atm. Probably my fault, I'll have a look at this some point. Anyway, O1 seems to be enough to enable asm.js which gives a nice performance boost (10x in my unscientific benchmark)