diff options
-rw-r--r-- | libavcodec/aaccoder.c | 4 | ||||
-rw-r--r-- | libavcodec/aacenc.c | 5 | ||||
-rw-r--r-- | libavcodec/aacenc.h | 1 | ||||
-rw-r--r-- | libavcodec/aacenc_tns.c | 211 | ||||
-rw-r--r-- | libavcodec/aacenc_tns.h | 11 |
5 files changed, 110 insertions, 122 deletions
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index 8256f961c0..86d598f021 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -964,6 +964,7 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { ff_aac_encode_main_pred, ff_aac_adjust_common_prediction, ff_aac_apply_main_pred, + ff_aac_apply_tns, set_special_band_scalefactors, search_for_pns, ff_aac_search_for_tns, @@ -979,6 +980,7 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { ff_aac_encode_main_pred, ff_aac_adjust_common_prediction, ff_aac_apply_main_pred, + ff_aac_apply_tns, set_special_band_scalefactors, search_for_pns, ff_aac_search_for_tns, @@ -994,6 +996,7 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { ff_aac_encode_main_pred, ff_aac_adjust_common_prediction, ff_aac_apply_main_pred, + ff_aac_apply_tns, set_special_band_scalefactors, search_for_pns, ff_aac_search_for_tns, @@ -1009,6 +1012,7 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { ff_aac_encode_main_pred, ff_aac_adjust_common_prediction, ff_aac_apply_main_pred, + ff_aac_apply_tns, set_special_band_scalefactors, search_for_pns, ff_aac_search_for_tns, diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index a7c43c7411..9f59b9213a 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -404,10 +404,9 @@ static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s, encode_band_info(s, sce); encode_scale_factors(avctx, s, sce); encode_pulses(s, &sce->pulse); + put_bits(&s->pb, 1, !!sce->tns.present); if (s->coder->encode_tns_info) s->coder->encode_tns_info(s, sce); - else - put_bits(&s->pb, 1, 0); put_bits(&s->pb, 1, 0); //ssr encode_spectral_coeffs(s, sce); return 0; @@ -609,6 +608,8 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->coder->search_for_pns(s, avctx, sce); if (s->options.tns && s->coder->search_for_tns) s->coder->search_for_tns(s, sce); + if (s->options.tns && s->coder->apply_tns_filt) + s->coder->apply_tns_filt(sce); if (sce->tns.present) tns_mode = 1; } diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h index 69a8c01d82..51dce8a0fd 100644 --- a/libavcodec/aacenc.h +++ b/libavcodec/aacenc.h @@ -63,6 +63,7 @@ typedef struct AACCoefficientsEncoder { void (*encode_main_pred)(struct AACEncContext *s, SingleChannelElement *sce); void (*adjust_common_prediction)(struct AACEncContext *s, ChannelElement *cpe); void (*apply_main_pred)(struct AACEncContext *s, SingleChannelElement *sce); + void (*apply_tns_filt)(SingleChannelElement *sce); void (*set_special_band_scalefactors)(struct AACEncContext *s, SingleChannelElement *sce); void (*search_for_pns)(struct AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce); void (*search_for_tns)(struct AACEncContext *s, SingleChannelElement *sce); diff --git a/libavcodec/aacenc_tns.c b/libavcodec/aacenc_tns.c index 8c21255f7b..912229e692 100644 --- a/libavcodec/aacenc_tns.c +++ b/libavcodec/aacenc_tns.c @@ -31,62 +31,30 @@ #include "aacenc_utils.h" #include "aacenc_quantization.h" -static inline void conv_to_int32(int32_t *loc, float *samples, int num, float norm) -{ - int i; - for (i = 0; i < num; i++) - loc[i] = ceilf((samples[i]/norm)*INT32_MAX); -} - -static inline void conv_to_float(float *arr, int32_t *cof, int num) -{ - int i; - for (i = 0; i < num; i++) - arr[i] = (float)cof[i]/INT32_MAX; -} - -/* Input: quantized 4 bit coef, output: 1 if first (MSB) 2 bits are the same */ -static inline int coef_test_compression(int coef) -{ - int tmp = coef >> 2; - int res = ff_ctz(tmp); - if (res > 1) - return 1; /* ...00 -> compressable */ - else if (res == 1) - return 0; /* ...10 -> uncompressable */ - else if (ff_ctz(tmp >> 1) > 0) - return 0; /* ...0 1 -> uncompressable */ - else - return 1; /* ...1 1 -> compressable */ -} - static inline int compress_coef(int *coefs, int num) { - int i, res = 0; + int i, c = 0; for (i = 0; i < num; i++) - res += coef_test_compression(coefs[i]); - return res == num ? 1 : 0; + c += coefs[i] < 4 || coefs[i] > 11; + return c == num; } /** * Encode TNS data. - * Coefficient compression saves a single bit. + * Coefficient compression saves a single bit per coefficient. */ void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce) { int i, w, filt, coef_len, coef_compress; - const int coef_res = MAX_LPC_PRECISION == 4 ? 1 : 0; const int is8 = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE; - put_bits(&s->pb, 1, !!sce->tns.present); - if (!sce->tns.present) return; for (i = 0; i < sce->ics.num_windows; i++) { put_bits(&s->pb, 2 - is8, sce->tns.n_filt[i]); if (sce->tns.n_filt[i]) { - put_bits(&s->pb, 1, !!coef_res); + put_bits(&s->pb, 1, 1); for (filt = 0; filt < sce->tns.n_filt[i]; filt++) { put_bits(&s->pb, 6 - 2 * is8, sce->tns.length[i][filt]); put_bits(&s->pb, 5 - 2 * is8, sce->tns.order[i][filt]); @@ -95,7 +63,7 @@ void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce) sce->tns.order[i][filt]); put_bits(&s->pb, 1, !!sce->tns.direction[i][filt]); put_bits(&s->pb, 1, !!coef_compress); - coef_len = coef_res + 3 - coef_compress; + coef_len = 4 - coef_compress; for (w = 0; w < sce->tns.order[i][filt]; w++) put_bits(&s->pb, coef_len, sce->tns.coef_idx[i][filt][w]); } @@ -104,24 +72,25 @@ void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce) } } -static int process_tns_coeffs(TemporalNoiseShaping *tns, float *tns_coefs_raw, - int order, int w, int filt) +static void process_tns_coeffs(TemporalNoiseShaping *tns, double *coef_raw, + int *order_p, int w, int filt) { - int i, j; + int i, j, order = *order_p; int *idx = tns->coef_idx[w][filt]; float *lpc = tns->coef[w][filt]; - const int iqfac_p = ((1 << (MAX_LPC_PRECISION-1)) - 0.5)/(M_PI/2.0); - const int iqfac_m = ((1 << (MAX_LPC_PRECISION-1)) + 0.5)/(M_PI/2.0); float temp[TNS_MAX_ORDER] = {0.0f}, out[TNS_MAX_ORDER] = {0.0f}; - /* Quantization */ + if (!order) + return; + + /* Not what the specs say, but it's better */ for (i = 0; i < order; i++) { - idx[i] = ceilf(asin(tns_coefs_raw[i])*((tns_coefs_raw[i] >= 0) ? iqfac_p : iqfac_m)); - lpc[i] = 2*sin(idx[i]/((idx[i] >= 0) ? iqfac_p : iqfac_m)); + idx[i] = quant_array_idx(coef_raw[i], tns_tmp2_map_0_4, 16); + lpc[i] = tns_tmp2_map_0_4[idx[i]]; } /* Trim any coeff less than 0.1f from the end */ - for (i = order; i > -1; i--) { + for (i = order-1; i > -1; i--) { lpc[i] = (fabs(lpc[i]) > 0.1f) ? lpc[i] : 0.0f; if (lpc[i] != 0.0 ) { order = i; @@ -129,9 +98,6 @@ static int process_tns_coeffs(TemporalNoiseShaping *tns, float *tns_coefs_raw, } } - if (!order) - return 0; - /* Step up procedure, convert to LPC coeffs */ out[0] = 1.0f; for (i = 1; i <= order; i++) { @@ -143,35 +109,59 @@ static int process_tns_coeffs(TemporalNoiseShaping *tns, float *tns_coefs_raw, } out[i] = lpc[i-1]; } + *order_p = order; memcpy(lpc, out, TNS_MAX_ORDER*sizeof(float)); - - return order; } -static void apply_tns_filter(float *out, float *in, int order, int direction, - float *tns_coefs, int ltp_used, int w, int filt, - int start_i, int len) +/* Apply TNS filter */ +void ff_aac_apply_tns(SingleChannelElement *sce) { - int i, j, inc, start = start_i; - float tmp[TNS_MAX_ORDER+1]; - if (direction) { - inc = -1; - start = (start + len) - 1; - } else { - inc = 1; - } - if (!ltp_used) { /* AR filter */ - for (i = 0; i < len; i++, start += inc) - out[i] = in[start]; - for (j = 1; j <= FFMIN(i, order); j++) - out[i] += tns_coefs[j]*in[start - j*inc]; - } else { /* MA filter */ - for (i = 0; i < len; i++, start += inc) { - tmp[0] = out[i] = in[start]; - for (j = 1; j <= FFMIN(i, order); j++) - out[i] += tmp[j]*tns_coefs[j]; - for (j = order; j > 0; j--) - tmp[j] = tmp[j - 1]; + const int mmm = FFMIN(sce->ics.tns_max_bands, sce->ics.max_sfb); + float *coef = sce->pcoeffs; + TemporalNoiseShaping *tns = &sce->tns; + int w, filt, m, i; + int bottom, top, order, start, end, size, inc; + float *lpc, tmp[TNS_MAX_ORDER+1]; + + return; + + for (w = 0; w < sce->ics.num_windows; w++) { + bottom = sce->ics.num_swb; + for (filt = 0; filt < tns->n_filt[w]; filt++) { + top = bottom; + bottom = FFMAX(0, top - tns->length[w][filt]); + order = tns->order[w][filt]; + lpc = tns->coef[w][filt]; + if (!order) + continue; + + start = sce->ics.swb_offset[FFMIN(bottom, mmm)]; + end = sce->ics.swb_offset[FFMIN( top, mmm)]; + if ((size = end - start) <= 0) + continue; + if (tns->direction[w][filt]) { + inc = -1; + start = end - 1; + } else { + inc = 1; + } + start += w * 128; + + if (!sce->ics.ltp.present) { + // ar filter + for (m = 0; m < size; m++, start += inc) + for (i = 1; i <= FFMIN(m, order); i++) + coef[start] += coef[start - i * inc]*lpc[i - 1]; + } else { + // ma filter + for (m = 0; m < size; m++, start += inc) { + tmp[0] = coef[start]; + for (i = 1; i <= FFMIN(m, order); i++) + coef[start] += tmp[i]*lpc[i - 1]; + for (i = order; i > 0; i--) + tmp[i] = tmp[i - 1]; + } + } } } } @@ -179,57 +169,54 @@ static void apply_tns_filter(float *out, float *in, int order, int direction, void ff_aac_search_for_tns(AACEncContext *s, SingleChannelElement *sce) { TemporalNoiseShaping *tns = &sce->tns; - int w, g, order, sfb_start, sfb_len, coef_start, shift[MAX_LPC_ORDER], count = 0; + int w, g, w2, prev_end_sfb = 0, count = 0; const int is8 = sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE; const int tns_max_order = is8 ? 7 : s->profile == FF_PROFILE_AAC_LOW ? 12 : TNS_MAX_ORDER; - const float freq_mult = mpeg4audio_sample_rates[s->samplerate_index]/(1024.0f/sce->ics.num_windows)/2.0f; - float max_coef = 0.0f; - - sce->tns.present = 0; - return; - - for (coef_start = 0; coef_start < 1024; coef_start++) - max_coef = FFMAX(max_coef, sce->pcoeffs[coef_start]); - for (w = 0; w < sce->ics.num_windows; w++) { - int filters = 1, start = 0, coef_len = 0; - int32_t conv_coeff[1024] = {0}; - int32_t coefs_t[MAX_LPC_ORDER][MAX_LPC_ORDER] = {{0}}; - - /* Determine start sfb + coef - excludes anything below threshold */ + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + int order = 0, filters = 1; + int sfb_start = 0, sfb_len = 0; + int coef_start = 0, coef_len = 0; + float energy = 0.0f, threshold = 0.0f; + double coefs[MAX_LPC_ORDER][MAX_LPC_ORDER] = {{0}}; for (g = 0; g < sce->ics.num_swb; g++) { - if (start*freq_mult > TNS_LOW_LIMIT) { + if (!sfb_start && w*16+g > TNS_LOW_LIMIT && w*16+g > prev_end_sfb) { sfb_start = w*16+g; - sfb_len = (w+1)*16 + g - sfb_start; - coef_start = sce->ics.swb_offset[sfb_start]; - coef_len = sce->ics.swb_offset[sfb_start + sfb_len] - coef_start; - break; + coef_start = sce->ics.swb_offset[sfb_start]; + } + if (sfb_start) { + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + if (!sfb_len && band->energy < band->threshold*1.3f) { + sfb_len = (w+w2)*16+g - sfb_start; + prev_end_sfb = sfb_start + sfb_len; + coef_len = sce->ics.swb_offset[sfb_start + sfb_len] - coef_start; + break; + } + energy += band->energy; + threshold += band->threshold; + } + if (!sfb_len) { + sfb_len = (w+sce->ics.group_len[w])*16+g - sfb_start; + coef_len = sce->ics.swb_offset[sfb_start + sfb_len] - coef_start; + } } - start += sce->ics.swb_sizes[g]; } - if (coef_len <= 0) + if (sfb_len <= 0 || coef_len <= 0) continue; - - conv_to_int32(conv_coeff, &sce->pcoeffs[coef_start], coef_len, max_coef); + if (coef_start + coef_len > 1024) + coef_len = 1024 - coef_start; /* LPC */ - order = ff_lpc_calc_coefs(&s->lpc, conv_coeff, coef_len, - TNS_MIN_PRED_ORDER, tns_max_order, - 32, coefs_t, shift, - FF_LPC_TYPE_LEVINSON, 10, - ORDER_METHOD_EST, MAX_LPC_SHIFT, 0) - 1; - - /* Works surprisingly well, remember to tweak MAX_LPC_SHIFT if you want to play around with this */ - if (shift[order] > 3) { + order = ff_lpc_calc_levinsion(&s->lpc, &sce->coeffs[coef_start], coef_len, + coefs, 0, tns_max_order, ORDER_METHOD_LOG); + + if (energy > threshold) { int direction = 0; - float tns_coefs_raw[TNS_MAX_ORDER]; tns->n_filt[w] = filters++; - conv_to_float(tns_coefs_raw, coefs_t[order], order); for (g = 0; g < tns->n_filt[w]; g++) { - process_tns_coeffs(tns, tns_coefs_raw, order, w, g); - apply_tns_filter(&sce->coeffs[coef_start], sce->pcoeffs, order, direction, tns->coef[w][g], - sce->ics.ltp.present, w, g, coef_start, coef_len); + process_tns_coeffs(tns, coefs[order], &order, w, g); tns->order[w][g] = order; tns->length[w][g] = sfb_len; tns->direction[w][g] = direction; diff --git a/libavcodec/aacenc_tns.h b/libavcodec/aacenc_tns.h index 789e9a64fe..72c91239a3 100644 --- a/libavcodec/aacenc_tns.h +++ b/libavcodec/aacenc_tns.h @@ -30,16 +30,11 @@ #include "aacenc.h" -/** Frequency in Hz for lower limit of TNS **/ -#define TNS_LOW_LIMIT 2150 - -/** LPC settings */ -#define TNS_MIN_PRED_ORDER 0 -#define MAX_LPC_PRECISION 4 /* 4 bits ltp coeff precision */ -#define TNS_LPC_PASSES 2 -#define MAX_LPC_SHIFT 4 +/** Lower limit of TNS in SFBs **/ +#define TNS_LOW_LIMIT 24 void ff_aac_encode_tns_info(AACEncContext *s, SingleChannelElement *sce); +void ff_aac_apply_tns(SingleChannelElement *sce); void ff_aac_search_for_tns(AACEncContext *s, SingleChannelElement *sce); #endif /* AVCODEC_AACENC_TNS_H */ |