[FFmpeg-devel] [PATCH 6/6] aacenc: Move Intensity Stereo search functions to a new file

Rostislav Pehlivanov atomnuker at gmail.com
Wed Jul 29 06:44:29 CEST 2015


With the new method to determine the phase, the functions
got sufficiently large to have their own file.
There are absolutely no changes from the IS patch from
this patchset, this commit simply moves it out of aaccoder.c
Encoding is still being done within the aacenc.c file due
to the way IS and M/S interact and affect the spectral coefficients.
This commit also makes use of the separated quantization functions
from the previous commit.
---
 libavcodec/Makefile    |   2 +-
 libavcodec/aaccoder.c  | 118 +---------------------------------------
 libavcodec/aacenc_is.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/aacenc_is.h |  46 ++++++++++++++++
 4 files changed, 190 insertions(+), 118 deletions(-)
 create mode 100644 libavcodec/aacenc_is.c
 create mode 100644 libavcodec/aacenc_is.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7778326..70d72c8 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -130,7 +130,7 @@ OBJS-$(CONFIG_AAC_FIXED_DECODER)       += aacdec_fixed.o aactab.o aacsbr_fixed.o
                                           aacadtsdec.o mpeg4audio.o kbdwin.o \
                                           sbrdsp_fixed.o aacpsdsp_fixed.o
 OBJS-$(CONFIG_AAC_ENCODER)             += aacenc.o aaccoder.o aacenctab.o    \
-                                          aacpsy.o aactab.o      \
+                                          aacpsy.o aactab.o aacenc_is.o      \
                                           psymodel.o mpeg4audio.o kbdwin.o
 OBJS-$(CONFIG_AASC_DECODER)            += aasc.o msrledec.o
 OBJS-$(CONFIG_AC3_DECODER)             += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 83376aa..3527a90 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -40,6 +40,7 @@
 #include "aacenc.h"
 #include "aactab.h"
 #include "aacenctab.h"
+#include "aacenc_is.h"
 #include "aacenc_utils.h"
 #include "aacenc_quantization.h"
 #include "aac_tablegen_decl.h"
@@ -897,123 +898,6 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
     }
 }
 
-struct is_error {
-    int pass;
-    int phase;
-    float error;
-};
-
-static struct is_error calc_encoding_err_is(AACEncContext *s, ChannelElement *cpe,
-                                            float *L34, float *R34, float ener0,
-                                            float ener1, float ener01,
-                                            int start, int g, int w, int phase)
-{
-    int i, w2;
-    float IS[128];
-    float *I34  = s->scoefs + 128*2;
-    float dist1 = 0.0f, dist2 = 0.0f;
-    struct is_error is_error = {0};
-    SingleChannelElement *sce0 = &cpe->ch[0];
-    SingleChannelElement *sce1 = &cpe->ch[1];
-
-    if (cpe->ms_mode)
-        phase = 1 - 2 * cpe->ms_mask[w*16+g];
-
-    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(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],
-                                    s->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],
-                                    s->lambda / band1->threshold, INFINITY, NULL, 0);
-        dist2 += quantize_band_cost(s, IS, I34, sce0->ics.swb_sizes[g],
-                                    is_sf_idx, is_band_type,
-                                    s->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 *= s->lambda / minthr;
-        dist2 += dist_spec_err;
-    }
-
-    is_error.phase = phase;
-    is_error.pass  = dist2 <= dist1;
-    is_error.error = (dist1 - dist2)*(dist1 - dist2);
-
-    return is_error;
-}
-
-static void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe)
-{
-    SingleChannelElement *sce0 = &cpe->ch[0];
-    SingleChannelElement *sce1 = &cpe->ch[1];
-    int start = 0, count = 0, w, g, w2, i;
-    const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f;
-    float *L34  = s->scoefs + 128*0, *R34  = s->scoefs + 128*1;
-
-    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*(s->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]) {
-                    float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f;
-                struct is_error ph_err1, ph_err2, *erf;
-                for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
-                    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]);
-                    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;
-                        ener01 += (coef0 + coef1)*(coef0 + coef1);
-                    }
-                }
-                ph_err1 = calc_encoding_err_is(s, cpe, L34, R34, ener0, ener1,
-                                               ener01, start, g, w, -1);
-                ph_err2 = calc_encoding_err_is(s, cpe, L34, R34, ener0, ener1,
-                                               ener01, start, g, w, +1);
-                erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
-                if (erf->pass) {
-                    cpe->is_mask[w*16+g] = 1;
-                    cpe->ch[0].is_ener[w*16+g] = sqrt(ener0/ener01);
-                    cpe->ch[1].is_ener[w*16+g] = ener0/ener1;
-                    cpe->ch[1].band_type[w*16+g] = erf->phase ? INTENSITY_BT : 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;
diff --git a/libavcodec/aacenc_is.c b/libavcodec/aacenc_is.c
new file mode 100644
index 0000000..08005b2
--- /dev/null
+++ b/libavcodec/aacenc_is.c
@@ -0,0 +1,142 @@
+/*
+ * AAC encoder intensity stereo
+ * 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 intensity stereo
+ * @author Rostislav Pehlivanov ( atomnuker gmail com )
+ */
+
+#include "aacenc.h"
+#include "aacenc_utils.h"
+#include "aacenc_quantization.h"
+#include "aacenc_is.h"
+
+struct is_error calc_encoding_err_is(AACEncContext *s, ChannelElement *cpe,
+                                     float *L34, float *R34, float ener0,
+                                     float ener1, float ener01,
+                                     int start, int g, int w, int phase)
+{
+    int i, w2;
+    float IS[128];
+    float *I34  = s->scoefs + 128*2;
+    float dist1 = 0.0f, dist2 = 0.0f;
+    struct is_error is_error = {0};
+    SingleChannelElement *sce0 = &cpe->ch[0];
+    SingleChannelElement *sce1 = &cpe->ch[1];
+
+    if (cpe->ms_mode)
+        phase = 1 - 2 * cpe->ms_mask[w*16+g];
+
+    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(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],
+                                    s->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],
+                                    s->lambda / band1->threshold, INFINITY, NULL, 0);
+        dist2 += quantize_band_cost(s, IS, I34, sce0->ics.swb_sizes[g],
+                                    is_sf_idx, is_band_type,
+                                    s->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 *= s->lambda / minthr;
+        dist2 += dist_spec_err;
+    }
+
+    is_error.phase = phase;
+    is_error.pass  = dist2 <= dist1;
+    is_error.error = (dist1 - dist2)*(dist1 - dist2);
+
+    return is_error;
+}
+
+void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe)
+{
+    SingleChannelElement *sce0 = &cpe->ch[0];
+    SingleChannelElement *sce1 = &cpe->ch[1];
+    int start = 0, count = 0, w, g, w2, i;
+    const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f;
+    float *L34  = s->scoefs + 128*0, *R34  = s->scoefs + 128*1;
+
+    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*(s->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]) {
+                float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f;
+                struct is_error ph_err1, ph_err2, *erf;
+                for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
+                    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]);
+                    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;
+                        ener01 += (coef0 + coef1)*(coef0 + coef1);
+                    }
+                }
+                ph_err1 = calc_encoding_err_is(s, cpe, L34, R34, ener0, ener1,
+                                               ener01, start, g, w, -1);
+                ph_err2 = calc_encoding_err_is(s, cpe, L34, R34, ener0, ener1,
+                                               ener01, start, g, w, +1);
+                erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
+                if (erf->pass) {
+                    cpe->is_mask[w*16+g] = 1;
+                    cpe->ch[0].is_ener[w*16+g] = sqrt(ener0/ener01);
+                    cpe->ch[1].is_ener[w*16+g] = ener0/ener1;
+                    cpe->ch[1].band_type[w*16+g] = erf->phase ? INTENSITY_BT : INTENSITY_BT2;
+                    count++;
+                }
+            }
+            start += sce0->ics.swb_sizes[g];
+        }
+    }
+    cpe->is_mode = !!count;
+}
diff --git a/libavcodec/aacenc_is.h b/libavcodec/aacenc_is.h
new file mode 100644
index 0000000..064bc2f
--- /dev/null
+++ b/libavcodec/aacenc_is.h
@@ -0,0 +1,46 @@
+/*
+ * AAC encoder intensity stereo
+ * 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 intensity stereo
+ * @author Rostislav Pehlivanov ( atomnuker gmail com )
+ */
+
+#ifndef AVCODEC_AACENC_INTENSITY_STEREO_H
+#define AVCODEC_AACENC_INTENSITY_STEREO_H
+
+/** Frequency in Hz for lower limit of intensity stereo **/
+#define INT_STEREO_LOW_LIMIT 6100
+
+struct is_error {
+    int pass;
+    int phase;
+    float error;
+};
+
+struct is_error calc_encoding_err_is(AACEncContext *s, ChannelElement *cpe,
+                                     float *L34, float *R34, float ener0,
+                                     float ener1, float ener01,
+                                     int start, int g, int w, int phase);
+void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
+
+#endif /* AVCODEC_AACENC_INTENSITY_STEREO_H */
-- 
2.5.0.rc2.392.g76e840b



More information about the ffmpeg-devel mailing list