static int parse_dmix_coeffs(struct xll_chset *chs) { struct xll_decoder *xll = chs->decoder; int m, n; if (chs->primary_chset) { m = dmix_primary_nch[chs->dmix_type]; n = chs->nchannels; } else { m = chs->dmix_m; n = chs->nchannels + 2; // Two extra columns for scales } // Reallocate downmix coefficients matrix if (ta_zalloc_fast(xll->chset, &chs->dmix_coeff, m * n, sizeof(int)) < 0) return -DCADEC_ENOMEM; if (chs->primary_chset) { chs->dmix_scale = NULL; chs->dmix_scale_inv = NULL; } else { chs->dmix_scale = chs->dmix_coeff + m * chs->nchannels; chs->dmix_scale_inv = chs->dmix_coeff + m * (chs->nchannels + 1); } int *coeff_ptr = chs->dmix_coeff; for (int i = 0; i < m; i++) { int scale_inv = 0; // Downmix scale // Only for non-primary channel sets if (!chs->primary_chset) { int code = bits_get(&xll->bits, 9); int sign = (code >> 8) - 1; code &= 0xff; if (code > 0) { unsigned int index = code - 1; enforce(index >= 40 && index < dca_countof(dmix_table), "Invalid downmix scale index"); int scale = dmix_table[index]; scale_inv = dmix_table_inv[index - 40]; chs->dmix_scale[i] = (scale ^ sign) - sign; chs->dmix_scale_inv[i] = (scale_inv ^ sign) - sign; } else { chs->dmix_scale[i] = 0; chs->dmix_scale_inv[i] = 0; } } // Downmix coefficients for (int j = 0; j < chs->nchannels; j++) { int code = bits_get(&xll->bits, 9); int sign = (code >> 8) - 1; code &= 0xff; if (code > 0) { unsigned int index = code - 1; enforce(index < dca_countof(dmix_table), "Invalid downmix coefficient index"); int coeff = dmix_table[index]; if (!chs->primary_chset) // Multiply by |InvDmixScale| to get |UndoDmixScale| coeff = mul16(scale_inv, coeff); // Convert sign *coeff_ptr++ = (coeff ^ sign) - sign; } else { *coeff_ptr++ = 0; } } }
int exss_parse(struct exss_parser *exss, uint8_t *data, int size) { int i, j, ret; bits_init(&exss->bits, data, size); // Extension substream sync word bits_skip(&exss->bits, 32); // User defined bits bits_skip(&exss->bits, 8); // Extension substream index exss->exss_index = bits_get(&exss->bits, 2); // Flag indicating short or long header size bool wide_hdr = bits_get1(&exss->bits); // Extension substream header length int header_size = bits_get(&exss->bits, 8 + 4 * wide_hdr) + 1; // Check CRC if ((ret = bits_check_crc(&exss->bits, 32 + 8, header_size * 8)) < 0) { exss_err("Invalid EXSS header checksum"); return ret; } exss->exss_size_nbits = 16 + 4 * wide_hdr; // Number of bytes of extension substream exss->exss_size = bits_get(&exss->bits, exss->exss_size_nbits) + 1; if (exss->exss_size > size) { exss_err("Packet too short for EXSS frame"); return -DCADEC_EBADDATA; } // Per stream static fields presence flag exss->static_fields_present = bits_get1(&exss->bits); if (exss->static_fields_present) { // Reference clock code bits_skip(&exss->bits, 2); // Extension substream frame duration bits_skip(&exss->bits, 3); // Timecode presence flag if (bits_get1(&exss->bits)) { // Timecode data bits_skip(&exss->bits, 32); bits_skip(&exss->bits, 4); } // Number of defined audio presentations exss->npresents = bits_get(&exss->bits, 3) + 1; // Number of audio assets in extension substream exss->nassets = bits_get(&exss->bits, 3) + 1; // Reject unsupported features for now if (exss->npresents > 1 || exss->nassets > 1) { exss_err_once("Multiple audio presentations " "and/or assets are not supported"); return -DCADEC_ENOSUP; } // Active extension substream mask for audio presentation int active_exss_mask[8]; for (i = 0; i < exss->npresents; i++) active_exss_mask[i] = bits_get(&exss->bits, exss->exss_index + 1); // Active audio asset mask for (i = 0; i < exss->npresents; i++) for (j = 0; j <= exss->exss_index; j++) if (active_exss_mask[i] & (1 << j)) bits_skip(&exss->bits, 8); // Mixing metadata enable flag exss->mix_metadata_enabled = bits_get1(&exss->bits); if (exss->mix_metadata_enabled) { // Mixing metadata adjustment level bits_skip(&exss->bits, 2); // Number of bits for mixer output speaker activity mask int spkr_mask_nbits = (bits_get(&exss->bits, 2) + 1) << 2; // Number of mixing configurations exss->nmixoutconfigs = bits_get(&exss->bits, 2) + 1; // Speaker layout mask for mixer output channels for (i = 0; i < exss->nmixoutconfigs; i++) exss->nmixoutchs[i] = count_chs_for_mask(bits_get(&exss->bits, spkr_mask_nbits)); } } else { exss->npresents = 1; exss->nassets = 1; } // Reallocate assets if (ta_zalloc_fast(exss, &exss->assets, exss->nassets, sizeof(struct exss_asset)) < 0) return -DCADEC_ENOMEM; // Size of encoded asset data in bytes int offset = header_size; for (i = 0; i < exss->nassets; i++) { exss->assets[i].asset_offset = offset; exss->assets[i].asset_size = bits_get(&exss->bits, exss->exss_size_nbits) + 1; offset += exss->assets[i].asset_size; if (offset > exss->exss_size) { exss_err("Asset out of bounds"); return -DCADEC_EBADDATA; } } // Audio asset descriptor for (i = 0; i < exss->nassets; i++) { exss->assets[i].parser = exss; if ((ret = parse_descriptor(&exss->assets[i])) < 0) return ret; if ((ret = set_exss_offsets(&exss->assets[i])) < 0) { exss_err("Invalid extension size in asset descriptor"); return ret; } } // Backward compatible core present // Backward compatible core substream index // Backward compatible core asset index // Reserved // Byte align // CRC16 of extension substream header if ((ret = bits_seek(&exss->bits, header_size * 8)) < 0) exss_err("Read past end of EXSS header"); return ret; }
static int parse_dmix_coeffs(struct xll_chset *chs) { struct xll_decoder *xll = chs->decoder; int m, n; if (chs->primary_chset) { m = dmix_primary_nch[chs->dmix_type]; n = chs->nchannels; } else { m = chs->dmix_m; n = chs->nchannels + 2; // Two extra columns for scales } // Reallocate downmix coefficients buffer if (ta_zalloc_fast(xll->chset, &chs->dmix_coeff, m * n * 2, sizeof(int)) < 0) return -DCADEC_ENOMEM; // Setup buffer pointers for current and previous frame bool valid = (chs->dmix_coeffs_signature == XLL_DMIX_SIGNATURE(chs)); chs->dmix_coeff_cur = chs->dmix_coeff + m * n * chs->dmix_coeffs_parity; chs->dmix_coeff_pre = chs->dmix_coeff + m * n * (chs->dmix_coeffs_parity ^ valid); if (chs->primary_chset) { chs->dmix_scale_cur = chs->dmix_scale_pre = NULL; chs->dmix_scale_inv_cur = chs->dmix_scale_inv_pre = NULL; } else { chs->dmix_scale_cur = chs->dmix_coeff_cur + m * chs->nchannels; chs->dmix_scale_pre = chs->dmix_coeff_pre + m * chs->nchannels; chs->dmix_scale_inv_cur = chs->dmix_coeff_cur + m * (chs->nchannels + 1); chs->dmix_scale_inv_pre = chs->dmix_coeff_pre + m * (chs->nchannels + 1); } int *coeff_ptr = chs->dmix_coeff_cur; for (int i = 0; i < m; i++) { int scale_inv = 0; // Downmix scale // Only for non-primary channel sets if (!chs->primary_chset) { int code = bits_get(&xll->bits, 9); int sign = (code >> 8) - 1; code &= 0xff; if (code > 0) { unsigned int index = code - 1; if (index < 40 || index >= dca_countof(dmix_table)) { xll_err("Invalid downmix scale index"); return -DCADEC_EBADDATA; } int scale = dmix_table[index]; scale_inv = dmix_table_inv[index - 40]; chs->dmix_scale_cur[i] = (scale ^ sign) - sign; chs->dmix_scale_inv_cur[i] = (scale_inv ^ sign) - sign; } else { chs->dmix_scale_cur[i] = 0; chs->dmix_scale_inv_cur[i] = 0; } } // Downmix coefficients for (int j = 0; j < chs->nchannels; j++) { int code = bits_get(&xll->bits, 9); int sign = (code >> 8) - 1; code &= 0xff; if (code > 0) { unsigned int index = code - 1; if (index >= dca_countof(dmix_table)) { xll_err("Invalid downmix coefficient index"); return -DCADEC_EBADDATA; } int coeff = dmix_table[index]; if (!chs->primary_chset) // Multiply by |InvDmixScale| to get |UndoDmixScale| coeff = mul16(scale_inv, coeff); // Convert sign *coeff_ptr++ = (coeff ^ sign) - sign; } else { *coeff_ptr++ = 0; } } }