1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00
Files
ffmpeg/libavcodec/psymodel.h
Lynne a86dc8bd2a avcodec/aaccoder_nmr, aacenc, aacpsy: nd-target VBR
-q:a with the NMR coder becomes a quality-domain VBR: bisect the pooled
lambda until the mean log2 dist/real-mask over coded bands (floored at
-4/band, so a flat sf-chain over-coding quiet bands cannot let a coarser
lambda read as a finer statistic) meets a target. The target is anchored
so -q:a 1 lands near 128 kbps stereo; higher q is finer, as with the
other coders, at -1.2 per q doubling (about a third more rate), clamped
at a reachable floor that q above about 6 reaches: the stat clips at
-4/band, targets below the clamp are asymptotically unreachable, the
bisect rails at the finest lambda and the frame exceeds the decoder
buffer. The anchor is calibrated with the broadband quality-mode mask
floor from earlier in the series; that floor measured -8.8% / -5.0% /
-0.9% Zimtohrli (ViSQOL +0.013 / +0.018 / +0.004) at matched rate on
three corpora, worst sample -34%, per-sample quality spread 2.41 ->
1.74.

The psy model runs its PE reduction at a fixed reference quality for
this coder (psy.unbounded_pe): thresholds keep their perceptual shaping
but stay independent of -q:a, which otherwise moves thr_real under the
coder's own statistic and inverts the quality ladder.

Frame classes the statistic mishandles:
- Short frames: the grouped-band statistic is inflated, so they bisect
  against an offset target and never write solver state. A fixed +3
  offset was a content-class policy in disguise - broadband beats
  (velvet) need it, LF/mid tonal decays audibly do not and paid 1.7-2.8x
  the CBR error through every post-hit decay. The offset is measured
  per frame instead: evaluate the grouped stat at the long-anchor lambda
  (continuity says true quality is on target there, the excess is this
  content's inflation), weighted by the frame's HF energy share - the
  stat reads inflated on both classes, audibility does not. Post-hit
  decays 1.67x -> 1.13x CBR error (worst 2.82x -> 1.44x).
- Continuous shorts: the offset-bisect assumes isolated transients
  between long anchors; on dense onsets the per-frame stat is bisect
  noise and lambda careened across decades (0.16 -> 82 -> 2 -> 43), an
  audible whoosh. Shorts hold to the CBR run slew, clamped after the
  last solve (PASS 2 re-bisects on a fresh +-32x bracket and otherwise
  rails at exactly lam*32); dives toward finer stay free.
- Operating points: only bisected long frames whose stat actually
  landed within 0.5 of the target write slew/warm-start state. Cheap
  frames (room tone, gaps) rail fine at no cost; the first frames of a
  quiet channel rail coarse from no warm state - writing either builds
  a slew prison the channel climbs out of one rung per frame (a muffled
  stream head on fade-ins).
- Decoupled solo solves keep per-channel slew state: a shared lam_slew
  clamped each channel against the OTHER channel's operating lambda and
  landed the damage asymmetrically.

The window history the slew rules read (previous-frame short, frames
since the last short run) used to advance only inside the CBR reservoir
bookkeeping; it now advances once per frame in every rate-control mode,
so the run slew and the pooled short-TNS hysteresis see real history
here too. Measured neutral (IgorC-1 VBR q=1: -0.3% Zimtohrli).

Legality is absolute: a frame may never exceed the decoder buffer.
- The cap is the format limit regardless of -q:a. It used to scale with
  the outer lambda, i.e. with -q:a itself, so the finest settings had
  the smallest cap (531 bits/channel at q=0.1 under the old direction)
  and lost bands where they wanted the most bits.
- Dense short frames at high rates can exceed 6144 bits/channel even at
  the coarsest candidate grid (the 1e4 rail still emitted 11-13k
  spectral bits); the legality path sheds the highest bands across all
  window groups (act[] runs group by group) until the frame fits,
  keeping the scalefactor-chain anchor.
- The bits a solve reports for the next frame's side-information
  estimate count only the surviving bands, and PNS filters the active
  list instead of rebuilding it from all bands. Counting shed bands
  drove the estimate negative (one frame emitting 1256 bits counted
  13825), and a negative estimate enlarged the next frame's cap: 13056
  payload bits against a 12288 limit. A negative estimate can no longer
  enlarge the cap.
- The outer loop no longer skips the size check under a constant
  quality: an oversized frame is retried at a lower lambda, which
  shrinks the coders' caps. This applies to every coder, and only to
  frames that would otherwise be illegal.
A fine-quality encode test (fate-aac-nmr-vbr-encode) pins the per-packet
sizes; its largest frame is 11560 payload bits.

Encoder side: the bandwidth ladder takes the expected per-channel rate
from the quality ladder (q=1 ~ 64.5 kbps/ch, x1.27 per doubling), and
Qavg reports the coder's quality-mode slew state: the lambda of the last
long operating-point solve. The encoder documentation describes the
NMR meaning of -q:a.

CBR output is unchanged.
2026-10-04 17:51:10 +09:00

220 lines
8.5 KiB
C

/*
* audio encoder psychoacoustic model
* Copyright (C) 2008 Konstantin Shishkov
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_PSYMODEL_H
#define AVCODEC_PSYMODEL_H
#include "avcodec.h"
/** maximum possible number of bands */
#define PSY_MAX_BANDS 128
/** maximum number of channels */
#define PSY_MAX_CHANS 20
/* cutoff for VBR is purposely increased, since LP filtering actually
* hinders VBR performance rather than the opposite
*/
#define AAC_CUTOFF_FROM_BITRATE(bit_rate,channels,sample_rate) (bit_rate ? FFMIN3(FFMIN3( \
FFMAX(bit_rate/channels/5, bit_rate/channels*15/32 - 5500), \
3000 + bit_rate/channels/4, \
12000 + bit_rate/channels/16), \
22000, \
sample_rate / 2): (sample_rate / 2))
#define AAC_CUTOFF(s) ( \
(s->flags & AV_CODEC_FLAG_QSCALE) \
? s->sample_rate / 2 \
: AAC_CUTOFF_FROM_BITRATE(s->bit_rate, s->ch_layout.nb_channels, s->sample_rate) \
)
/**
* single band psychoacoustic information
*/
typedef struct FFPsyBand {
int bits;
float energy;
float threshold;
float spread; /* Energy spread over the band */
} FFPsyBand;
/**
* single channel psychoacoustic information
*/
typedef struct FFPsyChannel {
FFPsyBand psy_bands[PSY_MAX_BANDS]; ///< channel bands information
float entropy; ///< total PE for this channel
} FFPsyChannel;
/**
* psychoacoustic information for an arbitrary group of channels
*/
typedef struct FFPsyChannelGroup {
FFPsyChannel *ch[PSY_MAX_CHANS]; ///< pointers to the individual channels in the group
uint8_t num_ch; ///< number of channels in this group
uint8_t coupling[PSY_MAX_BANDS]; ///< allow coupling for this band in the group
} FFPsyChannelGroup;
/**
* windowing related information
*/
typedef struct FFPsyWindowInfo {
int window_type[3]; ///< window type (short/long/transitional, etc.) - current, previous and next
int window_shape; ///< window shape (sine/KBD/whatever)
int num_windows; ///< number of windows in a frame
int grouping[8]; ///< window grouping (for e.g. AAC)
float clipping[8]; ///< maximum absolute normalized intensity in the given window for clip avoidance
int *window_sizes; ///< sequence of window sizes inside one frame (for eg. WMA)
} FFPsyWindowInfo;
/**
* context used by psychoacoustic model
*/
typedef struct FFPsyContext {
AVCodecContext *avctx; ///< encoder context
const struct FFPsyModel *model; ///< encoder-specific model functions
FFPsyChannel *ch; ///< single channel information
FFPsyChannelGroup *group; ///< channel group information
int num_groups; ///< number of channel groups
int cutoff; ///< lowpass frequency cutoff for analysis
int unbounded_pe; ///< PE reduction at a fixed reference quality, not the rate (quality-target coder owns the rate)
uint8_t **bands; ///< scalefactor band sizes for possible frame sizes
int *num_bands; ///< number of scalefactor bands for possible frame sizes
int num_lens; ///< number of scalefactor band sets
struct {
int size; ///< size of the bitresevoir in bits
int bits; ///< number of bits used in the bitresevoir
int alloc; ///< number of bits allocated by the psy, or -1 if no allocation was done
} bitres;
void* model_priv_data; ///< psychoacoustic model implementation private data
float pair_joint[16]; ///< encoder-fed per-CPE joint-tool candidacy fraction EMA (bands M/S would adopt or I/S renders; ~0 = joint tools dead); 0 = unseeded
uint8_t pair_decoupled[16]; ///< Schmitt state over pair_joint: 1 = joint tools dead on this pair, joint windowing/M-S coupling suspended
} FFPsyContext;
/**
* codec-specific psychoacoustic model implementation
*/
typedef struct FFPsyModel {
const char *name;
int (*init) (FFPsyContext *apc);
/**
* Suggest window sequence for channel.
*
* @param ctx model context
* @param audio samples for the current frame
* @param la lookahead samples (NULL when unavailable)
* @param channel number of channel element to analyze
* @param prev_type previous window type
*
* @return suggested window information in a structure
*/
FFPsyWindowInfo (*window)(FFPsyContext *ctx, const float *audio, const float *la, int channel, int prev_type);
/**
* Suggest window sequences for both channels of a CPE with block switching
* synchronized across the pair (either channel's attack switches both), so
* common_window and the joint stereo tools stay available. Optional; when
* NULL the encoder decides each channel independently via window().
*/
void (*window_pair)(FFPsyContext *ctx, const float *audio0, const float *la0,
const float *audio1, const float *la1,
int channel0, int channel1,
int prev_type0, int prev_type1, FFPsyWindowInfo wi[2]);
/**
* Perform psychoacoustic analysis and set band info (threshold, energy) for a group of channels.
*
* @param ctx model context
* @param channel channel number of the first channel in the group to perform analysis on
* @param coeffs array of pointers to the transformed coefficients
* @param wi window information for the channels in the group
*/
void (*analyze)(FFPsyContext *ctx, int channel, const float **coeffs, const FFPsyWindowInfo *wi);
void (*end) (FFPsyContext *apc);
} FFPsyModel;
/**
* Initialize psychoacoustic model.
*
* @param ctx model context
* @param avctx codec context
* @param num_lens number of possible frame lengths
* @param bands scalefactor band lengths for all frame lengths
* @param num_bands number of scalefactor bands for all frame lengths
* @param num_groups number of channel groups
* @param group_map array with # of channels in group - 1, for each group
* @param cutoff analysis bandwidth in Hz, 0 to derive it from avctx
*
* @return zero if successful, a negative value if not
*/
int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens,
const uint8_t **bands, const int *num_bands,
int num_groups, const uint8_t *group_map, int cutoff);
/**
* Determine what group a channel belongs to.
*
* @param ctx psymodel context
* @param channel channel to locate the group for
*
* @return pointer to the FFPsyChannelGroup this channel belongs to
*/
FFPsyChannelGroup *ff_psy_find_group(FFPsyContext *ctx, int channel);
/**
* Cleanup model context at the end.
*
* @param ctx model context
*/
void ff_psy_end(FFPsyContext *ctx);
/**************************************************************************
* Audio preprocessing stuff. *
* This should be moved into some audio filter eventually. *
**************************************************************************/
struct FFPsyPreprocessContext;
/**
* psychoacoustic model audio preprocessing initialization
*/
struct FFPsyPreprocessContext *ff_psy_preprocess_init(AVCodecContext *avctx);
/**
* Preprocess several channel in audio frame in order to compress it better.
*
* @param ctx preprocessing context
* @param audio samples to be filtered (in place)
* @param channels number of channel to preprocess
*/
void ff_psy_preprocess(struct FFPsyPreprocessContext *ctx, float **audio, int channels);
/**
* Cleanup audio preprocessing module.
*/
void ff_psy_preprocess_end(struct FFPsyPreprocessContext *ctx);
#endif /* AVCODEC_PSYMODEL_H */