📄 nok_ltp_enc.c
字号:
*************************************************************************/voidnok_ltp_reconstruct(double *p_spectrum, WINDOW_SEQUENCE win_type, int *sfb_offset, int num_of_sfb, int block_size_short, NOK_LT_PRED_STATUS *lt_status){ int i, sw; int last_band; if(lt_status->global_pred_flag) { switch(win_type) { case ONLY_LONG_SEQUENCE: case LONG_START_SEQUENCE: case LONG_STOP_SEQUENCE: last_band = (num_of_sfb < NOK_MAX_LT_PRED_LONG_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_LONG_SFB; for (i = 0; i < sfb_offset[last_band]; i++) p_spectrum[i] += lt_status->mdct_predicted[i]; break; case EIGHT_SHORT_SEQUENCE: last_band = (num_of_sfb < NOK_MAX_LT_PRED_SHORT_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_SHORT_SFB; for(sw = 0; sw < MAX_SHORT_WINDOWS; sw++) if(lt_status->sbk_prediction_used[sw]) for (i = 0; i < sfb_offset[last_band]; i++) p_spectrum[sw * block_size_short + i] += lt_status->mdct_predicted[sw * block_size_short + i]; break; default: break; } } }/************************************************************************** Title: nok_ltp_update Purpose: Updates the time domain buffer of LTP. Usage: nok_ltp_update(p_spectrum, win_type, win_shape, win_shape_prev, block_size_long, block_size_medium, block_size_short, lt_status) Input: p_spectrum - reconstructed spectrum win_type - window sequence (frame, block) type win_shape - shape of the mdct window win_shape_prev - shape from previous block 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: lt_status : buffer - history buffer for prediction References: 1.) freq2buffer in imdct.c 2.) double_to_int Explanation: - Author(s): Juha Ojanpera *************************************************************************/voidnok_ltp_update(double *p_spectrum, WINDOW_SEQUENCE win_type, WINDOW_SHAPE win_shape, WINDOW_SHAPE win_shape_prev, int block_size_long, int block_size_medium, int block_size_short, NOK_LT_PRED_STATUS *lt_status){ int i, j, sw; double predicted_samples[2 * NOK_MAX_BLOCK_LEN_LONG]; double overlap_buffer[2 * NOK_MAX_BLOCK_LEN_LONG]; for (i = 0; i < NOK_LT_BLEN - block_size_long; i++) lt_status->buffer[i] = lt_status->buffer[i + block_size_long]; switch(win_type) { case ONLY_LONG_SEQUENCE: case LONG_START_SEQUENCE: case LONG_STOP_SEQUENCE: /* Finally update the time domain history buffer. */ for (i = 0; i < block_size_long; i++){ /***TM */ overlap_buffer[i] = 0.; overlap_buffer[i+block_size_long] = 0.; predicted_samples[i] = 0.; predicted_samples[i+block_size_long] = 0.; } freq2buffer (p_spectrum, predicted_samples, overlap_buffer, win_type, block_size_long, block_size_medium, block_size_short, win_shape, win_shape_prev, NON_OVERLAPPED_MODE, -1); 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 (predicted_samples[i + block_size_long]); } break; case EIGHT_SHORT_SEQUENCE: for (i = NOK_LT_BLEN - block_size_long; i < NOK_LT_BLEN; i++) lt_status->buffer[i] = 0; for(sw = 0; sw < MAX_SHORT_WINDOWS; sw++) { /***TM */ for (i = 0; i < block_size_short; i++){ overlap_buffer[i+ sw *2* block_size_short] = 0.; overlap_buffer[i+ sw *2* block_size_short+block_size_short] = 0.; predicted_samples[i+ sw *2* block_size_short] = 0.; predicted_samples[i+ sw *2* block_size_short+block_size_short] = 0.; } } for(sw = 0; sw < MAX_SHORT_WINDOWS; sw++) { /* Finally update the time domain history buffer. */ freq2buffer (p_spectrum + sw * block_size_short, predicted_samples, overlap_buffer, win_type, block_size_long, block_size_medium, block_size_short, win_shape, win_shape_prev, NON_OVERLAPPED_MODE, 1); i = NOK_LT_BLEN - 2 * block_size_long + SHORT_SQ_OFFSET + sw * block_size_short; for (j = 0; j < 2 * block_size_short; j++) lt_status->buffer[i + j] = double_to_int (predicted_samples[j] + lt_status->buffer[i + j]); } break; default: break; }}/************************************************************************** Title: nok_ltp_encode Purpose: Writes LTP parameters to the bit stream. Usage: nok_ltp_encode (bs, win_type, num_of_sfb, lt_status, qc_select, coreCodecIdx, max_sfb_tvq_set) Input: bs - bit stream win_type - window sequence (frame, block) type num_of_sfb - number of scalefactor bands lt_status side_info - 1, if prediction not used in this frame > 1 otherwise weight_idx - 3 bit number indicating the LTP coefficient in the codebook sfb_prediction_used - 1 bit for each scalefactor band (sfb) where LTP can be used indicating whether LTP is switched on (1) /off (0) in that sfb. delay - LTP lag qc_select - MPEG4/TF codec type max_sfb_tvq_set - 1 if max_sfb need to be written into the bit stream, 0 otherwise Output: - References: 1.) BsPutBit Explanation: - Author(s): Juha Ojanpera *************************************************************************/intnok_ltp_encode (BsBitStream *bs, WINDOW_SEQUENCE win_type, int num_of_sfb, NOK_LT_PRED_STATUS *lt_status, QC_MOD_SELECT qc_select, enum CORE_CODEC coreCodecIdx, int max_sfb_tvq_set){ int i, last_band; int first_subblock; int prev_subblock; int bits_written; bits_written = 1; if (lt_status->global_pred_flag) { BsPutBit (bs, 1, 1); /* LTP used */ if(coreCodecIdx == NTT_TVQ && !max_sfb_tvq_set) { BsPutBit (bs, num_of_sfb, 6); /* max sfb. */ bits_written += 6; } switch(win_type) { case ONLY_LONG_SEQUENCE: case LONG_START_SEQUENCE: case LONG_STOP_SEQUENCE: { BsPutBit (bs, lt_status->delay[0], LEN_LTP_LAG); bits_written += LEN_LTP_LAG; } BsPutBit (bs, lt_status->weight_idx, LEN_LTP_COEF); bits_written += LEN_LTP_COEF; last_band = (num_of_sfb < NOK_MAX_LT_PRED_LONG_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_LONG_SFB; for (i = 0; i < last_band; i++) BsPutBit (bs, lt_status->sfb_prediction_used[i], LEN_LTP_LONG_USED); bits_written += last_band; break; case EIGHT_SHORT_SEQUENCE: for(i=0; i < MAX_SHORT_WINDOWS; i++) { if(lt_status->sbk_prediction_used[i]) { first_subblock = i; break; } } BsPutBit (bs, lt_status->delay[first_subblock], LEN_LTP_LAG); BsPutBit (bs, lt_status->weight_idx, LEN_LTP_COEF); bits_written += LEN_LTP_LAG + LEN_LTP_COEF; prev_subblock = first_subblock; for(i = 0; i < MAX_SHORT_WINDOWS; i++) { BsPutBit (bs, lt_status->sbk_prediction_used[i], LEN_LTP_SHORT_USED); bits_written += LEN_LTP_SHORT_USED; if(lt_status->sbk_prediction_used[i]) { if(i > first_subblock) { int diff; diff = lt_status->delay[prev_subblock] - lt_status->delay[i]; prev_subblock = i; if(diff) { BsPutBit (bs, 1, 1); BsPutBit (bs, diff + NOK_LTP_LAG_OFFSET, LEN_LTP_SHORT_LAG); bits_written += 1 + LEN_LTP_SHORT_LAG; } else { BsPutBit (bs, 0, 1); bits_written += 1; } } } } break; default: CommonExit(1, "nok_ltp_encode : unsupported window sequence %i", win_type); break; } } else BsPutBit (bs, 0, 1); /* LTP not used */ return (bits_written);}/************************************************************************** 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 *************************************************************************/static shortdouble_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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -