📄 cook_float.h
字号:
/* * COOK compatible decoder, floating point implementation. * Copyright (c) 2003 Sascha Sommer * Copyright (c) 2005 Benjamin Larsson * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * *//** * @file cook_float.h * * Cook AKA RealAudio G2 floating point functions. *//** * Initialise floating point implementation: * lookup tables, mdct and associated window. * * @param q pointer to the COOKContext */static inline int init_cook_math(COOKContext *q){ int gain_size_factor = q->samples_per_channel/8; int mlt_size = q->samples_per_channel; int i; float alpha; /* Table of pow(2, [-63:63]) */ q->math.pow2tab[63] = 1.0; for (i=1 ; i<64 ; i++){ q->math.pow2tab[63+i]=(float)((uint64_t)1<<i); q->math.pow2tab[63-i]=1.0/(float)((uint64_t)1<<i); } /* Table of pow(2, [-63..63]/2) */ q->math.rootpow2tab[63] = 1.0; for (i=1 ; i<64 ; i++){ q->math.rootpow2tab[63+i]=sqrt((float)((uint64_t)1<<i)); q->math.rootpow2tab[63-i]=sqrt(1.0/(float)((uint64_t)1<<i)); } /* Table of pow(2, [-11..11]/(samples_per_channel/8)) */ for (i=0 ; i<23 ; i++) { q->math.gain_table[i] = pow((double)q->math.pow2tab[i+52], 1.0/(double)gain_size_factor); } /* Initialize the MLT window: simple sine window. */ if ((q->math.mlt_window = av_malloc(sizeof(float)*mlt_size)) == 0) return -1; alpha = M_PI / (2.0 * (float)mlt_size); for(i=0 ; i<mlt_size ; i++) { q->math.mlt_window[i] = sin((i + 0.5) * alpha) * sqrt(2.0 / q->samples_per_channel); } /* Initialize the MDCT. */ if (ff_mdct_init(&q->math.mdct_ctx, av_log2(mlt_size)+1, 1)) { av_free(q->math.mlt_window); return -1; } av_log(NULL,AV_LOG_DEBUG,"MDCT initialized, order = %d.\n", av_log2(mlt_size)+1); return 0;}/** * Free resources used by floating point implementation. * * @param q pointer to the COOKContext */static inline void free_cook_math(COOKContext *q){ /* Free allocated memory buffers. */ av_free(q->math.mlt_window); /* Free the transform. */ ff_mdct_end(&q->math.mdct_ctx);}/** * The real requantization of the mltcoefs * * @param q pointer to the COOKContext * @param index index * @param quant_index quantisation index * @param subband_coef_index array of indexes to quant_centroid_tab * @param subband_coef_sign signs of coefficients * @param mlt_p pointer into the mlt buffer */static void scalar_dequant_math(COOKContext *q, int index, int quant_index, int* subband_coef_index, int* subband_coef_sign, float* mlt_p){ int i; float f1; for(i=0 ; i<SUBBAND_SIZE ; i++) { if (subband_coef_index[i]) { f1 = quant_centroid_tab[index][subband_coef_index[i]]; if (subband_coef_sign[i]) f1 = -f1; } else { /* noise coding if subband_coef_index[i] == 0 */ f1 = dither_tab[index]; if (av_random(&q->random_state) < 0x80000000) f1 = -f1; } mlt_p[i] = f1 * q->math.rootpow2tab[quant_index+63]; }}/** * 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 inline void interpolate_math(COOKContext *q, float* buffer, int gain_index, int gain_index_next){ int gain_size_factor = q->samples_per_channel/8; int i; float fc1, fc2; fc1 = q->math.pow2tab[gain_index+63]; if(gain_index == gain_index_next){ //static gain for(i=0 ; i<gain_size_factor ; i++){ buffer[i]*=fc1; } } else { //smooth gain fc2 = q->math.gain_table[11 + (gain_index_next-gain_index)]; for(i=0 ; i<gain_size_factor ; i++){ buffer[i]*=fc1; fc1*=fc2; } }}/** * The modulated lapped transform, this takes transform coefficients * and transforms them into timedomain samples. * Applies transform window and overlaps buffers. * * @param q pointer to the COOKContext * @param inbuffer pointer to the mltcoefficients * @param gain0 gain difference now/previous buffers * @param previous_buffer pointer to the previous buffer to be used for overlapping */static void imlt_math(COOKContext *q, float *inbuffer, int gain0, float* previous_buffer){ const float fc = q->math.pow2tab[gain0 + 63]; float *buffer1 = q->mono_mdct_output + q->samples_per_channel; int i; /* Inverse modified discrete cosine transform */ q->math.mdct_ctx.fft.imdct_calc(&q->math.mdct_ctx, q->mono_mdct_output, inbuffer, q->math.mdct_tmp); /* The weird thing here, is that the two halves of the time domain * buffer are swapped. Also, the newest data, that we save away for * next frame, has the wrong sign. Hence the subtraction below. * Almost sounds like a complex conjugate/reverse data/FFT effect. */ /* Apply window and overlap */ for(i = 0; i < q->samples_per_channel; i++){ buffer1[i] = buffer1[i] * fc * q->math.mlt_window[i] - previous_buffer[i] * q->math.mlt_window[q->samples_per_channel - 1 - i]; }}/** * Decoupling calculation for joint stereo coefficients. * * @param x mono coefficient * @param table number of decoupling table * @param i table index */static inline float cplscale_math(float x, int table, int i){ return x * cplscales[table-2][i];}/** * Final converion from floating point values to * signed, 16 bit sound samples. Round and clip. * * @param q pointer to the COOKContext * @param out pointer to the output buffer * @param chan 0: left or single channel, 1: right channel */static inline void output_math(COOKContext *q, int16_t *out, int chan){ float *output = q->mono_mdct_output + q->samples_per_channel; int j; /* FIXME: Should use DSPContext.float_to_int16() here. */ for (j = 0; j < q->samples_per_channel; j++) { out[chan + q->nb_channels * j] = av_clip(lrintf(output[j]), -32768, 32767); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -