History

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.

Rostislav Pehlivanov committed 11 years ago

Commit d1ca7141 parent 860dbe05 files · +192 −102Browse files

Showing the changes to libavcodec/aaccoder.c (1 of 5 files). Show all

Unified · Split

libavcodec/aaccoder.c+3−99
@@ -44,6 +44,8 @@ · 43 unmodified lines
4444 #include "aacenc_quantization.h"
4545 #include "aac_tablegen_decl.h"
4646
47+#include "aacenc_is.h"
48+
4749 /** Frequency in Hz for lower limit of noise substitution **/
4850 #define NOISE_LOW_LIMIT 4500
4951
@@ -889,104 +891,6 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 839 unmodified lines
889891 }
890892 }
891893
892−static void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe)
893−{
894− float IS[128];
895− float *L34 = s->scoefs + 128*0, *R34 = s->scoefs + 128*1;
896− float *I34 = s->scoefs + 128*2;
897− SingleChannelElement *sce0 = &cpe->ch[0];
898− SingleChannelElement *sce1 = &cpe->ch[1];
899− int start = 0, count = 0, i, w, w2, g;
900− const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f;
901− const float lambda = s->lambda;
902−
903− for (w = 0; w < 128; w++)
904− if (sce1->band_type[w] >= INTENSITY_BT2)
905− sce1->band_type[w] = 0;
906−
907− if (!cpe->common_window)
908− return;
909− for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
910− start = 0;
911− for (g = 0; g < sce0->ics.num_swb; g++) {
912− if (start*freq_mult > INT_STEREO_LOW_LIMIT*(lambda/170.0f) &&
913− cpe->ch[0].band_type[w*16+g] != NOISE_BT && !cpe->ch[0].zeroes[w*16+g] &&
914− cpe->ch[1].band_type[w*16+g] != NOISE_BT && !cpe->ch[1].zeroes[w*16+g]) {
915− int phase = 0;
916− float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f;
917− float dist1 = 0.0f, dist2 = 0.0f;
918− for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
919− for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
920− float coef0 = sce0->pcoeffs[start+(w+w2)*128+i];
921− float coef1 = sce1->pcoeffs[start+(w+w2)*128+i];
922− phase += coef0*coef1 >= 0.0f ? 1 : -1;
923− ener0 += coef0*coef0;
924− ener1 += coef1*coef1;
925− ener01 += (coef0 + coef1)*(coef0 + coef1);
926− }
927− }
928− if (!phase) { /* Too much phase difference between channels */
929− start += sce0->ics.swb_sizes[g];
930− continue;
931− }
932− phase = av_clip(phase, -1, 1);
933− for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
934− FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
935− FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
936− int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[(w+w2)*16+g]-4);
937− float e01_34 = phase*pow(sqrt(ener1/ener0), 3.0/4.0);
938− float maxval, dist_spec_err = 0.0f;
939− float minthr = FFMIN(band0->threshold, band1->threshold);
940− for (i = 0; i < sce0->ics.swb_sizes[g]; i++)
941− IS[i] = (sce0->pcoeffs[start+(w+w2)*128+i] + phase*sce1->pcoeffs[start+(w+w2)*128+i]) * sqrt(ener0/ener01);
942− abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
943− abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
944− abs_pow34_v(I34, IS, sce0->ics.swb_sizes[g]);
945− maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);
946− is_band_type = find_min_book(maxval, is_sf_idx);
947− dist1 += quantize_band_cost(s, sce0->coeffs + start + (w+w2)*128,
948− L34,
949− sce0->ics.swb_sizes[g],
950− sce0->sf_idx[(w+w2)*16+g],
951− sce0->band_type[(w+w2)*16+g],
952− lambda / band0->threshold, INFINITY, NULL, 0);
953− dist1 += quantize_band_cost(s, sce1->coeffs + start + (w+w2)*128,
954− R34,
955− sce1->ics.swb_sizes[g],
956− sce1->sf_idx[(w+w2)*16+g],
957− sce1->band_type[(w+w2)*16+g],
958− lambda / band1->threshold, INFINITY, NULL, 0);
959− dist2 += quantize_band_cost(s, IS,
960− I34,
961− sce0->ics.swb_sizes[g],
962− is_sf_idx,
963− is_band_type,
964− lambda / minthr, INFINITY, NULL, 0);
965− for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
966− dist_spec_err += (L34[i] - I34[i])*(L34[i] - I34[i]);
967− dist_spec_err += (R34[i] - I34[i]*e01_34)*(R34[i] - I34[i]*e01_34);
968− }
969− dist_spec_err *= lambda / minthr;
970− dist2 += dist_spec_err;
971− }
972− if (dist2 <= dist1) {
973− cpe->is_mask[w*16+g] = 1;
974− cpe->ms_mask[w*16+g] = 0;
975− cpe->ch[0].is_ener[w*16+g] = sqrt(ener0/ener01);
976− cpe->ch[1].is_ener[w*16+g] = ener0/ener1;
977− if (phase)
978− cpe->ch[1].band_type[w*16+g] = INTENSITY_BT;
979− else
980− cpe->ch[1].band_type[w*16+g] = INTENSITY_BT2;
981− count++;
982− }
983− }
984− start += sce0->ics.swb_sizes[g];
985− }
986− }
987− cpe->is_mode = !!count;
988−}
989−
990894 static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
991895 {
992896 int start = 0, i, w, w2, g;
@@ -1000,7 +904,7 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) · 7 unmodified lines
1000904 for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
1001905 start = 0;
1002906 for (g = 0; g < sce0->ics.num_swb; g++) {
1003− if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g] && !cpe->is_mask[w*16+g]) {
907+ if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {
1004908 float dist1 = 0.0f, dist2 = 0.0f;
1005909 for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
1006910 FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t