| /* ------------------------------------------------------------------ |
| * 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: inv_short_complex_rot.c |
| Funtions: inv_short_complex_rot |
| |
| ------------------------------------------------------------------------------ |
| REVISION HISTORY |
| |
| Date: 10/18/2002 |
| Description: |
| (1) Change the input argument, only a single max is passed. |
| (2) Eliminate search for max, a fixed shift has replaced the |
| search for max with minimal loss of precision. |
| (3) Eliminated unused variables |
| |
| Date: 10/28/2002 |
| Description: |
| (1) Added comments per code review |
| (2) Eliminated hardly used condition on if-else (exp==0) |
| |
| Description: |
| |
| ------------------------------------------------------------------------------ |
| INPUT AND OUTPUT DEFINITIONS |
| |
| Inputs: |
| |
| Data_in = Input vector (sized for short windows |
| 2*INV_SHORT_CX_ROT_LENGTH elements), with time domain samples |
| type Int32 * |
| |
| Data_out = Output vector with a post-rotation by exp(j(2pi/N)(k+1/8)), |
| (sized for short windows 2*INV_SHORT_CX_ROT_LENGTH) |
| type Int32 * |
| |
| max = Input, carries the maximum value of the input vector |
| "Data_in" |
| type Int32 |
| |
| |
| Local Stores/Buffers/Pointers Needed: |
| None |
| |
| Global Stores/Buffers/Pointers Needed: |
| None |
| |
| Outputs: |
| exp = shift factor to reflect signal scaling |
| |
| Pointers and Buffers Modified: |
| Results are return in "Data_out" |
| |
| Local Stores Modified: |
| None |
| |
| Global Stores Modified: |
| None |
| ------------------------------------------------------------------------------ |
| FUNCTION DESCRIPTION |
| |
| inv_short_complex_rot() performs the complex rotation for the inverse MDCT |
| for the case of short windows. It performs digit reverse ordering as well |
| word normalization to ensure 16 by 16 bit multiplications. |
| |
| ------------------------------------------------------------------------------ |
| REQUIREMENTS |
| |
| inv_short_complex_rot() should execute a post-rotation by |
| exp( j(2pi/N)(k+1/8)), digit reverse ordering and word normalization |
| |
| ------------------------------------------------------------------------------ |
| REFERENCES |
| |
| ------------------------------------------------------------------------------ |
| RESOURCES USED |
| When the code is written for a specific target processor the |
| 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 "digit_reversal_tables.h" |
| #include "imdct_fxp.h" |
| #include "inv_short_complex_rot.h" |
| #include "pv_normalize.h" |
| #include "fxp_mul32.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 VARIABLE DEFINITIONS |
| ; Variable declaration - defined here and used outside this module |
| ----------------------------------------------------------------------------*/ |
| |
| /*---------------------------------------------------------------------------- |
| ; EXTERNAL FUNCTION REFERENCES |
| ; Declare functions defined elsewhere and referenced in this module |
| ----------------------------------------------------------------------------*/ |
| |
| /*---------------------------------------------------------------------------- |
| ; EXTERNAL VARIABLES REFERENCES |
| ; Declare variables used in this module but defined elsewhere |
| ----------------------------------------------------------------------------*/ |
| |
| |
| Int inv_short_complex_rot( |
| Int32 *Data_in, |
| Int32 *Data_out, |
| Int32 max) |
| |
| { |
| Int i; |
| Int16 I; |
| const Int16 *pTable; |
| const Int32 *p_rotate; |
| |
| Int32 *pData_in_1; |
| Int exp; |
| Int32 temp_re; |
| Int32 temp_im; |
| |
| Int32 exp_jw; |
| Int16 *pData_re; |
| Int16 *pData_im; |
| Int32 *pData_in_ref; |
| |
| Int16 temp_re_0; |
| Int16 temp_im_0; |
| Int16 temp_re_1; |
| Int16 temp_im_1; |
| Int16 *p_data_1; |
| Int16 *p_data_2; |
| Int16 *p_Data_Int_precision; |
| Int16 *p_Data_Int_precision_1; |
| Int16 *p_Data_Int_precision_2; |
| |
| Int n = 256; |
| Int n_2 = n >> 1; |
| Int n_4 = n >> 2; |
| Int n_8 = n >> 3; |
| Int n_3_4 = n_2 + n_4; |
| |
| |
| p_data_1 = (Int16 *)Data_out; |
| p_data_1 += n; |
| pData_re = p_data_1; |
| pData_im = p_data_1 + n_4; |
| |
| |
| p_rotate = exp_rotation_N_256; |
| pTable = digit_reverse_64; |
| |
| pData_in_ref = Data_in; |
| |
| exp = 16 - pv_normalize(max); |
| |
| |
| if (exp < 0) |
| { |
| exp = 0; |
| } |
| |
| exp -= 1; |
| |
| for (i = INV_SHORT_CX_ROT_LENGTH; i != 0; i--) |
| { |
| |
| /* |
| * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8)) |
| */ |
| |
| /* |
| * Perform digit reversal by accessing index I from table |
| */ |
| |
| I = *pTable++; |
| pData_in_1 = pData_in_ref + I; |
| /* |
| * Use auxiliary variables to avoid double accesses to memory. |
| * Data in is scaled to use only lower 16 bits. |
| */ |
| |
| temp_im = *(pData_in_1++); |
| temp_re = *(pData_in_1); |
| |
| exp_jw = *p_rotate++; |
| |
| /* |
| * Post-rotation |
| */ |
| |
| *(pData_re++) = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp); |
| *(pData_im++) = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp); |
| } |
| |
| |
| p_data_2 = pData_im - 1; |
| |
| |
| p_Data_Int_precision = (Int16 *)Data_out; |
| p_Data_Int_precision_1 = p_Data_Int_precision + n_3_4 - 1; |
| p_Data_Int_precision_2 = p_Data_Int_precision + n_3_4; |
| |
| for (i = n_8 >> 1; i != 0; i--) |
| { |
| temp_re_0 = (*(p_data_1++)); |
| temp_re_1 = (*(p_data_1++)); |
| temp_im_0 = (*(p_data_2--)); |
| temp_im_1 = (*(p_data_2--)); |
| |
| *(p_Data_Int_precision_1--) = temp_re_0; |
| *(p_Data_Int_precision_1--) = temp_im_0; |
| *(p_Data_Int_precision_1--) = temp_re_1; |
| *(p_Data_Int_precision_1--) = temp_im_1; |
| |
| *(p_Data_Int_precision_2++) = temp_re_0; |
| *(p_Data_Int_precision_2++) = temp_im_0; |
| *(p_Data_Int_precision_2++) = temp_re_1; |
| *(p_Data_Int_precision_2++) = temp_im_1; |
| |
| } |
| |
| |
| /* |
| * loop is split to avoid conditional testing inside loop |
| */ |
| |
| p_Data_Int_precision_2 = p_Data_Int_precision; |
| |
| for (i = n_8 >> 1; i != 0; i--) |
| { |
| |
| temp_re_0 = (*(p_data_1++)); |
| temp_re_1 = (*(p_data_1++)); |
| temp_im_0 = (*(p_data_2--)); |
| temp_im_1 = (*(p_data_2--)); |
| |
| *(p_Data_Int_precision_1--) = temp_re_0; |
| *(p_Data_Int_precision_1--) = temp_im_0; |
| *(p_Data_Int_precision_1--) = temp_re_1; |
| *(p_Data_Int_precision_1--) = temp_im_1; |
| |
| *(p_Data_Int_precision_2++) = (Int16)(-temp_re_0); |
| *(p_Data_Int_precision_2++) = (Int16)(-temp_im_0); |
| *(p_Data_Int_precision_2++) = (Int16)(-temp_re_1); |
| *(p_Data_Int_precision_2++) = (Int16)(-temp_im_1); |
| |
| } |
| |
| return (exp + 1); |
| } |