#include "libavutil/libm.h" // brought forward to work around cygwin header breakage
#include <float.h>
+
#include "libavutil/mathematics.h"
+#include "mathops.h"
#include "avcodec.h"
#include "put_bits.h"
#include "aac.h"
#include "aacenc_is.h"
#include "aacenc_tns.h"
+#include "aacenc_ltp.h"
#include "aacenc_pred.h"
-/** Frequency in Hz for lower limit of noise substitution **/
-#define NOISE_LOW_LIMIT 4000
+#include "libavcodec/aaccoder_twoloop.h"
/* Parameter of f(x) = a*(lambda/100), defines the maximum fourier spread
* beyond which no PNS is used (since the SFBs contain tone rather than noise) */
-#define NOISE_SPREAD_THRESHOLD 0.9673f
+#define NOISE_SPREAD_THRESHOLD 0.5073f
/* Parameter of f(x) = a*(100/lambda), defines how much PNS is allowed to
* replace low energy non zero bands */
#define NOISE_LAMBDA_REPLACE 1.948f
+#include "libavcodec/aaccoder_trellis.h"
+
/**
* structure used in optimal codebook search
*/
rd += quantize_band_cost(s, &sce->coeffs[start + w*128],
&s->scoefs[start + w*128], size,
sce->sf_idx[(win+w)*16+swb], aac_cb_out_map[cb],
- lambda / band->threshold, INFINITY, NULL, 0);
+ lambda / band->threshold, INFINITY, NULL, NULL, 0);
}
cost_stay_here = path[swb][cb].cost + rd;
cost_get_here = minrd + rd + run_bits + 4;
}
}
-static void codebook_trellis_rate(AACEncContext *s, SingleChannelElement *sce,
- int win, int group_len, const float lambda)
-{
- BandCodingPath path[120][CB_TOT_ALL];
- int w, swb, cb, start, size;
- int i, j;
- const int max_sfb = sce->ics.max_sfb;
- const int run_bits = sce->ics.num_windows == 1 ? 5 : 3;
- const int run_esc = (1 << run_bits) - 1;
- int idx, ppos, count;
- int stackrun[120], stackcb[120], stack_len;
- float next_minbits = INFINITY;
- int next_mincb = 0;
-
- abs_pow34_v(s->scoefs, sce->coeffs, 1024);
- start = win*128;
- for (cb = 0; cb < CB_TOT_ALL; cb++) {
- path[0][cb].cost = run_bits+4;
- path[0][cb].prev_idx = -1;
- path[0][cb].run = 0;
- }
- for (swb = 0; swb < max_sfb; swb++) {
- size = sce->ics.swb_sizes[swb];
- if (sce->zeroes[win*16 + swb]) {
- float cost_stay_here = path[swb][0].cost;
- float cost_get_here = next_minbits + run_bits + 4;
- if ( run_value_bits[sce->ics.num_windows == 8][path[swb][0].run]
- != run_value_bits[sce->ics.num_windows == 8][path[swb][0].run+1])
- cost_stay_here += run_bits;
- if (cost_get_here < cost_stay_here) {
- path[swb+1][0].prev_idx = next_mincb;
- path[swb+1][0].cost = cost_get_here;
- path[swb+1][0].run = 1;
- } else {
- path[swb+1][0].prev_idx = 0;
- path[swb+1][0].cost = cost_stay_here;
- path[swb+1][0].run = path[swb][0].run + 1;
- }
- next_minbits = path[swb+1][0].cost;
- next_mincb = 0;
- for (cb = 1; cb < CB_TOT_ALL; cb++) {
- path[swb+1][cb].cost = 61450;
- path[swb+1][cb].prev_idx = -1;
- path[swb+1][cb].run = 0;
- }
- } else {
- float minbits = next_minbits;
- int mincb = next_mincb;
- int startcb = sce->band_type[win*16+swb];
- startcb = aac_cb_in_map[startcb];
- next_minbits = INFINITY;
- next_mincb = 0;
- for (cb = 0; cb < startcb; cb++) {
- path[swb+1][cb].cost = 61450;
- path[swb+1][cb].prev_idx = -1;
- path[swb+1][cb].run = 0;
- }
- for (cb = startcb; cb < CB_TOT_ALL; cb++) {
- float cost_stay_here, cost_get_here;
- float bits = 0.0f;
- if (cb >= 12 && sce->band_type[win*16+swb] != aac_cb_out_map[cb]) {
- path[swb+1][cb].cost = 61450;
- path[swb+1][cb].prev_idx = -1;
- path[swb+1][cb].run = 0;
- continue;
- }
- for (w = 0; w < group_len; w++) {
- bits += quantize_band_cost(s, &sce->coeffs[start + w*128],
- &s->scoefs[start + w*128], size,
- sce->sf_idx[win*16+swb],
- aac_cb_out_map[cb],
- 0, INFINITY, NULL, 0);
- }
- cost_stay_here = path[swb][cb].cost + bits;
- cost_get_here = minbits + bits + run_bits + 4;
- if ( run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run]
- != run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run+1])
- cost_stay_here += run_bits;
- if (cost_get_here < cost_stay_here) {
- path[swb+1][cb].prev_idx = mincb;
- path[swb+1][cb].cost = cost_get_here;
- path[swb+1][cb].run = 1;
- } else {
- path[swb+1][cb].prev_idx = cb;
- path[swb+1][cb].cost = cost_stay_here;
- path[swb+1][cb].run = path[swb][cb].run + 1;
- }
- if (path[swb+1][cb].cost < next_minbits) {
- next_minbits = path[swb+1][cb].cost;
- next_mincb = cb;
- }
- }
- }
- start += sce->ics.swb_sizes[swb];
- }
-
- //convert resulting path from backward-linked list
- stack_len = 0;
- idx = 0;
- for (cb = 1; cb < CB_TOT_ALL; cb++)
- if (path[max_sfb][cb].cost < path[max_sfb][idx].cost)
- idx = cb;
- ppos = max_sfb;
- while (ppos > 0) {
- av_assert1(idx >= 0);
- cb = idx;
- stackrun[stack_len] = path[ppos][cb].run;
- stackcb [stack_len] = cb;
- idx = path[ppos-path[ppos][cb].run+1][cb].prev_idx;
- ppos -= path[ppos][cb].run;
- stack_len++;
- }
- //perform actual band info encoding
- start = 0;
- for (i = stack_len - 1; i >= 0; i--) {
- cb = aac_cb_out_map[stackcb[i]];
- put_bits(&s->pb, 4, cb);
- count = stackrun[i];
- memset(sce->zeroes + win*16 + start, !cb, count);
- //XXX: memset when band_type is also uint8_t
- for (j = 0; j < count; j++) {
- sce->band_type[win*16 + start] = cb;
- start++;
- }
- while (count >= run_esc) {
- put_bits(&s->pb, run_bits, run_esc);
- count -= run_esc;
- }
- put_bits(&s->pb, run_bits, count);
- }
-}
typedef struct TrellisPath {
float cost;
minscaler_i = FFMIN(minscaler_i, sce->sf_idx[w*16+g]);
bands++;
} else if (sce->band_type[w*16+g] == NOISE_BT) {
- sce->sf_idx[w*16+g] = av_clip(roundf(log2f(sce->pns_ener[w*16+g])*2), -100, 155);
+ sce->sf_idx[w*16+g] = av_clip(3+ceilf(log2f(sce->pns_ener[w*16+g])*2), -100, 155);
minscaler_n = FFMIN(minscaler_n, sce->sf_idx[w*16+g]);
bands++;
}
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
dist += quantize_band_cost(s, coefs + w2*128, s->scoefs + start + w2*128, sce->ics.swb_sizes[g],
- q + q0, cb, lambda / band->threshold, INFINITY, NULL, 0);
+ q + q0, cb, lambda / band->threshold, INFINITY, NULL, NULL, 0);
}
minrd = FFMIN(minrd, dist);
sce->sf_idx[(w+w2)*16+g] = sce->sf_idx[w*16+g];
}
-/**
- * two-loop quantizers search taken from ISO 13818-7 Appendix C
- */
-static void search_for_quantizers_twoloop(AVCodecContext *avctx,
- AACEncContext *s,
- SingleChannelElement *sce,
- const float lambda)
-{
- int start = 0, i, w, w2, g;
- int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels * (lambda / 120.f);
- float dists[128] = { 0 }, uplims[128] = { 0 };
- float maxvals[128];
- int fflag, minscaler;
- int its = 0;
- int allz = 0;
- float minthr = INFINITY;
-
- // for values above this the decoder might end up in an endless loop
- // due to always having more bits than what can be encoded.
- destbits = FFMIN(destbits, 5800);
- //XXX: some heuristic to determine initial quantizers will reduce search time
- //determine zero bands and upper limits
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- for (g = 0; g < sce->ics.num_swb; g++) {
- int nz = 0;
- float uplim = 0.0f, energy = 0.0f;
- for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
- FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
- uplim += band->threshold;
- energy += band->energy;
- if (band->energy <= band->threshold || band->threshold == 0.0f) {
- sce->zeroes[(w+w2)*16+g] = 1;
- continue;
- }
- nz = 1;
- }
- uplims[w*16+g] = uplim *512;
- sce->zeroes[w*16+g] = !nz;
- if (nz)
- minthr = FFMIN(minthr, uplim);
- allz |= nz;
- }
- }
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- for (g = 0; g < sce->ics.num_swb; g++) {
- if (sce->zeroes[w*16+g]) {
- sce->sf_idx[w*16+g] = SCALE_ONE_POS;
- continue;
- }
- sce->sf_idx[w*16+g] = SCALE_ONE_POS + FFMIN(log2f(uplims[w*16+g]/minthr)*4,59);
- }
- }
-
- if (!allz)
- return;
- abs_pow34_v(s->scoefs, sce->coeffs, 1024);
-
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- start = w*128;
- for (g = 0; g < sce->ics.num_swb; g++) {
- const float *scaled = s->scoefs + start;
- maxvals[w*16+g] = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], scaled);
- start += sce->ics.swb_sizes[g];
- }
- }
-
- //perform two-loop search
- //outer loop - improve quality
- do {
- int tbits, qstep;
- minscaler = sce->sf_idx[0];
- //inner loop - quantize spectrum to fit into given number of bits
- qstep = its ? 1 : 32;
- do {
- int prev = -1;
- tbits = 0;
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- start = w*128;
- for (g = 0; g < sce->ics.num_swb; g++) {
- const float *coefs = &sce->coeffs[start];
- const float *scaled = &s->scoefs[start];
- int bits = 0;
- int cb;
- float dist = 0.0f;
-
- if (sce->zeroes[w*16+g] || sce->sf_idx[w*16+g] >= 218) {
- start += sce->ics.swb_sizes[g];
- continue;
- }
- minscaler = FFMIN(minscaler, sce->sf_idx[w*16+g]);
- cb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
- for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
- int b;
- dist += quantize_band_cost(s, coefs + w2*128,
- scaled + w2*128,
- sce->ics.swb_sizes[g],
- sce->sf_idx[w*16+g],
- cb,
- 1.0f,
- INFINITY,
- &b,
- 0);
- bits += b;
- }
- dists[w*16+g] = dist - bits;
- if (prev != -1) {
- bits += ff_aac_scalefactor_bits[sce->sf_idx[w*16+g] - prev + SCALE_DIFF_ZERO];
- }
- tbits += bits;
- start += sce->ics.swb_sizes[g];
- prev = sce->sf_idx[w*16+g];
- }
- }
- if (tbits > destbits) {
- for (i = 0; i < 128; i++)
- if (sce->sf_idx[i] < 218 - qstep)
- sce->sf_idx[i] += qstep;
- } else {
- for (i = 0; i < 128; i++)
- if (sce->sf_idx[i] > 60 - qstep)
- sce->sf_idx[i] -= qstep;
- }
- qstep >>= 1;
- if (!qstep && tbits > destbits*1.02 && sce->sf_idx[0] < 217)
- qstep = 1;
- } while (qstep);
-
- fflag = 0;
- minscaler = av_clip(minscaler, 60, 255 - SCALE_MAX_DIFF);
-
- for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- for (g = 0; g < sce->ics.num_swb; g++) {
- int prevsc = sce->sf_idx[w*16+g];
- if (dists[w*16+g] > uplims[w*16+g] && sce->sf_idx[w*16+g] > 60) {
- if (find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]-1))
- sce->sf_idx[w*16+g]--;
- else //Try to make sure there is some energy in every band
- sce->sf_idx[w*16+g]-=2;
- }
- sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler, minscaler + SCALE_MAX_DIFF);
- sce->sf_idx[w*16+g] = FFMIN(sce->sf_idx[w*16+g], 219);
- if (sce->sf_idx[w*16+g] != prevsc)
- fflag = 1;
- sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
- }
- }
- its++;
- } while (fflag && its < 10);
-}
static void search_for_quantizers_faac(AVCodecContext *avctx, AACEncContext *s,
SingleChannelElement *sce,
ESC_BT,
lambda,
INFINITY,
- &b,
+ &b, NULL,
0);
dist -= b;
}
static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce)
{
FFPsyBand *band;
- int w, g, w2, i, start, count = 0;
+ int w, g, w2, i;
+ int wlen = 1024 / sce->ics.num_windows;
+ int bandwidth, cutoff;
float *PNS = &s->scoefs[0*128], *PNS34 = &s->scoefs[1*128];
float *NOR34 = &s->scoefs[3*128];
const float lambda = s->lambda;
- const float freq_mult = avctx->sample_rate/(1024.0f/sce->ics.num_windows)/2.0f;
+ const float freq_mult = avctx->sample_rate*0.5f/wlen;
const float thr_mult = NOISE_LAMBDA_REPLACE*(100.0f/lambda);
- const float spread_threshold = NOISE_SPREAD_THRESHOLD*(lambda/100.f);
+ const float spread_threshold = FFMIN(0.75f, NOISE_SPREAD_THRESHOLD*FFMAX(0.5f, lambda/100.f));
+ const float dist_bias = av_clipf(4.f * 120 / lambda, 0.25f, 4.0f);
+ const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);
+
+ int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
+ / ((avctx->flags & CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels)
+ * (lambda / 120.f);
+
+ /** Keep this in sync with twoloop's cutoff selection */
+ float rate_bandwidth_multiplier = 1.5f;
+ int frame_bit_rate = (avctx->flags & CODEC_FLAG_QSCALE)
+ ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
+ : (avctx->bit_rate / avctx->channels);
+
+ frame_bit_rate *= 1.15f;
+
+ if (avctx->cutoff > 0) {
+ bandwidth = avctx->cutoff;
+ } else {
+ bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_bit_rate, 1, avctx->sample_rate));
+ }
+
+ cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
+ memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
- start = 0;
+ int wstart = w*128;
for (g = 0; g < sce->ics.num_swb; g++) {
- int noise_sfi, try_pns = 0;
+ int noise_sfi;
float dist1 = 0.0f, dist2 = 0.0f, noise_amp;
- float pns_energy = 0.0f, energy_ratio, dist_thresh;
- float sfb_energy = 0.0f, threshold = 0.0f, spread = 0.0f;
- float freq_boost = FFMAX(0.88f*start*freq_mult/NOISE_LOW_LIMIT, 1.0f);
- if (start*freq_mult < NOISE_LOW_LIMIT) {
- start += sce->ics.swb_sizes[g];
+ float pns_energy = 0.0f, pns_tgt_energy, energy_ratio, dist_thresh;
+ float sfb_energy = 0.0f, threshold = 0.0f, spread = 2.0f;
+ float min_energy = -1.0f, max_energy = 0.0f;
+ const int start = wstart+sce->ics.swb_offset[g];
+ const float freq = (start-wstart)*freq_mult;
+ const float freq_boost = FFMAX(0.88f*freq/NOISE_LOW_LIMIT, 1.0f);
+ if (freq < NOISE_LOW_LIMIT || (start-wstart) >= cutoff)
continue;
- } else {
- dist_thresh = FFMIN(0.008f*(NOISE_LOW_LIMIT/start*freq_mult), 1.11f);
- }
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
sfb_energy += band->energy;
- spread += band->spread;
+ spread = FFMIN(spread, band->spread);
threshold += band->threshold;
+ if (!w2) {
+ min_energy = max_energy = band->energy;
+ } else {
+ min_energy = FFMIN(min_energy, band->energy);
+ max_energy = FFMAX(max_energy, band->energy);
+ }
}
- if (sce->zeroes[w*16+g]) {
- try_pns = 1;
- } else if (sfb_energy < threshold*freq_boost) {
- try_pns = 1;
- } else if (spread > spread_threshold) {
- try_pns = 0;
- } else if (sfb_energy < threshold*thr_mult*freq_boost) {
- try_pns = 1;
- }
-
- if (!try_pns || !sfb_energy) {
- start += sce->ics.swb_sizes[g];
+ /* Ramps down at ~8000Hz and loosens the dist threshold */
+ dist_thresh = av_clipf(2.5f*NOISE_LOW_LIMIT/freq, 0.5f, 2.5f) * dist_bias;
+
+ /* PNS is acceptable when all of these are true:
+ * 1. high spread energy (noise-like band)
+ * 2. near-threshold energy (high PE means the random nature of PNS content will be noticed)
+ * 3. on short window groups, all windows have similar energy (variations in energy would be destroyed by PNS)
+ *
+ * At this stage, point 2 is relaxed for zeroed bands near the noise threshold (hole avoidance is more important)
+ */
+ if (((sce->zeroes[w*16+g] || !sce->band_alt[w*16+g]) && sfb_energy < threshold*sqrtf(1.5f/freq_boost)) || spread < spread_threshold ||
+ (!sce->zeroes[w*16+g] && sce->band_alt[w*16+g] && sfb_energy > threshold*thr_mult*freq_boost) ||
+ min_energy < pns_transient_energy_r * max_energy ) {
+ sce->pns_ener[w*16+g] = sfb_energy;
continue;
}
- noise_sfi = av_clip(roundf(log2f(sfb_energy)*2), -100, 155); /* Quantize */
+ pns_tgt_energy = sfb_energy*FFMIN(1.0f, spread*spread);
+ noise_sfi = av_clip(roundf(log2f(pns_tgt_energy)*2), -100, 155); /* Quantize */
noise_amp = -ff_aac_pow2sf_tab[noise_sfi + POW_SF2_ZERO]; /* Dequantize */
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
- float band_energy, scale;
- band = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
+ float band_energy, scale, pns_senergy;
+ const int start_c = (w+w2)*128+sce->ics.swb_offset[g];
+ band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
for (i = 0; i < sce->ics.swb_sizes[g]; i++)
PNS[i] = s->random_state = lcg_random(s->random_state);
band_energy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
scale = noise_amp/sqrtf(band_energy);
s->fdsp->vector_fmul_scalar(PNS, PNS, scale, sce->ics.swb_sizes[g]);
- pns_energy += s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
- abs_pow34_v(NOR34, &sce->coeffs[start+(w+w2)*128], sce->ics.swb_sizes[g]);
+ pns_senergy = s->fdsp->scalarproduct_float(PNS, PNS, sce->ics.swb_sizes[g]);
+ pns_energy += pns_senergy;
+ abs_pow34_v(NOR34, &sce->coeffs[start_c], sce->ics.swb_sizes[g]);
abs_pow34_v(PNS34, PNS, sce->ics.swb_sizes[g]);
- dist1 += quantize_band_cost(s, &sce->coeffs[start + (w+w2)*128],
+ dist1 += quantize_band_cost(s, &sce->coeffs[start_c],
NOR34,
sce->ics.swb_sizes[g],
sce->sf_idx[(w+w2)*16+g],
sce->band_alt[(w+w2)*16+g],
- lambda/band->threshold, INFINITY, NULL, 0);
- dist2 += quantize_band_cost(s, PNS,
- PNS34,
- sce->ics.swb_sizes[g],
- noise_sfi,
- NOISE_BT,
- lambda/band->threshold, INFINITY, NULL, 0);
+ lambda/band->threshold, INFINITY, NULL, NULL, 0);
+ /* Estimate rd on average as 5 bits for SF, 4 for the CB, plus spread energy * lambda/thr */
+ dist2 += band->energy/(band->spread*band->spread)*lambda*dist_thresh/band->threshold;
+ }
+ if (g && sce->sf_idx[(w+w2)*16+g-1] == NOISE_BT) {
+ dist2 += 5;
+ } else {
+ dist2 += 9;
}
- energy_ratio = sfb_energy/pns_energy; /* Compensates for quantization error */
- sce->pns_ener[w*16+g] = energy_ratio*sfb_energy;
- if (energy_ratio > 0.80f && energy_ratio < 1.20f && dist1/dist2 > dist_thresh) {
+ energy_ratio = pns_tgt_energy/pns_energy; /* Compensates for quantization error */
+ sce->pns_ener[w*16+g] = energy_ratio*pns_tgt_energy;
+ if (sce->zeroes[w*16+g] || !sce->band_alt[w*16+g] || (energy_ratio > 0.85f && energy_ratio < 1.25f && dist2 < dist1)) {
sce->band_type[w*16+g] = NOISE_BT;
sce->zeroes[w*16+g] = 0;
- if (sce->band_type[w*16+g-1] != NOISE_BT && /* Prevent holes */
- sce->band_type[w*16+g-2] == NOISE_BT) {
- sce->band_type[w*16+g-1] = NOISE_BT;
- sce->zeroes[w*16+g-1] = 0;
+ }
+ }
+ }
+}
+
+static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce)
+{
+ FFPsyBand *band;
+ int w, g, w2;
+ int wlen = 1024 / sce->ics.num_windows;
+ int bandwidth, cutoff;
+ const float lambda = s->lambda;
+ const float freq_mult = avctx->sample_rate*0.5f/wlen;
+ const float spread_threshold = FFMIN(0.75f, NOISE_SPREAD_THRESHOLD*FFMAX(0.5f, lambda/100.f));
+ const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);
+
+ int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
+ / ((avctx->flags & CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels)
+ * (lambda / 120.f);
+
+ /** Keep this in sync with twoloop's cutoff selection */
+ float rate_bandwidth_multiplier = 1.5f;
+ int frame_bit_rate = (avctx->flags & CODEC_FLAG_QSCALE)
+ ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
+ : (avctx->bit_rate / avctx->channels);
+
+ frame_bit_rate *= 1.15f;
+
+ if (avctx->cutoff > 0) {
+ bandwidth = avctx->cutoff;
+ } else {
+ bandwidth = FFMAX(3000, AAC_CUTOFF_FROM_BITRATE(frame_bit_rate, 1, avctx->sample_rate));
+ }
+
+ cutoff = bandwidth * 2 * wlen / avctx->sample_rate;
+
+ memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
+ for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
+ for (g = 0; g < sce->ics.num_swb; g++) {
+ float sfb_energy = 0.0f, threshold = 0.0f, spread = 2.0f;
+ float min_energy = -1.0f, max_energy = 0.0f;
+ const int start = sce->ics.swb_offset[g];
+ const float freq = start*freq_mult;
+ const float freq_boost = FFMAX(0.88f*freq/NOISE_LOW_LIMIT, 1.0f);
+ if (freq < NOISE_LOW_LIMIT || start >= cutoff) {
+ sce->can_pns[w*16+g] = 0;
+ continue;
+ }
+ for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
+ band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
+ sfb_energy += band->energy;
+ spread = FFMIN(spread, band->spread);
+ threshold += band->threshold;
+ if (!w2) {
+ min_energy = max_energy = band->energy;
+ } else {
+ min_energy = FFMIN(min_energy, band->energy);
+ max_energy = FFMAX(max_energy, band->energy);
}
- count++;
}
- start += sce->ics.swb_sizes[g];
+
+ /* PNS is acceptable when all of these are true:
+ * 1. high spread energy (noise-like band)
+ * 2. near-threshold energy (high PE means the random nature of PNS content will be noticed)
+ * 3. on short window groups, all windows have similar energy (variations in energy would be destroyed by PNS)
+ */
+ sce->pns_ener[w*16+g] = sfb_energy;
+ if (sfb_energy < threshold*sqrtf(1.5f/freq_boost) || spread < spread_threshold || min_energy < pns_transient_energy_r * max_energy) {
+ sce->can_pns[w*16+g] = 0;
+ } else {
+ sce->can_pns[w*16+g] = 1;
+ }
}
}
}
static void search_for_ms(AACEncContext *s, ChannelElement *cpe)
{
- int start = 0, i, w, w2, g;
+ int start = 0, i, w, w2, g, sid_sf_boost;
float M[128], S[128];
float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3;
const float lambda = s->lambda;
+ const float mslambda = FFMIN(1.0f, lambda / 120.f);
SingleChannelElement *sce0 = &cpe->ch[0];
SingleChannelElement *sce1 = &cpe->ch[1];
if (!cpe->common_window)
return;
for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
+ int min_sf_idx_mid = SCALE_MAX_POS;
+ int min_sf_idx_side = SCALE_MAX_POS;
+ for (g = 0; g < sce0->ics.num_swb; g++) {
+ if (!sce0->zeroes[w*16+g] && sce0->band_type[w*16+g] < RESERVED_BT)
+ min_sf_idx_mid = FFMIN(min_sf_idx_mid, sce0->sf_idx[w*16+g]);
+ if (!sce1->zeroes[w*16+g] && sce1->band_type[w*16+g] < RESERVED_BT)
+ min_sf_idx_side = FFMIN(min_sf_idx_side, sce1->sf_idx[w*16+g]);
+ }
+
start = 0;
for (g = 0; g < sce0->ics.num_swb; g++) {
+ float bmax = bval2bmax(g * 17.0f / sce0->ics.num_swb) / 0.0045f;
+ cpe->ms_mask[w*16+g] = 0;
if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) {
- float dist1 = 0.0f, dist2 = 0.0f;
+ float Mmax = 0.0f, Smax = 0.0f;
+
+ /* Must compute mid/side SF and book for the whole window group */
for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
- FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
- FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
- float minthr = FFMIN(band0->threshold, band1->threshold);
- float maxthr = FFMAX(band0->threshold, band1->threshold);
for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
M[i] = (sce0->coeffs[start+(w+w2)*128+i]
+ sce1->coeffs[start+(w+w2)*128+i]) * 0.5;
S[i] = M[i]
- sce1->coeffs[start+(w+w2)*128+i];
}
- abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
- abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
- abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]);
- abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]);
- dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128],
- L34,
- sce0->ics.swb_sizes[g],
- sce0->sf_idx[(w+w2)*16+g],
- sce0->band_type[(w+w2)*16+g],
- lambda / band0->threshold, INFINITY, NULL, 0);
- dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128],
- R34,
- sce1->ics.swb_sizes[g],
- sce1->sf_idx[(w+w2)*16+g],
- sce1->band_type[(w+w2)*16+g],
- lambda / band1->threshold, INFINITY, NULL, 0);
- dist2 += quantize_band_cost(s, M,
- M34,
- sce0->ics.swb_sizes[g],
- sce0->sf_idx[(w+w2)*16+g],
- sce0->band_type[(w+w2)*16+g],
- lambda / maxthr, INFINITY, NULL, 0);
- dist2 += quantize_band_cost(s, S,
- S34,
- sce1->ics.swb_sizes[g],
- sce1->sf_idx[(w+w2)*16+g],
- sce1->band_type[(w+w2)*16+g],
- lambda / minthr, INFINITY, NULL, 0);
+ abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]);
+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++ ) {
+ Mmax = FFMAX(Mmax, M34[i]);
+ Smax = FFMAX(Smax, S34[i]);
+ }
+ }
+
+ for (sid_sf_boost = 0; sid_sf_boost < 4; sid_sf_boost++) {
+ float dist1 = 0.0f, dist2 = 0.0f;
+ int B0 = 0, B1 = 0;
+ int minidx;
+ int mididx, sididx;
+ int midcb, sidcb;
+
+ minidx = FFMIN(sce0->sf_idx[w*16+g], sce1->sf_idx[w*16+g]);
+ mididx = av_clip(minidx, min_sf_idx_mid, min_sf_idx_mid + SCALE_MAX_DIFF);
+ sididx = av_clip(minidx - sid_sf_boost * 3, min_sf_idx_side, min_sf_idx_side + SCALE_MAX_DIFF);
+ midcb = find_min_book(Mmax, mididx);
+ sidcb = find_min_book(Smax, sididx);
+
+ if ((mididx > minidx) || (sididx > minidx)) {
+ /* scalefactor range violation, bad stuff, will decrease quality unacceptably */
+ continue;
+ }
+
+ /* No CB can be zero */
+ midcb = FFMAX(1,midcb);
+ sidcb = FFMAX(1,sidcb);
+
+ for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
+ FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g];
+ FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g];
+ float minthr = FFMIN(band0->threshold, band1->threshold);
+ int b1,b2,b3,b4;
+ for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
+ M[i] = (sce0->coeffs[start+(w+w2)*128+i]
+ + sce1->coeffs[start+(w+w2)*128+i]) * 0.5;
+ S[i] = M[i]
+ - sce1->coeffs[start+(w+w2)*128+i];
+ }
+
+ abs_pow34_v(L34, sce0->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(R34, sce1->coeffs+start+(w+w2)*128, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]);
+ abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]);
+ dist1 += quantize_band_cost(s, &sce0->coeffs[start + (w+w2)*128],
+ L34,
+ sce0->ics.swb_sizes[g],
+ sce0->sf_idx[(w+w2)*16+g],
+ sce0->band_type[(w+w2)*16+g],
+ lambda / band0->threshold, INFINITY, &b1, NULL, 0);
+ dist1 += quantize_band_cost(s, &sce1->coeffs[start + (w+w2)*128],
+ R34,
+ sce1->ics.swb_sizes[g],
+ sce1->sf_idx[(w+w2)*16+g],
+ sce1->band_type[(w+w2)*16+g],
+ lambda / band1->threshold, INFINITY, &b2, NULL, 0);
+ dist2 += quantize_band_cost(s, M,
+ M34,
+ sce0->ics.swb_sizes[g],
+ sce0->sf_idx[(w+w2)*16+g],
+ sce0->band_type[(w+w2)*16+g],
+ lambda / minthr, INFINITY, &b3, NULL, 0);
+ dist2 += quantize_band_cost(s, S,
+ S34,
+ sce1->ics.swb_sizes[g],
+ sce1->sf_idx[(w+w2)*16+g],
+ sce1->band_type[(w+w2)*16+g],
+ mslambda / (minthr * bmax), INFINITY, &b4, NULL, 0);
+ B0 += b1+b2;
+ B1 += b3+b4;
+ dist1 -= B0;
+ dist2 -= B1;
+ }
+ cpe->ms_mask[w*16+g] = dist2 <= dist1 && B1 < B0;
+ if (cpe->ms_mask[w*16+g]) {
+ /* Setting the M/S mask is useful with I/S, but only the flag */
+ if (!cpe->is_mask[w*16+g]) {
+ sce0->sf_idx[w*16+g] = mididx;
+ sce1->sf_idx[w*16+g] = sididx;
+ sce0->band_type[w*16+g] = midcb;
+ sce1->band_type[w*16+g] = sidcb;
+ }
+ break;
+ } else if (B1 > B0) {
+ /* More boost won't fix this */
+ break;
+ }
}
- cpe->ms_mask[w*16+g] = dist2 < dist1;
}
start += sce0->ics.swb_sizes[g];
}
encode_window_bands_info,
quantize_and_encode_band,
ff_aac_encode_tns_info,
+ ff_aac_encode_ltp_info,
ff_aac_encode_main_pred,
- ff_aac_adjust_common_prediction,
+ ff_aac_adjust_common_pred,
+ ff_aac_adjust_common_ltp,
ff_aac_apply_main_pred,
ff_aac_apply_tns,
+ ff_aac_update_ltp,
+ ff_aac_ltp_insert_new_frame,
set_special_band_scalefactors,
search_for_pns,
+ mark_pns,
ff_aac_search_for_tns,
+ ff_aac_search_for_ltp,
search_for_ms,
ff_aac_search_for_is,
ff_aac_search_for_pred,
encode_window_bands_info,
quantize_and_encode_band,
ff_aac_encode_tns_info,
+ ff_aac_encode_ltp_info,
ff_aac_encode_main_pred,
- ff_aac_adjust_common_prediction,
+ ff_aac_adjust_common_pred,
+ ff_aac_adjust_common_ltp,
ff_aac_apply_main_pred,
ff_aac_apply_tns,
+ ff_aac_update_ltp,
+ ff_aac_ltp_insert_new_frame,
set_special_band_scalefactors,
search_for_pns,
+ mark_pns,
ff_aac_search_for_tns,
+ ff_aac_search_for_ltp,
search_for_ms,
ff_aac_search_for_is,
ff_aac_search_for_pred,
codebook_trellis_rate,
quantize_and_encode_band,
ff_aac_encode_tns_info,
+ ff_aac_encode_ltp_info,
ff_aac_encode_main_pred,
- ff_aac_adjust_common_prediction,
+ ff_aac_adjust_common_pred,
+ ff_aac_adjust_common_ltp,
ff_aac_apply_main_pred,
ff_aac_apply_tns,
+ ff_aac_update_ltp,
+ ff_aac_ltp_insert_new_frame,
set_special_band_scalefactors,
search_for_pns,
+ mark_pns,
ff_aac_search_for_tns,
+ ff_aac_search_for_ltp,
search_for_ms,
ff_aac_search_for_is,
ff_aac_search_for_pred,
encode_window_bands_info,
quantize_and_encode_band,
ff_aac_encode_tns_info,
+ ff_aac_encode_ltp_info,
ff_aac_encode_main_pred,
- ff_aac_adjust_common_prediction,
+ ff_aac_adjust_common_pred,
+ ff_aac_adjust_common_ltp,
ff_aac_apply_main_pred,
ff_aac_apply_tns,
+ ff_aac_update_ltp,
+ ff_aac_ltp_insert_new_frame,
set_special_band_scalefactors,
search_for_pns,
+ mark_pns,
ff_aac_search_for_tns,
+ ff_aac_search_for_ltp,
search_for_ms,
ff_aac_search_for_is,
ff_aac_search_for_pred,