| /* ------------------------------------------------------------------ |
| * 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() */ |