📄 wavpack.c
字号:
/* LINTLIBRARY */#ifndef lint static char copyright[]="***************************************************************************\n\ Copyright (C) 1992 Massachusetts Institute of Technology. \n\ All rights reserved \n\***************************************************************************\n";#endif/* * This software is being provided to you, the LICENSEE, by the Massachusetts * Institute of Technology (M.I.T.) under the following license. By * obtaining, using and/or copying this software, you agree that you have * read, understood, and will comply with these terms and conditions: * * Permission to use, copy, modify and distribute, including the right to * grant others the right to distribute at any tier, this software and its * documentation for any purpose and without fee or royalty is hereby granted, * provided that you agree to comply with the following copyright notice and * statements, including the disclaimer, and that the same appear on ALL * copies of the software and documentation, including modifications that you * make for internal use or for distribution: * * Copyright 1992 by the Massachusetts Institute of Technology. All rights * reserved. * * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS OR * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not limitation, * M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS * FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE OR * DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, * TRADEMARKS OR OTHER RIGHTS. * * The name of the Massachusetts Institute of Technology or M.I.T. may NOT be * used in advertising or publicity pertaining to distribution of the * software. Title to copyright in this software and any associated * documentation shall at all times remain with M.I.T., and USER agrees to * preserve same. */#ifndef lint static char rcsid[] = "$Header: /home/beldar/stan/sphere/RCS/wavpack.c,v 1.10 1993/03/25 00:20:51 stan Exp stan $";#endif/* wavpack: machine indpendent waveform packing routine * assumes only that data is organized in bytes * tries a number of strategies: includes mono/stereo, byte/short, data * lossless (bit preserving) for any kind of input data */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sp/wavpack/wavpack.h>static char magic[] = WAVPACK_MAGIC; /* magic string to identify wavpack files */static int strat[]= /* strategy info */{ BYTE, /* 0 */ BYTE|DIFF, /* 1 */ BYTE|STEREO, /* 2 */ BYTE|DIFF|STEREO, /* 3 */ SHORT, /* 4 */ SHORT|REV, /* 5 */ SHORT|DIFF, /* 6 */ SHORT|REV|DIFF, /* 7 */ SHORT|OFFSET, /* 8 */ SHORT|OFFSET|REV, /* 9 */ SHORT|OFFSET|DIFF, /* 10 */ SHORT|OFFSET|REV|DIFF, /* 11 */ SHORT|STEREO, /* 12 */ SHORT|REV|STEREO, /* 13 */ SHORT|DIFF|STEREO, /* 14 */ SHORT|REV|DIFF|STEREO, /* 15 */ SHORT|OFFSET|STEREO, /* 16 */ SHORT|OFFSET|REV|STEREO, /* 17 */ SHORT|OFFSET|DIFF|STEREO, /* 18 */ SHORT|OFFSET|REV|DIFF|STEREO, /* 19 */ -1};static int nstrat;struct hdr /* compressed data header */{ unsigned char flags; /* strategy and channel info */ unsigned char count; /* nr samples -1 */ unsigned char nbits; /* nr pcm bits */ unsigned char offset_byte; /* (opt) offst byte */ unsigned short dbase; /* (opt) diff base, byte/short */ unsigned short pbase; /* (opt) pcm base, byte/short */};static struct strat_eval /* strat evaluation with sample hdrs */{ struct hdr hdr; int nsam; /* samples available (from condition_data) */ int min, max; /* min and max of data */ int range; /* range of data */ int count; /* nr samples */ int obytes; /* total output bytes (including header) */ int ibytes; /* input bytes consumed */ float obpib; /* output bytes per input byte */ int chan_1; /* if chan0, stereo pair (chan1) */} strat_eval[256]; /* address microcoded through strat[] */static struct strat_eval f0b[RUNL+1],f1b[RUNL+1]; /* for mixed strat stereo */static struct strat_eval f0s[RUNL+1],f1s[RUNL+1]; static struct strat_eval f0so[RUNL+1],f1so[RUNL+1]; static float bm,b0b,b1b,b0s,b1s,b0so,b1so; /* bests for pruning */static unsigned char input[4*RUNL+5]; /* raw input */static int ninput; /* input channels for strategies */static unsigned short chan_0[RUNL]; /* byte/short chan 0 */static unsigned short chan_1[RUNL]; /* byte/short chan 1 */static int vflg=0; /* verbosity */static int monoflg = 0; /* mono data only */static int byteflg = 0; /* byte data only */static int sflg= -1;static int runl=128; /* max run length */static char *progname = (char *) NULL;static char *oname = (char *) NULL;static int oflg = 0; /* if non-zero, unlink(oname) on error */static int pwr2[17]={1,2,4,8,16,32,64,128,256, 512,1024,2048,4096,8192,16384,32678,65536};#define mod(x) ((x)&bitmask)/* #define maxm(x,y) ((x)>(y)?(x):(y)) */#define perr(s) wavpack_perr(s)int wavpack_set_monoflg(){ monoflg = 1;}int wavpack_get_monoflg(){ return monoflg;}int wavpack_set_byteflg(){ byteflg = 1;}int wavpack_get_byteflg(){ return byteflg;}int wavpack_set_vflg( value ) int value;{ vflg = value;}int wavpack_set_oname( s ) char * s;{ if ( oname != (char *) NULL ) free( oname ); oname = strdup( s ); return (oname == (char *) NULL) ? -1 : 0;}int wavpack_set_oflg( value ) int value;{ oflg = value;}int wavpack_set_progname( s ) char * s;{ if ( progname != (char *) NULL ) free( progname ); progname = strdup( s ); return ( progname == (char *) NULL ) ? -1 : 0;}int wavpack_get_nstrat(){ int n; for ( n=0; strat[n] >= 0; n++ ) ; return n;}#ifdef fread# undef fread#endif#define fread(a,b,c,d) fob_fread((a),(b),(c),(d))#ifdef fwrite# undef fwrite#endif#define fwrite(a,b,c,d) fob_fwrite((a),(b),(c),(d))#ifdef ferror# undef ferror#endif#define ferror(a) fob_ferror((a))wavpack_pack(ifile,ofile)FILE *ifile, *ofile;{ register i,j,k,n; int m,eof,ibytes,obytes,inbytes,flags; int hist[256]; float obpib,x,*bp; nstrat = wavpack_get_nstrat(); /* magic */ if(fwrite(magic,strlen(magic)+1,1,ofile)!=1/*==0*/ ) perr("fwrite err"); for(i=0;i<256;i++) hist[i]=0; obytes=strlen(magic)+1; ibytes=inbytes=ninput=eof=0; for(m=0;;m++) { if(!eof) { n=fread(&input[ninput],1,4*RUNL+5-ninput,ifile); if(n==0) { if(ferror(ifile)) perr("input file error"); eof=1; if(ninput==0) break; } ninput+=n; inbytes+=n; } for(i=0;i<nstrat;i++) { strat_eval[strat[i]].obpib=1e5; if(strat[i]&STEREO) strat_eval[strat[i]|CHAN1].obpib=1e5; } if(!monoflg) for(i=0;i<runl+1;i++) f0b[i].obpib=f1b[i].obpib=1e5; if(!byteflg && !monoflg) for(i=0;i<runl+1;i++) f0s[i].obpib=f1s[i].obpib= f0so[i].obpib=f1so[i].obpib=1e5; bm=b0b=b1b=b0s=b1s=b0so=b1so=1e5; if(sflg>=0) evaluate_strat(strat[sflg]); /* debug */ else for(i=0;i<nstrat;i++) { flags=strat[i]; if(monoflg && (flags&STEREO)) continue; if(byteflg && (flags&SHORT)) continue; evaluate_strat(flags); if(flags&STEREO) { if(flags&SHORT) { if(flags&CHAN1) { if(flags&OFFSET) bp= &b1so; else bp= &b1s; } else { if(flags&OFFSET) bp= &b0so; else bp= &b0s; } } else { if(flags&CHAN1) bp= &b1b; else bp= &b0b; } } else bp= &bm; if(strat_eval[flags].obpib<*bp) *bp=strat_eval[flags].obpib; } if(!monoflg) /* finish stereo */ { for(i=0;i<nstrat;i++) if(strat[i]&STEREO) strat_eval[strat[i]].obpib=1e5; for(i=0,j= -1,x=1000;i<runl+1;i++) /* byte */ { if(f0b[i].obpib+f1b[i].obpib<10.) { f0b[i].obytes+=f1b[i].obytes; f0b[i].ibytes+=f1b[i].ibytes; f0b[i].obpib=(float) f0b[i].obytes/f0b[i].ibytes; if(f0b[i].obpib<x) x=f0b[i].obpib, j=i; f0b[i].chan_1=f1b[i].hdr.flags; } } if(j>=0) { strat_eval[f0b[j].hdr.flags]=f0b[j]; strat_eval[f1b[j].hdr.flags]=f1b[j]; } } if(!monoflg && !byteflg) /* finish stereo */ { for(i=0,j= -1,x=1000;i<runl+1;i++) /* short */ { if(f0s[i].obpib+f1s[i].obpib<10.) { f0s[i].obytes+=f1s[i].obytes; f0s[i].ibytes+=f1s[i].ibytes; f0s[i].obpib=(float) f0s[i].obytes/f0s[i].ibytes; if(f0s[i].obpib<x) x=f0s[i].obpib, j=i; f0s[i].chan_1=f1s[i].hdr.flags; } } if(j>=0) { strat_eval[f0s[j].hdr.flags]=f0s[j]; strat_eval[f1s[j].hdr.flags]=f1s[j]; } for(i=0,j= -1,x=1000;i<runl+1;i++) /* short, offset */ { if(f0so[i].obpib+f1so[i].obpib<10.) { f0so[i].obytes+=f1so[i].obytes; f0so[i].ibytes+=f1so[i].ibytes; f0so[i].obpib=(float) f0so[i].obytes/f0so[i].ibytes; if(f0so[i].obpib<x) x=f0so[i].obpib,j=i; f0so[i].chan_1=f1so[i].hdr.flags; } } if(j>=0) { strat_eval[f0so[j].hdr.flags]=f0so[j]; strat_eval[f1so[j].hdr.flags]=f1so[j]; } } k= -1; /* choose winning strategy */ obpib=100; for(i=0;i<nstrat;i++) if(strat_eval[strat[i]].obpib<obpib) { k=strat[i]; obpib=strat_eval[k].obpib; } if(obpib<=0) perr("pack: illegal obpib"); if(k<0) perr("pack: no channel found"); if(sflg>=0 && k!=strat[sflg]) perr("k!=strat[sflg]"); hist[k]++; output_strat(k,ofile); if(vflg>2) { fprintf(stderr,"%d\t",m); fprintf(stderr,"%d\t",ibytes); printstrat(k); fprintf(stderr,"\tib=%d\tob=%d", strat_eval[k].ibytes,strat_eval[k].obytes); fprintf(stderr,"\t%d",strat_eval[k].hdr.nbits); fprintf(stderr,"\t%.2f",strat_eval[k].obpib); fprintf(stderr,"\n"); if(k&STEREO) { fprintf(stderr,"%d\t",m); fprintf(stderr,"%d\t",ibytes); j=strat_eval[k].chan_1; printstrat(j); fprintf(stderr,"\tib=%d\tob=%d", strat_eval[j].ibytes,strat_eval[j].obytes); fprintf(stderr,"\t%d",strat_eval[j].hdr.nbits); fprintf(stderr,"\t%.2f",strat_eval[j].obpib); fprintf(stderr,"\n"); } } j=strat_eval[k].ibytes; /* shift input */ for(i=0;j<ninput;i++,j++) input[i]=input[j]; ninput-=strat_eval[k].ibytes; if(ninput<0) perr("ninput<0"); ibytes+=strat_eval[k].ibytes; obytes+=strat_eval[k].obytes; if(eof && ninput==0) break; } if(ibytes!=inbytes) perr("ibytes!=inbytes"); if(vflg) { if(vflg>1) { fprintf(stderr,"ib=%d\tob=%d\t",ibytes,obytes); fprintf(stderr,"rec=%d\t",m); } fprintf(stderr,"compression=%.1f%%\n",100.-100.*obytes/ibytes); if(vflg>1) { for(i=0;i<256;i++) if(hist[i]) { printstrat(i); fprintf(stderr,"\t%d\t",hist[i]); } fprintf(stderr,"\n"); } }}static int condition_data(flags){ register int i,j,n; int osam,nbytes; unsigned short sinput[4*RUNL+5]; if(flags&CHAN1) perr("flags&CHAN1"); strat_eval[flags].hdr.flags=flags; nbytes=0; /* input bytes consumed */ osam=0; /* ouput samples generated */ if(flags&SHORT) /* short data */ { if(flags&OFFSET) { strat_eval[flags].hdr.offset_byte=input[nbytes++]; if(nbytes>=ninput) return 1; } i=nbytes; /* construct short array */ if(flags&REV) /* rev (lsByte first) */ { for(j=0;i<ninput;i+=2,j++) sinput[j]= ((input[i])&0377) | (((input[i+1])&0377)<<8); } else /* normal (msByte first) */ { for(j=0;i<ninput;i+=2,j++) sinput[j]= (((input[i])&0377)<<8) | ((input[i+1])&0377); } n=0; if(flags&STEREO) /* stereo */ { if(flags&DIFF) /* diff */ { strat_eval[flags].hdr.dbase=sinput[n++]; nbytes+=2; if(nbytes>=ninput) return 1; strat_eval[flags+CHAN1].hdr.dbase=sinput[n++]; nbytes+=2; if(nbytes+4>ninput) return 1; while(osam<runl && nbytes+4<=ninput) { chan_0[osam]=sinput[n]-sinput[n-2]; n++; chan_1[osam++]=sinput[n]-sinput[n-2]; n++; nbytes+=4; } } else /* pcm */ { if(nbytes+4>ninput) return 1; while(osam<runl && nbytes+4<=ninput) { chan_0[osam]=sinput[n++]; chan_1[osam++]=sinput[n++]; nbytes+=4; } } } else /* mono */ { if(flags&DIFF) /* diff */ { strat_eval[flags].hdr.dbase=sinput[n++]; nbytes+=2; if(nbytes+2>ninput) return 1; while(osam<runl && nbytes+2<=ninput) { chan_0[osam++]= sinput[n]-sinput[n-1]; n++; nbytes+=2; } } else /* pcm */ { if(nbytes+2>ninput) return 1; while(osam<runl && nbytes+2<=ninput) { chan_0[osam++]=sinput[n++]; nbytes+=2; } } } } else /* byte data */ { if(flags&OFFSET) perr("byte && offset"); if(flags&REV) perr("byte && byte_rev"); if(flags&STEREO) /* stereo */ { if(flags&DIFF) /* diff */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -