-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Figure out SPX (Speech) Audio format #2
Comments
Aah these look to be Speex https://www.speex.org/ files with a custom header instead of vorbis? Haven't tried decoding them yet but it looks like from the symbol names they use this official speex library in the game: https://www.speex.org/docs/api/speex-api-reference/globals.html Notice the symbols like |
Yup, I believe they're Speex with a custom header |
How's the progress on this? I'm trying to figure out what to do next |
Haven't touched this yet, I believe there is Speex source code floating around if you want to take a look, but it's all C/C++ as far as I know. Also just a really obscure format nowadays. |
Unfortunately the main implementations are all some cpp nonsense so all the calls are behind vtables that I haven't worked out of the location of. Still getting a handle on how Ghidra works, and a plugin to resolve rtti wasn't working right. IDA was choking on it as well, giving binary ninja a shot. The actual file seems to have the header followed by some kind of regular potentially padding data, then something that seems to be the actual speex payload. Once where the custom implementation falls out and it's just calling libspeex decode it should be fairly easy from there. |
Hey! Thanks for checking this out, happy to see some progress. I should probably link to this somewhere, maybe in the readme, there's a MAC build of the Bon Voyage executable with debug symbols which might help as it reveals function and class names: Dropbox Link |
so turns out these aren't speex frames, they're some kind of further encoded audio frames that do some kind of nonsense before actually calling the speex frame decode. Fun. Seems like it might just be 1 byte frame size followed by the speex frame? not sure. |
Tentatively saying I think I've got it, working on writing a tool to decode spx1 files to wav now. If that works, then this is correct, and the true test of it actually being accurate will be reencoding header: payload: |
awesome, should be straightforward to turn into unity audioclips if the wav conversion works |
The format suggested by @actioninja is roughly correct:
You would call speex_decode_int on the encoded frames to decode the file, the decoded frame size is always 640 samples/1280 bytes. This example in the speex website shows a similar approach to encoding and decoding. The total decoded file size actually comes out to be a little larger than the decoded size written in the header. This is likely because zeros were appended to the end of the file before encoding so that the last frame would have the same size as the other frames. To work around this you could just allocate your array/buffer to the decoded size from the header + 1280 bytes, so that you won't need to resize the array later. I've managed to decode the files using this format. I found two C# libraries that can decode speex: |
That works great! Might implement NAudio as it's convenient for playing MP3s as well. Thank you! |
Implemented, works like a charm! |
I have no experience figuring out audio formats, so this is something I will need help with.
In the TSData/Res/Sound folder there are Voice1, Voice2, etc. packages. Inside of them there are audio files that begin with a SPX1 magic number - these are the audio files left to figure out.
The text was updated successfully, but these errors were encountered: