mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-06-27 02:52:25 +08:00
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
This commit is contained in:
@ -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)
|
|||||||
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)
|
|||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
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 {
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user