Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/tools/sdk-tools/adpcm/vadpcm_dec.c
7861 views
1
#include <unistd.h>
2
#include <assert.h>
3
#include <string.h>
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <signal.h>
7
#include <fcntl.h>
8
#include "vadpcm.h"
9
10
static void int_handler(s32 sig)
11
{
12
s32 flags;
13
14
flags = fcntl(STDIN_FILENO, F_GETFL, 0);
15
flags &= ~FNDELAY;
16
fcntl(STDIN_FILENO, F_SETFL, flags);
17
exit(0);
18
}
19
20
static char usage[] = "bitfile";
21
22
#ifdef __sgi
23
24
// Declaring a sigaction like this is wildly unportable; you're supposed to
25
// assign members one by one in code. We do that in the non-SGI case.
26
static struct sigaction int_act = {
27
/* sa_flags = */ SA_RESTART,
28
/* sa_handler = */ &int_handler,
29
/* sa_mask = */ 0,
30
};
31
32
#endif
33
34
s32 main(s32 argc, char **argv)
35
{
36
s32 c;
37
u8 cc;
38
u8 doloop = 0;
39
s16 order;
40
s16 version;
41
s16 nloops;
42
s16 npredictors;
43
s32 flags;
44
s32 ***coefTable = NULL;
45
s32 i;
46
s32 j;
47
s32 *outp;
48
s32 *state;
49
s32 done = 0;
50
s32 num;
51
u32 ts;
52
s32 soundPointer;
53
s32 cType;
54
s32 offset;
55
s32 currPos = 0;
56
s32 nSamples;
57
s32 framePos;
58
s32 loopBegin;
59
s32 left;
60
ALADPCMloop *aloops;
61
Chunk FormChunk;
62
ChunkHeader Header;
63
CommonChunk CommChunk;
64
SoundDataChunk SndDChunk;
65
char *ChunkName;
66
FILE *ifile;
67
char *progname = argv[0];
68
69
#ifndef __sgi
70
nloops = 0;
71
#endif
72
73
if (argc < 2)
74
{
75
fprintf(stderr, "%s %s\n", progname, usage);
76
exit(1);
77
}
78
79
while ((c = getopt(argc, argv, "l")) != -1)
80
{
81
switch (c)
82
{
83
case 'l':
84
doloop = 1;
85
break;
86
}
87
}
88
89
argv += optind - 1;
90
if ((ifile = fopen(argv[1], MODE_READ)) == NULL)
91
{
92
fprintf(stderr, "%s: bitstream file [%s] could not be opened\n", progname, argv[1]);
93
exit(1);
94
}
95
96
state = malloc(16 * sizeof(int));
97
for (i = 0; i < 16; i++)
98
{
99
state[i] = 0;
100
}
101
102
fread(&FormChunk, sizeof(FormChunk), 1, ifile);
103
BSWAP32(FormChunk.ckID)
104
BSWAP32(FormChunk.formType)
105
if ((FormChunk.ckID != 0x464f524d) || (FormChunk.formType != 0x41494643)) // FORM, AIFC
106
{
107
fprintf(stderr, "%s: [%s] is not an AIFF-C File\n", progname, argv[1]);
108
exit(1);
109
}
110
111
while (!done)
112
{
113
num = fread(&Header, sizeof(Header), 1, ifile);
114
if (num <= 0)
115
{
116
done = 1;
117
break;
118
}
119
BSWAP32(Header.ckID)
120
BSWAP32(Header.ckSize)
121
122
Header.ckSize++, Header.ckSize &= ~1;
123
switch (Header.ckID)
124
{
125
case 0x434f4d4d: // COMM
126
offset = ftell(ifile);
127
num = fread(&CommChunk, sizeof(CommChunk), 1, ifile);
128
if (num <= 0)
129
{
130
fprintf(stderr, "%s: error parsing file [%s]\n", progname, argv[1]);
131
done = 1;
132
}
133
BSWAP16(CommChunk.numChannels)
134
BSWAP16(CommChunk.numFramesH)
135
BSWAP16(CommChunk.numFramesL)
136
BSWAP16(CommChunk.sampleSize)
137
BSWAP16(CommChunk.compressionTypeH)
138
BSWAP16(CommChunk.compressionTypeL)
139
cType = (CommChunk.compressionTypeH << 16) + CommChunk.compressionTypeL;
140
if (cType != 0x56415043) // VAPC
141
{
142
fprintf(stderr, "%s: file [%s] is of the wrong compression type.\n", progname, argv[1]);
143
exit(1);
144
}
145
if (CommChunk.numChannels != 1)
146
{
147
fprintf(stderr, "%s: file [%s] contains %ld channels, only 1 channel supported.\n", progname, argv[1], (long) CommChunk.numChannels);
148
exit(1);
149
}
150
if (CommChunk.sampleSize != 16)
151
{
152
fprintf(stderr, "%s: file [%s] contains %ld bit samples, only 16 bit samples supported.\n", progname, argv[1], (long) CommChunk.sampleSize);
153
exit(1);
154
}
155
nSamples = (CommChunk.numFramesH << 16) + CommChunk.numFramesL;
156
fseek(ifile, offset + Header.ckSize, SEEK_SET);
157
break;
158
159
case 0x53534e44: // SSND
160
offset = ftell(ifile);
161
fread(&SndDChunk, sizeof(SndDChunk), 1, ifile);
162
BSWAP32(SndDChunk.offset)
163
BSWAP32(SndDChunk.blockSize)
164
// The assert error messages specify line numbers 165/166. Match
165
// that using a #line directive.
166
#ifdef __sgi
167
# line 164
168
#endif
169
assert(SndDChunk.offset == 0);
170
assert(SndDChunk.blockSize == 0);
171
soundPointer = ftell(ifile);
172
fseek(ifile, offset + Header.ckSize, SEEK_SET);
173
break;
174
175
case 0x4150504c: // APPL
176
offset = ftell(ifile);
177
fread(&ts, sizeof(u32), 1, ifile);
178
BSWAP32(ts)
179
if (ts == 0x73746f63) // stoc
180
{
181
ChunkName = ReadPString(ifile);
182
if (strcmp("VADPCMCODES", ChunkName) == 0)
183
{
184
fread(&version, sizeof(s16), 1, ifile);
185
BSWAP16(version)
186
if (version != 1)
187
{
188
fprintf(stderr, "Non-identical codebook chunk versions\n");
189
}
190
readaifccodebook(ifile, &coefTable, &order, &npredictors);
191
}
192
else if (strcmp("VADPCMLOOPS", ChunkName) == 0)
193
{
194
fread(&version, sizeof(s16), 1, ifile);
195
BSWAP16(version)
196
if (version != 1)
197
{
198
fprintf(stderr, "Non-identical loop chunk versions\n");
199
}
200
aloops = readlooppoints(ifile, &nloops);
201
}
202
}
203
fseek(ifile, offset + Header.ckSize, SEEK_SET);
204
break;
205
206
default:
207
// We don't understand this chunk. Skip it.
208
fseek(ifile, Header.ckSize, SEEK_CUR);
209
break;
210
}
211
}
212
213
if (coefTable == NULL)
214
{
215
// @bug should use progname; argv[0] may be an option
216
fprintf(stderr, "%s: Codebook missing from bitstream [%s]\n", argv[0], argv[1]);
217
exit(1);
218
}
219
220
outp = malloc(16 * sizeof(s32));
221
for (i = 0; i < order; i++)
222
{
223
outp[15 - i] = 0;
224
}
225
226
fseek(ifile, soundPointer, SEEK_SET);
227
if (doloop && nloops > 0)
228
{
229
#ifndef __sgi
230
struct sigaction int_act;
231
int_act.sa_flags = SA_RESTART;
232
int_act.sa_handler = int_handler;
233
sigemptyset(&int_act.sa_mask);
234
#endif
235
236
sigaction(SIGINT, &int_act, NULL);
237
flags = fcntl(STDIN_FILENO, F_GETFL, 0);
238
flags |= FNDELAY;
239
fcntl(STDIN_FILENO, F_SETFL, flags);
240
for (i = 0; i < nloops; i++)
241
{
242
while (currPos < aloops[i].end)
243
{
244
left = aloops[i].end - currPos;
245
vdecodeframe(ifile, outp, order, coefTable);
246
writeout(stdout, left < 16 ? left : 16, outp, outp, 1);
247
currPos += 16;
248
}
249
250
while (read(STDIN_FILENO, &cc, 1) == 0)
251
{
252
framePos = (aloops[i].start >> 4) + 1;
253
fseek(ifile, (framePos * 9) + soundPointer, SEEK_SET);
254
for (j = 0; j < 16; j++)
255
{
256
outp[j] = aloops[i].state[j];
257
}
258
loopBegin = aloops[i].start & 0xf;
259
writeout(stdout, 16 - loopBegin, outp + loopBegin, outp + loopBegin, 1);
260
currPos = framePos * 16;
261
while (currPos < aloops[i].end)
262
{
263
left = aloops[i].end - currPos;
264
vdecodeframe(ifile, outp, order, coefTable);
265
writeout(stdout, left < 16 ? left : 16, outp, outp, 1);
266
currPos += 16;
267
}
268
}
269
270
left = 16 - left;
271
if (left != 0)
272
{
273
writeout(stdout, left, &outp[left], &outp[left], 1);
274
}
275
276
while (currPos < nSamples)
277
{
278
vdecodeframe(ifile, outp, order, coefTable);
279
left = nSamples - currPos;
280
writeout(stdout, left < 16 ? left : 16, outp, outp, 1);
281
currPos += 16;
282
}
283
284
flags = fcntl(STDIN_FILENO, F_GETFL, 0);
285
flags &= ~FNDELAY;
286
fcntl(STDIN_FILENO, F_SETFL, flags);
287
}
288
}
289
else
290
{
291
while (currPos < nSamples)
292
{
293
vdecodeframe(ifile, outp, order, coefTable);
294
writeout(stdout, 16, outp, outp, 1);
295
currPos += 16;
296
}
297
}
298
299
fclose(ifile);
300
return 0;
301
}
302
303