--- /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;
+}