?? shorten.c
字號:
} /* define type to be RIFF WAVE if not already committed */ if(ftype == TYPE_EOF) ftype = TYPE_RIFF_WAVE; /* If we're dealing with RIFF WAVE, process the header now, * before calling fread_type_init() which will want to know the * sample type. This also resets ftype to the _real_ sample * type, and nchan to the correct number of channels, and * prepares a verbatim section containing the header, which we * will write out after the filetype and channel count. */ if (ftype == TYPE_RIFF_WAVE) { int wtype; wavhdr = riff_wave_prochdr(filei, &ftype, &nchan, &datalen, &wtype); if (wavhdr == NULL) { if (wtype == 0) /* the header must have been invalid */ usage_exit(1, "input file is not a valid RIFF WAVE file\n"); else /* the wave type is wrong */ usage_exit(1,"RIFF WAVE file has unhandled format tag %d\n",wtype); } else { /* we have a valid RIFF WAVE so override anything the user may have said to do with the alignment */ nskip = 0; } } /* sort out specific types for ULAW and ALAW */ if(ftype == TYPE_GENERIC_ULAW || ftype == TYPE_GENERIC_ALAW) { int linearLossy=(Satof(maxresnstr)!=Satof(DEFAULT_MAXRESNSTR)||quanterror!=DEFAULT_QUANTERROR); /* sort out which ulaw type we are going to use */ if(ftype == TYPE_GENERIC_ULAW) { if(linearLossy) ftype = TYPE_ULAW; else if(version < 2 || ulawZeroMerge == 1) ftype = TYPE_AU1; else ftype = TYPE_AU2; } /* sort out which alaw type we are going to use */ if(ftype == TYPE_GENERIC_ALAW) { if(linearLossy) ftype = TYPE_ALAW; else ftype = TYPE_AU3; } } /* mean compensation is not supported for TYPE_AU1 or TYPE_AU2 */ /* (the bit shift compensation can't cope with the lag vector) */ if(ftype == TYPE_AU1 || ftype == TYPE_AU2) nmean = 0; nwrap = MAX(NWRAP, maxnlpc); if(maxnlpc > 0) qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc))); /* verbatim copy of skip bytes from input to output checking for the existence of magic number in header, and defaulting to internal storage if that happens */ if(version >= 2) { while(nskip - nscan > 0 && vbyte > MAX_VERSION) { int byte = getc_exit(filei); if(magic[nscan] != '\0' && byte == magic[nscan]) nscan++; else if(magic[nscan] == '\0' && byte <= MAX_VERSION) vbyte = byte; else { for(i = 0; i < nscan; i++) putc_exit(magic[i], fileo); if(byte == magic[0]) { nskip -= nscan; nscan = 1; } else { putc_exit(byte, fileo); nskip -= nscan + 1; nscan = 0; } } } if(vbyte > MAX_VERSION) { for(i = 0; i < nscan; i++) putc_exit(magic[i], fileo); nskip -= nscan; nscan = 0; } } /* write magic number */ if(fwrite(magic, 1, strlen(magic), fileo) != strlen(magic)) usage_exit(1, "could not write the magic number\n"); /* write version number */ putc_exit(version, fileo); /* grab some space for the input buffers */ buffer = long2d((ulong) nchan, (ulong) (blocksize + nwrap)); offset = long2d((ulong) nchan, (ulong) MAX(1, nmean)); maxresn = parseList(maxresnstr, nchan); for(chan = 0; chan < nchan; chan++) if(maxresn[chan] < MINBITRATE) usage_exit(1,"channel %d: expected bit rate must be >= %3.1f: %3.1f\n",chan, MINBITRATE, maxresn[chan]); else maxresn[chan] -= 3.0; for(chan = 0; chan < nchan; chan++) { for(i = 0; i < nwrap; i++) buffer[chan][i] = 0; buffer[chan] += nwrap; } /* initialise the fixed length file read for the uncompressed stream */ fread_type_init(); /* initialise the variable length file write for the compressed stream */ var_put_init(); /* put file type and number of channels */ UINT_PUT(ftype, TYPESIZE, fileo); UINT_PUT(nchan, CHANSIZE, fileo); /* put blocksize if version > 0 */ if(version == 0) { if(blocksize != DEFAULT_BLOCK_SIZE) { uvar_put((ulong) FN_BLOCKSIZE, FNSIZE, fileo); UINT_PUT(blocksize, (int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),fileo); } } else { UINT_PUT(blocksize, (int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2),fileo); UINT_PUT(maxnlpc, LPCQSIZE, fileo); UINT_PUT(nmean, 0, fileo); UINT_PUT(nskip, NSKIPSIZE, fileo); if(version == 1) { for(i = 0; i < nskip; i++) { int byte = getc_exit(filei); uvar_put((ulong) byte, XBYTESIZE, fileo); } } else { if(vbyte <= MAX_VERSION) { for(i = 0; i < nscan; i++) uvar_put((ulong) magic[i], XBYTESIZE, fileo); uvar_put((ulong) vbyte, XBYTESIZE, fileo); } for(i = 0; i < nskip - nscan - 1; i++) { int byte = getc_exit(filei); uvar_put((ulong) byte, XBYTESIZE, fileo); } lpcqoffset = V2LPCQOFFSET; } } /* if we had a RIFF WAVE header, write it out in the form of verbatim * chunks at this point */ if (wavhdr) write_header(wavhdr, fileo); init_offset(offset, nchan, MAX(1, nmean), ftype); /* this is the main read/code/write loop for the whole file */ while((nread = fread_type(buffer, ftype, nchan,blocksize, filei, &datalen)) != 0) {#ifdef _WINDOWS /* Include processing to enable Windows program to abort */ CheckWindowsAbort();#endif /* put blocksize if changed */ if(nread != blocksize) { uvar_put((ulong) FN_BLOCKSIZE, FNSIZE, fileo); UINT_PUT(nread, (int) (log((double) blocksize) / M_LN2), fileo); blocksize = nread; } /* loop over all channels, processing each channel in turn */ for(chan = 0; chan < nchan; chan++) { float sigbit; /* PT expected root mean squared value of the signal */ float resbit; /* PT expected root mean squared value of the residual*/ slong coffset, *cbuffer = buffer[chan], fulloffset = 0L; int fnd, resn = 0, nlpc = 0; /* force the lower quanterror bits to be zero */ if(quanterror != 0) { slong offset = (1L << (quanterror - 1)); for(i = 0; i < blocksize; i++) cbuffer[i] = (cbuffer[i] + offset) >> quanterror; } /* merge both ulaw zeros if required */ if(ulawZeroMerge == 1) for(i = 0; i < blocksize; i++) if(cbuffer[i] == NEGATIVE_ULAW_ZERO) cbuffer[i]=POSITIVE_ULAW_ZERO; /* test for excessive and exploitable quantisation, and exploit!! */ bitshift = find_bitshift(cbuffer, blocksize, ftype) + quanterror; if(bitshift > NBITPERLONG) bitshift = NBITPERLONG; /* find mean offset : N.B. this code duplicated */ if(nmean == 0) fulloffset = coffset = offset[chan][0]; else { slong sum = (version < 2) ? 0 : nmean / 2; for(i = 0; i < nmean; i++) sum += offset[chan][i]; if(version < 2) coffset = sum / nmean; else { fulloffset = sum / nmean; if(bitshift == NBITPERLONG && version >= 2) coffset = ROUNDEDSHIFTDOWN(fulloffset, lastbitshift); else coffset = ROUNDEDSHIFTDOWN(fulloffset, bitshift); } } /* find the best model */ if(bitshift == NBITPERLONG && version >= 2) { bitshift = lastbitshift; fnd = FN_ZERO; } else { int maxresnbitshift, snrbitshift, extrabitshift; float sigpow, nn; if(maxnlpc == 0) fnd = wav2poly(cbuffer, blocksize,coffset,version,&sigbit,&resbit); else { nlpc = wav2lpc(cbuffer, blocksize, coffset, qlpc, maxnlpc, version, &sigbit, &resbit); fnd = FN_QLPC; } if(resbit > 0.0) resn = floor(resbit + 0.5); else resn = 0; maxresnbitshift = floor(resbit - maxresn[chan] + 0.5); sigpow = exp(2.0 * M_LN2 * sigbit) / (0.5 * M_LN2 * M_LN2); nn = 12.0 * sigpow / pow(10.0, minsnr / 10.0); snrbitshift = (nn>25.0/12.0)?floor(0.5*log(nn-25.0/12.0)/M_LN2):0; extrabitshift = MAX(maxresnbitshift, snrbitshift); if(extrabitshift > resn) extrabitshift = resn; if(extrabitshift > 0) { slong offset = (1L << (extrabitshift - 1)); for(i = 0; i < blocksize; i++) cbuffer[i] = (cbuffer[i] + offset) >> extrabitshift; bitshift += extrabitshift; if(version >= 2) coffset = ROUNDEDSHIFTDOWN(fulloffset, bitshift); resn -= extrabitshift; } } /* store mean value if appropriate : N.B. Duplicated code */ if(nmean > 0) { slong sum = (version < 2) ? 0 : blocksize / 2; for(i = 0; i < blocksize; i++) sum += cbuffer[i]; for(i = 1; i < nmean; i++) offset[chan][i - 1] = offset[chan][i]; if(version < 2) offset[chan][nmean - 1] = sum / blocksize; else offset[chan][nmean - 1] = (sum / blocksize) << bitshift; } if(bitshift != lastbitshift) { uvar_put((ulong) FN_BITSHIFT, FNSIZE, fileo); uvar_put((ulong) bitshift, BITSHIFTSIZE, fileo); lastbitshift = bitshift; } if(fnd == FN_ZERO) { uvar_put((ulong) fnd, FNSIZE, fileo); } else if(maxnlpc == 0) { uvar_put((ulong) fnd, FNSIZE, fileo); uvar_put((ulong) resn, ENERGYSIZE, fileo); switch(fnd) { case FN_DIFF0: for(i = 0; i < blocksize; i++) VAR_PUT(cbuffer[i] - coffset, resn, fileo); break; case FN_DIFF1: for(i = 0; i < blocksize; i++) VAR_PUT(cbuffer[i] - cbuffer[i - 1], resn, fileo); break; case FN_DIFF2: for(i = 0; i < blocksize; i++) VAR_PUT(cbuffer[i] - 2 * cbuffer[i - 1] + cbuffer[i - 2],resn, fileo); break; case FN_DIFF3: for(i = 0; i < blocksize; i++) VAR_PUT(cbuffer[i] - 3 * (cbuffer[i - 1] - cbuffer[i - 2])-cbuffer[i - 3], resn, fileo); break; } } else { uvar_put((ulong) FN_QLPC, FNSIZE, fileo); uvar_put((ulong) resn, ENERGYSIZE, fileo); uvar_put((ulong) nlpc, LPCQSIZE, fileo); for(i = 0; i < nlpc; i++) var_put((slong) qlpc[i], LPCQUANT, fileo); /* deduct mean from everything */ for(i = -nlpc; i < blocksize; i++) cbuffer[i] -= coffset; /* use the quantised LPC coefficients to generate the residual */ for(i = 0; i < blocksize; i++) { int j; slong sum = lpcqoffset; slong *obuffer = &(cbuffer[i - 1]); for(j = 0; j < nlpc; j++) sum += qlpc[j] * obuffer[-j]; var_put(cbuffer[i] - (sum >> LPCQUANT), resn, fileo); } /* add mean back to those samples that will be wrapped */ for(i = blocksize - nwrap; i < blocksize; i++) cbuffer[i] += coffset; } /* do the wrap */ for(i = -nwrap; i < 0; i++) cbuffer[i] = cbuffer[i + blocksize]; } } /* if we had a RIFF WAVE header, we had better be prepared to deal with a RIFF WAVE footer too... */ if (wavhdr) verbatim_file (filei, fileo); /* wind up */ fread_type_quit(); uvar_put((ulong) FN_QUIT, FNSIZE, fileo); var_put_quit(fileo); /* and free the space used */ if (wavhdr) free_header (wavhdr); free((void *) buffer); free((void *) offset); if(maxnlpc > 0) free((void *) qlpc); } else { /***********************/ /* EXTRACT starts here */ /***********************/ int i, cmd; int internal_ftype; bytes_read = 0; /* Firstly skip the number of bytes requested in the command line */ for(i = 0; i < nskip; i++) { int byte = getc(filei); bytes_read++; if(byte == EOF) usage_exit(1, "File too short for requested alignment\n"); putc_exit(byte, fileo); } /* read magic number */#ifdef STRICT_FORMAT_COMPATABILITY if(FORMAT_VERSION < 2) { for(i = 0; i < strlen(magic); i++) { if(getc_exit(filei) != magic[i]) usage_exit(1, "Bad magic number\n"); bytes_read++; } /* get version number */ version = getc_exit(filei); bytes_read++; } else#endif /* STRICT_FORMAT_COMPATABILITY */ { int nscan = 0; version = MAX_VERSION + 1; while(version > MAX_VERSION) { int byte = getc(filei); bytes_read++; if(byte == EOF) { if (WriteSeekTable) { unlink(SeekTableFilename); usage_exit(1, "-k, -s and -S can only be used on shorten files\n"); } else usage_exit(1, "No magic number\n");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -