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