blob: 96ecd2748e00ca4ac3f8cd17e666dea05b6b5a2b [file] [log] [blame]
/* ------------------------------------------------------------------
* 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.
* -------------------------------------------------------------------
*/
/*
Pathname: apply_tns.c
------------------------------------------------------------------------------
INPUT AND OUTPUT DEFINITIONS
Inputs:
coef = Array of input coefficients.
[Int32 *, length 1024]
q_format = Array of q-formats, one per scalefactor band, for the
entire frame. In the case of tns_inv_filter, only the
first element is used, since the input to tns_inv_filter
is all of the same q-format.
[Int * const, length MAX_SFB]
pFrameInfo = Pointer to structure that holds information about each group.
(long block flag, number of windows, scalefactor bands
per group, etc.)
[const FrameInfo * const]
pTNS_frame_info = pointer to structure containing the details on each
TNS filter (order, filter coefficients,
coefficient res., etc.)
[TNS_frame_info * const]
inverse_flag = TRUE if inverse filter is to be applied.
FALSE if forward filter is to be applied.
[Bool]
scratch_Int_buffer = Pointer to scratch memory to store the
filter's state memory. Used by both
tns_inv_filter.
[Int *, length TNS_MAX_ORDER]
Local Stores/Buffers/Pointers Needed:
None
Global Stores/Buffers/Pointers Needed:
None
Outputs:
None
Pointers and Buffers Modified:
coef[] = TNS altered data.
q_format = q-formats in TNS scalefactor bands may be modified.
Local Stores Modified:
None
Global Stores Modified:
None
------------------------------------------------------------------------------
FUNCTION DESCRIPTION
This function applies either the TNS forward or TNS inverse filter, based
on inverse_flag being FALSE or TRUE, respectively.
For the TNS forward filter, the data fed into tns_ar_filter is normalized
all to the same q-format.
------------------------------------------------------------------------------
REQUIREMENTS
The input, coef, should use all 32-bits, else the scaling by tns_ar_filter
may eliminate the data.
------------------------------------------------------------------------------
REFERENCES
(1) ISO/IEC 14496-3:1999(E)
Part 3
Subpart 4.6.8 (Temporal Noise Shaping)
------------------------------------------------------------------------------
PSEUDO-CODE
NO PSEUDO-CODE
------------------------------------------------------------------------------
RESOURCES USED
When the code is written for a specific target processor
the resources used should be documented below.
STACK USAGE: [stack count for this module] + [variable to represent
stack usage for each subroutine called]
where: [stack usage variable] = stack usage for [subroutine
name] (see [filename].ext)
DATA MEMORY USED: x words
PROGRAM MEMORY USED: x words
CLOCK CYCLES: [cycle count equation for this module] + [variable
used to represent cycle count for each subroutine
called]
where: [cycle count variable] = cycle count for [subroutine
name] (see [filename].ext)
------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "pv_audio_type_defs.h"
#include "s_tns_frame_info.h"
#include "s_tnsfilt.h"
#include "s_frameinfo.h"
#include "tns_inv_filter.h"
#include "tns_ar_filter.h"
#include "apply_tns.h"
/*----------------------------------------------------------------------------
; MACROS
; Define module specific macros here
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; DEFINES
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL FUNCTION DEFINITIONS
; Function Prototype declaration
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; LOCAL STORE/BUFFER/POINTER DEFINITIONS
; Variable declaration - defined here and used outside this module
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
; 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 apply_tns(
Int32 coef[],
Int q_format[],
const FrameInfo * const pFrameInfo,
TNS_frame_info * const pTNS_frame_info,
const Bool inverse_flag,
Int32 scratch_Int_buffer[])
{
Int num_tns_bands;
Int num_TNS_coef;
Int f;
Int tempInt;
Int tempInt2;
Int sfb_per_win;
Int sfbWidth;
Int coef_per_win;
Int min_q;
Int win;
Int32 *pCoef = coef;
Int32 *pTempCoef;
Int *pStartQformat = q_format;
Int *pQformat;
Int32 *pLpcCoef;
Int sfb_offset;
const Int16 *pWinSfbTop;
TNSfilt *pFilt;
coef_per_win = pFrameInfo->coef_per_win[0];
sfb_per_win = pFrameInfo->sfb_per_win[0];
win = 0;
pLpcCoef = pTNS_frame_info->lpc_coef;
pFilt = pTNS_frame_info->filt;
do
{
for (f = pTNS_frame_info->n_filt[win]; f > 0; f--)
{
/* Skip to the next filter if the order is 0 */
tempInt = pFilt->order;
if (tempInt > 0)
{
/*
* Do not call tns_ar_filter or tns_inv_filter
* if the difference
* between start_coef and stop_stop is <= 0.
*
*/
num_TNS_coef = (pFilt->stop_coef - pFilt->start_coef);
if (num_TNS_coef > 0)
{
if (inverse_flag != FALSE)
{
tns_inv_filter(
&(pCoef[pFilt->start_coef]),
num_TNS_coef,
pFilt->direction,
pLpcCoef,
pFilt->q_lpc,
pFilt->order,
scratch_Int_buffer);
}
else
{
num_tns_bands = (pFilt->stop_band - pFilt->start_band);
/*
* pQformat is initialized only once.
*
* Here is how TNS is applied on scalefactor bands
*
* [0][1][2][3][4][5][6][7][8]
* | \
* start_band stop_band
*
* In this example, TNS would be applied to 8
* scalefactor bands, 0-7.
*
* pQformat is initially set to &(pStartQformat[8])
*
* 1st LOOP
* Entry: pQformat = &(pStartQformat[8])
*
* pQformat is pre-decremented 8 times in the
* search for min_q
*
* Exit: pQformat = &(pStartQformat[0])
*
* 2nd LOOP
* Entry: pQformat = &(pStartQformat[0])
*
* pQformat is post-incremented 8 times in the
* normalization of the data loop.
*
* Exit: pQformat = &(pStartQformat[8]
*
*
* shift_amt = tns_ar_filter(...)
*
* 3rd LOOP
* Entry: pQformat = &(pStartQformat[8])
*
* pQformat is pre-decremented 8 times in the
* adjustment of the q-format to min_q - shift_amt
*
* Exit: pQformat = &(pStartQformat[0])
*
*/
pQformat =
&(pStartQformat[pFilt->stop_band]);
/*
* Scan the array of q-formats and find the minimum over
* the range where the filter is to be applied.
*
* At the end of this scan,
* pQformat = &(q-format[pFilt->start_band]);
*
*/
min_q = INT16_MAX;
for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
{
tempInt2 = *(--pQformat);
if (tempInt2 < min_q)
{
min_q = tempInt2;
}
} /* for(tempInt = num_bands; tempInt > 0; tempInt--)*/
/*
* Set up the pointers so we can index into coef[]
* on a scalefactor band basis.
*/
tempInt = pFilt->start_band;
tempInt--;
/* Initialize sfb_offset and pWinSfbTop */
if (tempInt >= 0)
{
pWinSfbTop =
&(pFrameInfo->win_sfb_top[win][tempInt]);
sfb_offset = *(pWinSfbTop++);
}
else
{
pWinSfbTop = pFrameInfo->win_sfb_top[win];
sfb_offset = 0;
}
pTempCoef = pCoef + pFilt->start_coef;
/* Scale the data in the TNS bands to min_q q-format */
for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
{
sfbWidth = *(pWinSfbTop++) - sfb_offset;
sfb_offset += sfbWidth;
tempInt2 = *(pQformat++) - min_q;
/*
* This should zero out the data in one scalefactor
* band if it is so much less than the neighboring
* scalefactor bands.
*
* The only way this "should" happen is if one
* scalefactor band contains zero data.
*
* Zero data can be of any q-format, but we always
* set it very high to avoid the zero-data band being
* picked as the one to normalize to in the scan for
* min_q.
*
*/
if (tempInt2 > 31)
{
tempInt2 = 31;
}
for (sfbWidth >>= 2; sfbWidth > 0; sfbWidth--)
{
*(pTempCoef++) >>= tempInt2;
*(pTempCoef++) >>= tempInt2;
*(pTempCoef++) >>= tempInt2;
*(pTempCoef++) >>= tempInt2;
}
} /* for(tempInt = num_bands; tempInt > 0; tempInt--)*/
tempInt2 =
tns_ar_filter(
&(pCoef[pFilt->start_coef]),
num_TNS_coef,
pFilt->direction,
pLpcCoef,
pFilt->q_lpc,
pFilt->order);
/*
* Update the q-format for all the scalefactor bands
* taking into account the adjustment caused by
* tns_ar_filter
*/
min_q -= tempInt2;
for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
{
*(--pQformat) = min_q;
}
} /* if (inverse_flag != FALSE) */
} /* if (num_TNS_coef > 0) */
pLpcCoef += pFilt->order;
} /* if (tempInt > 0) */
pFilt++;
} /* for (f = pTNSinfo->n_filt; f > 0; f--) */
pCoef += coef_per_win;
pStartQformat += sfb_per_win;
win++;
}
while (win < pFrameInfo->num_win);
return;
} /* apply_tns() */