Reputation: 71
Using resources such as http://soundfile.sapp.org/doc/WaveFormat/ and http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html, I'm trying to create a program where you can extract a wave file that's embedded in an executable and copy its byte contents to a file that can be read by a file to convert it from its raw byte data to a WAV file type.
In code, I'm using the below structure:
public class WAVEFile
{
public Header header;
public FMT fmt;
public Data data;
public WAVEFile()
{
header = new Header();
fmt = new FMT();
data = new Data();
}
public class Header
{
public byte[] chunkID;
public int chunkSize;
public byte[] format;
}
public class FMT
{
public byte[] chunkID;
public byte[] chunkSize;
public byte[] audioFormat;
public byte[] noOfChannels;
public byte[] sampleRate;
public byte[] byteRate;
public byte[] blockAlign;
public byte[] bitsPerSample;
}
public class Data
{
public byte[] chunkID;
public byte[] chunkSize;
public byte[] audioData;
}
}
In hex, the main file header and fmt header appear as the following:
52 49 46 46 84 80 00 00 57 41 56 45 66 6D 74 20
20 00 00 00 65 01 10 00 D6 10 00 00 01 00 00 02
E1 55 00 00 44 AC 00 00 00 00 00 00 00 00 00 00
00 02 01 02
However, as per the soundfile.sapp.org website source, the header seems non-standard, at least from what I can tell. The Subchunk1Size is 32 bytes (20 00 00 00 in hex) vs the more common 16. Subsequently, the data that makes up the header is in an abnormal order and appears to include additional or garbage data (in this case, if I continue through the standard structure of a 16 byte header, I'd end up with 00 00 as my bits per sample). Subsequently, I'm left with either static sound or Windows Media Player unable to play the file.
I looked into this further and have came to the conclusion that this can only mean one of two things (of course, I could be wrong):
1) This wave file uses some sort "custom" header or format different from a "standard PCM" wave file, at least at what both sources reference in their examples.
2) This could be using a WAV file as a wrapper, meaning this could, in fact, be a different file type entirely.
Upon further delving into the hex to find any further clues, there appears to be a section at the end of each wave file that begins with "seek". This could be related but I'm unsure. Here's the "seek" data I'm referencing:
73 65 65 6B 48 00 00 00 01 00 00 00 10 00 00 00
00 00 00 00 00 12 00 00 00 20 00 00 00 30 00 00
00 42 00 00 00 52 00 00 00 60 00 00 00 70 00 00
00 7E 00 00 00 8E 00 00 00 9C 00 00 00 AC 00 00
00 BE 00 00 00 D2 00 00 00 E8 00 00 00 00 01 00
After this "seek" code or instruction, another RIFF file header begins.
Essentially, I'm all out of ideas/options/resources to further decipher what is going on with the fmt header and why it does not appear to fit the subchunk one format shown and is 32 bytes long, not 16 which consequently invalidates and disorders the rest of the data in the header. Would anyone have any advice or potential reading sources for further information on how I could go about reading the header correctly to create a valid WAV file?
Upvotes: 1
Views: 1614
Reputation: 71
On further investigation, the 65 01 format tag (or 0x0165) corresponds to the XMA Audio Codec, most commonly used with the Xbox 360 and, I'd assume, its games. It appears to be based on, or at least very similar to, WMA Pro. This was discovered via the following source: http://forum.xentax.com/viewtopic.php?f=17&t=14897
With testing, FFMPEG's libavcodec is able to convert any raw hex data of the .xma type to .wav. By placing the raw hex data similar to above into a file (using any hex editor such as HxD) and renaming its extension to .xma, FFMPEG can convert it to a WAV with the following command:
ffmpeg -i myaudio.xma myaudio.wav
As mentioned in the original question, the seek command's purpose is still ambigious but removing that section from the hex code (so any data between the start of seek and the beginning of the next audio header) the WAV file plays correctly in Windows Media Player.
Upvotes: 1