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

📄 wmadec.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * WMA compatible decoder * Copyright (c) 2002 The FFmpeg Project. * * 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 wmadec.c * WMA compatible decoder. * This decoder handles Microsoft Windows Media Audio data, versions 1 & 2. * WMA v1 is identified by audio format 0x160 in Microsoft media files * (ASF/AVI/WAV). WMA v2 is identified by audio format 0x161. * * To use this decoder, a calling application must supply the extra data * bytes provided with the WMA data. These are the extra, codec-specific * bytes at the end of a WAVEFORMATEX data structure. Transmit these bytes * to the decoder using the extradata[_size] fields in AVCodecContext. There * should be 4 extra bytes for v1 data and 6 extra bytes for v2 data. */#include "avcodec.h"#include "wma.h"#undef NDEBUG#include <assert.h>#define EXPVLCBITS 8#define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS)#define HGAINVLCBITS 9#define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS)static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len);#ifdef TRACEstatic void dump_shorts(WMACodecContext *s, const char *name, const short *tab, int n){    int i;    tprintf(s->avctx, "%s[%d]:\n", name, n);    for(i=0;i<n;i++) {        if ((i & 7) == 0)            tprintf(s->avctx, "%4d: ", i);        tprintf(s->avctx, " %5d.0", tab[i]);        if ((i & 7) == 7)            tprintf(s->avctx, "\n");    }}static void dump_floats(WMACodecContext *s, const char *name, int prec, const float *tab, int n){    int i;    tprintf(s->avctx, "%s[%d]:\n", name, n);    for(i=0;i<n;i++) {        if ((i & 7) == 0)            tprintf(s->avctx, "%4d: ", i);        tprintf(s->avctx, " %8.*f", prec, tab[i]);        if ((i & 7) == 7)            tprintf(s->avctx, "\n");    }    if ((i & 7) != 0)        tprintf(s->avctx, "\n");}#endifstatic int wma_decode_init(AVCodecContext * avctx){    WMACodecContext *s = avctx->priv_data;    int i, flags1, flags2;    uint8_t *extradata;    s->avctx = avctx;    /* extract flag infos */    flags1 = 0;    flags2 = 0;    extradata = avctx->extradata;    if (avctx->codec->id == CODEC_ID_WMAV1 && avctx->extradata_size >= 4) {        flags1 = AV_RL16(extradata);        flags2 = AV_RL16(extradata+2);    } else if (avctx->codec->id == CODEC_ID_WMAV2 && avctx->extradata_size >= 6) {        flags1 = AV_RL32(extradata);        flags2 = AV_RL16(extradata+4);    }// for(i=0; i<avctx->extradata_size; i++)//     av_log(NULL, AV_LOG_ERROR, "%02X ", extradata[i]);    s->use_exp_vlc = flags2 & 0x0001;    s->use_bit_reservoir = flags2 & 0x0002;    s->use_variable_block_len = flags2 & 0x0004;    if(ff_wma_init(avctx, flags2)<0)        return -1;    /* init MDCT */    for(i = 0; i < s->nb_block_sizes; i++)        ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 1);    if (s->use_noise_coding) {        init_vlc(&s->hgain_vlc, HGAINVLCBITS, sizeof(ff_wma_hgain_huffbits),                 ff_wma_hgain_huffbits, 1, 1,                 ff_wma_hgain_huffcodes, 2, 2, 0);    }    if (s->use_exp_vlc) {        init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(ff_wma_scale_huffbits), //FIXME move out of context                 ff_wma_scale_huffbits, 1, 1,                 ff_wma_scale_huffcodes, 4, 4, 0);    } else {        wma_lsp_to_curve_init(s, s->frame_len);    }    return 0;}/** * 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 float pow_m1_4(WMACodecContext *s, float x){    union {        float f;        unsigned int v;    } u, t;    unsigned int e, m;    float 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 s->lsp_pow_e_table[e] * (a + b * t.f);}static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len){    float wdel, a, b;    int i, e, m;    wdel = M_PI / frame_len;    for(i=0;i<frame_len;i++)        s->lsp_cos_table[i] = 2.0f * cos(wdel * i);    /* tables for x^-0.25 computation */    for(i=0;i<256;i++) {        e = i - 126;        s->lsp_pow_e_table[i] = pow(2.0, e * -0.25);    }    /* NOTE: these two tables are needed to avoid two operations in       pow_m1_4 */    b = 1.0;    for(i=(1 << LSP_POW_BITS) - 1;i>=0;i--) {        m = (1 << LSP_POW_BITS) + i;        a = (float)m * (0.5 / (1 << LSP_POW_BITS));        a = pow(a, -0.25);        s->lsp_pow_m_table1[i] = 2 * a - b;        s->lsp_pow_m_table2[i] = b - a;        b = a;    }#if 0    for(i=1;i<20;i++) {        float v, r1, r2;        v = 5.0 / i;        r1 = pow_m1_4(s, v);        r2 = pow(v,-0.25);        printf("%f^-0.25=%f e=%f\n", v, r1, r2 - r1);    }#endif}/** * NOTE: We use the same code as Vorbis here * @todo optimize it further with SSE/3Dnow */static void wma_lsp_to_curve(WMACodecContext *s,                             float *out, float *val_max_ptr,                             int n, float *lsp){    int i, j;    float p, q, w, v, val_max;    val_max = 0;    for(i=0;i<n;i++) {        p = 0.5f;        q = 0.5f;        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 * (2.0f - w);        q *= q * (2.0f + w);        v = p + q;        v = pow_m1_4(s, v);        if (v > val_max)            val_max = v;        out[i] = v;    }    *val_max_ptr = val_max;}/** * decode exponents coded with LSP coefficients (same idea as Vorbis) */static void decode_exp_lsp(WMACodecContext *s, int ch){    float 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] = ff_wma_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(WMACodecContext *s, int ch){    int last_exp, n, code;    const uint16_t *ptr, *band_ptr;    float v, *q, max_scale, *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, last_exp * (1.0 / 16.0));        max_scale = v;        n = *ptr++;        do {            *q++ = v;        } while (--n);    }else        last_exp = 36;    while (q < q_end) {        code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX);        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, last_exp * (1.0 / 16.0));        if (v > max_scale)            max_scale = v;        n = *ptr++;        do {            *q++ = v;        } while (--n);    }    s->max_exponent[ch] = max_scale;    return 0;}/** * Apply MDCT window and add into output. * * We ensure that when the windows overlap their squared sum * is always 1 (MDCT reconstruction rule). */static void wma_window(WMACodecContext *s, float *out){    float *in = s->output;    int block_len, bsize, n;    /* left part */    if (s->block_len_bits <= s->prev_block_len_bits) {        block_len = s->block_len;        bsize = s->frame_len_bits - s->block_len_bits;        s->dsp.vector_fmul_add_add(out, in, s->windows[bsize],                                   out, 0, block_len, 1);    } else {        block_len = 1 << s->prev_block_len_bits;        n = (s->block_len - block_len) / 2;        bsize = s->frame_len_bits - s->prev_block_len_bits;        s->dsp.vector_fmul_add_add(out+n, in+n, s->windows[bsize],                                   out+n, 0, block_len, 1);        memcpy(out+n+block_len, in+n+block_len, n*sizeof(float));    }    out += s->block_len;    in += s->block_len;    /* right part */    if (s->block_len_bits <= s->next_block_len_bits) {        block_len = s->block_len;        bsize = s->frame_len_bits - s->block_len_bits;        s->dsp.vector_fmul_reverse(out, in, s->windows[bsize], block_len);    } else {        block_len = 1 << s->next_block_len_bits;        n = (s->block_len - block_len) / 2;        bsize = s->frame_len_bits - s->next_block_len_bits;        memcpy(out, in, n*sizeof(float));        s->dsp.vector_fmul_reverse(out+n, in+n, s->windows[bsize], block_len);        memset(out+n+block_len, 0, n*sizeof(float));    }}/** * @return 0 if OK. 1 if last block of frame. return -1 if * unrecorrable error. */static int wma_decode_block(WMACodecContext *s){    int n, v, a, ch, code, bsize;    int coef_nb_bits, total_gain;    int nb_coefs[MAX_CHANNELS];    float mdct_norm;#ifdef TRACE    tprintf(s->avctx, "***decode_block: %d:%d\n", s->frame_count - 1, s->block_num);#endif    /* 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_bits1(&s->gb);    }    v = 0;    for(ch = 0; ch < s->nb_channels; ch++) {        a = get_bits1(&s->gb);        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;    }    coef_nb_bits= ff_wma_total_gain_to_bits(total_gain);    /* 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_bits1(&s->gb);                    s->high_band_coded[ch][i] = a;                    /* if noise coding, the coefficients are not transmitted */                    if (a)

⌨️ 快捷键说明

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