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

📄 wmadeci.c

📁 wma定点解码算法
💻 C
📖 第 1 页 / 共 5 页
字号:
        {            scale[i] = scale[j];            j += jincr;        }    }}/* compute x^-0.25 with an exponent and mantissa table. We use linear   interpolation to reduce the mantissa table size at a small speed   expense (linear interpolation approximately doubles the number of   bits of precision). */static inline fixed32 pow_m1_4(WMADecodeContext *s, fixed32 x){    union {        fixed64 f;        unsigned int v;    } u, t;    unsigned int e, m;    fixed64 a, b;    u.f = x;    e = u.v >> 23;    m = (u.v >> (23 - LSP_POW_BITS)) & ((1 << LSP_POW_BITS) - 1);    /* build interpolation scale: 1 <= t < 2. */    t.v = ((u.v << LSP_POW_BITS) & ((1 << 23) - 1)) | (127 << 23);    a = s->lsp_pow_m_table1[m];    b = s->lsp_pow_m_table2[m];    return lsp_pow_e_table[e] * (a + b * t.f);}static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len){    fixed32 wdel, a, b;    int i, m;    wdel = fixdiv32(M_PI_F, itofix32(frame_len));    for (i=0; i<frame_len; ++i)    {        s->lsp_cos_table[i] = 0x20000 * fixcos32(wdel * i);    }    /* NOTE: these two tables are needed to avoid two operations in       pow_m1_4 */    b = itofix32(1);    int ix = 0;    for(i=(1 << LSP_POW_BITS) - 1;i>=0;i--)    {        m = (1 << LSP_POW_BITS) + i;        a = m * (0x8000 / (1 << LSP_POW_BITS)); /* PJJ */        a = pow_a_table[++ix];  /* PJJ : further refinement */        s->lsp_pow_m_table1[i] = 2 * a - b;        s->lsp_pow_m_table2[i] = b - a;        b = a;    }}/* NOTE: We use the same code as Vorbis here */static void wma_lsp_to_curve(WMADecodeContext *s,                             fixed32 *out,                             fixed32 *val_max_ptr,                             int n,                             fixed32 *lsp){    int i, j;    fixed32 p, q, w, v, val_max;    val_max = 0;    for(i=0;i<n;++i)    {        p = 0x8000;        q = 0x8000;        w = s->lsp_cos_table[i];        for (j=1;j<NB_LSP_COEFS;j+=2)        {            q *= w - lsp[j - 1];            p *= w - lsp[j];        }        p *= p * (0x20000 - w);        q *= q * (0x20000 + w);        v = p + q;        v = pow_m1_4(s, v); /* PJJ */        if (v > val_max)        {            val_max = v;        }        out[i] = v;    }    *val_max_ptr = val_max;}void free_vlc(VLC *vlc){    av_free(vlc->table);}/* decode exponents coded with LSP coefficients (same idea as Vorbis) */static void decode_exp_lsp(WMADecodeContext *s, int ch){    fixed32 lsp_coefs[NB_LSP_COEFS];    int val, i;    for (i = 0; i < NB_LSP_COEFS; ++i)    {        if (i == 0 || i >= 8)        {            val = get_bits(&s->gb, 3);        }        else        {            val = get_bits(&s->gb, 4);        }        lsp_coefs[i] = lsp_codebook[i][val];    }    wma_lsp_to_curve(s,                     s->exponents[ch],                     &s->max_exponent[ch],                     s->block_len,                     lsp_coefs);}/* decode exponents coded with VLC codes */static int decode_exp_vlc(WMADecodeContext *s, int ch){    int last_exp, n, code;    const uint16_t *ptr, *band_ptr;    fixed32 v, max_scale;    fixed32 *q,*q_end;    band_ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits];    ptr = band_ptr;    q = s->exponents[ch];    q_end = q + s->block_len;    max_scale = 0;    if (s->version == 1)    {        last_exp = get_bits(&s->gb, 5) + 10;        /* XXX: use a table */        v = pow_10_to_yover16[last_exp];        max_scale = v;        n = *ptr++;        do        {            *q++ = v;        }        while (--n);    }    last_exp = 36;    while (q < q_end)    {        code = get_vlc(&s->gb, &s->exp_vlc);        if (code < 0)        {            return -1;        }        /* NOTE: this offset is the same as MPEG4 AAC ! */        last_exp += code - 60;        /* XXX: use a table */        v = pow_10_to_yover16[last_exp];        if (v > max_scale)        {            max_scale = v;        }        n = *ptr++;        do        {            *q++ = v;        }        while (--n);    }    s->max_exponent[ch] = max_scale;    return 0;}/* return 0 if OK. return 1 if last block of frame. return -1 if   unrecorrable error. */static int wma_decode_block(WMADecodeContext *s){    int n, v, a, ch, code, bsize;    int coef_nb_bits, total_gain, parse_exponents;    fixed32 window[BLOCK_MAX_SIZE * 2];    int nb_coefs[MAX_CHANNELS];    fixed32 mdct_norm;    /* compute current block length */    if (s->use_variable_block_len)    {        n = av_log2(s->nb_block_sizes - 1) + 1;        if (s->reset_block_lengths)        {            s->reset_block_lengths = 0;            v = get_bits(&s->gb, n);            if (v >= s->nb_block_sizes)            {                return -1;            }            s->prev_block_len_bits = s->frame_len_bits - v;            v = get_bits(&s->gb, n);            if (v >= s->nb_block_sizes)            {                return -1;            }            s->block_len_bits = s->frame_len_bits - v;        }        else        {            /* update block lengths */            s->prev_block_len_bits = s->block_len_bits;            s->block_len_bits = s->next_block_len_bits;        }        v = get_bits(&s->gb, n);        if (v >= s->nb_block_sizes)        {            return -1;        }        s->next_block_len_bits = s->frame_len_bits - v;    }    else    {        /* fixed block len */        s->next_block_len_bits = s->frame_len_bits;        s->prev_block_len_bits = s->frame_len_bits;        s->block_len_bits = s->frame_len_bits;    }    /* now check if the block length is coherent with the frame length */    s->block_len = 1 << s->block_len_bits;    if ((s->block_pos + s->block_len) > s->frame_len)    {        return -1;    }    if (s->nb_channels == 2)    {        s->ms_stereo = get_bits(&s->gb, 1);    }    v = 0;    for (ch = 0; ch < s->nb_channels; ++ch)    {        a = get_bits(&s->gb, 1);        s->channel_coded[ch] = a;        v |= a;    }    /* if no channel coded, no need to go further */    /* XXX: fix potential framing problems */    if (!v)    {        goto next;    }    bsize = s->frame_len_bits - s->block_len_bits;    /* read total gain and extract corresponding number of bits for       coef escape coding */    total_gain = 1;    for(;;)    {        a = get_bits(&s->gb, 7);        total_gain += a;        if (a != 127)        {            break;        }    }    if (total_gain < 15)        coef_nb_bits = 13;    else if (total_gain < 32)        coef_nb_bits = 12;    else if (total_gain < 40)        coef_nb_bits = 11;    else if (total_gain < 45)        coef_nb_bits = 10;    else        coef_nb_bits = 9;    /* compute number of coefficients */    n = s->coefs_end[bsize] - s->coefs_start;    for(ch = 0; ch < s->nb_channels; ++ch)    {        nb_coefs[ch] = n;    }    /* complex coding */    if (s->use_noise_coding)    {        for(ch = 0; ch < s->nb_channels; ++ch)        {            if (s->channel_coded[ch])            {                int i, n, a;                n = s->exponent_high_sizes[bsize];                for(i=0;i<n;++i)                {                    a = get_bits(&s->gb, 1);                    s->high_band_coded[ch][i] = a;                    /* if noise coding, the coefficients are not transmitted */                    if (a)                        nb_coefs[ch] -= s->exponent_high_bands[bsize][i];                }            }        }        for(ch = 0; ch < s->nb_channels; ++ch)        {            if (s->channel_coded[ch])            {                int i, n, val, code;                n = s->exponent_high_sizes[bsize];                val = (int)0x80000000;                for(i=0;i<n;++i)                {                    if (s->high_band_coded[ch][i])                    {                        if (val == (int)0x80000000)                        {                            val = get_bits(&s->gb, 7) - 19;                        }                        else                        {                            code = get_vlc(&s->gb, &s->hgain_vlc);                            if (code < 0)                            {                                return -1;                            }                            val += code - 18;                        }                        s->high_band_values[ch][i] = val;                    }                }            }        }    }    /* exposant can be interpolated in short blocks. */    parse_exponents = 1;    if (s->block_len_bits != s->frame_len_bits)    {        parse_exponents = get_bits(&s->gb, 1);    }    if (parse_exponents)    {        for(ch = 0; ch < s->nb_channels; ++ch)        {            if (s->channel_coded[ch])            {                if (s->use_exp_vlc)                {                    if (decode_exp_vlc(s, ch) < 0)                    {                        return -1;                    }                }                else                {                    decode_exp_lsp(s, ch);                }            }        }    }    else    {        for(ch = 0; ch < s->nb_channels; ++ch)        {            if (s->channel_coded[ch])            {                interpolate_array(s->exponents[ch],                                  1 << s->prev_block_len_bits,                                  s->block_len);            }        }    }    /* parse spectral coefficients : just RLE encoding */    for(ch = 0; ch < s->nb_channels; ++ch)    {        if (s->channel_coded[ch])        {            VLC *coef_vlc;            int level, run, sign, tindex;            int16_t *ptr, *eptr;            const int16_t *level_table, *run_table;            /* special VLC tables are used for ms stereo because               there is potentially less energy there */            tindex = (ch == 1 && s->ms_stereo);            coef_vlc = &s->coef_vlc[tindex];            run_table = s->run_table[tindex];            level_table = s->level_table[tindex];            /* XXX: optimize */            ptr = &s->coefs1[ch][0];            eptr = ptr + nb_coefs[ch];            memset(ptr, 0, s->block_len * sizeof(int16_t));            for(;;)            {                code = get_vlc(&s->gb, coef_vlc);                if (code < 0)                {                    return -1;                }                if (code == 1)                {                    /* EOB */                    break;                }                else if (code == 0)                {                    /* escape */                    level = get_bits(&s->gb, coef_nb_bits);                    /* NOTE: this is rather suboptimal. reading                       block_len_bits would be better */                    run = get_bits(&s->gb, s->frame_len_bits);                }                else                {                    /* normal code */                    run = run_table[code];                    level = level_table[code];                }                sign = get_bits(&s->gb, 1);                if (!sign)                    level = -level;                ptr += run;                if (ptr >= eptr)                {                    return -1;                }                *ptr++ = level;                /* NOTE: EOB can be omitted */                if (ptr >= eptr)                    break;            }        }        if (s->version == 1 && s->nb_channels >= 2)        {            align_get_bits(&s->gb);        }    }    /* normalize */    {        int n4 = s->block_len >> 1;        mdct_norm = 0x10000;        mdct_norm = fixdiv32(mdct_norm,itofix32(n4));        if (s->version == 1)        {            fixed32 tmp = fixsqrt32(itofix32(n4));            mdct_norm *= tmp; /* PJJ : exercise this path */        }    }    /* finally compute the MDCT coefficients */    for(ch = 0; ch < s->nb_channels; ++ch)    {        if (s->channel_coded[ch])        {            int16_t *coefs1;            fixed32 *exponents, *exp_ptr;            fixed32 *coefs;            fixed64 mult;            fixed64 mult1;            fixed32 noise;            int i, j, n, n1, last_high_band;            fixed32 exp_power[HIGH_BAND_MAX_SIZE];            coefs1 = s->coefs1[ch];            exponents = s->exponents[ch];            mult = fixdiv64(pow_table[total_gain],Fixed32To64(s->max_exponent[ch]));            mult = fixmul64byfixed(mult, mdct_norm);            coefs = s->coefs[ch];            if (s->use_noise_coding)            {                mult1 = mult;                /* very low freqs : noise */                for(i = 0;i < s->coefs_start; ++i)                {                    *coefs++ = fixmul32(fixmul32(s->noise_table[s->noise_index],(*exponents++)),Fixed32From64(mult1));                    s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1);                }                n1 = s->exponent_high_sizes[bsize];                /* compute power of high bands */                exp_ptr = exponents +                          s->high_band_start[bsize] -                          s->coefs_start;                last_high_band = 0; /* avoid warning */                for (j=0;j<n1;++j)                {                    n = s->exponent_high_bands[s->frame_len_bits -                                               s->block_len_bits][j];                    if (s->high_band_coded[ch][j])                    {                        fixed32 e2, v;                        e2 = 0;                        for(i = 0;i < n; ++i)                        {                            v = exp_ptr[i];                            e2 += v * v;                        }                        exp_power[j] = fixdiv32(e2,n);                        last_high_band = j;                    }                    exp_ptr += n;                }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -