AU plays HEXAWE voices as factory presets; fix crashes on load and state restore #6
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/hexawe-runtime-voice"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The AU now plays the HEXAWE patches. Each one shows up as a factory preset and plays its LittleGPTracker voice from #5. This PR also fixes two crashes that are already on
main: the AU couldn't be created, and it couldn't restore saved state.Voices as presets
presets/hexaweis copied into the extension as a folder.<release>[ / <song>] <instrument> · <artist>.hogtypet 06 · k9d n BuZorLIVE @ SAVE FILE / STeP 0A · KEFF.fullStatesaves the voice's path and restores it. If the saved voice is missing or won't decode, the AU falls back to the wavetable engine rather than keeping the previous voice.musicalContextBlock) drives the voice's tables. With no host tempo, the voice keeps its song's own tempo.Crashes fixed (already on main)
sample.index, …) contained., which AudioToolbox reserves as a delimiter.indexlives in groupsample.sample.index, whichopsl_parityandudg_paritydepend on.param.value, and reading that calls the provider again.Testing
tests/lgpt/au_check.swiftcreates the real AU and checks each of the following:internalRenderBlockat a host tempo of 97 BPM, matches the same voice rendered directly, sample for sample.fullStaterestores both the voice and parameter values. Init and a missing saved voice both return to the wavetable engine.tests/lgpt/run.shruns this check too. Its wavetable regression baseline now buildsmain's kernel together withmain'sLGPTVoice.swift.Other checks:
tests/lgpt/run.sh(full): all checks pass, and LGPT still matches exactly on 418 of 418 comparable renders.udg_parityandopsl_parityboth pass.xcodebuildfor the iOS Simulator succeeds, and the.appexcontainshexawe/.Not covered
The AU now plays the HEXAWE patches' LGPT voices: - presets/hexawe is bundled into the extension; every *.lgpt.json is a factory preset after Init (the wavetable engine), named from its credit. - Choosing a preset loads its voice; fullState saves the voice's path and restores it, falling back to the wavetable engine if it is missing. - The host tempo (musicalContextBlock) drives the voice's tables; with no host tempo the voice keeps its song's tempo. - The kernel takes up a new voice through a try-lock hand-off at its next note or block, so loading while audio runs never swaps the voice mid-render, and replaced voices are released off the render thread. Two bugs already on main, found by instantiating the AU in a test: - Every AUParameter identifier ("sample.index") contained ".", which AudioToolbox reserves, so creating the AU threw. Parameters now use the part after their section ("index" in group "sample"), so their key paths are still the OPSL identifiers. - The tree's value provider returned param.value, which calls the provider again; restoring any saved state overflowed the stack. Values are now kept per address and the provider reads those. tests/lgpt/au_check.swift checks all of this through the real AU and render block (control: expecting the song's tempo must fail); run.sh runs it and now builds main's kernel with main's LGPTVoice for the regression baseline. Co-Authored-By: Claude <noreply@anthropic.com>