Skip to content
Snippets Groups Projects
mpegaudiodec.c 74.7 KiB
Newer Older
  • Learn to ignore specific revisions
  •         s0 = t1 + t0;
            s2 = t1 - t0;
    
            t2 = tmp[i + 1];
            t3 = tmp[i + 3];
            s1 = MULL(t3 + t2, icos36[j]);
            s3 = MULL(t3 - t2, icos36[8 - j]);
            
            t0 = MULL(s0 + s1, icos72[9 + 8 - j]);
            t1 = MULL(s0 - s1, icos72[8 - j]);
            out[18 + 9 + j] = t0;
            out[18 + 8 - j] = t0;
            out[9 + j] = -t1;
            out[8 - j] = t1;
            
            t0 = MULL(s2 + s3, icos72[9+j]);
            t1 = MULL(s2 - s3, icos72[j]);
            out[18 + 9 + (8 - j)] = t0;
            out[18 + j] = t0;
            out[9 + (8 - j)] = -t1;
            out[j] = t1;
            i += 4;
        }
    
        s0 = tmp[16];
        s1 = MULL(tmp[17], icos36[4]);
        t0 = MULL(s0 + s1, icos72[9 + 4]);
        t1 = MULL(s0 - s1, icos72[4]);
        out[18 + 9 + 4] = t0;
        out[18 + 8 - 4] = t0;
        out[9 + 4] = -t1;
        out[8 - 4] = t1;
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    /* fast header check for resync */
    static int check_header(UINT32 header)
    {
        /* header */
        if ((header & 0xffe00000) != 0xffe00000)
    	return -1;
        /* layer check */
        if (((header >> 17) & 3) == 0)
    	return -1;
    
        /* bit rate */
        if (((header >> 12) & 0xf) == 0xf)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    	return -1;
        /* frequency */
        if (((header >> 10) & 3) == 3)
    	return -1;
        return 0;
    }
    
    
    /* header + layer + bitrate + freq + lsf/mpeg25 */
    #define SAME_HEADER_MASK \
       (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19))
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    /* header decoding. MUST check the header before because no
    
       consistency check is done there. Return 1 if free format found and
       that the frame size must be computed externally */
    static int decode_header(MPADecodeContext *s, UINT32 header)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        int sample_rate, frame_size, mpeg25, padding;
        int sample_rate_index, bitrate_index;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (header & (1<<20)) {
    
            s->lsf = (header & (1<<19)) ? 0 : 1;
            mpeg25 = 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        } else {
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
        
        s->layer = 4 - ((header >> 17) & 3);
        /* extract frequency */
    
        sample_rate_index = (header >> 10) & 3;
        sample_rate = mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25);
        sample_rate_index += 3 * (s->lsf + mpeg25);
        s->sample_rate_index = sample_rate_index;
        s->error_protection = ((header >> 16) & 1) ^ 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        bitrate_index = (header >> 12) & 0xf;
        padding = (header >> 9) & 1;
        //extension = (header >> 8) & 1;
        s->mode = (header >> 6) & 3;
        s->mode_ext = (header >> 4) & 3;
        //copyright = (header >> 3) & 1;
        //original = (header >> 2) & 1;
        //emphasis = header & 3;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        if (s->mode == MPA_MONO)
            s->nb_channels = 1;
        else
            s->nb_channels = 2;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        
    
        if (bitrate_index != 0) {
            frame_size = mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index];
            s->bit_rate = frame_size * 1000;
            switch(s->layer) {
            case 1:
                frame_size = (frame_size * 12000) / sample_rate;
                frame_size = (frame_size + padding) * 4;
                break;
            case 2:
                frame_size = (frame_size * 144000) / sample_rate;
                frame_size += padding;
                break;
            default:
            case 3:
                frame_size = (frame_size * 144000) / (sample_rate << s->lsf);
                frame_size += padding;
                break;
            }
            s->frame_size = frame_size;
        } else {
            /* if no frame size computed, signal it */
            if (!s->free_format_frame_size)
                return 1;
            /* free format: compute bitrate and real frame size from the
               frame size we extracted by reading the bitstream */
            s->frame_size = s->free_format_frame_size;
            switch(s->layer) {
            case 1:
                s->frame_size += padding  * 4;
                s->bit_rate = (s->frame_size * sample_rate) / 48000;
                break;
            case 2:
                s->frame_size += padding;
                s->bit_rate = (s->frame_size * sample_rate) / 144000;
                break;
            default:
            case 3:
                s->frame_size += padding;
                s->bit_rate = (s->frame_size * (sample_rate << s->lsf)) / 144000;
                break;
            }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    #if defined(DEBUG)
    
        printf("layer%d, %d Hz, %d kbits/s, ",
               s->layer, s->sample_rate, s->bit_rate);
        if (s->nb_channels == 2) {
            if (s->layer == 3) {
                if (s->mode_ext & MODE_EXT_MS_STEREO)
                    printf("ms-");
                if (s->mode_ext & MODE_EXT_I_STEREO)
                    printf("i-");
            }
            printf("stereo");
        } else {
            printf("mono");
        }
        printf("\n");
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #endif
    
    /* return the number of decoded frames */
    static int mp_decode_layer1(MPADecodeContext *s)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        int bound, i, v, n, ch, j, mant;
        UINT8 allocation[MPA_MAX_CHANNELS][SBLIMIT];
        UINT8 scale_factors[MPA_MAX_CHANNELS][SBLIMIT];
    
        if (s->mode == MPA_JSTEREO) 
            bound = (s->mode_ext + 1) * 4;
        else
            bound = SBLIMIT;
    
        /* allocation bits */
        for(i=0;i<bound;i++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                allocation[ch][i] = get_bits(&s->gb, 4);
            }
        }
        for(i=bound;i<SBLIMIT;i++) {
            allocation[0][i] = get_bits(&s->gb, 4);
        }
    
        /* scale factors */
        for(i=0;i<bound;i++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                if (allocation[ch][i])
                    scale_factors[ch][i] = get_bits(&s->gb, 6);
            }
        }
        for(i=bound;i<SBLIMIT;i++) {
            if (allocation[0][i]) {
                scale_factors[0][i] = get_bits(&s->gb, 6);
                scale_factors[1][i] = get_bits(&s->gb, 6);
            }
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        
    
        /* compute samples */
        for(j=0;j<12;j++) {
            for(i=0;i<bound;i++) {
                for(ch=0;ch<s->nb_channels;ch++) {
                    n = allocation[ch][i];
                    if (n) {
                        mant = get_bits(&s->gb, n + 1);
                        v = l1_unscale(n, mant, scale_factors[ch][i]);
                    } else {
                        v = 0;
                    }
                    s->sb_samples[ch][j][i] = v;
                }
            }
            for(i=bound;i<SBLIMIT;i++) {
                n = allocation[0][i];
                if (n) {
                    mant = get_bits(&s->gb, n + 1);
                    v = l1_unscale(n, mant, scale_factors[0][i]);
                    s->sb_samples[0][j][i] = v;
                    v = l1_unscale(n, mant, scale_factors[1][i]);
                    s->sb_samples[1][j][i] = v;
                } else {
                    s->sb_samples[0][j][i] = 0;
                    s->sb_samples[1][j][i] = 0;
                }
            }
        }
        return 12;
    }
    
    /* bitrate is in kb/s */
    int l2_select_table(int bitrate, int nb_channels, int freq, int lsf)
    {
        int ch_bitrate, table;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        
    
        ch_bitrate = bitrate / nb_channels;
        if (!lsf) {
            if ((freq == 48000 && ch_bitrate >= 56) ||
                (ch_bitrate >= 56 && ch_bitrate <= 80)) 
                table = 0;
            else if (freq != 48000 && ch_bitrate >= 96) 
                table = 1;
            else if (freq != 32000 && ch_bitrate <= 48) 
                table = 2;
            else 
                table = 3;
        } else {
            table = 4;
        }
        return table;
    }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    static int mp_decode_layer2(MPADecodeContext *s)
    {
        int sblimit; /* number of used subbands */
        const unsigned char *alloc_table;
        int table, bit_alloc_bits, i, j, ch, bound, v;
        unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT];
        unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT];
        unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3], *sf;
        int scale, qindex, bits, steps, k, l, m, b;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* select decoding table */
        table = l2_select_table(s->bit_rate / 1000, s->nb_channels, 
                                s->sample_rate, s->lsf);
        sblimit = sblimit_table[table];
        alloc_table = alloc_tables[table];
    
        if (s->mode == MPA_JSTEREO) 
            bound = (s->mode_ext + 1) * 4;
        else
            bound = sblimit;
    
        dprintf("bound=%d sblimit=%d\n", bound, sblimit);
        /* parse bit allocation */
        j = 0;
        for(i=0;i<bound;i++) {
            bit_alloc_bits = alloc_table[j];
            for(ch=0;ch<s->nb_channels;ch++) {
                bit_alloc[ch][i] = get_bits(&s->gb, bit_alloc_bits);
            }
            j += 1 << bit_alloc_bits;
        }
        for(i=bound;i<sblimit;i++) {
            bit_alloc_bits = alloc_table[j];
            v = get_bits(&s->gb, bit_alloc_bits);
            bit_alloc[0][i] = v;
            bit_alloc[1][i] = v;
            j += 1 << bit_alloc_bits;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
    #ifdef DEBUG
        {
            for(ch=0;ch<s->nb_channels;ch++) {
                for(i=0;i<sblimit;i++)
                    printf(" %d", bit_alloc[ch][i]);
                printf("\n");
            }
        }
    #endif
    
        /* scale codes */
        for(i=0;i<sblimit;i++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                if (bit_alloc[ch][i]) 
                    scale_code[ch][i] = get_bits(&s->gb, 2);
            }
        }
        
        /* scale factors */
        for(i=0;i<sblimit;i++) {
            for(ch=0;ch<s->nb_channels;ch++) {
                if (bit_alloc[ch][i]) {
                    sf = scale_factors[ch][i];
                    switch(scale_code[ch][i]) {
                    default:
                    case 0:
                        sf[0] = get_bits(&s->gb, 6);
                        sf[1] = get_bits(&s->gb, 6);
                        sf[2] = get_bits(&s->gb, 6);
                        break;
                    case 2:
                        sf[0] = get_bits(&s->gb, 6);
                        sf[1] = sf[0];
                        sf[2] = sf[0];
                        break;
                    case 1:
                        sf[0] = get_bits(&s->gb, 6);
                        sf[2] = get_bits(&s->gb, 6);
                        sf[1] = sf[0];
                        break;
                    case 3:
                        sf[0] = get_bits(&s->gb, 6);
                        sf[2] = get_bits(&s->gb, 6);
                        sf[1] = sf[2];
                        break;
                    }
                }
            }
        }
    
    #ifdef DEBUG
        for(ch=0;ch<s->nb_channels;ch++) {
            for(i=0;i<sblimit;i++) {
                if (bit_alloc[ch][i]) {
                    sf = scale_factors[ch][i];
                    printf(" %d %d %d", sf[0], sf[1], sf[2]);
                } else {
                    printf(" -");
                }
            }
            printf("\n");
        }
    #endif
    
        /* samples */
        for(k=0;k<3;k++) {
            for(l=0;l<12;l+=3) {
                j = 0;
                for(i=0;i<bound;i++) {
                    bit_alloc_bits = alloc_table[j];
                    for(ch=0;ch<s->nb_channels;ch++) {
                        b = bit_alloc[ch][i];
                        if (b) {
                            scale = scale_factors[ch][i][k];
                            qindex = alloc_table[j+b];
                            bits = quant_bits[qindex];
                            if (bits < 0) {
                                /* 3 values at the same time */
                                v = get_bits(&s->gb, -bits);
                                steps = quant_steps[qindex];
                                s->sb_samples[ch][k * 12 + l + 0][i] = 
                                    l2_unscale_group(steps, v % steps, scale);
                                v = v / steps;
                                s->sb_samples[ch][k * 12 + l + 1][i] = 
                                    l2_unscale_group(steps, v % steps, scale);
                                v = v / steps;
                                s->sb_samples[ch][k * 12 + l + 2][i] = 
                                    l2_unscale_group(steps, v, scale);
                            } else {
                                for(m=0;m<3;m++) {
                                    v = get_bits(&s->gb, bits);
                                    v = l1_unscale(bits - 1, v, scale);
                                    s->sb_samples[ch][k * 12 + l + m][i] = v;
                                }
                            }
                        } else {
                            s->sb_samples[ch][k * 12 + l + 0][i] = 0;
                            s->sb_samples[ch][k * 12 + l + 1][i] = 0;
                            s->sb_samples[ch][k * 12 + l + 2][i] = 0;
                        }
                    }
                    /* next subband in alloc table */
                    j += 1 << bit_alloc_bits; 
                }
                /* XXX: find a way to avoid this duplication of code */
                for(i=bound;i<sblimit;i++) {
                    bit_alloc_bits = alloc_table[j];
                    b = bit_alloc[0][i];
                    if (b) {
                        int mant, scale0, scale1;
                        scale0 = scale_factors[0][i][k];
                        scale1 = scale_factors[1][i][k];
                        qindex = alloc_table[j+b];
                        bits = quant_bits[qindex];
                        if (bits < 0) {
                            /* 3 values at the same time */
                            v = get_bits(&s->gb, -bits);
                            steps = quant_steps[qindex];
                            mant = v % steps;
                            v = v / steps;
                            s->sb_samples[0][k * 12 + l + 0][i] = 
                                l2_unscale_group(steps, mant, scale0);
                            s->sb_samples[1][k * 12 + l + 0][i] = 
                                l2_unscale_group(steps, mant, scale1);
                            mant = v % steps;
                            v = v / steps;
                            s->sb_samples[0][k * 12 + l + 1][i] = 
                                l2_unscale_group(steps, mant, scale0);
                            s->sb_samples[1][k * 12 + l + 1][i] = 
                                l2_unscale_group(steps, mant, scale1);
                            s->sb_samples[0][k * 12 + l + 2][i] = 
                                l2_unscale_group(steps, v, scale0);
                            s->sb_samples[1][k * 12 + l + 2][i] = 
                                l2_unscale_group(steps, v, scale1);
                        } else {
                            for(m=0;m<3;m++) {
                                mant = get_bits(&s->gb, bits);
                                s->sb_samples[0][k * 12 + l + m][i] = 
                                    l1_unscale(bits - 1, mant, scale0);
                                s->sb_samples[1][k * 12 + l + m][i] = 
                                    l1_unscale(bits - 1, mant, scale1);
                            }
                        }
                    } else {
                        s->sb_samples[0][k * 12 + l + 0][i] = 0;
                        s->sb_samples[0][k * 12 + l + 1][i] = 0;
                        s->sb_samples[0][k * 12 + l + 2][i] = 0;
                        s->sb_samples[1][k * 12 + l + 0][i] = 0;
                        s->sb_samples[1][k * 12 + l + 1][i] = 0;
                        s->sb_samples[1][k * 12 + l + 2][i] = 0;
                    }
                    /* next subband in alloc table */
                    j += 1 << bit_alloc_bits; 
                }
                /* fill remaining samples to zero */
                for(i=sblimit;i<SBLIMIT;i++) {
                    for(ch=0;ch<s->nb_channels;ch++) {
                        s->sb_samples[ch][k * 12 + l + 0][i] = 0;
                        s->sb_samples[ch][k * 12 + l + 1][i] = 0;
                        s->sb_samples[ch][k * 12 + l + 2][i] = 0;
                    }
                }
            }
        }
        return 3 * 12;
    
     * Seek back in the stream for backstep bytes (at most 511 bytes)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
     */
    
    static void seek_to_maindata(MPADecodeContext *s, long backstep)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        UINT8 *ptr;
    
        /* compute current position in stream */
    
    #ifdef ALT_BITSTREAM_READER
        ptr = s->gb.buffer + (s->gb.index>>3);
    #else
    
        ptr = s->gb.buf_ptr - (s->gb.bit_cnt >> 3);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* copy old data before current one */
        ptr -= backstep;
    
        memcpy(ptr, s->inbuf1[s->inbuf_index ^ 1] + 
               BACKSTEP_SIZE + s->old_frame_size - backstep, backstep);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* init get bits again */
    
        init_get_bits(&s->gb, ptr, s->frame_size + backstep);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        /* prepare next buffer */
        s->inbuf_index ^= 1;
        s->inbuf = &s->inbuf1[s->inbuf_index][BACKSTEP_SIZE];
        s->old_frame_size = s->frame_size;
    }
    
    static inline void lsf_sf_expand(int *slen,
                                     int sf, int n1, int n2, int n3)
    {
        if (n3) {
            slen[3] = sf % n3;
            sf /= n3;
        } else {
            slen[3] = 0;
        }
        if (n2) {
            slen[2] = sf % n2;
            sf /= n2;
        } else {
            slen[2] = 0;
        }
        slen[1] = sf % n1;
        sf /= n1;
        slen[0] = sf;
    }
    
    static void exponents_from_scale_factors(MPADecodeContext *s, 
                                             GranuleDef *g,
                                             INT16 *exponents)
    {
        const UINT8 *bstab, *pretab;
        int len, i, j, k, l, v0, shift, gain, gains[3];
        INT16 *exp_ptr;
    
        exp_ptr = exponents;
        gain = g->global_gain - 210;
        shift = g->scalefac_scale + 1;
    
        bstab = band_size_long[s->sample_rate_index];
        pretab = mpa_pretab[g->preflag];
        for(i=0;i<g->long_end;i++) {
            v0 = gain - ((g->scale_factors[i] + pretab[i]) << shift);
            len = bstab[i];
            for(j=len;j>0;j--)
                *exp_ptr++ = v0;
        }
    
        if (g->short_start < 13) {
            bstab = band_size_short[s->sample_rate_index];
            gains[0] = gain - (g->subblock_gain[0] << 3);
            gains[1] = gain - (g->subblock_gain[1] << 3);
            gains[2] = gain - (g->subblock_gain[2] << 3);
            k = g->long_end;
            for(i=g->short_start;i<13;i++) {
                len = bstab[i];
                for(l=0;l<3;l++) {
                    v0 = gains[l] - (g->scale_factors[k++] << shift);
                    for(j=len;j>0;j--)
                    *exp_ptr++ = v0;
                }
            }
        }
    }
    
    /* handle n = 0 too */
    static inline int get_bitsz(GetBitContext *s, int n)
    {
        if (n == 0)
            return 0;
        else
            return get_bits(s, n);
    }
    
    static int huffman_decode(MPADecodeContext *s, GranuleDef *g,
                              INT16 *exponents, int end_pos)
    {
        int s_index;
        int linbits, code, x, y, l, v, i, j, k, pos;
        UINT8 *last_buf_ptr;
        UINT32 last_bit_buf;
        int last_bit_cnt;
        VLC *vlc;
        UINT8 *code_table;
    
        /* low frequencies (called big values) */
        s_index = 0;
        for(i=0;i<3;i++) {
            j = g->region_size[i];
            if (j == 0)
                continue;
            /* select vlc table */
            k = g->table_select[i];
            l = mpa_huff_data[k][0];
            linbits = mpa_huff_data[k][1];
            vlc = &huff_vlc[l];
            code_table = huff_code_table[l];
    
            /* read huffcode and compute each couple */
            for(;j>0;j--) {
                if (get_bits_count(&s->gb) >= end_pos)
                    break;
                if (code_table) {
                    code = get_vlc(&s->gb, vlc);
                    if (code < 0)
                        return -1;
                    y = code_table[code];
                    x = y >> 4;
                    y = y & 0x0f;
                } else {
                    x = 0;
                    y = 0;
                }
                dprintf("region=%d n=%d x=%d y=%d exp=%d\n", 
                        i, g->region_size[i] - j, x, y, exponents[s_index]);
                if (x) {
                    if (x == 15)
                        x += get_bitsz(&s->gb, linbits);
                    v = l3_unscale(x, exponents[s_index]);
                    if (get_bits1(&s->gb))
                        v = -v;
                } else {
                    v = 0;
                }
                g->sb_hybrid[s_index++] = v;
                if (y) {
                    if (y == 15)
                        y += get_bitsz(&s->gb, linbits);
                    v = l3_unscale(y, exponents[s_index]);
                    if (get_bits1(&s->gb))
                        v = -v;
                } else {
                    v = 0;
                }
                g->sb_hybrid[s_index++] = v;
            }
        }
                
        /* high frequencies */
        vlc = &huff_quad_vlc[g->count1table_select];
        last_buf_ptr = NULL;
        last_bit_buf = 0;
        last_bit_cnt = 0;
        while (s_index <= 572) {
            pos = get_bits_count(&s->gb);
            if (pos >= end_pos) {
                if (pos > end_pos && last_buf_ptr != NULL) {
                    /* some encoders generate an incorrect size for this
                       part. We must go back into the data */
                    s_index -= 4;
    
    #ifdef ALT_BITSTREAM_READER
                    s->gb.buffer = last_buf_ptr;
                    s->gb.index = last_bit_cnt;
    #else
    
                    s->gb.buf_ptr = last_buf_ptr;
                    s->gb.bit_buf = last_bit_buf;
                    s->gb.bit_cnt = last_bit_cnt;
    
    #ifdef ALT_BITSTREAM_READER
            last_buf_ptr = s->gb.buffer;
            last_bit_cnt = s->gb.index;
    #else
    
            last_buf_ptr = s->gb.buf_ptr;
            last_bit_buf = s->gb.bit_buf;
            last_bit_cnt = s->gb.bit_cnt;
    
            
            code = get_vlc(&s->gb, vlc);
            dprintf("t=%d code=%d\n", g->count1table_select, code);
            if (code < 0)
                return -1;
            for(i=0;i<4;i++) {
                if (code & (8 >> i)) {
                    /* non zero value. Could use a hand coded function for
                       'one' value */
                    v = l3_unscale(1, exponents[s_index]);
                    if(get_bits1(&s->gb))
                        v = -v;
                } else {
                    v = 0;
                }
                g->sb_hybrid[s_index++] = v;
            }
        }
        while (s_index < 576)
            g->sb_hybrid[s_index++] = 0;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        return 0;
    }
    
    
    /* Reorder short blocks from bitstream order to interleaved order. It
       would be faster to do it in parsing, but the code would be far more
       complicated */
    static void reorder_block(MPADecodeContext *s, GranuleDef *g)
    {
        int i, j, k, len;
        INT32 *ptr, *dst, *ptr1;
        INT32 tmp[576];
    
        if (g->block_type != 2)
            return;
    
        if (g->switch_point) {
            if (s->sample_rate_index != 8) {
                ptr = g->sb_hybrid + 36;
            } else {
                ptr = g->sb_hybrid + 48;
            }
        } else {
            ptr = g->sb_hybrid;
        }
        
        for(i=g->short_start;i<13;i++) {
            len = band_size_short[s->sample_rate_index][i];
            ptr1 = ptr;
            for(k=0;k<3;k++) {
                dst = tmp + k;
                for(j=len;j>0;j--) {
                    *dst = *ptr++;
                    dst += 3;
                }
            }
            memcpy(ptr1, tmp, len * 3 * sizeof(INT32));
        }
    }
    
    #define ISQRT2 FIXR(0.70710678118654752440)
    
    static void compute_stereo(MPADecodeContext *s,
                               GranuleDef *g0, GranuleDef *g1)
    {
        int i, j, k, l;
        INT32 v1, v2;
        int sf_max, tmp0, tmp1, sf, len, non_zero_found;
        INT32 (*is_tab)[16];
        INT32 *tab0, *tab1;
        int non_zero_found_short[3];
    
        /* intensity stereo */
        if (s->mode_ext & MODE_EXT_I_STEREO) {
            if (!s->lsf) {
                is_tab = is_table;
                sf_max = 7;
            } else {
                is_tab = is_table_lsf[g1->scalefac_compress & 1];
                sf_max = 16;
            }
                
            tab0 = g0->sb_hybrid + 576;
            tab1 = g1->sb_hybrid + 576;
    
            non_zero_found_short[0] = 0;
            non_zero_found_short[1] = 0;
            non_zero_found_short[2] = 0;
            k = (13 - g1->short_start) * 3 + g1->long_end - 3;
            for(i = 12;i >= g1->short_start;i--) {
                /* for last band, use previous scale factor */
                if (i != 11)
                    k -= 3;
                len = band_size_short[s->sample_rate_index][i];
                for(l=2;l>=0;l--) {
                    tab0 -= len;
                    tab1 -= len;
                    if (!non_zero_found_short[l]) {
                        /* test if non zero band. if so, stop doing i-stereo */
                        for(j=0;j<len;j++) {
                            if (tab1[j] != 0) {
                                non_zero_found_short[l] = 1;
                                goto found1;
                            }
                        }
                        sf = g1->scale_factors[k + l];
                        if (sf >= sf_max)
                            goto found1;
    
                        v1 = is_tab[0][sf];
                        v2 = is_tab[1][sf];
                        for(j=0;j<len;j++) {
                            tmp0 = tab0[j];
                            tab0[j] = MULL(tmp0, v1);
                            tab1[j] = MULL(tmp0, v2);
                        }
                    } else {
                    found1:
                        if (s->mode_ext & MODE_EXT_MS_STEREO) {
                            /* lower part of the spectrum : do ms stereo
                               if enabled */
                            for(j=0;j<len;j++) {
                                tmp0 = tab0[j];
                                tmp1 = tab1[j];
                                tab0[j] = MULL(tmp0 + tmp1, ISQRT2);
                                tab1[j] = MULL(tmp0 - tmp1, ISQRT2);
                            }
                        }
                    }
                }
            }
    
            non_zero_found = non_zero_found_short[0] | 
                non_zero_found_short[1] | 
                non_zero_found_short[2];
    
            for(i = g1->long_end - 1;i >= 0;i--) {
                len = band_size_long[s->sample_rate_index][i];
                tab0 -= len;
                tab1 -= len;
                /* test if non zero band. if so, stop doing i-stereo */
                if (!non_zero_found) {
                    for(j=0;j<len;j++) {
                        if (tab1[j] != 0) {
                            non_zero_found = 1;
                            goto found2;
                        }
                    }
                    /* for last band, use previous scale factor */
                    k = (i == 21) ? 20 : i;
                    sf = g1->scale_factors[k];
                    if (sf >= sf_max)
                        goto found2;
                    v1 = is_tab[0][sf];
                    v2 = is_tab[1][sf];
                    for(j=0;j<len;j++) {
                        tmp0 = tab0[j];
                        tab0[j] = MULL(tmp0, v1);
                        tab1[j] = MULL(tmp0, v2);
                    }
                } else {
                found2:
                    if (s->mode_ext & MODE_EXT_MS_STEREO) {
                        /* lower part of the spectrum : do ms stereo
                           if enabled */
                        for(j=0;j<len;j++) {
                            tmp0 = tab0[j];
                            tmp1 = tab1[j];
                            tab0[j] = MULL(tmp0 + tmp1, ISQRT2);
                            tab1[j] = MULL(tmp0 - tmp1, ISQRT2);
                        }
                    }
                }
            }
        } else if (s->mode_ext & MODE_EXT_MS_STEREO) {
            /* ms stereo ONLY */
            /* NOTE: the 1/sqrt(2) normalization factor is included in the
               global gain */
            tab0 = g0->sb_hybrid;
            tab1 = g1->sb_hybrid;
            for(i=0;i<576;i++) {
                tmp0 = tab0[i];
                tmp1 = tab1[i];
                tab0[i] = tmp0 + tmp1;
                tab1[i] = tmp0 - tmp1;
            }
        }
    }
    
    static void compute_antialias(MPADecodeContext *s,
                                  GranuleDef *g)
    {
        INT32 *ptr, *p0, *p1, *csa;
        int n, tmp0, tmp1, i, j;
    
        /* we antialias only "long" bands */
        if (g->block_type == 2) {
            if (!g->switch_point)
                return;
            /* XXX: check this for 8000Hz case */
            n = 1;
        } else {
            n = SBLIMIT - 1;
        }
        
        ptr = g->sb_hybrid + 18;
        for(i = n;i > 0;i--) {
            p0 = ptr - 1;
            p1 = ptr;
            csa = &csa_table[0][0];
            for(j=0;j<8;j++) {
                tmp0 = *p0;
                tmp1 = *p1;
                *p0 = FRAC_RND(MUL64(tmp0, csa[0]) - MUL64(tmp1, csa[1]));
                *p1 = FRAC_RND(MUL64(tmp0, csa[1]) + MUL64(tmp1, csa[0]));
                p0--;
                p1++;
                csa += 2;
            }
            ptr += 18;
        }
    }
    
    static void compute_imdct(MPADecodeContext *s,
                              GranuleDef *g, 
                              INT32 *sb_samples,
                              INT32 *mdct_buf)
    {
        INT32 *ptr, *win, *win1, *buf, *buf2, *out_ptr, *ptr1;
        INT32 in[6];
        INT32 out[36];
        INT32 out2[12];
        int i, j, k, mdct_long_end, v, sblimit;
    
        /* find last non zero block */
        ptr = g->sb_hybrid + 576;
        ptr1 = g->sb_hybrid + 2 * 18;
        while (ptr >= ptr1) {
            ptr -= 6;
            v = ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5];
            if (v != 0)
                break;
        }
        sblimit = ((ptr - g->sb_hybrid) / 18) + 1;
    
        if (g->block_type == 2) {
            /* XXX: check for 8000 Hz */
            if (g->switch_point)
                mdct_long_end = 2;
            else
                mdct_long_end = 0;
        } else {
            mdct_long_end = sblimit;
        }
    
        buf = mdct_buf;
        ptr = g->sb_hybrid;
        for(j=0;j<mdct_long_end;j++) {
            imdct36(out, ptr);
            /* apply window & overlap with previous buffer */
            out_ptr = sb_samples + j;
            /* select window */
            if (g->switch_point && j < 2)
                win1 = mdct_win[0];
            else
                win1 = mdct_win[g->block_type];
            /* select frequency inversion */
            win = win1 + ((4 * 36) & -(j & 1));
            for(i=0;i<18;i++) {
                *out_ptr = MULL(out[i], win[i]) + buf[i];
                buf[i] = MULL(out[i + 18], win[i + 18]);
                out_ptr += SBLIMIT;
            }
            ptr += 18;
            buf += 18;
        }
        for(j=mdct_long_end;j<sblimit;j++) {
            for(i=0;i<6;i++) {
                out[i] = 0;
                out[6 + i] = 0;
                out[30+i] = 0;
            }
            /* select frequency inversion */
            win = mdct_win[2] + ((4 * 36) & -(j & 1));
            buf2 = out + 6;
            for(k=0;k<3;k++) {
                /* reorder input for short mdct */
                ptr1 = ptr + k;
                for(i=0;i<6;i++) {
                    in[i] = *ptr1;
                    ptr1 += 3;
                }
                imdct12(out2, in);
                /* apply 12 point window and do small overlap */
                for(i=0;i<6;i++) {
                    buf2[i] = MULL(out2[i], win[i]) + buf2[i];
                    buf2[i + 6] = MULL(out2[i + 6], win[i + 6]);
                }
                buf2 += 6;
            }
            /* overlap */
            out_ptr = sb_samples + j;
            for(i=0;i<18;i++) {
                *out_ptr = out[i] + buf[i];
                buf[i] = out[i + 18];
                out_ptr += SBLIMIT;
            }
            ptr += 18;
            buf += 18;
        }
        /* zero bands */
        for(j=sblimit;j<SBLIMIT;j++) {
            /* overlap */
            out_ptr = sb_samples + j;
            for(i=0;i<18;i++) {
                *out_ptr = buf[i];
                buf[i] = 0;
                out_ptr += SBLIMIT;
            }
            buf += 18;
        }
    }
    
    
    #if defined(DEBUG)
    
    void sample_dump(int fnum, INT32 *tab, int n)
    {
        static FILE *files[16], *f;
        char buf[512];
    
            sprintf(buf, "/tmp/out%d.%s.pcm", 
                    fnum, 
    #ifdef USE_HIGHPRECISION
                    "hp"
    #else
                    "lp"
    #endif
                    );
    
            f = fopen(buf, "w");
            if (!f)
                return;
            files[fnum] = f;
        }
        
        if (fnum == 0) {
            static int pos = 0;
            printf("pos=%d\n", pos);
            for(i=0;i<n;i++) {
    
                printf(" %0.4f", (double)tab[i] / FRAC_ONE);
    
        for(i=0;i<n;i++) {
            /* normalize to 23 frac bits */
            v = tab[i] << (23 - FRAC_BITS);
            fwrite(&v, 1, sizeof(INT32), f);
        }