diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 1e1e47947376440f3b1cfca14842d3ff1a918fd5..af93f8acb9737e0be96b7c1f4eebaeceeb954ce2 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -135,6 +135,7 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacpsy.o aactab.o \ aacenc_is.o \ aacenc_tns.o \ + aacenc_ltp.o \ aacenc_pred.o \ psymodel.o mpeg4audio.o kbdwin.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o diff --git a/libavcodec/aac.h b/libavcodec/aac.h index 37f98adb31f8a6d6bff335fe6829314ff68c6107..3333bfe5b2e36878d6d21ad50d26bfbf090353bb 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -161,6 +161,7 @@ typedef struct PredictorState { typedef struct LongTermPrediction { int8_t present; int16_t lag; + int coef_idx; INTFLOAT coef; int8_t used[MAX_LTP_LONG_SFB]; } LongTermPrediction; @@ -260,6 +261,7 @@ typedef struct SingleChannelElement { DECLARE_ALIGNED(32, INTFLOAT, saved)[1536]; ///< overlap DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP + DECLARE_ALIGNED(32, AAC_FLOAT, lcoeffs)[1024]; ///< MDCT of LTP coefficients (used by encoder) DECLARE_ALIGNED(32, AAC_FLOAT, prcoeffs)[1024]; ///< Main prediction coefs (used by encoder) PredictorState predictor_state[MAX_PREDICTORS]; INTFLOAT *ret; ///< PCM output diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index c25189dbda330024262fb3a756b5b706f3eb2032..fd9785e26a46b91b076360b0867021dbb15f3dfe 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -48,6 +48,7 @@ #include "aacenc_is.h" #include "aacenc_tns.h" +#include "aacenc_ltp.h" #include "aacenc_pred.h" #include "libavcodec/aaccoder_twoloop.h" @@ -911,14 +912,19 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { encode_window_bands_info, quantize_and_encode_band, ff_aac_encode_tns_info, + ff_aac_encode_ltp_info, ff_aac_encode_main_pred, ff_aac_adjust_common_pred, + ff_aac_adjust_common_ltp, ff_aac_apply_main_pred, ff_aac_apply_tns, + ff_aac_update_ltp, + ff_aac_ltp_insert_new_frame, set_special_band_scalefactors, search_for_pns, mark_pns, ff_aac_search_for_tns, + ff_aac_search_for_ltp, search_for_ms, ff_aac_search_for_is, ff_aac_search_for_pred, @@ -928,14 +934,19 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { encode_window_bands_info, quantize_and_encode_band, ff_aac_encode_tns_info, + ff_aac_encode_ltp_info, ff_aac_encode_main_pred, ff_aac_adjust_common_pred, + ff_aac_adjust_common_ltp, ff_aac_apply_main_pred, ff_aac_apply_tns, + ff_aac_update_ltp, + ff_aac_ltp_insert_new_frame, set_special_band_scalefactors, search_for_pns, mark_pns, ff_aac_search_for_tns, + ff_aac_search_for_ltp, search_for_ms, ff_aac_search_for_is, ff_aac_search_for_pred, @@ -945,14 +956,19 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { codebook_trellis_rate, quantize_and_encode_band, ff_aac_encode_tns_info, + ff_aac_encode_ltp_info, ff_aac_encode_main_pred, ff_aac_adjust_common_pred, + ff_aac_adjust_common_ltp, ff_aac_apply_main_pred, ff_aac_apply_tns, + ff_aac_update_ltp, + ff_aac_ltp_insert_new_frame, set_special_band_scalefactors, search_for_pns, mark_pns, ff_aac_search_for_tns, + ff_aac_search_for_ltp, search_for_ms, ff_aac_search_for_is, ff_aac_search_for_pred, @@ -962,14 +978,19 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { encode_window_bands_info, quantize_and_encode_band, ff_aac_encode_tns_info, + ff_aac_encode_ltp_info, ff_aac_encode_main_pred, ff_aac_adjust_common_pred, + ff_aac_adjust_common_ltp, ff_aac_apply_main_pred, ff_aac_apply_tns, + ff_aac_update_ltp, + ff_aac_ltp_insert_new_frame, set_special_band_scalefactors, search_for_pns, mark_pns, ff_aac_search_for_tns, + ff_aac_search_for_ltp, search_for_ms, ff_aac_search_for_is, ff_aac_search_for_pred, diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 8d5f4387f3f856fb2d61de4ced89c2e266ce5ab4..9454a9491bab3ae9dd5a93fb1943b76bbea1762e 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -60,6 +60,7 @@ static const struct AACProfileOptions aacenc_profiles[] = { .mid_side = 0, .pns = 1, .tns = 0, + .ltp = OPT_BANNED, .pred = OPT_REQUIRED, .intensity_stereo = 1, }, @@ -69,6 +70,7 @@ static const struct AACProfileOptions aacenc_profiles[] = { .mid_side = 0, .pns = 1, .tns = 0, + .ltp = OPT_NEEDS_LTP, .pred = OPT_NEEDS_MAIN, .intensity_stereo = 1, }, @@ -78,6 +80,17 @@ static const struct AACProfileOptions aacenc_profiles[] = { .mid_side = 0, .pns = OPT_BANNED, .tns = 0, + .ltp = OPT_BANNED, + .pred = OPT_BANNED, + .intensity_stereo = 1, + }, + }, + {FF_PROFILE_AAC_LTP, + { /* Long term prediction profile */ + .mid_side = 0, + .pns = 1, + .tns = 0, + .ltp = OPT_REQUIRED, .pred = OPT_BANNED, .intensity_stereo = 1, }, @@ -475,6 +488,8 @@ static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s, put_ics_info(s, &sce->ics); if (s->coder->encode_main_pred) s->coder->encode_main_pred(s, sce); + if (s->coder->encode_ltp_info) + s->coder->encode_ltp_info(s, sce, 0); } encode_band_info(s, sce); encode_scale_factors(avctx, s, sce); @@ -625,6 +640,13 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } apply_window_and_mdct(s, sce, overlap); + + if (s->options.ltp && s->coder->update_ltp) { + s->coder->update_ltp(s, sce); + apply_window[sce->ics.window_sequence[0]](s->fdsp, sce, &sce->ltp_state[0]); + s->mdct1024.mdct_calc(&s->mdct1024, sce->lcoeffs, sce->ret_buf); + } + if (isnan(cpe->ch->coeffs[0])) { av_log(avctx, AV_LOG_ERROR, "Input contains NaN\n"); return AVERROR(EINVAL); @@ -659,6 +681,8 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, sce = &cpe->ch[ch]; coeffs[ch] = sce->coeffs; sce->ics.predictor_present = 0; + sce->ics.ltp.present = 0; + memset(sce->ics.ltp.used, 0, sizeof(sce->ics.ltp.used)); memset(sce->ics.prediction_used, 0, sizeof(sce->ics.prediction_used)); memset(&sce->tns, 0, sizeof(TemporalNoiseShaping)); for (w = 0; w < 128; w++) @@ -738,12 +762,26 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, apply_mid_side_stereo(cpe); } adjust_frame_information(cpe, chans); + if (s->options.ltp) { /* LTP */ + for (ch = 0; ch < chans; ch++) { + sce = &cpe->ch[ch]; + s->cur_channel = start_ch + ch; + if (s->coder->search_for_ltp) + s->coder->search_for_ltp(s, sce, cpe->common_window); + if (sce->ics.ltp.present) pred_mode = 1; + } + s->cur_channel = start_ch; + if (s->coder->adjust_common_ltp) + s->coder->adjust_common_ltp(s, cpe); + } if (chans == 2) { put_bits(&s->pb, 1, cpe->common_window); if (cpe->common_window) { put_ics_info(s, &cpe->ch[0].ics); if (s->coder->encode_main_pred) s->coder->encode_main_pred(s, &cpe->ch[0]); + if (s->coder->encode_ltp_info) + s->coder->encode_ltp_info(s, &cpe->ch[0], 1); encode_ms_info(&s->pb, cpe); if (cpe->ms_mode) ms_mode = 1; } @@ -816,6 +854,9 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } } while (1); + if (s->options.ltp && s->coder->ltp_insert_new_frame) + s->coder->ltp_insert_new_frame(s); + put_bits(&s->pb, 3, TYPE_END); flush_put_bits(&s->pb); avctx->frame_bits = put_bits_count(&s->pb); @@ -935,6 +976,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) AAC_OPT_SET(&s->options, p_opt, 1, coder); AAC_OPT_SET(&s->options, p_opt, 0, pns); AAC_OPT_SET(&s->options, p_opt, 1, tns); + AAC_OPT_SET(&s->options, p_opt, 0, ltp); AAC_OPT_SET(&s->options, p_opt, 0, pred); AAC_OPT_SET(&s->options, p_opt, 1, mid_side); AAC_OPT_SET(&s->options, p_opt, 0, intensity_stereo); @@ -993,6 +1035,7 @@ static const AVOption aacenc_options[] = { {"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS}, {"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS}, {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, + {"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS}, {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = OPT_AUTO}, -1, 1, AACENC_FLAGS}, {NULL} }; diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h index 0f4fc05e3d8fbe3a996ed7c4f63ef74d056362a9..d8bed82abe7c789f46294635c71bcdd90e135679 100644 --- a/libavcodec/aacenc.h +++ b/libavcodec/aacenc.h @@ -45,6 +45,7 @@ typedef struct AACEncOptions { int coder; int pns; int tns; + int ltp; int pred; int mid_side; int intensity_stereo; @@ -60,14 +61,19 @@ typedef struct AACCoefficientsEncoder { void (*quantize_and_encode_band)(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, int size, int scale_idx, int cb, const float lambda, int rtz); void (*encode_tns_info)(struct AACEncContext *s, SingleChannelElement *sce); + void (*encode_ltp_info)(struct AACEncContext *s, SingleChannelElement *sce, int common_window); void (*encode_main_pred)(struct AACEncContext *s, SingleChannelElement *sce); void (*adjust_common_pred)(struct AACEncContext *s, ChannelElement *cpe); + void (*adjust_common_ltp)(struct AACEncContext *s, ChannelElement *cpe); void (*apply_main_pred)(struct AACEncContext *s, SingleChannelElement *sce); void (*apply_tns_filt)(struct AACEncContext *s, SingleChannelElement *sce); + void (*update_ltp)(struct AACEncContext *s, SingleChannelElement *sce); + void (*ltp_insert_new_frame)(struct AACEncContext *s); void (*set_special_band_scalefactors)(struct AACEncContext *s, SingleChannelElement *sce); void (*search_for_pns)(struct AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce); void (*mark_pns)(struct AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce); void (*search_for_tns)(struct AACEncContext *s, SingleChannelElement *sce); + void (*search_for_ltp)(struct AACEncContext *s, SingleChannelElement *sce, int common_window); void (*search_for_ms)(struct AACEncContext *s, ChannelElement *cpe); void (*search_for_is)(struct AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe); void (*search_for_pred)(struct AACEncContext *s, SingleChannelElement *sce); diff --git a/libavcodec/aacenc_ltp.c b/libavcodec/aacenc_ltp.c new file mode 100644 index 0000000000000000000000000000000000000000..066e1952e785ea136c19563c6b39390e1375d8b0 --- /dev/null +++ b/libavcodec/aacenc_ltp.c @@ -0,0 +1,227 @@ +/* + * AAC encoder TNS + * Copyright (C) 2015 Rostislav Pehlivanov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * AAC encoder long term prediction + * @author Rostislav Pehlivanov ( atomnuker gmail com ) + */ + +#include "aacenc_ltp.h" +#include "aacenc_quantization.h" +#include "aacenc_utils.h" + +/** + * Encode LTP data. + */ +void ff_aac_encode_ltp_info(AACEncContext *s, SingleChannelElement *sce, + int common_window) +{ + int i; + IndividualChannelStream *ics = &sce->ics; + if (s->profile != FF_PROFILE_AAC_LTP || !ics->predictor_present) + return; + if (common_window) + put_bits(&s->pb, 1, 0); + put_bits(&s->pb, 1, ics->ltp.present); + if (!ics->ltp.present) + return; + put_bits(&s->pb, 11, ics->ltp.lag); + put_bits(&s->pb, 3, ics->ltp.coef_idx); + for (i = 0; i < FFMIN(ics->max_sfb, MAX_LTP_LONG_SFB); i++) + put_bits(&s->pb, 1, ics->ltp.used[i]); +} + +void ff_aac_ltp_insert_new_frame(AACEncContext *s) +{ + int i, ch, tag, chans, cur_channel, start_ch = 0; + ChannelElement *cpe; + SingleChannelElement *sce; + for (i = 0; i < s->chan_map[0]; i++) { + cpe = &s->cpe[i]; + tag = s->chan_map[i+1]; + chans = tag == TYPE_CPE ? 2 : 1; + for (ch = 0; ch < chans; ch++) { + sce = &cpe->ch[ch]; + cur_channel = start_ch + ch; + /* New sample + overlap */ + memcpy(&sce->ltp_state[0], &sce->ltp_state[1024], 1024*sizeof(sce->ltp_state[0])); + memcpy(&sce->ltp_state[1024], &s->planar_samples[cur_channel][2048], 1024*sizeof(sce->ltp_state[0])); + memcpy(&sce->ltp_state[2048], &sce->ret_buf[0], 1024*sizeof(sce->ltp_state[0])); + } + start_ch += chans; + } +} + +/** + * Process LTP parameters + * @see Patent WO2006070265A1 + */ +void ff_aac_update_ltp(AACEncContext *s, SingleChannelElement *sce) +{ + int i, j, lag; + float corr, s0, s1, max_corr = 0.0f; + float *samples = &s->planar_samples[s->cur_channel][1024]; + float *pred_signal = &sce->ltp_state[0]; + int samples_num = 2048; + + if (s->profile != FF_PROFILE_AAC_LTP) + return; + + /* Calculate lag */ + for (i = 0; i < samples_num; i++) { + s0 = s1 = 0.0f; + for (j = 0; j < samples_num; j++) { + if (j + 1024 < i) + continue; + s0 += samples[j]*pred_signal[j-i+1024]; + s1 += pred_signal[j-i+1024]*pred_signal[j-i+1024]; + } + corr = s1 > 0.0f ? s0/sqrt(s1) : 0.0f; + if (corr > max_corr) { + max_corr = corr; + lag = i; + } + } + lag = av_clip(lag, 0, 2048); /* 11 bits => 2^11 = 2048 */ + + if (!lag) { + sce->ics.ltp.lag = lag; + return; + } + + s0 = s1 = 0.0f; + for (i = 0; i < lag; i++) { + s0 += samples[i]; + s1 += pred_signal[i-lag+1024]; + } + + sce->ics.ltp.coef_idx = quant_array_idx(s0/s1, ltp_coef, 8); + sce->ics.ltp.coef = ltp_coef[sce->ics.ltp.coef_idx]; + + /* Predict the new samples */ + if (lag < 1024) + samples_num = lag + 1024; + for (i = 0; i < samples_num; i++) + pred_signal[i+1024] = sce->ics.ltp.coef*pred_signal[i-lag+1024]; + memset(&pred_signal[samples_num], 0, (2048 - samples_num)*sizeof(float)); + + sce->ics.ltp.lag = lag; +} + +void ff_aac_adjust_common_ltp(AACEncContext *s, ChannelElement *cpe) +{ + int sfb, count = 0; + SingleChannelElement *sce0 = &cpe->ch[0]; + SingleChannelElement *sce1 = &cpe->ch[1]; + + if (!cpe->common_window || + sce0->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE || + sce1->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) + return; + + for (sfb = 0; sfb < FFMIN(sce0->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++) { + int sum = sce0->ics.ltp.used[sfb] + sce1->ics.ltp.used[sfb]; + if (sum != 2) { + sce0->ics.ltp.used[sfb] = 0; + } else if (sum == 2) { + count++; + } + } + + sce0->ics.ltp.present = !!count; + sce0->ics.predictor_present = !!count; +} + +/** + * Mark LTP sfb's + */ +void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce, + int common_window) +{ + int w, g, w2, i, start = 0, count = 0; + int saved_bits = -(15 + FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB)); + float *C34 = &s->scoefs[128*0], *PCD = &s->scoefs[128*1]; + float *PCD34 = &s->scoefs[128*2]; + const int max_ltp = FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); + + if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE || + !sce->ics.ltp.lag) + return; + + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = 0; + for (g = 0; g < sce->ics.num_swb; g++) { + int bits1 = 0, bits2 = 0; + float dist1 = 0.0f, dist2 = 0.0f; + if (w*16+g > max_ltp) { + start += sce->ics.swb_sizes[g]; + continue; + } + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + int bits_tmp1, bits_tmp2; + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + for (i = 0; i < sce->ics.swb_sizes[g]; i++) + PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i]; + abs_pow34_v(C34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]); + abs_pow34_v(PCD34, PCD, sce->ics.swb_sizes[g]); + dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g], + sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g], + s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL, 0); + dist2 += quantize_band_cost(s, PCD, PCD34, sce->ics.swb_sizes[g], + sce->sf_idx[(w+w2)*16+g], + sce->band_type[(w+w2)*16+g], + s->lambda/band->threshold, INFINITY, &bits_tmp2, NULL, 0); + bits1 += bits_tmp1; + bits2 += bits_tmp2; + } + if (dist2 < dist1 && bits2 < bits1) { + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) + for (i = 0; i < sce->ics.swb_sizes[g]; i++) + sce->coeffs[start+(w+w2)*128+i] -= sce->lcoeffs[start+(w+w2)*128+i]; + sce->ics.ltp.used[w*16+g] = 1; + saved_bits += bits1 - bits2; + count++; + } + start += sce->ics.swb_sizes[g]; + } + } + + sce->ics.ltp.present = !!count && (saved_bits >= 0); + sce->ics.predictor_present = !!sce->ics.ltp.present; + + /* Reset any marked sfbs */ + if (!sce->ics.ltp.present && !!count) { + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = 0; + for (g = 0; g < sce->ics.num_swb; g++) { + if (sce->ics.ltp.used[w*16+g]) { + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + for (i = 0; i < sce->ics.swb_sizes[g]; i++) { + sce->coeffs[start+(w+w2)*128+i] += sce->lcoeffs[start+(w+w2)*128+i]; + } + } + } + start += sce->ics.swb_sizes[g]; + } + } + } +} diff --git a/libavcodec/aacenc_ltp.h b/libavcodec/aacenc_ltp.h new file mode 100644 index 0000000000000000000000000000000000000000..7276878427f715abb0b192b092d84c1bc2c8bcbc --- /dev/null +++ b/libavcodec/aacenc_ltp.h @@ -0,0 +1,41 @@ +/* + * AAC encoder long term prediction extension + * Copyright (C) 2015 Rostislav Pehlivanov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * AAC encoder long term prediction extension + * @author Rostislav Pehlivanov ( atomnuker gmail com ) + */ + +#ifndef AVCODEC_AACENC_LTP_H +#define AVCODEC_AACENC_LTP_H + +#include "aacenc.h" + +void ff_aac_encode_ltp_info(AACEncContext *s, SingleChannelElement *sce, + int common_window); +void ff_aac_update_ltp(AACEncContext *s, SingleChannelElement *sce); +void ff_aac_adjust_common_ltp(AACEncContext *s, ChannelElement *cpe); +void ff_aac_ltp_insert_new_frame(AACEncContext *s); +void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce, + int common_window); + +#endif /* AVCODEC_AACENC_LTP_H */