Skip to content

tap.tune~ — real-time pitch correction (full vertical slice)#56

Merged
tap merged 13 commits into
mainfrom
claude/auto-tune-discussion-w8ky0p
Jul 22, 2026
Merged

tap.tune~ — real-time pitch correction (full vertical slice)#56
tap merged 13 commits into
mainfrom
claude/auto-tune-discussion-w8ky0p

Conversation

@tap

@tap tap commented Jul 22, 2026

Copy link
Copy Markdown
Owner

The Max wrapper and package slice for the new pitch corrector — a thin Min shim over taptools/tune.h (tap/TapTools#20, which composes the DspTap primitives from tap/DspTap#3).

The object:

  • @key / @scale (chromatic, major, minor, harmonic, melodic, pentatonic, minorpentatonic), notes message (twelve panel-style toggles or a pitch-class list), @mode scale|midi with note <pitch> <velocity> / flush.
  • @speed (retune time constant; 0 = the hard snap), @amount, @minfreq/@maxfreq, bypass/mute.
  • @backend grain|psola|pvoc — three resynthesis engines behind the shared detector/mapper/glide; @formant enables LPC formant preservation on the pvoc path (matters for large MIDI-mode corrections).
  • @autokey + getkey/applykey — the advisory Krumhansl–Kessler key learner; applykey adopts the estimate through the key/scale attributes so saved state stays the source of truth.
  • Right outlet: pitch <midi> <hz> every @interval ms while voiced (atomic audio→scheduler handoff, coalesced, self-rearming timer), plus the key ... replies.

Package slice: reference page (docs/tap.tune~.maxref.xml), help patcher, wrapper tests (attribute defaults, kernel forwarding for every attribute, both notes forms, no-estimate getkey/applykey paths, bypass/mute), and the runtime maxtest (runtime-tests/patchers/tap.tune~.maxtest.maxpat, generated via make_maxtest.py: unpitched DC passes the grain engine at exactly unity). REVIVAL.md §12 documents the whole cross-repo slice including the IP framing (expired-patent pipeline; trademark-safe naming; polyphonic editing deliberately out of scope).

DSP correctness is gated in the kernel repos' suites (60 DspTap + 145 TapTools cases green); this repo's CI verifies the wrapper build on macOS/Windows and the universal binary. Still pending after merge: the on-Mac runtime validation pass (help patcher + maxtest under a licensed Max) — and, before any public release, the freedom-to-operate review flagged in §12.

Merge order: last, after tap/DspTap#3 and tap/TapTools#20 (submodules/taptools pins the latter's head).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs


Generated by Claude Code

tap and others added 9 commits July 22, 2026 02:23
The classic retune effect as a full vertical slice: Min wrapper over the
new taptools/tune.h kernel (YIN detection via the shared DspTap
primitive, scale/key mapper with per-note enables, MIDI-target mode,
retune-speed glide, period-locked two-tap transposer), reference page,
help patcher, and wrapper tests (attribute defaults and kernel
forwarding, both notes-message forms, finite output, bypass/mute).

Controls: @key/@scale (chromatic, major, minor, harmonic, melodic,
pentatonic, minorpentatonic), @mode scale|midi, @speed (ms; 0 = hard
snap), @amount, @minfreq/@maxfreq, bypass/mute; messages notes
(12 toggles or a pitch-class list), note <pitch> <velocity>, flush,
clear. Monophonic by design — wrap in mc. for multichannel.

Bumps submodules/taptools to pick up tune.h (which pins DspTap's
tap::dsp::yin). The object links tap::dsp like the spectral trio.
REVIVAL.md gains the §12 entry with the cross-repo slice, the IP
framing, and the deferred work (PSOLA/phase-vocoder backends, formant
preservation, auto-key, pitch outlet, runtime maxtest).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
Surfaces the kernel's new backend selection: @backend chooses between
the low-latency two-tap grain engine (default), formant-preserving
TD-PSOLA, and the peak-locked phase vocoder — all behind the same
detector, scale/MIDI mapper, and retune glide. Reference page and help
patcher document the trade-offs (psola wants harmonic-rich input; pvoc
carries one FFT frame of latency); wrapper tests cover the default and
kernel forwarding for all three values.

Bumps submodules/taptools to the backend-capable tune.h (which pins
DspTap's new psola.h and pvoc.h primitives). REVIVAL.md §12 updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
Surfaces the kernel's new formant option: @formant keeps the spectral
envelope in place while the correction shifts the pitch (LPC
source-filter, in DspTap's pvoc primitive), which matters for the
large corrections MIDI mode can command. The psola backend preserves
formants inherently; the grain engine is unaffected. Reference page
and help patcher updated; wrapper test covers the default and kernel
forwarding.

Bumps submodules/taptools to the formant-capable tune.h. REVIVAL.md
§12 notes the formant slice and the new verification notebooks in both
upstream repos (DspTap notebooks/pitchshift.ipynb with the two
findings; TapTools notebooks/tune.ipynb comparing the three backends).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
The right outlet reports the detected pitch — 'pitch <midi> <hz>' every
@interval ms while the input is voiced (0 disables), coalesced so only
changes are sent, with a relaxed-atomic audio-to-scheduler handoff and
a self-rearming timer (declared before the attributes so the
constructor-time default setter finds it built) — and answers
getkey/applykey. @autokey enables the kernel's Krumhansl-Kessler key
learner; getkey reports 'key <root> <major|minor> <confidence>' (or
'key none'), applykey adopts the estimate into the key and scale
attributes so the attribute state stays the source of truth.

Runtime maxtest added via make_maxtest.py: unpitched DC passes the
grain engine at exactly unity (the detector reports unvoiced, no
correction applies, and the complementary envelopes sum to 1) —
tap.tune~ joins the on-Mac max-test gate. Reference page, help patcher
(second outlet, autokey/getkey/applykey wiring, print monitor), and
REVIVAL.md updated; wrapper tests cover the new defaults, kernel
forwarding, and the no-estimate paths of getkey/applykey.

Bumps submodules/taptools to the autokey-capable tune.h.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
Follows tap/DspTap#3 merging — the kernel branch repointed its nested
dsptap pin from the side-branch SHA to the identical tree on DspTap
main, and this picks that up so the recursive checkout stays reachable
after branch cleanup. No code change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
tap/TapTools#20 merged (rebase); the pin moves from the side-branch SHA
to the identical tree on main (d5d3dd4) so it stays reachable after
branch cleanup. No code change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
Formatting only — no behavior change. The kernel repos' files were
formatted locally; this repo's own drift gate caught the wrapper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
clang (the tidy front end, and Apple clang on the macOS test build)
rejects static_cast<symbol>(attribute<symbol>) as ambiguous — the
attribute converts both through T& and through atom, and symbol is
constructible from either. min's attribute already provides
operator==(const attribute&, const T&), so compare against
symbol("...") directly. GCC had accepted the cast, which is why the
mock-kernel build never caught it locally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
Same canonical hook as the kernel repos: recursive submodule init (the
min-api chain, max-test, and the nested kernel pins), pre-commit
install against the pinned config, and a hook-environment warm for the
container snapshot — so web sessions can never again commit unformatted
code past the clang-format gate (the failure mode this PR's CI just
demonstrated). Web-only, synchronous, idempotent. Candidate for the
taphouse sync set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
tap and others added 2 commits July 22, 2026 17:46
The tap::dsp linker list gains tap.tune~ (and names the full primitive
set); the kernel-extraction count becomes a pointer to REVIVAL.md
instead of a number that goes stale; the CI section documents the
style workflow (clang-format/clang-tidy/drift), the pre-commit
expectation, the web SessionStart hook, and the treat-tidy-as-a-
second-compiler lesson from the tap.tune~ PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
TapHouse has adopted the hook into its sync set; this re-sync updates
the header to the canonical provenance wording so the copy is
byte-identical and passes the drift guard once the TapHouse tag
advances past v4. No functional change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
tap and others added 2 commits July 22, 2026 18:55
v5 canonicalizes the Claude Code web SessionStart hook (tap/TapHouse#4
merged); this branch already carries the synced hook, so the v5 drift
guard — which now covers it — passes by construction. Both the reusable
workflow ref and the comparison ref move together.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
The style workflow references taphouse@v5, which did not exist when the
ref bump was pushed; this empty commit re-triggers the runs now that
the tag is live.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
@tap
tap merged commit fdbfe95 into main Jul 22, 2026
10 checks passed
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