"Fossies" - the Fresh Open Source Software archive

Member "tplay-0.6.1/au.c" of archive tplay-0.6.1.tar.gz:


/* 
 * tplay - buffered audio player
 *
 * (c) 1997 ilkka karvinen <ik@iki.fi>
 *
 * Copyright under the GNU GENERAL PUBLIC LICENSE
 *   (see the file COPYING in this directory)
 *
 * 
 *   SunOS audio file header functions.
 *   Reference: http://www.wotsit.demon.co.uk/formats/au/au.txt
 */

#include "common.h"
#include "audio.h"

/* read_au returns zero if Sun audio file format is found. */
int read_au(byte *buffer)
{
  DWORD magic, start, end, encoding, speed, channels;
  int bits;
  int i, comment_size;

  /* If '.snd'-header exits, this should be an au-file */
  magic    = read_big_endian_long(buffer);
  if (magic != SUN_MAGIC) {
    if (magic == SUN_INV_MAGIC) 
      info.swap = TRUE;
    else
      return(1);
  }
      
  start    = read_big_endian_long(buffer+0x04);
  end      = read_big_endian_long(buffer+0x08);
  encoding = read_big_endian_long(buffer+0x0C);
  speed    = read_big_endian_long(buffer+0x10);
  channels = read_big_endian_long(buffer+0x14);

  bits = DEFAULT_BITS;
  switch(encoding) {
  case 1 :
    /* 8-bit ISDN u-law */
    encoding = ULAW_BITS;
    bits = 8;
    break;
  case 2 :
    /* 8-bit linear PCM */
    encoding = LIN8_BITS;
    bits = 8;
    break;
  case 3 :
    /* 16-bit linear PCM */
    encoding = LIN_BITS;
    bits = 16;
    break;
  case 4 :
    die("24-bit linear PCM Sun audio file not supported");
    break;
  case 5 :
    die("32-bit linear PCM Sun audio file not supported");
    break;
  case 6 :
    die("32-bit IEEE floating point Sun audio file not supported");
    break;
  case 7 :
    die("64-bit IEEE floating point Sun audio file not supported");
    break;
  case 23 :
    die("8-bit ISDN u-law compressed(G.721 ADPCM) Sun audio file \
not supported");
    break;
  case 27 :
    /* 8-bit a-law */
    bits = 8;
    encoding = ALAW_BITS;
    break;
  default :
    errdie("Unknown Sun audio file");
    break;
  }

  info.filetype = SUN_FILE;

  /* Set audio parameters */
  info.speed    = (int)speed;
  info.bits     = bits;
  info.encoding = encoding;
  info.channels = (int)channels;

  if (info.verbose) {
    printf("Sun audio file: %d samples/s, %d bits, %d channel%s.\n",
	   (int)speed, (int)bits, (int)channels, ((channels != 1) 
						    ? "s" : ""));
    if ((comment_size = start - SUN_HDRSIZE) > 0) {
      printf("Header info: ");
      for (i=0; i<comment_size; i++)
	nice_fputc((int)buffer[SUN_HDRSIZE + i], stdout);
      printf("\n");
    }
  }

  /* Move data to start from the beginning of the buffer.            */
  /* This is to ensure the correct behaviour of rounding when 16bits */
  /* and/or stereo sample is to be played.                           */
  memmove(buffer, buffer+(start+1), info.blocksize-start-1);

  info.headerskip = (int)(start + 1);

  return(0);
}

/* write_au returns buffer offset if header is successfully written. */
/* here we overload bits to mean the encoding type */
int write_au(byte *buffer, int speed, int bits, int channels)
{
  DWORD encoding;

  switch(bits) {
  case ULAW_BITS :
    encoding = 1;
    break;
  case ALAW_BITS :
    encoding = 27;
    break;
  case LIN8_BITS :
    encoding = 2;
    break;
  case LIN_BITS :
    encoding = 3;
    break;
  default :
    return(0);
    break;
  }

  write_big_endian_long(buffer,      (DWORD)SUN_MAGIC);
  write_big_endian_long(buffer+0x04, (DWORD)44);
  write_big_endian_long(buffer+0x08, (DWORD)~0);
  write_big_endian_long(buffer+0x0C, (DWORD)encoding);
  write_big_endian_long(buffer+0x10, (DWORD)speed);
  write_big_endian_long(buffer+0x14, (DWORD)channels);

  return(44);
}