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.
Showing the changes to libavcodec/aaccoder.c (1 of 5 files). Show all
Unified · Split
| @@ -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 4500 | 50 | #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 | ||
| 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 | |||
| 990 | static void search_for_ms(AACEncContext *s, ChannelElement *cpe) | 894 | static 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]; |