home *** CD-ROM | disk | FTP | other *** search
/ Da Capo / da_capo_vol1.bin / programs / amiga / edit / amisox3.3 / dist / hcom.c < prev    next >
C/C++ Source or Header  |  1994-01-23  |  11KB  |  476 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 Macintosh HCOM format.
  12.  * These are really FSSD type files with Huffman compression,
  13.  * in MacBinary format.
  14.  * To do: make the MacBinary format optional (so that .data files
  15.  * are also acceptable).  (How to do this on output?)
  16.  */
  17.  
  18. #include "st.h"
  19.  
  20. #ifdef __STDC__
  21. /*
  22. #include <stdlib.h>
  23. */
  24. #else
  25. #include <string.h>
  26. IMPORT char *malloc(), *realloc();
  27. #endif
  28.  
  29. /* Dictionary entry for Huffman (de)compression */
  30. typedef struct {
  31.     long frequ;
  32.     short dict_leftson;
  33.     short dict_rightson;
  34. } dictent;
  35.  
  36. /* Private data used by reader */
  37. struct readpriv {
  38.     /* Static data from the header */
  39.     dictent *dictionary;
  40.     long checksum;
  41.     int deltacompression;
  42.     /* Engine state */
  43.     long huffcount;
  44.     long cksum;
  45.     int dictentry;
  46.     int nrbits;
  47.     unsigned long current;
  48.     short sample;
  49. };
  50.  
  51. /*void*/ hcomstartread(ft)
  52. ft_t ft;
  53. {
  54.     struct readpriv *p = (struct readpriv *) ft->priv;
  55.     int i;
  56.     char buf[4];
  57.     unsigned long datasize, rsrcsize;
  58.     unsigned long huffcount, checksum, compresstype, divisor;
  59.     unsigned short dictsize;
  60.  
  61.     /* Skip first 65 bytes of header */
  62.     skipbytes(ft, 65);
  63.  
  64.     /* Check the file type (bytes 65-68) */
  65.     if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "FSSD", 4) != 0)
  66.         fail("Mac header type is not FSSD");
  67.  
  68.     /* Skip to byte 83 */
  69.     skipbytes(ft, 83-69);
  70.  
  71.     /* Get essential numbers from the header */
  72.     datasize = rblong(ft); /* bytes 83-86 */
  73.     rsrcsize = rblong(ft); /* bytes 87-90 */
  74.  
  75.     /* Skip the rest of the header (total 128 bytes) */
  76.     skipbytes(ft, 128-91);
  77.  
  78.     /* The data fork must contain a "HCOM" header */
  79.     if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "HCOM", 4) != 0)
  80.         fail("Mac data fork is not HCOM");
  81.  
  82.     /* Then follow various parameters */
  83.     huffcount = rblong(ft);
  84.     checksum = rblong(ft);
  85.     compresstype = rblong(ft);
  86.     if (compresstype > 1)
  87.         fail("Bad compression type in HCOM header");
  88.     divisor = rblong(ft);
  89.     if (divisor == 0 || divisor > 4)
  90.         fail("Bad sampling rate divisor in HCOM header");
  91.     dictsize = rbshort(ft);
  92.  
  93.     /* Translate to sox parameters */
  94.     ft->info.style = UNSIGNED;
  95.     ft->info.size = BYTE;
  96.     ft->info.rate = 22050 / divisor;
  97.     ft->info.channels = 1;
  98.  
  99.     /* Allocate memory for the dictionary */
  100.     p->dictionary = (dictent *) malloc(511 * sizeof(dictent));
  101.     if (p->dictionary == NULL)
  102.         fail("can't malloc memory for Huffman dictionary");
  103.  
  104.     /* Read dictionary */
  105.     for(i = 0; i < dictsize; i++) {
  106.         p->dictionary[i].dict_leftson = rbshort(ft);
  107.         p->dictionary[i].dict_rightson = rbshort(ft);
  108.         /*
  109.         report("%d %d",
  110.                p->dictionary[i].dict_leftson,
  111.                p->dictionary[i].dict_rightson);
  112.                */
  113.     }
  114.     skipbytes(ft, 1); /* skip pad byte */
  115.  
  116.     /* Initialized the decompression engine */
  117.     p->checksum = checksum;
  118.     p->deltacompression = compresstype;
  119.     if (!p->deltacompression)
  120.         report("HCOM data using value compression");
  121.     p->huffcount = huffcount;
  122.     p->cksum = 0;
  123.     p->dictentry = 0;
  124.     p->nrbits = -1; /* Special case to get first byte */
  125. }
  126.  
  127. /*void*/ skipbytes(ft, n)
  128. ft_t ft;
  129. int n;
  130. {
  131.     while (--n >= 0) {
  132.         if (getc(ft->fp) == EOF)
  133.             fail("unexpected EOF in Mac header");
  134.     }
  135. }
  136.  
  137. int hcomread(ft, buf, len)
  138. ft_t ft;
  139. long *buf, len;
  140. {
  141.     register struct readpriv *p = (struct readpriv *) ft->priv;
  142.     int done = 0;
  143.  
  144.     if (p->nrbits < 0) {
  145.         /* The first byte is special */
  146.         if (p->huffcount == 0)
  147.             return 0; /* Don't know if this can happen... */
  148.         p->sample = getc(ft->fp);
  149.         if (p->sample == EOF)
  150.             fail("unexpected EOF at start of HCOM data");
  151.         *buf++ = (p->sample - 128) * 0x1000000;
  152.         p->huffcount--;
  153.         p->nrbits = 0;
  154.         done++;
  155.         len--;
  156.         if (len == 0)
  157.             return done;
  158.     }
  159.  
  160.     while (p->huffcount > 0) {
  161.         if(p->nrbits == 0) {
  162.             p->current = rblong(ft);
  163.             if (feof(ft->fp))
  164.                 fail("unexpected EOF in HCOM data");
  165.             p->cksum += p->current;
  166.             p->nrbits = 32;
  167.         }
  168.         if(p->current & 0x80000000) {
  169.             p->dictentry =
  170.                 p->dictionary[p->dictentry].dict_rightson;
  171.         } else {
  172.             p->dictentry =
  173.                 p->dictionary[p->dictentry].dict_leftson;
  174.         }
  175.         p->current = p->current << 1;
  176.         p->nrbits--;
  177.         if(p->dictionary[p->dictentry].dict_leftson < 0) {
  178.             short datum;
  179.             datum = p->dictionary[p->dictentry].dict_rightson;
  180.             if (!p->deltacompression)
  181.                 p->sample = 0;
  182.             p->sample = (p->sample + datum) & 0xff;
  183.             p->huffcount--;
  184.             if (p->sample == 0)
  185.                 *buf++ = -127 * 0x1000000;
  186.             else
  187.                 *buf++ = (p->sample - 128) * 0x1000000;
  188.             p->dictentry = 0;
  189.             done++;
  190.             len--;
  191.             if (len == 0)
  192.                 break;
  193.         }
  194.     }
  195.  
  196.     return done;
  197. }
  198.  
  199. /*void*/ hcomstopread(ft) 
  200. ft_t ft;
  201. {
  202.     register struct readpriv *p = (struct readpriv *) ft->priv;
  203.  
  204.     if (p->huffcount != 0)
  205.         fail("not all HCOM data read");
  206.     if(p->cksum != p->checksum)
  207.         fail("checksum error in HCOM data");
  208.     free((char *)p->dictionary);
  209.     p->dictionary = NULL;
  210. }
  211.  
  212. struct writepriv {
  213.     unsigned char *data;    /* Buffer allocated with malloc */
  214.     unsigned int size;    /* Size of allocated buffer */
  215.     unsigned int pos;    /* Where next byte goes */
  216. };
  217.  
  218. #define BUFINCR (10*BUFSIZ)
  219.  
  220. /*void*/ hcomstartwrite(ft) 
  221. ft_t ft;
  222. {
  223.     register struct writepriv *p = (struct writepriv *) ft->priv;
  224.  
  225.     switch (ft->info.rate) {
  226.     case 22050:
  227.     case 22050/2:
  228.     case 22050/3:
  229.     case 22050/4:
  230.         break;
  231.     default:
  232.         fail("unacceptable output rate for HCOM: try 5512, 7350, 11025 or 22050 hertz");
  233.     }
  234.     ft->info.size = BYTE;
  235.     ft->info.style = UNSIGNED;
  236.     ft->info.channels = 1;
  237.  
  238.     p->size = BUFINCR;
  239.     p->pos = 0;
  240.     p->data = (unsigned char *) malloc(p->size);
  241.     if (p->data == NULL)
  242.         fail("can't malloc buffer for uncompressed HCOM data");
  243. }
  244.  
  245. /*void*/ hcomwrite(ft, buf, len)
  246. ft_t ft;
  247. long *buf, len;
  248. {
  249.     register struct writepriv *p = (struct writepriv *) ft->priv;
  250.     long datum;
  251.  
  252.     if (p->pos + len > p->size) {
  253.         p->size = ((p->pos + len) / BUFINCR + 1) * BUFINCR;
  254.         p->data = (unsigned char *) realloc(p->data, p->size);
  255.         if (p->data == NULL)
  256.             fail("can't realloc buffer for uncompressed HCOM data");
  257.     }
  258.  
  259.     while (--len >= 0) {
  260.         datum = *buf++;
  261.         datum >>= 24;
  262.         datum ^= 128;
  263.         p->data[p->pos++] = datum;
  264.     }
  265. }
  266.  
  267. /*void*/ hcomstopwrite(ft) 
  268. ft_t ft;
  269. {
  270.     register struct writepriv *p = (struct writepriv *) ft->priv;
  271.     unsigned char *data = p->data;
  272.     long len = p->pos;
  273.  
  274.     /* Compress it all at once */
  275.     compress(&data, &len, (double) ft->info.rate);
  276.     free((char *) p->data);
  277.  
  278.     /* Write the header */
  279.     (void) fwrite("\000\001A", 1, 3, ft->fp); /* Dummy file name "A" */
  280.     padbytes(ft, 65-3);
  281.     (void) fwrite("FSSD", 1, 4, ft->fp);
  282.     padbytes(ft, 83-69);
  283.     wblong(ft, (unsigned long) len); /* data size */
  284.     wblong(ft, (unsigned long) 0); /* rsrc size */
  285.     padbytes(ft, 128 - 91);
  286.     if (ferror(ft->fp))
  287.         fail("write error in HCOM header");
  288.  
  289.     /* Write the data fork */
  290.     if (fwrite((char *) data, 1, (int)len, ft->fp) != len)
  291.         fail("can't write compressed HCOM data");
  292.     free((char *) data);
  293.  
  294.     /* Pad the data fork to a multiple of 128 bytes */
  295.     padbytes(ft, 128 - (int) (len%128));
  296. }
  297.  
  298. /*void*/ padbytes(ft, n)
  299. ft_t ft;
  300. int n;
  301. {
  302.     while (--n >= 0)
  303.         putc('\0', ft->fp);
  304. }
  305.  
  306.  
  307. /* XXX This uses global variables -- one day these should all be
  308.    passed around in a structure instead. */
  309.  
  310. void putlong(c, v)
  311. unsigned char *c;
  312. long v;
  313. {
  314.   *c++ = (v >> 24) & 0xff;
  315.   *c++ = (v >> 16) & 0xff;
  316.   *c++ = (v >> 8) & 0xff;
  317.   *c++ = v & 0xff;
  318. }
  319.  
  320. void putshort(c, v)
  321. unsigned char *c;
  322. short v;
  323. {
  324.   *c++ = (v >> 8) & 0xff;
  325.   *c++ = v & 0xff;
  326. }
  327.  
  328. dictent dictionary[511];
  329. dictent *de;
  330. long codes[256];
  331. long codesize[256];
  332. long checksum;
  333.  
  334. void makecodes(e, c, s, b)
  335. int e, c, s, b;
  336. {
  337.   if(dictionary[e].dict_leftson < 0) {
  338.     codes[dictionary[e].dict_rightson] = c;
  339.     codesize[dictionary[e].dict_rightson] = s;
  340.   } else {
  341.     makecodes(dictionary[e].dict_leftson, c, s + 1, b << 1);
  342.     makecodes(dictionary[e].dict_rightson, c + b, s + 1, b << 1);
  343.   }
  344. }
  345.  
  346. long curword;
  347. int nbits;
  348.  
  349. void putcode(c, df)
  350. unsigned char c;
  351. unsigned char ** df;
  352. {
  353. long code, size;
  354. int i;
  355.   code = codes[c];
  356.   size = codesize[c];
  357.   for(i = 0; i < size; i++) {
  358.     curword = (curword << 1);
  359.     if(code & 1) curword += 1;
  360.     nbits++;
  361.     if(nbits == 32) {