diff options
author | Rostislav Pehlivanov <atomnuker@gmail.com> | 2015-08-21 19:13:26 +0100 |
---|---|---|
committer | Rostislav Pehlivanov <atomnuker@gmail.com> | 2015-08-21 19:13:26 +0100 |
commit | d1ca7142ac93e713dce5654476b7b91b00ebbef2 (patch) | |
tree | 67bca8615f5b20f6c32c2cd3bd994c709a20c23d /libavcodec/aaccoder.c | |
parent | 860dbe0275e57cbf4228f3f653f872ff66ca596b (diff) | |
download | ffmpeg-d1ca7142ac93e713dce5654476b7b91b00ebbef2.tar.gz |
aaccoder: move the Intensity Stereo implementation out
This commit moves the intensity stereo implementation
out from aaccoder and into a separate file. This was
possible using the previous commits.
This commit also drastically improves the IS implementation
by making it phase invariant e.g. it will always choose the
best possible phase regardless of whether M/S coding is on
or most of the coefficients have identical phases.
This also increases the quality and reduces any distortions
introduced by enablind intensity stereo.
Users are encouraged to test it out using the -aac_is 1
parameter as it has always been.
Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
Diffstat (limited to 'libavcodec/aaccoder.c')
-rw-r--r-- | libavcodec/aaccoder.c | 102 |
1 files changed, 3 insertions, 99 deletions
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index e325788560..5df30a61ef 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -44,6 +44,8 @@ #include "aacenc_quantization.h" #include "aac_tablegen_decl.h" +#include "aacenc_is.h" + /** Frequency in Hz for lower limit of noise substitution **/ #define NOISE_LOW_LIMIT 4500 @@ -889,104 +891,6 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne } } -static void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe) -{ - float IS[128]; - float *L34 = s->scoefs + 128*0, *R34 = s->scoefs + 128*1; - float *I34 = s->scoefs + 128*2; - SingleChannelElement *sce0 = &cpe->ch[0]; - SingleChannelElement *sce1 = &cpe->ch[1]; - int start = 0, count = 0, i, w, w2, g; - const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f; - const float lambda = s->lambda; - - for (w = 0; w < 128; w++) - if (sce1->band_type[w] >= INTENSITY_BT2) - sce1->band_type[w] = 0; - - if (!cpe->common_window) - return; - for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) { - start = 0; - for (g = 0; g < sce0->ics.num_swb; g++) { - if (start*freq_mult > INT_STEREO_LOW_LIMIT*(lambda/170.0f) && - cpe->ch[0].band_type[w*16+g] != NOISE_BT && !cpe->ch[0].zeroes[w*16+g] && - cpe->ch[1].band_type[w*16+g] != NOISE_BT && !cpe->ch[1].zeroes[w*16+g]) { - int phase = 0; - float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f; - float dist1 = 0.0f, dist2 = 0.0f; - for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { - for (i = 0; i < sce0->ics.swb_sizes[g]; i++) { - float coef0 = sce0->pcoeffs[start+(w+w2)*128+i]; - float coef1 = sce1->pcoeffs[start+(w+w2)*128+i]; - phase += coef0*coef1 >= 0.0f ? 1 : -1; - ener0 += coef0*coef0; - ener1 += coef1*coef1; - ener01 += (coef0 + coef1)*(coef0 + coef1); - } - } - if (!phase) { /* Too much phase difference between channels */ - start += sce0->ics.swb_sizes[g]; - continue; - } - phase = av_clip(phase, -1, 1); - for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { - FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g]; - FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g]; - int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[(w+w2)*16+g]-4); - float e01_34 = phase*pow(sqrt(ener1/ener0), 3.0/4.0); - float maxval, dist_spec_err = 0.0f; - float minthr = FFMIN(band0->threshold, band1->threshold); - for (i = 0; i < sce0->ics.swb_sizes[g]; i++) - IS[i] = (sce0->pcoeffs[start+(w+w2)*128+i] + phase*sce1->pcoeffs[start+(w+w2)*128+i]) * sqrt(ener0/ener01); - abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); - abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]); - abs_pow34_v(I34, IS, sce0->ics.swb_sizes[g]); - maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34); - is_band_type = find_min_book(maxval, is_sf_idx); - dist1 += quantize_band_cost(s, sce0->coeffs + start + (w+w2)*128, - L34, - sce0->ics.swb_sizes[g], - sce0->sf_idx[(w+w2)*16+g], - sce0->band_type[(w+w2)*16+g], - lambda / band0->threshold, INFINITY, NULL, 0); - dist1 += quantize_band_cost(s, sce1->coeffs + start + (w+w2)*128, - R34, - sce1->ics.swb_sizes[g], - sce1->sf_idx[(w+w2)*16+g], - sce1->band_type[(w+w2)*16+g], - lambda / band1->threshold, INFINITY, NULL, 0); - dist2 += quantize_band_cost(s, IS, - I34, - sce0->ics.swb_sizes[g], - is_sf_idx, - is_band_type, - lambda / minthr, INFINITY, NULL, 0); - for (i = 0; i < sce0->ics.swb_sizes[g]; i++) { - dist_spec_err += (L34[i] - I34[i])*(L34[i] - I34[i]); - dist_spec_err += (R34[i] - I34[i]*e01_34)*(R34[i] - I34[i]*e01_34); - } - dist_spec_err *= lambda / minthr; - dist2 += dist_spec_err; - } - if (dist2 <= dist1) { - cpe->is_mask[w*16+g] = 1; - cpe->ms_mask[w*16+g] = 0; - cpe->ch[0].is_ener[w*16+g] = sqrt(ener0/ener01); - cpe->ch[1].is_ener[w*16+g] = ener0/ener1; - if (phase) - cpe->ch[1].band_type[w*16+g] = INTENSITY_BT; - else - cpe->ch[1].band_type[w*16+g] = INTENSITY_BT2; - count++; - } - } - start += sce0->ics.swb_sizes[g]; - } - } - cpe->is_mode = !!count; -} - static void search_for_ms(AACEncContext *s, ChannelElement *cpe) { int start = 0, i, w, w2, g; @@ -1000,7 +904,7 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) { start = 0; for (g = 0; g < sce0->ics.num_swb; g++) { - if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g] && !cpe->is_mask[w*16+g]) { + if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) { float dist1 = 0.0f, dist2 = 0.0f; for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g]; |