]> git.sesse.net Git - ffmpeg/commitdiff
aacenc_is: add a flag to use pure coefficients instead
authorRostislav Pehlivanov <atomnuker@gmail.com>
Sat, 5 Sep 2015 07:32:09 +0000 (08:32 +0100)
committerRostislav Pehlivanov <atomnuker@gmail.com>
Sat, 5 Sep 2015 07:32:09 +0000 (08:32 +0100)
This commit adds a flag to use the pure coefficients instead
of the processed ones (sce->coeffs). This is needed because
IS will apply the changes to the coefficients immediately
before the adjust_common_prediction function and it doesn't
make sense to measure stereo channel coefficient difference
when one of the channels coefficients are all zero.

Therefore add a flag to use pure coefficients in that case.
TNS is the only thing touching the coefficients before IS
so common window prediction will not take that into account
but the effect of the TNS filter per coefficient can be small
(a few percent) so to some approximation it's fine to just
ignore that.

Also fixed a small error which doesn't alter the results
that much. pow(sqrt(number), 3.0/4.0) == pow(number, 3.0/8.0) !=
pow(number, 3.0/4.0).

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
libavcodec/aacenc_is.c
libavcodec/aacenc_is.h
libavcodec/aacenc_pred.c

index 88ba915d2adce407661f26d50687e87003d7db51..bb201f628d00eeefb425f7580d4e6e5761624621 100644 (file)
 
 struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
                                          int start, int w, int g, float ener0,
-                                         float ener1, float ener01, int phase)
+                                         float ener1, float ener01,
+                                         int use_pcoeffs, int phase)
 {
     int i, w2;
+    SingleChannelElement *sce0 = &cpe->ch[0];
+    SingleChannelElement *sce1 = &cpe->ch[1];
+    float *L = use_pcoeffs ? sce0->pcoeffs : sce0->coeffs;
+    float *R = use_pcoeffs ? sce1->pcoeffs : sce1->coeffs;
     float *L34 = &s->scoefs[256*0], *R34 = &s->scoefs[256*1];
     float *IS  = &s->scoefs[256*2], *I34 = &s->scoefs[256*3];
     float dist1 = 0.0f, dist2 = 0.0f;
     struct AACISError is_error = {0};
-    SingleChannelElement *sce0 = &cpe->ch[0];
-    SingleChannelElement *sce1 = &cpe->ch[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 e01_34 = phase*pow(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]);
+        for (i = 0; i < sce0->ics.swb_sizes[g]; i++)
+            IS[i] = (L[start+(w+w2)*128+i] + phase*R[start+(w+w2)*128+i])*sqrt(ener0/ener01);
+        abs_pow34_v(L34, &L[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
+        abs_pow34_v(R34, &R[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,
+        dist1 += quantize_band_cost(s, &L[start + (w+w2)*128], L34,
                                     sce0->ics.swb_sizes[g],
                                     sce0->sf_idx[(w+w2)*16+g],
                                     sce0->band_type[(w+w2)*16+g],
                                     s->lambda / band0->threshold, INFINITY, NULL, 0);
-        dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128], R34,
+        dist1 += quantize_band_cost(s, &R[start + (w+w2)*128], R34,
                                     sce1->ics.swb_sizes[g],
                                     sce1->sf_idx[(w+w2)*16+g],
                                     sce1->band_type[(w+w2)*16+g],
@@ -111,15 +111,15 @@ void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElemen
                     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];
-                        ener0 += coef0*coef0;
-                        ener1 += coef1*coef1;
+                        ener0  += coef0*coef0;
+                        ener1  += coef1*coef1;
                         ener01 += (coef0 + coef1)*(coef0 + coef1);
                     }
                 }
                 ph_err1 = ff_aac_is_encoding_err(s, cpe, start, w, g,
-                                                 ener0, ener1, ener01, -1);
+                                                 ener0, ener1, ener01, 0, -1);
                 ph_err2 = ff_aac_is_encoding_err(s, cpe, start, w, g,
-                                                 ener0, ener1, ener01, +1);
+                                                 ener0, ener1, ener01, 0, +1);
                 erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
                 if (erf->pass) {
                     cpe->is_mask[w*16+g] = 1;
index e35f0aa695241f5b387e41a94192c525d13f237a..31bbacac5800460ceb8279a132d771d44f97d1d7 100644 (file)
@@ -43,7 +43,8 @@ struct AACISError {
 
 struct AACISError ff_aac_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
                                          int start, int w, int g, float ener0,
-                                         float ener1, float ener01, int phase);
+                                         float ener1, float ener01,
+                                         int use_pcoeffs, int phase);
 void ff_aac_search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
 
 #endif /* AVCODEC_AACENC_IS_H */
index fafe0029d4208d6c2e3d0c78ff579718068b01ea..eb8e7f7d2783e87dc162369a3c51c52f6d9868ce 100644 (file)
@@ -179,15 +179,15 @@ void ff_aac_adjust_common_prediction(AACEncContext *s, ChannelElement *cpe)
                 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];
-                    ener0 += coef0*coef0;
-                    ener1 += coef1*coef1;
+                    ener0  += coef0*coef0;
+                    ener1  += coef1*coef1;
                     ener01 += (coef0 + coef1)*(coef0 + coef1);
                 }
             }
             ph_err1 = ff_aac_is_encoding_err(s, cpe, start, w, g,
-                                             ener0, ener1, ener01, -1);
+                                             ener0, ener1, ener01, 1, -1);
             ph_err2 = ff_aac_is_encoding_err(s, cpe, start, w, g,
-                                             ener0, ener1, ener01, +1);
+                                             ener0, ener1, ener01, 1, +1);
             erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
             if (erf->pass) {
                 sce0->ics.prediction_used[sfb] = 1;