AV_CH_BACK_CENTER,
AV_CH_BACK_LEFT,
AV_CH_BACK_RIGHT,
- AV_CH_BACK_LEFT, /* side surround left -- dup sur rear L */
- AV_CH_BACK_RIGHT, /* side surround right -- dup sur rear R */
+ AV_CH_SIDE_LEFT, /* side surround left -- dup sur side L */
+ AV_CH_SIDE_RIGHT, /* side surround right -- dup sur side R */
AV_CH_FRONT_LEFT_OF_CENTER,
AV_CH_FRONT_RIGHT_OF_CENTER,
AV_CH_TOP_FRONT_LEFT,
/* XXCH extension information */
int xxch_chset;
int xxch_nbits_spk_mask;
- int xxch_num_chsets; /* number of channel sets */
uint32_t xxch_core_spkmask;
- int xxch_num_chans[4]; /* num in channel set */
uint32_t xxch_spk_masks[4]; /* speaker masks, last element is core mask */
int xxch_chset_nch[4];
+ float xxch_dmix_sf[DCA_CHSETS_MAX];
uint32_t xxch_downmix; /* downmix enabled per channel set */
uint32_t xxch_dmix_embedded; /* lower layer has mix pre-embedded, per chset */
*dst++ = get_bits(gb, bits);
}
+static inline int dca_xxch2index(DCAContext *s, int xxch_ch)
+{
+ int i, base, mask;
+
+ /* locate channel set containing the channel */
+ for (i = -1, base = 0, mask = (s->xxch_core_spkmask & ~DCA_XXCH_LFE1);
+ i <= s->xxch_chset && !(mask & xxch_ch); mask = s->xxch_spk_masks[++i])
+ base += av_popcount(mask);
+
+ return base + av_popcount(mask & (xxch_ch - 1));
+}
+
static int dca_parse_audio_coding_header(DCAContext *s, int base_channel,
int xxch)
{
if (get_bits1(&s->gb)) {
embedded_downmix = get_bits1(&s->gb);
scale_factor =
- 1.0f / dca_downmix_scale_factors[get_bits(&s->gb, 6) << 2];
+ 1.0f / dca_downmix_scale_factors[(get_bits(&s->gb, 6) - 1) << 2];
+
+ s->xxch_dmix_sf[s->xxch_chset] = scale_factor;
for (i = base_channel; i < s->prim_channels; i++) {
s->xxch_downmix |= (1 << i);
for (j = base_channel; j < s->prim_channels; j++) {
memset(s->xxch_dmix_coeff[j], 0, sizeof(s->xxch_dmix_coeff[0]));
- if (mask[j])
- s->xxch_dmix_embedded |= (embedded_downmix << j);
+ s->xxch_dmix_embedded |= (embedded_downmix << j);
for (i = 0; i < s->xxch_nbits_spk_mask; i++) {
if (mask[j] & (1 << i)) {
+ if ((1 << i) == DCA_XXCH_LFE1) {
+ av_log(s->avctx, AV_LOG_WARNING,
+ "DCA-XXCH: dmix to LFE1 not supported.\n");
+ continue;
+ }
+
coeff = get_bits(&s->gb, 7);
sign = (coeff & 64) ? 1.0 : -1.0;
- mag = dca_downmix_scale_factors[(coeff & 63) << 2];
- ichan = av_popcount((acc_mask & ~DCA_XXCH_LFE1)
- & ((1 << i) - 1));
- s->xxch_dmix_coeff[j][ichan] = sign * mag * scale_factor;
+ mag = dca_downmix_scale_factors[((coeff & 63) - 1) << 2];
+ ichan = dca_xxch2index(s, 1 << i);
+ s->xxch_dmix_coeff[j][ichan] = sign * mag;
}
}
}
int lavc;
int posn;
int j, k;
+ int ch;
+ int endch;
s->xch_present = 0;
}
/* If stream contains XXCH, we might need to undo an embedded downmix */
- if (s->xxch_downmix & s->xxch_dmix_embedded) {
- mask = s->xxch_downmix & s->xxch_dmix_embedded;
- for (j = 0; j < channels; j++) {
- if (mask & (1 << j)) { /* this channel has been mixed-out */
- src_chan = s->samples + s->channel_order_tab[j] * 256;
- for (k = 0; k < channels - !!s->lfe; k++) {
- achan = s->channel_order_tab[k];
- scale = s->xxch_dmix_coeff[j][k];
- if (scale != 0.0) {
- dst_chan = s->samples + achan * 256;
- s->fdsp.vector_fmac_scalar(dst_chan, src_chan,
- -scale, 256);
+ if (s->xxch_dmix_embedded) {
+ /* Loop over channel sets in turn */
+ ch = num_core_channels;
+ for (chset = 0; chset < s->xxch_chset; chset++) {
+ endch = ch + s->xxch_chset_nch[chset];
+ mask = s->xxch_dmix_embedded;
+
+ /* undo downmix */
+ for (j = ch; j < endch; j++) {
+ if (mask & (1 << j)) { /* this channel has been mixed-out */
+ src_chan = s->samples + s->channel_order_tab[j] * 256;
+ for (k = 0; k < endch; k++) {
+ achan = s->channel_order_tab[k];
+ scale = s->xxch_dmix_coeff[j][k];
+ if (scale != 0.0) {
+ dst_chan = s->samples + achan * 256;
+ s->fdsp.vector_fmac_scalar(dst_chan, src_chan,
+ -scale, 256);
+ }
}
}
}
+
+ /* if a downmix has been embedded then undo the pre-scaling */
+ if ((mask & (1 << ch)) && s->xxch_dmix_sf[chset] != 1.0f) {
+ scale = s->xxch_dmix_sf[chset];
+
+ for (j = 0; j < ch; j++) {
+ src_chan = s->samples + s->channel_order_tab[j] * 256;
+ for (k = 0; k < 256; k++)
+ src_chan[k] *= scale;
+ }
+
+ /* LFE channel is always part of core, scale if it exists */
+ if (s->lfe) {
+ src_chan = s->samples + s->lfe_index * 256;
+ for (k = 0; k < 256; k++)
+ src_chan[k] *= scale;
+ }
+ }
+
+ ch = endch;
}
+
}
if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) {