You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
init2
This commit is contained in:
210
tools/aiff_extract_codebook.c
Normal file
210
tools/aiff_extract_codebook.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Create an ADPCM codebook either by extracting it from an AIFF section, or
|
||||
* by executing tabledesign.
|
||||
*/
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef short s16;
|
||||
typedef int s32;
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned int u32;
|
||||
|
||||
#define BSWAP16(x) x = __builtin_bswap16(x)
|
||||
#define BSWAP32(x) x = __builtin_bswap32(x)
|
||||
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 start;
|
||||
u32 end;
|
||||
u32 count;
|
||||
s16 state[16];
|
||||
} ALADPCMloop;
|
||||
|
||||
static const char usage[] = "input.aiff";
|
||||
static const char *progname, *infilename;
|
||||
|
||||
#define checked_fread(a, b, c, d) if (fread(a, b, c, d) != c) fail_parse("error parsing file")
|
||||
|
||||
NORETURN
|
||||
void fail_parse(const char *fmt, ...)
|
||||
{
|
||||
char *formatted = NULL;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int size = vsnprintf(NULL, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
if (size >= 0) {
|
||||
size++;
|
||||
formatted = malloc(size);
|
||||
if (formatted != NULL) {
|
||||
va_start(ap, fmt);
|
||||
size = vsnprintf(formatted, size, fmt, ap);
|
||||
va_end(ap);
|
||||
if (size < 0) {
|
||||
free(formatted);
|
||||
formatted = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (formatted != NULL) {
|
||||
fprintf(stderr, "%s: %s [%s]\n", progname, formatted, infilename);
|
||||
free(formatted);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
s32 readaifccodebook(FILE *fhandle, s32 ****table, s16 *order, s16 *npredictors)
|
||||
{
|
||||
checked_fread(order, sizeof(s16), 1, fhandle);
|
||||
BSWAP16(*order);
|
||||
checked_fread(npredictors, sizeof(s16), 1, fhandle);
|
||||
BSWAP16(*npredictors);
|
||||
*table = malloc(*npredictors * sizeof(s32 **));
|
||||
for (s32 i = 0; i < *npredictors; i++) {
|
||||
(*table)[i] = malloc(8 * sizeof(s32 *));
|
||||
for (s32 j = 0; j < 8; j++) {
|
||||
(*table)[i][j] = malloc((*order + 8) * sizeof(s32));
|
||||
}
|
||||
}
|
||||
|
||||
for (s32 i = 0; i < *npredictors; i++) {
|
||||
s32 **table_entry = (*table)[i];
|
||||
for (s32 j = 0; j < *order; j++) {
|
||||
for (s32 k = 0; k < 8; k++) {
|
||||
s16 ts;
|
||||
checked_fread(&ts, sizeof(s16), 1, fhandle);
|
||||
BSWAP16(ts);
|
||||
table_entry[k][j] = ts;
|
||||
}
|
||||
}
|
||||
|
||||
for (s32 k = 1; k < 8; k++) {
|
||||
table_entry[k][*order] = table_entry[k - 1][*order - 1];
|
||||
}
|
||||
|
||||
table_entry[0][*order] = 1 << 11;
|
||||
|
||||
for (s32 k = 1; k < 8; k++) {
|
||||
s32 j = 0;
|
||||
for (; j < k; j++) {
|
||||
table_entry[j][k + *order] = 0;
|
||||
}
|
||||
|
||||
for (; j < 8; j++) {
|
||||
table_entry[j][k + *order] = table_entry[j - k][*order];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
s16 order = -1;
|
||||
s16 npredictors = -1;
|
||||
s32 ***coefTable = NULL;
|
||||
FILE *ifile;
|
||||
progname = argv[0];
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "%s %s\n", progname, usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
infilename = argv[1];
|
||||
|
||||
if ((ifile = fopen(infilename, "rb")) == NULL) {
|
||||
fail_parse("AIFF file could not be opened");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char buf[5] = {0};
|
||||
checked_fread(buf, 4, 1, ifile);
|
||||
if (strcmp(buf, "FORM") != 0) fail_parse("not an AIFF file");
|
||||
checked_fread(buf, 4, 1, ifile);
|
||||
checked_fread(buf, 4, 1, ifile);
|
||||
if (strcmp(buf, "AIFF") != 0 && strcmp(buf, "AIFC") != 0) {
|
||||
fail_parse("not an AIFF file");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
s32 size;
|
||||
if (!fread(buf, 4, 1, ifile) || !fread(&size, 4, 1, ifile)) break;
|
||||
BSWAP32(size);
|
||||
s32 nextOffset = ftell(ifile) + ((size + 1) & ~1);
|
||||
|
||||
if (strcmp(buf, "APPL") == 0) {
|
||||
checked_fread(buf, 4, 1, ifile);
|
||||
if (strcmp(buf, "stoc") == 0) {
|
||||
u8 len;
|
||||
checked_fread(&len, 1, 1, ifile);
|
||||
if (len == 11) {
|
||||
char chunkName[12];
|
||||
s16 version;
|
||||
checked_fread(chunkName, 11, 1, ifile);
|
||||
chunkName[11] = '\0';
|
||||
if (strcmp(chunkName, "VADPCMCODES") == 0) {
|
||||
checked_fread(&version, sizeof(s16), 1, ifile);
|
||||
BSWAP16(version);
|
||||
if (version == 1) {
|
||||
readaifccodebook(ifile, &coefTable, &order, &npredictors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fseek(ifile, nextOffset, SEEK_SET);
|
||||
}
|
||||
fclose(ifile);
|
||||
|
||||
if (coefTable == NULL) {
|
||||
// Missing codebook, execute tabledesign instead
|
||||
const char *procDirs[] = {
|
||||
"/proc/self/exe", // Linux
|
||||
"/proc/curproc/exe", // FreeBSD
|
||||
"/proc/self/path/a.out", // Solaris
|
||||
};
|
||||
char buf[0x1000 + 0x100];
|
||||
s32 bufSize = 0x1000, found = 0;
|
||||
for (s32 i = 0; i < 3; i++) {
|
||||
ssize_t ret = readlink(procDirs[i], buf, bufSize);
|
||||
if (ret > 0 && ret < bufSize) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Not able to determine filename, let's guess
|
||||
strcpy(buf, "./tools/");
|
||||
}
|
||||
char *sep = strrchr(buf, '/');
|
||||
if (sep == NULL) {
|
||||
sep = buf + strlen(buf);
|
||||
}
|
||||
*sep++ = '/';
|
||||
strcpy(sep, "tabledesign");
|
||||
execl(buf, "tabledesign", "-s", "1", infilename, NULL);
|
||||
} else {
|
||||
printf("%d\n%d\n", order, npredictors);
|
||||
for (s32 i = 0; i < npredictors; i++) {
|
||||
for (s32 j = 0; j < order; j++) {
|
||||
for (s32 k = 0; k < 8; k++) {
|
||||
printf("% 5d ", coefTable[i][k][j]);
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user