Skip to content

libelizainference ABI 21: caller-set speed range per Paradee voice slot - #92

Merged
lalalune merged 1 commit into
mainfrom
paradee/voice-speed-range
Nov 1, 2026
Merged

lalalune merged 1 commit into
mainfrom
paradee/voice-speed-range

Conversation

@lalalune

@lalalune lalalune commented Nov 1, 2026

Copy link
Copy Markdown
Member

Why

libelizainference clamps every Paradee-family synthesis to the GGUF's paradee.validated_speed (Delibes-8M-esES: [0.85, 1.15], written by convert_paradee_onnx_to_gguf.py). Grace's owner widened its Spanish speech rate to 0.5x–1.5x (owner decision OCT31-14); Grace already asks for that rate, but the library holds it to 0.85–1.15. Changing the converter's range would change the Delibes GGUF bytes and hash that eliza inputs.json, pins.json and Grace's voice.lock.json pin, and would misstate what the release validated. This adds a runtime override instead.

What

  • New eliza_inference_paradee_set_voice_speed_range(ctx, voice_id, min_speed, max_speed, &err):
    • sets the range the slot's synthesis (alloc and stream) clamps speed to;
    • requires finite 0.25 <= min <= 1 <= max <= 4 (the architecture's limits, the same bounds the GGUF loader enforces on validated_speed); 0, 0 restores the model's validated range; anything else, or a slot never loaded, is ELIZA_ERR_INVALID_ARG and leaves the range unchanged;
    • belongs to the slot: kept across mmap_evict("tts") → reload and across a new load_voice into the slot, dropped by unload_voice; does not load the model. Slot "" is the v17 voice.
  • paradee_voice_info adds speed_range (in force) next to the unchanged validated_speed (the model's).
  • ABI 20 → 21 (one additive symbol, no signature changes), per the header's convention; changelog, probe table and tools/paradee/README.md updated.
  • The GGUF, its keys, pins.json and the converter are untouched: no model hash changes.

Tests

  • tests/ffi-paradee-asr.cpp (contract doubles, no weights): argument refusals (below 0.25, above 4, not spanning 1, reversed, NaN, ∞, 0, x, unknown slot, null ctx/id), info JSON for both slots, the clamp it sets (0.3/2.0 → 0.5/1.5, values inside pass through), lifetime across evict → reload, setting on an evicted slot without loading it, 0, 0 reset back to 0.85/1.15, a new load keeping the range, unload dropping it. ABI string "21".
  • tests/ffi-abi.c: ABI "21"; the new symbol refuses before any load (NOT_IMPLEMENTED without Paradee).

Run locally (macOS arm64, the eliza-paradee-stream.yml configure): ctest -R 'eliza-inference-test-(paradee-(asr|stream-output)|abi)$' → 3/3 passed (paradee-asr: 668 checks, 0 failures). Not run: real-model synthesis at the widened rate, Android cross-build, any listening test. Speech outside 0.85–1.15 was not validated by the Delibes release; a caller that sets a wider range owns that choice.

Follow-up

elizaOS/eliza: bind it in the Android voice bridge (ParadeeVoice.speedRange), accept ABI 21 in ffi-bindings.ts, and move the submodule here once this merges.

🤖 Generated with Claude Code

Synthesis on a Paradee voice slot clamps speed to the GGUF's
paradee.validated_speed ([0.85, 1.15] for Delibes-8M-esES). A product that
chooses to speak outside that envelope had no way to do so short of
reconverting the model with a different range, which changes the GGUF hash
every consumer pins.

Add eliza_inference_paradee_set_voice_speed_range(ctx, voice_id, min, max,
&err): a runtime override of the slot's clamp, within the architecture's
[0.25, 4] and spanning 1.0; 0, 0 restores the validated range. It belongs to
the slot (kept across mmap_evict -> reload and a new load_voice, dropped by
unload_voice) and does not load the model. paradee_voice_info adds
speed_range next to the unchanged validated_speed. The GGUF, its keys and the
converter are untouched.

One additive symbol; ABI 20 -> 21 per the header's convention.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation examples labels Nov 1, 2026
@lalalune
lalalune merged commit b3eb2bf into main Nov 1, 2026
14 checks passed
lalalune added a commit to elizaOS/eliza that referenced this pull request Nov 1, 2026
…inference ABI 21) (#38470)

* feat(voice): caller-set speed range for Paradee voice slots (ABI 21)

libelizainference clamps a Paradee-family synthesis to the GGUF's
paradee.validated_speed (Delibes-8M-esES: 0.85-1.15). elizaOS/llama.cpp#92
adds eliza_inference_paradee_set_voice_speed_range, a runtime override per
voice slot that leaves the GGUF and its hash unchanged. Bind it:

- move native/llama.cpp to the #92 head (ABI 21);
- elizavoice-jni registers nativeParadeeSetVoiceSpeedRange (needs ABI 21) on
  both VoiceNative classes;
- ParadeeVoice.speedRange(min, max) / validatedSpeedRange(), checked in Java
  against 0.25 <= min <= 1 <= max <= 4 before reaching native;
- ffi-bindings.ts: ABI 21, still accepting v20 (the binding does not call the
  new symbol); ffi-stub/ffi.h re-copied from the pinned header;
- stream-contract covers the new call and its refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(voice): pin merged llama.cpp speed-range ABI

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation examples

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant