BEWARE! Long post!
*How Keenwave extracts Keen 4-6 type sounds*
The first step is decompressing the sounds. To do this you need the AUDIOHEAD and AUDIODCT files from the executable. If Keenwave cannot find these it runs a search subroutine. You *could* use hard coded values for this (Like Modkeen) but since Keenwave is to work with all versions, it manually searches the executable.
To find the AUDIOHEAD, look for the first dword (4 bytes) in the executable that has the value of the AUDIO.CKx size. This will be the LAST 4-byte entry in the header file. Then just move back in dwords until you come to the value 0 (File start.)
To find AUDIODCT, note that ALL ID DCTs have as the root node '$FD $01 $00 $00 $00 $00' (That is, this is the last few bytes of the 1024 byte file.) The FIRST of these DCTs is always the AUDIO one.
Next KeenWave decompresses the AUDIO data. This is hard to explain because of the difficulty BASIC has in working at the byte level (And due to speed problems I had to drastically modify Napalm's original code.) but works roughly as follows.
All you need from AUDIODCT is the 255 huffman nodes, built into the Huffman tree. (If you don't understand how Huffman works, check online or at the Patch Index under 'File Formats-> Keen 4-6' ) KeenWave stores this as NODE
To get the compressed data note that each dword in AUDIOHED is an address to a sound in AUDIO.CKx, so the first is $00000000, the second $0000000D, and so on. If you do this right, the location in AUDIO.CKx will have a dword giving the length of the UNCOMPRESSED data (So even in a hex editor it's pretty simple to see where sounds start.)
After getting the compressed data start reading it into the Huffman tree, bit by bit, outputting bytes as you go, until you reach the uncompressed length. (For BASIC this is time consuming as I must manually travel down the tree for each byte. I am considering a hash table.)
Hopefully you now have perfectly sensible Raw Data. For IMFs, you can play them in Adplug. Adlib sounds, I can do nothing with yet as I have no idea where to even start.
For PC sounds you have the following structure:
Code: Select all
-------------------------------------------------------------------------------
FILE STRUCTURE:
0 4 Length Length of sound data in bytes
+4 2 Priority Sounds of a high priority interrupt those with equal or lesser priority
(So the 'Got a life' sound will be long, loud and interrupt all other
sounds, while the 'walking' sound will get interrupted all the time.)
+6 x Data Sound data. Each byte is an inverse-frequency datum lasting about
0.07s, much like the Keen 1-3 sounds but using 1-byte entires instead
of 2 (Since PC sounds are less important here.)
+x 1 Terminator $00, ends the sound
-------------------------------------------------------------------------------
What will matter to you is the data, a series of values between 1-255 (Or 0, which is silent.) to play these I use the SOUND command, SOUND [Frequency] [Duration] where the frequency is 1193180 / x * 75 (In this case because the single byte values of Keen 4-6 sounds are 75x less than Keen 1-3 sounds.) and the duration is 1 / 128 * 18.2 (I.e 1/128th of a second.)
Any questions?
What you really need, not what you think you ought to want.