📄 cook_fixpoint.h
字号:
/* * COOK compatible decoder, fixed point implementation. * Copyright (c) 2007 Ian Braithwaite * * 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_fixpoint.h * * Cook AKA RealAudio G2 fixed point functions. * * Fixed point values are represented as 32 bit signed integers, * which can be added and subtracted directly in C (without checks for * overflow/saturation. * * Three multiplication routines are provided: * 1) Multiplication by powers of two (2^-31 .. 2^31), implemented * with C's bit shift operations. * 2) Multiplication by 16 bit fractions (0 <= x < 1), implemented * in C using two 16x16->32 bit integer multiplications. * 3) A combination of the two above. *//** * Fixed point shift right with rounding. * * @param x fix point value * @param i shift, 1..31 */static inline FIXP fixp_shr(FIXP x, int i){ return (x + (1 << (i-1))) >> i;}/** * Fixed point multiply by power of two. * * @param x fix point value * @param i integer power-of-two, -31..+31 */static inline FIXP fixp_pow2(FIXP x, int i){ if (i < 0) return fixp_shr(x, -i); else return x << i; /* no check for overflow */}/** * Combined fixed point multiply by fraction and power of two. * * @param a fix point value * @param b fix point fraction, 0 <= b < 1 * @param i integer power-of-two, -31..+15 */static inline FIXP fixp_mult_pow2(FIXP a, FIXPU b, int i){#define COOK_MUL_16_32#ifdef COOK_MUL_16_32 int32_t hb = (a >> 16) * b; uint32_t lb = (a & 0xffffUL) * b; if (i < 0) return (hb + (int32_t)(lb >> 16) + (1 << (-1-i))) >> -i; else /* no check for overflow */ return (hb << i) + (int32_t)((lb + (1 << (15-i))) >> (16-i));#else#ifdef COOK_MUL_32_64 int32_t bs = b; int64_t ab = (int64_t) a * bs;#else int64_t ab = (int64_t) a * b;#endif return (ab + (1 << (15-i))) >> (16-i); /* no check for overflow */#endif}/** * Fixed point multiply by fraction. * * @param a fix point value * @param b fix point fraction, 0 <= b < 1 */static inline FIXP fixp_mult(FIXP a, FIXPU b){ return fixp_mult_pow2(a, b, 0);}/** * Initialise fixed point implementation. * Fill in the sine/cosine table. * * @param q pointer to the COOKContext */static inline int init_cook_math(COOKContext *q){ FIXPU *const sincos_lookup = q->math.sincos_lookup; FIXP s = 0, c = 0x80000000; /* 0.0, -1.0 */ uint16_t a = 0xc910; /* 2^14 pi */ int i = 0; sincos_lookup[i++] = 0x0000; sincos_lookup[i++] = 0xffff; while (i < 2050) { FIXP s2 = s + fixp_mult_pow2(c - fixp_mult_pow2(s, a, -11), a, -10); FIXP c2 = c - fixp_mult_pow2(s + fixp_mult_pow2(c, a, -11), a, -10); s = s2; c = c2; sincos_lookup[i++] = -fixp_shr(s, 15); sincos_lookup[i++] = FFMIN(-fixp_shr(c, 15), 0xffff); } return 0;}/** * Free resources used by floating point implementation. * Nothing to do for fixed point. * * @param q pointer to the COOKContext */static inline void free_cook_math(COOKContext *q){ return;}/** * 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, FIXP *mlt_p){ /* Num. half bits to right shift */ const int s = 33 - quant_index + av_log2(q->samples_per_channel); FIXP f1; int i; if (s >= 64) { memset(mlt_p, 0, sizeof(FIXP) * SUBBAND_SIZE); return; } for(i=0 ; i<SUBBAND_SIZE ; i++) { if (subband_coef_index[i]) { f1 = quant_centroid_tab[index][subband_coef_index[i]][s&1]; if (subband_coef_sign[i]) f1 = -f1; } else { /* noise coding if subband_coef_index[i] == 0 */ f1 = dither_tab[index][s&1]; if (av_random(&q->random_state) < 0x80000000) f1 = -f1; } mlt_p[i] = fixp_shr(f1, s/2); }}/** * 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, FIXP* buffer, int gain_index, int gain_index_next){ int gain_size_factor = q->samples_per_channel/8; int i; if(gain_index == gain_index_next){ //static gain for(i = 0; i < gain_size_factor; i++) { buffer[i] = fixp_pow2(buffer[i], gain_index); } } else { //smooth gain int step = (gain_index_next - gain_index) << (7 - av_log2(gain_size_factor)); int x = 0; for(i = 0; i < gain_size_factor; i++) { buffer[i] = fixp_mult_pow2(buffer[i], pow128_tab[x], gain_index+1); x += step; gain_index += x >> 7; x = x & 0x7f; } }}/* Include fixed point modified discrete cosine transform */#include "cook_fixp_mdct.h"/** * 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, FIXP *inbuffer, int gain0, FIXP *previous_buffer){ const FIXPU *sincos_lookup = q->math.sincos_lookup; const int n = q->samples_per_channel; const int step = 4 << (10 - av_log2(n)); FIXP *buffer1 = q->mono_mdct_output + n; int i = 0, j = step>>1; cook_mdct_backward(2 * n, inbuffer, q->mono_mdct_output, q->math.sincos_lookup); /* Apply window and overlap */ do { buffer1[i] = fixp_mult_pow2(buffer1[i], sincos_lookup[j], gain0) - fixp_mult(previous_buffer[i], sincos_lookup[j+1]); j += step; } while (++i < n/2); do { j -= step; buffer1[i] = fixp_mult_pow2(buffer1[i], sincos_lookup[j+1], gain0) - fixp_mult(previous_buffer[i], sincos_lookup[j]); } while (++i < n);}/** * Decoupling calculation for joint stereo coefficients. * * @param x mono coefficient * @param table number of decoupling table * @param i table index */static inline FIXP cplscale_math(FIXP x, int table, int i){ return fixp_mult(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){ FIXP *output = q->mono_mdct_output + q->samples_per_channel; int j; for (j = 0; j < q->samples_per_channel; j++) { FIXP v = fixp_shr(output[j], 11); if ((uint32_t) v + 0x8000 > 0xffff) v = (v >> 31) ^ 0x7fff; out[chan + q->nb_channels * j] = v; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -