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

Unified · Split

5 files
  1. libavcodec/Makefile +1 −0
  2. libavcodec/aaccoder.c +3 −99
  3. libavcodec/aacenc.c +5 −3
  4. libavcodec/aacenc_is.c +136 −0
  5. libavcodec/aacenc_is.h +47 −0
libavcodec/Makefile+1−0
@@ -132,6 +132,7 @@ OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o · 131 unmodified lines
132132 sbrdsp_fixed.o aacpsdsp_fixed.o
133133 OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
134134 aacpsy.o aactab.o \
135+ aacenc_is.o \
135136 psymodel.o mpeg4audio.o kbdwin.o
136137 OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
137138 OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o
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];
libavcodec/aacenc.c+5−3
@@ -459,7 +459,9 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 458 unmodified lines
459459 AACEncContext *s = avctx->priv_data;
460460 float **samples = s->planar_samples, *samples2, *la, *overlap;
461461 ChannelElement *cpe;
462− int i, ch, w, g, chans, tag, start_ch, ret, ms_mode = 0, is_mode = 0;
462+ SingleChannelElement *sce;
463+ int i, ch, w, g, chans, tag, start_ch, ret;
464+ int ms_mode = 0, is_mode = 0, tns_mode = 0, pred_mode = 0;
463465 int chan_el_counter[4];
464466 FFPsyWindowInfo windows[AAC_MAX_CHANNELS];
465467
@@ -608,7 +610,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 142 unmodified lines
608610 s->coder->search_for_ms(s, cpe);
609611 }
610612 }
611− if (chans > 1 && s->options.intensity_stereo && s->coder->search_for_is) {
613+ if (s->options.intensity_stereo && s->coder->search_for_is) {
612614 s->coder->search_for_is(s, avctx, cpe);
613615 if (cpe->is_mode) is_mode = 1;
614616 }
@@ -636,7 +638,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 21 unmodified lines
636638 s->psy.bitres.bits = frame_bits / s->channels;
637639 break;
638640 }
639− if (is_mode || ms_mode) {
641+ if (is_mode || ms_mode || tns_mode || pred_mode) {
640642 for (i = 0; i < s->chan_map[0]; i++) {
641643 // Must restore coeffs
642644 chans = tag == TYPE_CPE ? 2 : 1;
libavcodec/aacenc_is.c+136−0
@@ -0,0 +1,136 @@
1+/*
2+ * AAC encoder intensity stereo
3+ * Copyright (C) 2015 Rostislav Pehlivanov
4+ *
5+ * This file is part of FFmpeg.
6+ *
7+ * FFmpeg is free software; you can redistribute it and/or
8+ * modify it under the terms of the GNU Lesser General Public
9+ * License as published by the Free Software Foundation; either
10+ * version 2.1 of the License, or (at your option) any later version.
11+ *
12+ * FFmpeg is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+ * Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public
18+ * License along with FFmpeg; if not, write to the Free Software
19+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+ */
21+
22+/**
23+ * @file
24+ * AAC encoder Intensity Stereo
25+ * @author Rostislav Pehlivanov ( atomnuker gmail com )
26+ */
27+
28+#include "aacenc.h"
29+#include "aacenc_utils.h"
30+#include "aacenc_is.h"
31+#include "aacenc_quantization.h"
32+
33+struct is_error calc_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
34+ int start, int w, int g, float ener0,
35+ float ener1, float ener01, int phase)
36+{
37+ int i, w2;
38+ float *L34 = &s->scoefs[256*0], *R34 = &s->scoefs[256*1];
39+ float *IS = &s->scoefs[256*2], *I34 = &s->scoefs[256*3];
40+ float dist1 = 0.0f, dist2 = 0.0f;
41+ struct is_error is_error = {0};
42+ SingleChannelElement *sce0 = &cpe->ch[0];
43+ SingleChannelElement *sce1 = &cpe->ch[1];
44+
45+ for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
46+ FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
47+ FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
48+ int is_band_type, is_sf_idx = FFMAX(1, sce0->sf_idx[(w+w2)*16+g]-4);
49+ float e01_34 = phase*pow(sqrt(ener1/ener0), 3.0/4.0);
50+ float maxval, dist_spec_err = 0.0f;
51+ float minthr = FFMIN(band0->threshold, band1->threshold);
52+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
53+ IS[i] = (sce0->pcoeffs[start+(w+w2)*128+i]+
54+ phase*sce1->pcoeffs[start+(w+w2)*128+i])*
55+ sqrt(ener0/ener01);
56+ }
57+ abs_pow34_v(L34, &sce0->coeffs[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
58+ abs_pow34_v(R34, &sce1->coeffs[start+(w+w2)*128], sce0->ics.swb_sizes[g]);
59+ abs_pow34_v(I34, IS, sce0->ics.swb_sizes[g]);
60+ maxval = find_max_val(1, sce0->ics.swb_sizes[g], I34);
61+ is_band_type = find_min_book(maxval, is_sf_idx);
62+ dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128], L34,
63+ sce0->ics.swb_sizes[g],
64+ sce0->sf_idx[(w+w2)*16+g],
65+ sce0->band_type[(w+w2)*16+g],
66+ s->lambda / band0->threshold, INFINITY, NULL, 0);
67+ dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128], R34,
68+ sce1->ics.swb_sizes[g],
69+ sce1->sf_idx[(w+w2)*16+g],
70+ sce1->band_type[(w+w2)*16+g],
71+ s->lambda / band1->threshold, INFINITY, NULL, 0);
72+ dist2 += quantize_band_cost(s, IS, I34, sce0->ics.swb_sizes[g],
73+ is_sf_idx, is_band_type,
74+ s->lambda / minthr, INFINITY, NULL, 0);
75+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
76+ dist_spec_err += (L34[i] - I34[i])*(L34[i] - I34[i]);
77+ dist_spec_err += (R34[i] - I34[i]*e01_34)*(R34[i] - I34[i]*e01_34);
78+ }
79+ dist_spec_err *= s->lambda / minthr;
80+ dist2 += dist_spec_err;
81+ }
82+
83+ is_error.pass = dist2 <= dist1;
84+ is_error.phase = phase;
85+ is_error.error = fabsf(dist1 - dist2);
86+ is_error.dist1 = dist1;
87+ is_error.dist2 = dist2;
88+
89+ return is_error;
90+}
91+
92+void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe)
93+{
94+ SingleChannelElement *sce0 = &cpe->ch[0];
95+ SingleChannelElement *sce1 = &cpe->ch[1];
96+ int start = 0, count = 0, w, w2, g, i;
97+ const float freq_mult = avctx->sample_rate/(1024.0f/sce0->ics.num_windows)/2.0f;
98+
99+ if (!cpe->common_window)
100+ return;
101+
102+ for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
103+ start = 0;
104+ for (g = 0; g < sce0->ics.num_swb; g++) {
105+ if (start*freq_mult > INT_STEREO_LOW_LIMIT*(s->lambda/170.0f) &&
106+ cpe->ch[0].band_type[w*16+g] != NOISE_BT && !cpe->ch[0].zeroes[w*16+g] &&
107+ cpe->ch[1].band_type[w*16+g] != NOISE_BT && !cpe->ch[1].zeroes[w*16+g]) {
108+ float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f;
109+ struct is_error ph_err1, ph_err2, *erf;
110+ for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
111+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
112+ float coef0 = sce0->pcoeffs[start+(w+w2)*128+i];
113+ float coef1 = sce1->pcoeffs[start+(w+w2)*128+i];
114+ ener0 += coef0*coef0;
115+ ener1 += coef1*coef1;
116+ ener01 += (coef0 + coef1)*(coef0 + coef1);
117+ }
118+ }
119+ ph_err1 = calc_is_encoding_err(s, cpe, start, w, g,
120+ ener0, ener1, ener01, -1);
121+ ph_err2 = calc_is_encoding_err(s, cpe, start, w, g,
122+ ener0, ener1, ener01, +1);
123+ erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
124+ if (erf->pass) {
125+ cpe->is_mask[w*16+g] = 1;
126+ cpe->ch[0].is_ener[w*16+g] = sqrt(ener0/ener01);
127+ cpe->ch[1].is_ener[w*16+g] = ener0/ener1;
128+ cpe->ch[1].band_type[w*16+g] = erf->phase ? INTENSITY_BT : INTENSITY_BT2;
129+ count++;
130+ }
131+ }
132+ start += sce0->ics.swb_sizes[g];
133+ }
134+ }
135+ cpe->is_mode = !!count;
136+}
libavcodec/aacenc_is.h+47−0
@@ -0,0 +1,47 @@
1+/*
2+ * AAC encoder intensity stereo
3+ * Copyright (C) 2015 Rostislav Pehlivanov
4+ *
5+ * This file is part of FFmpeg.
6+ *
7+ * FFmpeg is free software; you can redistribute it and/or
8+ * modify it under the terms of the GNU Lesser General Public
9+ * License as published by the Free Software Foundation; either
10+ * version 2.1 of the License, or (at your option) any later version.
11+ *
12+ * FFmpeg is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+ * Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public
18+ * License along with FFmpeg; if not, write to the Free Software
19+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+ */
21+
22+/**
23+ * @file
24+ * AAC encoder Intensity Stereo
25+ * @author Rostislav Pehlivanov ( atomnuker gmail com )
26+ */
27+
28+#ifndef AVCODEC_AACENC_INTENSITY_STEREO_H
29+#define AVCODEC_AACENC_INTENSITY_STEREO_H
30+
31+/** Frequency in Hz for lower limit of intensity stereo **/
32+#define INT_STEREO_LOW_LIMIT 6100
33+
34+struct is_error {
35+ int pass; /* 1 if dist2 <= dist1 */
36+ int phase; /* -1 or +1 */
37+ float error; /* fabs(dist1 - dist2) */
38+ float dist1; /* From original coeffs */
39+ float dist2; /* From IS'd coeffs */
40+};
41+
42+struct is_error calc_is_encoding_err(AACEncContext *s, ChannelElement *cpe,
43+ int start, int g, int w, float ener0,
44+ float ener1, float ener01, int phase);
45+void search_for_is(AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
46+
47+#endif /* AVCODEC_AACENC_INTENSITY_STEREO_H */

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