📄 shorten.c
字号:
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; } } /* this is the main read/code/write loop for the whole file */ while((nread = fread_type(buffer, ftype, nchan, blocksize, filei)) != 0) { /* 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*/ long coffset, *cbuffer = buffer[chan], fulloffset = 0L; int fnd, resn = 0, nlpc = 0; /* force the lower quanterror bits to be zero */ if(quanterror != 0) { long 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 { long 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) { long 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) { long 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((long) 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; long sum = lpcqoffset; long *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]; } } /* wind up */ fread_type_quit(); uvar_put((ulong) FN_QUIT, FNSIZE, fileo); var_put_quit(fileo); /* and free the space used */ free((char*) buffer); free((char*) buffer1); free((char*) offset); if(maxnlpc > 0) free((char*) qlpc); } else { /***********************/ /* EXTRACT starts here */ /***********************/ int i, cmd; /* firstly skip the number of bytes requested in the command line */ for(i = 0; i < nskip; i++) { int byte = getc(filei); 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"); /* get version number */ version = getc_exit(filei); } else#endif /* STRICT_FORMAT_COMPATABILITY */ { int nscan = 0; version = MAX_VERSION + 1; while(version > MAX_VERSION) { int byte = getc(filei); if(byte == EOF) usage_exit(1, "No magic number\n"); if(magic[nscan] != '\0' && byte == magic[nscan]) nscan++; else if(magic[nscan] == '\0' && byte <= MAX_VERSION) version = byte; else { for(i = 0; i < nscan; i++) putc_exit(magic[i], fileo); if(byte == magic[0]) nscan = 1; else { putc_exit(byte, fileo); nscan = 0; } version = MAX_VERSION + 1; } } } /* check version number */ if(version > MAX_SUPPORTED_VERSION) update_exit(1, "can't decode version %d\n", version); /* set up the default nmean, ignoring the command line state */ nmean = (version < 2) ? DEFAULT_V0NMEAN : DEFAULT_V2NMEAN; /* initialise the variable length file read for the compressed stream */ var_get_init(); /* initialise the fixed length file write for the uncompressed stream */ fwrite_type_init(); /* get file type and set up appropriately, ignoring command line state */ ftype = UINT_GET(TYPESIZE, filei); if(ftype >= TYPE_EOF) update_exit(1, "can't decode file type %d\n", ftype); nchan = UINT_GET(CHANSIZE, filei); /* get blocksize if version > 0 */ if(version > 0) { blocksize = UINT_GET((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2), filei); maxnlpc = UINT_GET(LPCQSIZE, filei); nmean = UINT_GET(0, filei); nskip = UINT_GET(NSKIPSIZE, filei); for(i = 0; i < nskip; i++) { int byte = uvar_get(XBYTESIZE, filei); putc_exit(byte, fileo); } } else blocksize = DEFAULT_BLOCK_SIZE; nwrap = MAX(NWRAP, maxnlpc); /* grab some space for the input buffer */ buffer = long2d((ulong) nchan, (ulong) (blocksize + nwrap)); offset = long2d((ulong) nchan, (ulong) MAX(1, nmean)); for(chan = 0; chan < nchan; chan++) { for(i = 0; i < nwrap; i++) buffer[chan][i] = 0; buffer[chan] += nwrap; } if(maxnlpc > 0) qlpc = (int*) pmalloc((ulong) (maxnlpc * sizeof(*qlpc))); if(version > 1) lpcqoffset = V2LPCQOFFSET; init_offset(offset, nchan, MAX(1, nmean), ftype); /* get commands from file and execute them */ chan = 0; while((cmd = uvar_get(FNSIZE, filei)) != FN_QUIT) switch(cmd) { case FN_ZERO: case FN_DIFF0: case FN_DIFF1: case FN_DIFF2: case FN_DIFF3: case FN_QLPC: { long coffset, *cbuffer = buffer[chan]; int resn = 0, nlpc, j; if(cmd != FN_ZERO) { resn = uvar_get(ENERGYSIZE, filei); /* this is a hack as version 0 differed in definition of var_get */ if(version == 0) resn--; } /* find mean offset : N.B. this code duplicated */ if(nmean == 0) coffset = offset[chan][0]; else { long sum = (version < 2) ? 0 : nmean / 2; for(i = 0; i < nmean; i++) sum += offset[chan][i]; if(version < 2) coffset = sum / nmean; else coffset = ROUNDEDSHIFTDOWN(sum / nmean, bitshift); } switch(cmd) { case FN_ZERO: for(i = 0; i < blocksize; i++) cbuffer[i] = 0; break; case FN_DIFF0: for(i = 0; i < blocksize; i++) cbuffer[i] = var_get(resn, filei) + coffset; break; case FN_DIFF1: for(i = 0; i < blocksize; i++) cbuffer[i] = var_get(resn, filei) + cbuffer[i - 1]; break; case FN_DIFF2: for(i = 0; i < blocksize; i++) cbuffer[i] = var_get(resn, filei) + (2 * cbuffer[i - 1] - cbuffer[i - 2]); break; case FN_DIFF3: for(i = 0; i < blocksize; i++) cbuffer[i] = var_get(resn, filei) + 3 * (cbuffer[i - 1] - cbuffer[i - 2]) + cbuffer[i - 3]; break; case FN_QLPC: nlpc = uvar_get(LPCQSIZE, filei); for(i = 0; i < nlpc; i++) qlpc[i] = var_get(LPCQUANT, filei); for(i = 0; i < nlpc; i++) cbuffer[i - nlpc] -= coffset; for(i = 0; i < blocksize; i++) { long sum = lpcqoffset; for(j = 0; j < nlpc; j++) sum += qlpc[j] * cbuffer[i - j - 1]; cbuffer[i] = var_get(resn, filei) + (sum >> LPCQUANT); } if(coffset != 0) for(i = 0; i < blocksize; i++) cbuffer[i] += coffset; break; } /* store mean value if appropriate : N.B. Duplicated code */ if(nmean > 0) { long 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; } /* do the wrap */ for(i = -nwrap; i < 0; i++) cbuffer[i] = cbuffer[i + blocksize]; fix_bitshift(cbuffer, blocksize, bitshift, ftype); if(chan == nchan - 1) fwrite_type(buffer, ftype, nchan, blocksize, fileo); chan = (chan + 1) % nchan; } break; case FN_BLOCKSIZE: blocksize = UINT_GET((int) (log((double) blocksize) / M_LN2), filei); break; case FN_BITSHIFT: bitshift = uvar_get(BITSHIFTSIZE, filei); break; default: update_exit(1, "sanity check fails trying to decode function: %d\n", cmd); } /* wind up */ var_get_quit(); fwrite_type_quit(); free((char*) buffer); free((char*) offset); if(maxnlpc > 0) free((char*) qlpc); } /* close the files if this function opened them */ if(filei != stdi) fclose(filei); if(fileo != stdo) fclose(fileo); /* make the compressed file look like the original if possible */ if((filei != stdi) && (fileo != stdo)) (void) dupfileinfo(filenamei, filenameo); if(tmpfilename != NULL) free(tmpfilename); if(nfilename == 1) if(unlink(filenamei)) perror_exit("unlink(\"%s\")", filenamei); /* quit happy */ return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -