OBD:SNDD/wav: Difference between revisions

13,185 bytes removed ,  6 January 2024
m
replaced formula GIFs with Math markup; replaced nowiki tags around equals signs with new {{=}} magic word
(getting there...)
m (replaced formula GIFs with Math markup; replaced nowiki tags around equals signs with new {{=}} magic word)
 
(2 intermediate revisions by one other user not shown)
Line 40: Line 40:
{{OBDtr| 0x0C | char[4]  |00FFFF| 66 6D 74 20 | "fmt "    | identifier announcing the following "fmt " (format) section }}
{{OBDtr| 0x0C | char[4]  |00FFFF| 66 6D 74 20 | "fmt "    | identifier announcing the following "fmt " (format) section }}
{{OBDtr| 0x10 | uint32  |FFC8C8| 10 00 00 00 | 16        | content size for the "fmt " section, in bytes (always 16 for PCM) }}
{{OBDtr| 0x10 | uint32  |FFC8C8| 10 00 00 00 | 16        | content size for the "fmt " section, in bytes (always 16 for PCM) }}
{{OBDtr| 0x14 | uint16  |FFFFC8| '''''01 00'''''      | 1        | format ID (1 <nowiki>=</nowiki> linear PCM format) }}
{{OBDtr| 0x14 | uint16  |FFFFC8| '''''01 00'''''      | 1        | format ID (1 {{=}} linear PCM format) }}
{{OBDtr| 0x16 | uint16  |C8FFC8| '''''02 00'''''      | 2        | number of channels (2 <nowiki>=</nowiki> stereo) }}
{{OBDtr| 0x16 | uint16  |C8FFC8| '''''02 00'''''      | 2        | number of channels (2 {{=}} stereo) }}
{{OBDtr| 0x18 | uint32  |C8FFFF| '''''22 56 00 00''''' | 22050    | sample rate in Hz (samples per second), a.k.a. "sampling frequency" }}
{{OBDtr| 0x18 | uint32  |C8FFFF| '''''22 56 00 00''''' | 22050    | sample rate in Hz (samples per second), a.k.a. "sampling frequency" }}
{{OBDtr| 0x1C | uint32  |FFC8FF| '''''88 58 01 00''''' | 88200    | data rate (<nowiki>=</nowiki> "sample rate" * "block alignment"), in bytes per second
{{OBDtr| 0x1C | uint32  |FFC8FF| '''''88 58 01 00''''' | 88200    | data rate ({{=}} "sample rate" * "block alignment"), in bytes per second
:<small>'''N.B.''' For PCM, there is one block per sample, hence the simple formula.</small> }}
:<small>'''N.B.''' For PCM, there is one block per sample, hence the simple formula.</small> }}
{{OBDtr| 0x20 | uint16  |FFC800| '''''04 00'''''      | 4        | block alignment a.k.a "block size", in bytes
{{OBDtr| 0x20 | uint16  |FFC800| '''''04 00'''''      | 4        | block alignment a.k.a "block size", in bytes
Line 50: Line 50:
{{OBDtr| 0x24 | char[4]  |FF00C8| 64 61 74 61 | data      | identifier announcing the following "data" section }}
{{OBDtr| 0x24 | char[4]  |FF00C8| 64 61 74 61 | data      | identifier announcing the following "data" section }}
{{OBDtr| 0x28 | uint32  |C8FF00| 00 50 09 00 | 610304    | content size for the "data" section, in bytes (implies 152576 stereo sample blocks, 4 bytes each) }}
{{OBDtr| 0x28 | uint32  |C8FF00| 00 50 09 00 | 610304    | content size for the "data" section, in bytes (implies 152576 stereo sample blocks, 4 bytes each) }}
{{OBDtr| 0x2C | block[4] |C800FF| F5 FF F5 FF | (-11,-11) | first stereo sample; the left and the right sample values are both -11<nowiki>=</nowiki>0xFFF5 }}
{{OBDtr| 0x2C | block[4] |C800FF| F5 FF F5 FF | (-11,-11) | first stereo sample; the left and the right sample values are both -11{{=}}0xFFF5 }}
|}
|}
;Mono vs stereo
;Mono vs stereo
Line 125: Line 125:
{{OBDtr| 0x0C | char[4]  |00FFFF| 66 6D 74 20 | "fmt "    | identifier announcing the following "fmt " (format) section }}
{{OBDtr| 0x0C | char[4]  |00FFFF| 66 6D 74 20 | "fmt "    | identifier announcing the following "fmt " (format) section }}
{{OBDtr| 0x10 | uint32  |FFC8C8| 32 00 00 00 | 50        | content size for the "fmt " section, in bytes (typically 50 for MS ADPCM) }}
{{OBDtr| 0x10 | uint32  |FFC8C8| 32 00 00 00 | 50        | content size for the "fmt " section, in bytes (typically 50 for MS ADPCM) }}
{{OBDtr| 0x14 | uint16  |FFFFC8| '''''02 00'''''      | 2        | format ID (2 <nowiki>=</nowiki> MS ADPCM format) }}
{{OBDtr| 0x14 | uint16  |FFFFC8| '''''02 00'''''      | 2        | format ID (2 {{=}} MS ADPCM format) }}
{{OBDtr| 0x16 | uint16  |C8FFC8| '''''02 00'''''      | 2        | number of channels (2 <nowiki>=</nowiki> stereo) }}
{{OBDtr| 0x16 | uint16  |C8FFC8| '''''02 00'''''      | 2        | number of channels (2 {{=}} stereo) }}
{{OBDtr| 0x18 | uint32  |C8FFFF| '''''22 56 00 00''''' | 22050    | sample rate in Hz (samples per second), a.k.a. "sampling frequency" }}
{{OBDtr| 0x18 | uint32  |C8FFFF| '''''22 56 00 00''''' | 22050    | sample rate in Hz (samples per second), a.k.a. "sampling frequency" }}
{{OBDtr| 0x1C | uint32  |FFC8FF| '''''27 57 00 00''''' | 22311    | [[image:sndd_hd1.gif]]
{{OBDtr| 0x1C | uint32  |FFC8FF| '''''27 57 00 00''''' | 22311    | <math>\frac{\text{samples per second}*\text{block alignment}}{\text{samples per block}}</math>
:<small>'''N.B.''' The data rate (in bytes per second) is truncated to the lower integer value.</small> }}
:<small>'''N.B.''' The data rate (in bytes per second) is truncated to the lower integer value.</small> }}
{{OBDtr| 0x20 | uint16  |FFC800| '''''00 04'''''      | 1024      | block alignment a.k.a "block size", in bytes
{{OBDtr| 0x20 | uint16  |FFC800| '''''00 04'''''      | 1024      | block alignment a.k.a "block size", in bytes
Line 134: Line 134:
{{OBDtr| 0x22 | uint16  |00FFC8| '''''04 00'''''      | 4        | bits per sample (per channel); typically 4 bits for MS ADPCM }}
{{OBDtr| 0x22 | uint16  |00FFC8| '''''04 00'''''      | 4        | bits per sample (per channel); typically 4 bits for MS ADPCM }}
{{OBDtr| 0x24 | uint16  |C87C64| '''''20 00'''''      | 32        | size of the following extended format specification, in bytes }}
{{OBDtr| 0x24 | uint16  |C87C64| '''''20 00'''''      | 32        | size of the following extended format specification, in bytes }}
{{OBDtr| 0x26 | uint16  |B0C3D4| '''''F4 03'''''      | 1012      | [[image:sndd_hd2.gif]] }}
{{OBDtr| 0x26 | uint16  |B0C3D4| '''''F4 03'''''      | 1012      | <math>\dfrac{(\text{block alignment}-7*\text{number of channels})*8}{\text{bits per sample}*\text{number of channels}}+2</math> }}
{{OBDtr| 0x28 | uint16  |E7CEA5| '''''07 00'''''      | 7        | number of the following coefficient pairs; always 7 in practice }}
{{OBDtr| 0x28 | uint16  |E7CEA5| '''''07 00'''''      | 7        | number of the following coefficient pairs; always 7 in practice }}
|-align=center valign=top
|-align=center valign=top
| 0x2A || int16-16 || bgcolor="#FFDDDD" | '''''00 01 00 00''''' || 256, 0 || rowspan=7 align=left | The coefficient pairs themselves (always the same in practice).<br>[[image:sndd_hd3.gif]]
| 0x2A || int16-16 || bgcolor="#FFDDDD" | '''''00 01 00 00''''' || 256, 0 || rowspan=7 align=left | The coefficient pairs themselves (always the same in practice).<br><math>\begin{array}{|c|c||c|} \text{coefficient set} & \text{coefficient 1} & \text{coefficient 2} \\
\hline
0 & 256 &    0\\
1 & 512 & -256\\
2 &  0 &    0\\
3 & 192 &  64\\
4 & 240 &    0\\
5 & 460 & -208\\
6 & 392 & -232
\end{array} </math>
|-align=center valign=top
|-align=center valign=top
| 0x2E || int16-16 || bgcolor="#FFDDDD" | '''''00 02 00 FF''''' || 512, -256  
| 0x2E || int16-16 || bgcolor="#FFDDDD" | '''''00 02 00 FF''''' || 512, -256  
Line 171: Line 180:
:From the "samples per block" follows the average rate (at 0x1C). From the actual number of samples (at 0x4E) follows the number of ADPCM blocks required to store the waveform, and therefore the data size at (0x56), a multiple of "block size", which in turn affects the total RIFF size at 0x04.
:From the "samples per block" follows the average rate (at 0x1C). From the actual number of samples (at 0x4E) follows the number of ADPCM blocks required to store the waveform, and therefore the data size at (0x56), a multiple of "block size", which in turn affects the total RIFF size at 0x04.
;"fact" section VS truncated data
;"fact" section VS truncated data
:It is ''not'' standard-compliant to truncate the final ADPCM block after the last actual sample like Oni does. The WAVE file is expected to contain ''whole'' ADPCM blocks (usually padded with zeroes), and the exact number of actual samples is specified in the "fact" section. This is not very space-efficient, but it allows a waveform to have a completely arbitrary number of samples. With Oni's truncated data and lack of an explicit sample count, it is impossible to specify an odd-numbered count of mono samples (because the bytes of mono ADPCM blocks consist of consecutive same-channel nibbles, and there is no way to tell whether the last nibble counts or not). Also, Oni can only truncate after the header of an ADPCM block, therefore the two explicitly stored samples int he header are always played, whereas "fact" can be used to indicate that only the first sample is actual waveform data, and the other is a dummy.
:It is ''not'' standard-compliant to truncate the final ADPCM block after the last actual sample like Oni does. The WAVE file is expected to contain ''whole'' ADPCM blocks (usually padded with zeroes), and the exact number of actual samples is specified in the "fact" section. This is not very space-efficient, but it allows a waveform to have a completely arbitrary number of samples. With Oni's truncated data and lack of an explicit sample count, it is impossible to specify an odd-numbered count of mono samples (because the bytes of mono ADPCM blocks consist of consecutive same-channel nibbles, and there is no way to tell whether the last nibble counts or not). Also, Oni can only truncate after the header of an ADPCM block, therefore the two explicitly stored samples in the header are always played, whereas "fact" can be used to indicate that only the first sample is actual waveform data, and the other is a dummy.
;Data size
;Data size
:The size at 0x56 is the size of the raw data that starts at 0x5A, which consists of whole ADPCM blocks and will need to be truncated after the last actual sample for use in an Oni SNDD instance. If the data is not truncated, Oni will determine the sample count from the padded data size, and there will be a noticeable silence (up to 46 milliseconds, or almost 3 game ticks, at 22.05 kHz and for 1012 samples per block) – not a problem for impulse sounds, but definitely not recommendable for ambients or music.
:The size at 0x56 is the size of the raw data that starts at 0x5A, which consists of whole ADPCM blocks and will need to be truncated after the last actual sample for use in an Oni SNDD instance. If the data is not truncated, Oni will determine the sample count from the padded data size, and there will be a noticeable silence (up to 46 milliseconds, or almost 3 game ticks, at 22.05 kHz and for 1012 samples per block) – not a problem for impulse sounds, but definitely not recommendable for ambients or music.


<!--
[[image:sndd_wav.gif]]
{{Table}}
{{OBDth}}
{{OBDtr| 0x0C | int16    |FFFFC8| 01 00      | 2    | format ID (2 <nowiki>=</nowiki> ADPCM format)
:<small>'''N.B.''' At the time of writing, only "1" (linear PCM) and "2" (ADPCM) are known to work in Oni.</small>}}
{{OBDtr| 0x0E | int16    |C8FFC8| 01 00      | 1    | number of channels (1 <nowiki>=</nowiki> mono)
:<small>'''N.B.''' Both PCM and ADPCM support only mono and stereo sounds, i.e., 1 or 2 channels.</small>}}
{{OBDtr| 0x10 | int32    |C8FFFF| 22 56 00 00 | 22050 | sample rate in Hz (samples per second), a.k.a. "sampling frequency" }}
{{OBDtr| 0x14 | int32    |FFC8FF| 93 2B 00 00 | 11155 | [[image:sndd_hd1.gif]]
:<small>'''N.B.''' For PCM, the data rate is simply "samples per second"*"block alignment", seeing as each sample gets its own block.</small>
:<small>'''N.B.''' For ADPCM, the potentially incomplete trailing block is not taken into account when calculating the average data rate.</small>}}
{{OBDtr| 0x18 | int16    |FFC800| 02 00      | 512  | block alignment a.k.a "block size", in bytes
:<small>'''N.B.''' The block size is trivially 2 bytes for PCM mono (one 16-bit sample) and 4 bytes for PCM stereo (Left and Right 16-bit samples).</small>
:<small>'''N.B.''' For ADPCM, Oni's Vanilla data always uses 512 bytes per channel for 22050 Hz waveforms, and 1024 bytes for 44.1 kHz mono (see below).}}
{{OBDtr| 0x1A | int16    |C800C8| 10 00      | 16    | bits per sample (per channel); typically 16 bits for PCM }}
|}
-->


==Importing from WAVE into Oni==
==Importing from WAVE into Oni==
Line 217: Line 206:
The PC retail engine is more flexible since it has a 50-byte format section specifically intended to receive the "fmt " chunk of a MS ADPCM .wav file along will all the non-trivial ADPCM settings. This format section is activated with the 0x00000008 flag, provided that the 0x00000004 flag is OFF (this "4" flag overrides the "8" flag and forces the interpretation of the data as IMA4 ADPCM).
The PC retail engine is more flexible since it has a 50-byte format section specifically intended to receive the "fmt " chunk of a MS ADPCM .wav file along will all the non-trivial ADPCM settings. This format section is activated with the 0x00000008 flag, provided that the 0x00000004 flag is OFF (this "4" flag overrides the "8" flag and forces the interpretation of the data as IMA4 ADPCM).


The 50-byte format section in the SNDD can also be used to store the shorter "fmt " chunk of as PCM .wav files, and this is the recommended procedure, as opposed to using the "raw PCM" functionality of PC retail SNDD (if you remove the 0x00000008 flag, then the format header is completely disabled and the .raw SNDD data is interpreted as 22.05 kHz PCM, using the channel count specified at OSGr level; don't do that, and just use the "8" flag).
The 50-byte format section in the SNDD can also be used to store the shorter "fmt " chunk of PCM .wav files, and this is the recommended procedure, as opposed to using the "raw PCM" functionality of PC retail SNDD (if you remove the 0x00000008 flag, then the format header is completely disabled and the .raw SNDD data is interpreted as 22.05 kHz PCM, using the channel count specified at OSGr level; don't do that, and just use the "8" flag).
;Copying the .raw data
;Copying the .raw data
:For PCM, just refer to the "PCM" template above: copy the data that starts at 0x2C in the WAVE file (its size can be found at 0x28, but it reaches to the end of the file anyway since there is no padding). Copy the data to the SNDD's .raw part, store the address at 0xC4 in the SNDD's .dat part and the size at 0xC0.
:For PCM, just refer to the "PCM" template above: copy the data that starts at 0x2C in the WAVE file (its size can be found at 0x28, but it reaches to the end of the file anyway since there is no padding). Copy the data to the SNDD's .raw part, store the address at 0xC4 in the SNDD's .dat part and the size at 0xC0.
Line 287: Line 276:




<!--
On PC sound data optionally uses an [https://docs.microsoft.com/en-us/previous-versions//ee415686(v=vs.85) ADPCMWAVEFORMAT] header, equivalent to what you find in a .wav file after "WAVEfmt ". In the following it will be called "WAVEfmt" for short. It is activated if the "flags" in the
==WAVE fmt header==
[[image:sndd_hd.gif]]
{{Table}}
{{OBDth}}
{{OBDtr| 0x0C | int16    |FFFFC8| 02 00      | 2    | format ID (2 <nowiki>=</nowiki> ADPCM format)
:<small>'''N.B.''' At the time of writing, only "1" (linear PCM) and "2" (ADPCM) are known to work in Oni.</small>}}
{{OBDtr| 0x0E | int16    |C8FFC8| 01 00      | 1    | number of channels (1 <nowiki>=</nowiki> mono)
:<small>'''N.B.''' Both PCM and ADPCM support only mono and stereo sounds, i.e., 1 or 2 channels.</small>}}
{{OBDtr| 0x10 | int32    |C8FFFF| 22 56 00 00 | 22050 | sample rate in Hz (samples per second), a.k.a. "sampling frequency" }}
{{OBDtr| 0x14 | int32    |FFC8FF| 93 2B 00 00 | 11155 | [[image:sndd_hd1.gif]]
:<small>'''N.B.''' For PCM, the data rate is simply "samples per second"*"block alignment", seeing as each sample gets its own block.</small>
:<small>'''N.B.''' For ADPCM, the potentially incomplete trailing block is not taken into account when calculating the average data rate.</small>}}
{{OBDtr| 0x18 | int16    |FFC800| 00 02      | 512  | block alignment a.k.a "block size", in bytes
:<small>'''N.B.''' The block size is trivially 2 bytes for PCM mono (one 16-bit sample) and 4 bytes for PCM stereo (Left and Right 16-bit samples).</small>
:<small>'''N.B.''' For ADPCM, Oni's Vanilla data always uses 512 bytes per channel for 22050 Hz waveforms, and 1024 bytes for 44.1 kHz mono (see below).}}
{{OBDtr| 0x1A | int16    |C800C8| 04 00      | 4    | bits per sample (per channel); typically 4 bits for ADPCM and 16 bits for PCM }}
{{OBDtrBK|1=Special extended ADPCM wav format header (black outline); ignored for PCM }}
{{OBDtr| 0x1C | int16    |C87C64| 20 00      | 32    | size of the following extended format specification, in bytes }}
{{OBDtr| 0x1E | int16    |B0C3D4| F4 03      | 1012  | [[image:sndd_hd2.gif]] }}
{{OBDtr| 0x20 | int16    |E7CEA5| 07 00      | 7    | number of the following coefficient pairs; always 7 in practice }}
|-align=center valign=top
| 0x22 || int16-16 || bgcolor="#FFDDDD" | 00 01 00 00 || 256, 0 || rowspan=7 align=left | [[image:sndd_hd3.gif|left]]
The 7 pairs of coefficients are a standard set (hardcoded in practically every implementation of MS ADPCM). However, in theory their number and values are allowed to vary, and therefore any ADPCM-compressed waveform still provides the coefficients that were used for encoding (always the same in practice).
TLDR: The "magic numbers" in this table are at the core of the ADPCM encoding/decoding algorithm; don't even think of modifying them.
|-align=center valign=top
| 0x26 || int16-16 || bgcolor="#FFDDDD" | 00 02 00 FF || 512, -256
|-align=center valign=top
| 0x2A || int16-16 || bgcolor="#FFDDDD" | 00 00 00 00 || 0, 0
|-align=center valign=top
| 0x2E || int16-16 || bgcolor="#FFDDDD" | C0 00 40 00 || 192, 64
|-align=center valign=top
| 0x32 || int16-16 || bgcolor="#FFDDDD" | F0 00 00 00 || 240, 0
|-align=center valign=top
| 0x36 || int16-16 || bgcolor="#FFDDDD" | CC 01 30 FF || 460, -208
|-align=center valign=top
| 0x3A || int16-16 || bgcolor="#FFDDDD" | 88 01 18 FF || 392, -232
|}
;Format ID
:Oni is only known to support the two first formats implemented for WAVE: 1 (linear [[wp:Pulse-code_modulation|PCM]]) and 2 (MS [[wp:Adaptive_differential_pulse-code_modulation|ADPCM]]).
:There are hundreds of other formats (including MP3, Vorbis, Dolby, FLAC and lots of legacy codecs that no one cares about), but (L)PCM and (MS)ADPCM are the most widespread and useful.
:Vanilla Oni data exclusively uses MS ADPCM (format ID 2, shown above), but some mods have successfully used (L)PCM, which is why we are documenting it too.
:'''N.B.''' At the time of writing, '''''formats other than (L)PCM (=1) and (MS)ADPCM (=2) have not been confirmed to work in Oni''''', and their use is strongly discouraged!
;Basic and extended sets of parameters
:Any WAVEfmt header must contain the six basic fields: format ID, channel count (typically 1 or 2, at least for PCM or ADPCM; could be more for Dolby and such), sample rate (in Hz), data rate (in bytes per second), block alignment (in bytes), and sample size (per channel; in bits). Besides, all the formats other than 1 (linear PCM) must include an extended header; even if there are actually no additional parameters, there should still be an "extension size" field, taking up two bytes, with value zero.
:For MS ADPCM, the extended header is always 32 bytes (value 0x0020 at 0x1C above) and contains the "samples per block" value (actually redundant of the sample count, block size and bits per sample) as well as the prediction coefficient table, as shown above. In theory, an encoder doesn't need to specify exactly 7 coefficient pairs, hence the extension size can theoretically vary. In practice, though, the same standard 7 coefficient pairs are hardcoded in every implementation of MS ADPCM.
:For PCM, there is no extended header, and no extension size is expected either, so everything starting at 0x1C can be zeroed out or filled with garbage. The other differences to ADPCM are that "bits per sample" is typically 16 (understood as bits per sample ''per channel''), block size is "number of channels"x"bits per sample"/8, and "data rate" is simply "sample rate"x"block size", since for PCM each sample gets its own block.
;Values ignored by Oni's playback
:Although Windows builds of Oni rely on Windows's [https://docs.microsoft.com/en-us/windows/win32/multimedia/audio-compression-manager Audio Compression Manager] for WAVE playback, the Windows retail builds do ''not'' directly forward the WAVE "fmt" header of an SNDD file to ACM, and the "sample rate" and "data rate" fields (at 0x10 and 0x14 above) are actually ignored/overwritten. All SNDDs are actually interpreted as 22.05 kHz waveforms (the actual playback rate depends on pitch/speed adjustments in [[OBD:OSBD/OSGr|OSGr]]). This includes the 46 Vanilla SNDDs that have a 44.1 kHz waveform in Windows retail versions ('''ap_hit_shld''' and '''zap##''', ##=01-45): all these 46 sounds are in fact misinterpreted as 22.05 kHz and played back 2 times slower/lower than intended.
:For (L)PCM, the "sample rate" and "data rate" are not entirely ignored. If these two values are mutually inconsistent, i.e., if "data rate" is ''not'' equal to "sample rate"x"block size", then playback will be affected (permutation glitches or no playback at all). If, however, "data rate" ''is'' equal to "sample rate"x"block size", then playback is smooth, but the waveforms are invariably interpreted as 22.05 kHz, regardless of the specified sample rate.
;Self-consistency requirement
:All the parameters of the WAVEfmt header are expected to be consistent both mutually and with the stream data in the .raw file. Thus, "bits per sample" should be consistent with the actual size of compressed samples (typically 4-bit nibbles) or uncompressed ones (typically 16-bit). The block size, together with the channel count, determines the number of samples per block (for ADPCM). Also, the prediction coefficient table, standard though it is, is still read by Oni (to allow for non-standard encoding); therefore the table must be consistent with the compressed data (i.e., typically it will merely list the standard coefficient pairs).
:Provided that the WAVE file was created by a standard-compliant tool, the WAVEfmt header should just be copied over to the SNDD file without any changes (the only caveat is that Oni will ignore the "sample rate" and "data rate" -- or merely check the consistency of "data rate" -- and play back all waveforms as if they were sampled at 22.05 kHz; this can be compensated in OSGr).
;Consistency with [[OBD:OSBD/OSGr|OSGr]] and SNDD header flags
:For the WAVEfmt header to be interpreted according to the above descriptoon, the SNDD header must have its 0x00000008 flag set and it 0x00000004 flag unset. If 0x00000004 is set, then it overrides 0x00000008 and interprets the 50-byte format block in another way than  lds that are redundant of the WAVE "fmt" header: the "compressed" flag, and the approximate duration in game ticks.
:*The duration is a non-critical parameter, used for for dialog cueing; its expected value is a "floor"ed integer (i.e. the number of ''whole'' game ticks covered by the sound).
:*The "compressed" flag (0x00000008) is semi-critical. If the WAVEfmt header describes the sound as PCM, then the compressed flag can be set or unset indifferently. If, however, the WAVEfmt header announces an ADPCM sound, then the "compressed" flag in SNDD should also be set, otherwise Oni will process the compressed stream as PCM (producing random-sounding noise).
:Besides, any SNDD played back by Oni is referenced through an [[OBD:OSBD/OSGr|OSGr]] file, which contains pitch/speed and volume adjustments, as well as a redundant channel count. If the channel count in OSGr is inconsistent with the SNDD's actual one, then the sound may play back 2x faster or slower than intended, or fail to play altogether. See the [[OBD:OSBD/OSGr|OSGr]] page for details.
Below are the three types of headers occurring in Oni
----
;22.05 kHz mono
*'''1''' channel
*sample rate '''''22050''''' Hz
*average rate '''11155''', truncated from ~11155.7312253 = 22050*512/1012
*block alignment '''''512'''''
*'''4''' bits per sample
*'''''1012''''' samples per block = 2 + (512 - 7)*8/4/1
*standard coefficient table
{|
{{HexRow|0x00|
|°°|°°|°°|°°|°°|°°|°°|°°|08|00|00|00|02|00|'''01'''|'''00'''|
}}
{{HexRow|0x10|
|'''''22'''''|'''''56'''''|'''''00'''''|'''''00'''''
|'''93'''|'''2B'''|'''00'''|'''00'''
|'''''00'''''|'''''02'''''
|'''04'''|'''00'''
|20|00
|'''''F4'''''|'''''03'''''
}}
{{HexRow|0x20|
|07|00|00|01|00|00|00|02|00|FF|00|00|00|00|C0|00|
}}
{{HexRow|0x30|
|40|00|F0|00|00|00|CC|01|30|FF|88|01|18|FF|°°|°°|
}}
|}
----
;22.05 kHz stereo
*'''2''' cnannels
*sample rate '''''22050''''' Hz
*average rate '''22311''', truncated from ~22311.4624506 = 22050*1024/1012
*block alignment '''''1024'''''
*'''4''' bits per sample
*'''''1012''''' samples per block = 2 + (1024 - 2*7)*8/4/2
*standard coefficient table
{|
{{HexRow|0x00|
|°°|°°|°°|°°|°°|°°|°°|°°|08|00|00|00|02|00|'''02'''|'''00'''|
}}
{{HexRow|0x10|
|'''''22'''''|'''''56'''''|'''''00'''''|'''''00'''''
|'''27'''|'''57'''|'''00'''|'''00'''
|'''''00'''''|'''''04'''''
|'''04'''|'''00'''
|20|00
|'''''F4'''''|'''''03'''''
}}
{{HexRow|0x20|
|07|00|00|01|00|00|00|02|00|FF|00|00|00|00|C0|00|
}}
{{HexRow|0x30|
|40|00|F0|00|00|00|CC|01|30|FF|88|01|18|FF|°°|°°
}}
|}
----
;44 kHz mono
*'''1''' channel
*sample rate '''''44100''''' kHz
*average rate '''22179''', truncated from ~22179.9607073 = 44100*1024/2036
*block alignment '''''1024'''''
*'''4''' bits per sample
*'''''2036''''' samples per block = 2 + (1024 - 7)*8/4/1
*standard coefficient table
{|
{{HexRow|0x00|
|°°|°°|°°|°°|°°|°°|°°|°°|08|00|00|00|02|00|'''01'''|'''00'''|
}}
{{HexRow|0x10|
|'''''44'''''|'''''AC'''''|'''''00'''''|'''''00'''''
|'''A3'''|'''56'''|'''00'''|'''00'''
|'''''00'''''|'''''04'''''
|'''04'''|'''00'''
|20|00
|'''''F4'''''|'''''07'''''
}}
{{HexRow|0x20|
|07|00|00|01|00|00|00|02|00|FF|00|00|00|00|C0|00|
}}
{{HexRow|0x30|
|40|00|F0|00|00|00|CC|01|30|FF|88|01|18|FF|°°|°°|
}}
|}
----
Here is
----
List of the (relatively rare) 44 kHz sounds and their OSBDs (without the .aif suffix):
*SNDDap_hit_shld (1 sound, referenced in '''OSBDap_hit_shld.grp''', present in level0)
*SNDDzap01 to SNDDzap45 (45 sounds, '''OSBDelec_detail.grp''', in level9 and level10)
*SNDDzap03, SNDDzap04, SNDDzap07, SNDDzap20, SNDDzap26, SNDDzap32 and SNDDzap40
*:([[seven|7]] sounds, '''OSBDelecfire_detail.grp''', in level3, level4, level6, level8, level9, level10 and level18)
-->
<center>[[OBD:SNDD|Back to SNDD]]</center>
<center>[[OBD:SNDD|Back to SNDD]]</center>


{{OBD}}
{{OBD}}