📄 cook_float.h
字号:
/*
* COOK compatible decoder, floating point implementation.
* Copyright (c) 2003 Sascha Sommer
* Copyright (c) 2005 Benjamin Larsson
*
*/
/**
* @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 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;
f1 = dither_tab[index];
if (av_random(&q->random_state) < 0x80000000) f1 = -f1;
}
mlt_p[i] = f1 * q->math.rootpow2tab[quant_index+63];
}
}
/**
* @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
*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 + -