Skip to content

Suggestions to better the .vgm format

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

Moderator: Staff

  • User avatar
  • Delek Offline
  • Posts: 41
  • Joined: 2012-05-05, 16:39:51

Suggestions to better the .vgm format

Post by Delek »

I was trying to sleep and something crazy came into my mind: what about adding "progressive" register changes in the .vgm format? :D

I mean, if you see this in a .vgm dump:
* channel 1 freq: 300
wait
* channel 1 freq: 302
wait
* channel 1 freq: 304
wait
* channel 1 freq: 306
wait
* another stuff

We all know that it can be packed like:
* channel 1 freq: 300 : progressive value 2 : 4 waits

Where "channel 1 freq" is register 0xA0 for example.

This is, maybe, not very suitable for apps that DUMP music (maybe vgm_cmp could add support for this) but I can see a HUGE improvement for apps that CREATE music to be exported in the .vgm format.

I imagine the specs to be like this:
0x52 0xA4 dd : we write the start point, for example, a frequency in YM2612 MSB
0x52 0xA0 dd : we write the start point, for example, a frequency in YM2612 LSB
0xE1 pp pp ww ww : PROGRESSIVE COMMAND -> pp = incremental value (most significant bit is the sign) , ww = waits count
0x62 <- the first wait and the one that will be used repeatedly for the command above (0x61 nn nn, 0x62, 0x63)

* Keep in mind that this is backward compatible, an app that doesn't support this will jump the incremental changes but will write the start point of the change and wait a single frame.


So, if we found:
0x52 0xA4 0x00
0x52 0xA0 0x20
0xE1 0x00 0x02 0x00 0x09
0x63


Will be unpacked to:
0x52 0xA4 0x00
0x52 0xA0 0x20
0x63
0x52 0xA4 0x00
0x52 0xA0 0x22
0x63
0x52 0xA4 0x00
0x52 0xA0 0x24
0x63
0x52 0xA4 0x00
0x52 0xA0 0x26
0x63
0x52 0xA4 0x00
0x52 0xA0 0x28
0x63
0x52 0xA4 0x00
0x52 0xA0 0x2A
0x63
0x52 0xA4 0x00
0x52 0xA0 0x2C
0x63
0x52 0xA4 0x00
0x52 0xA0 0x2E
0x63
0x52 0xA4 0x00
0x52 0xA0 0x30



PS1: I know that after adding .vgz (zlib) in the .vgm format the filesize is no more an issue, but there are lot of people playing back .vgm files in the real hardware fighting with rom filesize (including myself :lol: ) where unzipping on the fly is obviously not an option.
PS2: This woun't open the door to a world of really ultra small files and better support for music apps? I see this like the second part of the DAC STREAM support, first there was a bunch of register writes all over the place and some years after we've got the awesome streams to optimize the PCM filesizes a lot.
  • ctr Offline
  • Posts: 492
  • Joined: 2013-07-17, 23:32:39

Post by ctr »

Implementing something like this would be a mess because the parser would have to know exactly how each register work. And as you said, it would be only useful for rips. I think when creating music, the best way to replay songs on real hardware and keep file sizes down is to just write a sound driver, like Famitracker's NSF driver.
  • User avatar
  • Delek Offline
  • Posts: 41
  • Joined: 2012-05-05, 16:39:51

Post by Delek »

ctr wrote:Implementing something like this would be a mess because the parser would have to know exactly how each register work
EDIT:
Partially.
As I said in the OP, you will only set:
1) register number
2) start point
3) incremental value
4) waits count
5) wait value

No more is needed, no register knowledge, no system information, only predefined numbers. Maybe for systems that share the same register with the octave (like YM2612) you will need a special knowledge.
But this is simpler to implement than DAC Streaming isn't? :D

We should do some test, but it looks that it will be very surprising how much kbs you will save with something like this on dumps (if you look closely there's a lot of incremental stuff happening between short waits, the ones that actually are eating the most filesize) and, of course, in chiptune DAWs.
  • User avatar
  • ValleyBell Offline
  • Posts: 4768
  • Joined: 2011-12-01, 20:20:07
  • Location: Germany

Post by ValleyBell »

Unlike the DAC stream features, this would affect timing, so it would need larger modifications of the parser. And this alone is, IMO, not a good thing.

Also, in practise it would have barely any benefits because:
  1. There is usually more than 1 channel running. What do you do when you need it for two channels?
  2. You would need to interrupt the effect for *anything* - e.g. Key On/Off on other channels.
  3. For dumps there would be no improvement at all because [see 1.] and because the delays have rounding errors and would be e.g. 425, 425, 425, 426, 425, 425, 426, 425, ...
  4. Especially the way you described it (with looking back and looking ahead) is VERY messy. How do you know whether you need only the last register write OR the last 2 writes OR maybe even the last 3 writes?
If you still think your idea is good, then feel free to do some tests on your own and show us the results.

btw: The parser doesn't know anything about registers - at all. In fact, it doesn't even know whether a command with 3 parameters is "16-bit register + 8-bit data" (e.g. YMF278B) or "8-bit register + 16-bit data" (e.g. QSound).
  • User avatar
  • Delek Offline
  • Posts: 41
  • Joined: 2012-05-05, 16:39:51

Post by Delek »

Yep, you're quite right. The main issue with my proposal is that the vgm stream runs in one unique line with mixed commands between channels.

Another question, do you can gain filesize if you separate, for example, a Genesis track in 6 different vgm files, one for each channel, to apply vgm_cmp in each one of these? The thing is, the size of those 6 files will be less than the normal .vgm?
  • User avatar
  • ValleyBell Offline
  • Posts: 4768
  • Joined: 2011-12-01, 20:20:07
  • Location: Germany

Post by ValleyBell »

If you split into 1 VGM per channel, run vgm_cmp and then merge them into a single VGM again, the file size would be exactly the same as if you would vgm_cmp the original VGM.
  • User avatar
  • Delek Offline
  • Posts: 41
  • Joined: 2012-05-05, 16:39:51

Post by Delek »

ValleyBell wrote:If you split into 1 VGM per channel, run vgm_cmp and then merge them into a single VGM again, the file size would be exactly the same as if you would vgm_cmp the original VGM.
Without merging I mean, I'm imagining an in_vgm that plays multiple .vgm at the same time, 1 per channel (it is actually n instances of in_vgm playing really simple files).
  • User avatar
  • ValleyBell Offline
  • Posts: 4768
  • Joined: 2011-12-01, 20:20:07
  • Location: Germany

Post by ValleyBell »

You could maybe save a few bytes with recorded VGMs due to micro-delays, but for generated VGMs that don't have those, it should require more bytes, because you need each delay for every of the 6 channels.
Additionally, you need to add the bytes required for VGM header + GD3 tag that would be present in each of the VGMs.
(Right now there is no way to quickly test it, btw. vgm_ptch can only strip single channels from SN76489, SegaPCM, RF5C64/RF5C168 and C140.)

tl;dr: no size improvement
Post Reply