Path: utzoo!attcan!uunet!mcsun!hp4nl!charon!guido From: guido@cwi.nl (Guido van Rossum) Newsgroups: comp.sys.sgi Subject: Re: Sound on PI?? Help!! Message-ID: <2303@charon.cwi.nl> Date: 10 Oct 90 09:02:40 GMT References: <8868@jarthur.Claremont.EDU> <2296@charon.cwi.nl> Sender: news@cwi.nl Lines: 279 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@cwi.nl */ /************************************************************************/ #include #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); }