Skip to content

Tune the delivery knobs against real recordings - #4

Open
MattModeCode wants to merge 1 commit into
feat/liquid-glass-studiofrom
feat/delivery-tuning
Open

Tune the delivery knobs against real recordings#4
MattModeCode wants to merge 1 commit into
feat/liquid-glass-studiofrom
feat/delivery-tuning

Conversation

@MattModeCode

Copy link
Copy Markdown
Owner

Adds double-chin tune: a parameter search over the four delivery controls (expression, reference adherence, variation, speaking rate), scored against the user's own recordings with the existing indistinguishability gate, plus the plumbing that makes the result the profile Studio opens with.

Stacked on feat/liquid-glass-studio (#3) because it edits that branch's studio frontend.

What it does

  • src/double_chin/delivery.pyDeliveryProfile with validation, the neutral and tuned profiles, and atomic persistence to ~/.double-chin/delivery.json. A missing, corrupt or out-of-range file falls back to the tuned profile with a logged reason; a bad settings file must never stop the app opening.
  • src/double_chin/tuning/ — coordinate descent over a 0.05-step grid. Each candidate is synthesized several times and scored as a set through indistinguishability_gate. Before searching, the baseline is re-measured with different seeds to size run-to-run noise; a winner that does not clear that spread is reported as a tie. Every measurement lands in a resumable JSONL ledger, and a synthesis budget caps the run.
  • GET /api/delivery — serves the opening profile and the neutral baseline. The frontend hydrates from it instead of hardcoding knob values.
  • UI — "Match my voice" restores the tuned profile; "Reset to neutral" goes to the engine's own baseline (it previously went to the hardcoded defaults).

What the run found

Ranking had to be made explicit: the gate's discrimination component is 0.000 for every candidate here (eight real clips against three clone clips separate outright), which collapses the composite to ~0.026 for everything. The search ranks on the three components that respond, with the gate's own weights, and records the full gate result anyway.

  • Noise floor: mean 0.781, sd 0.012 over three repeats of the baseline.
  • Tuning-script winner 0.50 / 0.80 / 0.45 / 1.00x at 0.8018 (+0.021, clears the floor) — but on held-out text and held-out clips it scored 0.8104 against the baseline's 0.8213. It was fitted to the passage.
  • Between-condition variance (~0.04) exceeds any parameter effect within a condition (~0.02), so this measurement cannot resolve a winner among those three knobs.
  • Speaking rate is the exception: every value other than 1.00x costs 0.13–0.18 objective and drops speaker similarity from ~0.66 to ~0.40, because the time-stretch is applied to finished audio.

So TUNED_PROFILE is the neutral profile, and docs/tuning.md says why rather than dressing up a fitted win.

Test plan

  • 149 tests pass, 3 slow ones skipped (DOUBLECHIN_E2E=1 gates them)
  • Sweep logic covered offline with a stub engine and stub gate: caching, ledger resume, noise floor, budget cap, objective plumbing
  • New studio tests for /api/delivery, a saved profile, and a corrupt settings file
  • New static check that every element id app.js touches exists in index.html
  • Verified in a real browser: opens on the tuned profile, dragging a slider updates the summary, "Match my voice" restores it, "Reset to neutral" goes to the baseline, no console errors
  • DOUBLECHIN_E2E=1 pytest -m slow (real-model tune path) not run in this session

https://claude.ai/code/session_01FdWprv4TKfVzapYFJnRffz

Adds `double-chin tune`, which searches exaggeration, cfg_weight,
temperature and rate for the values that make synthesized takes least
distinguishable from the user's own recordings, and wires the result into
the app as the profile Studio opens with.

- src/double_chin/delivery.py: validated DeliveryProfile, the neutral and
  tuned profiles, and atomic persistence to ~/.double-chin/delivery.json
  with a logged fallback so a corrupt settings file cannot stop the app
  from opening.
- src/double_chin/tuning/: coordinate-descent search scoring each candidate
  as a set of takes through the existing indistinguishability gate, with a
  measured noise floor, a held-out check, a resumable JSONL ledger and a
  synthesis budget. What the search ranks on is a parameter, because the
  gate's discrimination component is saturated in this configuration.
- GET /api/delivery serves the opening profile and the neutral baseline, so
  the frontend stops hardcoding knob values; "Match my voice" restores the
  tuned profile and "Reset to neutral" goes to the engine baseline.

Result on the owner's voice (docs/tuning.md): a tie for expression,
adherence and variation — the tuning-script winner did not survive the
held-out check — so the tuned profile is the neutral one. Speaking rate is
the one clear finding and it is negative: any value other than 1.00x drops
speaker similarity from ~0.66 to ~0.40.

Claude-Session: https://claude.ai/code/session_01FdWprv4TKfVzapYFJnRffz
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.

1 participant