📄 cook.c
字号:
if(bits_left > q->samples_per_channel) { bits_left = q->samples_per_channel + ((bits_left - q->samples_per_channel)*5)/8; //av_log(NULL, AV_LOG_ERROR, "bits_left = %d\n",bits_left); } memset(&exp_index1,0,102*sizeof(int)); memset(&exp_index2,0,102*sizeof(int)); memset(&tmp_categorize_array1,0,128*sizeof(int)); memset(&tmp_categorize_array2,0,128*sizeof(int)); bias=-32; /* Estimate bias. */ for (i=32 ; i>0 ; i=i/2){ num_bits = 0; index = 0; for (j=q->total_subbands ; j>0 ; j--){ exp_idx = (i - quant_index_table[index] + bias) / 2; if (exp_idx<0){ exp_idx=0; } else if(exp_idx >7) { exp_idx=7; } index++; num_bits+=expbits_tab[exp_idx]; } if(num_bits >= bits_left - 32){ bias+=i; } } /* Calculate total number of bits. */ num_bits=0; for (i=0 ; i<q->total_subbands ; i++) { exp_idx = (bias - quant_index_table[i]) / 2; if (exp_idx<0) { exp_idx=0; } else if(exp_idx >7) { exp_idx=7; } num_bits += expbits_tab[exp_idx]; exp_index1[i] = exp_idx; exp_index2[i] = exp_idx; } tmpbias = bias = num_bits; for (j = 1 ; j < q->numvector_size ; j++) { if (tmpbias + bias > 2*bits_left) { /* ---> */ int max = -999999; index=-1; for (i=0 ; i<q->total_subbands ; i++){ if (exp_index1[i] < 7) { v = (-2*exp_index1[i]) - quant_index_table[i] - 32; if ( v >= max) { max = v; index = i; } } } if(index==-1)break; tmp_categorize_array1[tmp_categorize_array1_idx++] = index; tmpbias -= expbits_tab[exp_index1[index]] - expbits_tab[exp_index1[index]+1]; ++exp_index1[index]; } else { /* <--- */ int min = 999999; index=-1; for (i=0 ; i<q->total_subbands ; i++){ if(exp_index2[i] > 0){ v = (-2*exp_index2[i])-quant_index_table[i]; if ( v < min) { min = v; index = i; } } } if(index == -1)break; tmp_categorize_array2[tmp_categorize_array2_idx++] = index; tmpbias -= expbits_tab[exp_index2[index]] - expbits_tab[exp_index2[index]-1]; --exp_index2[index]; } } for(i=0 ; i<q->total_subbands ; i++) category[i] = exp_index2[i]; /* Concatenate the two arrays. */ for(i=tmp_categorize_array2_idx-1 ; i >= 0; i--) category_index[category_index_size++] = tmp_categorize_array2[i]; for(i=0;i<tmp_categorize_array1_idx;i++) category_index[category_index_size++ ] = tmp_categorize_array1[i]; /* FIXME: mc_sich_ra8_20.rm triggers this, not sure with what we should fill the remaining bytes. */ for(i=category_index_size;i<q->numvector_size;i++) category_index[i]=0;}/** * Expand the category vector. * * @param q pointer to the COOKContext * @param category pointer to the category array * @param category_index pointer to the category_index array */static void inline expand_category(COOKContext *q, int* category, int* category_index){ int i; for(i=0 ; i<q->num_vectors ; i++){ ++category[category_index[i]]; }}/** * The real requantization of the mltcoefs * * @param q pointer to the COOKContext * @param index index * @param band current subband * @param quant_value_table pointer to the array * @param subband_coef_index array of indexes to quant_centroid_tab * @param subband_coef_noise use random noise instead of predetermined value * @param mlt_buffer pointer to the mlt buffer */static void scalar_dequant(COOKContext *q, int index, int band, float* quant_value_table, int* subband_coef_index, int* subband_coef_noise, float* mlt_buffer){ int i; float f1; for(i=0 ; i<SUBBAND_SIZE ; i++) { if (subband_coef_index[i]) { if (subband_coef_noise[i]) { f1 = -quant_centroid_tab[index][subband_coef_index[i]]; } else { f1 = quant_centroid_tab[index][subband_coef_index[i]]; } } else { /* noise coding if subband_coef_noise[i] == 0 */ q->random_state = q->random_state * 214013 + 2531011; //typical RNG numbers f1 = randsign[(q->random_state/0x1000000)&1] * dither_tab[index]; //>>31 } mlt_buffer[band*20+ i] = f1 * quant_value_table[band]; }}/** * Unpack the subband_coef_index and subband_coef_noise vectors. * * @param q pointer to the COOKContext * @param category pointer to the category array * @param subband_coef_index array of indexes to quant_centroid_tab * @param subband_coef_noise use random noise instead of predetermined value */static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index, int* subband_coef_noise) { int i,j; int vlc, vd ,tmp, result; int ub; int cb; vd = vd_tab[category]; result = 0; for(i=0 ; i<vpr_tab[category] ; i++){ ub = get_bits_count(&q->gb); vlc = get_vlc2(&q->gb, q->sqvh[category].table, q->sqvh[category].bits, 3); cb = get_bits_count(&q->gb); if (q->bits_per_subpacket < get_bits_count(&q->gb)){ vlc = 0; result = 1; } for(j=vd-1 ; j>=0 ; j--){ tmp = (vlc * invradix_tab[category])/0x100000; subband_coef_index[vd*i+j] = vlc - tmp * (kmax_tab[category]+1); vlc = tmp; } for(j=0 ; j<vd ; j++){ if (subband_coef_index[i*vd + j]) { if(get_bits_count(&q->gb) < q->bits_per_subpacket){ subband_coef_noise[i*vd+j] = get_bits1(&q->gb); } else { result=1; subband_coef_noise[i*vd+j]=0; } } else { subband_coef_noise[i*vd+j]=0; } } } return result;}/** * Fill the mlt_buffer with mlt coefficients. * * @param q pointer to the COOKContext * @param category pointer to the category array * @param quant_value_table pointer to the array * @param mlt_buffer pointer to mlt coefficients */static void decode_vectors(COOKContext* q, int* category, float* quant_value_table, float* mlt_buffer){ /* A zero in this table means that the subband coefficient is random noise coded. */ int subband_coef_noise[SUBBAND_SIZE]; /* A zero in this table means that the subband coefficient is a positive multiplicator. */ int subband_coef_index[SUBBAND_SIZE]; int band, j; int index=0; for(band=0 ; band<q->total_subbands ; band++){ index = category[band]; if(category[band] < 7){ if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_noise)){ index=7; for(j=0 ; j<q->total_subbands ; j++) category[band+j]=7; } } if(index==7) { memset(subband_coef_index, 0, sizeof(subband_coef_index)); memset(subband_coef_noise, 0, sizeof(subband_coef_noise)); } scalar_dequant(q, index, band, quant_value_table, subband_coef_index, subband_coef_noise, mlt_buffer); } if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){ return; }}/** * function for decoding mono data * * @param q pointer to the COOKContext * @param mlt_buffer1 pointer to left channel mlt coefficients * @param mlt_buffer2 pointer to right channel mlt coefficients */static void mono_decode(COOKContext *q, float* mlt_buffer) { int category_index[128]; float quant_value_table[102]; int quant_index_table[102]; int category[128]; memset(&category, 0, 128*sizeof(int)); memset(&quant_value_table, 0, 102*sizeof(int)); memset(&category_index, 0, 128*sizeof(int)); decode_envelope(q, quant_index_table); q->num_vectors = get_bits(&q->gb,q->log2_numvector_size); dequant_envelope(q, quant_index_table, quant_value_table); categorize(q, quant_index_table, category, category_index); expand_category(q, category, category_index); decode_vectors(q, category, quant_value_table, mlt_buffer);}/** * The modulated lapped transform, this takes transform coefficients * and transforms them into timedomain samples. This is done through * an FFT-based algorithm with pre- and postrotation steps. * A window and reorder step is also included. * * @param q pointer to the COOKContext * @param inbuffer pointer to the mltcoefficients * @param outbuffer pointer to the timedomain buffer * @param mlt_tmp pointer to temporary storage space */static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer, float* mlt_tmp){ int i; /* prerotation */ for(i=0 ; i<q->mlt_size ; i+=2){ outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) + (q->mlt_precos[i/2] * inbuffer[i]); outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) - (q->mlt_presin[i/2] * inbuffer[i]); } /* FFT */ ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer); ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer); /* postrotation */ for(i=0 ; i<q->mlt_size ; i+=2){ mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) + (q->mlt_postcos[i/2] * outbuffer[i]); mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) - (q->mlt_postcos[i/2] * outbuffer[i+1]); } /* window and reorder */ for(i=0 ; i<q->mlt_size/2 ; i++){ outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i]; outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[q->mlt_size-1-i]; outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] * q->mlt_window[q->mlt_size-1-i]; outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] * q->mlt_window[i]); }}/** * the actual requantization of the timedomain samples * * @param q pointer to the COOKContext * @param buffer pointer to the timedomain buffer * @param gain_index index for the block multiplier * @param gain_index_next index for the next block multiplier */static void interpolate(COOKContext *q, float* buffer, int gain_index, int gain_index_next){ int i; float fc1, fc2; fc1 = q->pow2tab[gain_index+63]; if(gain_index == gain_index_next){ //static gain for(i=0 ; i<q->gain_size_factor ; i++){ buffer[i]*=fc1; } return; } else { //smooth gain fc2 = q->gain_table[11 + (gain_index_next-gain_index)]; for(i=0 ; i<q->gain_size_factor ; i++){ buffer[i]*=fc1; fc1*=fc2; } return; }}/** * 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->qidx_table1[index-1]==i) { gain_index[i] = gain_previous->qidx_table2[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->qidx_table1[index-1]==i) { gain_index[i]= gain_now->qidx_table2[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 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) { 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 ; i<q->samples_per_channel ; i++) buffer[i]+=previous_buffer[i]; /* Save away the current to be previous block. */ memcpy(previous_buffer, buffer+q->samples_per_channel, sizeof(float)*q->samples_per_channel);}/** * function for getting the jointstereo coupling information * * @param q pointer to the COOKContext * @param decouple_tab decoupling array * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -