Skip to content

VGM web player preview

Screenshot(s) of the next update!

Technical discussion about the VGM format, and all the software you need to handle VGM files.

Moderator: Staff

  • User avatar
  • neologix Offline
  • Posts: 211
  • Joined: 2012-04-22, 4:03:45
  • Location: New York, NY, USA

VGM web player preview

Post by neologix »

I haven't worked on fixing the YM2612 code in a while, but I did feel the player itself could look a hell of a lot better than it does now so I cleaned it up.

Image

It's also responsive!

Image

I'll upload the update as soon as it's finished

Post by vampirefrog »

Consider a native C version, since it's easier to just do some modifications to the vgmplay code.

As you may know, the classic API for writing browser plugins is NPAPI. However, the Chrome team stated that it has deprecated NPAPI and it will phase it out in April 2014. Therefore there are several new methods of running compiled code.

For chrome, there is NaCl (Native Client):

https://developers.google.com/native-client/dev/

https://developers.google.com/native-cl ... rial-part1

For firefox, there is NPAPI and js-ctypes https://developer.mozilla.org/en-US/doc ... /js-ctypes

Post by vampirefrog »

However, having looked at js-ctypes, I am starting to think that today is not a good day to write C plugins. Perhaps at some point there will be a cross-browser way of doing that, but not today.

That being said, what I think we need at this point is some sort of meta-code that would compile into C and JS, just so we can keep the chip emulation code in one place. I am talking about writing the sound chip code once, then generating the C files that vgmplay would use, and the JS files that your web player would use. Let's talk to ValleyBell about this.

There is also emscripten, which could speed this up greatly https://github.com/kripken/emscripten/wiki

But I think either way, VB would still need to separate vgmplay into a few components such as the chip library, the VGM parsing library and the command-line program. I dunno, to tell you the truth, I haven't looked at vgmplay source yet.
  • User avatar
  • neologix Offline
  • Posts: 211
  • Joined: 2012-04-22, 4:03:45
  • Location: New York, NY, USA

Post by neologix »

vampirefrog wrote:I dunno, to tell you the truth, I haven't looked at vgmplay source yet.
Oh, it's a doozy. VB kinda pulls a MAME on this program (in fact, many of the chips are from MAME/MESS) and has some glue code for the multimedia interfacing. The VGM processing code itself I'd prefer be cleaned up.

Yeah, you'll want to clear your afternoon for the first time you attempt a real deep-dive into that code. This is one of the reasons I'm doing native JS chip-by-chip instead of converting and the main reason I hate looking at Internet Archive's converted MESS scripts for Mega Drive.

Post by vampirefrog »

My suggestion is to try to convince ValleyBell to begin the rewrite of the vgmplay code, cleanly, in C, then use emscripten to convert the result. I've also urged him to separate the code into a couple of libraries (VGM file parser + player code) that could be reused for various tasks, the first of which being vgmplay, and the second being the web player.

In the meanwhile I've implemented a web player that uses a server-side script to convert from vgm/vgz to wav and then to ogg. The files are cached, so performance is decent, but the cache takes space on the server side, which can be avoided if there is a web vgm player.

Here is an example: http://vgm.mdscene.net/rip.php?pack=449

You can browse and listen to practically any pack here http://vgm.mdscene.net/rip.php

This is implemented with a php script that generates an ogg file from a wav file generated by vgmplay. It eats up server-side CPU power, server-side space (I'm caching the oggs, only generating once) and bandwidth (the ogg file is much larger than the original vgm or vgz file).

Hopefully this is a feature people will enjoy.
  • User avatar
  • MaliceX Offline
  • Posts: 226
  • Joined: 2012-09-29, 11:45:48
  • Location: Australia
  • Contact:

Post by MaliceX »

This is pretty good! I suppose you have more than enough hdd space and bandwidth to support such a feature. :P Thanks.
-dj.tuBIG/MaliceX

Post by vampirefrog »

For now it's ok, but I prefer the javascript vgm player, to reduce server cpu + bandwidth + hdd usage.
  • User avatar
  • blitzlunar Offline
  • Posts: 126
  • Joined: 2012-12-21, 15:30:24
  • Location: UK

Post by blitzlunar »

Very interesting. I'm a fb2k user and encounter a lot of sets which don't play accurately (or don't play at all), so this should serve very useful.
  • User avatar
  • neologix Offline
  • Posts: 211
  • Joined: 2012-04-22, 4:03:45
  • Location: New York, NY, USA

Post by neologix »

UPDATE!!!

I've implemented the visual refresh of my all-JavaScript web VGM player!

http://www.luxatom.com/VgmPlayer/

There may be a visual bug or two to stomp out, especially regarding its responsive/mobile behavior and the playlist; for example, I just found that I don't highlight the currently loaded song or album when the album list or songlist is expanded on smallest view.

Visual Updates
  • Responsive! Reflows itself for different browser widths and better overall layout on smartphone and tablet
  • Color scheme is muted blues for now until I can work out styling the player settings
Playback Updates
  • Working play/pause button :)
  • Removed YM2612 until I can fix it
  • Player code is cleaner and more flexible
Now that the visual refresh is online, I can work on fixing my JS YM2612 core. A reduced todo list is on the bottom of the page, though the style for "crossed off item" seems to have been lost in the transition. :/

It is now also easier to pack and distribute independent of my own site's code, though its functionality is still currently heavily tied to jQuery and XAudioJS.
  • User avatar
  • neologix Offline
  • Posts: 211
  • Joined: 2012-04-22, 4:03:45
  • Location: New York, NY, USA

Post by neologix »

Possible future idea: staff roll via VexFlow, piano roll via whatever vampirefrog comes up with for the packs player.

Post by vampirefrog »

After struggling with the WebAudio API and seeing how crappy support is currently (Firefox kinda works, but Chrome has not worked properly for me, no IE support), and looking at your project, it seems the best back-end is indeed one of sink.js or XAudioJS. However, I'm not sure how good an idea is to port chips to javascript by hand, so using emscripten is a more practical choice for a full VGM player at this point.

There are a couple of paths to go: Take VGMPlay apart and separate the playing code into a library, which would provide a couple of init functions and a fillBuffer function, and have that converted with emscripten, OR writing part of the code in JS and just using the chips code converted with emscripten. This might reduce the size. It's still a big and unwieldy project at this point... Of course, the best thing would be to have everything written in JS, but I think the good compromise is to write the vgm file reading part in JS and have the chips just translated.

Also, I've noticed you want to add decompress(). Is that for vgz files? In the particular setup of the packs project, that won't be needed, since we'll be sending the vgm data uncompressed, but the http request itself can be gzipped. We can just do that from php no problems. I am also thinking of storing the vgm data in the database, so the server can respond with a JSON with all the meta-data, and another response with just the vgm stream data (which means we can even begin to play before loading is finished btw).

Cheers!

Post by vampirefrog »

After taking a look at the chip emulation code, I realize it is not so hard to rewrite the chips in JS. YM2151 and YM2612 seem a couple of the more complex chips.

So, it looks like you're on the good path with the way you've written things so far. If you choose to focus on vgmrips, I suggest you begin with the most used chips (http://vgm.mdscene.net/packs/chips - as you can see they're ordered from most packs to least packs) - NES APU, YM2151, AY8910 and HuC6280. That way you will have big coverage. If we cover the first 6 chips, we'll have over 800 packs covered out of ~1.1K. Not bad. We can then implement your player on the packs page selectively - where the player can emulate all the chips in the pack, use it, and when it can't, we just use the ogg player. As you can see, there are 32 chips, so hopefully I can help with a few, maybe the simpler ones like AY8910.

As far as the chip code goes, I suggest you pick a standard interface and stick to it for all the chips, such as having a couple of standard methods for the chip classes. Just an example:

Code: Select all

function YM2151(clockRate, sampleRate) {
    this.reset = function() { ... };
    // use an Int16Array for buf
    // https://developer.mozilla.org/en-US/docs/Web/API/Int16Array
    this.update = function(buf, length) { ... }
    this.writeReg(reg, value) { ... }
    this.setMutemask(mask) { ... }
}

/* You may also wish to add some extra functionality, like a note callback */
var ym2151 = new YM2151(4000000, 44100);
ym2151.onNoteOn = function(note, channel) { ... }
ym2151.onNoteOff = function(note, channel) { ... }
Also, as a bug report, the player does not work on chrome, and I'm using latest stable chrome. It works on firefox. What I've found is that the chrome web audio api has a bug in which onaudioprocess() does not get called for a ScriptProcessor node. What you can do is force the backend to flash for chrome, and add an option to choose/force the backend in the UI.

Cheers!

Post by vampirefrog »

vampirefrog wrote:After taking a look at the chip emulation code, I realize it is not so hard to rewrite the chips in JS. YM2151 and YM2612 seem a couple of the more complex chips.

So, it looks like you're on the good path with the way you've written things so far. If you choose to focus on vgmrips, I suggest you begin with the most used chips (http://vgm.mdscene.net/packs/chips - as you can see they're ordered from most packs to least packs) - NES APU, YM2151, AY8910 and HuC6280. That way you will have big coverage. If we cover the first 6 chips, we'll have over 800 packs covered out of ~1.1K. Not bad. We can then implement your player on the packs page selectively - where the player can emulate all the chips in the pack, use it, and when it can't, we just use the ogg player. As you can see, there are 32 chips, so hopefully I can help with a few, maybe the simpler ones like AY8910.

As far as the chip code goes, I suggest you pick a standard interface and stick to it for all the chips, such as having a couple of standard methods for the chip classes. Just an example:

Code: Select all

function YM2151(clockRate, sampleRate) {
    this.reset = function() { ... };
    // use an Int16Array for buf
    // https://developer.mozilla.org/en-US/docs/Web/API/Int16Array
    this.update = function(buf, length) { ... }
    this.writeReg(reg, value) { ... }
    this.setMutemask(mask) { ... }
}

/* You may also wish to add some extra functionality, like a note callback */
var ym2151 = new YM2151(4000000, 44100);
ym2151.onNoteOn = function(note, channel) { ... }
ym2151.onNoteOff = function(note, channel) { ... }
Also, as a bug report, the player does not work on chrome, and I'm using latest stable chrome. It works on firefox. What I've found is that the chrome web audio api has a bug in which onaudioprocess() does not get called for a ScriptProcessor node. What you can do is force the backend to flash for chrome, and add an option to choose/force the backend in the UI.

Also, the sound is very skippy on IE unfortunately :(

Cheers!

Post by vampirefrog »

It has also occurred to me that if we write the chip code carefully, it might work in ActionScript as well, so we can have the playing part directly in flash, where we might get better results with the playback, and we can just use the UI in javascript and just send control signals to the flash app. Later, when the WebAudio API stabilizes (or when we're on firefox, where it seems to work fine), we just serve the plain JS. But otherwise, serve the flash app and have a JS interface to it. As we've seen, all the chip emulation web players use flash one way or another.
  • User avatar
  • neologix Offline
  • Posts: 211
  • Joined: 2012-04-22, 4:03:45
  • Location: New York, NY, USA

Post by neologix »

vampirefrog wrote:After struggling with the WebAudio API and seeing how crappy support is currently (Firefox kinda works, but Chrome has not worked properly for me, no IE support), and looking at your project, it seems the best back-end is indeed one of sink.js or XAudioJS.
Chrome 34.0.1847.131m has some jittery sound for me, but that's partly due to the window not being focused combined with my crappy connection. I don't currently have Firefox on my dev machine, but I might put it back eventually.
vampirefrog wrote:I'm not sure how good an idea is to port chips to javascript by hand, so using emscripten is a more practical choice for a full VGM player at this point.
If it works, fantastic!

Personally, I want to have hand-editable files for easier future maintenance, which is one of the reasons I don't use a build system like grunt or something to combine everything into one large file. There previously wasn't decoupled audio cores in JavaScript form, hence me writing them from scratch.
vampirefrog wrote:Also, I've noticed you want to add decompress(). Is that for vgz files? In the particular setup of the packs project, that won't be needed, since we'll be sending the vgm data uncompressed, but the http request itself can be gzipped. We can just do that from php no problems.
Yes, for VGZ processing. I'm building this for SMSPower to use as well (which they technically can if they don't care about YM2413 playback yet) and eventually Project2612, so it needs to be able to load a pre-existing VGM file (compressed or uncompressed) from the same domain (uses AJAX, so subject to cross-origin restrictions by default) and play it all client-side without being dependent on anything special (all the dependencies like jQuery are front-end deps). SMSPower hosts all their soundtracks and in zip format, so that's also a bonus (don't yet know of a client-side 7z parser for the vgm7z packs, though; that would be server-side :/ ).
vampirefrog wrote:So, it looks like you're on the good path with the way you've written things so far. If you choose to focus on vgmrips, I suggest you begin with the most used chips ... - NES APU, YM2151, AY8910 and HuC6280. That way you will have big coverage. If we cover the first 6 chips, we'll have over 800 packs covered out of ~1.1K.
Once I finish v1.50 parity (PSG, YM2413, YM2612, YM2151), then I'll focus on vgmrips-popular chips first, yes.
vampirefrog wrote:Also, as a bug report, the player does not work on chrome, and I'm using latest stable chrome. It works on firefox. What I've found is that the chrome web audio api has a bug in which onaudioprocess() does not get called for a ScriptProcessor node. What you can do is force the backend to flash for chrome, and add an option to choose/force the backend in the UI.

Also, the sound is very skippy on IE unfortunately :(
IE likely uses the Flash fallback that XAudioJS provides. Once I do the cleanup rewrite and increase buffer sizes that might be resolved. Increasing the buffers sizes might resolve the Chrome issue as well, though I'm actually getting playback on mine.
vampirefrog wrote:It has also occurred to me that if we write the chip code carefully, it might work in ActionScript as well, so we can have the playing part directly in flash, where we might get better results with the playback, and we can just use the UI in javascript and just send control signals to the flash app. Later, when the WebAudio API stabilizes (or when we're on firefox, where it seems to work fine), we just serve the plain JS. But otherwise, serve the flash app and have a JS interface to it. As we've seen, all the chip emulation web players use flash one way or another.
I'm not touching Flash. Anyone else wants to port my code to ActionScript, be my guest, but I'm not going to be the person to do it.
Post Reply