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
+6
View File
@@ -0,0 +1,6 @@
abx2raw: abx2raw.c abx2raw.h
gcc -W -Wall -g -O0 abx2raw.c -o abx2raw
clean:
rm abx2raw
+270
View File
@@ -0,0 +1,270 @@
/*
* abx to raw converter. By Serge van den Boom (svdb@stack.nl),
* The actual conversion code is from Toys for Bob.
* So far, it ignores sample rates, so it will work ok as long as all
* the frames have the same frequency. This is probably
* enough for our purposes.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "abx2raw.h"
void convert_abx(FILE *in, FILE *out);
uint8_t *UnCompressAudio(struct abx_header *abx, uint8_t *source);
int
main(int argc, char *argv[]) {
FILE *in, *out;
if (argc != 3) {
fprintf(stderr, "abx2wav <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_abx(in, out);
fclose(in);
fclose(out);
return EXIT_SUCCESS;
}
static signed char trans[16*16] =
{
-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8, // Multiplier of 1
-16,-14,-12,-10,-8,-6,-4,-2,2,4,6,8,10,12,14,16, // Multiplier of 2
-24,-21,-18,-15,-12,-9,-6,-3,3,6,9,12,15,18,21,24, // Multiplier of 3
-32,-28,-24,-20,-16,-12,-8,-4,4,8,12,16,20,24,28,32, // Multiplier of 4
-40,-35,-30,-25,-20,-15,-10,-5,5,10,15,20,25,30,35,40, // Multiplier of 5
-48,-42,-36,-30,-24,-18,-12,-6,6,12,18,24,30,36,42,48, // Multiplier of 6
-56,-49,-42,-35,-28,-21,-14,-7,7,14,21,28,35,42,49,56, // Multiplier of 7
-64,-56,-48,-40,-32,-24,-16,-8,8,16,24,32,40,48,56,64, // Multiplier of 8
-72,-63,-54,-45,-36,-27,-18,-9,9,18,27,36,45,54,63,72, // Multiplier of 9
-80,-70,-60,-50,-40,-30,-20,-10,10,20,30,40,50,60,70,80, // Multiplier of 10
-88,-77,-66,-55,-44,-33,-22,-11,11,22,33,44,55,66,77,88, // Multiplier of 11
-96,-84,-72,-60,-48,-36,-24,-12,12,24,36,48,60,72,84,96, // Multiplier of 12
-104,-91,-78,-65,-52,-39,-26,-13,13,26,39,52,65,78,91,104, // Multiplier of 13
-112,-98,-84,-70,-56,-42,-28,-14,14,28,42,56,70,84,98,112, // Multiplier of 14
-120,-105,-90,-75,-60,-45,-30,-15,15,30,45,60,75,90,105,120,// Multiplier of 15
-128,-112,-96,-80,-64,-48,-32,-16,16,32,48,64,80,96,112,127,// Multiplier of 16
};
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);
}
}
void
convert_abx(FILE *in, FILE *out) {
struct abx_header abx;
struct frame_info *frame_info;
uint8_t **frames;
uint8_t **uncoded;
int i;
read_data((uint8_t *) &abx, sizeof (struct abx_header), in);
fprintf(stderr, "Base sample rate: %dHz\n", abx.freq);
frame_info = malloc(sizeof (struct frame_info) * abx.num_frames);
read_data((uint8_t *) frame_info,
sizeof (struct frame_info) * abx.num_frames, in);
frames = malloc(sizeof (uint8_t *) * abx.num_frames);
uncoded = malloc(sizeof (uint8_t *) * abx.num_frames);
for (i = 0; i < abx.num_frames; i++) {
frames[i] = malloc(frame_info[i].fsize);
read_data(frames[i], frame_info[i].fsize, in);
#if 0
// debug output to locate the first bad frame
fprintf(stderr, "Now going to process frame %d.\n", i);
#endif
#if 0
// skip some corrupt frames
if (i >= 270 && i <= 271) {
// fill the bad part with zeros
uncoded[i] = malloc(frame_info[i].usize);
memset(uncoded[i], '\0', frame_info[i].usize);
continue;
}
#endif
uncoded[i] = UnCompressAudio(&abx, frames[i]);
}
for (i = 0; i < abx.num_frames; i++) {
fwrite(uncoded[i], frame_info[i].usize, 1, out);
}
for (i = 0; i < abx.num_frames; i++) {
free(frames[i]);
free(uncoded[i]);
}
free(uncoded);
free(frames);
free(frame_info);
}
#define MAKE_WORD(byte1, byte2) ((byte2 << 8) | (byte1))
// This is used to make certain this C code is compatible when compiled on
// a 68000 based machine. (Which it has been done and tested on.)
#define Get8086word(t) MAKE_WORD ((t)[0], (t)[1])
// GetFreq will report the playback frequency of a particular ACOMP data
// file.
uint16_t
GetFreq(uint8_t *sound) {
return(Get8086word(sound + 2));
}
uint8_t *
UnCompressAudio(struct abx_header *abx,
uint8_t *source) {
uint16_t slen, frame, freq;
int16_t prev;
uint8_t *result, *dest;
slen = Get8086word(source);
dest = result = malloc(slen * sizeof (uint8_t));
freq = GetFreq(source);
if (freq == 0) {
freq = abx->freq;
} else if (freq != abx->freq) {
fprintf(stderr, "Frame frequency (%d) != global frequency (%d).\n",
freq, abx->freq);
fprintf(stderr, "This is not supported. Output will be corrupted.\n");
abx->freq = freq;
}
source += 4; // Skip length, and then frequency word.
frame = *source++; // Frame size.
source += 3; // Skip sqelch value, and maximum error allowed.
prev = *source++; // Get initial previous data point.
*dest++ = prev ^ 0x80;
slen--; // Decrement total sound length.
while (slen > 0)
{
uint16_t bytes;
uint8_t sample;
sample = *source++; // Get sample.
if (sample & RESYNC) // Is it a resync byte?
{
--slen; // Decrement output sample length.
prev = (sample & 0x7F) << 1; // Store resync byte.
*dest++ = prev ^ 0x80;
}
else if (sample & SQLCH) // Is it a squelch byte?
{
bytes = sample & SQUELCHCNT; // And off the number of squelch bytes
slen -= bytes; // Decrement total samples remaining count.
memset(dest, prev ^ 0x80, bytes);
dest += bytes;
}
else // Must be a delta modulate byte!!
{
int8_t *base;
slen -= frame; // Pulling one frame out.
// Compute base address to multiplier table.
base = trans + (sample & MULTIPLIER) * 16;
switch (sample & DELTAMOD) // Delta mod resolution.
{
case ONEBIT:
{
int16_t up;
up = base[8]; // Go up 1 bit.
for (bytes = frame / 8; bytes; bytes--)
{
uint8_t mask;
sample = *source++;
for(mask = 0x80; mask; mask >>= 1)
{
if ( sample & mask )
prev += up;
else
prev -= up;
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
}
}
break;
}
case TWOBIT:
base+=6; // Base address of two bit delta's.
for (bytes = frame / 4; bytes; bytes--)
{
sample = *source++;
prev += base[sample>>6];
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
prev += base[(sample>>4)&0x3];
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
prev += base[(sample>>2)&0x3];
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
prev += base[sample&0x3];
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
}
break;
case FOURBIT:
for (bytes = frame / 2; bytes; bytes--)
{
sample = *source++;
prev += base[sample>>4];
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
prev += base[sample&0x0F];
if ( prev < 0 ) prev = 0;
else if ( prev > 255 ) prev = 255;
*dest++ = prev ^ 0x80;
}
break;
}
}
// While still audio data to decompress....
}
return result;
}
+27
View File
@@ -0,0 +1,27 @@
#include <stdint.h>
struct abx_header {
uint16_t num_frames;
uint32_t tot_size __attribute__ ((packed));
uint16_t bufsize __attribute__ ((packed));
uint16_t freq __attribute__ ((packed));
};
struct frame_info {
uint32_t addr;
uint16_t fsize; // compressed file size
uint16_t usize; // uncompressed file size
};
#define SQLCH 0x40 // Squelch byte flag
#define RESYNC 0x80 // Resync byte flag.
#define DELTAMOD 0x30 // Delta modulation bits.
#define ONEBIT 0x10 // One bit delta modulate
#define TWOBIT 0x20 // Two bit delta modulate
#define FOURBIT 0x30 // four bit delta modulate
#define MULTIPLIER 0x0F // Bottom nibble contains multiplier value.
#define SQUELCHCNT 0x3F // Bits for squelching.
+26
View File
@@ -0,0 +1,26 @@
#!/bin/sh
ABX2RAW="./abx2raw"
SOX="sox"
echo "Converting all abx files in the current directory to wav files."
echo "This script looks for abx2raw in the current dir. If it's somewhere"
echo "else, edit it to point the variable ABX2RAW 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 abx 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 "It's also possible that the sample rate changes within one .abx file."
echo "Press ENTER when ready."
read
for FILE in *.abx; do
echo "File $FILE"
BASE="${FILE%%.abx}"
"$ABX2RAW" "$FILE" "${BASE}.raw"
"$SOX" -c 1 -r 11025 -b -s "${BASE}.raw" "${BASE}.wav"
echo
done