377 lines
14 KiB
C++
377 lines
14 KiB
C++
/* ------------------------------------------------------------------
|
|
* 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
|
|
|
|
Date: 09/21/2007
|
|
|
|
------------------------------------------------------------------------------
|
|
REVISION HISTORY
|
|
|
|
|
|
Description:
|
|
|
|
------------------------------------------------------------------------------
|
|
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));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|