📄 wavpack.c
字号:
{ strat_eval[flags].hdr.dbase=input[nbytes++]; if(nbytes>=ninput) return 1; strat_eval[flags|CHAN1].hdr.dbase= input[nbytes++]; if(nbytes+2>ninput) return 1; while(osam<runl && nbytes+2<=ninput) { chan_0[osam]= input[nbytes]-input[nbytes-2]; nbytes++; chan_1[osam++]= input[nbytes]-input[nbytes-2]; nbytes++; } } else /* pcm */ { if(nbytes+2>ninput) return 1; while(osam<runl && nbytes+2<=ninput) { chan_0[osam]=input[nbytes++]; chan_1[osam++]=input[nbytes++]; } } } else /* mono */ { if(flags&DIFF) /* diff */ { strat_eval[flags].hdr.dbase=input[nbytes++]; if(nbytes+1>ninput) return 1; while(osam<runl && nbytes+1<=ninput) { chan_0[osam++]= input[nbytes]-input[nbytes-1]; nbytes++; } } else /* pcm */ { if(nbytes+1>ninput) return 1; while(osam<runl && nbytes+1<=ninput) chan_0[osam++]=input[nbytes++]; } } } strat_eval[flags].nsam=osam; if(flags&STEREO) strat_eval[flags|CHAN1].nsam=osam; return 0;}static evaluate_strat(flags){ register int i,count; register struct strat_eval *f0p,*f1p; int flags1; struct strat_eval f0[RUNL],f1[RUNL]; strat_eval[flags].obpib=1e5; if(flags&CHAN1) perr("flags&CHAN1"); if(condition_data(flags)) return; if(flags&STEREO) { flags1=flags|CHAN1; if(strat_eval[flags].nsam!=strat_eval[flags1].nsam) perr("STEREO: nsam!="); if(flags&SHORT && flags&OFFSET) f0p= &f0so[0], f1p= &f1so[0]; else if(flags&SHORT) f0p= &f0s[0], f1p= &f1s[0]; else f0p= &f0b[0], f1p= &f1b[0]; if(flags&DIFF) f0p++, f1p++; /* offset for DIFF */ evaluate_chan(flags,f0); count=strat_eval[flags].count; for(i=0;i<count;i++) if(f0[i].obpib<f0p[i].obpib) f0p[i]=f0[i]; evaluate_chan(flags1,f1); count=strat_eval[flags1].count; for(i=0;i<count;i++) if(f1[i].obpib<f1p[i].obpib) f1p[i]=f1[i]; /* must be finished in pack() */ } else evaluate_chan(flags,f0);}static evaluate_chan(flags,f) /* evaluate channel n */struct strat_eval *f; { register i,j,s; unsigned short *chanp; int dmin,dmax; int chan,hbytes,obits,pflg; int nsam,bitmask,maxbits,bpw; struct strat_eval x,y; float obpib,best; nsam=strat_eval[flags].nsam; if(flags&SHORT) bitmask=0xffff, maxbits=16, bpw=2; /* 16 bit */ else bitmask=0xff, maxbits=8, bpw=1; /* 8 bit */ if(flags&STEREO) { if(flags&SHORT) { if(flags&CHAN1) { if(flags&OFFSET) best=b1so; else best=b1s; } else { if(flags&OFFSET) best=b0so; else best=b0s; } } else { if(flags&CHAN1) best=b1b; else best=b0b; } } else best=bm; if(flags&CHAN1) chanp=chan_1, chan=1; else chanp=chan_0, chan=0; x=strat_eval[flags]; x.hdr.flags=flags; x.hdr.count=0; x.hdr.nbits=0; x.hdr.pbase=chanp[0]; x.min=x.max=chanp[0]; x.range=0; x.count=0; x.obytes=0; x.ibytes=0; x.obpib=1000; hbytes=3; /* req header bytes */ if(chan==0 && flags&OFFSET) hbytes++; /* for offset_byte */ if(flags&DIFF) hbytes+=bpw; /* for dbase */ hbytes+=bpw; /* for pbase if(nbits<maxbits)*/ x.obytes=hbytes; obits=7; x.ibytes=0; /* initial input bytes */ if(chan==0 && flags&OFFSET) x.ibytes++; /* for offset_byte */ if(flags&DIFF) x.ibytes+=bpw; /* for dbase */ obpib=0.; y=x; for(i=pflg=0;i<nsam;i++) { s=chanp[i]; /* current sample */ if(x.hdr.nbits<maxbits) { dmin=mod(s-x.min); /* outside zone */ dmax=mod(x.max-s); if(dmin>x.range || dmax>x.range) { if(dmax>=dmin) x.max=s; else x.min=x.hdr.pbase=s; x.range=mod(x.max-x.min); if(x.range>=pwr2[x.hdr.nbits]) { for(j=x.hdr.nbits;j<17;j++) if(x.range<pwr2[j]) break; if(j==maxbits) { x.min=x.hdr.pbase=0; x.max=x.range=bitmask; hbytes-=bpw; } x.hdr.nbits=j; /* bits req for pcm */ obits=j*x.count+7; /* output bits */ x.obytes=hbytes+obits/8; /* and bytes */ obits%=8; obpib=(float)j/maxbits; if(obpib>y.obpib) break; if(obpib>best) pflg=1; } } } x.count++; x.hdr.count=x.count-1; for(obits+=x.hdr.nbits;obits>=8;obits-=8) x.obytes++; /*output*/ x.ibytes+=bpw; /* input bytes */ x.obpib=(float)x.obytes/x.ibytes; /* obytes per ibytes */ f[i]=x; /* save result */ if(x.obpib<y.obpib) { y=x; /* best forward coding so far */ if(obpib>y.obpib) break; /* can only get worse */ } if(pflg && x.obpib>best) break; /* occasional premature prune */ } strat_eval[flags]=y; /* best run for this coding */}static output_strat(flags,ofile)FILE *ofile;{ if(flags&CHAN1) perr("output: flags&CHAN1"); if(condition_data(flags)) perr("output: unable to make channel"); output_chan(flags,ofile); if(flags&STEREO) { flags=strat_eval[flags].chan_1; if(condition_data(flags&~CHAN1)) perr("output: unable to make channel"); output_chan(flags,ofile); }}static output_chan(flags,ofile)FILE *ofile;{ register int i,j,k,pbase; register unsigned short *chanp; int bits,count; unsigned char c[2],obuf[4*RUNL+5]; bits=strat_eval[flags].hdr.nbits; count=strat_eval[flags].hdr.count+1; if(strat_eval[flags].hdr.flags!=flags) perr("flags!="); if(flags&CHAN1) chanp=chan_1; else chanp=chan_0; if(fwrite(&strat_eval[flags].hdr.flags,1,1,ofile)!=1 /*==0*/ ) /* header */ perr("fwrite err"); if(fwrite(&strat_eval[flags].hdr.count,1,1,ofile)!=1 /*==0*/ ) /* header */ perr("fwrite err"); if(fwrite(&strat_eval[flags].hdr.nbits,1,1,ofile)!=1 /*==0*/ ) /* header */ perr("fwrite err"); if(flags&OFFSET && (flags&CHAN1)==0 && /* offset */ fwrite(&strat_eval[flags].hdr.offset_byte,1,1,ofile)!=1 /*==0*/ ) perr("fwrite err"); if(flags&DIFF) /* diff base */ { if(flags&SHORT) { c[0]=strat_eval[flags].hdr.dbase>>8; c[1]=strat_eval[flags].hdr.dbase; if(fwrite(c,1,2,ofile)!=2 /*==0*/ ) perr("fwrite err"); } else { c[0]=strat_eval[flags].hdr.dbase; if(fwrite(c,1,1,ofile)!=1 /*==0*/ ) perr("fwrite err"); } } if(bits<8 || (flags&SHORT && bits<16)) /* pcm base */ { if(flags&SHORT) { c[0]=strat_eval[flags].hdr.pbase>>8; c[1]=strat_eval[flags].hdr.pbase; if(fwrite(c,1,2,ofile)!=2 /*==0*/ ) perr("fwrite err"); } else { c[0]=strat_eval[flags].hdr.pbase; if(fwrite(c,1,1,ofile)!=1 /*==0*/ ) perr("fwrite err"); } pbase=strat_eval[flags].hdr.pbase; } else pbase=0; if(flags&CHAN1) chanp=chan_1; else chanp=chan_0; if(bits>0) { if(pbase) for(i=0;i<count;i++) chanp[i]-=pbase; for(i=0;i<(bits*count+7)/8;i++) obuf[i]=0;#if 0 for(i=0;i<bits*count;i++) { if((1<<(bits-1-i%bits))&chanp[i/bits]) obuf[i/8]|=1<<(7-i%8); }#endif for(i=k=0;i<count;i++) for(j=bits-1;j>=0;j--,k++) if((1<<j)&chanp[i]) obuf[k>>3]|=0x80>>(k&7); { int nitems; nitems = (bits*count+7)/8; if(fwrite(obuf,1,nitems,ofile)!=nitems /*==0*/ ) /* pcm data */ perr("fwrite err"); } }}wavpack_unpack(ifile,ofile)FILE *ifile,*ofile;{ int k; char str[100]; unsigned char ibuf[2][4*RUNL+5]; unsigned short sobuf[2][RUNL+1]; int nsobuf[2]; struct hdr hdr[2]; nstrat = wavpack_get_nstrat(); if(fread(str,strlen(magic)+1,1,ifile)==0) /* read magic */ perr("fread err"); if(strcmp(str,magic)!=0) perr("not a wavpacked file"); for(k=0;;k++) { if(vflg>1) fprintf(stderr,"k=%d\t",k); if(readchan(ifile,&hdr[0],ibuf[0])) break; if(vflg>1) { printstrat((int)hdr[0].flags); fprintf(stderr,"\n"); if(hdr[0].flags&STEREO) { fprintf(stderr,"k=%d\t",k); printstrat((int)hdr[1].flags); fprintf(stderr,"\n"); } } decode_data(&hdr[0],ibuf[0],sobuf[0],&nsobuf[0]); if(hdr[0].flags&STEREO) { if(readchan(ifile,&hdr[1],ibuf[1])) perr("illegal chan 1"); decode_data(&hdr[1],ibuf[1],sobuf[1],&nsobuf[1]); } write_data(hdr,sobuf,nsobuf,ofile); } if(vflg>1) fprintf(stderr,"\n");}static int readchan(ifile,hp,ibuf)FILE *ifile;struct hdr *hp;unsigned char *ibuf;{ int i; int count; unsigned char c[2]; if(fread(&hp->flags,1,1,ifile)==0 /*NULL*/ ) return 1; /* header */ if(fread(&hp->count,1,1,ifile)==0 /*NULL*/ ) /* header */ perr("incomplete header"); if(fread(&hp->nbits,1,1,ifile)==0 /*NULL*/ ) /* header */ perr("incomplete header"); for(i=0;i<nstrat;i++) if((hp->flags&~CHAN1)==strat[i]) break; if(i>=nstrat) perr("illegal header"); count=hp->count+1; if(hp->flags&OFFSET && (hp->flags&CHAN1)==0) /* offset */ { if(fread(&hp->offset_byte,1,1,ifile)==0 /*NULL*/ ) perr("incomplete header"); } if(hp->flags&DIFF) /* diff base */ { if(hp->flags&SHORT) { if(fread(c,1,2,ifile)==0 /*NULL*/ ) perr("incomplete header"); hp->dbase=(c[0]<<8) | c[1]; } else { if(fread(c,1,1,ifile)==0 /*NULL*/ ) perr("incomplete header"); hp->dbase=c[0]; } } if(hp->nbits<8 || (hp->flags&SHORT && hp->nbits<16)) /* pcm */ { if(hp->flags&SHORT) { if(fread(c,1,2,ifile)==0 /*NULL*/ ) perr("incomplete header"); hp->pbase=(c[0]<<8) | c[1]; } else { if(fread(c,1,1,ifile)==0 /*NULL*/ ) perr("incomplete header"); hp->pbase=c[0]; } } else hp->pbase=0; if(hp->nbits>0) { if(fread(ibuf,(hp->nbits*count+7)/8,1,ifile)==0 /*NULL*/ ) perr("incomplete data"); } return 0;}static decode_data(hp,ibuf,sobuf,nsobuf)struct hdr *hp;unsigned char *ibuf;register unsigned short *sobuf;int *nsobuf;{ register int i,j,k,bits,count,pbase; count=hp->count+1; bits=hp->nbits; if(hp->flags&DIFF) { sobuf[0]=hp->dbase; sobuf++; } pbase=hp->pbase; for(i=0;i<count;i++) sobuf[i]=pbase;#if 0 if(bits>0) for(i=0;i<bits*count;i++) if(1<<(7-i%8)&ibuf[i/8]) sobuf[i/bits]+=1<<(bits-1-i%bits);#endif if(bits>0) { for(i=k=0;i<count;i++) for(j=bits-1;j>=0;j--,k++) if(ibuf[k>>3]&(0x80>>(k&7))) sobuf[i]+=1<<j; } if(hp->flags&DIFF) { for(i=0;i<count;i++) sobuf[i]+=sobuf[i-1]; *nsobuf=count+1; } else *nsobuf=count;}static write_data(hdr,sobuf,nsobuf,ofile)struct hdr hdr[];unsigned short sobuf[][RUNL+1];int nsobuf[];FILE *ofile;{ int i,k; unsigned char obuf[4*RUNL+5]; k=0; if(hdr[0].flags&OFFSET) obuf[k++]=hdr[0].offset_byte; if(nsobuf[0]>RUNL+1) perr("nsobuf>RUNL+1"); if(hdr[0].flags&STEREO) { if(nsobuf[0]!=nsobuf[1]) perr("nsobuf !="); if(hdr[0].flags&SHORT) { for(i=0;i<nsobuf[0];i++) { if(hdr[0].flags&REV) { obuf[k++]=sobuf[0][i]; obuf[k++]=sobuf[0][i]>>8; } else { obuf[k++]=sobuf[0][i]>>8; obuf[k++]=sobuf[0][i]; } if(hdr[1].flags&REV) { obuf[k++]=sobuf[1][i]; obuf[k++]=sobuf[1][i]>>8; } else { obuf[k++]=sobuf[1][i]>>8; obuf[k++]=sobuf[1][i]; } } } else for(i=0;i<nsobuf[0];i++) { obuf[k++]=sobuf[0][i]; obuf[k++]=sobuf[1][i]; } } else { if(hdr[0].flags&SHORT) for(i=0;i<nsobuf[0];i++) { if(hdr[0].flags&REV) { obuf[k++]=sobuf[0][i]; obuf[k++]=sobuf[0][i]>>8; } else { obuf[k++]=sobuf[0][i]>>8; obuf[k++]=sobuf[0][i]; } } else for(i=0;i<nsobuf[0];i++) obuf[k++]=sobuf[0][i]; } if(fwrite(obuf,1,k,ofile)!=k /*==0*/ ) perr("fwrite err");}static printstrat(x){ int i; char str[9]; for(i=0;i<5;i++) str[i]='_'; str[5]='\0'; if(x&SHORT) str[0]='S'; else str[0]='B'; if(x&REV) str[1]='R'; if(x&OFFSET) str[2]='O'; if(x&DIFF) str[3]='D'; if(x&STEREO) str[4]='2'; fprintf(stderr,"%s",str);}perr(s)char *s;{ if(oflg && unlink(oname)) /* delete the output file */ fprintf(stderr,"%s err: unable to remove output file\n", progname); fprintf(stderr,"%s err: %s\n",progname,s); exit(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -