Initial revision

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@117 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2002-10-14 23:55:51 +00:00
parent 427f29905b
commit 5389c45ca4
15 changed files with 1478 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
aif2raw: aif2raw.c aif2raw.h
gcc -W -Wall -g -O0 aif2raw.c -o aif2raw
clean:
rm aif2raw
+273
View File
@@ -0,0 +1,273 @@
/*
* aif to raw converter. By Serge van den Boom (svdb@stack.nl),
* 20020816
* Doesn't convert all .aif files in general, only AIFF-C, 16 bits
* SDX2-compressed.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "aif2raw.h"
void convert_aif(FILE *in, FILE *out);
void write_data(const uint8_t *data, ssize_t size, int numChannels,
FILE *out);
int
main(int argc, char *argv[]) {
FILE *in, *out;
if (argc != 3) {
fprintf(stderr, "aif2wav <infile> <outfile>\n");
return EXIT_FAILURE;
}
in = fopen(argv[1], "r");
if (!in) {
perror("Could not open input file");
return EXIT_FAILURE;
}
out = fopen(argv[2], "w");
if (!out) {
perror("Could not open output file");
return EXIT_FAILURE;
}
convert_aif(in, out);
fclose(in);
fclose(out);
return EXIT_SUCCESS;
}
/* local to file byte order */
inline uint32_t
ltof32(uint32_t val) {
return (val >> 24) |
((val & 0x00ff0000L) >> 8) |
((val & 0x0000ff00L) << 8) |
(val << 24);
}
/* file to local byte order */
inline uint32_t
ftol32(uint32_t val) {
return (val >> 24) |
((val & 0x00ff0000L) >> 8) |
((val & 0x0000ff00L) << 8) |
(val << 24);
}
/* local to file byte order */
inline uint16_t
ltof16(uint16_t val) {
return (val >> 8) | (val << 8);
}
/* file to local byte order */
inline uint16_t
ftol16(uint16_t val) {
return (val >> 8) | (val << 8);
}
#if 0
/* local to file byte order */
inline void
ltofld(char *dest, long double val) {
}
#endif
/* file to local byte order */
inline long double
ftolld(const char *val) {
long double result;
((char *) &result)[0] = val[9];
((char *) &result)[1] = val[8];
((char *) &result)[2] = val[7];
((char *) &result)[3] = val[6];
((char *) &result)[4] = val[5];
((char *) &result)[5] = val[4];
((char *) &result)[6] = val[3];
((char *) &result)[7] = val[2];
((char *) &result)[8] = val[1];
((char *) &result)[9] = val[0];
((char *) &result)[10] = 0x00;
((char *) &result)[11] = 0x00;
return result;
}
void
read_data(char *buf, size_t size, FILE *file) {
ssize_t numread;
numread = fread(buf, size, 1, file);
if (numread == 0 && ferror(file)) {
perror("read header");
exit(EXIT_FAILURE);
}
if ((size_t) numread != 1) {
fprintf(stderr, "Input file too small.\n");
exit(EXIT_FAILURE);
}
}
struct aifc_Chunk *
read_chunk(FILE *in) {
struct aifc_Chunk *result;
size_t numread;
result = malloc(sizeof (struct aifc_ChunkHeader));
numread = fread(result, sizeof (struct aifc_ChunkHeader), 1, in);
if (numread == 0) {
free(result);
if (ferror(in))
fprintf(stderr, "Fread failed.\n");
return NULL;
}
result = realloc(result, sizeof (struct aifc_ChunkHeader) +
ftol32(result->ckSize));
numread = fread(&result->ckData, ftol32(result->ckSize), 1, in);
if (numread == 0) {
free(result);
if (ferror(in))
fprintf(stderr, "Fread failed.\n");
return NULL;
}
return result;
}
/* number to increase number of sections by if all preallocated
sections are full */
#define CHUNK_NUM_INC 5
struct aifc_Chunk **
read_chunks(FILE *in) {
struct aifc_Chunk **chunks;
struct aifc_ContainerChunk *form;
int maxchunks;
int numchunks;
/* The FORM chunk contains all the other chunks. */
form = malloc(sizeof (struct aifc_ContainerChunk));
read_data((char *) form, sizeof (struct aifc_ContainerChunk), in);
if (form->formType != aifc_FormTypeAIFC) {
fprintf(stderr, "File is not an AIFF-C file.\n");
free(form);
exit(EXIT_FAILURE);
}
free(form);
numchunks = 0;
maxchunks = 0;
chunks = NULL;
while (1) {
if (numchunks >= maxchunks) {
maxchunks += CHUNK_NUM_INC;
chunks = realloc(chunks,
(maxchunks + 1) * sizeof (struct aifc_Chunk *));
}
chunks[numchunks] = read_chunk(in);
if (chunks[numchunks] == NULL)
break;
numchunks++;
}
chunks = realloc(chunks,
(numchunks + 1) * sizeof (struct aifc_Chunk *));
return chunks;
}
void
free_chunks(struct aifc_Chunk **chunks) {
int i;
for (i = 0; chunks[i] != NULL; i++)
free(chunks[i]);
free(chunks);
}
void
convert_aif(FILE *in, FILE *out) {
struct aifc_Chunk **chunks;
struct aifc_FormatVersionChunk *fverChunk;
struct aifc_ExtCommonChunk *commChunk;
struct aifc_SoundDataChunk *ssndChunk;
int i;
fverChunk = NULL;
commChunk = NULL;
ssndChunk = NULL;
chunks = read_chunks(in);
for (i = 0; chunks[i] != NULL; i++) {
if (chunks[i]->ckID == aifc_FormVersionID && fverChunk == NULL) {
fverChunk = (struct aifc_FormatVersionChunk *) chunks[i];
} else if (chunks[i]->ckID == aifc_CommonID && commChunk == NULL) {
commChunk = (struct aifc_ExtCommonChunk *) chunks[i];
} else if (chunks[i]->ckID == aifc_SoundDataID && ssndChunk == NULL) {
ssndChunk = (struct aifc_SoundDataChunk *) chunks[i];
}
}
if (fverChunk == NULL) {
fprintf(stderr, "No format version chunk found.\n");
exit(EXIT_FAILURE);
}
if (commChunk == NULL) {
fprintf(stderr, "No common chunk found.\n");
exit(EXIT_FAILURE);
}
if (ssndChunk == NULL) {
fprintf(stderr, "No sound data chunk found.\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "Number of channels: %d\n",
ftol16(commChunk->numChannels));
fprintf(stderr, "Number of sample frames: %d\n",
ftol32(commChunk->numSampleFrames));
fprintf(stderr, "Number of bits per sample: %d\n",
ftol16(commChunk->sampleSize));
fprintf(stderr, "Sample rate: %.2LfHz\n",
ftolld((char *) &commChunk->sampleRate));
if (ftol16(commChunk->sampleSize) != 16) {
fprintf(stderr, "Only 16-bits files are supported.\n");
exit(EXIT_FAILURE);
}
if (commChunk->compressionType != aifc_CompressionTypeSDX2) {
fprintf(stderr, "Only SDX2 compression is supported.\n");
exit(EXIT_FAILURE);
}
write_data(ssndChunk->data + ftol32(ssndChunk->offset),
ftol32(ssndChunk->ckSize) - ftol32(ssndChunk->offset),
ftol16(commChunk->numChannels), out);
free_chunks(chunks);
}
void
write_data(const uint8_t *data, ssize_t size, int numChannels, FILE *out) {
const uint8_t *srcptr, *endptr;
uint16_t *buffer, *dstptr;
int i;
int16_t *last;
endptr = data + size;
srcptr = data;
buffer = alloca(size * sizeof (uint16_t));
dstptr = buffer;
last = alloca(numChannels * sizeof(int16_t));
memset(last, '\0', numChannels * sizeof(uint16_t));
while (srcptr < endptr) {
for (i = 0; i < numChannels; i++) {
if (*srcptr & 1) {
*dstptr = last[i] +
((*(int8_t *)srcptr * abs(*(int8_t *)srcptr)) << 1);
} else
*dstptr = (*(int8_t *)srcptr * abs(*(int8_t *)srcptr)) << 1;
last[i] = *dstptr;
dstptr++;
srcptr++;
}
}
fwrite(buffer, size * sizeof (uint16_t), 1, out);
}
+69
View File
@@ -0,0 +1,69 @@
#include <stdint.h>
typedef uint32_t aifc_ID;
typedef uint8_t aifc_Extended[10];
/* This should actually be a 80-bits integer, but
* long double takes 96 bits, even though only 80 are used */
#define aifc_MAKE_ID(x1, x2, x3, x4) \
(((x4) << 24) | ((x3) << 16) | ((x2) << 8) | (x1))
#define aifc_FormID aifc_MAKE_ID('F', 'O', 'R', 'M')
#define aifc_FormVersionID aifc_MAKE_ID('F', 'V', 'E', 'R')
#define aifc_CommonID aifc_MAKE_ID('C', 'O', 'M', 'M')
#define aifc_SoundDataID aifc_MAKE_ID('S', 'S', 'N', 'D')
#define aifc_FormTypeAIFF aifc_MAKE_ID('A', 'I', 'F', 'F')
#define aifc_FormTypeAIFC aifc_MAKE_ID('A', 'I', 'F', 'C')
#define aifc_CompressionTypeSDX2 aifc_MAKE_ID('S', 'D', 'X', '2')
struct aifc_ChunkHeader {
aifc_ID ckID;
uint32_t ckSize;
};
struct aifc_Chunk {
aifc_ID ckID; /* Chunk ID */
uint32_t ckSize; /* Chunk size, excluding header */
uint8_t ckData[1]; /* placeholder for data */
};
struct aifc_ContainerChunk {
aifc_ID ckID; /* "FORM" */
uint32_t ckSize; /* number of bytes of data */
aifc_ID formType; /* type of file, "AIFC" */
};
struct aifc_FormatVersionChunk {
aifc_ID ckID; /* "FVER" */
uint32_t ckSize; /* 4 */
uint32_t timestamp; /* date of format version, in Mac format */
};
struct aifc_ExtCommonChunk {
aifc_ID ckID; /* "COMM" */
uint32_t ckSize; /* size of chunk data */
uint16_t numChannels; /* number of channels */
uint32_t numSampleFrames __attribute__ ((packed));
/* number of sample frames */
uint16_t sampleSize __attribute__ ((packed));
/* number of bits per sample */
aifc_Extended sampleRate __attribute__ ((packed));
/* number of frames per second */
aifc_ID compressionType __attribute__ ((packed));
/* compression type ID */
char *compressionName;
/* compression type name */
};
struct aifc_SoundDataChunk {
aifc_ID ckID; /* "SSND" */
uint32_t ckSize; /* size of chunk data */
uint32_t offset; /* offset to sound data */
uint32_t blocksize; /* size of alignment blocks */
uint8_t data[1]; /* placeholder for data */
};
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
AIF2RAW="./aif2raw"
SOX="sox"
echo "Converting all aif files in the current directory to wav files."
echo "This script looks for aif2raw in the current dir. If it's somewhere"
echo "else, edit it to point the variable AIF2RAW to the correct location."
echo "The same goes for sox, which is expected somewhere in the path."
echo "It's just supposed to work once on a specific set of files, and hence"
echo "is pretty fragile."
echo "It is assumed that all aif files have a sample rate of 11025."
echo "If this is not the case, files won't be converted correctly."
echo "The sample rate is reported, so you can see if it goes wrong."
echo "Press ENTER when ready."
read
for FILE in *.aif; do
echo "File $FILE"
BASE="${FILE%%.aif}"
"$AIF2RAW" "$FILE" "${BASE}.raw"
"$SOX" -c 2 -r 44100 -w -s "${BASE}.raw" "${BASE}.wav"
echo
done