blob: 69e4c466fedf1ca80fc74c174a1adde155fbb691 [file] [log] [blame]
/* ------------------------------------------------------------------
* 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 */