home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / windows3 / mtlabsnd.zip / 8SVX.C next >
Text File  |  1993-04-26  |  8KB  |  325 lines

  1. /*
  2.  * Amiga 8SVX format handler: W V Neisius, February 1992
  3.  */
  4.  
  5. #include <math.h>
  6. #include <sys/types.h>
  7. #include "st.h"
  8.  
  9. extern errno;
  10. extern char *sys_errlist[];
  11.  
  12. /* Private data used by writer */
  13. struct svxpriv {
  14.         unsigned long nsamples;
  15.     FILE *ch[4];
  16. };
  17.  
  18. #ifndef SEEK_CUR
  19. #define SEEK_CUR        1
  20. #endif
  21. #ifndef SEEK_SET
  22. #define SEEK_SET        0
  23. #endif
  24.  
  25. /*======================================================================*/
  26. /*                         8SVXSTARTREAD                                */
  27. /*======================================================================*/
  28.  
  29. svxstartread(ft)
  30. ft_t ft;
  31. {
  32.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  33.  
  34.     char buf[12];
  35.     char *endptr;
  36.     char *chunk_buf;
  37.  
  38.     unsigned long totalsize;
  39.     unsigned long chunksize;
  40.  
  41.     int channels;
  42.     int rate;
  43.     int littlendian = 0;
  44.     int i;
  45.  
  46.     unsigned long chan1_pos;
  47.  
  48.     rate = 0;
  49.     channels = 1;
  50.  
  51.     /* read FORM chunk */
  52.     if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "FORM", 4) != 0)
  53.         fail("8SVX: header does not begin with magic word 'FORM'");
  54.     totalsize = rblong(ft);
  55.     if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "8SVX", 4) != 0)
  56.         fail("8SVX: 'FORM' chunk does not specify '8SVX' as type");
  57.  
  58.     /* read chunks until 'BODY' (or end) */
  59.     while (fread(buf,1,4,ft->fp) == 4 && strncmp(buf,"BODY",4) != 0) {
  60.         if (strncmp(buf,"VHDR",4) == 0) {
  61.             chunksize = rblong(ft);
  62.             if (chunksize != 20)
  63.                 fail ("8SVX: VHDR chunk has bad size");
  64.             fseek(ft->fp,12,SEEK_CUR);
  65.             rate = rbshort(ft);
  66.             fseek(ft->fp,1,SEEK_CUR);
  67.             fread(buf,1,1,ft->fp);
  68.             if (buf[0] != 0)
  69.                 fail ("8SVX: unsupported data compression");
  70.             fseek(ft->fp,4,SEEK_CUR);
  71.             continue;
  72.         }
  73.  
  74.         if (strncmp(buf,"ANNO",4) == 0) {
  75.             chunksize = rblong(ft);
  76.             if (chunksize & 1)
  77.                 chunksize++;
  78.             chunk_buf = (char *) malloc(chunksize + 1);
  79.             if (fread(chunk_buf,1,(size_t)chunksize,ft->fp) 
  80.                     != chunksize)
  81.                 fail("8SVX: Unexpected EOF in ANNO header");
  82.             chunk_buf[chunksize] = '\0';
  83.             report ("%s",chunk_buf);
  84.             free(chunk_buf);
  85.  
  86.             continue;
  87.         }
  88.  
  89.         if (strncmp(buf,"NAME",4) == 0) {
  90.             chunksize = rblong(ft);
  91.             if (chunksize & 1)
  92.                 chunksize++;
  93.             chunk_buf = (char *) malloc(chunksize + 1);
  94.             if (fread (chunk_buf,1,(size_t)chunksize,ft->fp) 
  95.                     != chunksize)
  96.                 fail("8SVX: Unexpected EOF in NAME header");
  97.             chunk_buf[chunksize] = '\0';
  98.             report ("%s",chunk_buf);
  99.             free(chunk_buf);
  100.  
  101.             continue;
  102.         }
  103.  
  104.         if (strncmp(buf,"CHAN",4) == 0) {
  105.             chunksize = rblong(ft);
  106.             if (chunksize != 4) 
  107.                 fail("8SVX: Short channel chunk");
  108.             channels = rblong(ft);
  109.             channels = (channels & 0x01) + 
  110.                     ((channels & 0x02) >> 1) +
  111.                        ((channels & 0x04) >> 2) + 
  112.                     ((channels & 0x08) >> 3);
  113.  
  114.             continue;
  115.         }
  116.  
  117.         /* some other kind of chunk */
  118.         chunksize = rblong(ft);
  119.         if (chunksize & 1)
  120.             chunksize++;
  121.         fseek(ft->fp,chunksize,SEEK_CUR);
  122.         continue;
  123.  
  124.     }
  125.  
  126.     if (rate == 0)
  127.         fail ("8SVX: invalid rate");
  128.     if (strncmp(buf,"BODY",4) != 0)
  129.         fail ("8SVX: BODY chunk not found");
  130.     p->nsamples = rblong(ft);
  131.  
  132.     ft->info.channels = channels;
  133.     ft->info.rate = rate;
  134.     ft->info.style = SIGN2;
  135.     ft->info.size = BYTE;
  136.  
  137.     /* open files to channels */
  138.     p->ch[0] = ft->fp;
  139.     chan1_pos = ftell(p->ch[0]);
  140.  
  141.     for (i = 1; i < channels; i++) {
  142.         if ((p->ch[i] = fopen(ft->filename, READBINARY)) == NULL)
  143.             fail("Can't open channel file '%s': %s",
  144.                 ft->filename, sys_errlist[errno]);
  145.  
  146.         /* position channel files */
  147.         if (fseek(p->ch[i],chan1_pos,SEEK_SET))
  148.             fail ("Can't position channel %d: %s",i,sys_errlist[errno]);
  149.         if (fseek(p->ch[i],p->nsamples/channels*i,SEEK_CUR))
  150.             fail ("Can't seek channel %d: %s",i,sys_errlist[errno]);
  151.     }
  152.  
  153.  
  154.     endptr = (char *) &littlendian;
  155.     *endptr = 1;
  156.     if (littlendian == 1)
  157.         ft->swap = 1;
  158.  
  159. }
  160.  
  161. /*======================================================================*/
  162. /*                         8SVXREAD                                     */
  163. /*======================================================================*/
  164. svxread(ft, buf, nsamp) 
  165. ft_t ft;
  166. long *buf, nsamp;
  167. {
  168.     register unsigned long datum;
  169.     int done = 0;
  170.     int i;
  171.  
  172.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  173.  
  174.     while (done < nsamp) {
  175.         for (i = 0; i < ft->info.channels; i++) {
  176.             datum = getc(p->ch[i]);
  177.             if (feof(p->ch[i]))
  178.                 return done;
  179.             /* scale signed up to long's range */
  180.             *buf++ = LEFT(datum, 24);
  181.         }
  182.         done += ft->info.channels;
  183.     }
  184.     return done;
  185. }
  186.  
  187. /*======================================================================*/
  188. /*                         8SVXSTOPREAD                                 */
  189. /*======================================================================*/
  190. svxstopread(ft)
  191. ft_t ft;
  192. {
  193.     int i;
  194.  
  195.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  196.  
  197.     /* close channel files */
  198.     for (i = 1; i < ft->info.channels; i++) {
  199.         fclose (p->ch[i]);
  200.     }
  201. }
  202.  
  203. /*======================================================================*/
  204. /*                         8SVXSTARTWRITE                               */
  205. /*======================================================================*/
  206. svxstartwrite(ft)
  207. ft_t ft;
  208. {
  209.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  210.     int littlendian = 0;
  211.     int i;
  212.     char *endptr;
  213.  
  214.     /* open channel output files */
  215.     p->ch[0] = ft->fp;
  216.     for (i = 1; i < ft->info.channels; i++) {
  217.         if ((p->ch[i] = tmpfile()) == NULL)
  218.             fail("Can't open channel output file: %s",
  219.                 sys_errlist[errno]);
  220.     }
  221.  
  222.     /* write header (channel 0) */
  223.     ft->info.style = SIGN2;
  224.     ft->info.size = BYTE;
  225.  
  226.     p->nsamples = 0;
  227.     svxwriteheader(ft, p->nsamples);
  228.  
  229.     endptr = (char *) &littlendian;
  230.     *endptr = 1;
  231.     if (littlendian == 1)
  232.         ft->swap = 1;
  233. }
  234.  
  235. /*======================================================================*/
  236. /*                         8SVXWRITE                                    */
  237. /*======================================================================*/
  238.  
  239. svxwrite(ft, buf, len)
  240. ft_t ft;
  241. long *buf, len;
  242. {
  243.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  244.  
  245.     register long datum;
  246.     int done = 0;
  247.     int i;
  248.  
  249.     p->nsamples += len;
  250.  
  251.     while(done < len) {
  252.         for (i = 0; i < ft->info.channels; i++) {
  253.             datum = RIGHT(*buf++, 24);
  254.             putc((int)datum, p->ch[i]);
  255.         }
  256.         done += ft->info.channels;
  257.     }
  258. }
  259.  
  260. /*======================================================================*/
  261. /*                         8SVXSTOPWRITE                                */
  262. /*======================================================================*/
  263.  
  264. svxstopwrite(ft)
  265. ft_t ft;
  266. {
  267.     struct svxpriv *p = (struct svxpriv *) ft->priv;
  268.  
  269.     int i;
  270.     int len;
  271.     char svxbuf[512];
  272.  
  273.     /* append all channel pieces to channel 0 */
  274.     /* close temp files */
  275.     for (i = 1; i < ft->info.channels; i++) {
  276.         if (fseek (p->ch[i], 0L, 0))
  277.             fail ("Can't rewind channel output file %d",i);
  278.         while (!feof(p->ch[i])) {
  279.             len = fread (svxbuf, 1, 512, p->ch[i]);
  280.             fwrite (svxbuf, 1, len, p->ch[0]);
  281.         }
  282.         fclose (p->ch[i]);
  283.     }
  284.  
  285.     /* fixup file sizes in header */
  286.     if (fseek(ft->fp, 0L, 0) != 0)
  287.         fail("can't rewind output file to rewrite 8SVX header");
  288.     svxwriteheader(ft, p->nsamples);
  289. }
  290.  
  291. /*======================================================================*/
  292. /*                         8SVXWRITEHEADER                              */
  293. /*======================================================================*/
  294. #define SVXHEADERSIZE 100
  295. svxwriteheader(ft,nsamples)
  296. ft_t ft;
  297. long nsamples;
  298. {
  299.     fputs ("FORM", ft->fp);
  300.     wblong(ft, nsamples + SVXHEADERSIZE - 8);  /* size of file */
  301.     fputs("8SVX", ft->fp); /* File type */
  302.  
  303.     fputs ("VHDR", ft->fp);
  304.     wblong(ft, (long) 20); /* number of bytes to follow */
  305.     wblong(ft, nsamples);  /* samples, 1-shot */
  306.     wblong(ft, (long) 0);  /* samples, repeat */
  307.     wblong(ft, (long) 0);  /* samples per repeat cycle */
  308.     wbshort(ft, ft->info.rate); /* samples per second */
  309.     fputc(1,ft->fp); /* number of octaves */
  310.     fputc(0,ft->fp); /* data compression (none) */
  311.     wbshort(ft,1); wbshort(ft,0); /* volume */
  312.  
  313.     fputs ("ANNO", ft->fp);
  314.     wblong(ft, (long) 32); /* length of block */
  315.     fputs ("File created by Sound Exchange  ", ft->fp);
  316.  
  317.     fputs ("CHAN", ft->fp);
  318.     wblong(ft, (long) 4);
  319.     wblong(ft, (ft->info.channels == 2) ? (long) 6 :
  320.            (ft->info.channels == 4) ? (long) 15 : (long) 2);
  321.  
  322.     fputs ("BODY", ft->fp);
  323.     wblong(ft, nsamples); /* samples in file */
  324. }
  325.