20,365
edits
(first part of the SNDD rewrite; shouldn't be (m)any mistakes, will check later) |
m (link fix and section name tweak) |
||
| (4 intermediate revisions by the same user not shown) | |||
| Line 7: | Line 7: | ||
No AIFC format other than "ima4" seems to be supported by Oni, therefore we are only documenting "ima4". | No AIFC format other than "ima4" seems to be supported by Oni, therefore we are only documenting "ima4". | ||
== | ==IMA4 as stored in AIFC== | ||
Below is the header of one of Oni's sounds (mono) stored as an .aif file. Note the [[ | Below is the header of one of Oni's sounds (mono) stored as an .aif file. Note the [[wp:Endianness|Big Endian]] order. | ||
[[ | [[Image:sndm_aif.gif]] | ||
{{Table}} | {{Table}} | ||
{{OBDth}} | {{OBDth}} | ||
{{OBDtr| 0x00 | char[4] |FF0000| 46 4F 52 4D | FORM | identifier for the "EA IFF 85" standard }} | {{OBDtr| 0x00 | char[4] |FF0000| 46 4F 52 4D | FORM | identifier for the "EA IFF 85" standard }} | ||
{{OBDtr| 0x04 | int32 |FFFF00| 00 00 2A 90 | 10896 | size of the file from 0x08 to the end ( | {{OBDtr| 0x04 | int32 |FFFF00| 00 00 2A 90 | 10896 | size of the file from 0x08 to the end ({{=}} size of the raw IMA4 data + 50 bytes) }} | ||
{{OBDtr| 0x08 | char[4] |00FF00| 41 49 46 43 | AIFC | identifier for the "AIFC" format (compressed aif file) }} | {{OBDtr| 0x08 | char[4] |00FF00| 41 49 46 43 | AIFC | identifier for the "AIFC" format (compressed aif file) }} | ||
{{OBDtr| 0x0C | char[4] |00FFFF| 43 4F 4D 4D | COMM | identifier announcing the following aif format header (COMM stands for "common")}} | {{OBDtr| 0x0C | char[4] |00FFFF| 43 4F 4D 4D | COMM | identifier announcing the following aif format header (COMM stands for "common")}} | ||
{{OBDtr| 0x10 | block[26]|FFC8C8| | | COMM data (a.k.a. AIFC format header, similar to a WAVE file's "fmt"; see below) }} | {{OBDtr| 0x10 | block[26]|FFC8C8| | | COMM data (a.k.a. AIFC format header, similar to a WAVE file's "fmt"; see below) }} | ||
{{OBDtr| 0x2A | char[4] |FFFFC8| 53 53 4E 44 | SSND | identifier announcing the following aif data (actual stream + stream size + 2 more parameters) }} | {{OBDtr| 0x2A | char[4] |FFFFC8| 53 53 4E 44 | SSND | identifier announcing the following aif data (actual stream + stream size + 2 more parameters) }} | ||
{{OBDtr| 0x2E | int32 |C8FFC8| 00 00 2A 66 | 10854 | size of the following SSND data ( | {{OBDtr| 0x2E | int32 |C8FFC8| 00 00 2A 66 | 10854 | size of the following SSND data ({{=}} size of the raw IMA4 data + 8 bytes) | ||
:(since SSND is the last section, this is also the remaining file size, from 0x32 to the end) }} | :(since SSND is the last section, this is also the remaining file size, from 0x32 to the end) }} | ||
{{OBDtr| 0x32 | int32 |C8FFFF| 00 00 00 00 | 0 | "offset"; determines where the first sample in the data starts; typically zero }} | {{OBDtr| 0x32 | int32 |C8FFFF| 00 00 00 00 | 0 | "offset"; determines where the first sample in the data starts; typically zero }} | ||
| Line 28: | Line 28: | ||
Here is the detail of the format header at 0x10: | Here is the detail of the format header at 0x10: | ||
[[ | [[Image:sndd_hdm.gif]] | ||
{{Table}} | {{Table}} | ||
{{OBDth}} | {{OBDth}} | ||
{{OBDtr| 0x10 | int32 |FFC8C8| 00 00 00 16 | 22 | size of the following COMM data (AIFC format settings) }} | {{OBDtr| 0x10 | int32 |FFC8C8| 00 00 00 16 | 22 | size of the following COMM data (AIFC format settings) }} | ||
{{OBDtr| 0x14 | int16 |FFFFC8| 00 01 | 1 | number of channels (1 | {{OBDtr| 0x14 | int16 |FFFFC8| 00 01 | 1 | number of channels (1 {{=}} mono) }} | ||
{{OBDtr| 0x16 | int32 |C8FFC8| 00 00 01 3F | 319 | | {{OBDtr| 0x16 | int32 |C8FFC8| 00 00 01 3F | 319 | number of frames: <math>\frac{\text{size of the part in the raw file}}{\text{number of channels}*34}</math> }} | ||
{{OBDtr| 0x1A | int16 |C8FFFF| 00 10 | 16 | bits per sample }} | {{OBDtr| 0x1A | int16 |C8FFFF| 00 10 | 16 | bits per sample }} | ||
{{OBDtr| 0x1C | float80 |FFC8FF| 40 0D AC... | 22050 | samples per second (a.k.a. "frequency" or "sample rate") | {{OBDtr| 0x1C | float80 |FFC8FF| 40 0D AC... | 22050 | samples per second (a.k.a. "frequency" or "sample rate") | ||
| Line 44: | Line 44: | ||
At 0x3A start the IMA4 frames, each of them 34 bytes long and coding for 64 samples. Here is a view of a stereo .aif file (based on Oni's SNDDalarm_loop.aif), showing how the IMA4 frames are organized. | At 0x3A start the IMA4 frames, each of them 34 bytes long and coding for 64 samples. Here is a view of a stereo .aif file (based on Oni's SNDDalarm_loop.aif), showing how the IMA4 frames are organized. | ||
[[ | [[Image:sndm_aif2.gif]] | ||
{{Table}} | {{Table}} | ||
{{OBDth}} | {{OBDth}} | ||
{{OBDtr| 0x00 | char[4] |FF0000| 46 4F 52 4D | FORM | identifier for the "EA IFF 85" standard }} | {{OBDtr| 0x00 | char[4] |FF0000| 46 4F 52 4D | FORM | identifier for the "EA IFF 85" standard }} | ||
{{OBDtr| 0x04 | int32 |FFFF00| 00 01 16 4E | 71246 | size of the file from 0x08 to the end ( | {{OBDtr| 0x04 | int32 |FFFF00| 00 01 16 4E | 71246 | size of the file from 0x08 to the end ({{=}} size of the raw IMA4 data + 50 bytes) }} | ||
{{OBDtr| 0x08 | char[4] |00FF00| 41 49 46 43 | AIFC | identifier for the "AIFC" format (compressed aif file) }} | {{OBDtr| 0x08 | char[4] |00FF00| 41 49 46 43 | AIFC | identifier for the "AIFC" format (compressed aif file) }} | ||
{{OBDtr| 0x0C | char[4] |00FFFF| 43 4F 4D 4D | COMM | identifier announcing the following aif format header (COMM stands for "common")}} | {{OBDtr| 0x0C | char[4] |00FFFF| 43 4F 4D 4D | COMM | identifier announcing the following aif format header (COMM stands for "common")}} | ||
{{OBDtr| 0x10 | int32 |FFC8C8| 00 00 00 16 | 22 | size of the following COMM data (AIFC format settings) }} | {{OBDtr| 0x10 | int32 |FFC8C8| 00 00 00 16 | 22 | size of the following COMM data (AIFC format settings) }} | ||
{{OBDtr| 0x14 | int16 |FFFFC8| 00 02 | 2 | number of channels (2 | {{OBDtr| 0x14 | int16 |FFFFC8| 00 02 | 2 | number of channels (2 {{=}} stereo) }} | ||
{{OBDtr| 0x16 | int32 |C8FFC8| 00 00 04 17 | 1047 | | {{OBDtr| 0x16 | int32 |C8FFC8| 00 00 04 17 | 1047 | number of frames: <math>\frac{\text{size of the part in the raw file}}{\text{number of channels}*34}</math> }} | ||
{{OBDtr| 0x1A | int16 |C8FFFF| 00 10 | 16 | bits per sample }} | {{OBDtr| 0x1A | int16 |C8FFFF| 00 10 | 16 | bits per sample }} | ||
{{OBDtr| 0x1C | float80 |FFC8FF| 40 0D AC... | 22050 | samples per second (a.k.a. "frequency" or "sample rate") | {{OBDtr| 0x1C | float80 |FFC8FF| 40 0D AC... | 22050 | samples per second (a.k.a. "frequency" or "sample rate") | ||
| Line 60: | Line 60: | ||
{{OBDtr| 0x26 | char[4] |FFC800| 69 6D 61 34 | ima4 | compression type }} | {{OBDtr| 0x26 | char[4] |FFC800| 69 6D 61 34 | ima4 | compression type }} | ||
{{OBDtr| 0x2A | char[4] |00FFC8| 53 53 4E 44 | SSND | identifier announcing the following aif data (actual stream + stream size + 2 more parameters) }} | {{OBDtr| 0x2A | char[4] |00FFC8| 53 53 4E 44 | SSND | identifier announcing the following aif data (actual stream + stream size + 2 more parameters) }} | ||
{{OBDtr| 0x2E | int32 |FF00C8| 00 01 16 24 | 71204 | size of the following SSND data ( | {{OBDtr| 0x2E | int32 |FF00C8| 00 01 16 24 | 71204 | size of the following SSND data ({{=}} size of the raw IMA4 data + 8 bytes) | ||
:(since SSND is the last section, this is also the remaining file size, from 0x32 to the end) }} | :(since SSND is the last section, this is also the remaining file size, from 0x32 to the end) }} | ||
{{OBDtr| 0x32 | int32 |C8FF00| 00 00 00 00 | 0 | "offset"; determines where the first sample in the data starts; typically zero }} | {{OBDtr| 0x32 | int32 |C8FF00| 00 00 00 00 | 0 | "offset"; determines where the first sample in the data starts; typically zero }} | ||
| Line 75: | Line 75: | ||
*For the stereo example, there are 1047 frames of 68 bytes each (a stereo frame is the combination of a Left frame and a Right frame), or 71196 bytes (8 bytes less than 0x11624, 50 bytes less than 0x1164E). | *For the stereo example, there are 1047 frames of 68 bytes each (a stereo frame is the combination of a Left frame and a Right frame), or 71196 bytes (8 bytes less than 0x11624, 50 bytes less than 0x1164E). | ||
The SNDD file in .dat receives the offset to the .raw data as well as several parameters that depend on the engine version. | The SNDD file in .dat receives the offset to the .raw data as well as several parameters that depend on the engine version. | ||
===Filling in Mac SNDD=== | ===Filling in Mac SNDD=== | ||
Here is how the SNDD instance should look (in .dat) for the above mono example: | Here is how the SNDD instance should look (in .dat) for the above mono example: | ||
[[ | [[Image:sndd_alm.gif]] | ||
*The "compressed" flag is set (because IMA4 is a compressed format; however, if the flag isn't set, the Mac engine will process the data as IMA4 anyway). | *The "compressed" flag is set (because IMA4 is a compressed format; however, if the flag isn't set, the Mac engine will process the data as IMA4 anyway). | ||
| Line 89: | Line 90: | ||
Here is how the SNDD instance looks (in an .oni file) for the above stereo example: | Here is how the SNDD instance looks (in an .oni file) for the above stereo example: | ||
[[ | [[Image:sndd_alm2.gif]] | ||
Same as above, except: | Same as above, except: | ||
| Line 101: | Line 102: | ||
Here is how the PC retail SNDD instance will look (in an .oni file) for the above stereo example: | Here is how the PC retail SNDD instance will look (in an .oni file) for the above stereo example: | ||
[[ | [[Image:sndd_alm4.gif]] | ||
All the fields can be zeroed out or filled with garbage, except: | All the fields can be zeroed out or filled with garbage, except: | ||
| Line 116: | Line 117: | ||
The channel count is either 2 or 1 depending on whether the "2" bit of the flags (at 0x08) is set: if the bitset's value is 0x00000001 then the sound is mono, if the bitset's value is 0x00000003 then the sound is stereo. Knowing the channel count, you deduce the frame count (number of 34- or 68- byte frames) by dividing the .raw size by either 34 (mono) or 68 (stereo); it should divide evenly. | The channel count is either 2 or 1 depending on whether the "2" bit of the flags (at 0x08) is set: if the bitset's value is 0x00000001 then the sound is mono, if the bitset's value is 0x00000003 then the sound is stereo. Knowing the channel count, you deduce the frame count (number of 34- or 68- byte frames) by dividing the .raw size by either 34 (mono) or 68 (stereo); it should divide evenly. | ||
Next you create an AIFC file based of the template described [[# | Next you create an AIFC file based of the template described [[#IMA4 as stored in AIFC|ABOVE]] and adjust it as follows (don't forget about Big Endian!). | ||
*The SNDD's .raw data must be copied into the SSND section of the AIFC file, starting at 0x3A. Copy as-is, no byte swapping required. | *The SNDD's .raw data must be copied into the SSND section of the AIFC file, starting at 0x3A. Copy as-is, no byte swapping required. | ||
*At 0x04, set the remaining file size to the size of the copied .raw data + 50 (Big Endian order!). | *At 0x04, set the remaining file size to the size of the copied .raw data + 50 (Big Endian order!). | ||
| Line 127: | Line 128: | ||
In Vanilla Oni (PC retail) there are no SNDDs that use IMA4 compression, so the situation described here is not very likely. If you need to do it anyway, then you essentially need to look up two things in the .dat part of the SNDD: the channel count at 0x0E and the frame count at 0x18. The frame count multiplied by 34 and by the channel count gives you the size of the .raw part (unlike in all the other situations, the size will not necessarily be stored explicitly in the SNDD, because the engine uses the frame count instead), which allows you to retrieve the IMA4 stream from the .raw file. | In Vanilla Oni (PC retail) there are no SNDDs that use IMA4 compression, so the situation described here is not very likely. If you need to do it anyway, then you essentially need to look up two things in the .dat part of the SNDD: the channel count at 0x0E and the frame count at 0x18. The frame count multiplied by 34 and by the channel count gives you the size of the .raw part (unlike in all the other situations, the size will not necessarily be stored explicitly in the SNDD, because the engine uses the frame count instead), which allows you to retrieve the IMA4 stream from the .raw file. | ||
Next you create an AIFC file based of the template described [[# | Next you create an AIFC file based of the template described [[#IMA4 as stored in AIFC|ABOVE]] and adjust it as follows (don't forget about Big Endian!). | ||
*The SNDD's .raw data must be copied into the SSND section of the AIFC file, starting at 0x3A. Copy as-is, no byte swapping required. | *The SNDD's .raw data must be copied into the SSND section of the AIFC file, starting at 0x3A. Copy as-is, no byte swapping required. | ||
*At 0x04, set the remaining file size to the size of the copied .raw data + 50 (Big Endian order!). | *At 0x04, set the remaining file size to the size of the copied .raw data + 50 (Big Endian order!). | ||
| Line 135: | Line 136: | ||
That is all. Save the file and it should work. | That is all. Save the file and it should work. | ||
<center>[[OBD:SNDD# | <center>[[OBD:SNDD#Mac and Windows demo|Back to Mac SNDD (.dat part)]]</center> | ||
{{OBD}} | {{OBD}} | ||