📄 nok_ltp_enc.c
字号:
Input: p_spectrum - spectral coefficients p_time_signal - current input samples 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 sfb_offset - scalefactor band boundaries num_of_sfb - number of scalefactor bands in each block lt_status : buffer - history buffer tnsInfo - TNS encoding parameters qc_select - MPEG4/TF codec type Output: y - 1 if LTP used, 0 otherwise p_spectrum - error spectrum (if LTP used) lt_status : weight_idx - 3 bit number indicating the LTP coefficient in the codebook sbk_prediction_used - 1 bit for each subblock indicating wheather LTP is used in that subblock 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 side_info - LTP side information References: 1.) pitch in nok_pitch.c 2.) prediction in nok_pitch.c 3.) ltp_enc_tf Explanation: - Author(s): Juha Ojanpera *************************************************************************/intnok_ltp_enc(double *p_spectrum, double *p_time_signal, 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, int *sfb_offset, int num_of_sfb, NOK_LT_PRED_STATUS *lt_status, TNS_INFO *tnsInfo, QC_MOD_SELECT qc_select){ int i, j, sw, sw_ltp_on; int first_sblck_found, lag0, lag1; int last_band, max_side_info; int weight_idx; Float weight_tmp; double max_bits, max_gain; double *time_signal; double num_bit[MAX_SHORT_WINDOWS]; double predicted_samples[2 * NOK_MAX_BLOCK_LEN_LONG]; double overlap_buffer[2 * NOK_MAX_BLOCK_LEN_LONG]; lt_status->global_pred_flag = 0; lt_status->side_info = 0; 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; lt_status->delay[0] = pitch(p_time_signal, lt_status->buffer, 2 * block_size_long, 0, 2 * block_size_long, predicted_samples, <_status->weight, <_status->weight_idx, qc_select, win_type, -1); lt_status->side_info = LEN_LTP_DATA_PRESENT + last_band + LEN_LTP_LAG + LEN_LTP_COEF; num_bit[0] = ltp_enc_tf(p_spectrum, predicted_samples, lt_status->mdct_predicted, win_type, win_shape, win_shape_prev, block_size_long, block_size_medium, block_size_short, sfb_offset, num_of_sfb, last_band, lt_status->side_info, lt_status->sfb_prediction_used, tnsInfo, -1);#ifdef LTP_DEBUG fprintf(stdout, "(LTP) lag : %i ", lt_status->delay[0]); fprintf(stdout, "(LTP) bit gain : %f\n", num_bit[0]);#endif /* LTP_DEBUG */ lt_status->global_pred_flag = (num_bit[0] == 0.0) ? 0 : 1; if(lt_status->global_pred_flag) for (i = 0; i < sfb_offset[last_band]; i++) p_spectrum[i] -= lt_status->mdct_predicted[i]; else lt_status->side_info = 1; for(i = sfb_offset[last_band]; i < block_size_long; i++) lt_status->mdct_predicted[i] = 0.0f; break; case EIGHT_SHORT_SEQUENCE: /* Short windows are used only in a scalable mode. */ if(qc_select == AAC_QC || qc_select == AAC_BSAC) return (0); last_band = (num_of_sfb < NOK_MAX_LT_PRED_SHORT_SFB) ? num_of_sfb : NOK_MAX_LT_PRED_SHORT_SFB; for(i = 0; i < MAX_SHORT_WINDOWS; i++) lt_status->sbk_prediction_used[i] = 0; /* Global LTP prediction flag. */ max_side_info = LEN_LTP_DATA_PRESENT; /* Initial lag parameters. */ lag0 = 0; lag1 = DELAY; first_sblck_found = 0; for (sw = sw_ltp_on = 0; sw < MAX_SHORT_WINDOWS; sw++) { time_signal = p_time_signal + SHORT_SQ_OFFSET + block_size_short * sw; /* Compute the lag range for this subblock. */ if(lt_status->global_pred_flag) { lag0 = lt_status->delay[sw_ltp_on] - (NOK_LTP_LAG_OFFSET >> 1); if(lag0 < 0) lag0 = 0; lag1 = lag0 + NOK_LTP_LAG_OFFSET - 1; if(lag1 > DELAY) lag1 = DELAY; } if(lt_status->global_pred_flag == 0) { /* Compute the lag, gain and get the predicted signal. */ { int ii; for(ii=0; ii<2*block_size_long; ii++)predicted_samples[ii]= 0.0; } lt_status->delay[sw] = pitch(time_signal, lt_status->buffer, 2 * block_size_short, DELAY / 2 - 2 * block_size_short, 2 * block_size_long + DELAY / 2 - 2 * block_size_short, predicted_samples, <_status->weight, &weight_idx, qc_select, win_type, first_sblck_found); /* Common to all subblocks. */ lt_status->weight_idx = weight_idx; /* Side information bits needed for this subblock. */ lt_status->side_info = LEN_LTP_DATA_PRESENT + LEN_LTP_LAG + LEN_LTP_COEF; num_bit[sw] = ltp_enc_tf(p_spectrum + block_size_short * sw, predicted_samples, lt_status->mdct_predicted + block_size_short * sw, win_type, win_shape, win_shape_prev, block_size_long, block_size_medium, block_size_short, sfb_offset, num_of_sfb, last_band, lt_status->side_info, lt_status->sfb_prediction_used + last_band * sw, tnsInfo, sw); } else { lt_status->side_info = LEN_LTP_DATA_PRESENT + LEN_LTP_SHORT_LAG_PRESENT; #ifdef NOK_LTP_SHORT_FAST /* * The purpose of this function call here is to find the lag * within the allowable lag range. The gain and the predicted * frame are ignored. */ lt_status->delay[sw] = pitch(time_signal, lt_status->buffer, 2 * block_size_short, lag0, lag1, predicted_samples, &weight_tmp, &weight_idx, qc_select, win_type, first_sblck_found); /* Just get the predicted signal, gain is already computed. */ prediction (lt_status->buffer, predicted_samples, &codebook[lt_status->weight_idx], lt_status->delay[sw], 2 * block_size_short, qc_select, win_type); if(lt_status->delay[sw_ltp_on] - lt_status->delay[sw]) lt_status->side_info += LEN_LTP_SHORT_LAG; #else /* * Try all possible lags and choose the lag that gives the best * output in terms of prediction gain. */ for(i = lag0, max_gain = 0.0; i < lag1; i++) { lt_status->side_info = LEN_LTP_DATA_PRESENT + LEN_LTP_SHORT_LAG_PRESENT; if(lt_status->delay[sw_ltp_on] - i) lt_status->side_info += LEN_LTP_SHORT_LAG; prediction (lt_status->buffer, predicted_samples, &codebook[lt_status->weight_idx], i, 2 * block_size_short, qc_select, win_type); #endif /* NOK_LTP_SHORT_FAST */ num_bit[sw] = ltp_enc_tf(p_spectrum + block_size_short * sw, predicted_samples, lt_status->mdct_predicted + block_size_short * sw, win_type, win_shape, win_shape_prev, block_size_long, block_size_medium, block_size_short, sfb_offset, num_of_sfb, last_band, lt_status->side_info, lt_status->sfb_prediction_used + last_band * sw, tnsInfo, sw);#ifndef NOK_LTP_SHORT_FAST if(num_bit[sw] >= max_gain) /***TM */ { max_gain = num_bit[sw]; lt_status->delay[sw] = i; for(j = 0; j < block_size_short; j++) overlap_buffer[j] = lt_status->mdct_predicted[block_size_short * sw + j]; } } num_bit[sw] = max_gain; for(j = 0; j < block_size_short; j++) lt_status->mdct_predicted[block_size_short * sw + j] = overlap_buffer[j];#endif /* not NOK_LTP_SHORT_FAST */ } /* else */ /**/#ifdef LTP_DEBUG fprintf(stdout, "%i. subblock parameters for LTP :\n", sw); fprintf(stdout, "gain : %f\n", codebook[lt_status->weight_idx]); fprintf(stdout, "lag : %i\n", lt_status->delay[sw]); fprintf(stdout, "sfb flags (%i bands): ", last_band); for(i = 0; i < last_band; i++) fprintf(stdout, "%i", lt_status->sfb_prediction_used[last_band * sw + i]); fprintf(stdout, "\n"); fprintf (stdout, "prediction gain : %10f\n", num_bit[sw]);#endif /* LTP_DEBUG */ if (num_bit[sw]) { first_sblck_found = 1; lt_status->global_pred_flag = 1; lt_status->sbk_prediction_used[sw] = 1; max_side_info +=lt_status->side_info; sw_ltp_on = sw; } else max_side_info += LEN_LTP_DATA_PRESENT; 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]; for(i = sfb_offset[last_band]; i < block_size_short; i++) lt_status->mdct_predicted[sw * block_size_short + i] = 0.0f; } /* for (sw = sw_ltp_on = 0 ... */ if (lt_status->global_pred_flag) lt_status->side_info = max_side_info; else lt_status->side_info = LEN_LTP_DATA_PRESENT;#ifdef LTP_DEBUG { double total_bit; total_bit = 0.0; for (i = 0; i < MAX_SHORT_WINDOWS; i++) total_bit += num_bit[i]; fprintf (stdout, "total subbits %f\n\n", total_bit); }#endif /* LTP_DEBUG */ break; default: break; } return (lt_status->global_pred_flag);}/************************************************************************** Title: nok_ltp_reconstruct Purpose: Adds the predicted spectrum to the reconstructed error spectrum. Usage: nok_ltp_reconstruct(p_spectrum, win_type, sfb_offset, num_of_sfb, block_size_short, lt_status) Input: p_spectrum - reconstructed (error) spectrum win_type - window sequence (frame, block) type sfb_offset - scalefactor band boundaries num_of_sfb - number of scalefactor bands in each block block_size_short - size of the short block lt_status : mdct_predicted - predicted spectrum Output: p_spectrum - reconstructed spectrum containing also LTP contribution References: - Explanation: - Author(s): Juha Ojanpera
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -