videoeditorengine/mp3aacManipLib/MP3Gain/src/layer3.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/mp3aacManipLib/MP3Gain/src/layer3.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,733 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+/**************************************************************************
+layer3.cpp - MPEG-1, MPEG-2 LSF and MPEG-2.5 layer III bitstream parsing.
+
+  Author(s): Juha Ojanpera
+  Copyright (c) 1999-2004 by Nokia Research Center, Speech and Audio Systems.
+*************************************************************************/
+
+/**************************************************************************
+External Objects Needed
+*************************************************************************/
+
+/*-- Project Headers --*/
+#include "mpaud.h"
+#include "mpheader.h"
+#include "mp3tables.h"
+
+
+
+//uint8 scalefac_buffer[54];
+
+/**************************************************************************
+Title        : III_get_side_info
+
+  Purpose      : Reads Layer III side information from the bitstream.
+  
+    Usage        : y = III_get_side_info(mp, bs)
+    
+      Input        : mp - MP3 decoder handle
+      bs - input bitstream
+      
+        Output       : y - TRUE on success, FALSE otherwise
+        
+          Author(s)    : Juha Ojanpera
+*************************************************************************/
+
+
+BOOL
+III_get_side_info(CMP_Stream *mp, TBitStream *bs)
+{
+    uint16 i, j, k, flag;
+    TGranule_Info *gr_info;
+    
+    /*-- Get the protected bits for the crc error checking. --*/
+    if(bs->dsp_buffer)
+    {
+        int16 sideLen = (GetSideInfoSlots(mp->header) >> 1) + 1;
+        
+        if(bs->bit_counter == 8) 
+            for(i = bs->buf_index, j = 0; j < sideLen; i++, j++)
+            {
+                DSP_BYTE wTmp = bs->dsp_buffer[MOD_OPCODE(i, bs->buf_mask)] << 8;
+                wTmp |= (bs->dsp_buffer[MOD_OPCODE((i + 1), bs->buf_mask)] >> 8) & 255;
+                mp->mp3_crc.crc_payload[j + 2] = wTmp;
+            }
+            else
+                for(i = bs->buf_index, j = 0; j < sideLen; i++, j++)
+                    mp->mp3_crc.crc_payload[j + 2] = bs->dsp_buffer[MOD_OPCODE(i, bs->buf_mask)];
+    }
+    
+    if(version(mp->header) == MPEG_AUDIO_ID) /* MPEG-1 */
+    {
+        mp->side_info->main_data_begin = BsGetBits(bs, 9);
+        if(channels(mp->header) == 1)
+        {
+            mp->side_info->private_bits = BsGetBits(bs, 5);
+            for(i = 0; i < 4; i++)
+                mp->side_info->scfsi[0][i] = BsGetBits(bs, 1);
+        }
+        else
+        {
+            mp->side_info->private_bits = BsGetBits(bs, 3);
+            for(i = 0; i < 2; i++)
+                for(j = 0; j < 4; j++)
+                    mp->side_info->scfsi[i][j] = int16(BsGetBits(bs, 1));
+        }
+        
+        for(i = 0; i < 2; i++)
+        {
+            for(j = 0; j < channels(mp->header); j++)
+            {
+                gr_info = mp->side_info->ch_info[j]->gr_info[i];
+                
+                gr_info->part2_3_length = BsGetBits(bs, 12);
+                gr_info->big_values = BsGetBits(bs, 9) << 1;
+                gr_info->global_gain = BsGetBits(bs, 8);
+                gr_info->scalefac_compress = BsGetBits(bs, 4);
+                
+                gr_info->flags = 0;
+                gr_info->flags |= (BsGetBits(bs, 1)) ? WINDOW_SWITCHING_FLAG : 0;
+                
+                if(win_switch(gr_info))
+                {
+                    /* block_type */
+                    gr_info->flags |= BsGetBits(bs, 2);
+                    
+                    /* mixed_block_flag */
+                    flag = BsGetBits(bs, 1);
+                    gr_info->flags |= (flag) ? MIXED_BLOCK_FLAG : 0;
+                    
+                    for(k = 0; k < 2; k++)
+                        gr_info->table_select[k] = BsGetBits(bs, 5);
+                    
+                    for(k = 0; k < 3; k++)
+                        gr_info->subblock_gain[k] = BsGetBits(bs, 3);
+                    
+                    /* Set region_count parameters since they are implicit in this case. */
+                    if((gr_info->flags & 3) == 0)
+                        return (FALSE); /* This will trigger resync */
+                    else
+                        if(short_block(gr_info) && !mixed_block(gr_info))
+                        {
+                            gr_info->block_mode = SHORT_BLOCK_MODE;
+                            gr_info->region0_count = 7;
+                        }
+                        else
+                        {
+                            if(short_block(gr_info) && mixed_block(gr_info))
+                                return (FALSE); /* mixed block are not allowed => resync */
+                            else
+                                gr_info->block_mode = LONG_BLOCK_MODE;
+                            
+                            gr_info->region0_count = 7;
+                        }
+                        
+                    gr_info->region1_count = 20 - gr_info->region0_count;
+                }
+                else
+                {
+                    gr_info->block_mode = LONG_BLOCK_MODE;
+                    for(k = 0; k < 3; k++)
+                        gr_info->table_select[k] = BsGetBits(bs, 5);
+                    gr_info->region0_count = BsGetBits(bs, 4);
+                    gr_info->region1_count = BsGetBits(bs, 3);
+                    
+                    gr_info->flags &= ~(uint32)3; /* block_type == 0 (LONG) */
+                }
+                
+                flag = BsGetBits(bs, 3);
+                gr_info->flags |= (flag & 4) ? PRE_FLAG : 0;
+                gr_info->flags |= (flag & 2) ? SCALEFAC_SCALE : 0;
+                gr_info->flags |= (flag & 1) ? COUNT_1_TABLE_SELECT : 0;
+            }
+        }
+    }
+    else /* MPEG-2 LSF and MPEG-2.5 */
+    {
+        mp->side_info->main_data_begin = BsGetBits(bs, 8);
+        
+        if(channels(mp->header) == 1)
+            mp->side_info->private_bits = BsGetBits(bs, 1);
+        else
+            mp->side_info->private_bits = BsGetBits(bs, 2);
+        
+        for(i = 0; i < channels(mp->header); i++)
+        {
+            gr_info = mp->side_info->ch_info[i]->gr_info[0];
+            
+            gr_info->part2_3_length = BsGetBits(bs, 12);
+            gr_info->big_values = BsGetBits(bs, 9) << 1;
+            gr_info->global_gain = BsGetBits(bs, 8);
+            gr_info->scalefac_compress = BsGetBits(bs, 9);
+            gr_info->flags = 0;
+            gr_info->flags |= (BsGetBits(bs, 1)) ? WINDOW_SWITCHING_FLAG : 0;
+            
+            if(win_switch(gr_info))
+            {
+                /* block_type */
+                gr_info->flags |= BsGetBits(bs, 2);
+                
+                /* mixed_block_flag */
+                flag = BsGetBits(bs, 1);
+                gr_info->flags |= (flag) ? MIXED_BLOCK_FLAG : 0;
+                
+                for(k = 0; k < 2; k++)
+                    gr_info->table_select[k] = BsGetBits(bs, 5);
+                
+                for(k = 0; k < 3; k++)
+                    gr_info->subblock_gain[k] = BsGetBits(bs, 3);
+                
+                /* Set region_count parameters since they are implicit in this case. */
+                if((gr_info->flags & 3) == 0)
+                    return (FALSE);
+                else
+                    if(short_block(gr_info) && !mixed_block(gr_info))
+                    {
+                        gr_info->block_mode = SHORT_BLOCK_MODE;
+                        gr_info->region0_count = 5;
+                    }
+                    else
+                    {
+                        if(short_block(gr_info) && mixed_block(gr_info))
+                            return (FALSE);
+                        else
+                            gr_info->block_mode = LONG_BLOCK_MODE;
+                        
+                        gr_info->region0_count = 7;
+                    }
+                    
+                gr_info->region1_count = 20 - gr_info->region0_count;
+            }
+            else
+            {
+                gr_info->block_mode = LONG_BLOCK_MODE;
+                for(k = 0; k < 3; k++)
+                    gr_info->table_select[k] = BsGetBits(bs, 5);
+                gr_info->region0_count = BsGetBits(bs, 4);
+                gr_info->region1_count = BsGetBits(bs, 3);
+                
+                gr_info->flags &= ~(uint32)3; /* block_type == 0 (LONG) */
+            }
+            
+            flag = BsGetBits(bs, 2);
+            gr_info->flags |= (flag & 2) ? SCALEFAC_SCALE : 0;
+            gr_info->flags |= (flag & 1) ? COUNT_1_TABLE_SELECT : 0;
+        }
+    }
+    
+    return (TRUE);
+}
+
+/*
+* Writes layer 3 side information (excluding granule specific info) 
+* to the specified bitstream. For writing granule specific 
+* parameters 'L3WriteGranule()' function should be used.
+*/
+INLINE void
+L3WriteCommonSideInfo(TBitStream *bs, CIII_Side_Info *sideInfo, TMPEG_Header *header)
+{
+    int16 bits;
+    uint32 dWord;
+    
+    bits = 9;
+    dWord = sideInfo->main_data_begin;
+    
+    /*-- MPEG-1. --*/
+    if(version(header) == MPEG_AUDIO_ID)
+    {
+        if(channels(header) == 1)
+        {
+            bits = 18;
+            dWord <<= 5; dWord |= sideInfo->private_bits;
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][0];
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][1];
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][2];
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][3];
+        }
+        else
+        {
+            bits = 20;
+            dWord <<= 3; dWord |= sideInfo->private_bits;
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][0];
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][1];
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][2];
+            dWord <<= 1; dWord |= sideInfo->scfsi[0][3];
+            dWord <<= 1; dWord |= sideInfo->scfsi[1][0];
+            dWord <<= 1; dWord |= sideInfo->scfsi[1][1];
+            dWord <<= 1; dWord |= sideInfo->scfsi[1][2];
+            dWord <<= 1; dWord |= sideInfo->scfsi[1][3];
+        }
+    }
+    
+    /*-- MPEG-2 LSF, MPEG-2.5. --*/
+    else
+    {
+        if(channels(header) == 1)
+        { bits = 9;  dWord <<= 1; }
+        else 
+        { bits = 10; dWord <<= 2; }
+        
+        dWord |= sideInfo->private_bits;
+    }
+    
+    BsPutBits(bs, bits, dWord);
+}
+
+/*
+* Writes granule specific parameters to the specified bitstream.
+* Please note that the MPEG frame may contain more than one granule
+* depending on the number of channels and version. So this function
+* may need to be called multiple times.
+*/
+INLINE void
+L3WriteGranule(TBitStream *bs, TGranule_Info *gr_info, BOOL mpeg1)
+{
+    uint32 dWord;
+    
+    dWord = gr_info->part2_3_length << 9;
+    dWord |= gr_info->big_values >> 1;
+    dWord <<= 8; dWord |= gr_info->global_gain;
+    
+    BsPutBits(bs, 29, dWord);
+    
+    dWord = gr_info->scalefac_compress << 1;
+    if(win_switch(gr_info))
+    {
+        dWord |= 1;
+        dWord <<= 2; dWord |= (gr_info->flags & 3);
+        dWord <<= 1; if(mixed_block(gr_info)) dWord |= 1;
+        dWord <<= 5; dWord |= gr_info->table_select[0];
+        dWord <<= 5; dWord |= gr_info->table_select[1];
+        dWord <<= 3; dWord |= gr_info->subblock_gain[0];
+        dWord <<= 3; dWord |= gr_info->subblock_gain[1];
+        dWord <<= 3; dWord |= gr_info->subblock_gain[2];
+    }
+    else
+    {
+        dWord <<= 5; dWord |= gr_info->table_select[0];
+        dWord <<= 5; dWord |= gr_info->table_select[1];
+        dWord <<= 5; dWord |= gr_info->table_select[2];
+        dWord <<= 4; dWord |= gr_info->region0_count; 
+        dWord <<= 3; dWord |= gr_info->region1_count;
+    }
+    
+    if(mpeg1) { dWord <<= 1; if(pre_flag(gr_info)) dWord |= 1; }
+    else      { BsPutBits(bs, 32, dWord); dWord = 0; }
+    
+    dWord <<= 1; if(scalefac_scale(gr_info)) dWord |= 1;
+    dWord <<= 1; if(gr_info->flags & COUNT_1_TABLE_SELECT) dWord |= 1;
+    
+    BsPutBits(bs, (mpeg1) ? 30 : 2, dWord);
+}
+
+/*
+* Writes layer 3 side info to the specified bitstream. The side info
+* in this context includes the header and the actual side info
+* parameters.
+*/
+void
+L3WriteSideInfo(TBitStream *bs, CIII_Side_Info *sideInfo, TMPEG_Header *header)
+{
+    BOOL mpeg1;
+    int16 i, j, max_gr;
+    
+    mpeg1 = (version(header) == MPEG_AUDIO_ID) ? TRUE : FALSE;
+    max_gr = (mpeg1) ? 2 : 1;
+    
+    /*-- Write common side info. --*/
+    L3WriteCommonSideInfo(bs, sideInfo, header);
+    
+    /*-- Write granule parameters. --*/
+    for(i = 0; i < max_gr; i++)
+        for(j = 0; j < channels(header); j++)
+        {
+            TGranule_Info *gr_info = sideInfo->ch_info[j]->gr_info[i];
+            L3WriteGranule(bs, gr_info, mpeg1);
+        }
+}
+
+/**************************************************************************
+Title        : III_get_LSF_scale_data
+
+  Purpose      : Decodes scalafactors of MPEG-2 LSF and MPEG-2.5 bitstreams.
+  
+    Usage        : III_get_LSF_scale_data(mp, gr, ch)
+    
+      Input        : mp - MP3 stream parameters
+      gr - granule number
+      ch - channel number (left or right)
+      
+        Explanation  : -
+        
+          Author(s)    : Juha Ojanpera
+*************************************************************************/
+
+static void
+III_get_LSF_scale_data(CMP_Stream *mp, int16 gr, int16 ch, uint8* scalefac_buffer)
+{
+    int16 i, j, k, m = 0;
+    int16 blocktypenumber = 0, blocknumber = 0;
+    int16 scalefac_comp, int_scalefac_comp, new_slen[4] = {0, 0, 0, 0};
+    TGranule_Info *gr_info;
+    
+    gr_info = mp->side_info->ch_info[ch]->gr_info[gr];
+    scalefac_comp = gr_info->scalefac_compress;
+    
+    switch(gr_info->block_mode)
+    {
+    case SHORT_BLOCK_MODE:
+        blocktypenumber = 1;
+        break;
+        
+    case LONG_BLOCK_MODE:
+        blocktypenumber = 0;
+        break;
+        
+    default:
+        break;
+    }
+    
+    if(!((mode_extension(mp->header) == 1 || 
+        mode_extension(mp->header) == 3) && ch == 1))
+    {    
+        
+        if(scalefac_comp < 400)
+        {
+            new_slen[0] = (scalefac_comp >> 4) / 5;
+            new_slen[1] = (scalefac_comp >> 4) % 5;
+            new_slen[2] = (scalefac_comp & 15) >> 2;
+            new_slen[3] = (scalefac_comp & 3);
+            
+            blocknumber = 0;
+            m = 4;
+        }
+        else if(scalefac_comp < 500)
+        {
+            scalefac_comp -= 400;
+            
+            new_slen[0] = (scalefac_comp >> 2) / 5;
+            new_slen[1] = (scalefac_comp >> 2) % 5;
+            new_slen[2] = scalefac_comp & 3;
+            
+            blocknumber = 1;
+            m = 3;
+        }
+        else /*if(scalefac_comp < 512)*/
+        {
+            scalefac_comp -= 500;
+            
+            new_slen[0] = scalefac_comp / 3;
+            new_slen[1] = scalefac_comp % 3;
+            
+            gr_info->flags |= (uint32)PRE_FLAG; /* pre_flag = 1 */
+            
+            blocknumber = 2;
+            m = 2;
+        }
+    }
+    
+    if(((mode_extension(mp->header) == 1 || 
+        mode_extension(mp->header) == 3) && ch == 1))
+    {
+        
+        int_scalefac_comp = scalefac_comp >> 1;
+        
+        if(int_scalefac_comp < 180)
+        {
+            int16 tmp = int_scalefac_comp % 36;
+            
+            new_slen[0] = int_scalefac_comp / 36;
+            new_slen[1] = tmp / 6;
+            new_slen[2] = tmp % 6;
+            
+            blocknumber = 3;
+            m = 3;
+        }
+        else if(int_scalefac_comp < 244)
+        {
+            int_scalefac_comp -= 180;
+            
+            new_slen[0] = (int_scalefac_comp & 63) >> 4;
+            new_slen[1] = (int_scalefac_comp & 15) >> 2;
+            new_slen[2] = int_scalefac_comp & 3;
+            
+            blocknumber = 4;
+            m = 3;
+        }
+        else /*if(int_scalefac_comp < 255)*/
+        {
+            int_scalefac_comp -= 244;
+            
+            new_slen[0] = int_scalefac_comp / 3;
+            new_slen[1] = int_scalefac_comp % 3;
+            
+            blocknumber = 5;
+            m = 2;
+        }
+        
+        TIS_Info *is_info = &mp->side_info->is_info;
+        is_info->is_len[0] = (1 << new_slen[0]) - 1;
+        is_info->is_len[1] = (1 << new_slen[1]) - 1;
+        is_info->is_len[2] = (1 << new_slen[2]) - 1;
+        is_info->nr_sfb[0] = nr_of_sfb_block[blocknumber][blocktypenumber][0];
+        is_info->nr_sfb[1] = nr_of_sfb_block[blocknumber][blocktypenumber][1];
+        is_info->nr_sfb[2] = nr_of_sfb_block[blocknumber][blocktypenumber][2];
+        
+    }
+    
+    
+    Mem::Fill(scalefac_buffer, 54, 0);
+    
+    
+    for(i = k = 0; i < m; i++)
+    {
+        
+        if(new_slen[i] != 0)
+            for(j = 0; j < nr_of_sfb_block[blocknumber][blocktypenumber][i]; j++, k++)
+            {
+                
+                
+                
+                scalefac_buffer[k] = BsGetBits(mp->br, new_slen[i]);
+                
+                
+            }
+            else
+            {
+                
+                
+                if (i < 4)
+                {
+                    k += nr_of_sfb_block[blocknumber][blocktypenumber][i];
+                }
+                else
+                {
+                    k +=  0;
+                }            
+                
+            }      
+            
+    }
+    
+}
+
+/**************************************************************************
+Title        : III_get_scale_factors
+
+Purpose      : Reads the scale factors of layer III.
+  
+Usage        : III_get_scale_factors(mp, gr, ch)
+    
+Input        : mp - MP3 stream parameters
+gr - granule number
+ch - channel number (left or right)
+      
+Author(s)    : Juha Ojanpera
+*************************************************************************/
+        
+void III_get_scale_factors(CMP_Stream *mp, int16 gr, int16 ch)
+    {
+    uint8 *sf[3];
+    int16 i, sfb, bits, idx;
+    TGranule_Info *gr_info;
+    CIII_Scale_Factors *scale_fac;
+    
+    uint8* scalefac_buffer = NULL;
+    TRAPD(error, scalefac_buffer = new (ELeave) uint8[54]);
+    if (error != KErrNone)
+        return;
+    
+    Mem::Fill(scalefac_buffer, 54, 0);
+    
+    gr_info = mp->side_info->ch_info[ch]->gr_info[gr];
+    
+    scale_fac = mp->side_info->ch_info[ch]->scale_fac;
+    
+    idx = 0;
+    if(mp->side_info->lsf)
+        {
+        III_get_LSF_scale_data(mp, gr, ch, scalefac_buffer);
+        }
+        
+    
+    switch(gr_info->block_mode)
+    {
+    case SHORT_BLOCK_MODE:
+        sf[0] = scale_fac->scalefac_short[0];
+        sf[1] = scale_fac->scalefac_short[1];
+        sf[2] = scale_fac->scalefac_short[2];
+        if(mp->side_info->lsf)
+            for(sfb = 0; sfb < 12; sfb++)
+            {
+                *sf[0]++ = scalefac_buffer[idx++];
+                *sf[1]++ = scalefac_buffer[idx++];
+                *sf[2]++ = scalefac_buffer[idx++];
+            }
+            else
+                for(i = 0; i < 2; i++)
+                {
+                    bits = slen[i][gr_info->scalefac_compress];
+                    if(bits)
+                        for(sfb = sfbtable.s[i]; sfb < sfbtable.s[i + 1]; sfb++)
+                        {
+                            *sf[0]++ = BsGetBits(mp->br, bits);
+                            *sf[1]++ = BsGetBits(mp->br, bits);
+                            *sf[2]++ = BsGetBits(mp->br, bits);
+                        }
+                        else
+                            for(sfb = sfbtable.s[i]; sfb < sfbtable.s[i + 1]; sfb++)
+                            {
+                                *sf[0]++ = 0; *sf[1]++ = 0; *sf[2]++ = 0;
+                            }
+                }
+            break;
+                
+    case LONG_BLOCK_MODE:
+        sf[0] = scale_fac->scalefac_long;
+        
+        
+        if(mp->side_info->lsf)
+            for(i = 0; i < 21; i++)
+                *sf[0]++ = scalefac_buffer[idx++];
+            else
+                for(i = 0; i < 4; i++)
+                {
+                    
+                    if(mp->side_info->scfsi[ch][i] == 0 || gr == 0)
+                    {
+                        bits = slen[i >> 1][gr_info->scalefac_compress];
+                        if(bits)
+                            for(sfb = sfbtable.l[i]; sfb < sfbtable.l[i + 1]; sfb++)
+                            {
+                                
+                                *sf[0]++ = BsGetBits(mp->br, bits);
+                                
+                            }
+                            else
+                                for(sfb = sfbtable.l[i]; sfb < sfbtable.l[i + 1]; sfb++)
+                                    *sf[0]++ = 0;
+                    }
+                    else
+                        sf[0] += sfbtable.l[i + 1] - sfbtable.l[i];
+                }
+            break;
+                
+    default:
+        break;
+    }
+    
+    delete[] scalefac_buffer;
+    
+}
+
+
+void
+    init_III_reorder(int16 reorder_idx[2][MAX_MONO_SAMPLES], int16 *sfb_table, 
+    int16 *sfb_width_table)
+{
+    int32 sfb, sfb_start, i;
+    int32 window, freq, src_line, des_line;
+    
+    for(i = sfb = 0; sfb < MAX_SHORT_SFB_BANDS; sfb++)
+    {
+        sfb_start = sfb_table[sfb];
+        
+        for(window = 0; window < 3; window++)
+            for(freq = 0; freq < sfb_width_table[sfb]; freq++)
+            {
+                src_line = sfb_start * 3 + window * sfb_width_table[sfb] + freq;
+                des_line = (sfb_start * 3) + window + (freq * 3);
+                
+                reorder_idx[0][i] =
+                    ((des_line / SSLIMIT) * SSLIMIT) + (des_line % SSLIMIT);
+                
+                reorder_idx[1][i++] =
+                    ((src_line / SSLIMIT) * SSLIMIT) + (src_line % SSLIMIT);
+            }
+    }
+}
+
+
+
+/**************************************************************************
+Title        : III_reorder
+
+  Purpose      : Re-orders the input frame if short blocks are present.
+  
+    Usage        : III_reorder(mp, gr, ch)
+    
+      Input        : mp - MP3 stream parameters
+      ch - channel number (left or right)
+      gr - granule number
+      
+        Explanation  : -
+        
+          Author(s)    : Juha Ojanpera
+*************************************************************************/
+
+void
+    III_reorder(CMP_Stream *mp, int16 ch, int16 gr)
+{
+    int16 i, sb_start;
+    register int16 *id1, *id2;
+    
+    FLOAT* xr = NULL;
+    TRAPD(error, xr = new (ELeave) FLOAT[MAX_MONO_SAMPLES]);
+    if (error != KErrNone)
+        return;
+    
+    register FLOAT *src, *dst;
+    
+    if(mp->side_info->ch_info[ch]->gr_info[gr]->block_mode == LONG_BLOCK_MODE)
+    {
+        delete[] xr;
+        return;
+        
+    }
+    
+    sb_start = 0;
+    
+    id1 = &mp->reorder_idx[0][sb_start];
+    id2 = &mp->reorder_idx[1][sb_start];
+    
+    /*
+    * First re-order the short block to a temporary buffer
+    * and then copy back to the input buffer. Not fully optimal,
+    * a better way would be perhaps to do the re-ordering during the
+    * dequantization but to my opinion that would complicate the code
+    * too much. We also have to remember that short blocks do not occur
+    * very frequently, so the penalty of having a separate re-ordering
+    * routine is not so time consuming from the overall decoder complexity
+    * point of view.
+    */
+    src = &mp->buffer->ch_reconstructed[ch][0];
+    dst = &xr[0];
+    
+    for(i = sb_start; i < MAX_MONO_SAMPLES; i++)
+        dst[*id1++] = src[*id2++];
+    
+    /* Copy back. */
+    for(i = sb_start; i < MAX_MONO_SAMPLES; i++)
+        src[i] = dst[i];
+    
+    delete[] xr;
+}