home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / windows3 / mtlabsnd.zip / AU.C < prev    next >
Text File  |  1993-04-26  |  6KB  |  216 lines

  1. /*
  2.  * September 25, 1991
  3.  * Copyright 1991 Guido van Rossum And Sundry Contributors
  4.  * This source code is freely redistributable and may be used for
  5.  * any purpose.  This copyright notice must be maintained. 
  6.  * Guido van Rossum And Sundry Contributors are not responsible for 
  7.  * the consequences of using this software.
  8.  */
  9.  
  10. /*
  11.  * Sound Tools Sun format with header (SunOS 4.1; see /usr/demo/SOUND).
  12.  * NeXT uses this format also, but has more format codes defined.
  13.  * DEC uses a slight variation and swaps bytes.
  14.  * We only support the common formats.
  15.  * Output is always in big-endian (Sun/NeXT) order.
  16.  */
  17.  
  18. #include "st.h"
  19.  
  20. /* Magic numbers used in Sun and NeXT audio files */
  21. #define SUN_MAGIC     0x2e736e64        /* Really '.snd' */
  22. #define SUN_INV_MAGIC    0x646e732e        /* '.snd' upside-down */
  23. #define DEC_MAGIC    0x2e736400        /* Really '\0ds.' (for DEC) */
  24. #define DEC_INV_MAGIC    0x0064732e        /* '\0ds.' upside-down */
  25. #define SUN_HDRSIZE    24            /* Size of minimal header */
  26. #define SUN_UNSPEC    ((unsigned)(~0))    /* Unspecified data size */
  27. #define SUN_ULAW    1            /* u-law encoding */
  28. #define SUN_LIN_8    2            /* Linear 8 bits */
  29. #define SUN_LIN_16    3            /* Linear 16 bits */
  30. /* The other formats are not supported by sox at the moment */
  31.  
  32. /* Private data used by writer */
  33. struct aupriv {
  34.     unsigned long data_size;
  35. };
  36.  
  37. austartread(ft) 
  38. ft_t ft;
  39. {
  40.     /* The following 6 variables represent a Sun sound header on disk.
  41.        The numbers are written as big-endians.
  42.        Any extra bytes (totalling hdr_size - 24) are an
  43.        "info" field of unspecified nature, usually a string.
  44.        By convention the header size is a multiple of 4. */
  45.     unsigned long magic;
  46.     unsigned long hdr_size;
  47.     unsigned long data_size;
  48.     unsigned long encoding;
  49.     unsigned long sample_rate;
  50.     unsigned long channels;
  51.  
  52.     register int i;
  53.     unsigned char *buf;
  54.  
  55.  
  56.     /* Check the magic word */
  57.     magic = rlong(ft);
  58.     if (magic == DEC_INV_MAGIC) {
  59.         ft->swap = 1;
  60.         report("Found inverted DEC magic word");
  61.     }
  62.     else if (magic == SUN_INV_MAGIC) {
  63.         ft->swap = 1;
  64.         report("Found inverted Sun/NeXT magic word");
  65.     }
  66.     else if (magic == SUN_MAGIC) {
  67.         ft->swap = 0;
  68.         report("Found Sun/NeXT magic word");
  69.     }
  70.     else if (magic == DEC_MAGIC) {
  71.         ft->swap = 0;
  72.         report("Found DEC magic word");
  73.     }
  74.     else
  75.         fail("Sun/NeXT/DEC header doesn't start with magic word\nTry the '.ul' file type with '-t ul -r 8000 filename'");
  76.  
  77.     /* Read the header size */
  78.     hdr_size = rlong(ft);
  79.     if (hdr_size < SUN_HDRSIZE)
  80.         fail("Sun/NeXT header size too small.");
  81.  
  82.     /* Read the data size; may be ~0 meaning unspecified */
  83.     data_size = rlong(ft);
  84.  
  85.     /* Read the encoding; there are some more possibilities */
  86.     encoding = rlong(ft);
  87.  
  88.     /* Translate the encoding into style and size parameters */
  89.     switch (encoding) {
  90.     case SUN_ULAW:
  91.         ft->info.style = ULAW;
  92.         ft->info.size = BYTE;
  93.         break;
  94.     case SUN_LIN_8:
  95.         ft->info.style = SIGN2;
  96.         ft->info.size = BYTE;
  97.         break;
  98.     case SUN_LIN_16:
  99.         ft->info.style = SIGN2;
  100.         ft->info.size = WORD;
  101.         break;
  102.     default:
  103.         report("encoding: 0x%lx", encoding);
  104.         fail("Unsupported encoding in Sun/NeXT header.\nOnly U-law, signed bytes, and signed words are supported.");
  105.         /*NOTREACHED*/
  106.     }
  107.  
  108.     /* Read the sampling rate */
  109.     sample_rate = rlong(ft);
  110.     ft->info.rate = sample_rate;
  111.  
  112.     /* Read the number of channels */
  113.     channels = rlong(ft);
  114.     ft->info.channels = channels;
  115.  
  116.     /* Skip the info string in header; print it if verbose */
  117.     hdr_size -= SUN_HDRSIZE; /* #bytes already read */
  118.     if (hdr_size > 0) {
  119.         buf = (unsigned char *) malloc(hdr_size + 1);
  120.         for(i = 0; i < hdr_size; i++) {
  121.             buf[i] = (unsigned char ) getc(ft->fp);
  122.             if (feof(ft->fp))
  123.                 fail("Unexpected EOF in Sun/NeXT header info.");
  124.         }
  125.         buf[i] = 0;
  126.         report("Input file %s: Sun header info: %s", ft->filename, buf);
  127.     }
  128. }
  129.  
  130. /* When writing, the header is supposed to contain the number of
  131.    data bytes written, unless it is written to a pipe.
  132.    Since we don't know how many bytes will follow until we're done,
  133.    we first write the header with an unspecified number of bytes,
  134.    and at the end we rewind the file and write the header again
  135.    with the right size.  This only works if the file is seekable;
  136.    if it is not, the unspecified size remains in the header
  137.    (this is legal). */
  138.  
  139. austartwrite(ft) 
  140. ft_t ft;
  141. {
  142.     struct aupriv *p = (struct aupriv *) ft->priv;
  143.     int littlendian = 0;
  144.     char *endptr;
  145.  
  146.     p->data_size = 0;
  147.     auwriteheader(ft, SUN_UNSPEC);
  148.     endptr = (char *) &littlendian;
  149.     *endptr = 1;
  150.     if (littlendian == 1)
  151.         ft->swap = 1;
  152. }
  153.  
  154. auwrite(ft, buf, samp)
  155. ft_t ft;
  156. long *buf, samp;
  157. {
  158.     struct aupriv *p = (struct aupriv *) ft->priv;
  159.     p->data_size += samp * ft->info.size;
  160.     rawwrite(ft, buf, samp);
  161. }
  162.  
  163. void
  164. austopwrite(ft)
  165. ft_t ft;
  166. {
  167.     struct aupriv *p = (struct aupriv *) ft->priv;
  168.     if (!ft->seekable)
  169.         return;
  170.     if (fseek(ft->fp, 0L, 0) != 0)
  171.         fail("Can't rewind output file to rewrite Sun header.");
  172.     auwriteheader(ft, p->data_size);
  173. }
  174.  
  175. auwriteheader(ft, data_size)
  176. ft_t ft;
  177. unsigned long data_size;
  178. {
  179.     unsigned long magic;
  180.     unsigned long hdr_size;
  181.     unsigned long encoding;
  182.     unsigned long sample_rate;
  183.     unsigned long channels;
  184.  
  185.     if (ft->info.style == ULAW && ft->info.size == BYTE)
  186.         encoding = SUN_ULAW;
  187.     else if (ft->info.style == SIGN2 && ft->info.size == BYTE)
  188.         encoding = SUN_LIN_8;
  189.     else if (ft->info.style == SIGN2 && ft->info.size == WORD)
  190.         encoding = SUN_LIN_16;
  191.     else {
  192. /*        fail("Unsupported output style/size for Sun/NeXT header.  \nOnly U-law, signed bytes, and signed words are supported."); /* */
  193.         report("SUN .AU format not specified.  Defaulting to 8khz u-law");
  194.         encoding = SUN_ULAW;
  195.         ft->info.style = ULAW;
  196.         ft->info.size = BYTE;
  197.         ft->info.rate = 8012;  /* strange but true */
  198.     }
  199.  
  200.     magic = SUN_MAGIC;
  201.     wblong(ft, magic);
  202.  
  203.     hdr_size = SUN_HDRSIZE;
  204.     wblong(ft, hdr_size);
  205.  
  206.     wblong(ft, data_size);
  207.  
  208.     wblong(ft, encoding);
  209.  
  210.     sample_rate = ft->info.rate;
  211.     wblong(ft, sample_rate);
  212.  
  213.     channels = ft->info.channels;
  214.     wblong(ft, channels);
  215. }
  216.