+static void init_ptable(int *table, int rate_i, int rate_s)
+{
+ int value = 0x808000, rate = rate_i << 8;
+
+ for (int c = (rate + 128) >> 8; c--;)
+ value += (DOWN - value) >> DECAY;
+
+ for (int i = 0; i < PTABLE_BINS/2; i++) {
+ table[i] = value;
+ table[PTABLE_BINS-1-i] = 0x100ffff - value;
+
+ if (value > 0x010000) {
+ rate += (rate * rate_s + 128) >> 8;
+
+ for (int c = (rate + 64) >> 7; c--;)
+ value += (DOWN - value) >> DECAY;
+ }
+ }
+}
+
+typedef struct {
+ int32_t value, fltr0, fltr1, fltr2, fltr3, fltr4, fltr5, fltr6, factor;
+ unsigned int byte;
+} DSDfilters;
+
+static int wv_unpack_dsd_high(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right)
+{
+ uint32_t checksum = 0xFFFFFFFF;
+ uint8_t *dst_l = dst_left, *dst_r = dst_right;
+ int total_samples = s->samples, stereo = dst_r ? 1 : 0;
+ DSDfilters filters[2], *sp = filters;
+ int rate_i, rate_s;
+ uint32_t low, high, value;
+
+ if (bytestream2_get_bytes_left(&s->gbyte) < (stereo ? 20 : 13))
+ return AVERROR_INVALIDDATA;
+
+ rate_i = bytestream2_get_byte(&s->gbyte);
+ rate_s = bytestream2_get_byte(&s->gbyte);
+
+ if (rate_s != RATE_S)
+ return AVERROR_INVALIDDATA;
+
+ init_ptable(s->ptable, rate_i, rate_s);
+
+ for (int channel = 0; channel < stereo + 1; channel++) {
+ DSDfilters *sp = filters + channel;
+
+ sp->fltr1 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8);
+ sp->fltr2 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8);
+ sp->fltr3 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8);
+ sp->fltr4 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8);
+ sp->fltr5 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8);
+ sp->fltr6 = 0;
+ sp->factor = bytestream2_get_byte(&s->gbyte) & 0xff;
+ sp->factor |= (bytestream2_get_byte(&s->gbyte) << 8) & 0xff00;
+ sp->factor = (int32_t)((uint32_t)sp->factor << 16) >> 16;
+ }
+
+ value = bytestream2_get_be32(&s->gbyte);
+ high = 0xffffffff;
+ low = 0x0;
+
+ while (total_samples--) {
+ int bitcount = 8;
+
+ sp[0].value = sp[0].fltr1 - sp[0].fltr5 + ((sp[0].fltr6 * sp[0].factor) >> 2);
+
+ if (stereo)
+ sp[1].value = sp[1].fltr1 - sp[1].fltr5 + ((sp[1].fltr6 * sp[1].factor) >> 2);
+
+ while (bitcount--) {
+ int32_t *pp = s->ptable + ((sp[0].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK);
+ uint32_t split = low + ((high - low) >> 8) * (*pp >> 16);
+
+ if (value <= split) {
+ high = split;
+ *pp += (UP - *pp) >> DECAY;
+ sp[0].fltr0 = -1;
+ } else {
+ low = split + 1;
+ *pp += (DOWN - *pp) >> DECAY;
+ sp[0].fltr0 = 0;
+ }
+
+ while (DSD_BYTE_READY(high, low) && bytestream2_get_bytes_left(&s->gbyte)) {
+ value = (value << 8) | bytestream2_get_byte(&s->gbyte);
+ high = (high << 8) | 0xff;
+ low <<= 8;
+ }
+
+ sp[0].value += sp[0].fltr6 * 8;
+ sp[0].byte = (sp[0].byte << 1) | (sp[0].fltr0 & 1);
+ sp[0].factor += (((sp[0].value ^ sp[0].fltr0) >> 31) | 1) &
+ ((sp[0].value ^ (sp[0].value - (sp[0].fltr6 * 16))) >> 31);
+ sp[0].fltr1 += ((sp[0].fltr0 & VALUE_ONE) - sp[0].fltr1) >> 6;
+ sp[0].fltr2 += ((sp[0].fltr0 & VALUE_ONE) - sp[0].fltr2) >> 4;
+ sp[0].fltr3 += (sp[0].fltr2 - sp[0].fltr3) >> 4;
+ sp[0].fltr4 += (sp[0].fltr3 - sp[0].fltr4) >> 4;
+ sp[0].value = (sp[0].fltr4 - sp[0].fltr5) >> 4;
+ sp[0].fltr5 += sp[0].value;
+ sp[0].fltr6 += (sp[0].value - sp[0].fltr6) >> 3;
+ sp[0].value = sp[0].fltr1 - sp[0].fltr5 + ((sp[0].fltr6 * sp[0].factor) >> 2);
+
+ if (!stereo)
+ continue;
+
+ pp = s->ptable + ((sp[1].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK);
+ split = low + ((high - low) >> 8) * (*pp >> 16);
+
+ if (value <= split) {
+ high = split;
+ *pp += (UP - *pp) >> DECAY;
+ sp[1].fltr0 = -1;
+ } else {
+ low = split + 1;
+ *pp += (DOWN - *pp) >> DECAY;
+ sp[1].fltr0 = 0;
+ }
+
+ while (DSD_BYTE_READY(high, low) && bytestream2_get_bytes_left(&s->gbyte)) {
+ value = (value << 8) | bytestream2_get_byte(&s->gbyte);
+ high = (high << 8) | 0xff;
+ low <<= 8;
+ }
+
+ sp[1].value += sp[1].fltr6 * 8;
+ sp[1].byte = (sp[1].byte << 1) | (sp[1].fltr0 & 1);
+ sp[1].factor += (((sp[1].value ^ sp[1].fltr0) >> 31) | 1) &
+ ((sp[1].value ^ (sp[1].value - (sp[1].fltr6 * 16))) >> 31);
+ sp[1].fltr1 += ((sp[1].fltr0 & VALUE_ONE) - sp[1].fltr1) >> 6;
+ sp[1].fltr2 += ((sp[1].fltr0 & VALUE_ONE) - sp[1].fltr2) >> 4;
+ sp[1].fltr3 += (sp[1].fltr2 - sp[1].fltr3) >> 4;
+ sp[1].fltr4 += (sp[1].fltr3 - sp[1].fltr4) >> 4;
+ sp[1].value = (sp[1].fltr4 - sp[1].fltr5) >> 4;
+ sp[1].fltr5 += sp[1].value;
+ sp[1].fltr6 += (sp[1].value - sp[1].fltr6) >> 3;
+ sp[1].value = sp[1].fltr1 - sp[1].fltr5 + ((sp[1].fltr6 * sp[1].factor) >> 2);
+ }
+
+ checksum += (checksum << 1) + (*dst_l = sp[0].byte & 0xff);
+ sp[0].factor -= (sp[0].factor + 512) >> 10;
+ dst_l += 4;
+
+ if (stereo) {
+ checksum += (checksum << 1) + (*dst_r = filters[1].byte & 0xff);
+ filters[1].factor -= (filters[1].factor + 512) >> 10;
+ dst_r += 4;
+ }
+ }
+
+ if (wv_check_crc(s, checksum, 0)) {
+ if (s->avctx->err_recognition & AV_EF_CRCCHECK)
+ return AVERROR_INVALIDDATA;
+
+ memset(dst_left, 0x69, s->samples * 4);
+
+ if (dst_r)
+ memset(dst_right, 0x69, s->samples * 4);
+ }
+
+ return 0;
+}
+
+static int wv_unpack_dsd_fast(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right)
+{
+ uint8_t *dst_l = dst_left, *dst_r = dst_right;
+ uint8_t history_bits, max_probability;
+ int total_summed_probabilities = 0;
+ int total_samples = s->samples;
+ uint8_t *vlb = s->value_lookup_buffer;
+ int history_bins, p0, p1, chan;
+ uint32_t checksum = 0xFFFFFFFF;
+ uint32_t low, high, value;
+
+ if (!bytestream2_get_bytes_left(&s->gbyte))
+ return AVERROR_INVALIDDATA;
+
+ history_bits = bytestream2_get_byte(&s->gbyte);
+
+ if (!bytestream2_get_bytes_left(&s->gbyte) || history_bits > MAX_HISTORY_BITS)
+ return AVERROR_INVALIDDATA;
+
+ history_bins = 1 << history_bits;
+ max_probability = bytestream2_get_byte(&s->gbyte);
+
+ if (max_probability < 0xff) {
+ uint8_t *outptr = (uint8_t *)s->probabilities;
+ uint8_t *outend = outptr + sizeof(*s->probabilities) * history_bins;
+
+ while (outptr < outend && bytestream2_get_bytes_left(&s->gbyte)) {
+ int code = bytestream2_get_byte(&s->gbyte);
+
+ if (code > max_probability) {
+ int zcount = code - max_probability;
+
+ while (outptr < outend && zcount--)
+ *outptr++ = 0;
+ } else if (code) {
+ *outptr++ = code;
+ }
+ else {
+ break;
+ }
+ }
+
+ if (outptr < outend ||
+ (bytestream2_get_bytes_left(&s->gbyte) && bytestream2_get_byte(&s->gbyte)))
+ return AVERROR_INVALIDDATA;
+ } else if (bytestream2_get_bytes_left(&s->gbyte) > (int)sizeof(*s->probabilities) * history_bins) {
+ bytestream2_get_buffer(&s->gbyte, (uint8_t *)s->probabilities,
+ sizeof(*s->probabilities) * history_bins);
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+
+ for (p0 = 0; p0 < history_bins; p0++) {
+ int32_t sum_values = 0;
+
+ for (int i = 0; i < 256; i++)
+ s->summed_probabilities[p0][i] = sum_values += s->probabilities[p0][i];
+
+ if (sum_values) {
+ total_summed_probabilities += sum_values;
+
+ if (total_summed_probabilities > history_bins * MAX_BIN_BYTES)
+ return AVERROR_INVALIDDATA;
+
+ s->value_lookup[p0] = vlb;
+
+ for (int i = 0; i < 256; i++) {
+ int c = s->probabilities[p0][i];
+
+ while (c--)
+ *vlb++ = i;
+ }
+ }
+ }
+
+ if (bytestream2_get_bytes_left(&s->gbyte) < 4)
+ return AVERROR_INVALIDDATA;
+
+ chan = p0 = p1 = 0;
+ low = 0; high = 0xffffffff;
+ value = bytestream2_get_be32(&s->gbyte);
+
+ if (dst_r)
+ total_samples *= 2;
+
+ while (total_samples--) {
+ unsigned int mult, index, code;
+
+ if (!s->summed_probabilities[p0][255])
+ return AVERROR_INVALIDDATA;
+
+ mult = (high - low) / s->summed_probabilities[p0][255];
+
+ if (!mult) {
+ if (bytestream2_get_bytes_left(&s->gbyte) >= 4)
+ value = bytestream2_get_be32(&s->gbyte);
+
+ low = 0;
+ high = 0xffffffff;
+ mult = high / s->summed_probabilities[p0][255];
+
+ if (!mult)
+ return AVERROR_INVALIDDATA;
+ }
+
+ index = (value - low) / mult;
+
+ if (index >= s->summed_probabilities[p0][255])
+ return AVERROR_INVALIDDATA;
+
+ if (!dst_r) {
+ if ((*dst_l = code = s->value_lookup[p0][index]))
+ low += s->summed_probabilities[p0][code-1] * mult;
+
+ dst_l += 4;
+ } else {
+ if ((code = s->value_lookup[p0][index]))
+ low += s->summed_probabilities[p0][code-1] * mult;
+
+ if (chan) {
+ *dst_r = code;
+ dst_r += 4;
+ }
+ else {
+ *dst_l = code;
+ dst_l += 4;
+ }
+
+ chan ^= 1;
+ }
+
+ high = low + s->probabilities[p0][code] * mult - 1;
+ checksum += (checksum << 1) + code;
+
+ if (!dst_r) {
+ p0 = code & (history_bins-1);
+ } else {
+ p0 = p1;
+ p1 = code & (history_bins-1);
+ }
+
+ while (DSD_BYTE_READY(high, low) && bytestream2_get_bytes_left(&s->gbyte)) {
+ value = (value << 8) | bytestream2_get_byte(&s->gbyte);
+ high = (high << 8) | 0xff;
+ low <<= 8;
+ }
+ }
+
+ if (wv_check_crc(s, checksum, 0)) {
+ if (s->avctx->err_recognition & AV_EF_CRCCHECK)
+ return AVERROR_INVALIDDATA;
+
+ memset(dst_left, 0x69, s->samples * 4);
+
+ if (dst_r)
+ memset(dst_right, 0x69, s->samples * 4);
+ }
+
+ return 0;
+}
+
+static int wv_unpack_dsd_copy(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right)
+{
+ uint8_t *dst_l = dst_left, *dst_r = dst_right;
+ int total_samples = s->samples;
+ uint32_t checksum = 0xFFFFFFFF;
+
+ if (bytestream2_get_bytes_left(&s->gbyte) != total_samples * (dst_r ? 2 : 1))
+ return AVERROR_INVALIDDATA;
+
+ while (total_samples--) {
+ checksum += (checksum << 1) + (*dst_l = bytestream2_get_byte(&s->gbyte));
+ dst_l += 4;
+
+ if (dst_r) {
+ checksum += (checksum << 1) + (*dst_r = bytestream2_get_byte(&s->gbyte));
+ dst_r += 4;
+ }
+ }
+
+ if (wv_check_crc(s, checksum, 0)) {
+ if (s->avctx->err_recognition & AV_EF_CRCCHECK)
+ return AVERROR_INVALIDDATA;
+
+ memset(dst_left, 0x69, s->samples * 4);
+
+ if (dst_r)
+ memset(dst_right, 0x69, s->samples * 4);
+ }
+
+ return 0;
+}
+