Update README.md
[sm64pc.git] / tools / aiff_extract_codebook.c
blob481e31338ddcd737d6139453ba5dce876af4271e
1 /**
2 * Create an ADPCM codebook either by extracting it from an AIFF section, or
3 * by executing tabledesign.
4 */
5 #define _XOPEN_SOURCE 500
6 #include <unistd.h>
7 #include <math.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
13 typedef short s16;
14 typedef int s32;
15 typedef unsigned char u8;
16 typedef unsigned int u32;
18 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
19 # define BSWAP16(x)
20 # define BSWAP32(x)
21 #else
22 # define BSWAP16(x) x = __builtin_bswap16(x)
23 # define BSWAP32(x) x = __builtin_bswap32(x)
24 #endif
26 #define NORETURN __attribute__((noreturn))
27 #define UNUSED __attribute__((unused))
29 typedef struct
31 u32 start;
32 u32 end;
33 u32 count;
34 s16 state[16];
35 } ALADPCMloop;
37 static const char usage[] = "input.aiff";
38 static const char *progname, *infilename;
40 #define checked_fread(a, b, c, d) if (fread(a, b, c, d) != c) fail_parse("error parsing file")
42 NORETURN
43 void fail_parse(const char *fmt, ...)
45 char *formatted = NULL;
46 va_list ap;
47 va_start(ap, fmt);
48 int size = vsnprintf(NULL, 0, fmt, ap);
49 va_end(ap);
50 if (size >= 0) {
51 size++;
52 formatted = malloc(size);
53 if (formatted != NULL) {
54 va_start(ap, fmt);
55 size = vsnprintf(formatted, size, fmt, ap);
56 va_end(ap);
57 if (size < 0) {
58 free(formatted);
59 formatted = NULL;
64 if (formatted != NULL) {
65 fprintf(stderr, "%s: %s [%s]\n", progname, formatted, infilename);
66 free(formatted);
68 exit(1);
71 s32 readaifccodebook(FILE *fhandle, s32 ****table, s16 *order, s16 *npredictors)
73 checked_fread(order, sizeof(s16), 1, fhandle);
74 BSWAP16(*order);
75 checked_fread(npredictors, sizeof(s16), 1, fhandle);
76 BSWAP16(*npredictors);
77 *table = malloc(*npredictors * sizeof(s32 **));
78 for (s32 i = 0; i < *npredictors; i++) {
79 (*table)[i] = malloc(8 * sizeof(s32 *));
80 for (s32 j = 0; j < 8; j++) {
81 (*table)[i][j] = malloc((*order + 8) * sizeof(s32));
85 for (s32 i = 0; i < *npredictors; i++) {
86 s32 **table_entry = (*table)[i];
87 for (s32 j = 0; j < *order; j++) {
88 for (s32 k = 0; k < 8; k++) {
89 s16 ts;
90 checked_fread(&ts, sizeof(s16), 1, fhandle);
91 BSWAP16(ts);
92 table_entry[k][j] = ts;
96 for (s32 k = 1; k < 8; k++) {
97 table_entry[k][*order] = table_entry[k - 1][*order - 1];
100 table_entry[0][*order] = 1 << 11;
102 for (s32 k = 1; k < 8; k++) {
103 s32 j = 0;
104 for (; j < k; j++) {
105 table_entry[j][k + *order] = 0;
108 for (; j < 8; j++) {
109 table_entry[j][k + *order] = table_entry[j - k][*order];
113 return 0;
116 int main(int argc, char **argv)
118 s16 order = -1;
119 s16 npredictors = -1;
120 s32 ***coefTable = NULL;
121 FILE *ifile;
122 progname = argv[0];
124 if (argc < 2) {
125 fprintf(stderr, "%s %s\n", progname, usage);
126 exit(1);
129 infilename = argv[1];
131 if ((ifile = fopen(infilename, "rb")) == NULL) {
132 fail_parse("AIFF file could not be opened");
133 exit(1);
136 char buf[5] = {0};
137 checked_fread(buf, 4, 1, ifile);
138 if (strcmp(buf, "FORM") != 0) fail_parse("not an AIFF file");
139 checked_fread(buf, 4, 1, ifile);
140 checked_fread(buf, 4, 1, ifile);
141 if (strcmp(buf, "AIFF") != 0 && strcmp(buf, "AIFC") != 0) {
142 fail_parse("not an AIFF file");
145 for (;;) {
146 s32 size;
147 if (!fread(buf, 4, 1, ifile) || !fread(&size, 4, 1, ifile)) break;
148 BSWAP32(size);
149 s32 nextOffset = ftell(ifile) + ((size + 1) & ~1);
151 if (strcmp(buf, "APPL") == 0) {
152 checked_fread(buf, 4, 1, ifile);
153 if (strcmp(buf, "stoc") == 0) {
154 u8 len;
155 checked_fread(&len, 1, 1, ifile);
156 if (len == 11) {
157 char chunkName[12];
158 s16 version;
159 checked_fread(chunkName, 11, 1, ifile);
160 chunkName[11] = '\0';
161 if (strcmp(chunkName, "VADPCMCODES") == 0) {
162 checked_fread(&version, sizeof(s16), 1, ifile);
163 BSWAP16(version);
164 if (version == 1) {
165 readaifccodebook(ifile, &coefTable, &order, &npredictors);
172 fseek(ifile, nextOffset, SEEK_SET);
174 fclose(ifile);
176 if (coefTable == NULL) {
177 execl("./tools/tabledesign", "tabledesign", "-s", "1", infilename, NULL);
178 } else {
179 printf("%d\n%d\n", order, npredictors);
180 for (s32 i = 0; i < npredictors; i++) {
181 for (s32 j = 0; j < order; j++) {
182 for (s32 k = 0; k < 8; k++) {
183 printf("% 5d ", coefTable[i][k][j]);
185 puts("");
189 return 0;