home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Sound / SoX / Source / au.c < prev    next >
C/C++ Source or Header  |  1999-07-18  |  10KB  |  365 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993 Guido van Rossum And Sundry Contributors.
  3.  * This source code is freely redistributable and may be used for
  4.  * any purpose.  This copyright notice must be maintained. 
  5.  * Guido van Rossum And Sundry Contributors are not responsible for 
  6.  * the consequences of using this software.
  7.  *
  8.  * October 7, 1998 - cbagwell@sprynet.com
  9.  *   G.723 was using incorrect # of bits.  Corrected to 3 and 5 bits.
  10.  */
  11.  
  12. /*
  13.  * Sound Tools Sun format with header (SunOS 4.1; see /usr/demo/SOUND).
  14.  * NeXT uses this format also, but has more format codes defined.
  15.  * DEC uses a slight variation and swaps bytes.
  16.  * We only support the common formats.
  17.  * CCITT G.721 (32 kbit/s) and G.723 (24/40 kbit/s) are also supported,
  18.  * courtesy Sun's public domain implementation.
  19.  * Output is always in big-endian (Sun/NeXT) order.
  20.  */
  21.  
  22. #include "st.h"
  23. #include "g72x.h"
  24. #include <stdlib.h>
  25. #ifdef HAVE_MALLOC_H
  26. #include <malloc.h>
  27. #endif
  28.  
  29. /* Magic numbers used in Sun and NeXT audio files */
  30. #define SUN_MAGIC     0x2e736e64        /* Really '.snd' */
  31. #define SUN_INV_MAGIC    0x646e732e        /* '.snd' upside-down */
  32. #define DEC_MAGIC    0x2e736400        /* Really '\0ds.' (for DEC) */
  33. #define DEC_INV_MAGIC    0x0064732e        /* '\0ds.' upside-down */
  34. #define SUN_HDRSIZE    24            /* Size of minimal header */
  35. #define SUN_UNSPEC    ((unsigned)(~0))    /* Unspecified data size */
  36. #define SUN_ULAW    1            /* u-law encoding */
  37. #define SUN_LIN_8    2            /* Linear 8 bits */
  38. #define SUN_LIN_16    3            /* Linear 16 bits */
  39. #define SUN_LIN_24    4            /* Linear 24 bits */
  40. #define SUN_LIN_32    5            /* Linear 32 bits */
  41. #define SUN_FLOAT    6            /* IEEE FP 32 bits */
  42. #define SUN_DOUBLE    7            /* IEEE FP 64 bits */
  43. #define SUN_G721    23            /* CCITT G.721 4-bits ADPCM */
  44. #define SUN_G723_3    25            /* CCITT G.723 3-bits ADPCM */
  45. #define SUN_G723_5    26            /* CCITT G.723 5-bits ADPCM */
  46. #define SUN_ALAW    27            /* a-law encoding */
  47. /* The other formats are not supported by sox at the moment */
  48.  
  49. /* Private data */
  50. struct aupriv {
  51.     /* For writer: */
  52.     ULONG data_size;
  53.     /* For G72x decoding: */
  54.     struct g72x_state state;
  55.     int (*dec_routine)();
  56.     int dec_bits;
  57.     unsigned int in_buffer;
  58.     int in_bits;
  59. };
  60.  
  61. void auwriteheader(P2(ft_t ft, ULONG data_size));
  62. LONG rawread(P3(ft_t, LONG *, LONG));
  63. void rawwrite(P3(ft_t,LONG *, LONG));
  64.  
  65. void austartread(ft) 
  66. ft_t ft;
  67. {
  68.     /* The following 6 variables represent a Sun sound header on disk.
  69.        The numbers are written as big-endians.
  70.        Any extra bytes (totalling hdr_size - 24) are an
  71.        "info" field of unspecified nature, usually a string.
  72.        By convention the header size is a multiple of 4. */
  73.     ULONG magic;
  74.     ULONG hdr_size;
  75.     ULONG data_size;
  76.     ULONG encoding;
  77.     ULONG sample_rate;
  78.     ULONG channels;
  79.  
  80.     register int i;
  81.     char *buf;
  82.     struct aupriv *p = (struct aupriv *) ft->priv;
  83.  
  84.     int littlendian = 1;
  85.     char *endptr;
  86.  
  87.     /* Needed for rawread() */
  88.     rawstartread(ft);
  89.  
  90.     endptr = (char *) &littlendian;
  91.     /* AU is in big endian format.  Swap whats read
  92.      * in onlittle endian machines.
  93.      */
  94.     if (*endptr)
  95.     {
  96.         ft->swap = ft->swap ? 0 : 1;
  97.     }
  98.  
  99.     /* Sanity check */
  100.     if (sizeof(struct aupriv) > PRIVSIZE)
  101.         fail(
  102. "struct aupriv is too big (%d); change PRIVSIZE in st.h and recompile sox",
  103.              sizeof(struct aupriv));
  104.  
  105.     /* Check the magic word */
  106.     magic = rlong(ft);
  107.     if (magic == DEC_INV_MAGIC) {
  108.         /* Inverted headers are not standard.  Code was probably
  109.          * left over from pre-standardize period of testing for
  110.          * endianess.  Its not hurting though.
  111.          */
  112.         ft->swap = ft->swap ? 0 : 1;
  113.         report("Found inverted DEC magic word.  Swapping bytes.");
  114.     }
  115.     else if (magic == SUN_INV_MAGIC) {
  116.         ft->swap = ft->swap ? 0 : 1;
  117.         report("Found inverted Sun/NeXT magic word. Swapping bytes.");
  118.     }
  119.     else if (magic == SUN_MAGIC) {
  120.         report("Found Sun/NeXT magic word");
  121.     }
  122.     else if (magic == DEC_MAGIC) {
  123.         report("Found DEC magic word");
  124.     }
  125.     else
  126.         fail("Sun/NeXT/DEC header doesn't start with magic word\nTry the '.ul' file type with '-t ul -r 8000 filename'");
  127.  
  128.     /* Read the header size */
  129.     hdr_size = rlong(ft);
  130.     if (hdr_size < SUN_HDRSIZE)
  131.         fail("Sun/NeXT header size too small.");
  132.  
  133.     /* Read the data size; may be ~0 meaning unspecified */
  134.     data_size = rlong(ft);
  135.  
  136.     /* Read the encoding; there are some more possibilities */
  137.     encoding = rlong(ft);
  138.  
  139.  
  140.     /* Translate the encoding into style and size parameters */
  141.     /* (Or, for G.72x, set the decoding routine and parameters) */
  142.     p->dec_routine = NULL;
  143.     p->in_buffer = 0;
  144.     p->in_bits = 0;
  145.     switch (encoding) {
  146.     case SUN_ULAW:
  147.         ft->info.style = ULAW;
  148.         ft->info.size = BYTE;
  149.         break;
  150.     case SUN_ALAW:
  151.         ft->info.style = ALAW;
  152.         ft->info.size = BYTE;
  153.     case SUN_LIN_8:
  154.         ft->info.style = SIGN2;
  155.         ft->info.size = BYTE;
  156.         break;
  157.     case SUN_LIN_16:
  158.         ft->info.style = SIGN2;
  159.         ft->info.size = WORD;
  160.         break;
  161.     case SUN_G721:
  162.         ft->info.style = SIGN2;
  163.         ft->info.size = WORD;
  164.         g72x_init_state(&p->state);
  165.         p->dec_routine = g721_decoder;
  166.         p->dec_bits = 4;
  167.         break;
  168.     case SUN_G723_3:
  169.         ft->info.style = SIGN2;
  170.         ft->info.size = WORD;
  171.         g72x_init_state(&p->state);
  172.         p->dec_routine = g723_24_decoder;
  173.         p->dec_bits = 3;
  174.         break;
  175.     case SUN_G723_5:
  176.         ft->info.style = SIGN2;
  177.         ft->info.size = WORD;
  178.         g72x_init_state(&p->state);
  179.         p->dec_routine = g723_40_decoder;
  180.         p->dec_bits = 5;
  181.         break;
  182.     default:
  183.         report("encoding: 0x%lx", encoding);
  184.         fail("Unsupported encoding in Sun/NeXT header.\nOnly U-law, signed bytes, signed words, and ADPCM are supported.");
  185.         /*NOTREACHED*/
  186.     }
  187.  
  188.     /* Read the sampling rate */
  189.     sample_rate = rlong(ft);
  190.     ft->info.rate = sample_rate;
  191.  
  192.     /* Read the number of channels */
  193.     channels = rlong(ft);
  194.     ft->info.channels = (int) channels;
  195.  
  196.     /* Skip the info string in header; print it if verbose */
  197.     hdr_size -= SUN_HDRSIZE; /* #bytes already read */
  198.     if (hdr_size > 0) {
  199.         buf = (char *) malloc(hdr_size + 1);
  200.         for(i = 0; i < hdr_size; i++) {
  201.             buf[i] = (char) getc(ft->fp);
  202.             if (feof(ft->fp))
  203.                 fail("Unexpected EOF in Sun/NeXT header info.");
  204.         }
  205.         buf[i] = '\0';
  206.         ft->comment = buf;
  207.         report("Input file %s: Sun header info: %s", ft->filename, buf);
  208.     }
  209. }
  210.  
  211. /* When writing, the header is supposed to contain the number of
  212.    data bytes written, unless it is written to a pipe.
  213.    Since we don't know how many bytes will follow until we're done,
  214.    we first write the header with an unspecified number of bytes,
  215.    and at the end we rewind the file and write the header again
  216.    with the right size.  This only works if the file is seekable;
  217.    if it is not, the unspecified size remains in the header
  218.    (this is legal). */
  219.  
  220. void austartwrite(ft) 
  221. ft_t ft;
  222. {
  223.     struct aupriv *p = (struct aupriv *) ft->priv;
  224.     int littlendian = 1;
  225.     char *endptr;
  226.  
  227.     /* Needed because of rawwrite(); */
  228.     rawstartread(ft);
  229.  
  230.     endptr = (char *) &littlendian;
  231.     /* AU is in big endian format.  Swap whats read in
  232.      * on little endian machines.
  233.      */
  234.     if (*endptr)
  235.     {
  236.         ft->swap = ft->swap ? 0 : 1;
  237.     }
  238.  
  239.     p->data_size = 0;
  240.     auwriteheader(ft, SUN_UNSPEC);
  241. }
  242.  
  243. /*
  244.  * Unpack input codes and pass them back as bytes.
  245.  * Returns 1 if there is residual input, returns -1 if eof, else returns 0.
  246.  * (Adapted from Sun's decode.c.)
  247.  */
  248. int
  249. unpack_input(ft, code)
  250. ft_t            ft;
  251. unsigned char        *code;
  252. {
  253.     struct aupriv        *p = (struct aupriv *) ft->priv;
  254.     unsigned char        in_byte;
  255.  
  256.     if (p->in_bits < p->dec_bits) {
  257.         if (fread(&in_byte, sizeof (char), 1, ft->fp) != 1) {
  258.             *code = 0;
  259.             return (-1);
  260.         }
  261.         p->in_buffer |= (in_byte << p->in_bits);
  262.         p->in_bits += 8;
  263.     }
  264.     *code = p->in_buffer & ((1 << p->dec_bits) - 1);
  265.     p->in_buffer >>= p->dec_bits;
  266.     p->in_bits -= p->dec_bits;
  267.     return (p->in_bits > 0);
  268. }
  269.  
  270. LONG auread(ft, buf, samp)
  271. ft_t ft;
  272. LONG *buf, samp;
  273. {
  274.     struct aupriv *p = (struct aupriv *) ft->priv;
  275.     unsigned char code;
  276.     int done;
  277.     if (p->dec_routine == NULL)
  278.         return rawread(ft, buf, samp);
  279.     done = 0;
  280.     while (samp > 0 && unpack_input(ft, &code) >= 0) {
  281.         *buf++ = LEFT((*p->dec_routine)(code, AUDIO_ENCODING_LINEAR,
  282.                         &p->state),
  283.                   16);
  284.         samp--;
  285.         done++;
  286.     }
  287.     return done;
  288. }
  289.  
  290. void auwrite(ft, buf, samp)
  291. ft_t ft;
  292. LONG *buf, samp;
  293. {
  294.     struct aupriv *p = (struct aupriv *) ft->priv;
  295.     p->data_size += samp * ft->info.size;
  296.     rawwrite(ft, buf, samp);
  297. }
  298.  
  299. void austopwrite(ft)
  300. ft_t ft;
  301. {
  302.     struct aupriv *p = (struct aupriv *) ft->priv;
  303.  
  304.     /* Needed because of rawwrite(). Do now to flush
  305.      * data before seeking around below.
  306.      */
  307.     rawstopwrite(ft);
  308.  
  309.     if (!ft->seekable)
  310.         return;
  311.     if (fseek(ft->fp, 0L, 0) != 0)
  312.         fail("Can't rewind output file to rewrite Sun header.");
  313.     auwriteheader(ft, p->data_size);
  314. }
  315.  
  316. void auwriteheader(ft, data_size)
  317. ft_t ft;
  318. ULONG data_size;
  319. {
  320.     ULONG magic;
  321.     ULONG hdr_size;
  322.     ULONG encoding;
  323.     ULONG sample_rate;
  324.     ULONG channels;
  325.  
  326.     if (ft->info.style == ULAW && ft->info.size == BYTE)
  327.         encoding = SUN_ULAW;
  328.     else if (ft->info.style == ALAW && ft->info.size == BYTE)
  329.         encoding = SUN_ALAW;
  330.     else if (ft->info.style == SIGN2 && ft->info.size == BYTE)
  331.         encoding = SUN_LIN_8;
  332.     else if (ft->info.style == SIGN2 && ft->info.size == WORD)
  333.         encoding = SUN_LIN_16;
  334.     else {
  335.         report("Unsupported output style/size for Sun/NeXT header or .AU format not specified.");
  336.         report("Only U-law, A-law signed bytes, and signed words are supported.");
  337.         report("Defaulting to 8khz u-law\n");
  338.         encoding = SUN_ULAW;
  339.         ft->info.style = ULAW;
  340.         ft->info.size = BYTE;
  341.         ft->info.rate = 8000;  /* strange but true */
  342.     }
  343.  
  344.     magic = SUN_MAGIC;
  345.     wlong(ft, magic);
  346.  
  347.     if (ft->comment == NULL)
  348.         ft->comment = "";
  349.     hdr_size = SUN_HDRSIZE + strlen(ft->comment);
  350.     wlong(ft, hdr_size);
  351.  
  352.     wlong(ft, data_size);
  353.  
  354.     wlong(ft, encoding);
  355.  
  356.     sample_rate = ft->info.rate;
  357.     wlong(ft, sample_rate);
  358.  
  359.     channels = ft->info.channels;
  360.     wlong(ft, channels);
  361.  
  362.     fputs(ft->comment, ft->fp);
  363. }
  364.  
  365.