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

  1. /* Yamaha TX-16W sampler file support
  2.  *
  3.  * May 20, 1993
  4.  * Copyright 1993 Rob Talley   (rob@aii.com)
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose. This copyright notice and the following copyright 
  7.  * notice must be maintained intact. No warranty whatsoever is
  8.  * provided. This code is furnished AS-IS as a component of the
  9.  * larger work Copyright 1991 Lance Norskog and Sundry Contributors.
  10.  * Much appreciation to ross-c  for his sampConv utility for SGI/IRIX
  11.  * from where these methods were derived.
  12.  *
  13.  * Jan 24, 1994
  14.  * Pat McElhatton, HP Media Technology Lab <patmc@apollo.hp.com>
  15.  * Handles reading of files which do not have the sample rate field
  16.  * set to one of the expected by looking at some other bytes in the
  17.  * attack/loop length fields, and defaulting to 33kHz if the sample
  18.  * rate is still unknown.
  19.  *
  20.  * January 12, 1995
  21.  * Copyright 1995 Mark Lakata (lakata@physics.berkeley.edu)
  22.  * Additions to tx16w.c SOX driver.  This version writes as well as
  23.  * reads TX16W format.
  24.  *
  25.  * July 31, 1998
  26.  * Cleaned up by Leigh Smith (leigh@psychokiller.dialix.oz.au)
  27.  * for incorporation into the main sox distribution.
  28.  *
  29.  * September 24, 1998
  30.  * Forced output to mono signed words to match input.  It was basically
  31.  * doing this anyways but now the user will see a display that its being
  32.  * overriding.  cbagwell@sprynet.com
  33.  *
  34.  */
  35.  
  36. #define TXMAXLEN 0x3FF80
  37.  
  38. /*
  39.  * Sound Tools skeleton file format driver.
  40.  */
  41.  
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include "st.h"
  45.  
  46. /* Private data for TX16 file */
  47. typedef struct txwstuff {
  48.     LONG    rest;            /* bytes remaining in sample file */
  49. } *txw_t;
  50.  
  51. IMPORT float volume, amplitude;
  52. IMPORT int summary, verbose;
  53.  
  54. struct WaveHeader_ {
  55.   char filetype[6]; /* = "LM8953", */
  56.   unsigned char
  57.     nulls[10],
  58.     dummy_aeg[6],    /* space for the AEG (never mind this) */
  59.     format,          /* 0x49 = looped, 0xC9 = non-looped */
  60.     sample_rate,     /* 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz */
  61.     atc_length[3],   /* I'll get to this... */
  62.     rpt_length[3],
  63.     unused[2];       /* set these to null, to be on the safe side */
  64. } ;
  65.  
  66. static unsigned char magic1[4] = {0, 0x06, 0x10, 0xF6};
  67. static unsigned char magic2[4] = {0, 0x52, 0x00, 0x52};
  68.  
  69. static LONG tx16w_len=0;
  70. static LONG writedone=0;
  71.  
  72. /*
  73.  * Do anything required before you start reading samples.
  74.  * Read file header. 
  75.  *    Find out sampling rate, 
  76.  *    size and style of samples,
  77.  *    mono/stereo/quad.
  78.  */
  79. void txwstartread(ft)
  80.      ft_t ft;
  81. {
  82.   int c;
  83.   char filetype[7];
  84.   char format;
  85.   char sample_rate;
  86.   LONG num_samp_bytes = 0;
  87.   char dummy;
  88.   char gunk[8];
  89.   int blewIt;
  90.  
  91.   txw_t sk = (txw_t) ft->priv;
  92.   /* If you need to seek around the input file. */
  93.   if (! ft->seekable)
  94.     fail("txw input file must be a file, not a pipe");
  95.  
  96.   /* This is dumb but portable, just count the bytes til EOF */
  97.   while ( getc(ft->fp) != EOF ) 
  98.     num_samp_bytes++; 
  99.   num_samp_bytes -= 32;        /* calculate num samples by sub header size */
  100.   fseek(ft->fp,0L,0);        /* rewind file */
  101.   sk->rest = num_samp_bytes;    /* set how many sample bytes to read */
  102.  
  103.   /* first 6 bytes are file type ID LM8953 */
  104.   filetype[0] = getc(ft->fp);
  105.   filetype[1] = getc(ft->fp);
  106.   filetype[2] = getc(ft->fp);
  107.   filetype[3] = getc(ft->fp);
  108.   filetype[4] = getc(ft->fp);
  109.   filetype[5] = getc(ft->fp);
  110.   filetype[6] = '\0';
  111.   for( c = 16; c > 0 ; c-- )    /* Discard next 16 bytes */
  112.     dummy = getc(ft->fp);    /* they have no meaning here */
  113.   format = getc(ft->fp);
  114.   sample_rate = getc(ft->fp);
  115.   /*
  116.    * save next 8 bytes - if sample rate is 0, then we need
  117.    *  to look at gunk[2] and gunk[5] to get real rate
  118.    */
  119.   for( c = 0; c < 8; c++ )
  120.     gunk[c] = getc(ft->fp);
  121.   /*
  122.    * We should now be pointing at start of raw sample data in file 
  123.    */
  124.  
  125.   /* Check to make sure we got a good filetype ID from file */
  126.   report("Found header filetype %s",filetype);
  127.   if(strcmp(filetype,"LM8953"))
  128.     fail("Invalid filetype ID in input file header, != LM8953");
  129.   /*
  130.    * Set up the sample rate as indicated by the header
  131.    */
  132.  
  133.   switch( sample_rate ) {
  134.   case 1:
  135.     ft->info.rate = 33000;
  136.     break;
  137.   case 2:
  138.     ft->info.rate = 50000;
  139.     break;
  140.   case 3:
  141.     ft->info.rate = 16000;
  142.     break;
  143.   default:
  144.     blewIt = 1;
  145.     switch( gunk[2] & 0xFE ) {
  146.     case 0x06:
  147.       if ( (gunk[5] & 0xFE) == 0x52 ) {
  148.     blewIt = 0;
  149.     ft->info.rate = 33000;
  150.       }
  151.       break;
  152.     case 0x10:
  153.       if ( (gunk[5] & 0xFE) == 0x00 ) {
  154.     blewIt = 0;
  155.     ft->info.rate = 50000;
  156.       }
  157.       break;
  158.     case 0xF6:
  159.       if ( (gunk[5] & 0xFE) == 0x52 ) {
  160.     blewIt = 0;
  161.     ft->info.rate = 16000;
  162.       }
  163.       break;
  164.     }
  165.     if ( blewIt ) {
  166.       report("Invalid sample rate identifier found %d", (int)sample_rate);
  167.       ft->info.rate = 33000;
  168.     }
  169.   }
  170.   report("Sample rate = %ld",ft->info.rate);
  171.  
  172.   ft->info.channels = 1 ; /* not sure about stereo sample data yet ??? */
  173.   ft->info.size = WORD; /* this is close enough */
  174.   ft->info.style = SIGN2;
  175. }
  176.  
  177. /*
  178.  * Read up to len samples from file.
  179.  * Convert to signed LONGs.
  180.  * Place in buf[].
  181.  * Return number of samples read.
  182.  */
  183.  
  184. LONG txwread(ft, buf, len)
  185. ft_t ft;
  186. LONG *buf, len;
  187. {
  188.     txw_t sk = (txw_t) ft->priv;
  189.     int done = 0;
  190.     unsigned char uc1,uc2,uc3;
  191.     unsigned short s1,s2;
  192.  
  193.         /*
  194.      * This gets called by the top level 'process' routine.
  195.      * We will essentially get called with a buffer pointer
  196.      * and a max length to read. Graciously, it is always
  197.      * an even amount so we don't have to worry about
  198.      * hanging onto the left over odd samples since there
  199.      * won't be any. Something to look out for though :-(
  200.      * We return the number of samples we read.
  201.      * We will get called over and over again until we return
  202.      *  0 bytes read.
  203.      */
  204.  
  205.     /*
  206.      * This is ugly but it's readable!
  207.      * Read three bytes from stream, then decompose these into
  208.      * two unsigned short samples. 
  209.      * TCC 3.0 appeared to do unwanted things, so we really specify
  210.      *  exactly what we want to happen.
  211.      * Convert unsigned short to LONG then shift up the result
  212.      *  so that the 12-bit sample lives in the most significant
  213.      *  12-bits of the LONG.
  214.      * This gets our two samples into the internal format which we
  215.      * deposit into the given buffer and adjust our counts respectivly.
  216.          */
  217.         for(done = 0; done < len; ) {
  218.         if(sk->rest <= 0) break; /* Finished reading from file? */
  219.         uc1 = (unsigned char)getc(ft->fp); /* read the three bytes */
  220.         uc2 = (unsigned char)getc(ft->fp);
  221.         uc3 = (unsigned char)getc(ft->fp);
  222.         sk->rest -= 3; /* adjust remaining for bytes we just read */
  223.         s1 = (unsigned short) (uc1 << 4) | (((uc2 >> 4) & 017));
  224.         s2 = (unsigned short) (uc3 << 4) | (( uc2 & 017 ));
  225.         *buf = (LONG) s1;
  226.             *buf = (*buf << 20);
  227.         buf++; /* sample one is done */
  228.         *buf = (LONG) s2;
  229.             *buf = (*buf << 20);
  230.         buf++; /* sample two is done */
  231.         done += 2; /* adjust converted & stored sample count */
  232.         }
  233.     return done;
  234. }
  235.  
  236. /*
  237.  * Do anything required when you stop reading samples.  
  238.  * Don't close input file! 
  239.  */
  240. void txwstopread(ft)
  241. ft_t ft;
  242. {
  243. }
  244.  
  245. void txwstartwrite(ft)
  246. ft_t ft;
  247. {
  248.   struct WaveHeader_ WH;
  249.  
  250.   report("tx16w selected output");
  251.  
  252.   if (ft->info.channels != 1)
  253.       report("tx16w is overriding output format to 1 channel.");
  254.   ft->info.channels = 1 ; /* not sure about stereo sample data yet ??? */
  255.   if (ft->info.size != WORD || ft->info.style != SIGN2)
  256.       report("tx16w is overriding output format to size Signed Word format.");
  257.   ft->info.size = WORD; /* this is close enough */
  258.   ft->info.style = SIGN2;
  259.   
  260.   /* If you have to seek around the output file */
  261.   if (! ft->seekable)
  262.       fail("Output .txw file must be a file, not a pipe");
  263.  
  264.   /* dummy numbers, just for place holder, real header is written
  265.      at end of processing, since byte count is needed */
  266.  
  267.   fwrite(&WH,1,32,ft->fp);
  268.   writedone = 32;
  269. }
  270.  
  271. void txwwrite(ft, buf, len)
  272. ft_t ft;
  273. LONG *buf, len;
  274. {
  275.     int i;
  276.         unsigned int w1,w2;
  277.         
  278.         tx16w_len += len;
  279.         if (tx16w_len > TXMAXLEN) return;
  280.         
  281.         for (i=0;i<len;i+=2) {
  282.             w1 =  *buf++ >> 20;
  283.             if (i+1==len)
  284.                 w2 = 0;
  285.             else {
  286.                 w2 =  *buf++ >> 20;
  287.             }
  288.             putc((w1 >> 4) & 0xFF,ft->fp);
  289.             putc((((w1 & 0x0F) << 4) | (w2 & 0x0F)) & 0xFF,ft->fp);
  290.             putc((w2 >> 4) & 0xFF,ft->fp);
  291.             writedone += 3;
  292.         }
  293. }
  294.  
  295. void txwstopwrite(ft)
  296. ft_t ft;
  297. {
  298.     struct WaveHeader_ WH;
  299.     int AttackLength, LoopLength, i;
  300.   
  301.     /* All samples are already written out. */
  302.     /* If file header needs fixing up, for example it needs the */
  303.     /* the number of samples in a field, seek back and write them here. */
  304.     
  305.     /* If your format specifies any of the following info. */
  306.     /*
  307.       ft->info.rate = 
  308.       ft->info.size = BYTE or WORD ...;
  309.       ft->info.style = UNSIGNED or SIGN2 ...;
  310.       ft->info.channels = 1 or 2 or 4;
  311.       */
  312.     
  313.     report("tx16w:output finished");
  314.     
  315.     strncpy(WH.filetype,"LM8953",6);
  316.     for (i=0;i<10;i++) WH.nulls[i]=0;
  317.     for (i=0;i<6;i++)  WH.dummy_aeg[i]=0;
  318.     for (i=0;i<2;i++)  WH.unused[i]=0;
  319.     for (i=0;i<2;i++)  WH.dummy_aeg[i] = 0;
  320.     for (i=2;i<6;i++)  WH.dummy_aeg[i] = 0x7F;
  321.     
  322.     WH.format = 0xC9;   /* loop off */
  323.     
  324.     /* the actual sample rate is not that important ! */  
  325.     if (ft->info.rate < 24000)      WH.sample_rate = 3;
  326.     else if (ft->info.rate < 41000) WH.sample_rate = 1;
  327.     else                            WH.sample_rate = 2;
  328.     
  329.     if (tx16w_len >= TXMAXLEN) {
  330.         fprintf(stderr,"Sound too large for TX16W. Truncating, Loop Off\n");
  331.         AttackLength       = TXMAXLEN/2;
  332.         LoopLength         = TXMAXLEN/2;
  333.     }
  334.     else if (tx16w_len >=TXMAXLEN/2) {
  335.         AttackLength       = TXMAXLEN/2;
  336.         LoopLength         = tx16w_len - TXMAXLEN/2;
  337.         if (LoopLength < 0x40) {
  338.             LoopLength   +=0x40;
  339.             AttackLength -= 0x40;
  340.         }
  341.     }    
  342.     else if (tx16w_len >= 0x80) {
  343.         AttackLength                       = tx16w_len -0x40;
  344.         LoopLength                         = 0x40;
  345.     }
  346.     else {
  347.         AttackLength                       = 0x40;
  348.         LoopLength                         = 0x40;
  349.         for(i=tx16w_len;i<0x80;i++) {
  350.             putc(0,ft->fp);
  351.             putc(0,ft->fp);
  352.             putc(0,ft->fp);
  353.             writedone += 3;
  354.         }
  355.     }
  356.  
  357.     /* Fill up to 256 byte blocks; the TX16W seems to like that */
  358.  
  359.     while ((writedone % 0x100) != 0) {
  360.         putc(0,ft->fp);
  361.         writedone++;
  362.     }
  363.  
  364.     WH.atc_length[0] = 0xFF & AttackLength;
  365.     WH.atc_length[1] = 0xFF & (AttackLength >> 8);
  366.     WH.atc_length[2] = (0x01 & (AttackLength >> 16)) +
  367.         magic1[WH.sample_rate];
  368.     
  369.     WH.rpt_length[0] = 0xFF & LoopLength;
  370.     WH.rpt_length[1] = 0xFF & (LoopLength >> 8);
  371.     WH.rpt_length[2] = (0x01 & (LoopLength >> 16)) +
  372.         magic2[WH.sample_rate];
  373.     
  374.     rewind(ft->fp);
  375.     fwrite(&WH,1,32,ft->fp);
  376. }
  377.