Commit e60d2ecb authored by lorenm's avatar lorenm

optimize ac3_downmix.

1.3x faster 5.1->stereo, 1.9x faster 5.1->mono.


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@14719 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent e2e59c70
...@@ -321,6 +321,7 @@ static void set_downmix_coeffs(AC3DecodeContext *s) ...@@ -321,6 +321,7 @@ static void set_downmix_coeffs(AC3DecodeContext *s)
int i; int i;
float cmix = gain_levels[center_levels[s->center_mix_level]]; float cmix = gain_levels[center_levels[s->center_mix_level]];
float smix = gain_levels[surround_levels[s->surround_mix_level]]; float smix = gain_levels[surround_levels[s->surround_mix_level]];
float norm0, norm1;
for(i=0; i<s->fbw_channels; i++) { for(i=0; i<s->fbw_channels; i++) {
s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]];
...@@ -338,14 +339,23 @@ static void set_downmix_coeffs(AC3DecodeContext *s) ...@@ -338,14 +339,23 @@ static void set_downmix_coeffs(AC3DecodeContext *s)
s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix; s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix;
} }
/* calculate adjustment needed for each channel to avoid clipping */ /* renormalize */
s->downmix_coeff_adjust[0] = s->downmix_coeff_adjust[1] = 0.0f; norm0 = norm1 = 0.0;
for(i=0; i<s->fbw_channels; i++) { for(i=0; i<s->fbw_channels; i++) {
s->downmix_coeff_adjust[0] += s->downmix_coeffs[i][0]; norm0 += s->downmix_coeffs[i][0];
s->downmix_coeff_adjust[1] += s->downmix_coeffs[i][1]; norm1 += s->downmix_coeffs[i][1];
}
norm0 = 1.0f / norm0;
norm1 = 1.0f / norm1;
for(i=0; i<s->fbw_channels; i++) {
s->downmix_coeffs[i][0] *= norm0;
s->downmix_coeffs[i][1] *= norm1;
}
if(s->output_mode == AC3_CHMODE_MONO) {
for(i=0; i<s->fbw_channels; i++)
s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] + s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB;
} }
s->downmix_coeff_adjust[0] = 1.0f / s->downmix_coeff_adjust[0];
s->downmix_coeff_adjust[1] = 1.0f / s->downmix_coeff_adjust[1];
} }
/** /**
...@@ -619,25 +629,28 @@ static inline void do_imdct(AC3DecodeContext *s, int channels) ...@@ -619,25 +629,28 @@ static inline void do_imdct(AC3DecodeContext *s, int channels)
/** /**
* Downmix the output to mono or stereo. * Downmix the output to mono or stereo.
*/ */
static void ac3_downmix(AC3DecodeContext *s, static av_noinline void ac3_downmix(AC3DecodeContext *s,
float samples[AC3_MAX_CHANNELS][256], int ch_offset) float samples[AC3_MAX_CHANNELS][256])
{ {
int i, j; int i, j;
float v0, v1; float v0, v1;
for(i=0; i<256; i++) { if(s->output_mode == AC3_CHMODE_STEREO) {
v0 = v1 = 0.0f; for(i=0; i<256; i++) {
for(j=0; j<s->fbw_channels; j++) { v0 = v1 = 0.0f;
v0 += samples[j+ch_offset][i] * s->downmix_coeffs[j][0]; for(j=0; j<s->fbw_channels; j++) {
v1 += samples[j+ch_offset][i] * s->downmix_coeffs[j][1]; v0 += samples[j][i] * s->downmix_coeffs[j][0];
v1 += samples[j][i] * s->downmix_coeffs[j][1];
}
samples[0][i] = v0;
samples[1][i] = v1;
} }
v0 *= s->downmix_coeff_adjust[0]; } else if(s->output_mode == AC3_CHMODE_MONO) {
v1 *= s->downmix_coeff_adjust[1]; for(i=0; i<256; i++) {
if(s->output_mode == AC3_CHMODE_MONO) { v0 = 0.0f;
samples[ch_offset][i] = (v0 + v1) * LEVEL_MINUS_3DB; for(j=0; j<s->fbw_channels; j++)
} else if(s->output_mode == AC3_CHMODE_STEREO) { v0 += samples[j][i] * s->downmix_coeffs[j][0];
samples[ ch_offset][i] = v0; samples[0][i] = v0;
samples[1+ch_offset][i] = v1;
} }
} }
} }
...@@ -1002,17 +1015,17 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) ...@@ -1002,17 +1015,17 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
do_imdct(s, s->channels); do_imdct(s, s->channels);
if(downmix_output) { if(downmix_output) {
ac3_downmix(s, s->output, 0); ac3_downmix(s, s->output);
} }
} else { } else {
if(downmix_output) { if(downmix_output) {
ac3_downmix(s, s->transform_coeffs, 1); ac3_downmix(s, s->transform_coeffs+1);
} }
if(!s->downmixed) { if(!s->downmixed) {
s->downmixed = 1; s->downmixed = 1;
// FIXME delay[] is half the size of the other downmixes // FIXME delay[] is half the size of the other downmixes
ac3_downmix(s, s->delay, 0); ac3_downmix(s, s->delay);
} }
do_imdct(s, s->out_channels); do_imdct(s, s->out_channels);
......
...@@ -99,7 +99,6 @@ typedef struct { ...@@ -99,7 +99,6 @@ typedef struct {
int channels; ///< number of total channels int channels; ///< number of total channels
int lfe_ch; ///< index of LFE channel int lfe_ch; ///< index of LFE channel
float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients
float downmix_coeff_adjust[2]; ///< adjustment needed for each output channel when downmixing
int downmixed; ///< indicates if coeffs are currently downmixed int downmixed; ///< indicates if coeffs are currently downmixed
int output_mode; ///< output channel configuration int output_mode; ///< output channel configuration
int out_channels; ///< number of output channels int out_channels; ///< number of output channels
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment