ffmpeg Decodes .xma Too Fast? by Kurausukun at 4:34 AM EST on December 10, 2016
I just tried using the latest build of ffmpeg to decode an .xma file (specifically, an .xma file from Sonic 06, which uses xma1), and ffmpeg does successfully output the file, but it plays too fast. Does anyone else have this issue, or have any experience/tips in decoding .xma files with ffmpeg?
FFmpeg needs to be tricked into ignoring the "fmt " chunks in those files, so it only parses the XMA2 chunks for format information. I tried to make it override at one point, but that didn't work. It needs to not even see the "fmt " chunks if there are "XMA2" chunks.
I did some grotesque header forgery and it's working ok. I'll take some time to check variations and stuff though. (maybe it's just easier to fix it in FFmpeg itself)
Chopping out the "fmt " chunk will "fix" it too. Maybe add a check to FFmpeg to search for the XMA2 chunk separately first, then bypass the fmt chunk if an XMA2 chunk is found? And don't forget to submit your patch to the ffmpeg devel mailing list!
The main problem is that the XMA2 chunk has some variations but FFmpeg only supports one. I can reconstruct the header ignoring the fmt and moving XMA2 data around where FFmpeg expects it but it's so ugly.
Patching FFmpeg wouldn't be so hard but on the other hand it could take a while (months?) to propagate plus having to go through all their hoops.
Issues I know: - if the "fmt" chunk is found first "XMA2" is ignored (@ wavdec.c) - "XMA2" chunk: no V3 = size 0x24 (minor variation), expects V4 = size 0x2c (@ wavdec.c) - no XMA2 6 channel (@ wmaprodec.c) - no RIFX/big endian (also I'll check if various block sizes are supported)
The 6ch is the only one I can't hack into vgmstream, so it would be great if you could look into that first.
***
Also I couldn't find a XMA1 set with loop points. I'm blind, loop points are outside, or is every joshw set borked/transconverted? :S
The >2 channel in XMA1/2 is one big mess, i failed to dechiper it. Perhaps someone can explain to me how to implement it because it needs big blocks of data. I'm well aware of scripts which splits such streams into stereo files.
I don't know if His World actually loops in-game, so I'm not sure there are loop points in that file... I'll upload the one I've been using just in case: here.
I tested with vgmstream a bit and generally works fine, but there are some problems when looping/seeking. Seems channel packets are being mixed (ex. packets from ch0 will appear in ch2, etc).
Looping works by using avformat_seek_file to 0 + avcodec_flush_buffers, and decoding again until the desired sample.