|
|
Line 175: |
Line 175: |
| :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 287: |
Line 267: |
|
| |
|
|
| |
|
| <!--
| |
| 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}} |