home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3593 / voc.c < prev   
Encoding:
C/C++ Source or Header  |  1991-07-08  |  6.1 KB  |  292 lines

  1. /*
  2.  * July 5, 1991
  3.  * Copyright 1991 Lance Norskog 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.  * Lance Norskog And Sundry Contributors are not responsible for 
  7.  * the consequences of using this software.
  8.  */
  9.  
  10. /*
  11.  * AUX Sound Blaster VOC handler sources.
  12.  */
  13.  
  14. #include "aux.h"
  15.  
  16. /* Private data for VOC file */
  17. typedef struct vocstuff {
  18.     int    rest;            /* bytes remaining in current block */
  19.     int    rate;            /* rate code (byte) of this chunk */
  20.     int    silent;            /* sound or silence? */
  21.     int    srate;            /* rate code (byte) of silence */
  22.     int    blockseek;        /* start of current output block */
  23.     int    samples;        /* number of samples output */
  24. } *vs_t;
  25.  
  26. #define    VOC_TERM    0
  27. #define    VOC_DATA    1
  28. #define    VOC_CONT    2
  29. #define    VOC_SILENCE    3
  30. #define    VOC_MARKER    4
  31. #define    VOC_TEXT    5
  32. #define    VOC_LOOP    6
  33. #define    VOC_LOOPEND    7
  34.  
  35. #define    min(a, b)    (((a) < (b)) ? (a) : (b))
  36.  
  37. extern int summary, verbose;
  38.  
  39. vocstartread(ft) 
  40. ft_t ft;
  41. {
  42.     char header[20];
  43.     vs_t v = (vs_t) ft->priv;
  44.     int sbseek;
  45.  
  46.     if (! ft->seekable)
  47.         fail("VOC input file must be a file, not a pipe");
  48.     fread(header, 1, 20, ft->fp);
  49.     if (strncmp(header, "Creative Voice File\032", 19))
  50.         fail("VOC file header incorrect");
  51.  
  52.     sbseek = rlshort(ft);
  53.     fseek(ft->fp, sbseek, 0);
  54.  
  55.     v->rate = -1;
  56.     v->rest = 0;
  57.     getblock(ft);
  58.     if (v->rate == -1)
  59.         fail("Input .voc file had no sound!");
  60.  
  61.     ft->rate = 1000000.0/(256 - v->rate);
  62.     ft->size = BYTE;
  63.     ft->style = UNSIGNED;
  64.     ft->channels = 1;
  65. }
  66.  
  67. vocread(ft, buf, len) 
  68. ft_t ft;
  69. long *buf, len;
  70. {
  71.     vs_t v = (vs_t) ft->priv;
  72.     register int datum;
  73.     int abs;
  74.     float amp;
  75.     int done = 0;
  76.     
  77.     char c;
  78.     unsigned char uc;
  79.  
  80.     unsigned long sblen;
  81.  
  82.     if (v->rest == 0)
  83.         getblock(ft);
  84.     if (v->rest == 0)
  85.         return 0;
  86.  
  87.     if (v->silent) {
  88.         /* Fill in silence */
  89.         for(;v->rest && (done < len); v->rest--, done++)
  90.             *buf++ = 0x80000000;
  91.     } else {
  92.         for(;v->rest && (done < len); v->rest--, done++) {
  93.             long l;
  94.             if ((l = getc(ft->fp)) == EOF) {
  95.                 fail("VOC input: short file"); /* */
  96.                 v->rest = 0;
  97.                 return 0;
  98.             }
  99.             l ^= 0x80;    /* convert to signed */
  100.             *buf++ = (l << 24);
  101.         }
  102.     }
  103.     return done;
  104. }
  105.  
  106. /* nothing to do */
  107. vocstopread(ft) 
  108. ft_t ft;
  109. {
  110. }
  111.  
  112. vocstartwrite(ft) 
  113. ft_t ft;
  114. {
  115.     vs_t v = (vs_t) ft->priv;
  116.     int rate;
  117.  
  118.     if (! ft->seekable)
  119.         fail("Output .voc file must be a file, not a pipe");
  120.  
  121.     v->samples = 0;
  122.  
  123.     /* File format name and a ^Z (aborts printing under DOS) */
  124.     fwrite("Creative Voice File\032\032", 1, 20, ft->fp);
  125.     wlshort(ft, 26);            /* size of header */
  126.     wlshort(ft, 0x110);            /* major/minor version number */
  127.     wlshort(ft, 0x1129);            /* checksum of version number */
  128.  
  129. }
  130.  
  131. vocwrite(ft, buf, len) 
  132. ft_t ft;
  133. long *buf, len;
  134. {
  135.     vs_t v = (vs_t) ft->priv;
  136.     register int datum;
  137.     int abs;
  138.     int done = 0;
  139.  
  140.     v->rate = (256 - (1000000/ft->rate));    /* Rate code */
  141.     if (v->samples == 0) {
  142.         /* No silence packing yet. */
  143.         v->silent = 0;
  144.         blockstart(&outformat);
  145.     }
  146.     v->samples += len;
  147.     while(len--)
  148.         putc((*buf++ >> 24) ^ 0x80, ft->fp);
  149. }
  150.  
  151. vocstopwrite(ft) 
  152. ft_t ft;
  153. {
  154.     blockstop(ft);
  155. }
  156.  
  157. /* Voc-file handlers */
  158.  
  159. /* Read next block header, save info, leave position at start of data */
  160. getblock(ft)
  161. ft_t ft;
  162. {
  163.     vs_t v = (vs_t) ft->priv;
  164.     unsigned char uc, block;
  165.     unsigned long sblen;
  166.     int i;
  167.  
  168.     char c;
  169.  
  170.     v->silent = 0;
  171.     while (v->rest == 0) {
  172.         if (feof(ft->fp))
  173.             return 0;
  174.         block = getc(ft->fp);
  175.         if (block == VOC_TERM)
  176.             return 0;
  177.         if (feof(ft->fp))
  178.             return 0;
  179.         uc = getc(ft->fp);
  180.         sblen = uc;
  181.         uc = getc(ft->fp);
  182.         sblen |= uc << 8;
  183.         uc = getc(ft->fp);
  184.         sblen |= uc << 16;
  185.         switch(block) {
  186.         case VOC_DATA: 
  187.             uc = getc(ft->fp);
  188.             if (uc == 0)
  189.                fail("File %s: Sample rate is zero?");
  190.             if ((v->rate != -1) && (uc != v->rate))
  191.                fail("File %s: sample rate codes differ: %d != %d",
  192.                     v->rate, uc);
  193.             v->rate = uc;
  194.             uc = getc(ft->fp);
  195.             if (uc != 0)
  196.                 fail("File %s: only interpret 8-bit data!");
  197.             v->rest = sblen - 2;
  198.             return;
  199.         case VOC_CONT: 
  200.             v->rest = sblen;
  201.             return;
  202.         case VOC_SILENCE: 
  203.             {
  204.             unsigned short period;
  205.  
  206.             period = rlshort(ft);
  207.             uc = getc(ft->fp);
  208.             if (uc == 0)
  209.                 fail("File %s: Silence sample rate is zero");
  210.             /* 
  211.              * Some silence-packed files have gratuitously
  212.              * different sample rate codes in silence.
  213.              * Adjust period.
  214.              */
  215.             if ((v->rate != -1) && (uc != v->rate))
  216.                 period = (period * (256 - uc))/(256 - v->rate);
  217.             else
  218.                 v->rate = uc;
  219.             v->rest = period;
  220.             v->silent = 1;
  221.             return;
  222.             }
  223.         case VOC_MARKER:
  224.             uc = getc(ft->fp);
  225.             uc = getc(ft->fp);
  226.             /* Falling! Falling! */
  227.         case VOC_TEXT:
  228.             {
  229.             int i;
  230.             /* Could add to comment in SF? */
  231.             for(i = 0; i < sblen; i++)
  232.                 getc(ft->fp);
  233.             }
  234.             continue;    /* get next block */
  235.         case VOC_LOOP:
  236.         case VOC_LOOPEND:
  237.             report("File %s: skipping repeat loop");
  238.             for(i = 0; i < sblen; i++)
  239.                 getc(ft->fp);
  240.             break;
  241.         default:
  242.             report("File %s: skipping unknown block code %d",
  243.                 ft->which, block);
  244.             for(i = 0; i < sblen; i++)
  245.                 getc(ft->fp);
  246.         }
  247.     }
  248. }
  249.  
  250. /* Start an output block. */
  251. blockstart(ft)
  252. ft_t ft;
  253. {
  254.     vs_t v = (vs_t) ft->priv;
  255.  
  256.     v->blockseek = ftell(ft->fp);
  257.     if (v->silent) {
  258.         putc(VOC_SILENCE, ft->fp);    /* Silence block code */
  259.         putc(0, ft->fp);        /* Period length */
  260.         putc(0, ft->fp);        /* Period length */
  261.         putc(v->rate, ft->fp);        /* Rate code */
  262.     } else {
  263.         putc(VOC_DATA, ft->fp);        /* Voice Data block code */
  264.         putc(0, ft->fp);        /* block length (for now) */
  265.         putc(0, ft->fp);        /* block length (for now) */
  266.         putc(0, ft->fp);        /* block length (for now) */
  267.         putc(v->rate, ft->fp);        /* Rate code */
  268.         putc(0, ft->fp);        /* 8-bit raw data */
  269.     }
  270. }
  271.  
  272. /* End the current data or silence block. */
  273. blockstop(ft) 
  274. ft_t ft;
  275. {
  276.     vs_t v = (vs_t) ft->priv;
  277.  
  278.     putc(0, ft->fp);            /* End of file block code */
  279.     fseek(ft->fp, v->blockseek, 0);        /* seek back to block length */
  280.     fseek(ft->fp, 1, 1);            /* seek forward one */
  281.     if (v->silent) {
  282.         putc(v->samples, ft->fp);    /* low byte of length */
  283.         putc(v->samples >> 8, ft->fp);    /* high byte of length */
  284.     } else {
  285.         v->samples += 2;        /* adjustment: SBDK pp. 3-5 */
  286.         putc(v->samples, ft->fp);    /* low byte of length */
  287.         putc(v->samples >> 8, ft->fp);    /* middle byte of length */
  288.         putc(v->samples >> 16, ft->fp);    /* high byte of length */
  289.     }
  290. }
  291.  
  292.