diff -r 000000000000 -r 951a5db380a0 videoeditorengine/mp3aacManipLib/MP3Gain/src/layer3.cpp --- /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; +}