![]() |
|||
| EXTRACTOR | .RU – версия 2.2 |
||
![]() |
|
Что у нас есть? Это тоже интересно надежные маслонаполненные радиаторы - полная информация |
Статьи и описания форматов игровых файлов Electronic Arts Audio File Formats DescriptionЭта статья относится к играм: Автор материала: Valery V. Anisimovsky (samael@avn.mccme.ru) In this document I'll try to describe audio file formats used in many (older) Electronic Arts games. Described are formats for music, sound effects, speech and movie soundtracks. The games using these formats include: NBA Live'96, NHL'96, FIFA'96, The Need For Speed, NHL'97. Maybe many more, e.g.: NHL'95. 1. ASF/AS4 Music Files The music in many Electronic Arts games is in .ASF/.AS4 stand-alone files. These files have the block structure analoguous to RIFF. Namely, these files are divided into blocks (without any global file header like RIFFs have). Each block has the following header: struct ASFBlockHeader
{
char szBlockID[4];
DWORD dwSize;
};szBlockID -- string ID for the block. struct EACSHeader
{
char szID[4];
DWORD dwSampleRate;
BYTE bBits;
BYTE bChannels;
BYTE bCompression;
BYTE bType;
DWORD dwNumSamples;
DWORD dwLoopStart;
DWORD dwLoopLength;
DWORD dwDataStart;
DWORD dwUnknown;
};szID -- ID string, always "EACS". struct ASFChunkHeader
{
DWORD dwOutSize;
LONG lIndexLeft;
LONG lIndexRight;
LONG lCurSampleLeft;
LONG lCurSampleRight;
};dwOutSize -- size of uncompressed audio data in this chunk (in samples). 2. KSF Music Files Some EA games use other format for music/speech files: .KSF. These files begin with "KWK`" ID string. Following this ID, comes PATl header. It begins with "PATl" ID string and its size is 56 bytes (always?) including its ID string. After PATl header comes TMpl header: struct TMplHeader
{
char szID[4];
BYTE bUnknown1;
BYTE bBits;
BYTE bChannels;
BYTE bCompression;
WORD wUnknown2;
WORD wSampleRate;
DWORD dwNumSamples; // ???
BYTE bUnknown3[20];
};szID -- string ID, always "TMpl". 3. IMA ADPCM Decompression Algorithm During the decompression four LONG variables must be maintained for stereo stream: lIndexLeft, lIndexRight, lCurSampleLeft, lCurSampleRight and two -- for mono stream: lIndex, lCurSample. At the beginning of each "1SNd" data block and at the beginning of the file -- when processing "1SNh" block -- you must initialize these variables using the values in ASFChunkHeader. BYTE Input; // current byte of compressed data BYTE Code; LONG Delta; Code=HINIBBLE(Input); // get HIGHER 4-bit nibble Delta=StepTable[lIndexLeft]>>3; if (Code & 4) Delta+=StepTable[lIndexLeft]; if (Code & 2) Delta+=StepTable[lIndexLeft]>>1; if (Code & 1) Delta+=StepTable[lIndexLeft]>>2; if (Code & 8) // sign bit lCurSampleLeft-=Delta; else lCurSampleLeft+=Delta; // clip sample if (lCurSampleLeft>32767) lCurSampleLeft=32767; else if (lCurSampleLeft<-32768) lCurSampleLeft=-32768; lIndexLeft+=IndexAdjust[Code]; // adjust index // clip index if (lIndexLeft<0) lIndexLeft=0; else if (lIndexLeft>88) lIndexLeft=88; Code=LONIBBLE(Input); // get LOWER 4-bit nibble Delta=StepTable[lIndexRight]>>3; if (Code & 4) Delta+=StepTable[lIndexRight]; if (Code & 2) Delta+=StepTable[lIndexRight]>>1; if (Code & 1) Delta+=StepTable[lIndexRight]>>2; if (Code & 8) // sign bit lCurSampleRight-=Delta; else lCurSampleRight+=Delta; // clip sample if (lCurSampleRight>32767) lCurSampleRight=32767; else if (lCurSampleRight<-32768) lCurSampleRight=-32768; lIndexRight+=IndexAdjust[Code]; // adjust index // clip index if (lIndexRight<0) lIndexRight=0; else if (lIndexRight>88) lIndexRight=88; // Now we've got lCurSampleLeft and lCurSampleRight which form one stereo // sample and all is set for the next input byte... Output((SHORT)lCurSampleLeft,(SHORT)lCurSampleRight); // send the sample to output HINIBBLE and LONIBBLE are higher and lower 4-bit nibbles: #define HINIBBLE(byte) ((byte) >> 4) #define LONIBBLE(byte) ((byte) & 0x0F) Note that depending on your compiler you may need to use additional nibble separation in these defines, e.g. (((byte) >> 4) & 0x0F). Code=HINIBBLE(Input); // get HIGHER 4-bit nibble Delta=StepTable[lIndex]>>3; if (Code & 4) Delta+=StepTable[lIndex]; if (Code & 2) Delta+=StepTable[lIndex]>>1; if (Code & 1) Delta+=StepTable[lIndex]>>2; if (Code & 8) // sign bit lCurSample-=Delta; else lCurSample+=Delta; // clip sample if (lCurSample>32767) lCurSample=32767; else if (lCurSample<-32768) lCurSample=-32768; lIndex+=IndexAdjust[Code]; // adjust index // clip index if (lIndex<0) lIndex=0; else if (lIndex>88) lIndex=88; Output((SHORT)lCurSample); // send the sample to output Code=LONIBBLE(Input); // get LOWER 4-bit nibble // ...just the same as above for lower nibble Note that HIGHER nibble is processed first for mono sound and corresponds to LEFT channel for stereo. 4. IMA ADPCM Tables LONG IndexAdjust[]=
{
-1,
-1,
-1,
-1,
2,
4,
6,
8,
-1,
-1,
-1,
-1,
2,
4,
6,
8
};
LONG StepTable[]=
{
7, 8, 9, 10, 11, 12, 13, 14, 16,
17, 19, 21, 23, 25, 28, 31, 34, 37,
41, 45, 50, 55, 60, 66, 73, 80, 88,
97, 107, 118, 130, 143, 157, 173, 190, 209,
230, 253, 279, 307, 337, 371, 408, 449, 494,
544, 598, 658, 724, 796, 876, 963, 1060, 1166,
1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749,
3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};5. TGV Movie Soundtracks .TGV movies have the block structure analoguous to that of ASF/AS4. 6. Sound/Speech Files: .EAS, .SPH Some sounds and all speech are usually in .EAS and .SPH files. 7. Sound Effects in .BNK/.CRD Files Most of sound effects are stored in .BNK and .CRD resource files. Those .BNKs and .CRDs may contain several sounds. They begin with some seemingly meaningless data, but after some junk of that data (typically starting at position 0x228, but not necessarily) come several EACS headers describing all sounds in .BNK/.CRD. Each EACS header has almost the same format as described above with some minor changes (some fields have different placement): struct EACSHeader
{
char szID[4];
DWORD dwSampleRate;
BYTE bBits;
BYTE bChannels;
BYTE bCompression;
BYTE bType;
DWORD dwLoopStart;
DWORD dwLoopLength;
DWORD dwNumSamples;
DWORD dwDataStart;
DWORD dwUnknown;
};and with the same two additions just as for .EAS/.SPH speech/sound: (bType) is always 0xFF, (dwDataStart) is the starting position of sound data relative to the beginning of the .BNK/.CRD file containing that sound. So, what you need to do is just search in .BNK/.CRD for "EACS" ID string and read EACSHeader from the position where you found "EACS". And the same for all sounds contained within .BNK/.CRD. The sound data itself (for each EACS header describing it) starts at (dwDataStart) and its size may be computed using (dwNumSamples) EACSHeader field (for example) with the following formula:
8. Credits Vladan Bato ()
|
| © | 2000—2010 «EXTRACTOR.ru» — игровые ресурсы: распаковка музыки и графики, конверторы форматов и многое другое… Наши спонсоры: Свадебные автомобили напрокат и свадьба в замке быстро. ; Оптимизация сайтов |