btparser/cparser/WAVTemplate.bt

232 lines
6.1 KiB
Plaintext

//-----------------------------------
//--- 010 Editor v2.0 Binary Template
//
// File: WAVTemplate.bt
// Author: SweetScape Software
// Revision: 1.0
// Purpose: Defines a template for
// parsing WAV audio files.
//-----------------------------------
// Typedefs for the wave file
typedef char ID[4];
// Record whether we have found a format chunk yet
local int haveValidFormat = false;
//-----------------------------------
// Define structures used in WAV files
// Stores the file header information
typedef struct
{
ID groupID;
long size;
ID riffType;
} WAVRIFFHEADER;
// Stores the format information for the file
typedef struct {
ID chunkID;
long chunkSize;
local int pos = FTell();
short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
// Mark that we have found a valid format chunk
haveValidFormat = true;
// Unknown data at the end of the chunk
if( chunkSize > (FTell() - pos) )
uchar unknown[ chunkSize - (FTell() - pos) ];
// Padding so the next chunk starts on an even byte
if( chunkSize & 1 )
uchar padding;
} FORMATCHUNK;
// Stores the actual wave data
typedef struct
{
ID chunkID;
long chunkSize;
// Test if we have a valid format
if( !haveValidFormat )
{
Warning( "File contains no valid WAVE format chunk." );
return -1;
}
// Parse the samples of the data
if( ((format.wBitsPerSample != 8) && (format.wBitsPerSample != 16) && (format.wBitsPerSample != 32))
|| (chunkSize % (int)format.wBlockAlign != 0) )
{
// Unsupported storage method used
unsigned char waveformData[chunkSize];
}
else if( (format.wChannels == 1) && (format.wBitsPerSample == 8) )
{
// Define an array of 8-bit samples - common case
uchar samples[ chunkSize ];
}
else if( (format.wChannels == 1) && (format.wBitsPerSample == 16) )
{
// Define an array of 16-bit samples - common case
short samples[ chunkSize/2 ];
}
else if( (format.wChannels == 1) && (format.wBitsPerSample == 32) )
{
// Define an array of 32-bit samples - common case
int samples[ chunkSize/4 ];
}
else
{
// Define general case sample
struct SAMPLES {
if( format.wBitsPerSample == 8 )
uchar channels[ format.wChannels ];
else if( format.wBitsPerSample == 16 )
short channels[ format.wChannels ];
else if( format.wBitsPerSample == 32 )
int channels[ format.wChannels ];
} samples[ chunkSize / (int)format.wBlockAlign ];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
uchar padding;
} DATACHUNK;
// Stores the size of the wave after decompression
typedef struct
{
ID chunkID;
long chunkSize;
unsigned long uncompressedSize;
} FACTCHUNK;
// Stores a list of cue points or markers to points in the data
typedef struct {
long dwIdentifier;
long dwPosition;
ID fccChunk;
long dwChunkStart;
long dwBlockStart;
long dwSampleOffset;
} CUEPOINT;
typedef struct {
ID chunkID;
long chunkSize;
local int pos = FTell();
long dwCuePoints;
CUEPOINT points[dwCuePoints];
// Unknown data at the end of the chunk
if( chunkSize > (FTell() - pos) )
uchar unknown[ chunkSize - (FTell() - pos) ];
} CUECHUNK;
// Define a list chunk with a set of subchunks
typedef struct {
ID chunkID;
long chunkSize;
char listData[chunkSize];
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
uchar padding;
} LISTSUBCHUNK;
typedef struct {
ID chunkID;
long chunkSize;
local quad pos = FTell();
ID chunkType;
// Read the subchunks
while( FTell() - pos < chunkSize )
LISTSUBCHUNK subchunk;
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
uchar padding;
} LISTCHUNK;
// A chunk which could not be identified
typedef struct {
ID chunkID;
long chunkSize;
uchar unknownData[chunkSize];
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
uchar padding;
} UNKNOWNCHUNK;
//---------------------------------------------
// Define the headers
LittleEndian();
SetBackColor( cLtPurple );
WAVRIFFHEADER header;
// Check for valid header
if( header.groupID != "RIFF" || header.riffType != "WAVE" )
{
Warning( "File is not a valid wave file. Template stopped." );
return -1;
}
// Read the file as a set of chunks
local char tag[5];
local uint size;
while( !FEof() )
{
// Read the chunk tag
ReadBytes( tag, FTell(), 4 );
tag[4] = 0;
// See which chunk this is
switch( tag )
{
case "fmt ":
SetBackColor( cLtGray );
FORMATCHUNK format;
break;
case "data":
SetBackColor( cNone );
DATACHUNK data;
break;
case "fact":
SetBackColor( cLtBlue );
FACTCHUNK fact;
break;
case "cue ":
SetBackColor( cLtGray );
CUECHUNK cue;
break;
case "LIST":
SetBackColor( cLtYellow );
LISTCHUNK list;
break;
default:
// Unknown chunk
size = ReadUInt( FTell()+4 );
Printf( "Encountered unknown chunk '%s' of size %d at position %Ld.\n",
tag, size, FTell() );
SetBackColor( cNone );
UNKNOWNCHUNK unknown;
break;
}
}