www.pudn.com > mp3rar.rar > nok_lt_prediction.c
/************************************************************************** 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. ***************************************************************************/ /************************************************************************** nok_lt_prediction.c - Performs Long Term Prediction for the MPEG-4 T/F Decoder. Author(s): Mikko Suonio, Juha Ojanperä Nokia Research Center, Speech and Audio Systems, 1997. *************************************************************************/ /************************************************************************** Version Control Information Method: CVS Identifiers: $Revision: 1.8 $ $Date: 2000/01/19 15:12:18 $ (check in) $Author: menno $ *************************************************************************/ /************************************************************************** External Objects Needed *************************************************************************/ /* Standard library declarations. */ #include/* Interface to related modules. */ #include "all.h" #include "dolby_def.h" #include "block.h" #include "nok_ltp_common.h" /* Macro: PRINT Purpose: Interface to function for printing error messages. */ /* Enum constant:MAX_SHORT_WINDOWS Purpose: Gives the maximum number of subblocks (short windows). Explanation: - */ /* Variable: debug Purpose: Provided debug options. Explanation: If element debug['p'] is true, we give debug information on long term prediction. */ /* Function: buffer2freq Call: buffer2freq (p_in_data, p_out_mdct, p_overlap, block_type, wfun_select, nlong, nmed, nshort, overlap_select, num_short_win, save_window); Purpose: Modified discrete cosine transform Input: p_in_data[] - input signal (length: 2*shift length) p_overlap[] - buffer containing the previous frame in OVERLAPPED-mode (length: 2*shift length) block_type - selects the type of window to use wfun_select - select window function nlong - shift length for long windows nmed - shift length for medium windows nshort - shift length for short windows overlap_select - OVERLAPPED-mode select num_short_win - number of short windows to transform save_window - if true, save the block_type for future use Output: p_out_mdct[] - transformed signal (length: shift length) p_overlap[] - a copy of p_in_data in OVERLAPPED-mode (length: shift length) Explanation: - */ /* Function: freq2buffer Call: freq2buffer (p_in_data, p_out_data, p_overlap, block_type, nlong, nmed, nshort, wfun_select, fun_select_prev, overlap_select, num_short_win); Purpose: Inverse of modified discrete cosine transform Input: p_in_data[] - input signal (length: shift length) p_overlap[] - the overlap buffer; does not have an effect in NON_OVERLAPPED-mode, but have to be allocated (length: shift length) block_type - selects the type of window to use nlong - shift length for long windows nmed - shift length for medium windows nshort - shift length for short windows wfun_select - select window function overlap_select - OVERLAPPED-mode select num_short_win - number of short windows to transform save_window - if true, save block_type for future use Output: p_out_data[] - transformed signal (length: 2*shift length) p_overlap[] - the overlap buffer; always modified (length: shift length) Explanation: - */ /* Function: getbits Purpose: Reads specified number of bits from the open input bitstream. */ /************************************************************************** External Objects Provided *************************************************************************/ #include "nok_lt_prediction.h" /************************************************************************** Internal Objects *************************************************************************/ #include "nok_ltp_common_internal.h" short double_to_int (double sig_in); /************************************************************************** Object Definitions *************************************************************************/ /************************************************************************** Title: nok_init_lt_pred Purpose: Initialize the history buffer for long term prediction Usage: nok_init_lt_pred (lt_status) Input: lt_status - buffer: history buffer Output: lt_status - buffer: filled with 0 References: - Explanation: - Author(s): Mikko Suonio *************************************************************************/ void nok_init_lt_pred (NOK_LT_PRED_STATUS *lt_status) { int i; for (i = 0; i < NOK_LT_BLEN; i++) lt_status->buffer[i] = 0; lt_status->weight = 0; for(i=0; i sbk_prediction_used[i] = lt_status->delay[i] = 0; for(i=0; i sfb_prediction_used[i] = 0; } /************************************************************************** Title: nok_lt_prediction Purpose: Performs long term prediction using given coefficients. Usage: nok_lt_predict (profile, info, win_type, win_shape, sbk_prediction_used, sfb_prediction_used, lt_status, weight, delay, current_frame) Input: profile - currently not used info - information on the current frame nsbk: number of subblocks (subwindows) in a block (window sequence) bins_per_sbk: number of spectral coefficients in each subblock; currently we assume that they are of equal size sfb_per_bk: total number of scalefactor bands in a block sfb_per_sbk: number of scalefactor bands in each subblock win_type - window sequence (frame, block) type win_shape - shape of the mdct window sbk_prediction_used - first item toggles prediction on(1)/off(0) for all subblocks, next items toggle it on/off on each subblock separately sfb_prediction_used - first item is not used, but the following items toggle prediction on(1)/off(0) on each scalefactor-band of every subblock lt_status - history buffer for prediction weight - a weight factor to apply to all subblocks delay - array of delays to apply to each subblock current_frame - the dequantized spectral coeffients and prediction errors where prediction is used block_size_long - size of the long block block_size_medium - size of the medium block block_size_short - size of the short block Output: current_frame - the dequantized spectrum possible with a prediction vector added References: 1.) buffer2freq 2.) double_to_int 3.) freq2buffer Explanation: - Author(s): Mikko Suonio, Juha Ojanperä *************************************************************************/ void nok_lt_predict (int profile, Info *info, WINDOW_TYPE win_type, Wnd_Shape *win_shape, int *sbk_prediction_used, int *sfb_prediction_used, NOK_LT_PRED_STATUS *lt_status, Float weight, int *delay, Float *current_frame, int block_size_long, int block_size_medium, int block_size_short ) { int i, j; float_ext current_frame_double[NOK_MAX_BLOCK_LEN_LONG]; float_ext mdct_predicted[2 * NOK_MAX_BLOCK_LEN_LONG]; float_ext overlap_buffer[2 * NOK_MAX_BLOCK_LEN_LONG]; float_ext predicted_samples[2 * NOK_MAX_BLOCK_LEN_LONG]; /* printf ("long: %d, med: %d, short: %d.\n", block_size_long, block_size_medium, block_size_short); */ switch(win_type) { case ONLY_LONG_WINDOW: case LONG_START_WINDOW: case LONG_STOP_WINDOW: if (sbk_prediction_used[0]) { /* Prediction for time domain signal */ j = NOK_LT_BLEN - 2 * block_size_long - delay[0]; for (i = 0; i < 2 * block_size_long; i++) predicted_samples[i] = weight * lt_status->buffer[i + j]; /* Transform prediction to frequency domain. */ time2freq_adapt ((byte)win_type, win_shape, predicted_samples, mdct_predicted); /* Clean those sfb's where prediction is not used. */ for (i = 0, j = 0; i < info->sfb_per_bk; i++) if (sfb_prediction_used[i + 1] == 0) for (; j < info->sbk_sfb_top[0][i]; j++) mdct_predicted[j] = 0.0; else j = info->sbk_sfb_top[0][i]; /* Add the prediction to dequantized spectrum. */ for (i = 0; i < block_size_long; i++) current_frame[i] = current_frame[i] + mdct_predicted[i]; } for (i = 0; i < block_size_long; i++) { current_frame_double[i] = (float_ext)current_frame[i]; overlap_buffer[i] = 0; } /* Finally update the time domain history buffer. */ freq2time_adapt ((byte)win_type, win_shape, current_frame_double, overlap_buffer, predicted_samples); for (i = 0; i < NOK_LT_BLEN - block_size_long; i++) lt_status->buffer[i] = lt_status->buffer[i + block_size_long]; j = NOK_LT_BLEN - 2 * block_size_long; for (i = 0; i < block_size_long; i++) { lt_status->buffer[i + j] = double_to_int (predicted_samples[i] + lt_status->buffer[i + j]); lt_status->buffer[NOK_LT_BLEN - block_size_long + i] = double_to_int (overlap_buffer[i]); } break; case EIGHT_SHORT_WINDOW: /* Prepare the buffer for all forthcoming short windows at once. This could be done as the long window case, but that would be inefficient. We have to take this into account when referencing the buffer. */ #if 0 for (i = 0; i < NOK_LT_BLEN - block_size_long; i++) lt_status->buffer[i] = lt_status->buffer[i + block_size_long]; for (i = NOK_LT_BLEN - block_size_long; i < NOK_LT_BLEN; i++) lt_status->buffer[i] = 0; for (i = 0; i < block_size_long; i++) { current_frame_double[i] = (float_ext)current_frame[i]; overlap_buffer[i] = 0; } freq2time_adapt (win_type, win_shape, current_frame_double, overlap_buffer, predicted_samples); j = NOK_LT_BLEN - 2 * block_size_long + SHORT_SQ_OFFSET; for (i = 0; i < block_size_long; i++) { lt_status->buffer[i + j] = double_to_int (predicted_samples[i] + lt_status->buffer[i + j]); lt_status->buffer[i + block_size_long + j] = double_to_int (overlap_buffer[i]); } #endif break; default: break; } } /************************************************************************** Title: double_to_int Purpose: Converts floating point format to integer (16-bit). Usage: y = double_to_int(sig_in) Input: sig_in - floating point number Output: y - integer number References: - Explanation: - Author(s): Juha Ojanpera *************************************************************************/ short double_to_int (double sig_in) { short sig_out; if (sig_in > 32767) sig_out = 32767; else if (sig_in < -32768) sig_out = -32768; else if (sig_in > 0.0) sig_out = (short) (sig_in + 0.5); else if (sig_in <= 0.0) sig_out = (short) (sig_in - 0.5); return (sig_out); } /************************************************************************** Title: nok_lt_decode Purpose: Decode the bitstream elements for long term prediction Usage: nok_lt_decode (win_type, max_sfb, sbk_prediction_used, sfb_prediction_used, weight, delay) Input: win_type - window sequence (frame, block) type max_sfb - number of scalefactor bands used in the current frame Output: sbk_prediction_used - first item toggles prediction on(1)/off(0) for all subblocks, next items toggle it on/off on each subblock separately sfb_prediction_used - first item is not used, but the following items toggle prediction on(1)/off(0) on each scalefactor-band of every subblock weight - a weight factor to apply to all subblocks delay - array of delays to apply to each subblock References: 1.) getbits 2.) PRINT Explanation: - Author(s): Mikko Suonio *************************************************************************/ void nok_lt_decode (WINDOW_TYPE win_type, int max_sfb, int *sbk_prediction_used, int *sfb_prediction_used, Float *weight, int *delay) { int i, j, last_band; int prev_subblock; if ((sbk_prediction_used[0] = getbits (LEN_LTP_DATA_PRESENT))) { delay[0] = getbits (LEN_LTP_LAG); *weight = (float)codebook[getbits (LEN_LTP_COEF)]; if (win_type != EIGHT_SHORT_WINDOW) { last_band = (max_sfb < NOK_MAX_LT_PRED_LONG_SFB ? max_sfb : NOK_MAX_LT_PRED_LONG_SFB) + 1; sfb_prediction_used[0] = sbk_prediction_used[0]; for (i = 1; i < last_band; i++) sfb_prediction_used[i] = getbits (LEN_LTP_LONG_USED); for (; i < max_sfb + 1; i++) sfb_prediction_used[i] = 0; } else { last_band = (max_sfb < NOK_MAX_LT_PRED_SHORT_SFB) ? max_sfb : NOK_MAX_LT_PRED_SHORT_SFB; prev_subblock = -1; for (i = 0; i < NSHORT; i++) { if ((sbk_prediction_used[i+1] = getbits (LEN_LTP_SHORT_USED))) { if(prev_subblock == -1) { delay[i] = delay[0]; prev_subblock = i; } else { if (getbits (LEN_LTP_SHORT_LAG_PRESENT)) { delay[i] = getbits (LEN_LTP_SHORT_LAG); delay[i] -= NOK_LTP_LAG_OFFSET; delay[i] = delay[prev_subblock] - delay[i]; } else delay[i] = delay[prev_subblock]; } for (j = 0; j < last_band; j++) sfb_prediction_used[i * last_band + j] = 1; } } } } }