///////////////////////////// executable code //////////////////////////////// // Read the median log2 values from the specifed metadata structure, convert // them back to 32-bit unsigned values and store them. If length is not // exactly correct then we flag and return an error. internal static int read_entropy_vars(WavpackStream wps, WavpackMetadata wpmd) { byte[] byteptr = wpmd.data; int[] b_array = new int[12]; int i = 0; words_data w = new words_data(); for (i = 0; i < 6; i++) { b_array[i] = (int)(byteptr[i] & 0xff); } w.holding_one = 0; w.holding_zero = 0; if (wpmd.byte_length != 12) { if ((wps.wphdr.flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) == 0) { return(Defines.FALSE); } } w.c[0].median[0] = exp2s(b_array[0] + (b_array[1] << 8)); w.c[0].median[1] = exp2s(b_array[2] + (b_array[3] << 8)); w.c[0].median[2] = exp2s(b_array[4] + (b_array[5] << 8)); if ((wps.wphdr.flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) == 0) { for (i = 6; i < 12; i++) { b_array[i] = (int)(byteptr[i] & 0xff); } w.c[1].median[0] = exp2s(b_array[6] + (b_array[7] << 8)); w.c[1].median[1] = exp2s(b_array[8] + (b_array[9] << 8)); w.c[1].median[2] = exp2s(b_array[10] + (b_array[11] << 8)); } wps.w = w; return(Defines.TRUE); }
// Read the next word from the bitstream "wvbits" and return the value. This // function can be used for hybrid or lossless streams, but since an // optimized version is available for lossless this function would normally // be used for hybrid only. If a hybrid lossless stream is being read then // the "correction" offset is written at the specified pointer. A return value // of WORD_EOF indicates that the end of the bitstream was reached (all 1s) or // some other error occurred. internal static int get_words(long nsamples, long flags, words_data w, Bitstream bs, int[] buffer, int bufferStartPos) { entropy_data[] c = w.c; int csamples; int buffer_counter = bufferStartPos; int entidx = 1; if ((flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) == 0) // if not mono { nsamples *= 2; } else { // it is mono entidx = 0; } for (csamples = 0; csamples < nsamples; ++csamples) { long ones_count, low, high, mid; if ((flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) == 0) // if not mono { if (entidx == 1) { entidx = 0; } else { entidx = 1; } } if ((w.c[0].median[0] & ~1) == 0 && w.holding_zero == 0 && w.holding_one == 0 && (w.c[1].median[0] & ~1) == 0) { long mask; int cbits; if (w.zeros_acc > 0) { --w.zeros_acc; if (w.zeros_acc > 0) { c[entidx].slow_level -= ((c[entidx].slow_level + SLO) >> SLS); buffer[buffer_counter] = 0; buffer_counter++; continue; } } else { cbits = 0; bs = BitsUtils.getbit(bs); while (cbits < 33 && bs.bitval > 0) { cbits++; bs = BitsUtils.getbit(bs); } if (cbits == 33) { break; } if (cbits < 2) { w.zeros_acc = cbits; } else { --cbits; for (mask = 1, w.zeros_acc = 0; cbits > 0; mask <<= 1) { bs = BitsUtils.getbit(bs); if (bs.bitval > 0) { w.zeros_acc |= mask; } cbits--; } w.zeros_acc |= mask; } if (w.zeros_acc > 0) { c[entidx].slow_level -= ((c[entidx].slow_level + SLO) >> SLS); w.c[0].median[0] = 0; w.c[0].median[1] = 0; w.c[0].median[2] = 0; w.c[1].median[0] = 0; w.c[1].median[1] = 0; w.c[1].median[2] = 0; buffer[buffer_counter] = 0; buffer_counter++; continue; } } } if (w.holding_zero > 0) { ones_count = w.holding_zero = 0; } else { int next8; int uns_buf; if (bs.bc < 8) { bs.ptr++; bs.buf_index++; if (bs.ptr == bs.end) { bs = BitsUtils.bs_read(bs); } uns_buf = (int)(bs.buf[bs.buf_index] & 0xff); bs.sr = bs.sr | (uns_buf << bs.bc); // values in buffer must be unsigned next8 = (int)(bs.sr & 0xff); bs.bc += 8; } else { next8 = (int)(bs.sr & 0xff); } if (next8 == 0xff) { bs.bc -= 8; bs.sr >>= 8; ones_count = 8; bs = BitsUtils.getbit(bs); while (ones_count < (LIMIT_ONES + 1) && bs.bitval > 0) { ones_count++; bs = BitsUtils.getbit(bs); } if (ones_count == (LIMIT_ONES + 1)) { break; } if (ones_count == LIMIT_ONES) { int mask; int cbits; cbits = 0; bs = BitsUtils.getbit(bs); while (cbits < 33 && bs.bitval > 0) { cbits++; bs = BitsUtils.getbit(bs); } if (cbits == 33) { break; } if (cbits < 2) { ones_count = cbits; } else { for (mask = 1, ones_count = 0; --cbits > 0; mask <<= 1) { bs = BitsUtils.getbit(bs); if (bs.bitval > 0) { ones_count |= mask; } } ones_count |= mask; } ones_count += LIMIT_ONES; } } else { bs.bc = (int)(bs.bc - ((ones_count = ones_count_table[next8]) + 1)); bs.sr = bs.sr >> (int)(ones_count + 1); // needs to be unsigned } if (w.holding_one > 0) { w.holding_one = ones_count & 1; ones_count = (ones_count >> 1) + 1; } else { w.holding_one = ones_count & 1; ones_count >>= 1; } w.holding_zero = (int)(~w.holding_one & 1); } if ((flags & Defines.HYBRID_FLAG) > 0 && ((flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) > 0 || (csamples & 1) == 0)) { w = update_error_limit(w, flags); } if (ones_count == 0) { low = 0; high = (((c[entidx].median[0]) >> 4) + 1) - 1; // for c# I replace the division by DIV0 with >> 7 c[entidx].median[0] -= (((c[entidx].median[0] + (DIV0 - 2)) >> 7) * 2); } else { low = (((c[entidx].median[0]) >> 4) + 1); // for c# I replace the division by DIV0 with >> 7 c[entidx].median[0] += ((c[entidx].median[0] + DIV0) >> 7) * 5; if (ones_count == 1) { high = low + (((c[entidx].median[1]) >> 4) + 1) - 1; // for c# I replace the division by DIV1 with >> 6 c[entidx].median[1] -= ((c[entidx].median[1] + (DIV1 - 2)) >> 6) * 2; } else { low += (((c[entidx].median[1]) >> 4) + 1); // for c# I replace the division by DIV1 with >> 6 c[entidx].median[1] += ((c[entidx].median[1] + DIV1) >> 6) * 5; if (ones_count == 2) { high = low + (((c[entidx].median[2]) >> 4) + 1) - 1; // for c# I replace the division by DIV2 with >> 5 c[entidx].median[2] -= ((c[entidx].median[2] + (DIV2 - 2)) >> 5) * 2; } else { low += (ones_count - 2) * (((c[entidx].median[2]) >> 4) + 1); high = low + (((c[entidx].median[2]) >> 4) + 1) - 1; // for c# I replace the division by DIV2 with >> 5 c[entidx].median[2] += ((c[entidx].median[2] + DIV2) >> 5) * 5; } } } mid = (high + low + 1) >> 1; if (c[entidx].error_limit == 0) { mid = read_code(bs, high - low); mid = mid + low; } else { while (high - low > c[entidx].error_limit) { bs = BitsUtils.getbit(bs); if (bs.bitval > 0) { mid = (high + (low = mid) + 1) >> 1; } else { mid = ((high = mid - 1) + low + 1) >> 1; } } } bs = BitsUtils.getbit(bs); if (bs.bitval > 0) { buffer[buffer_counter] = (int)~mid; } else { buffer[buffer_counter] = (int)mid; } buffer_counter++; if ((flags & Defines.HYBRID_BITRATE) > 0) { c[entidx].slow_level = c[entidx].slow_level - ((c[entidx].slow_level + SLO) >> SLS) + mylog2(mid); } } w.c = c; if ((flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) != 0) { return(csamples); } else { return(csamples / 2); } }
// This function is called during both encoding and decoding of hybrid data to // update the "error_limit" variable which determines the maximum sample error // allowed in the main bitstream. In the HYBRID_BITRATE mode (which is the only // currently implemented) this is calculated from the slow_level values and the // bitrate accumulators. Note that the bitrate accumulators can be changing. internal static words_data update_error_limit(words_data w, long flags) { int bitrate_0 = (int)((w.bitrate_acc[0] += w.bitrate_delta[0]) >> 16); if ((flags & (Defines.MONO_FLAG | Defines.FALSE_STEREO)) != 0) { if ((flags & Defines.HYBRID_BITRATE) != 0) { int slow_log_0 = (int)((w.c[0].slow_level + SLO) >> SLS); if (slow_log_0 - bitrate_0 > -0x100) { w.c[0].error_limit = exp2s(slow_log_0 - bitrate_0 + 0x100); } else { w.c[0].error_limit = 0; } } else { w.c[0].error_limit = exp2s(bitrate_0); } } else { int bitrate_1 = (int)((w.bitrate_acc[1] += w.bitrate_delta[1]) >> 16); if ((flags & Defines.HYBRID_BITRATE) != 0) { int slow_log_0 = (int)((w.c[0].slow_level + SLO) >> SLS); int slow_log_1 = (int)((w.c[1].slow_level + SLO) >> SLS); if ((flags & Defines.HYBRID_BALANCE) != 0) { int balance = (slow_log_1 - slow_log_0 + bitrate_1 + 1) >> 1; if (balance > bitrate_0) { bitrate_1 = bitrate_0 * 2; bitrate_0 = 0; } else if (-balance > bitrate_0) { bitrate_0 = bitrate_0 * 2; bitrate_1 = 0; } else { bitrate_1 = bitrate_0 + balance; bitrate_0 = bitrate_0 - balance; } } if (slow_log_0 - bitrate_0 > -0x100) { w.c[0].error_limit = exp2s(slow_log_0 - bitrate_0 + 0x100); } else { w.c[0].error_limit = 0; } if (slow_log_1 - bitrate_1 > -0x100) { w.c[1].error_limit = exp2s(slow_log_1 - bitrate_1 + 0x100); } else { w.c[1].error_limit = 0; } } else { w.c[0].error_limit = exp2s(bitrate_0); w.c[1].error_limit = exp2s(bitrate_1); } } return(w); }