steffest / BassoonTracker

Webbased old-school Amiga music tracker in plain old javascript - Plays and edits Amiga Mod files and FastTracker XM files
http://www.stef.be/bassoontracker/
MIT License
1.01k stars 61 forks source link

Request: Ability to render the song to wav or Ogg file #7

Closed blurymind closed 5 years ago

blurymind commented 5 years ago

Right now it is pretty awesome, but it lacks the fundamental ability to export the music data to something that other software can read.

I am requesting this, because I am actually interested in embedding bassoon into gdevelop- to be used as a music tracker by game devs. https://github.com/4ian/GDevelop I already did that with piskel and it worked out quite well. :)

Bundling a copy of bassoon with gdevelop can be beneficial to both projects imo - giving exposure to bassoon and getting it in the hands of more users. I will like to keep the vanilla version of the editor- so it will retain all of its original charm. The only thing that I will need to do is inject a button 'Save back to Gdevelop' somewhere in the UI of my copy.

Unfortunately without the ability to actually export the data as a music file, gdevelop will not be able to use it.

Our other option is sonant or soundbox, but I like bassoon more.

steffest commented 5 years ago

There is already an option to export the module to a wav file (File operations -> Save Module as -> wav) but currently it is limited to the current pattern due to browser memory limitations. However if the gdevelop is running locally I see 3 options:

  1. we might use a batch processor on the local client to first export each pattern to wav and stitch them together.
  2. as bassoon produces standard .mod or .xm files, we might use another library to convert those to .wav or .mp3
  3. use a server-side process to render to .wav or .mp3

In fact - that last one I'm planning to implement anyway for the online version - but the second one will probably be much faster.

Of course you also could keep the music as mod files and include a mod playback routine in your end product. File size will be smaller, but - at least for the HTML5 version - it will use more CPU then a standard mp3 playback.

I'll look into it some more!

blurymind commented 5 years ago

Ah yes, sorry I couldnt initially find it. I thought that was exporting the sound sample, rather than rendering the song itself. Sorry I made a rushed judgement, should have read the readme more carefully.

Thank you for suggesting some ideas to explore. From the listed I like 2 the most and now wonder if there is some npm package I can get for rendering a wav from the mod. This is something worth exploring!

I played with bassoon a bit more today and must say that I am quite impressed with it. This is the best html5 tracker at the moment. You have created something that is quite special here

If bassoon can render the entire song (all 4 channels) on its own one day- that would be incredible! It's an amazing tracker!

blurymind commented 5 years ago

@steffest I found this library: https://www.npmjs.com/package/musicxml-to-wav https://www.npmjs.com/package/musicxml-to-mp3 Not sure if it will work. Wouldnt it be great if we used a library to add the feature to bassoon itself :)

I found a couple of js mod players, but nothing that can actually render it to a file https://www.npmjs.com/package/protracker https://github.com/jhalme/webaudio-mod-player

Btw Gdevelop 5 runs inside electron, not sure if that will help with the problem. Electron is based on chromium, but has less restrictions. I think I can embed bassoon to run in the same way piskel runs inside gdevelop via the electron api. Bassoon can technically have a desktop version on its own too if you ever want to- it wont take a lot of code to embed it in an electron container and there are a few advantages to that.You can for example be able to have custom context menus and better file system access.

Gdevelop is developed in that way. It has a web app, but it also has an electron version. The two share most of the code. The build/release process is very easy

steffest commented 5 years ago

I did some quick tests. If your system is beefy enough - the browser can render the entire song in memory and save it to wav - however this takes a long time and if it's a long song it will probably kill your browser. Delegating this to another process seems a logical step. I find that openmpt123 is probably the easiest way to implement ( https://lib.openmpt.org/libopenmpt/download/ ) it's a command line tool, has a render option and is probably the most compatible tracker player around.

I know Electron but at this point I would like to keep Bassoon inside the browser. Running it locally (in Electron or another wrapper) would indeed offer much better filesystem support, but as openmpt123 is a compiled binary, it would still require the proper binary for each platform. (Of course your completely free to bundle it yourself in Electron)

I think I will implement option 3 first: do the rendering through openmpt123 on the server, then offer a download link to the file when it's done. I'll probably throw in a "convert to mp3" option as well.

Still ... keeping the file in .mod or .xm format makes sense too as this would be a much (much!) smaller file. For example: demomusic.mod is 50kb - rendering it to wav is 50MB - times 1000 ! Of course a game would include it as .mp3, but that still would be a few MB, easily x10 or x20 the file size.

P.S. There's a standalone player component for Bassoon : http://www.stef.be/bassoontracker/player/ and http://www.stef.be/bassoontracker/player/progress.html - quit easy to have .mod and .xm playback in any game, then you could have "subsongs" and Sound FX all together in 1 audio tool. As 30 years of history tells us: tracker music and games are a good combo :-)

blurymind commented 5 years ago

Hey thank you for looking into this :) I need to see which option the main developer of Gdevelop @4ian likes the most and see if we can get it bundled with the IDE. I made a post of GD's issue tracker as well and it looks like people are generally excited about having a tracker inside the ide https://github.com/4ian/GDevelop/issues/689 Gdevelop has a js extension api - so it might be possible to get a mod player working in games by writing an extension that exposes bassoon's player to the engine and the ide.

Using mods in the engine makes a lot of sense indeed-especially when one of our target platforms is mobile, where apk publishing size is limited. This is a very very good point!

blurymind commented 5 years ago

btw this is awesome: http://www.stef.be/bassoontracker/player/progress.html However the volume slider doesn't seem to work. I'm on firefox :)

steffest commented 5 years ago

However the volume slider doesn't seem to work. I'm on firefox :)

Heh ... That's a bug - indeed Firefox specific. It's fixed now. (you might need to hit refresh a few times)

steffest commented 5 years ago

Rendering to .wav and .mp3 is added. Dev version on https://www.stef.be/bassoontracker/dev.html See File -> Save -> select .wav or .mp3

blurymind commented 5 years ago

This is fantastic, but it looks like it relies on internet connection to render. For Gdevelop integration I think we will need to just render the mod file in the game engine to avoid the always online requirement

blurymind commented 5 years ago

It looks like it is possible to compile libopenmpt to javascript via emscripten: https://github.com/deskjet/chiptune2.js https://github.com/Guichaguri/node-chiptune But I am not sure if that would resolve the server requirement

If possible can you see if we can use it in bassoon localy? Here is openmpt compiled to javascript https://github.com/Guichaguri/node-chiptune/blob/master/libopenmpt.js

The export seems to generate very good quality mp3 files

steffest commented 5 years ago

The current render solution does indeed require a internet connection, but in essence it's just an example how to offload the rendering step to another process, as you can't do this properly in the same thread than the one Bassoontracker is running. (it would work for short songs but for larger ones it would lock up the app for too long) - So yes: if you run Bassoon locally you would offload that to another local thread. (being a binary or js based renderer or whatever). Probably someday I will dive into a local version of Bassoon, but for now I would like to keep things inside an online webapp.

blurymind commented 5 years ago

Ok, in that case I guess it would be better to implement a module player in gdevelop.js (the game engine half) - perhaps use bassoon's player. Then once that is working, then work on bundle and embed bassoon with gdevelop5's electron app (the IDE half).

Being able to compress files to wav/mp3 without internet connection requirement via bassoon would have eliminated the need to do the first half (module player in gdevelop.js) - as gdevelop.js can already play mp3/wav files.

For extra features such as fetching resources/examples- the internet connection requirement is ok and is quite cool too. For core features such as game resource creation we absolutely need to be able to do it without the internet requirement.

Sorry I haven't properly looked into this yet. I had to do some work on adding jfxr to gdevelop and now some extra work to add support for saving layers when using piskel in gdevelop.