From d0429b4ff502c283e96b71498641b50e5c25f6da Mon Sep 17 00:00:00 2001 From: Ian Braithwaite Date: Thu, 8 Mar 2007 20:43:51 +0000 Subject: [PATCH] Simplify gain block handling. Patch by Ian Braithwaite Originally committed as revision 8298 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/cook.c | 152 ++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 100 deletions(-) diff --git a/libavcodec/cook.c b/libavcodec/cook.c index 07655b01ce..0bc97193b8 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -65,10 +65,9 @@ //#define COOKDEBUG typedef struct { - int size; - int loccode[8]; - int levcode[8]; -} COOKgain; + int *now; + int *previous; +} cook_gains; typedef struct { GetBitContext gb; @@ -102,12 +101,12 @@ typedef struct { int mlt_size; //modulated lapped transform size /* gain buffers */ - COOKgain *gain_ptr1[2]; - COOKgain *gain_ptr2[2]; - COOKgain gain_1; - COOKgain gain_2; - COOKgain gain_3; - COOKgain gain_4; + cook_gains gains1; + cook_gains gains2; + int gain_1[9]; + int gain_2[9]; + int gain_3[9]; + int gain_4[9]; /* VLC data */ int js_vlc_bits; @@ -339,29 +338,27 @@ static int cook_decode_close(AVCodecContext *avctx) } /** - * Fill the COOKgain structure for the timedomain quantization. + * Fill the gain array for the timedomain quantization. * * @param q pointer to the COOKContext - * @param gaininfo pointer to the COOKgain + * @param gaininfo[9] array of gain indices */ -static void decode_gain_info(GetBitContext *gb, COOKgain* gaininfo) { - int i; +static void decode_gain_info(GetBitContext *gb, int *gaininfo) +{ + int i, n; while (get_bits1(gb)) {} + n = get_bits_count(gb) - 1; //amount of elements*2 to update - gaininfo->size = get_bits_count(gb) - 1; //amount of elements*2 to update + i = 0; + while (n--) { + int index = get_bits(gb, 3); + int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1; - if (get_bits_count(gb) - 1 <= 0) return; - - for (i=0 ; isize ; i++){ - gaininfo->loccode[i] = get_bits(gb,3); - if (get_bits1(gb)) { - gaininfo->levcode[i] = get_bits(gb,4) - 7; //convert to signed - } else { - gaininfo->levcode[i] = -1; - } + while (i <= index) gaininfo[i++] = gain; } + while (i <= 8) gaininfo[i++] = 0; } /** @@ -784,77 +781,34 @@ static void interpolate(COOKContext *q, float* buffer, } } -/** - * timedomain requantization of the timedomain samples - * - * @param q pointer to the COOKContext - * @param buffer pointer to the timedomain buffer - * @param gain_now current gain structure - * @param gain_previous previous gain structure - */ - -static void gain_window(COOKContext *q, float* buffer, COOKgain* gain_now, - COOKgain* gain_previous){ - int i, index; - int gain_index[9]; - int tmp_gain_index; - - gain_index[8]=0; - index = gain_previous->size; - for (i=7 ; i>=0 ; i--) { - if(index && gain_previous->loccode[index-1]==i) { - gain_index[i] = gain_previous->levcode[index-1]; - index--; - } else { - gain_index[i]=gain_index[i+1]; - } - } - /* This is applied to the to be previous data buffer. */ - for(i=0;i<8;i++){ - interpolate(q, &buffer[q->samples_per_channel+q->gain_size_factor*i], - gain_index[i], gain_index[i+1]); - } - - tmp_gain_index = gain_index[0]; - index = gain_now->size; - for (i=7 ; i>=0 ; i--) { - if(index && gain_now->loccode[index-1]==i) { - gain_index[i]= gain_now->levcode[index-1]; - index--; - } else { - gain_index[i]=gain_index[i+1]; - } - } - - /* This is applied to the to be current block. */ - for(i=0;i<8;i++){ - interpolate(q, &buffer[i*q->gain_size_factor], - tmp_gain_index+gain_index[i], - tmp_gain_index+gain_index[i+1]); - } -} - /** * mlt overlapping and buffer management * * @param q pointer to the COOKContext - * @param buffer pointer to the timedomain buffer - * @param gain_now current gain structure - * @param gain_previous previous gain structure + * @param gains_ptr current and previous gains * @param previous_buffer pointer to the previous buffer to be used for overlapping - * */ -static void gain_compensate(COOKContext *q, float* buffer, COOKgain* gain_now, - COOKgain* gain_previous, float* previous_buffer) { +static void gain_compensate(COOKContext *q, cook_gains *gains_ptr, + float* previous_buffer) +{ + const float fc = q->pow2tab[gains_ptr->previous[0] + 63]; + float *buffer = q->mono_mdct_output; int i; - if((gain_now->size || gain_previous->size)) { - gain_window(q, buffer, gain_now, gain_previous); - } /* Overlap with the previous block. */ - for(i=0 ; isamples_per_channel ; i++) buffer[i]+=previous_buffer[i]; + for(i=0 ; isamples_per_channel ; i++) { + buffer[i] *= fc; + buffer[i] += previous_buffer[i]; + } + + /* Apply gain profile */ + for (i = 0; i < 8; i++) { + if (gains_ptr->now[i] || gains_ptr->now[i + 1]) + interpolate(q, &buffer[q->gain_size_factor * i], + gains_ptr->now[i], gains_ptr->now[i + 1]); + } /* Save away the current to be previous block. */ memcpy(previous_buffer, buffer+q->samples_per_channel, @@ -956,7 +910,7 @@ static void joint_decode(COOKContext *q, float* mlt_buffer1, static inline void decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer, - COOKgain *gain_ptr[]) + cook_gains *gains_ptr) { int offset; @@ -964,10 +918,10 @@ decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer, q->bits_per_subpacket/8); init_get_bits(&q->gb, q->decoded_bytes_buffer + offset, q->bits_per_subpacket); - decode_gain_info(&q->gb, gain_ptr[0]); + decode_gain_info(&q->gb, gains_ptr->now); /* Swap current and previous gains */ - FFSWAP(COOKgain *, gain_ptr[0], gain_ptr[1]); + FFSWAP(int *, gains_ptr->now, gains_ptr->previous); } /** @@ -985,14 +939,13 @@ decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer, static inline void mlt_compensate_output(COOKContext *q, float *decode_buffer, - COOKgain *gain_ptr[], float *previous_buffer, + cook_gains *gains, float *previous_buffer, int16_t *out, int chan) { int j; cook_imlt(q, decode_buffer, q->mono_mdct_output, q->mlt_tmp); - gain_compensate(q, q->mono_mdct_output, gain_ptr[0], - gain_ptr[1], previous_buffer); + gain_compensate(q, gains, previous_buffer); /* Clip and convert floats to 16 bits. */ @@ -1022,7 +975,7 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, // } // av_log(NULL, AV_LOG_ERROR, "\n"); - decode_bytes_and_gain(q, inbuffer, q->gain_ptr1); + decode_bytes_and_gain(q, inbuffer, &q->gains1); if (q->joint_stereo) { joint_decode(q, q->decode_buffer_1, q->decode_buffer_2); @@ -1030,21 +983,20 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, mono_decode(q, q->decode_buffer_1); if (q->nb_channels == 2) { - decode_bytes_and_gain(q, inbuffer + sub_packet_size/2, - q->gain_ptr2); + decode_bytes_and_gain(q, inbuffer + sub_packet_size/2, &q->gains2); mono_decode(q, q->decode_buffer_2); } } - mlt_compensate_output(q, q->decode_buffer_1, q->gain_ptr1, + mlt_compensate_output(q, q->decode_buffer_1, &q->gains1, q->mono_previous_buffer1, outbuffer, 0); if (q->nb_channels == 2) { if (q->joint_stereo) { - mlt_compensate_output(q, q->decode_buffer_2, q->gain_ptr1, + mlt_compensate_output(q, q->decode_buffer_2, &q->gains1, q->mono_previous_buffer2, outbuffer, 1); } else { - mlt_compensate_output(q, q->decode_buffer_2, q->gain_ptr2, + mlt_compensate_output(q, q->decode_buffer_2, &q->gains2, q->mono_previous_buffer2, outbuffer, 1); } } @@ -1225,10 +1177,10 @@ static int cook_decode_init(AVCodecContext *avctx) if (q->decoded_bytes_buffer == NULL) return -1; - q->gain_ptr1[0] = &q->gain_1; - q->gain_ptr1[1] = &q->gain_2; - q->gain_ptr2[0] = &q->gain_3; - q->gain_ptr2[1] = &q->gain_4; + q->gains1.now = q->gain_1; + q->gains1.previous = q->gain_2; + q->gains2.now = q->gain_3; + q->gains2.previous = q->gain_4; /* Initialize transform. */ if ( init_cook_mlt(q) == 0 )