home *** CD-ROM | disk | FTP | other *** search
- /*
- * July 5, 1991
- * Copyright 1991 Lance Norskog And Sundry Contributors
- * This source code is freely redistributable and may be used for
- * any purpose. This copyright notice must be maintained.
- * Lance Norskog And Sundry Contributors are not responsible for
- * the consequences of using this software.
- */
-
- /*
- * AUX Sound Blaster VOC handler sources.
- */
-
- #include "aux.h"
-
- /* Private data for VOC file */
- typedef struct vocstuff {
- int rest; /* bytes remaining in current block */
- int rate; /* rate code (byte) of this chunk */
- int silent; /* sound or silence? */
- int srate; /* rate code (byte) of silence */
- int blockseek; /* start of current output block */
- int samples; /* number of samples output */
- } *vs_t;
-
- #define VOC_TERM 0
- #define VOC_DATA 1
- #define VOC_CONT 2
- #define VOC_SILENCE 3
- #define VOC_MARKER 4
- #define VOC_TEXT 5
- #define VOC_LOOP 6
- #define VOC_LOOPEND 7
-
- #define min(a, b) (((a) < (b)) ? (a) : (b))
-
- extern int summary, verbose;
-
- vocstartread(ft)
- ft_t ft;
- {
- char header[20];
- vs_t v = (vs_t) ft->priv;
- int sbseek;
-
- if (! ft->seekable)
- fail("VOC input file must be a file, not a pipe");
- fread(header, 1, 20, ft->fp);
- if (strncmp(header, "Creative Voice File\032", 19))
- fail("VOC file header incorrect");
-
- sbseek = rlshort(ft);
- fseek(ft->fp, sbseek, 0);
-
- v->rate = -1;
- v->rest = 0;
- getblock(ft);
- if (v->rate == -1)
- fail("Input .voc file had no sound!");
-
- ft->rate = 1000000.0/(256 - v->rate);
- ft->size = BYTE;
- ft->style = UNSIGNED;
- ft->channels = 1;
- }
-
- vocread(ft, buf, len)
- ft_t ft;
- long *buf, len;
- {
- vs_t v = (vs_t) ft->priv;
- register int datum;
- int abs;
- float amp;
- int done = 0;
-
- char c;
- unsigned char uc;
-
- unsigned long sblen;
-
- if (v->rest == 0)
- getblock(ft);
- if (v->rest == 0)
- return 0;
-
- if (v->silent) {
- /* Fill in silence */
- for(;v->rest && (done < len); v->rest--, done++)
- *buf++ = 0x80000000;
- } else {
- for(;v->rest && (done < len); v->rest--, done++) {
- long l;
- if ((l = getc(ft->fp)) == EOF) {
- fail("VOC input: short file"); /* */
- v->rest = 0;
- return 0;
- }
- l ^= 0x80; /* convert to signed */
- *buf++ = (l << 24);
- }
- }
- return done;
- }
-
- /* nothing to do */
- vocstopread(ft)
- ft_t ft;
- {
- }
-
- vocstartwrite(ft)
- ft_t ft;
- {
- vs_t v = (vs_t) ft->priv;
- int rate;
-
- if (! ft->seekable)
- fail("Output .voc file must be a file, not a pipe");
-
- v->samples = 0;
-
- /* File format name and a ^Z (aborts printing under DOS) */
- fwrite("Creative Voice File\032\032", 1, 20, ft->fp);
- wlshort(ft, 26); /* size of header */
- wlshort(ft, 0x110); /* major/minor version number */
- wlshort(ft, 0x1129); /* checksum of version number */
-
- }
-
- vocwrite(ft, buf, len)
- ft_t ft;
- long *buf, len;
- {
- vs_t v = (vs_t) ft->priv;
- register int datum;
- int abs;
- int done = 0;
-
- v->rate = (256 - (1000000/ft->rate)); /* Rate code */
- if (v->samples == 0) {
- /* No silence packing yet. */
- v->silent = 0;
- blockstart(&outformat);
- }
- v->samples += len;
- while(len--)
- putc((*buf++ >> 24) ^ 0x80, ft->fp);
- }
-
- vocstopwrite(ft)
- ft_t ft;
- {
- blockstop(ft);
- }
-
- /* Voc-file handlers */
-
- /* Read next block header, save info, leave position at start of data */
- getblock(ft)
- ft_t ft;
- {
- vs_t v = (vs_t) ft->priv;
- unsigned char uc, block;
- unsigned long sblen;
- int i;
-
- char c;
-
- v->silent = 0;
- while (v->rest == 0) {
- if (feof(ft->fp))
- return 0;
- block = getc(ft->fp);
- if (block == VOC_TERM)
- return 0;
- if (feof(ft->fp))
- return 0;
- uc = getc(ft->fp);
- sblen = uc;
- uc = getc(ft->fp);
- sblen |= uc << 8;
- uc = getc(ft->fp);
- sblen |= uc << 16;
- switch(block) {
- case VOC_DATA:
- uc = getc(ft->fp);
- if (uc == 0)
- fail("File %s: Sample rate is zero?");
- if ((v->rate != -1) && (uc != v->rate))
- fail("File %s: sample rate codes differ: %d != %d",
- v->rate, uc);
- v->rate = uc;
- uc = getc(ft->fp);
- if (uc != 0)
- fail("File %s: only interpret 8-bit data!");
- v->rest = sblen - 2;
- return;
- case VOC_CONT:
- v->rest = sblen;
- return;
- case VOC_SILENCE:
- {
- unsigned short period;
-
- period = rlshort(ft);
- uc = getc(ft->fp);
- if (uc == 0)
- fail("File %s: Silence sample rate is zero");
- /*
- * Some silence-packed files have gratuitously
- * different sample rate codes in silence.
- * Adjust period.
- */
- if ((v->rate != -1) && (uc != v->rate))
- period = (period * (256 - uc))/(256 - v->rate);
- else
- v->rate = uc;
- v->rest = period;
- v->silent = 1;
- return;
- }
- case VOC_MARKER:
- uc = getc(ft->fp);
- uc = getc(ft->fp);
- /* Falling! Falling! */
- case VOC_TEXT:
- {
- int i;
- /* Could add to comment in SF? */
- for(i = 0; i < sblen; i++)
- getc(ft->fp);
- }
- continue; /* get next block */
- case VOC_LOOP:
- case VOC_LOOPEND:
- report("File %s: skipping repeat loop");
- for(i = 0; i < sblen; i++)
- getc(ft->fp);
- break;
- default:
- report("File %s: skipping unknown block code %d",
- ft->which, block);
- for(i = 0; i < sblen; i++)
- getc(ft->fp);
- }
- }
- }
-
- /* Start an output block. */
- blockstart(ft)
- ft_t ft;
- {
- vs_t v = (vs_t) ft->priv;
-
- v->blockseek = ftell(ft->fp);
- if (v->silent) {
- putc(VOC_SILENCE, ft->fp); /* Silence block code */
- putc(0, ft->fp); /* Period length */
- putc(0, ft->fp); /* Period length */
- putc(v->rate, ft->fp); /* Rate code */
- } else {
- putc(VOC_DATA, ft->fp); /* Voice Data block code */
- putc(0, ft->fp); /* block length (for now) */
- putc(0, ft->fp); /* block length (for now) */
- putc(0, ft->fp); /* block length (for now) */
- putc(v->rate, ft->fp); /* Rate code */
- putc(0, ft->fp); /* 8-bit raw data */
- }
- }
-
- /* End the current data or silence block. */
- blockstop(ft)
- ft_t ft;
- {
- vs_t v = (vs_t) ft->priv;
-
- putc(0, ft->fp); /* End of file block code */
- fseek(ft->fp, v->blockseek, 0); /* seek back to block length */
- fseek(ft->fp, 1, 1); /* seek forward one */
- if (v->silent) {
- putc(v->samples, ft->fp); /* low byte of length */
- putc(v->samples >> 8, ft->fp); /* high byte of length */
- } else {
- v->samples += 2; /* adjustment: SBDK pp. 3-5 */
- putc(v->samples, ft->fp); /* low byte of length */
- putc(v->samples >> 8, ft->fp); /* middle byte of length */
- putc(v->samples >> 16, ft->fp); /* high byte of length */
- }
- }
-
-