question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Suggestion: rewrite file format handlers in Rust

See original GitHub issue

Hi @jhalme, first I want to say thank you for an incredibly nice little thing here. 😄 And thanks for making it FOSS!

I guess I’m feeling a bit nostalgic right now, recorded an .avi of an old MSDOS intro I made 20 years ago and put up on YouTube the other day. And now I’m looking into making a web port of this intro, just for the sake of it…

I integrated the player in my web app quite easily, using this code (documenting this since it might help others who also want to integrate the player into their intros/whatever). Only the files below are needed if you don’t want the UI; no jQuery etc is necessary.

<script src="webaudio-mod-player/utils.js" type="text/javascript"></script>
<script src="webaudio-mod-player/player.js" type="text/javascript"></script>
<script src="webaudio-mod-player/pt.js" type="text/javascript"></script>

And then in a button event handler I kick it live like this:

window.module = new Modplayer();
window.module.setrepeat(true);

// Because the file gets loaded asynchronously, we need to wait until it's ready before we
// start playing the mod file.
window.module.onReady = () => {
  window.module.play();

  // ...start my animation etc, which is handled by some Rust code.
}
window.module.load("music.mod");

This all works quite well, and the performance is satisfying (only tested on Chrome on desktop yet.) With the https://mod.haxor.fi/ player, I noted some files (probably more complex ones) were stuttering when I played them on my iPhone - like you write on the web page, the Javascript runtimes can very greatly in speed.


I think we should consider rewriting the inner loops here in Rust, targetting WebAssembly. As you probably already know, webassembly is supported in all the bigger browsers these days and it’s providing a lot better performance than JavaScript will ever be able to deliver, because of its compiled and statically typed nature.

So, I think we should think about this. Maybe this is something you have already thought about? Or what do you think? This demo from hellorust.com is what inspired me to start playing around a bit with WebAssembly and Rust, and it’s actually really fun and works well. You have to use a nightly Rust compiler at the moment (webassembly is not supported by the stable releases yet) but apart from that, it works pretty much flawlessly and provides a really nice & capable platform for “low-level web stuff” - which .mod playing happens to be.

If you have a particular file handler (S3M? XM?) that is more performance-demanding than the others, this could perhaps be a suitable candidate for trying this idea out.

All in all, thanks for a great tool now already! 👍

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
electronooracommented, Feb 1, 2018

Hello, and thank you for the kind words - I really appreciate it! 😃

I am aware of the performance issue, and it actually seems be more frequent on desktop Chrome in comparison to macOS Safari or Firefox Quantum. Some XM modules with a large number of channels are especially prone to it, although the stuttering seems to always occur at particular positions in the song. As you also mentioned, I think that it is due to the heavy inner loop in the software mixing and interpolation code. It becomes even more apparent when switching the audio output sample rate from 44/48kHz to 96kHz.

Currently, Firefox seems to be the browser least affected by the issue. It seems that different browsers might have different priorities for the thread running Web Audio ScriptProcessorNode.onaudioprocess -callbacks.

As it turns out, I too had been thinking about converting the mixing code into using WebAssembly, although my plan was to use a language more familiar to me - plain old C. 😃 It’s more of a gut feeling at the moment, but I think that converting the channel loop inside .mix on each player into WebAssembly would provide a marked improvement in performance.

As soon as I have some more time to work on this project, I’ll start looking a bit closer into experimenting with this - perhaps even before continuing with .IT player code.

0reactions
electronooracommented, Mar 14, 2018

That’s an excellent analysis and comparison - thank you!

The lack of interpolation and volume ramping makes the Protracker mixing code perform reasonably well, but ST3 and FT2 mixing hits the CPU quite hard. Ping-pong looping in FT2 code also has lots of branches and nested contexts, so it could definitely use some improvement.

Some XM modules seem to be especially prone to stuttering. These two, for example:

https://mod.haxor.fi/Hunz/clone_it.xm https://mod.haxor.fi/Mystical/system_override.xm

Intrestingly, the stuttering seems to always occur at the same position within the module - for clone_it.xm, it is just before position 0x0a. I noticed that at least on Chrome, the heap usage goes absolutely bananas right at that position:

screen shot 2018-03-14 at 18 29 35

So using Webassembly for the mixing code may also help in providing finer control over memory allocation and when GC is allowed to run.

Read more comments on GitHub >

github_iconTop Results From Across the Web

eyre - Rust - Docs.rs
This library provides eyre::Report , a trait object based error handling type for easy idiomatic error handling and reporting in Rust applications.
Read more >
Rewriting of a small component from C to Rust - Pietro Lorefice
FOLLOW RUSTLAB CHANNEL In this first webinar, we'll talk with Pietro Lorefice about rewriting a small component from C to Rust.
Read more >
Editor compatibility and the new error format - Rust Internals
One of the interesting questions for the new error format is how much to retain compatibility with existing editors.
Read more >
A curated list of Rust code and resources. - GitHub
kpcyrd/rshijack — A TCP connection hijacker, rust rewrite of shijack build badge ... with files and directories in massive amounts in a fast...
Read more >
A practical guide to async in Rust - LogRocket Blog
One example is the actix_web web framework, which wraps its own API around tokio . Most of the time, you can choose any...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found