diff options
author | Andreas Huber <andih@google.com> | 2009-12-07 09:56:32 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2009-12-07 11:02:28 -0800 |
commit | dacaa73ae5010b66f4224d70a520945e5b653544 (patch) | |
tree | a2c9e71b6337dd25d149bd5fa43f7a782e9387fb /media/libstagefright/codecs/aacdec/long_term_prediction.cpp | |
parent | 5921fb51e0219ddd7cad439a73495f320c57d50e (diff) | |
download | frameworks_base-dacaa73ae5010b66f4224d70a520945e5b653544.zip frameworks_base-dacaa73ae5010b66f4224d70a520945e5b653544.tar.gz frameworks_base-dacaa73ae5010b66f4224d70a520945e5b653544.tar.bz2 |
Initial check in of stagefright software AAC decoder based on PV source code.
Diffstat (limited to 'media/libstagefright/codecs/aacdec/long_term_prediction.cpp')
-rw-r--r-- | media/libstagefright/codecs/aacdec/long_term_prediction.cpp | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/aacdec/long_term_prediction.cpp b/media/libstagefright/codecs/aacdec/long_term_prediction.cpp new file mode 100644 index 0000000..69e4c46 --- /dev/null +++ b/media/libstagefright/codecs/aacdec/long_term_prediction.cpp @@ -0,0 +1,648 @@ +/* ------------------------------------------------------------------ + * 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_prediction.c + +------------------------------------------------------------------------------ + REVISION HISTORY + + Description: Made changes based on comments and experiment results. + + Description: Passed in buffer sizes based on review comments and prototype + agreements. + + Description: 1. Passed in "weight_index" instead of "weight". + 2. Added weight table. + + Description: 1. Removed some passed in buffer size variables since they are + not used for long window. + 2. Modified comments format. + + Description: + Modified casting to ensure proper operations for different platforms + + Description: + Implemented circular buffer techniques, which save 4096 memmoves per + frame. + + Description: + Implemented some optimizations found during the code review of this + module. The optimizations related to the rules on the range of + ltp_buffer_index and num_samples, which allows for a simpler + code construct to be used in the processing of the predicted samples. + + Description: + Add max calculation on the filter implementation, this to eliminate + function buffer_adaptation() on the time to frequency transformation. + Function interface changed. It now return the amount of shifting needed + to garb only the top 16 MSB. + + Description: + Replace clearing memory with for-loop with pvmemset function + + Description: + +------------------------------------------------------------------------------ + INPUT AND OUTPUT DEFINITIONS + + Inputs: + win_seq = type of window sequence (WINDOW_SEQUENCE). + + weight_index = index (Int) of LTP coefficient table for all windows in + current frame. + + delay = buffer (Int) containing delays for each window. + + buffer = history buffer (Int16) containing the reconstructed time domain + signals of previous frames. + + buffer_offset = value (Int) that indicates the location of the first + element in the LTP circular buffer. (Either 0 or 1024) + + time_quant = filterbank buffer (Int32) This buffer is used by the + filterbank, but it's first 1024 elements are equivalent + to the last 1024 elements in the conventionally + implemented LTP buffer. Using this buffer directly avoids + costly duplication of memory. + + predicted_samples = buffer (Int32) with length of 2048 to hold + predicted time domain signals. + + buffer_index = index into buffer where the first sample of data from + the frame (t-2) (two frames ago) resides. (Int) + + frame_length = length of one frame, type of Int. + + Local Stores/Buffers/Pointers Needed: + None + + Global Stores/Buffers/Pointers Needed: + None + + Outputs: + Amount of shifting needed to grab the top 16 MSB from teh predicted buffer + + Pointers and Buffers Modified: + predicted_samples contents are the newly calculated predicted time + domain signals + + Local Stores Modified: + None + + Global Stores Modified: + None + +------------------------------------------------------------------------------ + FUNCTION DESCRIPTION + + Long term prediction (LTP) is used to reduce the redundancy of a signal + between successive coding frames. This function performs prediction by + applying 1-tap IIR filtering to calculate the predicted time domain + signals of current frame from previous reconstructed frames stored in + time domain history buffer. + + The equation used for IIR filter is as following. + + y(n) = weight * x(n - delay) + + where y(n) ----- predicted time domain signals + x(n) ----- reconstructed time domain signals + weight ----- LTP coefficient + delay ----- optimal delay from 0 to 2047 + +------------------------------------------------------------------------------ + 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_samples = &predicted_samples[0]; + + weight = codebook[weight_index]; + + IF (win_seq != EIGHT_SHORT_SEQUENCE) + THEN + + block_length = frame_length << 1; + + lag = delay[0]; + + j = block_length - lag; + + IF (lag < frame_length) + THEN + + num_samples = frame_length + lag; + + ELSE + + num_samples = block_length; + + ENDIF + + pBuffer = &buffer[j]; + + FOR (i = num_samples; i>0; i--) + + *pPredicted_samples = weight * (*pBuffer); + pPredicted_samples = pPredicted_samples + 1; + pBuffer = pBuffer + 1; + + ENDFOR + + FOR (i = block_length - num_samples; i>0; i--) + + *pPredicted_samples = 0; + pPredicted_samples = pPredicted_samples + 1; + + ENDFOR + + ELSE + + FOR (wnd = 0; wnd < short_window_num; wnd++) + + IF (win_prediction_used[wnd] != FALSE) + THEN + + delay[wnd] = delay[0] + ltp_short_lag[wnd]; + + lag = delay[wnd]; + + j = wnd*short_block_length - lag; + + IF (lag < short_frame_length) + THEN + + num_samples = short_frame_length + lag; + + ELSE + + num_samples = short_block_length; + + ENDIF + + pBuffer = &buffer[j]; + + FOR (i = num_samples; i>0; i--) + + *pPredicted_samples = weight * (*pBuffer); + pPredicted_samples = pPredicted_samples + 1; + pBuffer = pBuffer + 1; + + ENDFOR + + FOR (i = short_block_length - num_samples; i>0; i--) + + *pPredicted_samples = 0; + pPredicted_samples = pPredicted_samples + 1; + + ENDFOR + + ELSE + + CALL pv_memset( + pPredicted_samples, + 0, + sizeof(*pPredicted_samples)*short_block_length); + MODIFYING (predicted_samples[]); + + pPredicted_samples = pPredicted_samples + short_block_length; + + ENDIF [ IF (win_prediction_used[wnd] != FALSE) ] + + 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 "ltp_common_internal.h" +#include "long_term_prediction.h" +#include "aac_mem_funcs.h" +#include "pv_normalize.h" +#include "window_block_fxp.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 +----------------------------------------------------------------------------*/ +/* Purpose: Codebook for LTP weight coefficients. Stored in Q15 format */ +const UInt codebook[CODESIZE] = +{ + 18705, /* 0 */ + 22827, /* 1 */ + 26641, /* 2 */ + 29862, /* 3 */ + 32273, /* 4 */ + 34993, /* 5 */ + 39145, /* 6 */ + 44877 /* 7 */ +}; + +/*---------------------------------------------------------------------------- +; 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 +----------------------------------------------------------------------------*/ +Int long_term_prediction( + WINDOW_SEQUENCE win_seq, + const Int weight_index, + const Int delay[], + const Int16 buffer[], + const Int buffer_offset, + const Int32 time_quant[], + Int32 predicted_samples[], /* Q15 */ + const Int frame_length) +{ + /*---------------------------------------------------------------------------- + ; Define all local variables + ----------------------------------------------------------------------------*/ + /* + * Window index + * + * Int wnd; + * + * will be enabled when short window information is available. + */ + + /* Pointer to time domain history buffer */ + + const Int16 *pBuffer; + + const Int32 *pTimeQuant = time_quant; + + /* Pointer to array containing predicted samples */ + Int32 *pPredicted_samples; + + Int32 test; + Int32 datum; + + /* IIR coefficient with Q15 format */ + UInt weight; + + /* Length of one block (two frames) */ + Int block_length; + + Int shift; + Int k; + Int ltp_buffer_index; + Int jump_point; + Int lag; + Int num_samples; + + Int32 max = 0; + + /*---------------------------------------------------------------------------- + ; Function body here + ----------------------------------------------------------------------------*/ + /* Initialize pointers */ + pPredicted_samples = &predicted_samples[0]; + + weight = codebook[weight_index]; + + /****************************************/ + /* LTP decoding process for long window */ + /****************************************/ + + if (win_seq != EIGHT_SHORT_SEQUENCE) + { + /****************************************************/ + /* Prediction based on previous time domain signals */ + /****************************************************/ + block_length = frame_length << 1; + + /* Calculate time lag for 1-tap IIR filter */ + lag = delay[0]; + + ltp_buffer_index = block_length - lag; + + /* Calculate number of samples used in IIR filter */ + if (lag < frame_length) + { + num_samples = frame_length + lag; + } + else + { + num_samples = block_length; + } + + + /* + * Calculate the predicted time domain signals from the + * reconstructed time domain signals of previous frames. + */ + + /* The data is stored in TWO buffers, either as... + * + * [ t == 0 ] + * + * [ t == -1 ][ t == -2 ] + * + * OR... + * [ t == 0 ] + * + * [ t == -2 ][ t == -1 ] + * + * + * + * In the first case, all of the buffers are non-contiguous, + * and each must be handled separately. Code for this first case + * will function correctly for both cases. + * + * In the second case, the buffers storing t == -2, and t == -1 + * data are contiguous, and an optimization could take advantage + * of this, at the cost of an increase in code size for this function. + */ + + /* Decrement block_length by num_samples. This is important + * for the loop at the end of the "ACCESS DATA IN THE LTP BUFFERS" + * section that sets all remaining samples in the block to zero. + */ + + block_length -= num_samples; + + + + + + + /* + ************************************ ACCESS DATA IN THE LTP BUFFERS + */ + + /* + * This section of the code handles the t == -2 + * buffer, which corresponds to 0 <= ltp_buffer_index < 1024 + * + * BUFFER t == -2 + * + * [0][][][][][][][][][][][...][][][][][][][][][][][][1023] + * + */ + + jump_point = (frame_length - ltp_buffer_index); + + if (jump_point > 0) + { + pBuffer = &(buffer[ltp_buffer_index + buffer_offset]); + + for (k = jump_point; k > 0; k--) + { + /* Q15 = Q15 * Q0 */ + test = (Int32) weight * (*(pBuffer++)); + *(pPredicted_samples++) = test; + max |= (test >> 31) ^ test; + } + + num_samples -= jump_point; + + ltp_buffer_index += jump_point; + } + + /* + * This section of the code handles the t == -1 + * buffer, which corresponds to 1024 <= ltp_buffer_index < 2048 + * + * BUFFER t == -1 + * + * [1024][][][][][][][][][][][...][][][][][][][][][][][][2047] + * + */ + + jump_point = 2 * frame_length - ltp_buffer_index; + + pBuffer = &(buffer[ltp_buffer_index - buffer_offset]); + + if (num_samples < jump_point) + { + jump_point = num_samples; + } + + for (k = jump_point; k > 0; k--) + { + /* Q15 = Q15 * Q0 */ + test = (Int32) weight * (*(pBuffer++)); + *(pPredicted_samples++) = test; + max |= (test >> 31) ^ test; + } + + num_samples -= jump_point; + + ltp_buffer_index += jump_point; + + /* + * This section of the code handles the t == 0 + * buffer, which corresponds to 2048 <= ltp_buffer_index < 3072 + * + * BUFFER t == 0 + * + * [2048][][][][][][][][][][][...][][][][][][][][][][][][3071] + * + */ + for (k = num_samples; k > 0; k--) + { + + datum = *(pTimeQuant++) >> SCALING; + + /* + * Limit the values in the 32-bit filterbank's buffer to + * 16-bit resolution. + * + * Value's greater than 32767 or less than -32768 are saturated + * to 32767 and -32768, respectively. + */ + + test = (Int32)datum * weight; + *(pPredicted_samples++) = test; + max |= (test >> 31) ^ test; + + } + + /* Set any remaining samples in the block to 0. */ + + pv_memset( + pPredicted_samples, + 0, + block_length*sizeof(*pPredicted_samples)); + + } /* if (win_seq != EIGHT_SHORT_SEQUENCE) */ + + + /*****************************************/ + /* LTP decoding process for short window */ + /*****************************************/ + + /* + * For short window LTP, since there is no "ltp_short_lag" + * information being passed, the following code for short + * window LTP will be applied in the future when those + * information are available. + */ + + /* + *---------------------------------------------------------------------------- + * else + * { + * for (wnd = 0; wnd < short_window_num; wnd++) + * { + * if (win_prediction_used[wnd] != FALSE) + * { + * delay[wnd] = delay[0] + ltp_short_lag[wnd]; + * + * lag = delay[wnd]; + * + * j = wnd*short_block_length - lag; + * + * if (lag < short_frame_length) + * { + * num_samples = short_frame_length + lag; + * } + * else + * { + * num_samples = short_block_length; + * } + * + * pBuffer = &buffer[j]; + * + * for(i = num_samples; i>0; i--) + * { + * *(pPredicted_samples++) = weight * (*(pBuffer++)); + * } + * + * for(i = short_block_length - num_samples; i>0; i--) + * { + * *(pPredicted_samples++) = 0; + * } + * } + * else + * { + * pv_memset( + * pPredicted_samples, + * 0, + * sizeof(*pPredicted_samples)*short_block_length); + * + * pPredicted_samples += short_block_length; + * } + * } + * } + *---------------------------------------------------------------------------- + */ + + shift = 16 - pv_normalize(max); + + if (shift < 0) + { + shift = 0; + } + + /*---------------------------------------------------------------------------- + ; Return nothing or data or data pointer + ----------------------------------------------------------------------------*/ + return (shift); +} /* long_term_prediction */ + + + + |