diff options
author | Loren Merritt <lorenm@u.washington.edu> | 2008-08-12 23:45:46 +0000 |
---|---|---|
committer | Loren Merritt <lorenm@u.washington.edu> | 2008-08-12 23:45:46 +0000 |
commit | 557ac0c4481b619ad5fdb92ec994ab982ad8a7dd (patch) | |
tree | fa31078bcd5afbc2f2b7ec71d044d514599a5436 /libavcodec | |
parent | 0e55ba723b94f2cd21e0af56543d1ec8566052a4 (diff) | |
download | ffmpeg-557ac0c4481b619ad5fdb92ec994ab982ad8a7dd.tar.gz |
optimize ac3_downmix.
1.3x faster 5.1->stereo, 1.9x faster 5.1->mono.
Originally committed as revision 14719 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/ac3dec.c | 59 | ||||
-rw-r--r-- | libavcodec/ac3dec.h | 1 |
2 files changed, 36 insertions, 24 deletions
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index e5476b16d8..14b8dd90ae 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -321,6 +321,7 @@ static void set_downmix_coeffs(AC3DecodeContext *s) int i; float cmix = gain_levels[center_levels[s->center_mix_level]]; float smix = gain_levels[surround_levels[s->surround_mix_level]]; + float norm0, norm1; for(i=0; i<s->fbw_channels; i++) { 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) s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix; } - /* calculate adjustment needed for each channel to avoid clipping */ - s->downmix_coeff_adjust[0] = s->downmix_coeff_adjust[1] = 0.0f; + /* renormalize */ + norm0 = norm1 = 0.0; for(i=0; i<s->fbw_channels; i++) { - s->downmix_coeff_adjust[0] += s->downmix_coeffs[i][0]; - s->downmix_coeff_adjust[1] += s->downmix_coeffs[i][1]; + norm0 += s->downmix_coeffs[i][0]; + 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) /** * Downmix the output to mono or stereo. */ -static void ac3_downmix(AC3DecodeContext *s, - float samples[AC3_MAX_CHANNELS][256], int ch_offset) +static av_noinline void ac3_downmix(AC3DecodeContext *s, + float samples[AC3_MAX_CHANNELS][256]) { int i, j; float v0, v1; - for(i=0; i<256; i++) { - v0 = v1 = 0.0f; - for(j=0; j<s->fbw_channels; j++) { - v0 += samples[j+ch_offset][i] * s->downmix_coeffs[j][0]; - v1 += samples[j+ch_offset][i] * s->downmix_coeffs[j][1]; + if(s->output_mode == AC3_CHMODE_STEREO) { + for(i=0; i<256; i++) { + v0 = v1 = 0.0f; + for(j=0; j<s->fbw_channels; j++) { + 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]; - v1 *= s->downmix_coeff_adjust[1]; - if(s->output_mode == AC3_CHMODE_MONO) { - samples[ch_offset][i] = (v0 + v1) * LEVEL_MINUS_3DB; - } else if(s->output_mode == AC3_CHMODE_STEREO) { - samples[ ch_offset][i] = v0; - samples[1+ch_offset][i] = v1; + } else if(s->output_mode == AC3_CHMODE_MONO) { + for(i=0; i<256; i++) { + v0 = 0.0f; + for(j=0; j<s->fbw_channels; j++) + v0 += samples[j][i] * s->downmix_coeffs[j][0]; + samples[0][i] = v0; } } } @@ -1002,17 +1015,17 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) do_imdct(s, s->channels); if(downmix_output) { - ac3_downmix(s, s->output, 0); + ac3_downmix(s, s->output); } } else { if(downmix_output) { - ac3_downmix(s, s->transform_coeffs, 1); + ac3_downmix(s, s->transform_coeffs+1); } if(!s->downmixed) { s->downmixed = 1; // 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); diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 46e74d9828..8b6c057cfc 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -99,7 +99,6 @@ typedef struct { int channels; ///< number of total channels int lfe_ch; ///< index of LFE channel 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 output_mode; ///< output channel configuration int out_channels; ///< number of output channels |