btparser/cparser/SF2Template.bt

823 lines
22 KiB
Plaintext

//-----------------------------------
//--- 010 Editor v2.0 Binary Template
//
// File: SF2Template.bt
// Author: gocha
// Revision: 1.1
// Purpose: Defines a template for
// parsing SF2 (SoundFont 2.04) files.
// Tested with: Polyphone.
//-----------------------------------
typedef CHAR ID[4];
local int cGrayZone = 0xd9dadc;
local int cOrange = 0xaae3f9;
local int cSytrus = 0xaaf7ff;
local int cGreenGreens = 0xaaecdf;
local int cCureMarine = 0xffe1ce;
local int cCureMarine_Alt = 0xfdf1dd;
local int cPurpleMadness = 0xeec3dd;
local int cPurpleMadness_Alt = 0xffe1fa;
//-----------------------------------
// Define structures used in SF2 files
// SoundFont 2 RIFF File Format Type Definitions
typedef enum <WORD> {
monoSample = 1,
rightSample = 2,
leftSample = 4,
linkedSample = 8,
RomMonoSample = 0x8001,
RomRightSample = 0x8002,
RomLeftSample = 0x8004,
RomLinkedSample = 0x8008,
} SFSampleLink;
typedef enum <WORD> {
startAddrsOffset = 0,
endAddrsOffset = 1,
startloopAddrsOffset = 2,
endloopAddrsOffset = 3,
startAddrsCoarseOffset = 4,
modLfoToPitch = 5,
vibLfoToPitch = 6,
modEnvToPitch = 7,
initialFilterFc = 8,
initialFilterQ = 9,
modLfoToFilterFc = 10,
modEnvToFilterFc = 11,
endAddrsCoarseOffset = 12,
modLfoToVolume = 13,
chorusEffectsSend = 15,
reverbEffectsSend = 16,
pan = 17,
delayModLFO = 21,
freqModLFO = 22,
delayVibLFO = 23,
freqVibLFO = 24,
delayModEnv = 25,
attackModEnv = 26,
holdModEnv = 27,
decayModEnv = 28,
sustainModEnv = 29,
releaseModEnv = 30,
keynumToModEnvHold = 31,
keynumToModEnvDecay = 32,
delayVolEnv = 33,
attackVolEnv = 34,
holdVolEnv = 35,
decayVolEnv = 36,
sustainVolEnv = 37,
releaseVolEnv = 38,
keynumToVolEnvHold = 39,
keynumToVolEnvDecay = 40,
instrument = 41,
keyRange = 43,
velRange = 44,
startloopAddrsCoarseOffset = 45,
keynum = 46,
velocity = 47,
initialAttenuation = 48,
endloopAddrsCoarseOffset = 50,
coarseTune = 51,
fineTune = 52,
sampleID = 53,
sampleModes = 54,
scaleTuning = 56,
exclusiveClass = 57,
overridingRootKey = 58,
endOper = 60,
} SFGenerator;
typedef enum <BYTE> {
noController = 0,
noteOnVelocity = 2,
noteOnKeyNumber = 3,
polyPressure = 10,
channelPressure = 13,
pitchWheel = 14,
pitchWheelSensitivity = 16,
link = 127,
} SFGeneralController;
typedef enum <BYTE> {
generalController = 0,
midiController = 1,
} SFControllerPalette;
typedef enum <BYTE> {
increase = 0,
decrease = 1,
} SFControllerDirection;
typedef enum <BYTE> {
unipolar = 0,
bipolar = 1,
} SFControllerPolarity;
typedef enum <BYTE> {
linearType = 0,
concaveType = 1,
convexType = 2,
switchType = 3,
} SFControllerType;
typedef struct {
union {
SFGeneralController general : 7;
BYTE midi : 7;
} index;
SFControllerPalette palette : 1;
SFControllerDirection direction : 1;
SFControllerPolarity polarity : 1;
SFControllerType type : 6;
} SFModulator;
typedef enum <WORD> {
linear = 0,
absoluteValue = 2,
} SFTransform;
typedef struct
{
BYTE byLo;
BYTE byHi;
} rangesType;
typedef union
{
rangesType ranges;
SHORT shAmount;
WORD wAmount;
} genAmountType;
// SoundFont 2 RIFF File Format Level 3
typedef struct {
WORD wMajor;
WORD wMinor;
} sfVersionTag;
typedef struct {
CHAR achPresetName[20];
WORD wPreset;
WORD wBank;
WORD wPresetBagNdx;
DWORD dwLibrary;
DWORD dwGenre;
DWORD dwMorphology;
} sfPresetHeader;
typedef struct
{
WORD wGenNdx;
WORD wModNdx;
} sfPresetBag;
typedef struct
{
SFModulator sfModSrcOper;
SFGenerator sfModDestOper;
SHORT modAmount;
SFModulator sfModAmtSrcOper;
SFTransform sfModTransOper;
} sfModList;
typedef struct
{
SFGenerator sfGenOper;
genAmountType genAmount;
} sfGenList;
typedef struct
{
CHAR achInstName[20];
WORD wInstBagNdx;
} sfInst;
typedef struct
{
WORD wInstGenNdx;
WORD wInstModNdx;
} sfInstBag;
typedef struct
{
SFModulator sfModSrcOper;
SFGenerator sfModDestOper;
SHORT modAmount;
SFModulator sfModAmtSrcOper;
SFTransform sfModTransOper;
} sfInstModList;
typedef struct
{
SFGenerator sfGenOper;
genAmountType genAmount;
} sfInstGenList;
typedef struct
{
CHAR achSampleName[20];
DWORD dwStart;
DWORD dwEnd;
DWORD dwStartloop;
DWORD dwEndloop;
DWORD dwSampleRate;
BYTE byOriginalKey;
CHAR chCorrection;
WORD wSampleLink;
SFSampleLink sfSampleType;
} sfSample;
// SoundFont 2 RIFF File Format Level 2
typedef struct {
ID chunkID;
DWORD chunkSize;
CHAR text[chunkSize];
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} ZSTRCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
if( FileSize() - pos >= sizeof( sfVersionTag ) ) {
sfVersionTag version;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} sfVersionTagCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
SHORT samples[chunkSize / 2];
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} smplCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
BYTE samples[chunkSize];
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} sm24Ck;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfPresetHeader ) ) {
sfPresetHeader header;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} phdrCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfPresetBag ) ) {
sfPresetBag bag;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} pbagCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfModList ) ) {
sfModList mod;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} pmodCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfGenList ) ) {
sfGenList gen;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} pgenCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfInst ) ) {
sfInst inst;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} instCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfInstBag ) ) {
sfInstBag bag;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} ibagCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfInstModList ) ) {
sfInstModList mod;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} imodCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfInstGenList ) ) {
sfInstGenList gen;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} igenCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
while( chunkSize - (FTell() - pos) >= sizeof( sfSample ) ) {
sfSample sample;
}
local int unknownDataSize = chunkSize - (FTell() - pos);
if( unknownDataSize > 0 ) {
Printf( "Encountered unknown data in chunk '%s' of size %d at position 0x%LX.\n",
chunkID, unknownDataSize, FTell() );
UCHAR unknownData[unknownDataSize];
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} shdrCk;
// SoundFont 2 RIFF File Format Level 2
typedef struct {
ID chunkID;
DWORD chunkSize;
CHAR data[chunkSize];
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} UNKNOWNLISTSUBCHUNK;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
ID chunkType;
// Read the subchunks
local char tag[5];
local DWORD size;
while( FTell() - pos < chunkSize )
{
// Read the chunk tag
ReadBytes( tag, FTell(), 4 );
tag[4] = 0;
// Read the chunk size
size = ReadUInt( FTell() + 4 );
if( FTell() - pos + size > chunkSize ){
Printf( "Chunk '%s' of size %d at position 0x%LX exceeds the parent chunk size boundary.\n", tag, size, FTell() );
return -1;
}
// See which subchunk this is
switch( tag )
{
case "ifil":
SetBackColor( cOrange );
sfVersionTagCk ifil;
break;
case "isng":
SetBackColor( cOrange );
ZSTRCk isng;
break;
case "INAM":
SetBackColor( cOrange );
ZSTRCk INAM;
break;
case "iver":
SetBackColor( cSytrus );
sfVersionTagCk iver;
break;
case "ICRD":
SetBackColor( cSytrus );
ZSTRCk ICRD;
break;
case "IENG":
SetBackColor( cSytrus );
ZSTRCk IENG;
break;
case "IPRD":
SetBackColor( cSytrus );
ZSTRCk IPRD;
break;
case "ICOP":
SetBackColor( cSytrus );
ZSTRCk ICOP;
break;
case "ICMT":
SetBackColor( cSytrus );
ZSTRCk ICMT;
break;
case "ISFT":
SetBackColor( cSytrus );
ZSTRCk ISFT;
break;
default:
// Unknown chunk
Printf( "Encountered unknown chunk '%s' of size %d at position 0x%LX.\n",
tag, size, FTell() );
SetBackColor( cNone );
UNKNOWNLISTSUBCHUNK chunk;
break;
}
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} INFOCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
ID chunkType;
// Read the subchunks
local char tag[5];
local DWORD size;
while( FTell() - pos < chunkSize )
{
// Read the chunk tag
ReadBytes( tag, FTell(), 4 );
tag[4] = 0;
// Read the chunk size
size = ReadUInt( FTell() + 4 );
if( FTell() - pos + size > chunkSize ){
Printf( "Chunk '%s' of size %d at position 0x%LX exceeds the parent chunk size boundary.\n", tag, size, FTell() );
return -1;
}
// See which subchunk this is
switch( tag )
{
case "smpl":
SetBackColor( cGreenGreens );
smplCk smpl;
break;
case "sm24":
SetBackColor( cGreenGreens );
sm24Ck sm24;
break;
default:
// Unknown chunk
Printf( "Encountered unknown chunk '%s' of size %d at position 0x%LX.\n",
tag, size, FTell() );
SetBackColor( cNone );
UNKNOWNLISTSUBCHUNK chunk;
break;
}
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} sdtaCk;
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
ID chunkType;
// Read the subchunks
local char tag[5];
local DWORD size;
while( FTell() - pos < chunkSize )
{
// Read the chunk tag
ReadBytes( tag, FTell(), 4 );
tag[4] = 0;
// Read the chunk size
size = ReadUInt( FTell() + 4 );
if( FTell() - pos + size > chunkSize ){
Printf( "Chunk '%s' of size %d at position 0x%LX exceeds the parent chunk size boundary.\n", tag, size, FTell() );
return -1;
}
// See which subchunk this is
switch( tag )
{
case "phdr":
SetBackColor( cCureMarine );
phdrCk phdr;
break;
case "pbag":
SetBackColor( cCureMarine_Alt );
pbagCk pbag;
break;
case "pmod":
SetBackColor( cCureMarine );
pmodCk pmod;
break;
case "pgen":
SetBackColor( cCureMarine_Alt );
pgenCk pgen;
break;
case "inst":
SetBackColor( cPurpleMadness );
instCk inst;
break;
case "ibag":
SetBackColor( cPurpleMadness_Alt );
ibagCk ibag;
break;
case "imod":
SetBackColor( cPurpleMadness );
imodCk imod;
break;
case "igen":
SetBackColor( cPurpleMadness_Alt );
igenCk igen;
break;
case "shdr":
SetBackColor( cSytrus );
shdrCk shdr;
break;
default:
// Unknown chunk
Printf( "Encountered unknown chunk '%s' of size %d at position 0x%LX.\n",
tag, size, FTell() );
SetBackColor( cNone );
UNKNOWNLISTSUBCHUNK subchunk;
break;
}
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} pdtaCk;
// SoundFont 2 RIFF File Format Level 1
typedef struct {
ID chunkID;
DWORD chunkSize;
local quad pos = FTell();
ID chunkType;
// Read the subchunks
local char tag[5];
local DWORD size;
while( FTell() - pos < chunkSize )
{
// Read the chunk tag
ReadBytes( tag, FTell(), 4 );
tag[4] = 0;
// Read the chunk size
size = ReadUInt( FTell() + 4 );
if( FTell() - pos + size > chunkSize ){
Printf( "Chunk '%s' of size %d at position 0x%LX exceeds the parent chunk size boundary.\n", tag, size, FTell() );
return -1;
}
UNKNOWNLISTSUBCHUNK subchunk;
}
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} UNKNOWNLISTCHUNK;
typedef struct {
ID chunkID;
DWORD chunkSize;
UCHAR unknownData[chunkSize];
// Padding so the next chunk starts on an even byte
if( (chunkSize & 1) && (FTell() < FileSize()) )
UCHAR padding;
} UNKNOWNCHUNK;
// SoundFont 2 RIFF File Format Level 0
typedef struct
{
ID groupID;
DWORD size;
ID riffType;
} RIFFHEADER;
//---------------------------------------------
// Define the headers
local quad riff_pos = FTell();
LittleEndian();
SetBackColor( cGrayZone );
RIFFHEADER header;
// Check for valid header
if( header.groupID != "RIFF" || header.riffType != "sfbk" )
{
Warning( "File is not a valid SF2 file. Template stopped." );
return -1;
}
// Read the file as a set of chunks
local char tag[5];
local DWORD size;
local char list_tag[5];
while( FTell() + 8 <= FileSize() && FTell() - riff_pos != header.size + 8 )
{
// Read the chunk tag
ReadBytes( tag, FTell(), 4 );
tag[4] = 0;
// Read the chunk size
size = ReadUInt( FTell() + 4 );
// See which chunk this is
switch( tag )
{
case "LIST":
// Read the chunk tag
ReadBytes( list_tag, FTell() + 8, 4 );
list_tag[4] = 0;
switch( list_tag )
{
case "INFO":
SetBackColor( cGrayZone );
INFOCk INFO;
break;
case "sdta":
SetBackColor( cGrayZone );
sdtaCk sdta;
break;
case "pdta":
SetBackColor( cGrayZone );
pdtaCk pdta;
break;
default:
SetBackColor( cNone );
UNKNOWNLISTCHUNK list;
break;
}
break;
default:
// Unknown chunk
Printf( "Encountered unknown chunk '%s' of size %d at position 0x%LX.\n",
tag, size, FTell() );
SetBackColor( cNone );
UNKNOWNCHUNK unknown;
break;
}
}
// Verify the whole file size
local quad actual_size = FTell() - riff_pos;
if( actual_size != 8 + header.size )
{
Printf( "RIFF file size mismatch (header value %Ld, actual size %Ld).\n", header.size, actual_size - 8 );
return -1;
}