dca: support mixing LFE in dca_downmix.

Embedded downmix coefficients can use this.

Signed-off-by: Anton Khirnov <anton@khirnov.net>
This commit is contained in:
Tim Walker 2013-11-22 23:47:03 +01:00 committed by Anton Khirnov
parent 149438cfe5
commit aaa44d0299
2 changed files with 37 additions and 28 deletions

View File

@ -7551,17 +7551,17 @@ static const float dca_dmixtable[241] = {
1.000000, 1.000000,
}; };
static const float dca_default_coeffs[10][5][2] = { static const float dca_default_coeffs[10][6][2] = {
{ { 0.707107, 0.707107 }, }, // A { { 0.707107, 0.707107 }, { 0.000000, 0.000000 }, }, // A [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, }, // A + B (dual mono) { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // A + B (dual mono) [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, }, // L + R (stereo) { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // L + R (stereo) [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, }, // (L+R) + (L-R) (sum-difference) { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // (L+R) + (L-R) (sum-difference) [LFE]
{ { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, }, // LT + RT (left and right total) { { 1.000000, 0.000000 }, { 0.000000, 1.000000 }, { 0.000000, 0.000000 }, }, // LT + RT (left and right total) [LFE]
{ { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, }, // C + L + R { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.000000, 0.000000 }, }, // C + L + R [LFE]
{ { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, }, // L + R + S { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + S [LFE]
{ { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, }, // C + L + R + S { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + S [LFE]
{ { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, }, // L + R + SL + SR { { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // L + R + SL + SR [LFE]
{ { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, }, // C + L + R + SL + SR { { 0.501187, 0.501187 }, { 0.707107, 0.000000 }, { 0.000000, 0.707107 }, { 0.501187, 0.000000 }, { 0.000000, 0.501187 }, { 0.000000, 0.000000 }, }, // C + L + R + SL + SR [LFE]
}; };
/* downmix coeffs /* downmix coeffs

View File

@ -336,7 +336,7 @@ typedef struct {
int scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2]; ///< scale factors (2 if transient) int scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2]; ///< scale factors (2 if transient)
int joint_huff[DCA_PRIM_CHANNELS_MAX]; ///< joint subband scale factors codebook int joint_huff[DCA_PRIM_CHANNELS_MAX]; ///< joint subband scale factors codebook
int joint_scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< joint subband scale factors int joint_scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< joint subband scale factors
float downmix_coef[DCA_PRIM_CHANNELS_MAX][2]; ///< stereo downmix coefficients float downmix_coef[DCA_PRIM_CHANNELS_MAX + 1][2]; ///< stereo downmix coefficients
int dynrange_coef; ///< dynamic range coefficient int dynrange_coef; ///< dynamic range coefficient
/* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1) /* Core substream's embedded downmix coefficients (cf. ETSI TS 102 114 V1.4.1)
@ -991,8 +991,8 @@ static void lfe_interpolation_fir(DCAContext *s, int decimation_select,
op2 \ op2 \
} }
static void dca_downmix(float **samples, int srcfmt, static void dca_downmix(float **samples, int srcfmt, int lfe_present,
float coef[DCA_PRIM_CHANNELS_MAX][2], float coef[DCA_PRIM_CHANNELS_MAX + 1][2],
const int8_t *channel_mapping) const int8_t *channel_mapping)
{ {
int c, l, r, sl, sr, s; int c, l, r, sl, sr, s;
@ -1042,6 +1042,14 @@ static void dca_downmix(float **samples, int srcfmt,
MIX_REAR2(samples, sl, sr, 3, coef)); MIX_REAR2(samples, sl, sr, 3, coef));
break; break;
} }
if (lfe_present) {
int lf_buf = dca_lfe_index[srcfmt];
int lf_idx = dca_channels [srcfmt];
for (i = 0; i < 256; i++) {
samples[0][i] += samples[lf_buf][i] * coef[lf_idx][0];
samples[1][i] += samples[lf_buf][i] * coef[lf_idx][1];
}
}
} }
@ -1249,12 +1257,6 @@ static int dca_filter_channels(DCAContext *s, int block_index)
M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */); M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */);
} }
/* Down mixing */
if (s->prim_channels > 2 &&
s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
dca_downmix(s->samples_chanptr, s->amode, s->downmix_coef, s->channel_order_tab);
}
/* Generate LFE samples for this subsubframe FIXME!!! */ /* Generate LFE samples for this subsubframe FIXME!!! */
if (s->output & DCA_LFE) { if (s->output & DCA_LFE) {
lfe_interpolation_fir(s, s->lfe, 2 * s->lfe, lfe_interpolation_fir(s, s->lfe, 2 * s->lfe,
@ -1264,6 +1266,13 @@ static int dca_filter_channels(DCAContext *s, int block_index)
/* Outputs 20bits pcm samples */ /* Outputs 20bits pcm samples */
} }
/* Downmixing to Stereo */
if (s->prim_channels + !!s->lfe > 2 &&
s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef,
s->channel_order_tab);
}
return 0; return 0;
} }
@ -1858,7 +1867,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
s->channel_order_tab[channels - 1 - !!s->lfe] < 0) s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
if (s->prim_channels > 2 && if (s->prim_channels + !!s->lfe > 2 &&
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
channels = 2; channels = 2;
s->output = DCA_STEREO; s->output = DCA_STEREO;
@ -1868,12 +1877,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
* *
* The decoder can only downmix to 2-channel, so we need to ensure * The decoder can only downmix to 2-channel, so we need to ensure
* embedded downmix coefficients are actually targeting 2-channel. * embedded downmix coefficients are actually targeting 2-channel.
* */
* Coefficients for the LFE channel are ignored (not supported) */
if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO || if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
s->core_downmix_amode == DCA_STEREO_TOTAL)) { s->core_downmix_amode == DCA_STEREO_TOTAL)) {
int sign, code; int sign, code;
for (i = 0; i < s->prim_channels; i++) { for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1; sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
code = s->core_downmix_codes[i][0] & 0x0FF; code = s->core_downmix_codes[i][0] & 0x0FF;
s->downmix_coef[i][0] = (!code ? 0.0f : s->downmix_coef[i][0] = (!code ? 0.0f :
@ -1890,18 +1898,19 @@ FF_ENABLE_DEPRECATION_WARNINGS
"Invalid channel mode %d\n", am); "Invalid channel mode %d\n", am);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
if (s->prim_channels > FF_ARRAY_ELEMS(dca_default_coeffs[0])) { if (s->prim_channels + !!s->lfe >
FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
avpriv_request_sample(s->avctx, "Downmixing %d channels", avpriv_request_sample(s->avctx, "Downmixing %d channels",
s->prim_channels); s->prim_channels + !!s->lfe);
return AVERROR_PATCHWELCOME; return AVERROR_PATCHWELCOME;
} }
for (i = 0; i < s->prim_channels; i++) { for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
s->downmix_coef[i][0] = dca_default_coeffs[am][i][0]; s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
s->downmix_coef[i][1] = dca_default_coeffs[am][i][1]; s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
} }
} }
av_dlog(s->avctx, "Stereo downmix coeffs:\n"); av_dlog(s->avctx, "Stereo downmix coeffs:\n");
for (i = 0; i < s->prim_channels; i++) { for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
av_dlog(s->avctx, "L, input channel %d = %f\n", i, av_dlog(s->avctx, "L, input channel %d = %f\n", i,
s->downmix_coef[i][0]); s->downmix_coef[i][0]);
av_dlog(s->avctx, "R, input channel %d = %f\n", i, av_dlog(s->avctx, "R, input channel %d = %f\n", i,