⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cook_fixpoint.h

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 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 + -