Skip to content

higgs_audio_tts: give the codec decoder right-hand context at the end of the stream - #454

Merged
0xShug0 merged 1 commit into
0xShug0:mainfrom
niksedk:higgs-codec-tail-context
Sep 4, 2026
Merged

higgs_audio_tts: give the codec decoder right-hand context at the end of the stream#454
0xShug0 merged 1 commit into
0xShug0:mainfrom
niksedk:higgs-codec-tail-context

Conversation

@niksedk

@niksedk niksedk commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Problem

Higgs Audio v3 TTS output ends with a rising hiss over the final ~300 ms that is cut off abruptly. It is most audible on short utterances (e.g. Hello, how are you doing? with a cloned voice) but a faint version is there on long ones too. It is independent of sampling settings, seed, reference_text, punctuation, and it reproduces on v0.7.1 and current main.

The codec decoder is a non-causal conv stack. At the end of the stream the last frames see zero padding on their right instead of real context and decode to garbage that ramps up towards the edge. This is the same mechanism as the periodic click at chunk seams (#429 / #436), but at the end of the stream, where the chunked path's context frames do not help.

Fix

HiggsCodecRuntime::decode_codes() now repeats the last frame kCodecTailContextFrames (8) times before decoding and trims the extra samples again, so the public contract (sample count) is unchanged. The previous body becomes decode_codes_impl(). 16 and 32 context frames give sample-identical output to 8, so 8 is enough. Cost is 8 extra frames per decode.

Measurements

Metal (Apple M4), Q8_0 GGUF, higgs_audio_tts clone with a fixed seed, before → after. RMS of the last three 40 ms frames (dBFS) and peak sample of the last 100 ms:

request before after
short, seed 1 -39 -44 -34, peak 3990 -41 -48 -46, peak 864
short, seed 2 -39 -46 -32, peak 3951 -40 -47 -41, peak 1121
long, 11.4 s -48 -53 -46 -48 -53 -53, peak 334

The delayed/raw code tail was dumped to rule out stray BOC/EOC ids in the kept frames (there are none), and forcing EOC on finished codebooks during the delay flush like the reference implementation does gave bit-identical output, so the issue is purely in the codec decode edge.

Tested with scripts/build_metal.sh --model-set custom --models higgs_audio_tts --deployment-build, server mode, multiple requests in one session.

🤖 Generated with Claude Code

… of the stream

The Higgs codec decoder is a non-causal conv stack, so the last frames of a
stream are decoded against zero padding on their right instead of real
context. That decodes as a rising hiss over the final ~300 ms, clearly
audible on short utterances ("Hello, how are you doing?" with a cloned
voice ends in a swell that is cut off). This is the same mechanism as the
periodic click at chunk seams (0xShug0#429) but at the end of the stream, where
the chunked path's context frames do not apply.

Repeat the last frame kCodecTailContextFrames (8) times before decoding
and trim the extra samples again. 16 and 32 frames give sample-identical
output, so 8 is enough. decode_codes() keeps its contract (same sample
count as before); the previous body becomes decode_codes_impl().

Measured on Metal (M4), Q8_0, voice clone, same seed before/after,
RMS of the last three 40 ms frames and peak of the last 100 ms:

  short, seed 1:  -39 -44 -34 dBFS, peak 3990  ->  -41 -48 -46, peak  864
  short, seed 2:  -39 -46 -32 dBFS, peak 3951  ->  -40 -47 -41, peak 1121
  long (11.4 s):  -48 -53 -46 dBFS              ->  -48 -53 -53, peak  334

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@0xShug0

0xShug0 commented Sep 4, 2026

Copy link
Copy Markdown
Owner

@niksedk Thanks for the PR! I will test it after wrapping up release 0.7.2

@niksedk

niksedk commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

@niksedk Thanks for the PR! I will test it after wrapping up release 0.7.2

thx :)

@0xShug0
0xShug0 merged commit 0befc6f into 0xShug0:main Sep 4, 2026
6 checks passed
@0xShug0

0xShug0 commented Sep 4, 2026

Copy link
Copy Markdown
Owner

@niksedk PR merged. Thanks!

oiomaker pushed a commit to oiomaker/subtitleedit that referenced this pull request Sep 5, 2026
Rebuilt in support-files from upstream main a8fccb47, which includes
0xShug0/audio.cpp#454: the Higgs Audio v3 codec decoder now gets right-hand
context at the end of the stream, removing the rising hiss that ended every
clip. Same three families as before (index_tts2, higgs_audio_tts, fish_audio).

New archive hashes go in at index 0, so existing installs show the amber
'update available' status and the Update button in the audio.cpp settings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants