/codecs_v2/audio/mp3/dec/src/pvmp3_imdct_synth.cpp
C++ | 368 lines | 178 code | 57 blank | 133 comment | 13 complexity | 81d011979bd91cfd980052d5385a7d10 MD5 | raw file
- /* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- * -------------------------------------------------------------------
- */
- /*
- ------------------------------------------------------------------------------
- PacketVideo Corp.
- MP3 Decoder Library
- Filename: pvmp3_imdct_synth.cpp
- ------------------------------------------------------------------------------
- INPUT AND OUTPUT DEFINITIONS
- Input
- int32 in[], Pointer to spec values of current channel
- int32 overlap[], Pointer to overlap values of current channel
- uint32 blk_type, Block type
- int16 mx_band, In case of mixed blocks, # of bands with long
- blocks (2 or 4) else 0
- int32 *Scratch_mem
- Returns
- int32 in[],
- ------------------------------------------------------------------------------
- FUNCTION DESCRIPTION
- The frequency lines are preprocessed by the "alias reduction" scheme
- and fed into the IMDCT matrix, each 18 into one transform block.
- The first half of the output values are added to the stored overlap
- values from the last block. These values are new output values and
- are input values for the polyphase filterbank. The second half of the
- output values is stored for overlap with the next data granule.
- The number of windowed samples is 12 for short blocks, and 36 for long
- blocks
- Windowing
- Depending on window_switching_flag[gr][ch], block_type[gr][ch] and
- mixed_block_flag[gr][ch] different shapes of windows are used.
- normal window
- start window
- stop window
- short windows
- Each of the three short blocks is windowed separately.
- The windowed short blocks must be overlapped and concatenated.
- Overlapping and adding with previous block
- The first half (18 values) of the current block (36 values) has to be
- overlapped with the second half of the previous block. The second half
- of the current block has to be stored for overlapping with the next block
- ------------------------------------------------------------------------------
- REQUIREMENTS
- ------------------------------------------------------------------------------
- REFERENCES
- [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
- ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
- ------------------------------------------------------------------------------
- PSEUDO-CODE
- ------------------------------------------------------------------------------
- */
- /*----------------------------------------------------------------------------
- ; INCLUDES
- ----------------------------------------------------------------------------*/
- #include "pvmp3_imdct_synth.h"
- #include "pv_mp3dec_fxd_op.h"
- #include "pvmp3_dec_defs.h"
- #include "pvmp3_mdct_18.h"
- #include "pvmp3_mdct_6.h"
- #include "mp3_mem_funcs.h"
- /*----------------------------------------------------------------------------
- ; MACROS
- ; Define module specific macros here
- ----------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------
- ; DEFINES
- ; Include all pre-processor statements here. Include conditional
- ; compile variables also.
- ----------------------------------------------------------------------------*/
- #define LONG 0
- #define START 1
- #define SHORT 2
- #define STOP 3
- /*----------------------------------------------------------------------------
- ; LOCAL FUNCTION DEFINITIONS
- ; Function Prototype declaration
- ----------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------
- ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
- ; Variable declaration - defined here and used outside this module
- ----------------------------------------------------------------------------*/
- /*
- * sin(pi/36*(k+0.5)),k=0..35
- */
- const int32 normal_win[36] =
- {
- Qfmt_31(0.08723877473068f), Qfmt_31(0.26105238444010f), Qfmt_31(0.43287922787620f),
- Qfmt_31(0.60141159900854f), Qfmt_31(0.76536686473018f), Qfmt_31(0.92349722647006f),
- Qfmt_31(0.53729960834682f), Qfmt_31(0.60876142900872f), Qfmt_31(0.67559020761566f),
- Qfmt_31(-0.73727733681012f), Qfmt_31(-0.79335334029124f), Qfmt_31(0.84339144581289f),
- Qfmt_31(0.88701083317822f), Qfmt_31(0.92387953251129f), Qfmt_31(-0.95371695074823f),
- Qfmt_31(-0.97629600711993f), Qfmt_31(-0.99144486137381f), Qfmt_31(-0.99904822158186f),
- Qfmt_31(0.99904822158186f), Qfmt_31(0.99144486137381f), Qfmt_31(0.97629600711993f),
- Qfmt_31(0.95371695074823f), Qfmt_31(0.92387953251129f), Qfmt_31(0.88701083317822f),
- Qfmt_31(0.84339144581289f), Qfmt_31(0.79335334029124f), Qfmt_31(0.73727733681012f),
- Qfmt_31(0.67559020761566f), Qfmt_31(0.60876142900872f), Qfmt_31(0.53729960834682f),
- Qfmt_31(0.46174861323503f), Qfmt_31(0.38268343236509f), Qfmt_31(0.30070579950427f),
- Qfmt_31(0.21643961393810f), Qfmt_31(0.13052619222005f), Qfmt_31(0.04361938736534f)
- };
- const int32 start_win[36] =
- {
- /* k=0..17 sin(pi/36*(k+0.5)), */
- Qfmt_31(0.08723877473068f), Qfmt_31(0.26105238444010f), Qfmt_31(0.43287922787620f),
- Qfmt_31(0.60141159900854f), Qfmt_31(0.76536686473018f), Qfmt_31(0.92349722647006f),
- Qfmt_31(0.53729960834682f), Qfmt_31(0.60876142900872f), Qfmt_31(0.67559020761566f),
- Qfmt_31(-0.73727733681012f), Qfmt_31(-0.79335334029124f), Qfmt_31(0.84339144581289f),
- Qfmt_31(0.88701083317822f), Qfmt_31(0.92387953251129f), Qfmt_31(-0.95371695074823f),
- Qfmt_31(-0.97629600711993f), Qfmt_31(-0.99144486137381f), Qfmt_31(-0.99904822158186f),
- Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f),
- Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f),
- /* k=24..29; sin(pi/12*(k-18+0.5)) */
- Qfmt_31(0.99144486137381f), Qfmt_31(0.92387953251129f), Qfmt_31(0.79335334029124f),
- Qfmt_31(0.60876142900872f), Qfmt_31(0.38268343236509f), Qfmt_31(0.13052619222005f),
- Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f),
- Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f)
- };
- const int32 stop_win[36] =
- {
- Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f),
- Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f),
- /* k=6..11; sin(pi/12*(k-6+0.5)) */
- Qfmt_31(0.13052619222005f), Qfmt_31(0.38268343236509f), Qfmt_31(0.60876142900872f),
- Qfmt_31(-0.79335334029124f), Qfmt_31(-0.92387953251129f), Qfmt_31(0.99144486137381f),
- Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f), Qfmt_31(-0.99999990000000f),
- Qfmt_31(-0.99999990000000f), Qfmt_31(-0.99999990000000f), Qfmt_31(-0.99999990000000f),
- /* k=18..35 sin(pi/36*(k+0.5)), */
- Qfmt_31(0.99904822158186f), Qfmt_31(0.99144486137381f), Qfmt_31(0.97629600711993f),
- Qfmt_31(0.95371695074823f), Qfmt_31(0.92387953251129f), Qfmt_31(0.88701083317822f),
- Qfmt_31(0.84339144581289f), Qfmt_31(0.79335334029124f), Qfmt_31(0.73727733681012f),
- Qfmt_31(0.67559020761566f), Qfmt_31(0.60876142900872f), Qfmt_31(0.53729960834682f),
- Qfmt_31(0.46174861323503f), Qfmt_31(0.38268343236509f), Qfmt_31(0.30070579950427f),
- Qfmt_31(0.21643961393810f), Qfmt_31(0.13052619222005f), Qfmt_31(0.04361938736534f)
- };
- const int32 short_win[12] =
- {
- /* k=0..11; sin(pi/12*(k+0.5)) */
- Qfmt_31(0.13052619222005f), Qfmt_31(0.38268343236509f), Qfmt_31(0.60876142900872f),
- Qfmt_31(0.79335334029124f), Qfmt_31(0.92387953251129f), Qfmt_31(0.99144486137381f),
- Qfmt_31(0.99144486137381f), Qfmt_31(0.92387953251129f), Qfmt_31(0.79335334029124f),
- Qfmt_31(0.60876142900872f), Qfmt_31(0.38268343236509f), Qfmt_31(0.13052619222005f),
- };
- /*----------------------------------------------------------------------------
- ; EXTERNAL FUNCTION REFERENCES
- ; Declare functions defined elsewhere and referenced in this module
- ----------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------
- ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
- ; Declare variables used in this module but defined elsewhere
- ----------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------
- ; FUNCTION CODE
- ----------------------------------------------------------------------------*/
- void pvmp3_imdct_synth(int32 in[SUBBANDS_NUMBER*FILTERBANK_BANDS],
- int32 overlap[SUBBANDS_NUMBER*FILTERBANK_BANDS],
- uint32 blk_type,
- int16 mx_band,
- int32 used_freq_lines,
- int32 *Scratch_mem)
- {
- int32 band;
- int32 bands2process = used_freq_lines + 2;
- if (bands2process > SUBBANDS_NUMBER)
- {
- bands2process = SUBBANDS_NUMBER; /* default */
- }
- /*
- * in case of mx_poly_band> 0, do
- * long transforms
- */
- for (band = 0; band < bands2process; band++)
- {
- uint32 current_blk_type = (band < mx_band) ? LONG : blk_type;
- int32 * out = in + (band * FILTERBANK_BANDS);
- int32 * history = overlap + (band * FILTERBANK_BANDS);
- switch (current_blk_type)
- {
- case LONG:
- pvmp3_mdct_18(out, history, normal_win);
- break;
- case START:
- pvmp3_mdct_18(out, history, start_win);
- break;
- case STOP:
- pvmp3_mdct_18(out, history, stop_win);
- break;
- case SHORT:
- {
- int32 *tmp_prev_ovr = &Scratch_mem[FILTERBANK_BANDS];
- int32 i;
- for (i = 0; i < 6; i++)
- {
- Scratch_mem[i ] = out[(i*3)];
- Scratch_mem[6 +i] = out[(i*3) + 1];
- Scratch_mem[12 +i] = out[(i*3) + 2];
- }
- pvmp3_mdct_6(&Scratch_mem[ 0], &tmp_prev_ovr[ 0]);
- pvmp3_mdct_6(&Scratch_mem[ 6], &tmp_prev_ovr[ 6]);
- pvmp3_mdct_6(&Scratch_mem[12], &tmp_prev_ovr[12]);
- for (i = 0; i < 6; i++)
- {
- int32 temp = history[i];
- /* next iteration overlap */
- history[i] = fxp_mul32_Q32(tmp_prev_ovr[ 6+i] << 1, short_win[6+i]);
- history[i] += fxp_mul32_Q32(Scratch_mem[12+i] << 1, short_win[ i]);
- out[i] = temp;
- }
- for (i = 0; i < 6; i++)
- {
- out[i+6] = fxp_mul32_Q32(Scratch_mem[i] << 1, short_win[i]);
- out[i+6] += history[i+6];
- /* next iteration overlap */
- history[i+6] = fxp_mul32_Q32(tmp_prev_ovr[12+i] << 1, short_win[6+i]);
- }
- for (i = 0; i < 6; i++)
- {
- out[i+12] = fxp_mul32_Q32(tmp_prev_ovr[ i] << 1, short_win[6+i]);
- out[i+12] += fxp_mul32_Q32(Scratch_mem[6+i] << 1, short_win[ i]);
- out[i+12] += history[i+12];
- history[12+i] = 0;
- }
- }
- break;
- }
- /*
- * Compensation for frequency inversion of polyphase filterbank
- * every odd time sample of every odd odd subband is mulitplied by -1 before
- * processing by the polyphase filter
- */
- if (band & 1)
- {
- for (int32 slot = 1; slot < FILTERBANK_BANDS; slot += 6)
- {
- int32 temp1 = out[slot ];
- int32 temp2 = out[slot+2];
- int32 temp3 = out[slot+4];
- out[slot ] = -temp1;
- out[slot+2] = -temp2;
- out[slot+4] = -temp3;
- }
- }
- }
- for (band = bands2process; band < SUBBANDS_NUMBER; band++)
- {
- int32 * out = in + (band * FILTERBANK_BANDS);
- int32 * history = overlap + (band * FILTERBANK_BANDS);
- int32 slot;
- if (band & 1)
- {
- for (slot = 0; slot < FILTERBANK_BANDS; slot += 6)
- {
- int32 temp1 = history[slot ];
- int32 temp2 = history[slot+1];
- int32 temp3 = history[slot+2];
- out[slot ] = temp1;
- out[slot+1] = -temp2;
- out[slot+2] = temp3;
- temp1 = history[slot+3];
- temp2 = history[slot+4];
- temp3 = history[slot+5];
- out[slot+3] = -temp1;
- out[slot+4] = temp2;
- out[slot+5] = -temp3;
- }
- }
- else
- {
- for (slot = 0; slot < FILTERBANK_BANDS; slot += 3)
- {
- int32 temp1 = history[slot ];
- int32 temp2 = history[slot+1];
- int32 temp3 = history[slot+2];
- out[slot ] = temp1;
- out[slot+1] = temp2;
- out[slot+2] = temp3;
- }
- }
- pv_memset(history, 0, FILTERBANK_BANDS*sizeof(*overlap));
- }
- }