Sound on PI?? Help!!
Guido van Rossum
guido at cwi.nl
Wed Oct 10 19:02:40 AEST 1990
I wrote:
>I have a program that converts Mac
>samples (compressed or not) to sgi format. For other hints on how to
>use audio, see /usr/people/4Dgifts/examples/audio.
>From the reactions, I think I'd better post it here. Watch the
copyrights, and of course this comes with no warranty.
Cheer up,
--Guido
/************************************************************************/
/* Copyright 1989 by Rich Gopstein and Harris Corporation */
/* */
/* Permission to use, copy, modify, and distribute this software */
/* and its documentation for any purpose and without fee is */
/* hereby granted, provided that the above copyright notice */
/* appears in all copies and that both that copyright notice and */
/* this permission notice appear in supporting documentation, and */
/* that the name of Rich Gopstein and Harris Corporation not be */
/* used in advertising or publicity pertaining to distribution */
/* of the software without specific, written prior permission. */
/* Rich Gopstein and Harris Corporation make no representations */
/* about the suitability of this software for any purpose. It */
/* provided "as is" without express or implied warranty. */
/************************************************************************/
/************************************************************************/
/* Modified by Dik T. Winter to convert Mac soundfiles to sun */
/* soundfiles. Modifications are: */
/* 1. Program works as a filter, output can be piped to Jef */
/* Poskanzers sound programs. */
/* 2. Program converts standard soundfiles and Huffmann compressed */
/* soundfiles. */
/************************************************************************/
/************************************************************************/
/* Modified by Guido van Rossum to produce output suitable */
/* for the Silicon Graphics Personal Iris (which has linear */
/* encoding like the Macintosh format). */
/************************************************************************/
/************************************************************************/
/* macsound2sgi.c - Convert sampled audio files into linear format for */
/* the Silicon Graphics Personal Iris */
/* Send comments to ..!rutgers!soleil!gopstein */
/* But about this version guido at cwi.nl */
/************************************************************************/
#include <stdio.h>
#define DEFAULT_FREQUENCY 11000
extern char * malloc();
FILE* infile;
/*******************************************************/
/* */
/* Usage is "macsound2sgi [-f frequency] [infile]" */
/* */
/* "frequency" is the samples per second of the infile */
/* the outfile is always 8192 samples per second. */
/* "frequency is ignored if the file is Huffmann */
/* compressed (the file contains the sample rate in */
/* that case). */
/* */
/*******************************************************/
/***********************************************************************/
/* */
/* The input file is expected to be a stream of one-byte excess-128 */
/* samples. Each sample is converted to 2's complement by subtracting */
/* 128, then converted to uLAW and output. We calculate the proper */
/* number of input bytes to skip in order to make the sample frequency */
/* convert to 8192/sec properly. Interpolation could be added, but it */
/* doesn't appear to be necessary. */
/* */
/* Now also assumes the file is preceded by a 128 byte header */
/* (MacBinary format), and allows for Huffmann compressed data forks. */
/* File type should be "FSSD". */
/***********************************************************************/
unsigned char dogetchar()
{
int ch;
if((ch = fgetc(infile)) == EOF) {
fprintf(stderr, "macsound2sun: premature end of file.\n");
exit(1);
}
return (unsigned char)ch;
}
long getlong(c)
unsigned char *c;
{
long l;
l = *c++;
l = (l << 8) + *c++;
l = (l << 8) + *c++;
l = (l << 8) + *c++;
return l;
}
short getshort(c)
unsigned char *c;
{
short l;
l = *c++;
l = (l << 8) + *c++;
return l;
}
void uncompress(df, dl, fr)
unsigned char **df;
long *dl;
float *fr;
{
typedef struct {
short dict_leftson;
short dict_rightson;
} dictent;
unsigned char *datafork = *df;
long huffcount, checksum, compresstype, samplerate;
short dictsize;
unsigned char *uncompressed;
dictent dictionary[511];
int i;
huffcount = getlong(datafork + 4);
checksum = getlong(datafork + 8);
compresstype = getlong(datafork + 12);
samplerate = getlong(datafork + 16);
dictsize = getshort(datafork + 20);
datafork += 22;
switch(compresstype) {
case 0: /* value compression */
case 1: /* delta compression */
break;
default:
fprintf(stderr, "macsound2sun: compression type %d unknown.\n",
compresstype);
exit(1);
}
if(samplerate == 0 || samplerate > 4) {
fprintf(stderr, "macsound2sun: sample rate %d invalid.\n", samplerate);
exit(1);
}
*fr = (float)((DEFAULT_FREQUENCY * 2) / samplerate);
if((uncompressed = (unsigned char *)malloc((unsigned)huffcount)) == NULL) {
fprintf(stderr, "macsound2sun: cannot get memory for uncompressed data.\n");
exit(1);
}
for(i = 0; i < dictsize; i++) {
dictionary[i].dict_leftson = getshort(datafork);
datafork += 2;
dictionary[i].dict_rightson = getshort(datafork);
datafork += 2;
}
datafork++; /* skip pad byte */
/* return info to caller */
*df = uncompressed;
*dl = huffcount;
{
short sample = *datafork++;
long cksum = 0;
int dictentry = 0;
long current;
int nrbits = 0;
huffcount--;
*uncompressed++ = sample;
while(huffcount > 0) {
if(nrbits == 0) {
current = getlong(datafork);
datafork += 4;
cksum += current;
nrbits = 32;
}
if(current < 0) {
dictentry = dictionary[dictentry].dict_rightson;
} else {
dictentry = dictionary[dictentry].dict_leftson;
}
current = (current << 1);
nrbits--;
if(dictionary[dictentry].dict_leftson < 0) {
if(compresstype == 0) sample = 0;
sample += dictionary[dictentry].dict_rightson;
huffcount--;
*uncompressed++ = sample;
dictentry = 0;
}
}
if(cksum != checksum) {
fprintf(stderr, "macsound2sun: checksum error.\n");
exit(1);
}
}
}
main(argc, argv)
int argc;
char *argv[];
{
float sum = 0.5;
float frequency, increment;
unsigned char ch;
int chr, skip;
int i;
long datalength;
char mactype[4];
unsigned char *datafork;
infile = stdin;
if (argc == 4 || argc == 2) {
if ((infile = fopen(argv[argc-1], "r")) == NULL) {
perror("macsound2sun: error opening infile");
exit(0);
}
argc--;
}
if (argc == 3) {
if (strcmp(argv[1], "-f") != 0) {
fprintf(stderr, "Usage: macsound2sun [-f frequency] [infile]\n");
exit(1);
} else {
frequency = atoi(argv[2]);
}
} else if (argc == 1) {
frequency = DEFAULT_FREQUENCY;
} else {
fprintf(stderr, "Usage: macsound2sun [-f frequency] [infile]\n");
exit(1);
}
/* read info header. */
for(i = 0; i < 65; i++) ch = dogetchar();
/* get type. */
for(i = 65; i < 69; i++) mactype[i - 65] = dogetchar();
if(strncmp(mactype, "FSSD", 4)) {
fprintf(stderr, "macsound2sun: filetype is not FSSD, but %.4s.\n", mactype);
exit(1);
}
for(i = 69; i < 83; i++) ch = dogetchar();
/* get length of datafork. */
datalength = 0;
for(i = 83; i < 87; i++)
datalength = (datalength << 8) + (unsigned char)dogetchar();
/* skip remainder of header. */
for(i = 87; i < 128; i++) ch = dogetchar();
if((datafork = (unsigned char *)malloc((unsigned)datalength)) == NULL) {
fprintf(stderr, "macsound2sun: cannot allocate memory for data.\n");
exit(1);
}
for(i = 0; i < datalength; i++) datafork[i] = dogetchar();
if(!strncmp((char *)datafork, "HCOM", 4)) {
/* do uncompression first */
uncompress(&datafork, &datalength, &frequency);
}
/* increment is the number of bytes to read each time */
increment = frequency / 8192;
datalength--;
while (datalength > 0) {
ch = *datafork++;
datalength--;
/* convert the excess 128 to two's complement */
chr = 0x80 - ch;
/* output it */
putchar((char) chr);
/* skip enough input bytes to compensate for sampling frequency diff */
sum += increment;
skip = sum;
sum -= skip;
skip--;
datafork += skip;
datalength -= skip;
}
exit(0);
}
More information about the Comp.sys.sgi
mailing list