tap.tune~ — real-time pitch correction (full vertical slice)#56
Merged
Conversation
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
This was referenced Jul 22, 2026
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
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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),notesmessage (twelve panel-style toggles or a pitch-class list),@mode scale|midiwithnote <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;@formantenables LPC formant preservation on the pvoc path (matters for large MIDI-mode corrections).@autokey+getkey/applykey— the advisory Krumhansl–Kessler key learner;applykeyadopts the estimate through the key/scale attributes so saved state stays the source of truth.pitch <midi> <hz>every@intervalms while voiced (atomic audio→scheduler handoff, coalesced, self-rearming timer), plus thekey ...replies.Package slice: reference page (
docs/tap.tune~.maxref.xml), help patcher, wrapper tests (attribute defaults, kernel forwarding for every attribute, bothnotesforms, no-estimategetkey/applykeypaths, bypass/mute), and the runtime maxtest (runtime-tests/patchers/tap.tune~.maxtest.maxpat, generated viamake_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/taptoolspins the latter's head).🤖 Generated with Claude Code
https://claude.ai/code/session_01BuUawafae7RR2ySWabuJcs
Generated by Claude Code