home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * NAME : towav
- * DESCRIPTION : converts encoded pcm file to linear pcm
- * : and prepends a riff file header to make it
- * : playable as a .wav file
- * INPUT : options: filename [d] [a] [m] [6] [8] [w]
- * : filename input file name preffix[.suffix]
- * : d adpcm decode - default
- * : a alaw decode
- * : m mulaw decode
- * : 6 6khz sampling - default
- * : 8 8khz sampling
- * : w wrap with extended wave header
- * OUTPUT : file "preffix.wav"
- * RETURNS : none
- * NOTE : written with microsoft c7.0, thus the extra _'s
- * : on the compiler defines, use the oldnames library
- * : to avoid the same problem with the functions
- ****************************************************************/
-
- /* standard headers */
- #include <string.h>
- #include <ctype.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- /* standard wave file header */
- /****************************************************************
- * 'RIFF'
- * length in bytes of all that follows(long)
- * 'WAVE'
- * 'fmt '
- * length in bytes of the format block = 16(long)
- * format = 1(int)
- * number of channels = 1(int) - mono
- * sample rate(long)
- * bytes per second during play(long)
- * bytes per sample = 2(int)
- * bits per sample = 16(int)
- * 'data'
- * length in bytes of the data block(long)
- ****************************************************************/
- long wavehdr[11]=
- {0x46464952,0xffffffdb,0x45564157,0x20746d66,16,0x10001,6000,12000,0x100002,
- 0x61746164,-1};
- /*extended wave file header */
- /****************************************************************
- * 'RIFF'
- * length in bytes of all that follows(long)
- * 'WAVE'
- * 'fmt '
- * length in bytes of the format block = 18+extra bytes(long)
- * format = ?(int)
- * number of channels = 1(int) - mono
- * sample rate(long)
- * bytes per second during play(long)
- * bytes per sample = ?(int)
- * bits per sample = ?(int)
- * number of extra bytes = ?(int)
- * extra bytes
- * 'data'
- * length in bytes of the data block(long)
- ****************************************************************/
- long adpcmhdr[12]=
- {0x46464952,0xffffffdb,0x45564157,0x20746d66,20,0x10010,6000,3000,0x40001,
- 0x2,0x61746164,-1};
- long pcmhdr[12]=
- {0x46464952,0xffffffdb,0x45564157,0x20746d66,18,0x10007,6000,6000,0x80001,
- 0x6174,0x6164ffff,-1};
- /* alaw decode table */
- int alaw[256]=
- {-688,-656,-752,-720,-560,-528,-624,-592,-944,-912,-1008,-976,
- -816,-784,-880,-848,-344,-328,-376,-360,-280,-264,-312,-296,
- -472,-456,-504,-488,-408,-392,-440,-424,-2752,-2624,-3008,-2880,
- -2240,-2112,-2496,-2368,-3776,-3648,-4032,-3904,-3264,-3136,
- -3520,-3392,-1376,-1312,-1504,-1440,-1120,-1056,-1248,-1184,
- -1888,-1824,-2016,-1952,-1632,-1568,-1760,-1696,-43,-41,-47,-45,
- -35,-33,-39,-37,-59,-57,-63,-61,-51,-49,-55,-53,-11,-9,-15,
- -13,-3,-1,-7,-5,-27,-25,-31,-29,-19,-17,-23,-21,-172,-164,
- -188,-180,-140,-132,-156,-148,-236,-228,-252,-244,-204,-196,
- -220,-212,-86,-82,-94,-90,-70,-66,-78,-74,-118,-114,-126,-122,
- -102,-98,-110,-106,688,656,752,720,560,528,624,592,944,912,
- 1008,976,816,784,880,848,344,328,376,360,280,264,312,296,472,
- 456,504,488,408,392,440,424,2752,2624,3008,2880,2240,2112,
- 2496,2368,3776,3648,4032,3904,3264,3136,3520,3392,1376,1312,
- 1504,1440,1120,1056,1248,1184,1888,1824,2016,1952,1632,1568,
- 1760,1696,43,41,47,45,35,33,39,37,59,57,63,61,51,49,55,53,
- 11,9,15,13,3,1,7,5,27,25,31,29,19,17,23,21,172,164,188,
- 180,140,132,156,148,236,228,252,244,204,196,220,212,86,82,
- 94,90,70,66,78,74,118,114,126,122,102,98,110,106};
- /* mulaw decode table */
- int mulaw[256]=
- {-8031,-7775,-7519,-7263,-7007,-6751,-6495,-6239,-5983,-5727,-5471,
- -5215,-4959,-4703,-4447,-4191,-3999,-3871,-3743,-3615,-3487,
- -3359,-3231,-3103,-2975,-2847,-2719,-2591,-2463,-2335,-2207,
- -2079,-1983,-1919,-1855,-1791,-1727,-1663,-1599,-1535,-1471,
- -1407,-1343,-1279,-1215,-1151,-1087,-1023,-975,-943,-911,-879,
- -847,-815,-783,-751,-719,-687,-655,-623,-591,-559,-527,-495,
- -471,-455,-439,-423,-407,-391,-375,-359,-343,-327,-311,-295,
- -279,-263,-247,-231,-219,-211,-203,-195,-187,-179,-171,-163,
- -155,-147,-139,-131,-123,-115,-107,-99,-93,-89,-85,-81,-77,
- -73,-69,-65,-61,-57,-53,-49,-45,-41,-37,-33,-30,-28,-26,-24,
- -22,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,0,8031,7775,7519,
- 7263,7007,6751,6495,6239,5983,5727,5471,5215,4959,4703,4447,
- 4191,3999,3871,3743,3615,3487,3359,3231,3103,2975,2847,2719,
- 2591,2463,2335,2207,2079,1983,1919,1855,1791,1727,1663,1599,
- 1535,1471,1407,1343,1279,1215,1151,1087,1023,975,943,911,879,
- 847,815,783,751,719,687,655,623,591,559,527,495,471,455,439,
- 423,407,391,375,359,343,327,311,295,279,263,247,231,219,211,
- 203,195,187,179,171,163,155,147,139,131,123,115,107,99,93,
- 89,85,81,77,73,69,65,61,57,53,49,45,41,37,33,30,28,26,24,
- 22,20,18,16,14,12,10,8,6,4,2,0};
- /* step size index shift table */
- int indsft[8]={-1, -1, -1, -1, 2, 4, 6, 8};
- /* step size table
- stpsz[i]=floor[16*(11/10)^i] */
- int stpsz[49]=
- {16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66,73,80,88,
- 97,107,118,130,143,157,173,190,209,230,253,279,307,337,371,
- 408,449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,
- 1552};
- /* nibble to bit map */
- int nbl2bit[16][4]={
- {1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1},{1,1,0,0},{1,1,0,1},
- {1,1,1,0},{1,1,1,1},{-1,0,0,0},{-1,0,0,1},{-1,0,1,0},{-1,0,1,1},
- {-1,1,0,0},{-1,1,0,1},{-1,1,1,0},{-1,1,1,1}};
- /* step size index */
- int ssindex=0;
- /* the current adpcm signal */
- int signal=-2;
- /* tmp storage for last 128 values */
- int avgbuf[128]={
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- };
- /* index for same */
- int avgidx=0;
- /* total length decoded */
- long total=0;
- /* length of the current read buffer */
- long length;
- /* offset into the current read buffer */
- long offset;
- /* nibble of the byte */
- int nibble;
- /* read buffer */
- unsigned char readbuf[4096];
- /* write buffer */
- unsigned int writebuf[8192];
- /* decode method: 0 -> adpcm, 1 -> mulaw, 2 -> alaw */
- int law=0;
- /* wrap only flag */
- int wrap=0;
- /* input & output file handles */
- int ifh,ofh;
- void truncwarn();
- void errorout();
- int decode(unsigned char);
- /****************************************************************
- * NAME : main(argc,argv)
- * DESCRIPTION : entrypoint to application
- * INPUT : options: filename [d] [a] [m] [6] [8] [w]
- * : filename input file name preffix[.suffix]
- * : d adpcm decode - default
- * : a alaw decode
- * : m mulaw decode
- * : 6 6khz sampling - default
- * : 8 8khz sampling
- * : w wrap with extended wave header
- * OUTPUT : none
- * RETURNS : none
- ****************************************************************/
- int main (int argc,char *argv[])
- {
- int argn; /* argument index */
- int slth,sidx; /* string hacking variables */
- char oname[12];
- int yeanea;
- /* wellllll, we really do need input data */
- if(argc<2){
- printf("\nNo input file\n\n");
- errorout();
- }
- /* honest we do */
- if((ifh=_open(argv[1],_O_RDONLY|_O_BINARY))<0){
- printf("\nInput file %s was not opened\n\n",argv[1]);
- errorout();
- }
- /* check the rest of the arguments*/
- if(argc>2){
- for(argn=2;argn<argc;++argn){
- switch(tolower(*argv[argn])){
- case 'd': /* adpcm decode */
- law=0;
- break;
- case 'm':
- law=1; /* mulaw decode */
- pcmhdr[5]=0x10006;
- break;
- case 'a':
- law=2; /* alaw decode */
- pcmhdr[5]=0x10007;
- break;
- case '8':
- wavehdr[6]=8000; /* 8khz sampling */
- wavehdr[7]=16000;
- adpcmhdr[6]=8000;
- adpcmhdr[7]=4000;
- pcmhdr[6]=8000;
- pcmhdr[7]=8000;
- break;
- case '6':
- wavehdr[6]=6000; /* 6khz sampling */
- wavehdr[7]=12000;
- adpcmhdr[6]=6000;
- adpcmhdr[7]=3000;
- pcmhdr[6]=6000;
- pcmhdr[7]=6000;
- break;
- case 'w':
- wrap=1;
- default:
- printf("\nUnknown Option - %c\n\n",*argv[argn]);
- errorout();
- }
- }
- }
- /* build the output file name */
- strcpy(oname,argv[1]);
- slth=strlen(oname);
- /* get the prefix */
- for(sidx=0;sidx<slth;++sidx)
- if(oname[sidx]=='.')
- break;
- oname[sidx]=0; /* convert to asciz */
- strcat(oname,".wav"); /* tack on our suffix */
- /* opps, maybe */
- if((ofh=_open(oname,_O_RDONLY))>0){
- printf("output file %s already exits\n",oname);
- printf("Ok to replace (y or n)? ");
- yeanea=_getch();
- printf("%c\n",yeanea);
- if(yeanea=='y'||yeanea=='Y')
- _close(ofh);
- else
- errorout();
- }
- /* this should never happen */
- if((ofh=_open(oname,_O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC,_S_IWRITE))<0){
- printf("output file %s not opened\n",oname);
- errorout();
- }
- if(wrap==0)
- _write(ofh,wavehdr,44);
- else
- if(law==0)
- _write(ofh,adpcmhdr,48);
- else
- _write(ofh,pcmhdr,46);
- length=4096;
- while(length==4096){
- length=_read(ifh,readbuf,4096);
- if(wrap==0)
- switch(law){
- case 0:
- for(offset=0;offset<length;++offset){
- nibble=0;
- signal+=decode((unsigned char)(readbuf[offset]/16));
- if(signal>2047||signal<-2047)
- truncwarn();
- writebuf[2*offset]=signal*16;
- nibble=1;
- signal+=decode((unsigned char)(readbuf[offset]%16));
- if(signal>2047||signal<-2047)
- truncwarn();
- writebuf[2*offset+1]=signal*16;
- }
- _write(ofh,writebuf,(unsigned)(4*length));
- break;
- case 1:
- for(offset=0;offset<length;++offset)
- writebuf[offset]=mulaw[readbuf[offset]]*4;
- _write(ofh,writebuf,(unsigned)(2*length));
- break;
- case 2:
- for(offset=0;offset<length;++offset)
- writebuf[offset]=alaw[readbuf[offset]]*8;
- _write(ofh,writebuf,(unsigned)(2*length));
- break;
- }
- else
- _write(ofh,readbuf,(unsigned)length);
- total+=length;
- }
- _close(ifh);
- /* go back and fill in the wave length */
- length=_lseek(ofh,(long)4,SEEK_SET);
- if(wrap==0){
- if(law==0)
- total=4*total;
- else
- total=2*total;
- length=total+36;
- }
- else
- if(law==0)
- length=total+40;
- else
- length=total+38;
- _write(ofh,&length,4);
- /* go back and fill in the data length */
- if(wrap==0)
- length=_lseek(ofh,(long)40,SEEK_SET);
- else
- if(law==0)
- length=_lseek(ofh,(long)44,SEEK_SET);
- else
- length=_lseek(ofh,(long)42,SEEK_SET);
- _write(ofh,&total,4);
- _close(ofh);
- return(0);
- }
- /****************************************************************
- * NAME : truncwarn()
- * DESCRIPTION : prints a message when the decode goes out of bounds
- * INPUT : none
- * OUTPUT : none
- * RETURNS : none
- ****************************************************************/
- void truncwarn()
- {
- long value;
- value=2*total+2*offset+nibble;
- printf("adpcm decode truncated to 12bit value at nibble %ld\n",
- value);
- if(signal>2047)
- signal=2047;
- if(signal<-2047)
- signal=-2047;
- }
- /****************************************************************
- * NAME : errorout()
- * DESCRIPTION : bad argument handler, prints usage header & exits
- * INPUT : none
- * OUTPUT : none
- * RETURNS : does not return, exits to dos
- ****************************************************************/
- void errorout()
- {
- printf("usage: towav filename [d] [a] [m] [6] [8] [w]\n");
- printf(" filename - input file = prefix[.suffix]\n");
- printf(" output file = prefix.wav\n");
- printf(" NO indexed play files\n");
- printf(" d - default: adpcm decode\n");
- printf(" a - alaw decode\n m - mulaw decode\n");
- printf(" 6 - default: 6000 samples/second\n 8 - 8000 samples/second\n");
- printf(" w - wrap in extended wave header(no decode)\n");
- _close(ifh);
- _close(ofh);
- exit(0);
- }
- /****************************************************************
- * NAME : decode(encoded)
- * DESCRIPTION : does the actual adpcm decode
- * INPUT : the encoded nibble from the adpcm file
- * OUTPUT : the index into the step size table for the next decode
- * RETURNS : the decoded difference
- ****************************************************************/
- int decode(unsigned char encoded)
- {
- int diff,step;
- step=stpsz[ssindex];
- diff=nbl2bit[encoded][0]*(
- step*nbl2bit[encoded][1]+
- (step/2)*nbl2bit[encoded][2]+
- (step/4)*nbl2bit[encoded][3]+
- (step/8));
- ssindex=ssindex+indsft[(encoded%8)];
- if(ssindex<0)
- ssindex=0;
- if(ssindex>48)
- ssindex=48;
- return(diff);
- }
-