Skip to content

VGM file format timing issue

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

Moderator: Staff

VGM file format timing issue

Post by ClassicOldSong »

I'm creating an USB OPL3 hardware player which could be used to play VGM files now and could be used for music production or use as a sound card for DOSBox in the future. Prototype works pretty fine except for one problem: VGM playback speed is slightly faster compared to recordings on this site.

What I'm doing now is processing the VGM file on computer, sending the commands to the OPL3, calculate all the time spent on sending that data(Tdata) before a sleep command, and at a sleep command(Tsleep) I sleep for (Tsleep - Tdata). When listening directly it doesn't seems to be causing much problem, rhythm and tempo seems to be correct, but comparing the recorded file to a previously recorded one on this site shows it's actually a little bit fast. Is there anything wrong with my processing or there're other issues involved?

Thanks in advance for any generous help!

Video:

https://youtu.be/MI8EEHc744Y

Post by vampirefrog »

perhaps due to clock drift between the audio interface clock and the system clock, which I assume you're using to time the sending of VGM commands to the OPL3?
  • ctr Offline
  • Posts: 492
  • Joined: 2013-07-17, 23:32:39

Post by ctr »

ClassicOldSong wrote:Is there anything wrong with my processing or there're other issues involved?
most likely it's the former. be aware of rounding / precision errors. I think generally it might be a good idea to accumulate delays and process the writes in batches (for example every X millisecond, where you can use a hardware timer set to that exact period).

FM chips are slow so don't be alarmed if you end up taking more than one VGM tick to process all the writes.

Post by ClassicOldSong »

perhaps due to clock drift between the audio interface clock and the system clock
In this configuration playback speed should be completely controlled by CPU. This prototype uses GPIO for command transferring, since commands were sent directly by CPU, the CPU clock itself is the audio interface clock.
I think generally it might be a good idea to accumulate delays and process the writes in batches
That's exactly what I'm doing, except for that I took the time for commanding away from sleeps, otherwise it could be too slow or inconsistent.
  • User avatar
  • ValleyBell Offline
  • Posts: 4768
  • Joined: 2011-12-01, 20:20:07
  • Location: Germany

Post by ValleyBell »

In general, VGM timing assumed that the action of "sending a command" takes 0 time.
Only "wait" commands cause the time to advance. You need to be aware of that concept.

Thus, when sending a command takes some real time, you need to subtract that time from the next delay.
When I write timing code, I usually have a timestamp for "time of the next command", which is increased whenever there is a "wait" command.
And when I'm sleeping, I always wait until that timestamp is reached. (If the real time is already past it, then of course there is no wait.)

Post by ClassicOldSong »

When I write timing code, I usually have a timestamp for "time of the next command", which is increased whenever there is a "wait" command.
Interesting, it seems that we are doing the very same. But I'm still getting slightly faster. Probably it's the rounding issue. I saved 1/44100 in double and multiply it each time a wait command comes in. Probably should divide it each time instead of multiply it.
Last edited by ClassicOldSong on 2021-04-04, 22:52:08, edited 1 time in total.

Post by ClassicOldSong »

Not at my computer rn so tried on my phone:

Code: Select all

#include <iostream>
#include <cstdint>
using namespace std;

int main()
{
	double aaa = 1.0 / 44100;
	uint32_t bbb = aaa * 0xffffffff;
	uint32_t ccc = 0xffffffff / 44100;
	cout<<bbb<<"\n";
	cout<<ccc;

	return 0;
}
Which outputs

Code: Select all

97391
97391
Multiplying doesn't seem to be the main cause of this problem.

Post by ClassicOldSong »

I've calculated all wait command time and the total running time of the player, and there's no much difference, and even a little bit slower. So I don't think there's problem with my timing method, probably the recording here is just not time accurate.

Code: Select all

total time delay commands in usecs: 97424690
total play time in usecs: 98046745

Post by ClassicOldSong »

Update:

Rounding actually matters on a larger scale. Changed to divide and it seems playing at the same speed now. Anyway thanks for all the help!
Post Reply