Finding Trim Points with vgm2txt
Example 1: In Game 2 and others (Finding similar points in the file for looping)
Let's walk through with an example that gave me some trouble: Joe & Mac's In Game 2. vgmlpfnd gave me an exclamation point (try it!), but it's one of those inaccurate ones. Boo.
Time to convert it to wave (VGMPlay -w "07 In Game 2.vgm"
). Instead of trying to work off the inaccurate samples, I tried to find places nearby that looked identical. I went forward about 20,000 samples from the loop start, then adjusted on both sides until I was pretty sure I had matching endpoints.
I wound up with the loop start 403612, and end sample 3104527. This sounded fine, but I'm supposed to be teaching you how to use vgm2txt. Lettuce (get it?) confirm my loop points.
You will definitely want to stop the logging (use Ctrl-C/equivalent) around the 40% mark: that should be more than enough. The file is huge. It's a quarter of a gigabyte! Maybe you might just be satisfied with my pictures for this huge example.
After opening the txt file in a program that can handle such a monster (try MetaPad if you don't already have one), I scrolled, by any means that would work, to a sample near to my loop start.
It seems my loop start landed in a decent place: it came just before a Wait command. Jawesome.
Before continuing, I selected a goodly chunk of lines coming before and after my loop point, including any I felt would help me identify an equivalent region later on in the song/txt. Then I copied and pasted it into a new window. (You can tell by the size of the scrollbar.)
Next task is to find my end sample:
Amazing! It also landed just before a Wait, in an extremely similar spot. (The matching 3620-sample wait would also have been a good place to take the Totals from.) Although the numbers you can see don't exactly match, they're close enough as long as the loop is seamless and aurally-accurate.
There are many sorts of similarities depending on the VGMs you're trying to trim. For instance, the start of Puyo Puyo songs appears to be when the second Low Frequency Oscillator command appears:
0x00000766: 61 95 02 Wait: 661 samples ( 14.99 ms) (total 30119 (00:00.68)) 0x00000769: 52 22 09 YM2612: Low Frequency Oscillator: 5.56 Hz 0x0000076C: 61 35 00 Wait: 53 samples ( 1.20 ms) (total 30172 (00:00.68)) 0x0000076F: 52 2B 00 YM2612: DAC Disable
I used this apparent fact to find Start Samples without needing to make WAVs.
Meanwhile, the counterpart Mean Bean Machine is always sending CSM Mode: Disable, 3 Slot Mode: Disable, Enable Timer: -B, Timer IRQ Enable: -B, Reset Timer Status: AB
, with roughly same-sized Waits between, until playback begins. Similarly, it returns to doing so when the sound has finished. This means that instead of making it harder, the commands constantly being sent makes finding the start (and end of unlooped) songs very easy.
Now that you have some idea of what you're looking for, I hope this empowers you to use vgm2txt for even trickier tracks. Let's look at some now!
Example 2: One Jump Ahead (Using Smaller Text Files)
Now the last thing you want to deal with, especially if you're low on RAM for any reason, is those ginormous text files like in example 1. Must you deal with this horror every single time you trim?
No! Simply provide start and end times around where you expect to find the loop or the end/start of the music.
Aladdin should be a relatively easy pack to trim - except for the part where vgmlpfnd simply does not work with any of its tracks (or, rather, usually won't without making enormously-sized excessive !
loops). Not even the ones with silence gaps before their loops. You'll actually have to roll up your sleeves and look at .wavs or text files.
But we still have the reason Aladdin should be easy: the silence in many of the looping tracks. Can we find this silence in a VGM text file?
Yes. A very resounding yes.
As shown on its page, vgm2txt takes two arguments, each in M:SS format (not samples). This means you can cut what you need to look at down to size, focused on your start, loop, and end points.
To find your endpoint, listen as normal to the song and try to pause it when you think the loop ends. One Jump Ahead takes about two minutes and nineteen seconds, counting the leading recording silence. So we can do:
vgm2txt "14, 15 One Jump Ahead.vgm" 2:18 2:21
(or enter the start and end times when vgm2txt prompts for them on run) which, if the true loop/start/end point lies within these time boundaries, will give us more than enough text to find the right sample. If you guessed wrongly, just move the start and end times.
Just like for the start point, you want to look for a giant wait command. Unless your target game's engine always sends commands, even during silence. Even so, the end point should be easy to identify.
Should! But should is not always. Because you might be tempted to use this giant Wait:
If you do, though, you'll end up cutting off a final note just before the loop. Continue further and discover the true final silence, which is... in the first image I showed you in this section.
Now, having found our start point, we're ready to test our trim! Compare a two-looped WAV to a WAV of the untrimmed file... aaand it's still slightly off! Yaayyyy! *sigh.*
Well, depending on your approach, you'll either move the start point forward or just have non-matching start and loop samples. Doing the latter is definitely acceptable, and sometimes required. But I feel you wanting to make the start and loop points the same. It's a little more work, but we can do it.
When moving start samples around in Audacity, you can change End to Length; this will keep your full loop if you only change the start sample by typing in numbers. (Remember to change it back to End to get the new End sample. By the way, if you want methods for other such programs, see Finding Trim Points in WAV Files.)
35857 is too far, leaving the silence and entering the waveform. So we'll need to use 35500.
At the end of the process, for this file we should yield:
vgm_trim "14, 15 One Jump Ahead.vgm" 35500 35500 6178894
Wait! No! Zinkies! The first note is cut off by this start point! What if we move it back to the start point we expected to use, and subtract from the End point accordingly (or have Audacity subtract for us using the Length trick)?
vgm_trim "14, 15 One Jump Ahead.vgm" 33956 33956 6177350
It works!
Example 3: Storyline (Finding points for a track with natural silence)
Here's another interesting example from File:Storyline.vgm... this time, we'll go ahead and use different start/loop points. Why so? Around the end point, I found this giant wait:
It turned out to be slightly after the loop begins. That made me think I'd find a similar Wait, with a smaller one slightly before it, near the beginning, and so I did:
Hmm... but the loop sounds ever so minutely off to my ears (which are extremely familiar with this piece, since youth). Maybe we should try the shorter waits... Oh no! That's outright wrong - and also, bleck! Just because things appear to roughly line up doesn't mean they're the right loop points.
In that case, let's make it a no intro loop. That's very easy to do in this case: we know the first loop points I tried are the correct length apart.
First we subtract the start point by the loop point. This gives us the number we should subtract from the end point.
When you do the math, you should come out with 1322165 as the new end point. It sounds right, but better cook up some wavs and check visually, in a frenzy of double-bookkeeping.
...Oh! nice! The cut is slightly longer than the raw log, and the waveform looks a bit different! *grumbles further*
Now sometimes this outcome is unavoidable: some songs simply do have very slight differences on each loop, no matter what. But, I still had some paused VGMPlay windows open as I was testing, and saw the loop time decrease by 0.01ms. That tells me I should go back to the first set of loop points and compare that to the raw log.
(At this point, I entered the antlion pit of perfectionism; this doesn't work so well when there are other, non-influenceable reasons a waveform might look slightly different after a loop. How far to continue for the sake of hands-on education is up to the reader. But, note that big Waits are great places to have to move samples around slightly, since by definition you're not cutting off important commands.)
Example 4: Bughaunt (Final exam!)
Time to put it all together and tackle a tricky example that turns out deceptively easy.
Most of Bugs Bunny in Double Trouble's soundtrack is One of Those. What, you may ask, are Those? Really, really, really long tracks that are literally twice as long as you'd expect, because they actually loop without an intro after multiple minutes have passed.
"BUGHAUNT" is one of these. After the beginning's first long Wait, we can observe the following lines:
0x000002CC: 53 B2 3A YM2612: Ch 5 Feedback: 4 x PI, Algorithm: 2 0x000002CF: 71 Wait: 2 sample(s) ( 0.05 ms) (total 113249 (00:02.57)) 0x000002D0: 53 B6 C0 YM2612: Ch 5 PMS: 0x0, AMS: 0x0, Stereo: LR 0x000002D3: 72 Wait: 3 sample(s) ( 0.07 ms) (total 113252 (00:02.57)) 0x000002D4: 53 32 31 YM2612: Ch 5 Slot 0 Detune: 3, Multiple: Freq * 1.0
The important lines here are the YM2612 commands. If we go to where we're sure the song loops and, after a Wait, find these commands in that order (with small Waits in between them as above), we should find the end of our loop!
Now, as the tutorial writer, I am cheating because I actually looked for the end point first, so didn't know what I was seeking exactly. As before, I'll reproduce my fumbles to show you how the trial-and-error process might look.
0x0053467F: 52 2A 80 YM2612: DAC = 80 0x00534682: 61 6B 00 Wait: 107 samples ( 2.43 ms) (total 11538888 (04:21.65)) 0x00534685: 52 2B 00 YM2612: DAC Disable 0x00534688: 7F Wait: 16 sample(s) ( 0.36 ms) (total 11538904 (04:21.65)) 0x00534689: 53 B2 28 YM2612: Ch 5 Feedback: 1 x PI, Algorithm: 0 0x0053468C: 71 Wait: 2 sample(s) ( 0.05 ms) (total 11538906 (04:21.65)) 0x0053468D: 53 B6 C0 YM2612: Ch 5 PMS: 0x0, AMS: 0x0, Stereo: LR
Ah, here we are. "Ch 5
" appeared (but note that the number after the colon there is not the same). That "DAC Disable
" looks interesting. A Ctrl+F finding reveals it appears in the beginning commands, though before the waits; must mean we're on the right track, at least.
My first attempted end point came from further up, and was quite incorrect: too early. The right point is further down, way closer to 4:22 without quite reaching it.
0x00534796: 61 EC 0B Wait: 3052 samples ( 69.21 ms) (total 11542225 (04:21.73)) 0x00534799: 52 28 05 YM2612: Channel 4 Key On/Off: Slot1 Off, Slot2 Off, Slot3 Off, Slot4 Off 0x0053479C: 61 54 26 Wait: 9812 samples ( 222.49 ms) (total 11552037 (04:21.95)) 0x0053479F: 52 28 06 YM2612: Channel 5 Key On/Off: Slot1 Off, Slot2 Off, Slot3 Off, Slot4 Off 0x005347A2: 7E Wait: 15 sample(s) ( 0.34 ms) (total 11552052 (04:21.95)) 0x005347A3: 53 B2 3A YM2612: Ch 5 Feedback: 4 x PI, Algorithm: 2 0x005347A6: 72 Wait: 3 sample(s) ( 0.07 ms) (total 11552055 (04:21.95)) 0x005347A7: 53 B6 C0 YM2612: Ch 5 PMS: 0x0, AMS: 0x0, Stereo: LR 0x005347AA: 72 Wait: 3 sample(s) ( 0.07 ms) (total 11552058 (04:21.95)) 0x005347AB: 53 32 31 YM2612: Ch 5 Slot 0 Detune: 3, Multiple: Freq * 1.0
We see considerable Waits... hold on, is that our buddy Ch 5 Feedback: 4 x PI, Algorithm: 2
? Sure is! And the other two important YM2612 lines appear too. This time, we should use the total from the 15 sample wait, since it's the one that comes right before the first matching command.
Other songs in the set seem to be similarly loopable. By now you've no doubt noticed I haven't provided BUGHAUNT to use yourself. That's because INVULNER is much smaller, and you can use the exact same technique on it. (Besides, I rerecorded BUGHAUNT from the sound test and things changed because of how the music engine works...) Practice all the tricks I've shown you on this track, and you should be well on your way as a trimmer.
Thus by the power of vgm2txt, some mammoth monsters become so easily tamed, it isn't even funny.
(Is welcome, though. Definitely welcome.)
Article license
The contents of this article are given to you under the terms of Creative Commons Zero, which is the equivalent of a public domain dedication (even where such is not otherwise possible) and grants the same rights. Feel free to copy, spindle or mutilate without even worrying about credit.