Previous Page | Next Page

by Nisto at 5:24 PM EDT on June 3, 2018
Okay, well, for now here is v0.6. The code is quite messy, but it gets the job done..
by bnnm at 5:59 PM EDT on June 3, 2018
I added basic support, barely tested and output is not 100% correct yet.
I'll add extended IMA/RE0 and stuff later once I procure some samples.


@Nisto - sorry, it's a bit hard to explain. The number of samples per frame it writes is correct, "which ones" I wasn't so sure. Here is an example:

Pretend we have a "frame_format 1" mono audio frame (with ADPCM hist/index) of size 0x0c+0x02+0x04
- 0x0c are frame_type + format + size + frame_samples
- 0x02 are 1 hist sample + index (in format 1 style).
- 0x04 are 8 nibbles/samples.
So the frame actually contains 1+8 samples.

Now frame_samples could be:
- 9: means you must output *all* samples, including hist (not sure if H4M does this).
- 8 (or lower): you can output in two ways:
* A: write header sample, then write nibbles - 1 (1 + 7)
* B: don't write header sample, then write all nibbles (0 + 8)

The code seems to use uses the "A" model but I was hoping you could confirm it's correct (since you reverse engineered RE0). Looks fine but just wanted to be sure since I've seen different ADPCMs using those models, it's not so easy to guess.


Another oddity I noticed, it uses the first hist sample as right channel. Is this intended?

Ex. if (stereo, frame_format 1) ADPCM setup is "7F816582" (as in, sample 7f80 / index 1 + sample 6580 / index 2) it writes 6580=left,7f80=right channel.

(IOW channels may be swapped? ATM vgmstream swaps channels vs h4m_audio_decode, if you need to compare)
by Alpha23 at 11:16 AM EDT on June 4, 2018
Thanks A LOT for the update! This is fantastic!!! :D

Am I reading this correct that you're trying to add the codec to vgmstream?
by Alpha23 at 2:07 PM EDT on June 4, 2018
Just to be sure: Does this file contain any audio?
by bnnm at 3:02 PM EDT on June 4, 2018
h4m works now in vgmstream, but decoding (codec output) could be improved, based on Nisto's findings, which I'll do later I guess.

I tested RE0 and sounds ok though? I'll need to find edge cases and stuff.

Pikmin has audio but uses an unknown format/type.
by Nisto at 4:28 PM EDT on June 4, 2018
@bnnm: It definitely uses "model A". Here's an excerpt of the decoding routine with some of my notes (hopefully enough to give you some idea what goes on even if you're not familiar with PowerPC assembly):

As you might guess from this code, there are separate functions for different channel configurations and all the different codings. That felt redundant, so naturally I did optimize what I originally ended up with in C, to support varying channel configurations. But I think I did so without screwing things up.

> Another oddity I noticed, it uses the first hist sample as right channel. Is this intended?

Yep. I've just double checked the output with the help of Dolphin. Aside from Dolphin/GameCube writing big-endian samples instead of little-endian samples, the output of h4m_audio_decode is identical.

If you want to confirm it for yourself, here is what I did:

1. Open Dolphin with -d switch
2. Open Biohazard 0 (GBZJ08)
3. Put a breakpoint on 801BFD04 and 801BFF5C
4. Start a new game (mt00.h4m plays)
5. Wait for a breakpoint to be triggered
6. Check register r5 for the output address
7. Check register r7 for the sample count
8. Press play to trigger the next breakpoint
9. In the Memory window, press dump MRAM (find it in %userprofile%\Documents\Dolphin Emulator\Dump)
10. Go to the output offset (address - 0x80000000) in the memory dump
11. Copy the samples (sample count * 4 for decoded stereo IMA ADPCM)
12. Press play and repeat from step 5

You could probably automate all of this somehow. I decided to just check a few frames by hand. It covered all frame formats of course.
by bnnm at 4:36 PM EDT on June 6, 2018
Thanks for the confirmation, just wanted to be sure since those tiny bugs tend to slip by (vgmstream played all MS/XBOX-IMA slighlty off until recently due to mini bugs when handling those models).

I'll add a proper decoder based on your code later, but it's quite playable ATM with standard IMA.
by bnnm at 9:23 AM EDT on August 18, 2018
@Nisto - Something I noticed. I was adding proper decoding to vgmstream (with those big tables and stuff). I compared the output with the old IMA method (shifts-and-adds) and surprisingly I get byte-exact results vs h4m_audio_decode (at least in RE0's 1st disc videos).

Makes sense since (I think) tables are just mapping all possible IMA output (cool optimization though). Maybe there was some bug in the old h4m_audio_decode causing distortion? Or is there some particularly sensitive video?

Also, do you know which games (or can upload some samples) use ADPCM8/PCM or mono H4M?
by Nisto at 11:13 AM EDT on August 18, 2018
@bnnm: mt04.h4m (from RE0 Disc 1) for example will not decode with h4m_audio_decode version 0.3. It terminates with the message:

invalid step index (124) at 0x57cdc

I've tried recompiling v0.3 with Pelles C without optimizations but that did not help. Are you saying you are able to decode mt04.h4m using v0.3?

Regarding the ADPCM8 and PCM codings, I have still not found any game that use them, sorry.
by bnnm at 12:18 PM EDT on August 18, 2018
Oh, I meant in vgmstream. To clarify:
- I re-implemented vgmstream's H4M using your 'expansion' algorithm (converts nibble to sample with big [89][8] tables, like v0.5 line 379).
Now vgmstream creates files that are byte-exact vs h4m_audio_decode v0.5
- Then as a test, I swapped the algorithm with the 'classic IMA' one (converts nibble to sample using shifts-and-adds, like v0.3 line 192)
This also creates files that are byte-exact.

Since (I think) the big table is just the output of all possible classic-IMA combinations of steps/indexes, makes sense both ways decode the same. It's fun to know they opmitized it like that tho.


Checking v0.3 source (line ~160), I think the actual problem is that it doesn't understand frame format 0x03 (introduced in RE0 I pressume?), unlike v0.5.

At 0x57CD8 it should read: 0xFDD4,0x30 + 0xFC36,0x2F (0x03*2).
Instead it reads 0xFDD4 + 0x30FC (0x02*2)
> a.k.a. 0xFDD4&0xFF80=0xFD80, 0xFDD4&0x007F=0x54 + 0x30FC&0xFF80=0x3080, 0x30FC&0x007F=0x7c = 124 = error!

Previous Page | Next Page
Go to Page 0 1 2 3 4 5 6

Search this thread

Show all threads

Reply to this thread:

User Name Tags:

bold: [b]bold[/b]
italics: [i]italics[/i]
emphasis: [em]emphasis[/em]
underline: [u]underline[/u]
small: [small]small[/small]
Link: [url=]Link[/url]


HCS Forum Index
Halley's Comet Software
forum source