//-------------------------------------- //--- 010 Editor Binary Template // // File: FSB5.bt // Author: Simon Pinfold // Purpose: Parses the FSB5 (v0 and v1) audio container. //-------------------------------------- BitfieldDisablePadding(); string OffsetCalcComment(int offset){ string s; SPrintf(s, "Offset = %d from sampleData start", offset * 16); return s; } string FrequencyLookupComment(int value){ switch (value){ case 1: return "8000Hz"; case 2: return "11000Hz"; case 3: return "11025Hz"; case 4: return "16000Hz"; case 5: return "22050Hz"; case 6: return "24000Hz"; case 7: return "32000Hz"; case 8: return "44100Hz"; case 9: return "48000Hz"; default: { Warning("Invalid value for frequency"); return "Unknown"; } } } typedef enum { NONE = 0, PCM8 = 1, PCM16 = 2, PCM24 = 3, PCM32 = 4, PCMFLOAT = 5, GCADPCM = 6, IMAADPCM = 7, VAG = 8, HEVAG = 9, XMA = 10, MPEG = 11, CELT = 12, AT9 = 13, XWMA = 14, VORBIS = 15 } MODE; typedef enum { CHANNELS=1, FREQUENCY=2, LOOP=3, XMASEEK=6, DSPCOEFF=7, XWMADATA=10, VORBISDATA=11 } CHUNK_TYPE; typedef struct { char id[4]; if (id != "FSB5"){ Warning( "File is not FSB5. Template stopped." ); return -1; } int32 version; int32 numSamples; int32 sampleHeaderSize; int32 nameTableSize; int32 dataSize; MODE mode; byte zero[8]; byte hash[16]; byte dummy[8]; if (version == 0) { uint32 unknown ; } } FSOUND_FSB_HEADER_FSB5; typedef struct { uint32 extraParams :1; uint32 frequency :4 ; uint32 twoChannels :1; uint32 dataOffset :28 ; uint32 samples :30; if (extraParams){ // has extra params local int _next = 1; while (_next){ struct { uint32 next :1; uint32 size :24; CHUNK_TYPE type :7; if (type == CHANNELS){ Assert(size == 1, "Channels chunk should be 1 byte"); byte channels; } else if (type == FREQUENCY){ Assert(size == 4, "Frequency chunk should be 4 bytes"); uint32 frequency; } else if (type == LOOP){ Assert(size == 8, "Frequency chunk should be 8 bytes"); struct { uint32 loopstart; uint32 loopend; } loop; } else if (type == XMASEEK){ byte xmaSeek[size]; } else if (type == DSPCOEFF){ byte dspCoefficient[size]; } else if (type == XWMADATA){ byte xwmaData[size]; } else if (type == VORBISDATA){ struct { uint32 crc32; local int _remain = size - 4; while (_remain > 0){ struct { uint32 offset; if ( _remain > 4) uint32 granulePosition; } packetData; _remain -= 8; } //byte unknownData[size-4] ; } vorbis; } else { byte unknownData[size]; } } chunk; _next = chunk.next; } } } FSOUND_FSB_SAMPLE_HEADER; FSOUND_FSB_HEADER_FSB5 header ; struct { local int i; for (i = 0; i < header.numSamples; i++) { FSOUND_FSB_SAMPLE_HEADER sampleHeader; } } sampleHeaders ; if (header.nameTableSize) { local int nameTableStart = FTell(); struct { local int i; for (i = 0; i < header.numSamples; i++) { uint32 nameStart; } for (i = 0; i < header.numSamples; i++) { struct { Assert(nameTableStart + nameTable.nameStart[i] == FTell(), "nameStart did not point to expected start of string"); string name; } name; } } nameTable ; } else { Printf("No name table\n"); } byte pad[(sizeof(header) + header.sampleHeaderSize + header.nameTableSize) - FTell()]; struct { local int dataStart = FTell(); local int dataEnd = dataStart + header.dataSize; local int i, start, end; for (i = 0; i < header.numSamples; i++) { end = dataEnd; if (i+1 < header.numSamples) end = dataStart + sampleHeaders.sampleHeader[i+1].dataOffset * 16; start = dataStart + sampleHeaders.sampleHeader[i ].dataOffset * 16; Assert(start == FTell(), "Wrong length calculated for sample data"); struct { if (header.mode == VORBIS){ while (!FEof()){ struct { ushort size; if (!size) return 0; ubyte audio :1; ubyte r :7; ubyte data[size-1]; } packet; } } else byte bytes[end - start] ; } sample; } } sampleData;