/* 
 * pvfvoc.c
 *
 * Converts pvf <--> voc.
 *
 */

char pvfvoc_c[] = "$Id: pvfvoc.c,v 1.8 1995/03/29 18:27:18 marc Exp $";

#include <stdio.h>
#include <string.h>

#ifndef _NOSTDLIB_H
#include <stdlib.h>
#endif

#include "../mgetty.h"
#include "pvflib.h"

static char voc_hdr[32]={
    'C','r','e','a','t','i','v','e',' ',
    'V','o','i','c','e',' ','F','i','l','e',
    0x1a,0x1a,0x00,0x0a,0x01,0x29,0x11,
    0x01,0x82,0x70,0x00,0x98,0x00
};

static char *voc_type[]={
    "8 bit",
    "4 bit",
    "2.6 bit",
    "2 bit",
    "Multi DAC, 1 channel",
    "Multi DAC, 2 channels",
    "Multi DAC, 3 channels",
    "Multi DAC, 4 channels",
    "unknown"
};
			
int
pvftovoc _P2((argc, argv), int argc, char **argv ) {
    FILE *in=stdin, *out=stdout;
    int blocksize = 0x7080;
    int count;
    long rate = RATE;

    static char voc_blk[4]={
	0x02, 0x80, 0x70, 0x00
    };
    
    if (argc > 1 && (rate=atoi(argv[1]))) {
	--argc, argv++;
    }
    
    if( argc>1 ) USAGE("[rate]");

    voc_hdr[30] = 256 - ((long)1000000/rate);

    fwrite(voc_hdr, 1, 32, out);

    count = blocksize;
    while(1) {
	int d=zget(in);
	if(feof(in)) break;
	putc((d>>8)+0x80, out);
	count--;
	if(!count) {
	    count = blocksize;
	    fwrite(voc_blk, 1, 4, out);
	}
    }
    
    while(count--)
	putc(0x7f, out);
    
    putc(0, out);
    return 0;
}

int
voctopvf _P2((argc, argv), int argc, char **argv ) {
    FILE *in=stdin, *out=stdout;
    char hdr[32];
    int verbose = 0;
    int data_offset;
    int type;
    long count, blocksize;
    
    if (argc > 1 && !strcmp(argv[1], "-info")) {
	verbose++;
	--argc, argv++;
    }
    
    if( argc>1 ) USAGE("[-info]");

    fread(hdr, 1, 0x1a, in);
    if(strncmp(hdr, voc_hdr, 0x14)) ERRORRETURN("not a VOC file");

    data_offset = hdr[0x14] | hdr[0x15]<<8;
    
    if(verbose) {
	fprintf(stderr, "VOC version: %d.%d\n", hdr[0x17], hdr[0x16]);
	fprintf(stderr, "data offset: %d\n", data_offset);
    }
    if(hdr[0x17] != 1) ERRORRETURN("unsupported VOC major version");

    for(count=0x20; count<data_offset; count++)
	getc(in);

    /* read the data blocks */
    blocksize = count = 0;
    
    while(1) {
	type=getc(in);
	if(type==0) {
	    /* terminator */
	    return 0;
	} else {
	    blocksize = getc(in);
	    blocksize |= getc(in)<<8;
	    blocksize |= getc(in)<<16;
	    count=blocksize;
	    if(type>2 || verbose) {
		fprintf(stderr, "unknown block type %d, skipping...\n", type);
	    }
	    if(type==1) {
		long sample_rate = 1000000L / (long)(256-getc(in));
		int data_type = getc(in);
		if(verbose) {
		    int i=data_type, n;
		    n=sizeof(voc_type)/sizeof(voc_type[0]);
		    if(i<0 || i>=n) i=n-1;
		    fprintf(stderr, "sample rate: %ld Hz\n", sample_rate);
		    fprintf(stderr, "data type: %s\n", voc_type[i]);
		}
		if(data_type != 0) ERRORRETURN("unsupported data type");
		count-=2;
	    }
	    while( count-- ) {
		int d;
		d=getc(in);
		if(feof(in)) return 0;
		if(type<=2) zput((d-0x80)<<8, out );
	    }
	}
    }
    return 0;
}

