History

aaccoder: add frequency scaling and quantization correction for PNS

This commit once again improves the PNS implementation by scaling the thresholds with frequency. The thresholds get looser as the frequency increases since higher frequencies are basically noise to human ears. Also, this introduces quantization error correction for PNS. Should the error be too much, no PNS will be used. The energy_ratio is used to regulate the actual encoded PNS energy: if the generated PNS energy is higher than the energy from the psy system, energy_ratio is used to correct it so that hopefully once requantized and transmitted the value in the decoder will be closer to what the encoder has.

Rostislav Pehlivanov committed 11 years ago

Commit b6cc8ec1 parent 0c511eb2 files · +18 −12Browse files

Showing the changes to libavcodec/aaccoder.c (1 of 2 files). Show all

Unified · Split

libavcodec/aaccoder.c+17−11
@@ -876,36 +876,39 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 875 unmodified lines
876 for (g = 0; g < sce->ics.num_swb; g++) {876 for (g = 0; g < sce->ics.num_swb; g++) {
877 int noise_sfi, try_pns = 0;877 int noise_sfi, try_pns = 0;
878 float dist1 = 0.0f, dist2 = 0.0f, noise_amp;878 float dist1 = 0.0f, dist2 = 0.0f, noise_amp;
879 float energy = 0.0f, threshold = 0.0f, spread = 0.0f;879 float pns_energy = 0.0f, energy_ratio, dist_thresh;
880 float sfb_energy = 0.0f, threshold = 0.0f, spread = 0.0f;
881 float freq_boost = FFMAX(0.88f*start*freq_mult/NOISE_LOW_LIMIT, 1.0f);
880 if (start*freq_mult < NOISE_LOW_LIMIT) {882 if (start*freq_mult < NOISE_LOW_LIMIT) {
881 start += sce->ics.swb_sizes[g];883 start += sce->ics.swb_sizes[g];
882 continue;884 continue;
885 } else {
886 dist_thresh = FFMIN(0.008f*(NOISE_LOW_LIMIT/start*freq_mult), 1.11f);
883 }887 }
884 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {888 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
885 band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];889 band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
886 energy += band->energy;890 sfb_energy += band->energy;
887 spread += band->spread;891 spread += band->spread;
888 threshold += band->threshold;892 threshold += band->threshold;
889 }893 }
890 sce->pns_ener[w*16+g] = energy;
891 894
892 if (sce->zeroes[w*16+g]) {895 if (sce->zeroes[w*16+g]) {
893 try_pns = 1;896 try_pns = 1;
894 } else if (energy < threshold) {897 } else if (sfb_energy < threshold*freq_boost) {
895 try_pns = 1;898 try_pns = 1;
896 } else if (spread > spread_threshold) {899 } else if (spread > spread_threshold) {
897 try_pns = 0;900 try_pns = 0;
898 } else if (energy < threshold*thr_mult) {901 } else if (sfb_energy < threshold*thr_mult*freq_boost) {
899 try_pns = 1;902 try_pns = 1;
900 }903 }
901 904
902 if (!try_pns || !energy) {905 if (!try_pns || !sfb_energy) {
903 start += sce->ics.swb_sizes[g];906 start += sce->ics.swb_sizes[g];
904 continue;907 continue;
905 }908 }
906 909
907 noise_sfi = av_clip(roundf(log2f(energy)*2), -100, 155); /* Quantize */910 noise_sfi = av_clip(roundf(log2f(sfb_energy)*2), -100, 155); /* Quantize */
908 noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */911 noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */
909 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {912 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
910 float band_energy, scale;913 float band_energy, scale;
911 band = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];914 band = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
@@ -914,6 +917,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 2 unmodified lines
914 band_energy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);917 band_energy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
915 scale = noise_amp/sqrtf(band_energy);918 scale = noise_amp/sqrtf(band_energy);
916 s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]);919 s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]);
920 pns_energy += s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
917 abs_pow34_v(NOR34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]);921 abs_pow34_v(NOR34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]);
918 abs_pow34_v(PNS34, PNS, sce->ics.swb_sizes[g]);922 abs_pow34_v(PNS34, PNS, sce->ics.swb_sizes[g]);
919 dist1 += quantize_band_cost(s, &sce->coeffs[start + (w+w2)*128],923 dist1 += quantize_band_cost(s, &sce->coeffs[start + (w+w2)*128],
@@ -929,7 +933,9 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 9 unmodified lines
929 NOISE_BT,933 NOISE_BT,
930 lambda/band->threshold, INFINITY, NULL, 0);934 lambda/band->threshold, INFINITY, NULL, 0);
931 }935 }
932 if (dist2 < dist1) {936 energy_ratio = sfb_energy/pns_energy; /* Compensates for quantization error */
937 sce->pns_ener[w*16+g] = energy_ratio*sfb_energy;
938 if (energy_ratio > 0.80f && energy_ratio < 1.20f && dist1/dist2 > dist_thresh) {
933 sce->band_type[w*16+g] = NOISE_BT;939 sce->band_type[w*16+g] = NOISE_BT;
934 sce->zeroes[w*16+g] = 0;940 sce->zeroes[w*16+g] = 0;
935 if (sce->band_type[w*16+g-1] != NOISE_BT && /* Prevent holes */941 if (sce->band_type[w*16+g-1] != NOISE_BT && /* Prevent holes */

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