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
132 sbrdsp_fixed.o aacpsdsp_fixed.o132 sbrdsp_fixed.o aacpsdsp_fixed.o
133OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \133OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
134 aacpsy.o aactab.o \134 aacpsy.o aactab.o \
135 aacenc_is.o \
135 psymodel.o mpeg4audio.o kbdwin.o136 psymodel.o mpeg4audio.o kbdwin.o
136OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o137OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
137OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o138OBJS-$(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
44#include "aacenc_quantization.h"44#include "aacenc_quantization.h"
45#include "aac_tablegen_decl.h"45#include "aac_tablegen_decl.h"
46 46
47#include "aacenc_is.h"
48
47/** Frequency in Hz for lower limit of noise substitution **/49/** Frequency in Hz for lower limit of noise substitution **/
48#define NOISE_LOW_LIMIT 450050#define NOISE_LOW_LIMIT 4500
49 51
@@ -889,104 +891,6 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 839 unmodified lines
889 }891 }
890}892}
891 893
892static 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
990static void search_for_ms(AACEncContext *s, ChannelElement *cpe)894static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
991{895{
992 int start = 0, i, w, w2, g;896 int start = 0, i, w, w2, g;
@@ -1000,7 +904,7 @@ static void search_for_ms(AACEncContext *s, ChannelElement *cpe) · 7 unmodified lines
1000 for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {904 for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
1001 start = 0;905 start = 0;
1002 for (g = 0; g < sce0->ics.num_swb; g++) {906 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]) {
1004 float dist1 = 0.0f, dist2 = 0.0f;908 float dist1 = 0.0f, dist2 = 0.0f;
1005 for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {909 for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
1006 FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];910 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
459 AACEncContext *s = avctx->priv_data;459 AACEncContext *s = avctx->priv_data;
460 float **samples = s->planar_samples, *samples2, *la, *overlap;460 float **samples = s->planar_samples, *samples2, *la, *overlap;
461 ChannelElement *cpe;461 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;
463 int chan_el_counter[4];465 int chan_el_counter[4];
464 FFPsyWindowInfo windows[AAC_MAX_CHANNELS];466 FFPsyWindowInfo windows[AAC_MAX_CHANNELS];
465 467
@@ -608,7 +610,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 142 unmodified lines
608 s->coder->search_for_ms(s, cpe);610 s->coder->search_for_ms(s, cpe);
609 }611 }
610 }612 }
611 if (chans > 1 && s->options.intensity_stereo && s->coder->search_for_is) {613 if (s->options.intensity_stereo && s->coder->search_for_is) {
612 s->coder->search_for_is(s, avctx, cpe);614 s->coder->search_for_is(s, avctx, cpe);
613 if (cpe->is_mode) is_mode = 1;615 if (cpe->is_mode) is_mode = 1;
614 }616 }
@@ -636,7 +638,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, · 21 unmodified lines
636 s->psy.bitres.bits = frame_bits / s->channels;638 s->psy.bitres.bits = frame_bits / s->channels;
637 break;639 break;
638 }640 }
639 if (is_mode || ms_mode) {641 if (is_mode || ms_mode || tns_mode || pred_mode) {
640 for (i = 0; i < s->chan_map[0]; i++) {642 for (i = 0; i < s->chan_map[0]; i++) {
641 // Must restore coeffs643 // Must restore coeffs
642 chans = tag == TYPE_CPE ? 2 : 1;644 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
33struct 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
92void 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
34struct 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
42struct 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);
45void 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