Mercurial > libavcodec.hg
comparison ac3dec.c @ 7554:96d57e3b78e5 libavcodec
optimize ac3_downmix.
1.3x faster 5.1->stereo, 1.9x faster 5.1->mono.
author | lorenm |
---|---|
date | Tue, 12 Aug 2008 23:45:46 +0000 |
parents | f9e4afa46993 |
children | be6d31643128 |
comparison
equal
deleted
inserted
replaced
7553:b5f8d814a206 | 7554:96d57e3b78e5 |
---|---|
319 static void set_downmix_coeffs(AC3DecodeContext *s) | 319 static void set_downmix_coeffs(AC3DecodeContext *s) |
320 { | 320 { |
321 int i; | 321 int i; |
322 float cmix = gain_levels[center_levels[s->center_mix_level]]; | 322 float cmix = gain_levels[center_levels[s->center_mix_level]]; |
323 float smix = gain_levels[surround_levels[s->surround_mix_level]]; | 323 float smix = gain_levels[surround_levels[s->surround_mix_level]]; |
324 float norm0, norm1; | |
324 | 325 |
325 for(i=0; i<s->fbw_channels; i++) { | 326 for(i=0; i<s->fbw_channels; i++) { |
326 s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; | 327 s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; |
327 s->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; | 328 s->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; |
328 } | 329 } |
336 if(s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) { | 337 if(s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) { |
337 int nf = s->channel_mode - 4; | 338 int nf = s->channel_mode - 4; |
338 s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix; | 339 s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix; |
339 } | 340 } |
340 | 341 |
341 /* calculate adjustment needed for each channel to avoid clipping */ | 342 /* renormalize */ |
342 s->downmix_coeff_adjust[0] = s->downmix_coeff_adjust[1] = 0.0f; | 343 norm0 = norm1 = 0.0; |
343 for(i=0; i<s->fbw_channels; i++) { | 344 for(i=0; i<s->fbw_channels; i++) { |
344 s->downmix_coeff_adjust[0] += s->downmix_coeffs[i][0]; | 345 norm0 += s->downmix_coeffs[i][0]; |
345 s->downmix_coeff_adjust[1] += s->downmix_coeffs[i][1]; | 346 norm1 += s->downmix_coeffs[i][1]; |
346 } | 347 } |
347 s->downmix_coeff_adjust[0] = 1.0f / s->downmix_coeff_adjust[0]; | 348 norm0 = 1.0f / norm0; |
348 s->downmix_coeff_adjust[1] = 1.0f / s->downmix_coeff_adjust[1]; | 349 norm1 = 1.0f / norm1; |
350 for(i=0; i<s->fbw_channels; i++) { | |
351 s->downmix_coeffs[i][0] *= norm0; | |
352 s->downmix_coeffs[i][1] *= norm1; | |
353 } | |
354 | |
355 if(s->output_mode == AC3_CHMODE_MONO) { | |
356 for(i=0; i<s->fbw_channels; i++) | |
357 s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] + s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB; | |
358 } | |
349 } | 359 } |
350 | 360 |
351 /** | 361 /** |
352 * Decode the grouped exponents according to exponent strategy. | 362 * Decode the grouped exponents according to exponent strategy. |
353 * reference: Section 7.1.3 Exponent Decoding | 363 * reference: Section 7.1.3 Exponent Decoding |
617 } | 627 } |
618 | 628 |
619 /** | 629 /** |
620 * Downmix the output to mono or stereo. | 630 * Downmix the output to mono or stereo. |
621 */ | 631 */ |
622 static void ac3_downmix(AC3DecodeContext *s, | 632 static av_noinline void ac3_downmix(AC3DecodeContext *s, |
623 float samples[AC3_MAX_CHANNELS][256], int ch_offset) | 633 float samples[AC3_MAX_CHANNELS][256]) |
624 { | 634 { |
625 int i, j; | 635 int i, j; |
626 float v0, v1; | 636 float v0, v1; |
627 | 637 |
628 for(i=0; i<256; i++) { | 638 if(s->output_mode == AC3_CHMODE_STEREO) { |
629 v0 = v1 = 0.0f; | 639 for(i=0; i<256; i++) { |
630 for(j=0; j<s->fbw_channels; j++) { | 640 v0 = v1 = 0.0f; |
631 v0 += samples[j+ch_offset][i] * s->downmix_coeffs[j][0]; | 641 for(j=0; j<s->fbw_channels; j++) { |
632 v1 += samples[j+ch_offset][i] * s->downmix_coeffs[j][1]; | 642 v0 += samples[j][i] * s->downmix_coeffs[j][0]; |
633 } | 643 v1 += samples[j][i] * s->downmix_coeffs[j][1]; |
634 v0 *= s->downmix_coeff_adjust[0]; | 644 } |
635 v1 *= s->downmix_coeff_adjust[1]; | 645 samples[0][i] = v0; |
636 if(s->output_mode == AC3_CHMODE_MONO) { | 646 samples[1][i] = v1; |
637 samples[ch_offset][i] = (v0 + v1) * LEVEL_MINUS_3DB; | 647 } |
638 } else if(s->output_mode == AC3_CHMODE_STEREO) { | 648 } else if(s->output_mode == AC3_CHMODE_MONO) { |
639 samples[ ch_offset][i] = v0; | 649 for(i=0; i<256; i++) { |
640 samples[1+ch_offset][i] = v1; | 650 v0 = 0.0f; |
651 for(j=0; j<s->fbw_channels; j++) | |
652 v0 += samples[j][i] * s->downmix_coeffs[j][0]; | |
653 samples[0][i] = v0; | |
641 } | 654 } |
642 } | 655 } |
643 } | 656 } |
644 | 657 |
645 /** | 658 /** |
1000 } | 1013 } |
1001 | 1014 |
1002 do_imdct(s, s->channels); | 1015 do_imdct(s, s->channels); |
1003 | 1016 |
1004 if(downmix_output) { | 1017 if(downmix_output) { |
1005 ac3_downmix(s, s->output, 0); | 1018 ac3_downmix(s, s->output); |
1006 } | 1019 } |
1007 } else { | 1020 } else { |
1008 if(downmix_output) { | 1021 if(downmix_output) { |
1009 ac3_downmix(s, s->transform_coeffs, 1); | 1022 ac3_downmix(s, s->transform_coeffs+1); |
1010 } | 1023 } |
1011 | 1024 |
1012 if(!s->downmixed) { | 1025 if(!s->downmixed) { |
1013 s->downmixed = 1; | 1026 s->downmixed = 1; |
1014 // FIXME delay[] is half the size of the other downmixes | 1027 // FIXME delay[] is half the size of the other downmixes |
1015 ac3_downmix(s, s->delay, 0); | 1028 ac3_downmix(s, s->delay); |
1016 } | 1029 } |
1017 | 1030 |
1018 do_imdct(s, s->out_channels); | 1031 do_imdct(s, s->out_channels); |
1019 } | 1032 } |
1020 | 1033 |