libopenmpt emscripten port

Started by SimonG, July 24, 2014, 21:35:29

Previous topic - Next topic

SimonG

Hi,
I just wanted to let you know, that I finally created a JavaScript port of libopenmpt with Emscripten.
Saga Musix, you may remember me from the ModArchive Forums where I presented my earlier port of a different module player library.
I switched because it turned out that libopenmpt is much better suitable for connecting it with the WebAudioAPI.
Of course my JS port is still missing features, but is usable by now.
If you want to check is out: The code is hosted on Github. You can also try it your browser on the demo page.
Let me know how you like it. :D

Saga Musix

Nice work. Did you come across any problems while doing this, and how did you fix them? I remember that manx attempted an emscripten port a while back, and he ran into some problems where emscripted generated apparently buggy code, which made some floating point related test cases fail (module rendering still worked though, albeit slow).
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

manx

I would be great if you can make your modifications to libopenmpt (if any) public and provide the build scripts you used for building with emscripten. I would really like to integrate this into the libopenmpt code base itself.
Which emscripten version did you use?
The problems I had been facing might have been related to the fact that the emscripten version in debian is rather old (the last version before the new fastcomp backend). Did you try running the testsuite with your port?
Anyway, a small bug report for your port: Audio playback seems to be somewhat broken for me. It plays about 1 second of audio and then stops. Hitting pause twice plays another second and stops again. This is Firefox 31 on Ubuntu 12.04.

manx

Oh, I somehow missed your libopenmpt repository at github. So all your changes are already available. Great! :)

SimonG

#4
There were some issues, when I tried to run a small example, that was printing the audio to stdout in nodejs for testing. It was producing awkwardly distorded audio. It turned out, that nodejs somehow messed up the output and the libraray was working correctly.

manx, as you just found out, there is a libopenmpt repository. All my changes are in these two commits. I only modified the build system.
The emscription version is  1.16.0 (commit 326078dbfd2d1b412546dffef81964c3d2ca125d). I compiled it myself quite a while ago, but it already uses the fastcomp backend. There is a good guide in the emscripten wiki (a quadcore cpu is reccommended ;)).
I haven't run the tests yet, but i'll try to do so.

I will also look into your bug, strangely it works for me in Firefox and Chrome. Unfortunateley I am stuck with Firefox 30, as my internet connection is broken and I'm online via my phone.

Update:
I ran the tests. The TestITCompression fails. This is what it tells me:
Test: test/test.cpp(88): TestITCompression:
Test: test/test.cpp(88): TestITCompression: FAIL
FAIL: Test: test/test.cpp(88): TestITCompression : '
TEST ERROR: exception: vector


TestLoadSaveFile fails too. This seems correct to me, as you can't do file io in regular javascript. The tests were run in nodejs.

manx

Quote from: SimonG on July 25, 2014, 07:07:03
There were some issues, when I tried to run a small example, that was printing the audio to stdout in nodejs for testing. It was producing awkwardly distorded audio. It turned out, that nodejs somehow messed up the output and the libraray was working correctly.

I also remember problems getting nodejs to not garble the output, afair, I did not get stdout to work correctly with nodejs.

Quote from: SimonG on July 25, 2014, 07:07:03
The emscription version is  1.16.0 (commit 326078dbfd2d1b412546dffef81964c3d2ca125d). I compiled it myself quite a while ago, but it already uses the fastcomp backend. There is a good guide in the emscripten wiki (a quadcore cpu is reccommended ;)).

Debian has emscripten 1.10, which is totally ancient. I'm currently trying to build a current version. Will probably take some time :).

Quote from: SimonG on July 25, 2014, 07:07:03
I ran the tests. The TestITCompression fails. This is what it tells me:
Test: test/test.cpp(88): TestITCompression:
Test: test/test.cpp(88): TestITCompression: FAIL
FAIL: Test: test/test.cpp(88): TestITCompression : '
TEST ERROR: exception: vector


TestLoadSaveFile fails too. This seems correct to me, as you can't do file io in regular javascript. The tests were run in nodejs.

The it compression test (currently) also perform file i/o, so they fail probably for the same reason.
As you might have noticed, in -beta5, I added a basic Makefile.config.emscripten (which is not too different from the file you use).
The relevant part for getting the file i/o testcases to work is

EXESUFFIX=.js
SOSUFFIX=.js
RUNPREFIX=nodejs
TEST_LDFLAGS= --pre-js build/make/test-pre.js

and the contents of the build/make/test-pre.js file. This way, nodejs should allow the file i/o needed for the testcases.
Can you try rerunning the test cases that way?

manx

Quote from: manx on July 25, 2014, 06:29:00
Anyway, a small bug report for your port: Audio playback seems to be somewhat broken for me. It plays about 1 second of audio and then stops. Hitting pause twice plays another second and stops again. This is Firefox 31 on Ubuntu 12.04.

Update: Works without problems on Firefox 31 on Mint17 (aka Ubuntu 14.04).
On Ubuntu 12.04, I am running pulseaudio with 96kHz instead of the default 48kHz which might or might not be relevant (I know nothing about the javascript WebAudio API).

manx

Quote from: manx on July 25, 2014, 14:51:27
I'm currently trying to build a current version.

I successfully built emscripten 1.21 on Mint17 (Ubuntu 14.04).

manx@idefix ~/projects/openmpt/trunk-emscripten $ emcc --version
emcc (Emscripten GCC-like replacement) 1.21.0 (commit 06961a0ef6e3d8d92d5e36ff904262fefec62bec)
[...]
manx@idefix ~/projects/openmpt/trunk-emscripten $ nodejs --version
v0.10.25

After patching out a tiny test case which fails for unknown reasons with this version (see http://sourceforge.net/p/modplug/code/4190/, it completely passes the test suite for me with nodejs on amd64.
The stock makefile (as of -beta5) also builds the final javascript file (libopenmpt.js) directly without the need to explicitely set the exported-to-javascript symbols via emcc commandline. This is done using symbol visibility. Thus, you can probably simplify your documentation a bit.
libopenmpt.js, built with the stock makefile, works as a drop-in replacement with your chiptune2.js just fine (i put it up at http://manx.datengang.de/openmpt/chiptune2.js-manx/).

In case you did not know (and dont want to grad the current version from our svn directly), there a snapshots available at http://buildbot.openmpt.org/builds/, and in particular, http://buildbot.openmpt.org/builds/auto/src/libopenmpt-0.2.4191.tar.gz.

I think, I can consider emscripten a supported platform now (even though I would not be surprised if there are still some problems waiting to be found :) ).
Thanks for your work on chiptune.js and chiptune2.js. Working module playback in browsers without the need for flash or java is a big win! :)

SimonG

Quote from: manx on July 26, 2014, 09:22:32
Update: Works without problems on Firefox 31 on Mint17 (aka Ubuntu 14.04).
On Ubuntu 12.04, I am running pulseaudio with 96kHz instead of the default 48kHz which might or might not be relevant (I know nothing about the javascript WebAudio API).
I can't reproduce the bug. Pulseaudio on my system (Fedora 20) doesn't seem to accept anything over 48kHz. But I can imagine that the browsers Web Audio API implementations behave buggy with non-standard audio configurations. Chrome even crashes if there is no audio sink selected in Pulseaudio.

Quote from: manx on July 26, 2014, 09:46:42
I successfully built emscripten 1.21 on Mint17 (Ubuntu 14.04).


manx@idefix ~/projects/openmpt/trunk-emscripten $ emcc --version
emcc (Emscripten GCC-like replacement) 1.21.0 (commit 06961a0ef6e3d8d92d5e36ff904262fefec62bec)
[...]
manx@idefix ~/projects/openmpt/trunk-emscripten $ nodejs --version
v0.10.25

I think I should update my build some time. ;)

Quote from: manx on July 25, 2014, 14:51:27
After patching out a tiny test case which fails for unknown reasons with this version (see http://sourceforge.net/p/modplug/code/4190/, it completely passes the test suite for me with nodejs on amd64.
The stock makefile (as of -beta5) also builds the final javascript file (libopenmpt.js) directly without the need to explicitely set the exported-to-javascript symbols via emcc commandline. This is done using symbol visibility. Thus, you can probably simplify your documentation a bit.
libopenmpt.js, built with the stock makefile, works as a drop-in replacement with your chiptune2.js just fine (i put it up at http://manx.datengang.de/openmpt/chiptune2.js-manx/).

In case you did not know (and dont want to grad the current version from our svn directly), there a snapshots available at http://buildbot.openmpt.org/builds/, and in particular, http://buildbot.openmpt.org/builds/auto/src/libopenmpt-0.2.4191.tar.gz.
Great! This makes building nice and easy. I've updated my building instructions.

Quote from: manx on July 26, 2014, 09:46:42
I think, I can consider emscripten a supported platform now (even though I would not be surprised if there are still some problems waiting to be found :) ).
Thanks for your work on chiptune.js and chiptune2.js. Working module playback in browsers without the need for flash or java is a big win! :)
I am going to try and add more features to chiptune2.js and make it more robust. When I encounter problems I'll let you know.

manx

Quote from: SimonG on July 27, 2014, 20:10:59
Quote from: manx on July 26, 2014, 09:22:32
Update: Works without problems on Firefox 31 on Mint17 (aka Ubuntu 14.04).
On Ubuntu 12.04, I am running pulseaudio with 96kHz instead of the default 48kHz which might or might not be relevant (I know nothing about the javascript WebAudio API).
I can't reproduce the bug. Pulseaudio on my system (Fedora 20) doesn't seem to accept anything over 48kHz. But I can imagine that the browsers Web Audio API implementations behave buggy with non-standard audio configurations. Chrome even crashes if there is no audio sink selected in Pulseaudio.

I can reproduce this on all 3 of my Ubuntu 12.04 boxes. It happens even when running pulseaudio in default configuration. It did not even work when using other sample rates in your player code.

Anyway, I rewrote your player code to use the callback based ScriptProcessorNode nstead of scheduling multiple consecutive AudioBufferSourceNodes using timestamps. This works just fine on all my linux boxes running firefox (did not yet check windows or chrome). Disclaimer: I have no experience with javascript, so I might be doing some stupid things there. I put the code up at github https://github.com/manxorist/chiptune2.js. Feel free to merge this if you like it. The demo is at http://manx.datengang.de/openmpt/chiptune2.js-manx/.

Saga Musix

Nice work, I'm getting even better results performance-wise with manx' modifications, I think. At least I can recall experiencing far more dropouts in the other version.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

SimonG

Sorry for answering late. I'm have been very busy with lots other stuff and still will be for some more weeks.
Thank you for improving the player. Using the ScriptProcessorNode sounds like a good idea to me. I'm not an JavaScript expert either so I'm always open to new ideas.
I haven't checked your code yet. However I pulled your changes into my repository. If there are further improvements feel free the submit a pull request on Github.

Saga Musix

#12
I'm now using chiptune2.js + libopenmpt on both ModArchive and s3m.it and it's working really great so far and is super easy to integrate. I can really recommend this combination to anyone needing module playback on their website.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

RyanBram

Dear OpenMPT developers and community,

With the current enhanced MIDI Importer, I am prepare to convert my whole collection of MIDI file to be used for my HTML5 games. But the current port of libopenmpt in Chiptine2.js has almost 2.5 mb in size which will bloating my distribution compared to my game assets. It also not very friendly for people with low bandwidth.

Can anybody show me if there is a workaround or options to resulting smaller emscripten port of libopenmpt? Maybe by omitting unused module formats, which in my case I plan to use only IT, MPTM, and MO3.

Thanks,
RyanBram

Saga Musix

Why don't you use an actual javascript MIDI player rather than libopenmpt, which would be much more suitable for what you are trying to do, and most likely smaller as well? I know there are some MIDI players written in JavaScript, so you should definitely check them out.

To answer your question, though, removing supported module formats will only give you tiny gains in size - emscripten has a large overhead, and the answer is to always prepare a gzipped and optionally brotli-compressed version of libopenmpt. This will get the size down to 500kb, which is still a lot, but actually quite an OK size for the pile of code in there.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.