This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 06e949e45de3dd8f8680e7a290a0e947808f8bd2 Author: Lynne <[email protected]> AuthorDate: Tue Jun 30 16:23:10 2026 +0900 Commit: Lynne <[email protected]> CommitDate: Wed Jul 1 21:05:27 2026 +0900 aacpsy: pre-echo-aware short-block detection for isolated onsets The LAME attack detector high-pass filters at fs/4 before measuring attack intensity, so the gentler attacks of tonal material (piano, plucked strings) fall below the threshold and stay in long blocks, smearing pre-echo across the quiet gap before the note. Relax the attack threshold for an isolated onset, preceded by PSY_LAME_PE_GAP long frames with a near-silent pre-onset sub-block (< PSY_LAME_PE_QUIET of the frame peak), so it switches to short blocks. --- libavcodec/aacpsy.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c index 78c217f8f4..e38c43a323 100644 --- a/libavcodec/aacpsy.c +++ b/libavcodec/aacpsy.c @@ -99,6 +99,14 @@ enum { #define AAC_NUM_BLOCKS_SHORT 8 ///< number of blocks in a short sequence #define PSY_LAME_NUM_SUBBLOCKS 2 ///< Number of sub-blocks in each short block +/* Pre-echo-aware attack detection: the LAME ratio test misses gentler attacks after a quiet + * gap, which then stay long and pre-echo. For an isolated onset (long for PSY_LAME_PE_GAP + * frames) whose pre-onset is below PSY_LAME_PE_QUIET of the frame peak, scale the threshold by + * PSY_LAME_PE_RED so it switches short; dense-transient content never qualifies. */ +#define PSY_LAME_PE_GAP 12 ///< min consecutive long frames before the relaxation applies +#define PSY_LAME_PE_QUIET 0.4f ///< pre-onset must be below this fraction of the frame peak +#define PSY_LAME_PE_RED 0.45f ///< attack-threshold multiplier for a qualifying isolated onset + /** * @} */ @@ -134,6 +142,7 @@ typedef struct AacPsyChannel{ float prev_energy_subshort[AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS]; int prev_attack; ///< attack value for the last short block in the previous sequence int next_attack0_zero; ///< whether attack[0] of the next frame is zero + int frames_since_short; ///< consecutive long frames (pre-echo-aware isolated-onset gate) /* rate-loop re-analysis rewind state, see psy_3gpp_analyze() */ int64_t rc_frame_num; ///< frame this channel last saved rewind state for @@ -966,11 +975,21 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio, attack_intensity[i + PSY_LAME_NUM_SUBBLOCKS] = p; } - /* compare energy between sub-short blocks */ - for (i = 0; i < (AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS; i++) - if (!attacks[i / PSY_LAME_NUM_SUBBLOCKS]) - if (attack_intensity[i] > pch->attack_threshold) - attacks[i / PSY_LAME_NUM_SUBBLOCKS] = (i % PSY_LAME_NUM_SUBBLOCKS) + 1; + { /* pre-echo-aware threshold relaxation, see PSY_LAME_PE_* */ + float frame_peak = 1.0f; + for (i = PSY_LAME_NUM_SUBBLOCKS; i < (AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS; i++) + frame_peak = FFMAX(frame_peak, energy_subshort[i]); + for (i = 0; i < (AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS; i++) + if (!attacks[i / PSY_LAME_NUM_SUBBLOCKS]) { + float thr = pch->attack_threshold; + if (i >= PSY_LAME_NUM_SUBBLOCKS && + pch->frames_since_short >= PSY_LAME_PE_GAP && + energy_subshort[i - PSY_LAME_NUM_SUBBLOCKS] < PSY_LAME_PE_QUIET * frame_peak) + thr *= PSY_LAME_PE_RED; + if (attack_intensity[i] > thr) + attacks[i / PSY_LAME_NUM_SUBBLOCKS] = (i % PSY_LAME_NUM_SUBBLOCKS) + 1; + } + } /* should have energy change between short blocks, in order to avoid periodic signals */ /* Good samples to show the effect are Trumpet test songs */ @@ -1008,6 +1027,8 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio, if (attacks[i] && attacks[i-1]) attacks[i] = 0; } + + pch->frames_since_short = uselongblock ? pch->frames_since_short + 1 : 0; } else { /* We have no lookahead info, so just use same type as the previous sequence. */ uselongblock = !(prev_type == EIGHT_SHORT_SEQUENCE); _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
