Mercurial > libavcodec.hg
comparison cook.c @ 4653:1d88da25349b libavcodec
Combine the window and overlap loops,
and get rid of the data swapping.
Patch by Ian Braithwaite <dk dot braithwaite at ian>
author | banan |
---|---|
date | Tue, 13 Mar 2007 19:44:02 +0000 |
parents | 31bf54d9353d |
children | d4de8d9a2788 |
comparison
equal
deleted
inserted
replaced
4652:6679d37a3338 | 4653:1d88da25349b |
---|---|
683 decode_vectors(q, category, quant_value_table, mlt_buffer); | 683 decode_vectors(q, category, quant_value_table, mlt_buffer); |
684 } | 684 } |
685 | 685 |
686 | 686 |
687 /** | 687 /** |
688 * The modulated lapped transform, this takes transform coefficients | |
689 * and transforms them into timedomain samples. This is done through | |
690 * an FFT-based algorithm with pre- and postrotation steps. | |
691 * A window and reorder step is also included. | |
692 * | |
693 * @param q pointer to the COOKContext | |
694 * @param inbuffer pointer to the mltcoefficients | |
695 * @param outbuffer pointer to the timedomain buffer | |
696 * @param mlt_tmp pointer to temporary storage space | |
697 */ | |
698 | |
699 static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer) | |
700 { | |
701 int i; | |
702 | |
703 q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, outbuffer, inbuffer, q->mdct_tmp); | |
704 | |
705 for(i = 0; i < q->samples_per_channel; i++){ | |
706 float tmp = outbuffer[i]; | |
707 | |
708 outbuffer[i] = q->mlt_window[i] * outbuffer[q->samples_per_channel + i]; | |
709 outbuffer[q->samples_per_channel + i] = q->mlt_window[q->samples_per_channel - 1 - i] * -tmp; | |
710 } | |
711 } | |
712 | |
713 | |
714 /** | |
715 * the actual requantization of the timedomain samples | 688 * the actual requantization of the timedomain samples |
716 * | 689 * |
717 * @param q pointer to the COOKContext | 690 * @param q pointer to the COOKContext |
718 * @param buffer pointer to the timedomain buffer | 691 * @param buffer pointer to the timedomain buffer |
719 * @param gain_index index for the block multiplier | 692 * @param gain_index index for the block multiplier |
741 } | 714 } |
742 } | 715 } |
743 | 716 |
744 | 717 |
745 /** | 718 /** |
746 * mlt overlapping and buffer management | 719 * The modulated lapped transform, this takes transform coefficients |
720 * and transforms them into timedomain samples. | |
721 * Apply transform window, overlap buffers, apply gain profile | |
722 * and buffer management. | |
747 * | 723 * |
748 * @param q pointer to the COOKContext | 724 * @param q pointer to the COOKContext |
725 * @param inbuffer pointer to the mltcoefficients | |
749 * @param gains_ptr current and previous gains | 726 * @param gains_ptr current and previous gains |
750 * @param previous_buffer pointer to the previous buffer to be used for overlapping | 727 * @param previous_buffer pointer to the previous buffer to be used for overlapping |
751 */ | 728 */ |
752 | 729 |
753 static void gain_compensate(COOKContext *q, cook_gains *gains_ptr, | 730 static void imlt_gain(COOKContext *q, float *inbuffer, |
754 float* previous_buffer) | 731 cook_gains *gains_ptr, float* previous_buffer) |
755 { | 732 { |
756 const float fc = q->pow2tab[gains_ptr->previous[0] + 63]; | 733 const float fc = q->pow2tab[gains_ptr->previous[0] + 63]; |
757 float *buffer = q->mono_mdct_output; | 734 float *buffer0 = q->mono_mdct_output; |
735 float *buffer1 = q->mono_mdct_output + q->samples_per_channel; | |
758 int i; | 736 int i; |
759 | 737 |
760 /* Overlap with the previous block. */ | 738 /* Inverse modified discrete cosine transform */ |
761 for(i=0 ; i<q->samples_per_channel ; i++) { | 739 q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, q->mono_mdct_output, |
762 buffer[i] *= fc; | 740 inbuffer, q->mdct_tmp); |
763 buffer[i] += previous_buffer[i]; | 741 |
742 /* The weird thing here, is that the two halves of the time domain | |
743 * buffer are swapped. Also, the newest data, that we save away for | |
744 * next frame, has the wrong sign. Hence the subtraction below. | |
745 * Almost sounds like a complex conjugate/reverse data/FFT effect. | |
746 */ | |
747 | |
748 /* Apply window and overlap */ | |
749 for(i = 0; i < q->samples_per_channel; i++){ | |
750 buffer1[i] = buffer1[i] * fc * q->mlt_window[i] - | |
751 previous_buffer[i] * q->mlt_window[q->samples_per_channel - 1 - i]; | |
764 } | 752 } |
765 | 753 |
766 /* Apply gain profile */ | 754 /* Apply gain profile */ |
767 for (i = 0; i < 8; i++) { | 755 for (i = 0; i < 8; i++) { |
768 if (gains_ptr->now[i] || gains_ptr->now[i + 1]) | 756 if (gains_ptr->now[i] || gains_ptr->now[i + 1]) |
769 interpolate(q, &buffer[q->gain_size_factor * i], | 757 interpolate(q, &buffer1[q->gain_size_factor * i], |
770 gains_ptr->now[i], gains_ptr->now[i + 1]); | 758 gains_ptr->now[i], gains_ptr->now[i + 1]); |
771 } | 759 } |
772 | 760 |
773 /* Save away the current to be previous block. */ | 761 /* Save away the current to be previous block. */ |
774 memcpy(previous_buffer, buffer+q->samples_per_channel, | 762 memcpy(previous_buffer, buffer0, sizeof(float)*q->samples_per_channel); |
775 sizeof(float)*q->samples_per_channel); | |
776 } | 763 } |
777 | 764 |
778 | 765 |
779 /** | 766 /** |
780 * function for getting the jointstereo coupling information | 767 * function for getting the jointstereo coupling information |
900 static inline void | 887 static inline void |
901 mlt_compensate_output(COOKContext *q, float *decode_buffer, | 888 mlt_compensate_output(COOKContext *q, float *decode_buffer, |
902 cook_gains *gains, float *previous_buffer, | 889 cook_gains *gains, float *previous_buffer, |
903 int16_t *out, int chan) | 890 int16_t *out, int chan) |
904 { | 891 { |
892 float *output = q->mono_mdct_output + q->samples_per_channel; | |
905 int j; | 893 int j; |
906 | 894 |
907 cook_imlt(q, decode_buffer, q->mono_mdct_output); | 895 imlt_gain(q, decode_buffer, gains, previous_buffer); |
908 gain_compensate(q, gains, previous_buffer); | |
909 | 896 |
910 /* Clip and convert floats to 16 bits. | 897 /* Clip and convert floats to 16 bits. |
911 */ | 898 */ |
912 for (j = 0; j < q->samples_per_channel; j++) { | 899 for (j = 0; j < q->samples_per_channel; j++) { |
913 out[chan + q->nb_channels * j] = | 900 out[chan + q->nb_channels * j] = |
914 av_clip(lrintf(q->mono_mdct_output[j]), -32768, 32767); | 901 av_clip(lrintf(output[j]), -32768, 32767); |
915 } | 902 } |
916 } | 903 } |
917 | 904 |
918 | 905 |
919 /** | 906 /** |