forked from HearthSim/python-fsb5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FSB5.bt
201 lines (176 loc) · 5.48 KB
/
FSB5.bt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//--------------------------------------
//--- 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<uint32> {
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<uint32> {
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 <format=hex, bgcolor=0x0000ff>;
}
} FSOUND_FSB_HEADER_FSB5;
typedef struct {
uint32 extraParams :1;
uint32 frequency :4 <comment=FrequencyLookupComment>;
uint32 twoChannels :1;
uint32 dataOffset :28 <comment=OffsetCalcComment>;
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] <format=hex>;
} vorbis;
} else {
byte unknownData[size];
}
} chunk;
_next = chunk.next;
}
}
} FSOUND_FSB_SAMPLE_HEADER;
FSOUND_FSB_HEADER_FSB5 header <bgcolor=0xffbf00>;
struct {
local int i;
for (i = 0; i < header.numSamples; i++) {
FSOUND_FSB_SAMPLE_HEADER sampleHeader;
}
} sampleHeaders <bgcolor=0x00ffff>;
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 <bgcolor=0x33ff00>;
} 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] <bgcolor=cLtGray>;
} sample;
}
} sampleData;