libvgm icon indicating copy to clipboard operation
libvgm copied to clipboard

Question: how are gains calculated?

Open jprjr opened this issue 3 years ago • 2 comments

Reason I'm asking, I'm working on a small VGM decoder from scratch to better understand the format, and trying to work from the spec.

I noticed that libvgm calculates volumes, like a single-chip SN76489 song will use a gain of 0x200, a dual chip SN76489 will use 0x100 (so no gain) on each chip.

I couldn't find anything in the spec that covers what volumes chips should be at, I see some tables in vgmplayer.cpp, but it looks like there's some kind of calculation going on as well.

Is that documented anywhere? From a preservation perspective, I think it may be good to have a written definition. Or is the gain applied dependent on the emulator core? I see a comment in vgmplayer.cpp about some device structures having modified volume levels.

jprjr avatar Mar 12 '21 13:03 jprjr

It really depends on the cores. We try to equalize the volume of each core with chips with multiple cores. There is no standardization like (max signed value with amplification 0x200 equals absolute maximum chip output), because in many cases we don't even know this info.

superctr avatar Mar 12 '21 15:03 superctr

Yeah, I'm afraid there is neither a consistent rule nor proper documentaton on how the overall gain is calculated.
It is also a huge mess of "tweaking things until it sounds good".

per-chip volume gain:

  • every chip has its own default volume (VGMPlayer::_CHIP_VOLUME) This makes each chip sort of equally loud or ensures a certain common volume balance for certain sound chip combinations. (e.g. PSG vs. FM)
  • single vs. dual: dual usually reduces the "chip volume" of each instance by half, so 1xSN76496 and 2xSN76496 play at the same overall volume when mixed with other chips
  • after this, the VGM volume header is applied to the "chip volume" (can override or modify the chip volume)

global volume gain:

  • at first, all chip volumes are multiplied with VGMPlayer::_PB_VOL_AMNT and summed up With the extra factor I'm trying to give each chip an equal "weight" regarding loudness.
  • The resulting "overall" volume is doubled or halved until it gets into the range [0x181, 0x300].

The VGM header volume gain is applied at a later stage and doesn't effect any of the calculations.

ValleyBell avatar Mar 12 '21 21:03 ValleyBell