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 /**