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

Unified · Split

2 files
  1. libavcodec/aaccoder.c +17 −11
  2. tests/fate/aac.mak +1 −1
libavcodec/aaccoder.c+17−11
@@ -876,36 +876,39 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne · 875 unmodified lines
876876 for (g = 0; g < sce->ics.num_swb; g++) {
877877 int noise_sfi, try_pns = 0;
878878 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);
880882 if (start*freq_mult < NOISE_LOW_LIMIT) {
881883 start += sce->ics.swb_sizes[g];
882884 continue;
885+ } else {
886+ dist_thresh = FFMIN(0.008f*(NOISE_LOW_LIMIT/start*freq_mult), 1.11f);
883887 }
884888 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
885889 band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
886− energy += band->energy;
887− spread += band->spread;
888− threshold += band->threshold;
890+ sfb_energy += band->energy;
891+ spread += band->spread;
892+ threshold += band->threshold;
889893 }
890− sce->pns_ener[w*16+g] = energy;
891894
892895 if (sce->zeroes[w*16+g]) {
893896 try_pns = 1;
894− } else if (energy < threshold) {
897+ } else if (sfb_energy < threshold*freq_boost) {
895898 try_pns = 1;
896899 } else if (spread > spread_threshold) {
897900 try_pns = 0;
898− } else if (energy < threshold*thr_mult) {
901+ } else if (sfb_energy < threshold*thr_mult*freq_boost) {
899902 try_pns = 1;
900903 }
901904
902− if (!try_pns || !energy) {
905+ if (!try_pns || !sfb_energy) {
903906 start += sce->ics.swb_sizes[g];
904907 continue;
905908 }
906909
907− noise_sfi = av_clip(roundf(log2f(energy)*2), -100, 155); /* Quantize */
908− noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */
910+ noise_sfi = av_clip(roundf(log2f(sfb_energy)*2), -100, 155); /* Quantize */
911+ noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */
909912 for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
910913 float band_energy, scale;
911914 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
914917 band_energy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
915918 scale = noise_amp/sqrtf(band_energy);
916919 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]);
917921 abs_pow34_v(NOR34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]);
918922 abs_pow34_v(PNS34, PNS, sce->ics.swb_sizes[g]);
919923 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
929933 NOISE_BT,
930934 lambda/band->threshold, INFINITY, NULL, 0);
931935 }
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) {
933939 sce->band_type[w*16+g] = NOISE_BT;
934940 sce->zeroes[w*16+g] = 0;
935941 if (sce->band_type[w*16+g-1] != NOISE_BT && /* Prevent holes */
tests/fate/aac.mak+1−1
@@ -163,7 +163,7 @@ fate-aac-pns-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-re · 162 unmodified lines
163163 fate-aac-pns-encode: CMP = stddev
164164 fate-aac-pns-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
165165 fate-aac-pns-encode: CMP_SHIFT = -4096
166−fate-aac-pns-encode: CMP_TARGET = 647.11
166+fate-aac-pns-encode: CMP_TARGET = 637.66
167167 fate-aac-pns-encode: SIZE_TOLERANCE = 3560
168168 fate-aac-pns-encode: FUZZ = 5
169169

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