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

📄 huffdec.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:
    byte sect[ 2*(MAXBANDS+1) ];

    memset(sect, 0, sizeof(sect));

    /*
    * global gain
    */
    *global_gain = (short)faad_getbits(&hDecoder->ld, LEN_SCL_PCM);

    if (!common_window) {
        if (!get_ics_info(hDecoder, win, wshape, group, max_sfb, lpflag, prstflag,
            nok_ltp_status, NULL, 0))
            return 0;
    }

    CopyMemory(info, hDecoder->winmap[*win], sizeof(Info));

    /* calculate total number of sfb for this grouping */
    if (*max_sfb == 0) {
        tot_sfb = 0;
    }
    else {
        i=0;
        tot_sfb = info->sfb_per_sbk[0];
        while (group[i++] < info->nsbk) {
            tot_sfb += info->sfb_per_sbk[0];
        }
    }

    /*
    * section data
    */
    nsect = huffcb(hDecoder, sect, info->sectbits, tot_sfb, info->sfb_per_sbk[0], *max_sfb);
    if(nsect==0 && *max_sfb>0)
        return 0;

        /* generate "linear" description from section info
        * stored as codebook for each scalefactor band and group
    */
    if (nsect) {
        bot = 0;
        for (i=0; i<nsect; i++) {
            cb = sect[2*i];
            top = sect[2*i + 1];
            for (; bot<top; bot++)
                *cb_map++ = cb;
            bot = top;
        }
    }  else {
        for (i=0; i<MAXBANDS; i++)
            cb_map[i] = 0;
    }

    /* calculate band offsets
    * (because of grouping and interleaving this cannot be
    * a constant: store it in info.bk_sfb_top)
    */
    calc_gsfb_table(info, group);

    /*
    * scale factor data
    */
    if(!hufffac(hDecoder, info, group, nsect, sect, *global_gain, factors))
        return 0;

    /*
     *  Pulse coding
     */
    if ((hDecoder->pulse_info.pulse_data_present = faad_get1bit(&hDecoder->ld))) { /* pulse data present */
        if (info->islong) {
            get_pulse_nc(hDecoder, &hDecoder->pulse_info);
        } else {
            /* CommonExit(1,"Pulse data not allowed for short blocks"); */
            return 0;
        }
    }

    /*
    * tns data
    */
    if (faad_get1bit(&hDecoder->ld)) { /* tns present */
        get_tns(hDecoder, info, tns);
    }
    else {
        clr_tns(info, tns);
    }

    if (faad_get1bit(&hDecoder->ld)) { /* gain control present */
        /* CommonExit(1, "Gain control not implemented"); */
        return 0;
    }

    return huffspec(hDecoder, info, nsect, sect, factors, coef);
}

/*
 * read the codebook and boundaries
 */
static int huffcb(faacDecHandle hDecoder, byte *sect, int *sectbits,
           int tot_sfb, int sfb_per_sbk, byte max_sfb)
{
    int nsect, n, base, bits, len;

    bits = sectbits[0];
    len = (1 << bits) - 1;
    nsect = 0;

    for(base = 0; base < tot_sfb && nsect < tot_sfb; ) {
        *sect++ = (byte)faad_getbits(&hDecoder->ld, LEN_CB);

        n = faad_getbits(&hDecoder->ld, bits);
        while(n == len && base < tot_sfb) {
            base += len;
            n = faad_getbits(&hDecoder->ld, bits);
        }
        base += n;
        *sect++ = base;
        nsect++;

        /* insert a zero section for regions above max_sfb for each group */
        if ((sect[-1] % sfb_per_sbk) == max_sfb) {
            base += (sfb_per_sbk - max_sfb);
            *sect++ = 0;
            *sect++ = base;
            nsect++;
        }
    }

    if(base != tot_sfb || nsect > tot_sfb)
        return 0;

    return nsect;
}

/*
 * get scale factors
 */
static int hufffac(faacDecHandle hDecoder, Info *info, byte *group, int nsect, byte *sect,
        int global_gain, int *factors)
{
    Huffscl *hcw;
    int i, b, bb, t, n, sfb, top, fac, is_pos;
    int factor_transmitted[MAXBANDS], *fac_trans;
    int noise_pcm_flag = 1;
    int noise_nrg;

    /* clear array for the case of max_sfb == 0 */
    SetMemory(factor_transmitted, 0, MAXBANDS*sizeof(int));
    SetMemory(factors, 0, MAXBANDS*sizeof(int));

    sfb = 0;
    fac_trans = factor_transmitted;
    for(i = 0; i < nsect; i++){
        top = sect[1];      /* top of section in sfb */
        t = sect[0];        /* codebook for this section */
        sect += 2;
        for(; sfb < top; sfb++) {
            fac_trans[sfb] = t;
        }
    }

    /* scale factors are dpcm relative to global gain
    * intensity positions are dpcm relative to zero
    */
    fac = global_gain;
    is_pos = 0;
    noise_nrg = global_gain - NOISE_OFFSET;

    /* get scale factors */
    hcw = bookscl;
    bb = 0;
    for(b = 0; b < info->nsbk; ){
        n = info->sfb_per_sbk[b];
        b = *group++;
        for(i = 0; i < n; i++){
            switch (fac_trans[i]) {
            case ZERO_HCB:      /* zero book */
                break;
            default:            /* spectral books */
                /* decode scale factor */
                t = decode_huff_cw_scl(hDecoder, hcw);
                fac += t - MIDFAC;    /* 1.5 dB */
                if(fac >= 2*TEXP || fac < 0)
                    return 0;
                factors[i] = fac;
                break;
            case BOOKSCL:       /* invalid books */
                return 0;
            case INTENSITY_HCB:     /* intensity books */
            case INTENSITY_HCB2:
                /* decode intensity position */
                t = decode_huff_cw_scl(hDecoder, hcw);
                is_pos += t - MIDFAC;
                factors[i] = is_pos;
                break;
            case NOISE_HCB:     /* noise books */
                /* decode noise energy */
                if (noise_pcm_flag) {
                    noise_pcm_flag = 0;
                    t = faad_getbits(&hDecoder->ld, NOISE_PCM_BITS) - NOISE_PCM_OFFSET;
                } else
                    t = decode_huff_cw_scl(hDecoder, hcw) - MIDFAC;
                noise_nrg += t;
                factors[i] = noise_nrg;
                break;
            }
        }

        /* expand short block grouping */
        if (!(info->islong)) {
            for(bb++; bb < b; bb++) {
                for (i=0; i<n; i++) {
                    factors[i+n] = factors[i];
                }
                factors += n;
            }
        }
        fac_trans += n;
        factors += n;
    }
    return 1;
}

__inline float esc_iquant(faacDecHandle hDecoder, int q)
{
    if (q > 0) {
        if (q < MAX_IQ_TBL) {
            return((float)hDecoder->iq_exp_tbl[q]);
        } else {
            return((float)pow(q, 4./3.));
        }
    } else {
        q = -q;
        if (q < MAX_IQ_TBL) {
            return((float)(-hDecoder->iq_exp_tbl[q]));
        } else {
            return((float)(-pow(q, 4./3.)));
        }
    }
}

static int huffspec(faacDecHandle hDecoder, Info *info, int nsect, byte *sect,
             int *factors, Float *coef)
{
    Hcb *hcb;
    Huffman *hcw;
    int i, j, k, table, step, stop, bottom, top;
    int *bands, *bandp;
    int *quant, *qp;
    int *tmp_spec;
    int *quantPtr;
    int *tmp_specPtr;

    quant = AllocMemory(LN2*sizeof(int));
    tmp_spec = AllocMemory(LN2*sizeof(int));

    quantPtr = quant;
    tmp_specPtr = tmp_spec;

#ifndef WIN32
    SetMemory(quant, 0, LN2*sizeof(int));
#endif

    bands = info->bk_sfb_top;
    bottom = 0;
    k = 0;
    bandp = bands;
    for(i = nsect; i; i--) {
        table = sect[0];
        top = sect[1];
        sect += 2;
        if( (table == 0) || (table == NOISE_HCB) ||
            (table == INTENSITY_HCB) || (table == INTENSITY_HCB2) ) {
            bandp = bands+top;
            k = bandp[-1];
            bottom = top;
            continue;
        }
        if(table < BY4BOOKS+1) {
            step = 4;
        } else {
            step = 2;
        }
        hcb = &book[table];
        hcw = hcb->hcw;
        qp = quant+k;
        for(j = bottom; j < top; j++) {
            stop = *bandp++;
            while(k < stop) {
                decode_huff_cw(hDecoder, hcw, qp, hcb);

                if (!hcb->signed_cb)
                    get_sign_bits(hDecoder, qp, step);
                if(table == ESCBOOK){
                    qp[0] = getescape(hDecoder, qp[0]);
                    qp[1] = getescape(hDecoder, qp[1]);
                }
                qp += step;
                k += step;
            }
        }
        bottom = top;
    }

    /* pulse coding reconstruction */
    if ((info->islong) && (hDecoder->pulse_info.pulse_data_present))
        pulse_nc(hDecoder, quant, &hDecoder->pulse_info);

    if (!info->islong) {
        deinterleave (quant,tmp_spec,
            (short)info->num_groups,
            info->group_len,
            info->sfb_per_sbk,
            info->sfb_width_128);

        for (i = LN2/16 - 1; i >= 0; --i)
        {
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
            *quantPtr++ = *tmp_specPtr++; *quantPtr++ = *tmp_specPtr++;
        }
    }

    /* inverse quantization */
    for (i=0; i<info->bins_per_bk; i++) {
        coef[i] = esc_iquant(hDecoder, quant[i]);
    }

    /* rescaling */
    {
        int sbk, nsbk, sfb, nsfb, fac, top;
        Float *fp, scale;

        i = 0;
        fp = coef;
        nsbk = info->nsbk;
        for (sbk=0; sbk<nsbk; sbk++) {
            nsfb = info->sfb_per_sbk[sbk];
            k=0;
            for (sfb=0; sfb<nsfb; sfb++) {
                top = info->sbk_sfb_top[sbk][sfb];
                fac = factors[i++]-SF_OFFSET;

                if (fac >= 0 && fac < TEXP) {
                    scale = hDecoder->exptable[fac];
                }
                else {
                    if (fac == -SF_OFFSET) {
                        scale = 0;
                    }
                    else {
                        scale = (float)pow(2.0,  0.25*fac);
                    }
                }
                for ( ; k<top; k++) {
                    *fp++ *= scale;
                }
            }
        }
    }

    if (quant) FreeMemory(quant);
    if (tmp_spec) FreeMemory(tmp_spec);

    return 1;
}


/*
 * initialize the Hcb structure and sort the Huffman
 * codewords by length, shortest (most probable) first
 */
void hufftab(Hcb *hcb, Huffman *hcw, int dim, int signed_cb)
{
    hcb->dim = dim;
    hcb->signed_cb = signed_cb;
    hcb->hcw = hcw;
}

__inline void decode_huff_cw(faacDecHandle hDecoder, Huffman *h, int *qp, Hcb *hcb)
{
    int i, j;
    unsigned long cw;

    i = h->len;
    cw = faad_getbits_fast(&hDecoder->ld, i);

    while (cw != h->cw)
    {
        h++;
        j = h->len-i;
        if (j!=0) {
            i += j;
            while (j--)
                cw = (cw<<1)|faad_get1bit(&hDecoder->ld);
        }
    }

    if(hcb->dim == 4)
    {
        qp[0] = h->x;
        qp[1] = h->y;
        qp[2] = h->v;
        qp[3] = h->w;
    } else {
        qp[0] = h->x;
        qp[1] = h->y;
    }
}

__inline int decode_huff_cw_scl(faacDecHandle hDecoder, Huffscl *h)
{
    int i, j;
    long cw;

    i = h->len;
    cw = faad_getbits_fast(&hDecoder->ld, i);

    while ((unsigned long)cw != h->cw)
    {
        h++;
        j = h->len-i;
        if (j!=0) {
            i += j;
            while (j--)
                cw = (cw<<1)|faad_get1bit(&hDecoder->ld);
        }
    }

    return h->scl;
}

/* get sign bits */
static void get_sign_bits(faacDecHandle hDecoder, int *q, int n)
{
    int i;

    for(i=0; i < n; i++)
    {
        if(q[i])
        {
            if(faad_get1bit(&hDecoder->ld) & 1)
            {
                /* 1 signals negative, as in 2's complement */
                q[i] = -q[i];
            }
        }
    }
}

static int getescape(faacDecHandle hDecoder, int q)
{
    int i, off, neg;

    if(q < 0){
        if(q != -16)
            return q;
        neg = 1;
    } else{
        if(q != +16)
            return q;
        neg = 0;
    }

    for(i=4;; i++){
        if(faad_get1bit(&hDecoder->ld) == 0)
            break;
    }

    if(i > 16){
        off = faad_getbits(&hDecoder->ld, i-16) << 16;
        off |= faad_getbits(&hDecoder->ld, 16);
    } else
        off = faad_getbits(&hDecoder->ld, i);

    i = off + (1<<i);
    if(neg)
        i = -i;
    return i;
}

⌨️ 快捷键说明

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