====== Overview ======
The PC Engine CD hardware contains ADPCM sampling capabilities using the Oki ADPCM sound format. This page is a brief explanation of how to convert WAV files, store them in the sample RAM, and play them back using HuC.
A more detailed hardware explanation can be found in the sound section of this wiki. (Link to follow once it exists, lol)
You can store up to 64k worth of samples stored in the sample RAM at any given time.
**A brief note about that: You can use this sample RAM for other purposes, with people often sticking spare graphical data in there!**
====== SoX and VoX ======
The Oki ADPCM format is identical to the Intel/Dialogic VOX format. [[http://sox.sourceforge.net/|The 'Sound eXchange' utility ('sox')]] supports this format and the non-standard sample rates the PCE uses.
The VOX format has no header or other information to specify the sample rate, so that must be explicitly stated during file conversion.
Some examples are as follows:
; Convert 8 KHz ADPCM data to WAV file
sox -r 8000 test.vox test.wav
; Convert WAV file to 32 KHz ADPCM data
sox music.wav -r 32000 music.vox
The resulting header-less VOX file can be directly included into a program as binary data and stored to ADPCM RAM for playback. We will do this using the HuC CD library. For more information on this library, refer to the HuC C library reference that is included here and also came with your HuC download.
====== Loading and Playing the ADPCM sounds ======
Once you have created the appropriate files from the SoX utility, they will need loaded into ADPCM RAM using the CD programming library. There are a few general setup concepts that will make this easier.
This brief explanation assumes you are using the "overlay" concept, in which your APDCM samples are created as overlay "tracks". This is required to use the ADPCM loading library call that is part of HuC.
* First, you should put your ADPCM file sizes (in bytes) in an array. We will need these values to calculate some things for loading and playing the sounds back.
* In addition to the byte size, you also need to figure out how many sectors each sound will take. This could also be calculated ahead of time and stored in a table as well, but we are lazy. This is setup code that should run once when a level or entire game loads, so enjoy the chance to be lazy. Calculate it with a loop, and store it in a table dynamically.
* The formula is ((bytesize + 2047) / 2048)
. We are rounding to the nearest 2K block
* Next, we also suggest creating a "Starting Point" table, which would be the byte value offset where each sound starts in RAM. Remember, these are all loaded contiguously as one giant blob. If you don't start in the right spot, or you go too far, you'll be cutting sounds off, or playing extra stuff. This is generally what all of the tables we're setting up are for.
* The start point table is easy. It is just "previous startpoint + current sound's number of bytes + 1". The caveat being, the first entry in your table should be -1 so that the first track starts in the right spot, and the calculating works right.
* From there you have all of the data needed to load your data, and to play them back later.
===== Example of Loading an ADPCM sample using above explanation (note: the calculation functions have been omitted.) =====
/* assumes you are in a for loop, and used a #define for the starting track number*/
ad_trans( STARTING_TRACK_NUMBER, 0, numSectors[i], pcmStartPoint[i] );
===== Example of playing an ADPCM sample =====
ad_play( pcmStartPoint[trackToPlay], numBytes[trackToPlay], ADPCM_8KHZ, 0 );
====== A note about sample rates ======
While working on Insanity, we found that samples were playing ... not as expected. Some document we had read gave the following formula for sample rates, which must be specified when you play a track back.
This formula was documented as real_frequency_in_khz = 32 / (16 - 'freq')
If anyone has a better explanation of this, or decides that it's bad information, please update!
You can also just put a value in (2,4,8,12,16, etc.) and play the stupid thing back until it sounds like you wanted it to.