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

  1. /*
  2.  * Copyright 1991 Lance Norskog 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.  * Lance Norskog And Sundry Contributors are not responsible for 
  6.  * the consequences of using this software.
  7.  *
  8.  * September 8, 1993
  9.  * Copyright 1993 T. Allen Grider - for changes to support block type 9
  10.  * and word sized samples.  Same caveats and disclaimer as above.
  11.  *
  12.  * February 22, 1996
  13.  * by Chris Bagwell (cbagwell@sprynet.com)
  14.  * Added support for block type 8 (extended) which allows for 8-bit stereo 
  15.  * files.  Added support for saving stereo files and 16-bit files.
  16.  * Added VOC format info from audio format FAQ so I don't have to keep
  17.  * looking around for it.
  18.  */
  19.  
  20. /*
  21.  * Sound Tools Sound Blaster VOC handler sources.
  22.  */
  23.  
  24. /*------------------------------------------------------------------------
  25. The following is taken from the Audio File Formats FAQ dated 2-Jan-1995
  26. and submitted by Guido van Rossum <guido@cwi.nl>.
  27. --------------------------------------------------------------------------
  28. Creative Voice (VOC) file format
  29. --------------------------------
  30.  
  31. From: galt@dsd.es.com
  32.  
  33. (byte numbers are hex!)
  34.  
  35.     HEADER (bytes 00-19)
  36.     Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
  37.  
  38. - ---------------------------------------------------------------
  39.  
  40. HEADER:
  41. -------
  42.      byte #     Description
  43.      ------     ------------------------------------------
  44.      00-12      "Creative Voice File"
  45.      13         1A (eof to abort printing of file)
  46.      14-15      Offset of first datablock in .voc file (std 1A 00
  47.                 in Intel Notation)
  48.      16-17      Version number (minor,major) (VOC-HDR puts 0A 01)
  49.      18-19      2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11)
  50.  
  51. - ---------------------------------------------------------------
  52.  
  53. DATA BLOCK:
  54. -----------
  55.  
  56.    Data Block:  TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes)
  57.    NOTE: Terminator Block is an exception -- it has only the TYPE byte.
  58.  
  59.       TYPE   Description     Size (3-byte int)   Info
  60.       ----   -----------     -----------------   -----------------------
  61.       00     Terminator      (NONE)              (NONE)
  62.       01     Sound data      2+length of data    *
  63.       02     Sound continue  length of data      Voice Data
  64.       03     Silence         3                   **
  65.       04     Marker          2                   Marker# (2 bytes)
  66.       05     ASCII           length of string    null terminated string
  67.       06     Repeat          2                   Count# (2 bytes)
  68.       07     End repeat      0                   (NONE)
  69.       08     Extended        4                   ***
  70.  
  71.       *Sound Info Format:       **Silence Info Format:
  72.        ---------------------      ----------------------------
  73.        00   Sample Rate           00-01  Length of silence - 1
  74.        01   Compression Type      02     Sample Rate
  75.        02+  Voice Data
  76.  
  77.     ***Extended Info Format:
  78.        ---------------------
  79.        00-01  Time Constant: Mono: 65536 - (256000000/sample_rate)
  80.                              Stereo: 65536 - (25600000/(2*sample_rate))
  81.        02     Pack
  82.        03     Mode: 0 = mono
  83.                     1 = stereo
  84.  
  85.  
  86.   Marker#           -- Driver keeps the most recent marker in a status byte
  87.   Count#            -- Number of repetitions + 1
  88.                          Count# may be 1 to FFFE for 0 - FFFD repetitions
  89.                          or FFFF for endless repetitions
  90.   Sample Rate       -- SR byte = 256-(1000000/sample_rate)
  91.   Length of silence -- in units of sampling cycle
  92.   Compression Type  -- of voice data
  93.                          8-bits    = 0
  94.                          4-bits    = 1
  95.                          2.6-bits  = 2
  96.                          2-bits    = 3
  97.                          Multi DAC = 3+(# of channels) [interesting--
  98.                                        this isn't in the developer's manual]
  99.  
  100. Detailed description of new data blocks (VOC files version 1.20 and above):
  101.  
  102.         (Source is fax from Barry Boone at Creative Labs, 405/742-6622)
  103.  
  104. BLOCK 8 - digitized sound attribute extension, must preceed block 1.
  105.           Used to define stereo, 8 bit audio
  106.         BYTE bBlockID;       // = 8
  107.         BYTE nBlockLen[3];   // 3 byte length
  108.         WORD wTimeConstant;  // time constant = same as block 1
  109.         BYTE bPackMethod;    // same as in block 1
  110.         BYTE bVoiceMode;     // 0-mono, 1-stereo
  111.  
  112.         Data is stored left, right
  113.  
  114. BLOCK 9 - data block that supersedes blocks 1 and 8.  
  115.           Used for stereo, 16 bit.
  116.  
  117.         BYTE bBlockID;          // = 9
  118.         BYTE nBlockLen[3];      // length 12 plus length of sound
  119.         DWORD dwSamplesPerSec;  // samples per second, not time const.
  120.         BYTE bBitsPerSample;    // e.g., 8 or 16
  121.         BYTE bChannels;         // 1 for mono, 2 for stereo
  122.         WORD wFormat;           // see below
  123.         BYTE reserved[4];       // pad to make block w/o data 
  124.                                 // have a size of 16 bytes
  125.  
  126.         Valid values of wFormat are:
  127.  
  128.                 0x0000  8-bit unsigned PCM
  129.                 0x0001  Creative 8-bit to 4-bit ADPCM
  130.                 0x0002  Creative 8-bit to 3-bit ADPCM
  131.                 0x0003  Creative 8-bit to 2-bit ADPCM
  132.                 0x0004  16-bit signed PCM
  133.                 0x0006  CCITT a-Law
  134.                 0x0007  CCITT u-Law
  135.                 0x02000 Creative 16-bit to 4-bit ADPCM
  136.  
  137.         Data is stored left, right
  138.  
  139. ------------------------------------------------------------------------*/
  140.  
  141. #include "st.h"
  142. #include <string.h>
  143.  
  144. /* Private data for VOC file */
  145. typedef struct vocstuff {
  146.     LONG    rest;            /* bytes remaining in current block */
  147.     LONG    rate;            /* rate code (byte) of this chunk */
  148.     int        silent;            /* sound or silence? */
  149.     LONG    srate;            /* rate code (byte) of silence */
  150.     LONG    blockseek;        /* start of current output block */
  151.     LONG    samples;        /* number of samples output */
  152.     int        size;            /* word length of data */
  153.     int        channels;        /* number of sound channels */
  154.     int     extended;       /* Has an extended block been read? */
  155. } *vs_t;
  156.  
  157. #define    VOC_TERM    0
  158. #define    VOC_DATA    1
  159. #define    VOC_CONT    2
  160. #define    VOC_SILENCE    3
  161. #define    VOC_MARKER    4
  162. #define    VOC_TEXT    5
  163. #define    VOC_LOOP    6
  164. #define    VOC_LOOPEND    7
  165. #define VOC_EXTENDED    8
  166. #define VOC_DATA_16    9
  167.  
  168. #define    min(a, b)    (((a) < (b)) ? (a) : (b))
  169.  
  170. void getblock();
  171. void blockstart(P1(ft_t));
  172. void blockstop(P1(ft_t));
  173.  
  174. void vocstartread(ft) 
  175. ft_t ft;
  176. {
  177.     char header[20];
  178.     vs_t v = (vs_t) ft->priv;
  179.     int sbseek;
  180.     int littlendian = 1;
  181.     char *endptr;
  182.  
  183.     endptr = (char *) &littlendian;
  184.     /* VOC is in Little Endian format.  Swap bytes read in on */
  185.     /* Big Endian mahcines.                          */
  186.     if (!*endptr)
  187.     {
  188.         ft->swap = ft->swap ? 0 : 1;
  189.     }
  190.  
  191.     if (! ft->seekable)
  192.         fail("VOC input file must be a file, not a pipe");
  193.     if (fread(header, 1, 20, ft->fp) != 20)
  194.         fail("unexpected EOF in VOC header");
  195.     if (strncmp(header, "Creative Voice File\032", 19))
  196.         fail("VOC file header incorrect");
  197.  
  198.     sbseek = rshort(ft);
  199.     fseek(ft->fp, sbseek, 0);
  200.  
  201.     v->rate = -1;
  202.     v->rest = 0;
  203.     v->extended = 0;
  204.     getblock(ft);
  205.     if (v->rate == -1)
  206.         fail("Input .voc file had no sound!");
  207.  
  208.     ft->info.size = v->size;
  209.     ft->info.style = UNSIGNED;
  210.     if (v->size == WORD)
  211.         ft->info.style = SIGN2;
  212.     if (ft->info.channels == -1)
  213.         ft->info.channels = v->channels;
  214. }
  215.  
  216. LONG vocread(ft, buf, len) 
  217. ft_t ft;
  218. LONG *buf, len;
  219. {
  220.     vs_t v = (vs_t) ft->priv;
  221.     int done = 0;
  222.     
  223.     if (v->rest == 0)
  224.         getblock(ft);
  225.     if (v->rest == 0)
  226.         return 0;
  227.  
  228.     if (v->silent) {
  229.         /* Fill in silence */
  230.         for(;v->rest && (done < len); v->rest--, done++)
  231.             *buf++ = 0x80000000L;
  232.     } else {
  233.         for(;v->rest && (done < len); v->rest--, done++) {
  234.             LONG datum;
  235.             switch(v->size)
  236.             {
  237.                 case BYTE:
  238.                 if ((datum = getc(ft->fp)) == EOF) {
  239.                     warn("VOC input: short file");
  240.                     v->rest = 0;
  241.                     return done;
  242.                 }
  243.                 datum ^= 0x80;    /* convert to signed */
  244.                 *buf++ = LEFT(datum, 24);
  245.                 break;
  246.                 case WORD:
  247.                 datum = rshort(ft);
  248.                 if (feof(ft->fp))
  249.                 {
  250.                     warn("VOC input: short file");
  251.                     v->rest = 0;
  252.                     return done;
  253.                 }
  254.                 *buf++ = LEFT(datum, 16);
  255.                 v->rest--; /* Processed 2 bytes so update */
  256.                 break;
  257.             }    
  258.         }
  259.     }
  260.     return done;
  261. }
  262.  
  263. /* nothing to do */
  264. void vocstopread(ft) 
  265. ft_t ft;
  266. {
  267. }
  268.  
  269. /* When saving samples in VOC format the following outline is followed:
  270.  * If an 8-bit mono sample then use a VOC_DATA header.
  271.  * If an 8-bit stereo sample then use a VOC_EXTENDED header followed
  272.  * by a VOC_DATA header.
  273.  * If a 16-bit sample (either stereo or mono) then save with a 
  274.  * VOC_DATA_16 header.
  275.  *
  276.  * This approach will cause the output to be an its most basic format
  277.  * which will work with the oldest software (eg. an 8-bit mono sample
  278.  * will be able to be played with a really old SB VOC player.)
  279.  */
  280. void vocstartwrite(ft) 
  281. ft_t ft;
  282. {
  283.     vs_t v = (vs_t) ft->priv;
  284.     int littlendian = 1;
  285.     char *endptr;
  286.  
  287.     endptr = (char *) &littlendian;
  288.     /* VOC is in Little Endian format.  Swap whats read */
  289.     /* in on Big Endian machines.                */
  290.     if (!*endptr)
  291.     {
  292.         ft->swap = ft->swap ? 0 : 1;
  293.     }
  294.  
  295.     if (! ft->seekable)
  296.         fail("Output .voc file must be a file, not a pipe");
  297.  
  298.     v->samples = 0;
  299.  
  300.     /* File format name and a ^Z (aborts printing under DOS) */
  301.     (void) fwrite("Creative Voice File\032\032", 1, 20, ft->fp);
  302.     wshort(ft, 26);            /* size of header */
  303.     wshort(ft, 0x10a);              /* major/minor version number */
  304.     wshort(ft, 0x1129);        /* checksum of version number */
  305.  
  306.     if (ft->info.size == BYTE)
  307.       ft->info.style = UNSIGNED;
  308.     else
  309.       ft->info.style = SIGN2;
  310.     if (ft->info.channels == -1)
  311.         ft->info.channels = 1;
  312. }
  313.  
  314. void vocwrite(ft, buf, len) 
  315. ft_t ft;
  316. LONG *buf, len;
  317. {
  318.     vs_t v = (vs_t) ft->priv;
  319.     unsigned char uc;
  320.     int sw;
  321.     
  322.     if (v->samples == 0) {
  323.       /* No silence packing yet. */
  324.       v->silent = 0;
  325.       blockstart(ft);
  326.     }
  327.     v->samples += len;
  328.     while(len--) {
  329.       if (ft->info.size == BYTE) {
  330.         uc = RIGHT(*buf++, 24);
  331.         uc ^= 0x80;
  332.         putc(uc, ft->fp);
  333.       } else {
  334.         sw = (int) RIGHT(*buf++, 16);
  335.         wshort(ft,sw);
  336.           }
  337.     }
  338. }
  339.  
  340. void vocstopwrite(ft) 
  341. ft_t ft;
  342. {
  343.     blockstop(ft);
  344. }
  345.  
  346. /* Voc-file handlers */
  347.  
  348. /* Read next block header, save info, leave position at start of data */
  349. void
  350. getblock(ft)
  351. ft_t ft;
  352. {
  353.     vs_t v = (vs_t) ft->priv;
  354.     unsigned char uc, block;
  355.     ULONG sblen;
  356.     LONG new_rate;
  357.     int i;
  358.  
  359.     v->silent = 0;
  360.     while (v->rest == 0) {
  361.         if (feof(ft->fp))
  362.             return;
  363.         block = getc(ft->fp);
  364.         if (block == VOC_TERM)
  365.             return;
  366.         if (feof(ft->fp))
  367.             return;
  368.         /* 
  369.          * Size is an 24-bit value.  Currently there is no util 
  370.          * func to read this so do it this cross-platform way
  371.          *
  372.          */
  373.         uc = getc(ft->fp);
  374.         sblen = uc;
  375.         uc = getc(ft->fp);
  376.         sblen |= ((LONG) uc) << 8;
  377.         uc = getc(ft->fp);
  378.         sblen |= ((LONG) uc) << 16;
  379.         switch(block) {
  380.         case VOC_DATA: 
  381.                 uc = getc(ft->fp);
  382.             /* When DATA block preceeded by an EXTENDED     */
  383.             /* block, the DATA blocks rate value is invalid */
  384.                 if (!v->extended) {
  385.               if (uc == 0)
  386.                 fail("File %s: Sample rate is zero?");
  387.               if ((v->rate != -1) && (uc != v->rate))
  388.                 fail("File %s: sample rate codes differ: %d != %d",
  389.                  ft->filename,v->rate, uc);
  390.               v->rate = uc;
  391.               ft->info.rate = 1000000.0/(256 - v->rate);
  392.               v->channels = 1;
  393.             }
  394.             uc = getc(ft->fp);
  395.             if (uc != 0)
  396.               fail("File %s: only interpret 8-bit data!",
  397.                    ft->filename);
  398.             v->extended = 0;
  399.             v->rest = sblen - 2;
  400.             v->size = BYTE;
  401.             return;
  402.         case VOC_DATA_16:
  403.             new_rate = rlong(ft);
  404.             if (new_rate == 0)
  405.                 fail("File %s: Sample rate is zero?",ft->filename);
  406.             if ((v->rate != -1) && (new_rate != v->rate))
  407.                 fail("File %s: sample rate codes differ: %d != %d",
  408.                 ft->filename, v->rate, new_rate);
  409.             v->rate = new_rate;
  410.             ft->info.rate = new_rate;
  411.             uc = getc(ft->fp);
  412.             switch (uc)
  413.             {
  414.                 case 8:    v->size = BYTE; break;
  415.                 case 16:    v->size = WORD; break;
  416.                 default:    fail("Don't understand size %d", uc);
  417.             }
  418.             v->channels = getc(ft->fp);
  419.             getc(ft->fp);    /* unknown */
  420.             getc(ft->fp);    /* notused */
  421.             getc(ft->fp);    /* notused */
  422.             getc(ft->fp);    /* notused */
  423.             getc(ft->fp);    /* notused */
  424.             getc(ft->fp);    /* notused */
  425.             v->rest = sblen - 12;
  426.             return;
  427.         case VOC_CONT: 
  428.             v->rest = sblen;
  429.             return;
  430.         case VOC_SILENCE: 
  431.             {
  432.             unsigned short period;
  433.  
  434.             period = rshort(ft);
  435.             uc = getc(ft->fp);
  436.             if (uc == 0)
  437.                 fail("File %s: Silence sample rate is zero");
  438.             /* 
  439.              * Some silence-packed files have gratuitously
  440.              * different sample rate codes in silence.
  441.              * Adjust period.
  442.              */
  443.             if ((v->rate != -1) && (uc != v->rate))
  444.                 period = (period * (256 - uc))/(256 - v->rate);
  445.             else
  446.                 v->rate = uc;
  447.             v->rest = period;
  448.             v->silent = 1;
  449.             return;
  450.             }
  451.         case VOC_MARKER:
  452.             uc = getc(ft->fp);
  453.             uc = getc(ft->fp);
  454.             /* Falling! Falling! */
  455.         case VOC_TEXT:
  456.             {
  457.             int i;
  458.             /* Could add to comment in SF? */
  459.             for(i = 0; i < sblen; i++)
  460.                 getc(ft->fp);
  461.             }
  462.             continue;    /* get next block */
  463.         case VOC_LOOP:
  464.         case VOC_LOOPEND:
  465.             report("File %s: skipping repeat loop");
  466.             for(i = 0; i < sblen; i++)
  467.                 getc(ft->fp);
  468.             break;
  469.         case VOC_EXTENDED:
  470.             /* An Extended block is followed by a data block */
  471.             /* Set this byte so we know to use the rate      */
  472.             /* value from the extended block and not the     */
  473.             /* data block.                     */
  474.             v->extended = 1;
  475.             new_rate = rshort(ft);
  476.             if (new_rate == 0)
  477.                fail("File %s: Sample rate is zero?");
  478.             if ((v->rate != -1) && (new_rate != v->rate))
  479.                fail("File %s: sample rate codes differ: %d != %d",
  480.                     ft->filename, v->rate, new_rate);
  481.             v->rate = new_rate;
  482.             uc = getc(ft->fp);
  483.             if (uc != 0)
  484.                 fail("File %s: only interpret 8-bit data!",
  485.                     ft->filename);
  486.             uc = getc(ft->fp);
  487.             if (uc)
  488.                 ft->info.channels = 2;  /* Stereo */
  489.             /* Needed number of channels before finishing
  490.                compute for rate */
  491.             ft->info.rate = (256000000L/(65536L - v->rate))/ft->info.channels;
  492.             /* An extended block must be followed by a data */
  493.             /* block to be valid so loop back to top so it  */
  494.             /* can be grabed.                */
  495.             continue;
  496.         default:
  497.             report("File %s: skipping unknown block code %d",
  498.                 ft->filename, block);
  499.             for(i = 0; i < sblen; i++)
  500.                 getc(ft->fp);
  501.         }
  502.     }
  503. }
  504.  
  505. /* Start an output block. */
  506. void blockstart(ft)
  507. ft_t ft;
  508. {
  509.     vs_t v = (vs_t) ft->priv;
  510.  
  511.     v->blockseek = ftell(ft->fp);
  512.     if (v->silent) {
  513.         putc(VOC_SILENCE, ft->fp);    /* Silence block code */
  514.         putc(0, ft->fp);        /* Period length */
  515.         putc(0, ft->fp);        /* Period length */
  516.         putc((int) v->rate, ft->fp);        /* Rate code */
  517.     } else {
  518.       if (ft->info.size == BYTE) {
  519.         /* 8-bit sample section.  By always setting the correct     */
  520.         /* rate value in the DATA block (even when its preceeded    */
  521.         /* by an EXTENDED block) old software can still play stereo */
  522.         /* files in mono by just skipping over the EXTENDED block.  */
  523.         /* Prehaps the rate should be doubled though to make up for */
  524.         /* double amount of samples for a given time????            */
  525.         if (ft->info.channels > 1) {
  526.           putc(VOC_EXTENDED, ft->fp);    /* Voice Extended block code */
  527.           putc(4, ft->fp);                /* block length = 4 */
  528.           putc(0, ft->fp);                /* block length = 4 */
  529.           putc(0, ft->fp);                /* block length = 4 */
  530.           v->rate = 65536L - (256000000.0/(2*(float)ft->info.rate));
  531.           wshort(ft,v->rate);    /* Rate code */
  532.           putc(0, ft->fp);                /* File is not packed */
  533.           putc(1, ft->fp);                /* samples are in stereo */
  534.         }
  535.         putc(VOC_DATA, ft->fp);        /* Voice Data block code */
  536.         putc(0, ft->fp);        /* block length (for now) */
  537.         putc(0, ft->fp);        /* block length (for now) */
  538.         putc(0, ft->fp);        /* block length (for now) */
  539.         v->rate = 256 - (1000000.0/(float)ft->info.rate);
  540.         putc((int) v->rate, ft->fp);/* Rate code */
  541.         putc(0, ft->fp);        /* 8-bit raw data */
  542.     } else {
  543.         putc(VOC_DATA_16, ft->fp);        /* Voice Data block code */
  544.         putc(0, ft->fp);        /* block length (for now) */
  545.         putc(0, ft->fp);        /* block length (for now) */
  546.         putc(0, ft->fp);        /* block length (for now) */
  547.         v->rate = ft->info.rate;
  548.         wlong(ft, v->rate);    /* Rate code */
  549.         putc(16, ft->fp);        /* Sample Size */
  550.         putc(ft->info.channels, ft->fp);    /* Sample Size */
  551.         putc(0, ft->fp);        /* Unknown */
  552.         putc(0, ft->fp);        /* Unused */
  553.         putc(0, ft->fp);        /* Unused */
  554.         putc(0, ft->fp);        /* Unused */
  555.         putc(0, ft->fp);        /* Unused */
  556.         putc(0, ft->fp);        /* Unused */
  557.       }
  558.     }
  559. }
  560.  
  561. /* End the current data or silence block. */
  562. void blockstop(ft) 
  563. ft_t ft;
  564. {
  565.     vs_t v = (vs_t) ft->priv;
  566.     LONG datum;
  567.  
  568.     putc(0, ft->fp);            /* End of file block code */
  569.     fseek(ft->fp, v->blockseek, 0);        /* seek back to block length */
  570.     fseek(ft->fp, 1, 1);            /* seek forward one */
  571.     if (v->silent) {
  572.         wshort(ft, v->samples);
  573.     } else {
  574.       if (ft->info.size == BYTE) {
  575.         if (ft->info.channels > 1) {
  576.           fseek(ft->fp, 8, 1); /* forward 7 + 1 for new block header */
  577.         }
  578.       }
  579.             v->samples += 2;        /* adjustment: SBDK pp. 3-5 */
  580.         datum = (v->samples) & 0xff;
  581.         putc((int)datum, ft->fp);       /* low byte of length */
  582.         datum = (v->samples >> 8) & 0xff;
  583.         putc((int)datum, ft->fp);  /* middle byte of length */
  584.         datum = (v->samples >> 16) & 0xff;
  585.         putc((int)datum, ft->fp); /* high byte of length */
  586.     }
  587. }
  588.  
  589.