/* ------------------------------------------------------------------ * 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: tns_decode_coef.c ------------------------------------------------------------------------------ REVISION HISTORY Description: Modified from original shareware code Description: Implemented in 16-bit Fixed Point Description: Implemented in 24-bit Fixed Point Description: Modified to return the calculated LPC coefficients "in place" This saves memory, cycles, etc. because it saves a large temporary array being declared on the stack in another function (tns_setup_filter) Description: Modified to return the q-format of the lpc coefficients. Description: Modified for more reliable overflow protection. tns_decode_coef no longer relies on "reasonable" outputs. This code should handle all possible inputs. Description: Modified per review comments. Description: Added check condition to avoid numbers with a Q bigger than 15 from being passed, otherwise in a 16-bit number the sign is lost. Description: Modified to utilize scratch memory techniques, thereby eliminating two arrays of size TNS_MAX_ORDER, which were previously declared on the stack. Description: Updated the SW template to include the full pathname to the source file and a slightly modified copyright header. Description: (1) Changed the order of the unsigned * signed multiply so the casting to Int32 is performed on the unsigned operand. (2) Removed some unnecessary casting. (3) Fixed a problem where a 16-bit value was casted to 32-bits AFTER a shift. It should have been cast to 32-bits BEFORE the shifting. Description: modified precision of coefficients Who: Date: Description: ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS The inputs and their range are defined in ISO/IEC 14496-3:1999(E) Part 3 MPEG-4 Audio Subpart 4 Inputs: order = RANGE = 1-20 const Int coef_res = RANGE = 0-1 const Int lpc_coef = RANGE = -8 to 7 if coef_res = 1 compression OFF -4 to 3 if coef_res = 1 compression ON -4 to 3 if coef_res = 0 compression OFF -2 to 1 if coef_res = 0 compression ON [Int *, length TNS_MAX_ORDER] Global Stores/Buffers/Pointers Needed: None Outputs: q_lpc = q_format for the calculated LPC coefs. Int Pointers and Buffers Modified: lpc_coef = used to return the calculated LPC coefs in-place. Int * Global Stores Modified: None ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function calculates the LPC coefs from the encoded coefs... ------------------------------------------------------------------------------ REQUIREMENTS This function should match the functionality of the ISO source code within a reasonable tolerance for fixed point errors. ------------------------------------------------------------------------------ REFERENCES (1) ISO/IEC 14496-3:1999(E) Part 3 Subpart 4.6.8 (Temporal Noise Shaping) (2) Markel & Gray Page 95 As referenced in the ISO source code (3) MPEG-2 NBC Audio Decoder "This software module was originally developed by AT&T, Dolby Laboratories, Fraunhofer Gesellschaft IIS in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this software module or modifications thereof for use in hardware or software products claiming conformance to the MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software module in hardware or software products are advised that this use may infringe existing patents. The original developer of this software module and his/her company, the subsequent editors and their companies, and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. Copyright is not released for non MPEG-2 NBC/MPEG-4 Audio conforming products.The original developer retains full right to use the code for his/her own purpose, assign or donate the code to a third party and to inhibit third party from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This copyright notice must be included in all copies or derivative works." Copyright(c)1996. ------------------------------------------------------------------------------ */ /*---------------------------------------------------------------------------- PSEUDOCODE: (ISO Reference Code) int i, m; Real iqfac, iqfac_m; Real lpc_fp[TNS_MAX_ORDER+1]; Real sin_result_fp[TNS_MAX_ORDER+1], b[TNS_MAX_ORDER+1]; Inverse quantization iqfac = (Real)(((1 << (coef_res-1)) - 0.5) / (PI/2.0)); iqfac_m = (Real)(((1 << (coef_res-1)) + 0.5) / (PI/2.0)); for (i=0; i= 0) ? iqfac : iqfac_m) ); } lpc[0] = 1; for (m=1; m<=order; m++) { b[0] = lpc[0]; for (i=1; i 0; i--) { /* * temp_ptr used to optimize index into pA * mult = (Int32)( pA[m-i] * sin_result); */ mult_high = fxp_mul32_Q31(*(temp_ptr--), sin_result); /* * pB[i] = pA[i] + sin_result * pA[m-i] * * (mult_high <<1) eliminates extra sign bit */ *(pB++) = *(pA++) + (mult_high << 1); } /* END for (i=m; i > 0; i--) */ /* Shift to place pB[m] in q_lpc format */ *pB = sin_result >> 12; /* * Swapping the pointers here has the same effect * as specifically copying the data from b to a */ temp_ptr = pA; pA = pB; pB = temp_ptr; /* * At this point, pA = pA[m] * and pB = pB[m] */ temp_ptr = pA; tempInt32 = *(pA); mask = tempInt32 >> 31; tempInt32 ^= mask; max = tempInt32; /* * It is important that this for loop is not entered on the first * iteration of the do-while( m < order ) loop. */ for (i = m; i > 0; i--) { tempInt32 = *(--pA); mask = tempInt32 >> 31; tempInt32 ^= mask; max |= tempInt32; } pB -= m; /* * Here, pA = &(pA[0]) * and pB = &(pB[0]) */ if (max >= 0x40000000L) { max >>= 1; for (i = m; i > 0; i--) { *(pA++) >>= 1; *(pB++) >>= 1; } /* Shift the most recent entry down also */ *(pA) >>= 1; q_lpc--; pA -= m; pB -= m; } m++; } while (m < order); /* * The following code compacts * 32-bit LPC coefficients into 16-bit numbers, * shifting by the minimum amount necessary. */ shift_amount = 0; while (max > 32767) { max >>= 1; shift_amount++; } /* * This while loop is for protective purposes only. * I have not found data that causes it to be entered. * */ if (max != 0) { while (max < 16384) { max <<= 1; shift_amount--; } } pLPC = lpc_coef; if (shift_amount >= 0) { for (m = order; m > 0; m--) { *(pLPC++) = *(pA++) << (16 - shift_amount); } } q_lpc -= shift_amount; /* * make sure that the numbers have some meaning, q_lpc can not be * bigger than 15 (15 bits + sign) */ if (q_lpc > 15) { shift_amount = q_lpc - 15; pLPC = lpc_coef; for (m = order; m > 0; m--) { *(pLPC++) >>= shift_amount; } q_lpc -= shift_amount; } return (q_lpc); } /* tns_decode_coef */