General JavaScript VGM player discussion
Technical discussion about the VGM format, and all the software you need to handle VGM files.
Moderator: Staff
- vampirefrog Offline
- Webmaster
- Posts: 1506
- Joined: 2014-01-28, 5:51:54
General JavaScript VGM player discussion
VB edit: Split from [pack] Node.js+Electron VGM player in JavaScript thread
We need an actual web player on the site. Currently the pre-rendered mp3s take up 100GB and I'd like to eliminate that. Someone needs to maintain an emscripten version of vgmplay and fix bugs as they come along.
I don't know what the point of a JS player is. In order to be more convincing, you'd need to benchmark your VGM player and compare it to an emscripten version of vgmplay and see the difference in performance, filesize, accuracy and so on and so forth. In your JS player you also have to implement data block decompression, streams, error handling and who knows what else, besides emulating all the 30+ chips. But the biggest benchmark is that vgmplay exists and works 100% and your JS player is quite behind it. And when new features and chips will be added to vgmplay/libvgm, you'll have to re-translate them into JS, and you'd have to keep up with all the commits. Whereas if you just create a set of build scripts for emscripten, those would be a lot lower maintenance and a lot more useful.
I also remember when someone managed to make a web version of vgmplay, the one I used for project2612. The problem with that is that the guy didn't hang out on the site and we don't know how available he is for bugfixes.
Also, what's the point of using a JS player on the desktop when you already have vgmplay?
If you think a native JS version of, say, one sound chip, would exceed an emscripten compiled version, then perhaps we can make a sort of hybrid build where the JS chip is used alongside all the other chips, which aren't translated to JS yet. Perhaps make the VGM file player core (reading the VGM commands, GD3, header, decompression, streams, error handling) in JS, then import the chips code with emscripten, with the exception of the chips that are translated to JS and give better performance.
To benchmark your code you'd need to do some exaggerated comparisons, such as: creating 100 instances of the chip and measuring memory leakage and CPU time. Running each version of the chip code with the same VGM file for an hour (in rendering time, not CPU time), and measuring the CPU time of each version.
But anyway, for the site we just need a working JS version of vgmplay, and we need it to work, even if it is a bit big or slow.
We need an actual web player on the site. Currently the pre-rendered mp3s take up 100GB and I'd like to eliminate that. Someone needs to maintain an emscripten version of vgmplay and fix bugs as they come along.
I don't know what the point of a JS player is. In order to be more convincing, you'd need to benchmark your VGM player and compare it to an emscripten version of vgmplay and see the difference in performance, filesize, accuracy and so on and so forth. In your JS player you also have to implement data block decompression, streams, error handling and who knows what else, besides emulating all the 30+ chips. But the biggest benchmark is that vgmplay exists and works 100% and your JS player is quite behind it. And when new features and chips will be added to vgmplay/libvgm, you'll have to re-translate them into JS, and you'd have to keep up with all the commits. Whereas if you just create a set of build scripts for emscripten, those would be a lot lower maintenance and a lot more useful.
I also remember when someone managed to make a web version of vgmplay, the one I used for project2612. The problem with that is that the guy didn't hang out on the site and we don't know how available he is for bugfixes.
Also, what's the point of using a JS player on the desktop when you already have vgmplay?
If you think a native JS version of, say, one sound chip, would exceed an emscripten compiled version, then perhaps we can make a sort of hybrid build where the JS chip is used alongside all the other chips, which aren't translated to JS yet. Perhaps make the VGM file player core (reading the VGM commands, GD3, header, decompression, streams, error handling) in JS, then import the chips code with emscripten, with the exception of the chips that are translated to JS and give better performance.
To benchmark your code you'd need to do some exaggerated comparisons, such as: creating 100 instances of the chip and measuring memory leakage and CPU time. Running each version of the chip code with the same VGM file for an hour (in rendering time, not CPU time), and measuring the CPU time of each version.
But anyway, for the site we just need a working JS version of vgmplay, and we need it to work, even if it is a bit big or slow.
Maybe you mean this one? https://www.wothke.ch/webvgm/
On recent Chrome versions this doesn't run as good as it used too. But it ate one core of my CPU completely, now, and with older Chrome versions it was 80% as well. I hope this is a bug or my I5 750 which is getting pretty old, and not the performance loss you get by using Emscripten. Some things converted get the same speed, others will get a huge loss. I think people won't use the webplayer that much if it would eat their core and the fans will start making noise.
Another approach would be to generate the mp3 data live on the server and stream it to the user. Plenty of time for generation considering playback speed. And keep the most played packs in mp3. Of course I have no idea what load it would mean on the particular CPUs in the server(s)....
On recent Chrome versions this doesn't run as good as it used too. But it ate one core of my CPU completely, now, and with older Chrome versions it was 80% as well. I hope this is a bug or my I5 750 which is getting pretty old, and not the performance loss you get by using Emscripten. Some things converted get the same speed, others will get a huge loss. I think people won't use the webplayer that much if it would eat their core and the fans will start making noise.
Another approach would be to generate the mp3 data live on the server and stream it to the user. Plenty of time for generation considering playback speed. And keep the most played packs in mp3. Of course I have no idea what load it would mean on the particular CPUs in the server(s)....
- vampirefrog Offline
- Webmaster
- Posts: 1506
- Joined: 2014-01-28, 5:51:54
Yes, wothke's VGM player is what is used on Project2612.niekniek wrote:Maybe you mean this one? https://www.wothke.ch/webvgm/
On recent Chrome versions this doesn't run as good as it used too. But it ate one core of my CPU completely, now, and with older Chrome versions it was 80% as well. I hope this is a bug or my I5 750 which is getting pretty old, and not the performance loss you get by using Emscripten. Some things converted get the same speed, others will get a huge loss. I think people won't use the webplayer that much if it would eat their core and the fans will start making noise.
Another approach would be to generate the mp3 data live on the server and stream it to the user. Plenty of time for generation considering playback speed. And keep the most played packs in mp3. Of course I have no idea what load it would mean on the particular CPUs in the server(s)....
The performance issue is why we need someone to maintain it and optimize it all the time.
We're already using mp3's generated on the server, that's why it's taking up 100GB currently.
You don't get my point, what I mean is generate the MP3 files on demand, so only the VGM files are hosted. Less diskspace required, more CPU power. As I said, no idea if this is feasible...vampirefrog wrote:We're already using mp3's generated on the server, that's why it's taking up 100GB currently.niekniek wrote: Another approach would be to generate the mp3 data live on the server and stream it to the user. Plenty of time for generation considering playback speed. And keep the most played packs in mp3. Of course I have no idea what load it would mean on the particular CPUs in the server(s)....
- vampirefrog Offline
- Webmaster
- Posts: 1506
- Joined: 2014-01-28, 5:51:54
- vampirefrog Offline
- Webmaster
- Posts: 1506
- Joined: 2014-01-28, 5:51:54
It's a shared server so no.niekniek wrote:You don't get my point, what I mean is generate the MP3 files on demand, so only the VGM files are hosted. Less diskspace required, more CPU power. As I said, no idea if this is feasible...vampirefrog wrote:We're already using mp3's generated on the server, that's why it's taking up 100GB currently.niekniek wrote: Another approach would be to generate the mp3 data live on the server and stream it to the user. Plenty of time for generation considering playback speed. And keep the most played packs in mp3. Of course I have no idea what load it would mean on the particular CPUs in the server(s)....
Actually I would prefer audio data to be generated on the user's machine instead. Whether in real-time or in-memory. vgm2wav then play the result (enjoy doing that with long songs unless someone does a vgm2oggniekniek wrote:Another approach would be to generate the mp3 data live on the server and stream it to the user.
![Razz :P](./images/smilies/icon_razz.gif)
-dj.tuBIG/MaliceX
- vampirefrog Offline
- Webmaster
- Posts: 1506
- Joined: 2014-01-28, 5:51:54
Real-time is the way to go. I believe the most CPU time is taken by more complex chips, such as the FM stuff. Perhaps the real challenge is optimizing the YM chips for JS.
Also, for anyone wondering how memory allocation and garbage collection comes into all this, basically Emscripten allocates a big Uint8Array at the start, which is the Heap, and that remains allocated all the time (until you reload the page). The JS allocator or garbage collector is never used. It is possible to avoid it entirely by this method. It probably has its own allocation code which manages the heap. That is why it has good performance, because it managed to bypass the GC. Either way, the less you use the 'new' operator in JS the better. This is why I said we need actual benchmarks for this. Emscripten code could be even faster than porting the code to JS. I would suggest comparing the existing JS cores that neologix has collected to their emscripten compiled versions by having them render the exact same data. It is also possible to do profiling with Chrome (F12 -> Performance), and you can actually see the GC working.
Also, for anyone wondering how memory allocation and garbage collection comes into all this, basically Emscripten allocates a big Uint8Array at the start, which is the Heap, and that remains allocated all the time (until you reload the page). The JS allocator or garbage collector is never used. It is possible to avoid it entirely by this method. It probably has its own allocation code which manages the heap. That is why it has good performance, because it managed to bypass the GC. Either way, the less you use the 'new' operator in JS the better. This is why I said we need actual benchmarks for this. Emscripten code could be even faster than porting the code to JS. I would suggest comparing the existing JS cores that neologix has collected to their emscripten compiled versions by having them render the exact same data. It is also possible to do profiling with Chrome (F12 -> Performance), and you can actually see the GC working.
Hmm, cross-platform player with a nice Electron UI, media library and album art, or a command line player which I need to compile manually… I know which I’d pickvampirefrog wrote:Also, what's the point of using a JS player on the desktop when you already have vgmplay?
![Wink ;)](./images/smilies/icon_wink.gif)
Telling a friend who’s on MacOS and not so computer savvy to listen to VGMs right now kind of amounts to a no-go, basically.
I'd pick the option that doesn't rape my computer resources. Easy. And especially if you're on a laptop running on battery power.grauw wrote:Hmm, cross-platform player with a nice Electron UI, media library and album art, or a command line player which I need to compile manually… I know which I’d pickvampirefrog wrote:Also, what's the point of using a JS player on the desktop when you already have vgmplay?.
Telling a friend who’s on MacOS and not so computer savvy to listen to VGMs right now kind of amounts to a no-go, basically.
At least with a desktop application you do have the option of offloading the player component to native code, but not so much with a web player. That doesn't still change the fact that Electron itself is a huge waste of resources. Imagine running a separate instance of chrome for every single desktop application you use. That's the future Electron is striving toward.
I wasn't quite expecting the hostility that seems to have shown up in this thread. Interesting response.
I know that there are quite a few more VGM player solutions nowadays than there were back in 2011 when I first started to get serious about a web VGM player in JavaScript and in 2015 when I finally got the YM2612 for it working, and I know that there are at least two other web players, both Emscripten-ed from C or C++ source. What does it hurt having JS versions of VGM chips that don't need to be compiled/transpiled through Emscripten? These chips were ported nearly one-to-one line by line, with very few changes made to accommodate JS as its language and the web as its primary environment, and I've proven that VGM functionality (playback and even non-playback processing) can indeed be done in pure JS in and outside of a web browser without relying on Emscripten or other %LANGUAGE%-to-JS conversion solutions.
I've always treated HTML+CSS+JS development as a rapid prototyping environment. I've already added per-chip volume sliders to the interface (I'm still working on the interface) and I might even get per-channel mute toggles going pretty soon. Considerably less code needs to be added to this project as it is right now to turn it from a player to the JS equivalent of any of the command line tools, and even an updated VGMTool is easier to make using this HTML+CSS+JS combo than my previous stalled attempt at v3, mainly due to stability in making the interface.
I'm no stranger to the requirements of low-powered or small screen environments like laptops, tablets, and smartphones; I'm always working on mobile or laptop for something, so I become acutely aware of when performance becomes an issue. Electron is just a temporary means to an end for this project and I'm not married to it; I could have just as easily uses PhantomJS instead. Also, all work on the cores here also benefits not only my web player but also any potential web projects that would like to make use of VGM audio on a chip-by-chip basis. For example, with some work devs can come up with JS VGM trackers that only cater to reduced sets of chips (a CPS-1 tracker with only YM2151 and OKIM6295, a Genesis/Mega Drive tracker like VGM MM with YM2612/YM3438 and SN76489, a QSound tracker, etc). People can take the scripts and make their own interfaces instead of my Electron-based desktop UI or my jQuery-based web UI. People can integrate individual cores to power the retro audio of their webapps; for example, I myself have taken the YM2612 JS and given it a VST-like wrapper, allowing people to control the synth on a web page with a VST-like API.
The most important result of porting these cores to JS by hand is that not only do they exist, but that they're also as readable, and therefore maintainable, as the original code, if not more so, and don't require external transpiler solutions to generate. I even put off using anything Node.js as long as possible given that the Node community is full of code snobs who insist on using HAML or CoffeeScript or Grunt or the workflow du jour to make something that can easily be written in plain JS, a server side language like Python or PHP whose development isn't driven by hipsters and can be run on pretty much any server setup, etc, and that up until this point every single line of code I wrote for those cores was usable with maybe 4 or 5 lines of boilerplate wrapper in every single JS environment possible, even if the output isn't audio. While I myself did not benchmark any of it against the original VGMPlay, I have in the past asked for others more capable than myself to benchmark it against not only VGMPlay but also MAME's own Emscripten-ed code (what the Internet Archive uses) with no interested responses from anyone with the skill to do so.
I did not expect to have to justify the existence of a VGM player written in JavaScript in 2017. The main advantage of dynamically generating the audio client-side instead of rendering a full audio file server-side and playing that is obvious. While SMS Power user BlackAura may have been the first to write a web VGM player in JS, I took his SN76489-only work and made the first real VGM v1.50-compatible web player in 2015, something that didn't even exist for the decade before it since 1.50 was first finalized. Nobody accomplished that before me, not in Flash and not in Java. I did not expect to have to justify the existence of any VGM player in 2017. Though VGMPlay and in_vgm are currently the reference implementations of VGM playback, maybe people want different interfaces with different levels of control, and the current offerings may not necessarily provide that control.
I never intended for any of my JS VGM work to be the most performant of JS VGM offerings, but at least it's something. I never intended for my JS VGM player to be the de facto desktop VGM player, but at least it's something. Yes, VGM as a format has grown beyond three Sega chips and a Capcom chip, and so too will VGM in JS, and I have a gut feeling we won't be using Emscripten or other semi-automated conversion solutions to make that happen. As it stands right now, all one needs to do is strip the Node.js wrappings from my code and SMS Power can easily have an on-site JS player that only needs and uses SN76489 and YM2413, and Project 2612 can have an on-site JS player that only needs and uses YM2612, SN76489, and Sega PCM. VGMRips can easily use my player for chips that are complete and keep the existing solution as the player for VGMs with incomplete or missing chips while they're written on a chip-by-chip basis (I'm not saying mix players, I'm saying if the code detects a missing chip then use the server-side render for the entire song, else use the client-side solution). Will this be the official solution, only time will tell.
I can see why that Yarm guy decided to take his VGM2OPM project down a few months ago, but unlike him I actually have real investment in this, emotionally and physically. I want to see VGMRips succeed, thriving and expanding. As the largest curated host of sequenced video game audio, VGMRips has achieved success in this regard. I want to see the VGM format succeed, thriving and expanding. As the de facto file format for dozens of different retro video game audio chips, VGM has achieved success in this regard. As a community that promotes furthering either, however, both have failed. VGM as a format stagnated at 1.50 for years, being limited to SMS Power and Project 2612, and it took ValleyBell and eventually myself to revitalize public interest in the format once (Dega) Dave, Maxim, and Bock went hands off. Only then did Oerg866, Tom/nineko, and eventually vampirefrog come along to get VGMRips going and actually provide a location where VGM expansion could flourish, but even now people still go to YouTube or KHInsider or FFShrine to listen to retro video game music.
I put in a lot of work to understand the SN76489 and the YM2612 since 2005; granted I was mostly reading other people's research, but I had also made real attempts to apply that research usefully. I put in a lot of work since then to not only read the code that makes up VGMPlay/libvgm, most of it borrowed from MAME, but also to understand it at least enough to port it to any other language, let alone JavaScript, by hand. The fact that I can do so at all means it's possible, whether I optimize MAME's style or not. If somebody wants it to be performant, great! Feel free to volunteer to help me in that endeavor; it's on GitHub, so it's as simple as making a pull request, or one can even email me code and I'll try to integrate it properly myself. But don't anyone here fucking dare try to discourage me or anyone else from attempting to develop something useful to the VGM format or the community, native or not, performant or not, VGMPlay-based or not. I can't believe that has to be explicitly said or written here for any reason.
I know that there are quite a few more VGM player solutions nowadays than there were back in 2011 when I first started to get serious about a web VGM player in JavaScript and in 2015 when I finally got the YM2612 for it working, and I know that there are at least two other web players, both Emscripten-ed from C or C++ source. What does it hurt having JS versions of VGM chips that don't need to be compiled/transpiled through Emscripten? These chips were ported nearly one-to-one line by line, with very few changes made to accommodate JS as its language and the web as its primary environment, and I've proven that VGM functionality (playback and even non-playback processing) can indeed be done in pure JS in and outside of a web browser without relying on Emscripten or other %LANGUAGE%-to-JS conversion solutions.
I've always treated HTML+CSS+JS development as a rapid prototyping environment. I've already added per-chip volume sliders to the interface (I'm still working on the interface) and I might even get per-channel mute toggles going pretty soon. Considerably less code needs to be added to this project as it is right now to turn it from a player to the JS equivalent of any of the command line tools, and even an updated VGMTool is easier to make using this HTML+CSS+JS combo than my previous stalled attempt at v3, mainly due to stability in making the interface.
I'm no stranger to the requirements of low-powered or small screen environments like laptops, tablets, and smartphones; I'm always working on mobile or laptop for something, so I become acutely aware of when performance becomes an issue. Electron is just a temporary means to an end for this project and I'm not married to it; I could have just as easily uses PhantomJS instead. Also, all work on the cores here also benefits not only my web player but also any potential web projects that would like to make use of VGM audio on a chip-by-chip basis. For example, with some work devs can come up with JS VGM trackers that only cater to reduced sets of chips (a CPS-1 tracker with only YM2151 and OKIM6295, a Genesis/Mega Drive tracker like VGM MM with YM2612/YM3438 and SN76489, a QSound tracker, etc). People can take the scripts and make their own interfaces instead of my Electron-based desktop UI or my jQuery-based web UI. People can integrate individual cores to power the retro audio of their webapps; for example, I myself have taken the YM2612 JS and given it a VST-like wrapper, allowing people to control the synth on a web page with a VST-like API.
The most important result of porting these cores to JS by hand is that not only do they exist, but that they're also as readable, and therefore maintainable, as the original code, if not more so, and don't require external transpiler solutions to generate. I even put off using anything Node.js as long as possible given that the Node community is full of code snobs who insist on using HAML or CoffeeScript or Grunt or the workflow du jour to make something that can easily be written in plain JS, a server side language like Python or PHP whose development isn't driven by hipsters and can be run on pretty much any server setup, etc, and that up until this point every single line of code I wrote for those cores was usable with maybe 4 or 5 lines of boilerplate wrapper in every single JS environment possible, even if the output isn't audio. While I myself did not benchmark any of it against the original VGMPlay, I have in the past asked for others more capable than myself to benchmark it against not only VGMPlay but also MAME's own Emscripten-ed code (what the Internet Archive uses) with no interested responses from anyone with the skill to do so.
I did not expect to have to justify the existence of a VGM player written in JavaScript in 2017. The main advantage of dynamically generating the audio client-side instead of rendering a full audio file server-side and playing that is obvious. While SMS Power user BlackAura may have been the first to write a web VGM player in JS, I took his SN76489-only work and made the first real VGM v1.50-compatible web player in 2015, something that didn't even exist for the decade before it since 1.50 was first finalized. Nobody accomplished that before me, not in Flash and not in Java. I did not expect to have to justify the existence of any VGM player in 2017. Though VGMPlay and in_vgm are currently the reference implementations of VGM playback, maybe people want different interfaces with different levels of control, and the current offerings may not necessarily provide that control.
I never intended for any of my JS VGM work to be the most performant of JS VGM offerings, but at least it's something. I never intended for my JS VGM player to be the de facto desktop VGM player, but at least it's something. Yes, VGM as a format has grown beyond three Sega chips and a Capcom chip, and so too will VGM in JS, and I have a gut feeling we won't be using Emscripten or other semi-automated conversion solutions to make that happen. As it stands right now, all one needs to do is strip the Node.js wrappings from my code and SMS Power can easily have an on-site JS player that only needs and uses SN76489 and YM2413, and Project 2612 can have an on-site JS player that only needs and uses YM2612, SN76489, and Sega PCM. VGMRips can easily use my player for chips that are complete and keep the existing solution as the player for VGMs with incomplete or missing chips while they're written on a chip-by-chip basis (I'm not saying mix players, I'm saying if the code detects a missing chip then use the server-side render for the entire song, else use the client-side solution). Will this be the official solution, only time will tell.
I can see why that Yarm guy decided to take his VGM2OPM project down a few months ago, but unlike him I actually have real investment in this, emotionally and physically. I want to see VGMRips succeed, thriving and expanding. As the largest curated host of sequenced video game audio, VGMRips has achieved success in this regard. I want to see the VGM format succeed, thriving and expanding. As the de facto file format for dozens of different retro video game audio chips, VGM has achieved success in this regard. As a community that promotes furthering either, however, both have failed. VGM as a format stagnated at 1.50 for years, being limited to SMS Power and Project 2612, and it took ValleyBell and eventually myself to revitalize public interest in the format once (Dega) Dave, Maxim, and Bock went hands off. Only then did Oerg866, Tom/nineko, and eventually vampirefrog come along to get VGMRips going and actually provide a location where VGM expansion could flourish, but even now people still go to YouTube or KHInsider or FFShrine to listen to retro video game music.
I put in a lot of work to understand the SN76489 and the YM2612 since 2005; granted I was mostly reading other people's research, but I had also made real attempts to apply that research usefully. I put in a lot of work since then to not only read the code that makes up VGMPlay/libvgm, most of it borrowed from MAME, but also to understand it at least enough to port it to any other language, let alone JavaScript, by hand. The fact that I can do so at all means it's possible, whether I optimize MAME's style or not. If somebody wants it to be performant, great! Feel free to volunteer to help me in that endeavor; it's on GitHub, so it's as simple as making a pull request, or one can even email me code and I'll try to integrate it properly myself. But don't anyone here fucking dare try to discourage me or anyone else from attempting to develop something useful to the VGM format or the community, native or not, performant or not, VGMPlay-based or not. I can't believe that has to be explicitly said or written here for any reason.
Yeah it's crazy how much has changed over the years in terms of offerings and alternatives, and just from the mere fact that people have gone ahead and spent some time to adapt existing stuff to work on the web. I think the issue is vampi derailed the topic with a viewpoint on usefulness cause he's got an agenda lol (good on ya "site admin"). I probably would try to ignore all the passive-aggressive "hurr durr what's the point" tone and just get on with the program, as I'm sure you've been around for a lot longer here. ![Smile :)](./images/smilies/icon_smile.gif)
![Smile :)](./images/smilies/icon_smile.gif)
-dj.tuBIG/MaliceX
- vampirefrog Offline
- Webmaster
- Posts: 1506
- Joined: 2014-01-28, 5:51:54
I don't want to discredit you for doing something in your free time, it's entirely up to you. Personally I think JS is a bad choice for writing desktop applications, and in fact browser applications too. JS works for the 'lighter' stuff but wasm exists for a reason, to replace JS for any heavy duty stuff which I would consider VGM audio playback to be. Doesn't stop you from doing what you want, and I encourage you to do so. Maybe you'll make me eat my words in time...neologix wrote:snip
Maybe replacing the MP3 files with Opus would be a better choice now that iOS 11 finally supports it. It would allow you to cut the bitrate in half and still keep the existing quality of the MP3 files, or even improve it.vampirefrog wrote:snip
Regarding multi platform support, it is a little bit annoying that there is no well adapted multi platform sound codec API. There is Gstreamer which is still a little bit Linux and especially GNOME-centered. I think it would still be a good idea to write a GStreamer plugin for VGM playback though.