| /* ------------------------------------------------------------------ |
| * 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: long_term_synthesis.c |
| |
| |
| ------------------------------------------------------------------------------ |
| REVISION HISTORY |
| |
| Description: Made the following changes based on the review comments. |
| 1. Separated "shift_factor>=0" on line 395 to "shift_factor>0" |
| and "shift_factor=0" two cases. |
| 2. Added comments on line 393 to explain why factor 2 is being |
| used to calculate shift_factor. |
| 3. Added comments for short window implementation. |
| 4. Changed "*(pPredicted_spectral++) = *pPredicted_spectral>>2" |
| to "*(pPredicted++)>>=2" although they are the same. |
| 5. Changed pseudo code "X+=Y" to "X=X+Y". |
| 6. Fixed ending comment of "for" loop. |
| 7. Passed in the size of the array and deleted some of the |
| include files. |
| |
| Description: Unroll the loops. |
| |
| Description: Changed index "wnd" in previous line 584 with "wnd_offset" |
| and made other correspondent changes to the code. |
| |
| |
| Description: Based on Ken's suggestion, modified the function with the |
| passing-in Q format as scalefactor band basis in order to |
| simplify TNS block functions. |
| |
| Description: Optimization. |
| |
| Description: Made changes based on review comments. |
| 1. Changed misspellings. |
| 2. Changed win_sfb_top[] from two dimensional array to one |
| dimensional array and correspondently changed the code. |
| 3. Changed function prototype to remove some redundant |
| informations. |
| 4. Fixed the adjusting Q format part code. |
| 5. Fixed lines 825, 826 with correct updating pointers. |
| |
| Description: Due to TNS and LTP Q format issue, added code to adjust |
| predicted_spectral() to maximum resolution before perform |
| long term synthesis. |
| |
| Description: Modified based on review comments. |
| |
| Description: Changed "max" data type from UInt to UInt32. |
| |
| Description: Changed so that nothing is done for the case of "all zero" |
| data coming from the output of Trans4m_time_2_freq. Also, included more |
| efficient calculation of the abs(x). And, I updated the pseudocode. |
| |
| Description: Use an auxiliary variable temp, to avoid using the same |
| pointer and a post-increment pointer in the same line. This may not |
| work with all compilers. |
| |
| Who: Date: |
| Description: |
| |
| ------------------------------------------------------------------------------ |
| INPUT AND OUTPUT DEFINITIONS |
| |
| Inputs: |
| win_seq = type of window sequence (WINDOW_SEQUENCE). |
| sfb_per_win = number of scalefactor bands for each window, 1024 for |
| long window, 128 for short window, type of Int. |
| win_sfb_top = buffer (Int16) containing the top coefficient per |
| scalefactor band for each window. |
| win_prediction_used = buffer (Int) containing the prediction flag |
| information for short windows. Each item in the |
| buffer toggles prediction on(1)/off(0) for each |
| window separately. |
| sfb_prediction_used = buffer (Int) containing the prediction flag |
| information for scalefactor band(sfb). Each item |
| toggle prediction on(1)/off(0) on each scalefactor |
| band of every window. |
| current_frame = channel buffer (Int32) containing the dequantized |
| spectral coefficients or errors of current frame. |
| q_format = buffer (Int) containing Q format for each scalefactor band of |
| input current_frame. |
| predicted_spectral = buffer (Int32) containing predicted spectral |
| components of current frame. |
| pred_q_format = Q format (Int) for predicted spectral components of |
| current frame. |
| coef_per_win = number of coefficients per window for short windows. |
| type of Int. |
| short_window_num = number of short windows, type of Int. |
| reconstruct_sfb_num = number of scalefactor bands used for reconstruction |
| for short windows, type of Int. |
| |
| Local Stores/Buffers/Pointers Needed: |
| None |
| |
| Global Stores/Buffers/Pointers Needed: |
| None |
| |
| Outputs: |
| None |
| |
| Pointers and Buffers Modified: |
| current_frame contents are the dequantized spectrum with a prediction |
| vector added when prediction is turned on. |
| |
| q_format contents are updated with the new Q format (Int) for each |
| scalefactor band of output current_frame buffer. |
| |
| Local Stores Modified: |
| None |
| |
| Global Stores Modified: |
| None |
| |
| ------------------------------------------------------------------------------ |
| FUNCTION DESCRIPTION |
| |
| This function performs long term synthesis using transmitted spectral |
| coeffients or errors and predicted spectral components. |
| |
| Long term synthesis is part of long term prediction (LTP) which is used to |
| reduce the redundancy of a signal between successive coding frames. The |
| functionality of long term synthesis is to reconstruct the frequency domain |
| spectral by adding the predicted spectral components and the transmitted |
| spectral error when prediction is turned on. |
| |
| ------------------------------------------------------------------------------ |
| REQUIREMENTS |
| |
| None |
| |
| ------------------------------------------------------------------------------ |
| REFERENCES |
| |
| (1) ISO/IEC 14496-3:1999(E) |
| Part 3: Audio |
| Subpart 4.6.6 Long Term Prediction (LTP) |
| |
| (2) MPEG-2 NBC Audio Decoder |
| "This software module was originally developed by Nokia in the course |
| of development of the MPEG-2 AAC/MPEG-4 Audio standard ISO/IEC13818-7, |
| 14496-1, 2 and 3. This software module is an implementation of a part |
| of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the MPEG-2 |
| aac/MPEG-4 Audio standard. ISO/IEC gives users of the MPEG-2aac/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 aac/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, 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 |
| aac/MPEG-4 Audio conforming products. The original developer retains |
| full right to use the code for the developer's own purpose, assign or |
| donate the code to a third party and to inhibit third party from using |
| the code for non MPEG-2 aac/MPEG-4 Audio conforming products. This |
| copyright notice must be included in all copies or derivative works. |
| Copyright (c)1997. |
| |
| ------------------------------------------------------------------------------ |
| PSEUDO-CODE |
| |
| pPredicted_spectral = &predicted_spectral[0]; |
| pPredicted_spectral_start = pPredicted_spectral; |
| pSfb_prediction_used = &sfb_prediction_used[0]; |
| |
| IF (win_seq != EIGHT_SHORT_SEQUENCE) |
| THEN |
| |
| sfb_offset = 0; |
| |
| pWinSfbTop = &pWin_sfb_top[0]; |
| |
| pQ_format = &q_format[0]; |
| |
| FOR (i = sfb_per_frame; i>0; i--) |
| |
| IF (*(pSfb_prediction_used++) != FALSE) |
| THEN |
| |
| pPredicted_offset = pPredicted_spectral_start + |
| sfb_offset; |
| pCurrent_frame = ¤t_frame[sfb_offset]; |
| |
| quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2; |
| |
| max = 0; |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| FOR (j = (*pWinSfbTop - sfb_offset); j>0 ; j--) |
| |
| tmpInt32 = *(pPredicted_spectral++); |
| |
| IF (tmpInt32 < 0) |
| THEN |
| |
| tmpInt32 = -tmpInt32; |
| |
| ENDIF |
| |
| max |= tmpInt32; |
| |
| ENDFOR |
| |
| tmpInt = 0; |
| |
| IF (max != 0) |
| THEN |
| |
| WHILE (max < 0x40000000L) |
| |
| max <<= 1; |
| tmpInt++; |
| |
| ENDWHILE |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pPredicted_spectral++) <<= tmpInt; |
| *(pPredicted_spectral++) <<= tmpInt; |
| *(pPredicted_spectral++) <<= tmpInt; |
| *(pPredicted_spectral++) <<= tmpInt; |
| |
| ENDFOR |
| |
| adjusted_pred_q = pred_q_format + tmpInt; |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| shift_factor = *(pQ_format) - adjusted_pred_q; |
| |
| IF ((shift_factor >= 0) && (shift_factor < 31)) |
| THEN |
| |
| shift_factor = shift_factor + 1; |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) |
| + (*(pPredicted_spectral++)>>1); |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) |
| + (*(pPredicted_spectral++)>>1); |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) |
| + (*(pPredicted_spectral++)>>1); |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) |
| + (*(pPredicted_spectral++)>>1); |
| |
| ENDFOR |
| |
| *(pQ_format) = adjusted_pred_q - 1; |
| |
| ELSEIF (shift_factor >= 31) |
| THEN |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| |
| ENDFOR |
| |
| *(pQ_format) = adjusted_pred_q; |
| |
| ELSEIF ((shift_factor < 0) && (shift_factor > -31)) |
| THEN |
| |
| shift_factor = 1 - shift_factor; |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| |
| ENDFOR |
| |
| *(pQ_format) = *(pQ_format) - 1; |
| |
| ENDIF |
| |
| ENDIF |
| |
| ENDIF [ IF (*(pSfb_prediction_used++) != FALSE) ] |
| |
| sfb_offset = *pWinSfbTop; |
| pWinSfbTop = pWinSfbTop + 1; |
| pQ_format = pQ_format + 1; |
| |
| ENDFOR [ FOR (i = sfb_per_frame; i>0; i--) ] |
| |
| ELSE |
| |
| pCurrent_frame_start = ¤t_frame[0]; |
| |
| pQ_format_start = &q_format[0]; |
| |
| num_sfb = sfb_per_win[0]; |
| |
| FOR (wnd=0; wnd<short_window_num; wnd++) |
| |
| pWinSfbTop = &pWin_sfb_top[0]; |
| |
| pQ_format = pQ_format_start; |
| |
| IF (win_prediction_used[wnd] != FALSE) |
| THEN |
| |
| sfb_offset = 0; |
| |
| FOR (i = reconstruct_sfb_num; i > 0; i--) |
| |
| pPredicted_offset = pPredicted_spectral_start + |
| sfb_offset; |
| pCurrent_frame = pCurrent_frame_start + sfb_offset; |
| |
| quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2; |
| |
| max = 0; |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| FOR (j = (*pWinSfbTop - sfb_offset); j>0 ; j--) |
| |
| tmpInt32 = *(pPredicted_spectral++); |
| |
| IF (tmpInt32 < 0) |
| THEN |
| |
| tmpInt32 = -tmpInt32; |
| |
| ENDIF |
| |
| max |= tmpInt32; |
| |
| ENDFOR |
| |
| tmpInt = 0; |
| |
| IF (max != 0) |
| THEN |
| |
| WHILE (max < 0x40000000L) |
| |
| max <<= 1; |
| tmpInt++; |
| |
| ENDWHILE |
| |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pPredicted_spectral++) <<= tmpInt; |
| *(pPredicted_spectral++) <<= tmpInt; |
| *(pPredicted_spectral++) <<= tmpInt; |
| *(pPredicted_spectral++) <<= tmpInt; |
| |
| ENDFOR |
| |
| adjusted_pred_q = pred_q_format + tmpInt; |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| shift_factor = *(pQ_format) - adjusted_pred_q; |
| |
| IF ((shift_factor >= 0) && (shift_factor < 31)) |
| THEN |
| |
| shift_factor = shift_factor + 1; |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) + |
| (*(pPredicted_spectral++)>>1); |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) + |
| (*(pPredicted_spectral++)>>1); |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) + |
| (*(pPredicted_spectral++)>>1); |
| *(pCurrent_frame++) = |
| (*pCurrent_frame>>shift_factor) + |
| (*(pPredicted_spectral++)>>1); |
| |
| ENDFOR |
| |
| *(pQ_format) = adjusted_pred_q - 1; |
| |
| ELSEIF (shift_factor >= 31) |
| THEN |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| *(pCurrent_frame++) = *(pPredicted_spectral++); |
| |
| ENDFOR |
| |
| *(pQ_format) = adjusted_pred_q; |
| |
| ELSEIF ((shift_factor < 0) && (shift_factor > -31)) |
| THEN |
| |
| shift_factor = 1 - shift_factor; |
| |
| FOR (j = quarter_sfb_width; j>0 ; j--) |
| |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| *(pCurrent_frame++) = (*pCurrent_frame>>1) + |
| (*(pPredicted_spectral++)>>shift_factor); |
| |
| ENDFOR |
| |
| *(pQ_format) = *(pQ_format) - 1; |
| |
| ENDIF |
| |
| ENDIF |
| |
| sfb_offset = *pWinSfbTop; |
| pWinSfbTop = pWinSfbTop + 1; |
| pQ_format = pQ_format + 1; |
| |
| ENDFOR [ FOR (i = reconstruct_sfb_num; i > 0; i--) ] |
| |
| ENDIF [ IF (win_prediction_used[wnd] != FALSE) ] |
| |
| pPredicted_spectral_start = pPredicted_spectral_start + num_sfb; |
| pCurrent_frame_start = pCurrent_frame_start + num_sfb; |
| wnd_offset = wnd_offset + num_sfb; |
| pQ_format_start = pQ_format_start + num_sfb; |
| |
| ENDFOR [ FOR (wnd=0; wnd<short_window_num; wnd++) ] |
| |
| ENDIF [ IF (win_seq != EIGHT_SHORT_SEQUENCE) ] |
| |
| RETURN |
| |
| ------------------------------------------------------------------------------ |
| 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 "pv_audio_type_defs.h" |
| #include "e_window_sequence.h" |
| #include "long_term_synthesis.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 long_term_synthesis( |
| WINDOW_SEQUENCE win_seq, |
| Int sfb_per_win, |
| Int16 win_sfb_top[], |
| Int win_prediction_used[], |
| Int sfb_prediction_used[], |
| Int32 current_frame[], |
| Int q_format[], /* for each sfb */ |
| Int32 predicted_spectral[], |
| Int pred_q_format, /* for predicted_spectral[] */ |
| Int coef_per_win, |
| Int short_window_num, |
| Int reconstruct_sfb_num) |
| { |
| /*---------------------------------------------------------------------------- |
| ; Define all local variables |
| ----------------------------------------------------------------------------*/ |
| /* Scalefactor band offset */ |
| Int sfb_offset; |
| |
| /* Window index */ |
| Int wnd; |
| |
| /* Pointer to array containing predicted samples */ |
| Int32 *pPredicted_spectral; |
| |
| /* Pointer to the beginning of array containing predicted samples */ |
| Int32 *pPredicted_spectral_start; |
| |
| Int32 *pPredicted_offset; |
| |
| /* Pointer to array containing current spectral components for a channel*/ |
| Int32 *pCurrent_frame; |
| |
| /* Another pointer to array containing current spectral components */ |
| Int32 *pCurrent_frame_start; |
| |
| /* Pointer to prediction flag for each scalefactor band */ |
| Int *pSfb_prediction_used; |
| |
| /* Pointer to top coef per scalefactor band */ |
| Int16 *pWinSfbTop; |
| |
| /* Pointer to q_format array */ |
| Int *pQ_format; |
| Int *pQ_format_start; |
| Int32 temp; |
| |
| Int i; |
| Int j; |
| |
| Int quarter_sfb_width; |
| Int num_sfb; |
| Int shift_factor; |
| |
| UInt32 max; |
| Int32 tmpInt32; |
| |
| Int tmpInt; |
| Int adjusted_pred_q; |
| Int pred_shift; |
| |
| /*---------------------------------------------------------------------------- |
| ; Function body here |
| ----------------------------------------------------------------------------*/ |
| /* Initialize pointers */ |
| pPredicted_spectral = &predicted_spectral[0]; |
| pPredicted_spectral_start = pPredicted_spectral; |
| |
| /* |
| * NOTE: |
| * sfb_prediction_used[] start from 0 or 1 depending on nok_lt_decode.c; |
| * currently we agree to make it start from 0; |
| */ |
| pSfb_prediction_used = &sfb_prediction_used[0]; |
| |
| /*********************************/ |
| /* LTP synthesis for long window */ |
| /*********************************/ |
| if (win_seq != EIGHT_SHORT_SEQUENCE) |
| { |
| |
| /*******************************************************/ |
| /* Reconstruction of current frequency domain spectrum */ |
| /*******************************************************/ |
| |
| /* Initialize scalefactor band offset */ |
| sfb_offset = 0; |
| |
| /* |
| * Reconstruction is processed on scalefactor band basis. |
| * 1. When prediction is turned on, all the predicted spectral |
| * components will be used for reconstruction. |
| * 2. When prediction is turned off, reconstruction is not |
| * needed. Spectral components of current frame will directly |
| * come from the transmitted data. |
| */ |
| pWinSfbTop = &win_sfb_top[0]; |
| |
| pQ_format = &q_format[0]; |
| |
| for (i = sfb_per_win; i > 0; i--) |
| { |
| /* Check prediction flag for each scalefactor band. */ |
| if (*(pSfb_prediction_used++) != FALSE) |
| { |
| /* |
| * Prediction is on. Do reconstruction routine. |
| * Reconstruct spectral component of current |
| * frame by adding the predicted spectral |
| * components and the quantized prediction |
| * errors that reconstructed from transmitted |
| * data when prediction is turned on. |
| */ |
| |
| /* Set pointers to the offset of scalefactor bands */ |
| pPredicted_offset = pPredicted_spectral_start + |
| sfb_offset; |
| pCurrent_frame = ¤t_frame[sfb_offset]; |
| |
| /* |
| * (*pWinSfbTop - sfb_offset) is number of coefficients |
| * of the scalefactor band. |
| * ">>2" is used to set up for later unrolling the loop. |
| */ |
| quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2; |
| |
| /* |
| * Adjust pred_q_format and predicted_spectral() to |
| * maximum resolution. |
| */ |
| max = 0; |
| |
| pPredicted_spectral = pPredicted_offset; |
| |
| /* Find the maximum absolute value */ |
| for (j = (*pWinSfbTop - sfb_offset); j > 0 ; j--) |
| { |
| tmpInt32 = *(pPredicted_spectral++); |
| |
| /* |
| * Note: overflow is protected here even though |
| * tmpInt32 = 0x80000000 is very rare case. |
| * |
| * if (tmpInt32 == LONG_MIN) |
| * { |
| * tmpInt32 = LONG_MAX; |
| * } |
| * if (tmpInt32 < 0) |
| * { |
| * tmpInt32 = -tmpInt32; |
| * } |
| */ |
| |
| max |= tmpInt32 ^(tmpInt32 >> 31); |
| } |
| |
| /* |
| * IF the LTP data is all zeros |
| * (max == 0) - do nothing for this sfb. |
| */ |
| |
| if (max != 0) |
| { |
| /* Find the number of bits to reach the max resolution */ |
| tmpInt = 0; |
| |
| while (max < 0x40000000L) |
| { |
| max <<= 1; |
| tmpInt++; |
| } |
| |
| /* |
| * The following codes are combinded into shift factor |
| * adjusting and reconstruction section. |
| * |
| * pPredicted_spectral = pPredicted_offset; |
| * for(j = quarter_sfb_width; j>0 ; j--) |
| * { |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * } |
| * |
| */ |
| |
| /* Adjust Q format for predicted_spectral() */ |
| adjusted_pred_q = pred_q_format + tmpInt; |
| |
| /* |
| * Adjust Q format to prevent overflow that may occur during |
| * frequency domain reconstruction. |
| * |
| */ |
| pPredicted_spectral = pPredicted_offset; |
| |
| shift_factor = *(pQ_format) - adjusted_pred_q; |
| |
| if ((shift_factor >= 0) && (shift_factor < 31)) |
| { |
| shift_factor = shift_factor + 1; |
| pred_shift = tmpInt - 1; |
| |
| if (pred_shift >= 0) |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| } |
| } |
| else |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| } |
| } |
| |
| /* Updated new Q format for current scalefactor band */ |
| *(pQ_format) = adjusted_pred_q - 1; |
| } |
| else if (shift_factor >= 31) |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| } |
| |
| /* Updated new Q format for current scalefactor band */ |
| *(pQ_format) = adjusted_pred_q ; |
| } |
| else if ((shift_factor < 0) && (shift_factor > -31)) |
| { |
| shift_factor = 1 - shift_factor; |
| pred_shift = tmpInt - shift_factor; |
| |
| if (pred_shift >= 0) |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| } |
| } |
| else |
| { |
| pred_shift = -pred_shift; |
| |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| } |
| } |
| |
| /* |
| * Updated new Q format for current scalefactor band |
| * |
| * This is NOT a pointer decrement |
| */ |
| (*pQ_format)--; |
| } |
| |
| } /* if (max != 0) */ |
| |
| /* |
| * For case (shift_factor <= -31), *pCurrent_frame and |
| * *pQ_format do not need to be updated. |
| */ |
| |
| } /* if (*(pSfb_prediction_used++) != FALSE) */ |
| |
| /* Updated to next scalefactor band. */ |
| sfb_offset = *(pWinSfbTop++); |
| |
| /* Updated pointer to next scalefactor band's Q-format */ |
| pQ_format++; |
| |
| } /* for (i = sfb_per_frame; i>0; i--) */ |
| |
| } /* if (win_seq!=EIGHT_SHORT_SEQUENCE) */ |
| |
| /**********************************/ |
| /* LTP synthesis for short window */ |
| /**********************************/ |
| else |
| { |
| /******************************************************/ |
| /*Reconstruction of current frequency domain spectrum */ |
| /******************************************************/ |
| pCurrent_frame_start = ¤t_frame[0]; |
| |
| pQ_format_start = &q_format[0]; |
| |
| num_sfb = sfb_per_win; |
| |
| /* Reconstruction is processed on window basis */ |
| for (wnd = 0; wnd < short_window_num; wnd++) |
| { |
| pWinSfbTop = &win_sfb_top[0]; |
| |
| pQ_format = pQ_format_start; |
| |
| /* Check if prediction flag is on for each window */ |
| if (win_prediction_used[wnd] != FALSE) |
| { |
| /* Initialize scalefactor band offset */ |
| sfb_offset = 0; |
| |
| /* |
| * Reconstruction is processed on scalefactor band basis. |
| * 1. When prediction is turned on, all the predicted |
| * spectral components will be used for reconstruction. |
| * 2. When prediction is turned off, reconstruction is |
| * not needed. Spectral components of current frame |
| * will directly come from the transmitted data. |
| */ |
| |
| /* |
| * According to ISO/IEC 14496-3 pg.91 |
| * Only the spectral components in first eight scalefactor |
| * bands are added to the quantized prediction error. |
| */ |
| for (i = reconstruct_sfb_num; i > 0; i--) |
| { |
| /* Set pointer to the offset of scalefactor bands */ |
| pPredicted_offset = pPredicted_spectral_start + |
| sfb_offset; |
| pCurrent_frame = pCurrent_frame_start + sfb_offset; |
| |
| /* |
| * Prediction is on. Do reconstruction routine. |
| * Reconstruct spectral component of |
| * current frame by adding the predicted |
| * spectral components and the quantized |
| * prediction errors that reconstructed |
| * from transmitted data when prediction |
| * is turned on. |
| */ |
| |
| /* |
| * (*pWinSfbTop - sfb_offset) is number of coefficients |
| * of the scalefactor band. |
| * ">>2" is used to set up for later unrolling the loop. |
| */ |
| quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2; |
| |
| /* |
| * Adjust pred_q_format and predicted_spectral() to |
| * maximum resolution. |
| */ |
| max = 0; |
| pPredicted_spectral = pPredicted_offset; |
| |
| /* Find the maximum absolute value */ |
| for (j = (*pWinSfbTop - sfb_offset); j > 0 ; j--) |
| { |
| tmpInt32 = *(pPredicted_spectral++); |
| |
| |
| /* |
| * Note: overflow is protected here even though |
| * tmpInt32 = 0x80000000 is very rare case. |
| * |
| * if (tmpInt32 == LONG_MIN) |
| * { |
| * tmpInt32 = LONG_MAX; |
| * } |
| * if (tmpInt32 < 0) |
| * { |
| * tmpInt32 = -tmpInt32; |
| * } |
| */ |
| |
| max |= tmpInt32 ^(tmpInt32 >> 31); |
| } |
| |
| if (max != 0) |
| { |
| /* Find the number of bits to reach |
| * the max resolution |
| */ |
| tmpInt = 0; |
| |
| while (max < 0x40000000L) |
| { |
| max <<= 1; |
| tmpInt++; |
| } |
| /* |
| * The following codes are combined into shift factor |
| * adjusting and reconstruction section. |
| * |
| * pPredicted_spectral = pPredicted_offset; |
| * for(j = quarter_sfb_width; j>0 ; j--) |
| * { |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * *(pPredicted_spectral++) <<= tmpInt; |
| * } |
| * |
| */ |
| |
| /* Adjust Q format for predicted_spectral() */ |
| adjusted_pred_q = pred_q_format + tmpInt; |
| |
| /* |
| * Adjust Q format to prevent overflow that may occur |
| * during frequency domain reconstruction. |
| */ |
| pPredicted_spectral = pPredicted_offset; |
| |
| shift_factor = *(pQ_format) - adjusted_pred_q; |
| |
| if ((shift_factor >= 0) && (shift_factor < 31)) |
| { |
| shift_factor = shift_factor + 1; |
| |
| pred_shift = tmpInt - 1; |
| |
| if (pred_shift >= 0) |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) << pred_shift); |
| |
| } |
| } |
| else |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| temp = *pCurrent_frame >> shift_factor; |
| *(pCurrent_frame++) = temp |
| + (*(pPredicted_spectral++) >> 1); |
| } |
| } |
| |
| /* Updated new Q format for current scalefactor band*/ |
| *(pQ_format) = adjusted_pred_q - 1; |
| } |
| else if (shift_factor >= 31) |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| *(pCurrent_frame++) = |
| *(pPredicted_spectral++) << tmpInt; |
| } |
| |
| /* Updated new Q format for current scalefactor band*/ |
| *(pQ_format) = adjusted_pred_q; |
| } |
| else if ((shift_factor < 0) && (shift_factor > -31)) |
| { |
| shift_factor = 1 - shift_factor; |
| |
| pred_shift = tmpInt - shift_factor; |
| |
| if (pred_shift >= 0) |
| { |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) << pred_shift); |
| |
| } |
| } |
| else |
| { |
| pred_shift = -pred_shift; |
| |
| for (j = quarter_sfb_width; j > 0 ; j--) |
| { |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| temp = *pCurrent_frame >> 1; |
| *(pCurrent_frame++) = temp + |
| (*(pPredicted_spectral++) >> pred_shift); |
| } |
| } |
| |
| /* Updated new Q format for current scalefactor band*/ |
| *(pQ_format) = *(pQ_format) - 1; |
| } |
| |
| /* |
| * For case (shift_factor <= -31), *pCurrent_frame and |
| * *pQ_format do not need to be updated. |
| */ |
| |
| } /* if (max != 0) */ |
| |
| /* Updated to next scalefactor band. */ |
| sfb_offset = *(pWinSfbTop++); |
| |
| /* Updated pointer to next scalefactor band's Q-format */ |
| pQ_format++; |
| |
| } /* for (i = reconstruct_sfb_num; i > 0; i--) */ |
| |
| } /* if (win_prediction_used[wnd] != FALSE) */ |
| |
| /* Updated to next window */ |
| pPredicted_spectral_start += coef_per_win; |
| pCurrent_frame_start += coef_per_win; |
| pQ_format_start += num_sfb; |
| |
| } /* for (wnd=0; wnd<short_window_num; wnd++) */ |
| |
| } /* else */ |
| |
| /*---------------------------------------------------------------------------- |
| ; Return nothing or data or data pointer |
| ----------------------------------------------------------------------------*/ |
| return; |
| } /* long_term_synthesis */ |
| |
| |