Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/tools/aiff_extract_codebook.c
7854 views
1
/**
2
* Create an ADPCM codebook either by extracting it from an AIFF section, or
3
* by executing tabledesign.
4
*/
5
#include <unistd.h>
6
#include <math.h>
7
#include <string.h>
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <stdarg.h>
11
12
typedef short s16;
13
typedef int s32;
14
typedef unsigned char u8;
15
typedef unsigned int u32;
16
17
#define BSWAP16(x) x = __builtin_bswap16(x)
18
#define BSWAP32(x) x = __builtin_bswap32(x)
19
20
#define NORETURN __attribute__((noreturn))
21
#define UNUSED __attribute__((unused))
22
23
typedef struct
24
{
25
u32 start;
26
u32 end;
27
u32 count;
28
s16 state[16];
29
} ALADPCMloop;
30
31
static const char usage[] = "input.aiff";
32
static const char *progname, *infilename;
33
34
#define checked_fread(a, b, c, d) if (fread(a, b, c, d) != c) fail_parse("error parsing file")
35
36
NORETURN
37
void fail_parse(const char *fmt, ...)
38
{
39
char *formatted = NULL;
40
va_list ap;
41
va_start(ap, fmt);
42
int size = vsnprintf(NULL, 0, fmt, ap);
43
va_end(ap);
44
if (size >= 0) {
45
size++;
46
formatted = malloc(size);
47
if (formatted != NULL) {
48
va_start(ap, fmt);
49
size = vsnprintf(formatted, size, fmt, ap);
50
va_end(ap);
51
if (size < 0) {
52
free(formatted);
53
formatted = NULL;
54
}
55
}
56
}
57
58
if (formatted != NULL) {
59
fprintf(stderr, "%s: %s [%s]\n", progname, formatted, infilename);
60
free(formatted);
61
}
62
exit(1);
63
}
64
65
s32 readaifccodebook(FILE *fhandle, s32 ****table, s16 *order, s16 *npredictors)
66
{
67
checked_fread(order, sizeof(s16), 1, fhandle);
68
BSWAP16(*order);
69
checked_fread(npredictors, sizeof(s16), 1, fhandle);
70
BSWAP16(*npredictors);
71
*table = malloc(*npredictors * sizeof(s32 **));
72
for (s32 i = 0; i < *npredictors; i++) {
73
(*table)[i] = malloc(8 * sizeof(s32 *));
74
for (s32 j = 0; j < 8; j++) {
75
(*table)[i][j] = malloc((*order + 8) * sizeof(s32));
76
}
77
}
78
79
for (s32 i = 0; i < *npredictors; i++) {
80
s32 **table_entry = (*table)[i];
81
for (s32 j = 0; j < *order; j++) {
82
for (s32 k = 0; k < 8; k++) {
83
s16 ts;
84
checked_fread(&ts, sizeof(s16), 1, fhandle);
85
BSWAP16(ts);
86
table_entry[k][j] = ts;
87
}
88
}
89
90
for (s32 k = 1; k < 8; k++) {
91
table_entry[k][*order] = table_entry[k - 1][*order - 1];
92
}
93
94
table_entry[0][*order] = 1 << 11;
95
96
for (s32 k = 1; k < 8; k++) {
97
s32 j = 0;
98
for (; j < k; j++) {
99
table_entry[j][k + *order] = 0;
100
}
101
102
for (; j < 8; j++) {
103
table_entry[j][k + *order] = table_entry[j - k][*order];
104
}
105
}
106
}
107
return 0;
108
}
109
110
int main(int argc, char **argv)
111
{
112
s16 order = -1;
113
s16 npredictors = -1;
114
s32 ***coefTable = NULL;
115
FILE *ifile;
116
progname = argv[0];
117
118
if (argc < 2) {
119
fprintf(stderr, "%s %s\n", progname, usage);
120
exit(1);
121
}
122
123
infilename = argv[1];
124
125
if ((ifile = fopen(infilename, "rb")) == NULL) {
126
fail_parse("AIFF file could not be opened");
127
exit(1);
128
}
129
130
char buf[5] = {0};
131
checked_fread(buf, 4, 1, ifile);
132
if (strcmp(buf, "FORM") != 0) fail_parse("not an AIFF file");
133
checked_fread(buf, 4, 1, ifile);
134
checked_fread(buf, 4, 1, ifile);
135
if (strcmp(buf, "AIFF") != 0 && strcmp(buf, "AIFC") != 0) {
136
fail_parse("not an AIFF file");
137
}
138
139
for (;;) {
140
s32 size;
141
if (!fread(buf, 4, 1, ifile) || !fread(&size, 4, 1, ifile)) break;
142
BSWAP32(size);
143
s32 nextOffset = ftell(ifile) + ((size + 1) & ~1);
144
145
if (strcmp(buf, "APPL") == 0) {
146
checked_fread(buf, 4, 1, ifile);
147
if (strcmp(buf, "stoc") == 0) {
148
u8 len;
149
checked_fread(&len, 1, 1, ifile);
150
if (len == 11) {
151
char chunkName[12];
152
s16 version;
153
checked_fread(chunkName, 11, 1, ifile);
154
chunkName[11] = '\0';
155
if (strcmp(chunkName, "VADPCMCODES") == 0) {
156
checked_fread(&version, sizeof(s16), 1, ifile);
157
BSWAP16(version);
158
if (version == 1) {
159
readaifccodebook(ifile, &coefTable, &order, &npredictors);
160
}
161
}
162
}
163
}
164
}
165
166
fseek(ifile, nextOffset, SEEK_SET);
167
}
168
fclose(ifile);
169
170
if (coefTable == NULL) {
171
execl("./tools/tabledesign", "tabledesign", "-s", "1", infilename, NULL);
172
} else {
173
printf("%d\n%d\n", order, npredictors);
174
for (s32 i = 0; i < npredictors; i++) {
175
for (s32 j = 0; j < order; j++) {
176
for (s32 k = 0; k < 8; k++) {
177
printf("% 5d ", coefTable[i][k][j]);
178
}
179
puts("");
180
}
181
}
182
}
183
return 0;
184
}
185
186