diff --git a/patches/aquasynth-patch-cultcache.json b/patches/aquasynth-patch-cultcache.json new file mode 100644 index 0000000..018bf71 --- /dev/null +++ b/patches/aquasynth-patch-cultcache.json @@ -0,0 +1,127 @@ +{ + "type": "cultcache.document.aquasynth.sound_claims", + "schema": "cultcache/aquasynth/sound-claims.v1", + "version": 1, + "generated_from": [ + "patches/library.yaml", + "src/AquaSynth.Core/ReferenceRebuilds.cs", + "docs/ipa-vocal-tract-roadmap.md", + "state/scratch.md" + ], + "patch_database": { + "source_path": "patches/library.yaml", + "entries": [ + { "path": "patches/808/clap.aqua", "family": "808", "name": "clap", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/808/cowbell.aqua", "family": "808", "name": "cowbell", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/808/hat.aqua", "family": "808", "name": "hat", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/808/kick.aqua", "family": "808", "name": "kick", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/808/snare.aqua", "family": "808", "name": "snare", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/808/tom.aqua", "family": "808", "name": "tom", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/advanced/aurora-pad.aqua", "family": "advanced", "name": "aurora-pad", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/advanced/glass-creature.aqua", "family": "advanced", "name": "glass-creature", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/advanced/machine-breath.aqua", "family": "advanced", "name": "machine-breath", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/advanced/ritual-sequence.aqua", "family": "advanced", "name": "ritual-sequence", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/bfxr/coin-spark.aqua", "family": "bfxr", "name": "coin-spark", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/bfxr/portal-chirp.aqua", "family": "bfxr", "name": "portal-chirp", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/bfxr/shield-pop.aqua", "family": "bfxr", "name": "shield-pop", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/bfxr/ui-bloom.aqua", "family": "bfxr", "name": "ui-bloom", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/dx7/algorithm-32-additive-organ.aqua", "family": "dx7", "name": "Algorithm 32 additive organ", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/dx7/algorithm-8-bright-pair.aqua", "family": "dx7", "name": "Algorithm 8 bright pair", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/dx7/public-domain-mc-mm-5-3.aqua", "family": "dx7", "name": "Public-domain MC-MM 5-3", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/dx7/public-domain/prc-synth1-calibrated.aqua", "family": "dx7/public-domain", "name": "PRC SYNTH1 calibrated", "source": "analog1.syx voice 17 parity probe", "notes": "Generated from latest calibrated DX7 lowering." }, + { "path": "patches/examples/language-tour.aqua", "family": "examples", "name": "Language Tour", "source": "BuiltInScripts.PatchScriptExample", "notes": "Parser and DSL feature tour." }, + { "path": "patches/fm-bell/bell.aqua", "family": "fm-bell", "name": "bell", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/fm-bell/chime.aqua", "family": "fm-bell", "name": "chime", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/fm-bell/coin.aqua", "family": "fm-bell", "name": "coin", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/fm-bell/gong.aqua", "family": "fm-bell", "name": "gong", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/blip.aqua", "family": "sfxr", "name": "blip", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/classic/classic-sfxr-abstract-golf.aqua", "family": "sfxr/classic", "name": "Classic SFXR Abstract Golf", "source": "BuiltInScripts.ClassicSfxrAbstractGolfScript", "notes": "Compressed SFXR-derived multi-sound golf fixture." }, + { "path": "patches/sfxr/explosion.aqua", "family": "sfxr", "name": "explosion", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/hit.aqua", "family": "sfxr", "name": "hit", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/jump.aqua", "family": "sfxr", "name": "jump", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/laser.aqua", "family": "sfxr", "name": "laser", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/pickup.aqua", "family": "sfxr", "name": "pickup", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/sfxr/powerup.aqua", "family": "sfxr", "name": "powerup", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/wobble-bass/growl.aqua", "family": "wobble-bass", "name": "growl", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/wobble-bass/neuro.aqua", "family": "wobble-bass", "name": "neuro", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/wobble-bass/talker.aqua", "family": "wobble-bass", "name": "talker", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." }, + { "path": "patches/wobble-bass/yoy.aqua", "family": "wobble-bass", "name": "yoy", "source": "BuiltInScripts.ReferenceScripts", "notes": "Stock reference patch exported from the in-code catalog." } + ] + }, + "patch_claims": [ + { + "id": "zyn/project-additive-lead/aquasynth", + "patch_path": null, + "reference": { "synth_or_source": "ZynAddSubFX project-authored fixture", "fixture_or_artifact": "tests/AquaSynth.Dsl.Tests/Fixtures/ZynAddSubFX/ProjectAuthored/additive-lead.xiz", "license_scope": "project-authored development fixture" }, + "intent": { "perceptual_claim": "A layered additive lead expressed as named harmonic banks rather than anonymous partial piles.", "use_context": "Zyn ADDsynth pressure for AquaSynth harmonic-bank syntax." }, + "tier": "pressure", + "proof": { "latest_render_artifact": "ReferenceRebuildCatalog.ZynRebuilds", "latest_listening_receipt": "missing: no accepted listening receipt recorded for this fixture", "metric_summary": "structural pressure only", "known_lies": ["not exact Zyn ADDsynth oscillator phase/bandwidth semantics", "not exact Zyn free-envelope timing"] } + }, + { + "id": "zyn/project-pad-texture/aquasynth", + "patch_path": null, + "reference": { "synth_or_source": "ZynAddSubFX project-authored fixture", "fixture_or_artifact": "tests/AquaSynth.Dsl.Tests/Fixtures/ZynAddSubFX/ProjectAuthored/pad-texture.xiz", "license_scope": "project-authored development fixture" }, + "intent": { "perceptual_claim": "A slow layered PAD texture with body, shimmer, air, and explicit spectral-cloud source authority.", "use_context": "PAD syntax and FFT wavetable pressure." }, + "tier": "pressure", + "proof": { "latest_render_artifact": "artifacts/parity/zyn-pad-reference// when optional Zyn oracle is installed", "latest_listening_receipt": "ear rejected early angry-bees candidate; no final accepted receipt recorded for project-authored pad-texture", "metric_summary": "optional Zyn PAD render comparison writes log-mel/envelope report", "known_lies": ["not full Zyn PAD profile/randomness/pitch-zone behavior", "not arbitrary Zyn free-envelope curves"] } + }, + { + "id": "zyn/project-vocal-layer/aquasynth", + "patch_path": null, + "reference": { "synth_or_source": "ZynAddSubFX project-authored fixture", "fixture_or_artifact": "tests/AquaSynth.Dsl.Tests/Fixtures/ZynAddSubFX/ProjectAuthored/vocal-layer.xiz", "license_scope": "project-authored development fixture" }, + "intent": { "perceptual_claim": "A layered vocal-ish synth where air, body, and breath remain inspectable sound objects.", "use_context": "Formant/layer pressure before the full speech lane." }, + "tier": "pressure", + "proof": { "latest_render_artifact": "ReferenceRebuildCatalog.ZynRebuilds", "latest_listening_receipt": "missing: no accepted listening receipt recorded for this fixture", "metric_summary": "structural pressure only", "known_lies": ["no exact Zyn kit-item/effect routing", "formant motion remains approximate"] } + }, + { + "id": "dx7/algo32-additive-organ/aquasynth", + "patch_path": "patches/dx7/algorithm-32-additive-organ.aqua", + "reference": { "synth_or_source": "DX7 algorithm topology", "fixture_or_artifact": "in-code topology reference", "license_scope": "derived structural reference" }, + "intent": { "perceptual_claim": "DX7 algorithm 32 as the easy six-carrier additive case.", "use_context": "Operator topology pressure where AquaSynth should avoid inventing FM machinery it does not need." }, + "tier": "sketch", + "proof": { "latest_render_artifact": "parser/export tests", "latest_listening_receipt": "missing: topology sketch has no listening receipt", "metric_summary": "structural tests only", "known_lies": ["not exact DX7 envelope execution", "not ROM output compensation"] } + }, + { + "id": "dx7/algo8-bright-pair/aquasynth", + "patch_path": "patches/dx7/algorithm-8-bright-pair.aqua", + "reference": { "synth_or_source": "DX7 algorithm topology", "fixture_or_artifact": "in-code topology reference", "license_scope": "derived structural reference" }, + "intent": { "perceptual_claim": "DX7 algorithm 8 as an explicit AquaSynth operator graph with visible modulation routes.", "use_context": "Operator graph pressure for summed stacks and feedback." }, + "tier": "pressure", + "proof": { "latest_render_artifact": "parser/export tests", "latest_listening_receipt": "missing: topology pressure patch has no listening receipt", "metric_summary": "structural tests only", "known_lies": ["not calibrated DX7 feedback register", "not exact DX7 EG"] } + }, + { + "id": "dx7/public-domain-mc-mm-5-3/aquasynth", + "patch_path": "patches/dx7/public-domain-mc-mm-5-3.aqua", + "reference": { "synth_or_source": "Dexed/dexed-py render of public-domain DX7 SysEx", "fixture_or_artifact": "tests/AquaSynth.Dsl.Tests/Fixtures/Dx7/PublicDomain/analog1.syx#13", "license_scope": "public-domain development fixture; not packaged" }, + "intent": { "perceptual_claim": "A short C3-derived sine-like DX7 voice rebuilt as an AquaSynth parity rung.", "use_context": "Lawful rendered-audio parity proof for the DX7 lane." }, + "tier": "parity", + "proof": { "latest_render_artifact": "Dx7ReferenceParityTests optional dexed-py/Faust render report", "latest_listening_receipt": "metric-gated parity; no explicit human listening receipt recorded", "metric_summary": "score>=0.75 log_mel<0.12 envelope<0.10", "known_lies": ["matches rendered behavior, not exact operator-level execution", "uses AquaSynth ADSR timing matched to audio"] } + }, + { + "id": "dx7/public-domain-prc-synth1-calibrated/aquasynth", + "patch_path": "patches/dx7/public-domain/prc-synth1-calibrated.aqua", + "reference": { "synth_or_source": "Dexed/dexed-py render of public-domain DX7 SysEx", "fixture_or_artifact": "tests/AquaSynth.Dsl.Tests/Fixtures/Dx7/PublicDomain/analog1.syx#17", "license_scope": "public-domain development fixture; not packaged" }, + "intent": { "perceptual_claim": "A hard DX7 stacked-FM calibration probe that should keep body, attack, and harmonic grit believable.", "use_context": "DX7 calibration pressure for route scaling, feedback, detune, operator levels, and envelope shape." }, + "tier": "pressure", + "proof": { "latest_render_artifact": "artifacts/parity/dx7-prc-synth1// when optional dexed-py and Faust are installed", "latest_listening_receipt": "several user listening corrections recorded in state/scratch.md; not promoted to accepted parity", "metric_summary": "latest recorded calibrated probe: log-mel around 0.17-0.24 depending rung; pressure target, not accepted parity", "known_lies": ["DX7 EG remains approximated", "hard target still calibration pressure"] } + } + ], + "speech_claims": [ + { + "id": "speech/espeak-ng-tiny-workout", + "utterance_source": { "text_or_ipa": "a, pa, ta, ka, sa, ma", "phoneme_source": "tests/AquaSynth.Dsl.Tests/EspeakNgGradientDescentTests.cs", "reference_renderer": "eSpeak NG when ESPEAK_NG or espeak/espeak-ng is installed" }, + "target": { "anatomy_or_profile": "neutral human-ish tract controller profile", "phonetic_constraints": ["bilabial stop pressure", "alveolar stop pressure", "velar stop pressure", "sibilant turbulence", "nasal velum opening", "open vowel baseline"] }, + "intent": { "perceptual_claim": "AquaSynth should learn a tiny speech-control mapping against generated reference speech instead of hand-filled target paperwork.", "use_context": "First curriculum rung for Weksa IPA/phonetic utterance rendering." }, + "tier": "pressure", + "proof": { "latest_render_artifact": "artifacts/parity/espeak-ng-gradient-descent/-tiny/training-report.md when eSpeak NG is installed", "latest_listening_receipt": "missing: no human accepted speech artifact yet", "metric_summary": "optional fixture asserts chained learning loss reduction and records log-mel means", "known_lies": ["not intelligible AquaSynth speech yet", "reference supervision still eSpeak-shaped"] } + }, + { + "id": "speech/compiled-faust-loss-surface", + "utterance_source": { "text_or_ipa": "controller-output vector from learned phonetic pipeline", "phoneme_source": "SpeechBackpropagationPipeline + VocalTractNeuralMapper", "reference_renderer": "compiled native Faust speech-loss probe" }, + "target": { "anatomy_or_profile": "current minimal controllable speech synth; future curriculum target slot", "phonetic_constraints": ["all neural mapper outputs exported as speech/output/N controls", "cutoff clamped below Nyquist", "candidate batches render without recompiling DSP"] }, + "intent": { "perceptual_claim": "The optimizer can blast many controller attempts through one compiled Faust surface and climb toward a reference match.", "use_context": "Curriculum learning loss surface before richer anatomy and parity targets." }, + "tier": "proof", + "proof": { "latest_render_artifact": "CompiledFaustRenderedSpeechLossSurfaceReusesOnePatchWithExportedOutputKnobsWhenToolchainIsAvailable", "latest_listening_receipt": "missing: optimizer plumbing proof only", "metric_summary": "opt-in native batch proof renders multiple candidates through one compiled patch and checks lower loss for closer controls", "known_lies": ["finite-difference controller gradient, not analytic Faust DSP gradient", "minimal synth rung, not full vocal tract"] } + } + ] +} diff --git a/src/AquaSynth.Core/CultCachePatchDocument.cs b/src/AquaSynth.Core/CultCachePatchDocument.cs new file mode 100644 index 0000000..5abf04c --- /dev/null +++ b/src/AquaSynth.Core/CultCachePatchDocument.cs @@ -0,0 +1,63 @@ +using System.Text.Json.Serialization; + +namespace AquaSynth.Dsl; + +public sealed record CultCachePatchDocument( + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("schema")] string Schema, + [property: JsonPropertyName("version")] int Version, + [property: JsonPropertyName("generated_from")] IReadOnlyList GeneratedFrom, + [property: JsonPropertyName("patch_database")] CultCachePatchDatabase PatchDatabase, + [property: JsonPropertyName("patch_claims")] IReadOnlyList PatchClaims, + [property: JsonPropertyName("speech_claims")] IReadOnlyList SpeechClaims); + +public sealed record CultCachePatchDatabase( + [property: JsonPropertyName("source_path")] string SourcePath, + [property: JsonPropertyName("entries")] IReadOnlyList Entries); + +public sealed record CultCachePatchDatabaseEntry( + [property: JsonPropertyName("path")] string Path, + [property: JsonPropertyName("family")] string Family, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("source")] string Source, + [property: JsonPropertyName("notes")] string Notes); + +public sealed record CultCachePatchClaimCard( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("patch_path")] string? PatchPath, + [property: JsonPropertyName("reference")] CultCacheReferenceTruth Reference, + [property: JsonPropertyName("intent")] CultCacheIntentTruth Intent, + [property: JsonPropertyName("tier")] string Tier, + [property: JsonPropertyName("proof")] CultCacheProofTruth Proof); + +public sealed record CultCacheSpeechClaimCard( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("utterance_source")] CultCacheUtteranceSourceTruth UtteranceSource, + [property: JsonPropertyName("target")] CultCacheSpeechTargetTruth Target, + [property: JsonPropertyName("intent")] CultCacheIntentTruth Intent, + [property: JsonPropertyName("tier")] string Tier, + [property: JsonPropertyName("proof")] CultCacheProofTruth Proof); + +public sealed record CultCacheReferenceTruth( + [property: JsonPropertyName("synth_or_source")] string SynthOrSource, + [property: JsonPropertyName("fixture_or_artifact")] string FixtureOrArtifact, + [property: JsonPropertyName("license_scope")] string LicenseScope); + +public sealed record CultCacheUtteranceSourceTruth( + [property: JsonPropertyName("text_or_ipa")] string TextOrIpa, + [property: JsonPropertyName("phoneme_source")] string PhonemeSource, + [property: JsonPropertyName("reference_renderer")] string ReferenceRenderer); + +public sealed record CultCacheSpeechTargetTruth( + [property: JsonPropertyName("anatomy_or_profile")] string AnatomyOrProfile, + [property: JsonPropertyName("phonetic_constraints")] IReadOnlyList PhoneticConstraints); + +public sealed record CultCacheIntentTruth( + [property: JsonPropertyName("perceptual_claim")] string PerceptualClaim, + [property: JsonPropertyName("use_context")] string UseContext); + +public sealed record CultCacheProofTruth( + [property: JsonPropertyName("latest_render_artifact")] string LatestRenderArtifact, + [property: JsonPropertyName("latest_listening_receipt")] string LatestListeningReceipt, + [property: JsonPropertyName("metric_summary")] string MetricSummary, + [property: JsonPropertyName("known_lies")] IReadOnlyList KnownLies); diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 82e8976..8c693cf 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -116,3 +116,4 @@ {"date":"2026-05-19","topic":"speech-pipeline-chained-backprop","lesson":"The speech-learning path now has real chained backprop between the utterance encoder and synth driver. The packed network can return gradients with respect to its input, so downstream synth-driver loss can update the upstream utterance encoder instead of training the two models as separate supervised islands.","evidence":"Added PackedNeuralBackpropagation, TrainSingle/TrainSingleFromOutputGradient, SpeechBackpropagationPipeline, and SpeechBackpropagationPipelineTests; updated the eSpeak gradient fixture to train the utterance encoder from synth-driver loss rather than from a separate compressed-mel target."} {"date":"2026-05-19","topic":"faust-rendered-speech-loss","lesson":"For speech learning, Core should accept external synth-output gradients while Faust owns rendered loss evaluation. Finite-difference gradients over controller outputs are honest black-box renderer pressure, but too slow for default tests until render compilation is cached or proxied.","evidence":"Added SpeechBackpropagationPipeline.TrainSingleFromSynthOutputGradient and FaustRenderedSpeechLossSurface. The opt-in AQUASYNTH_RUN_FAUST_SPEECH_LOSS=1 proof renders reference and candidate speech targets through Faust, compares log-mel evidence, and returns a finite-difference output gradient for backpropagation through the learned chain."} {"date":"2026-05-19","topic":"compiled-faust-speech-loss-surface","lesson":"The usable speech loss surface should compile topology once and vary every neural mapper output through exported Faust controls. Batch rendering through a native compiled factory makes finite-difference and curriculum learning plausible; recompiling per candidate is only a proof scaffold.","evidence":"Added native Faust UI control discovery/set support, AquaSynthCompiledPatch.Render(controlValues), and CompiledFaustRenderedSpeechLossSurface with speech/output/N knobs for all mapper outputs. The opt-in proof renders multiple candidates through one compiled patch and caught the need to clamp dynamic filter cutoff below Nyquist."} +{"date":"2026-05-19","topic":"cultcache-sound-claim-cards","lesson":"Serious AquaSynth sound claims should be distributed as typed data beside the patch database. Patch and speech claim cards must name the reference/source, intent, tier, proof artifact, latest listening receipt surface, metrics, and known lies; stock sketches stay in the database but should not masquerade as parity without receipts.","evidence":"Added CultCachePatchDocument types, patches/aquasynth-patch-cultcache.json, and tests that load the typed document, check patch database count against library.yaml, and require every ReferenceRebuildCatalog entry to have a claim card."} diff --git a/state/map.yaml b/state/map.yaml index ce2c4be..20a506f 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -40,6 +40,8 @@ modules: faust_compiler: src/AquaSynth.Faust/FaustCompiler.cs native_faust_runtime: src/AquaSynth.Faust/NativeFaustRuntime.cs faust_rendered_speech_loss: src/AquaSynth.Faust/FaustRenderedSpeechLossSurface.cs + cultcache_sound_claim_document: patches/aquasynth-patch-cultcache.json + cultcache_sound_claim_types: src/AquaSynth.Core/CultCachePatchDocument.cs dx7_reference_render_tests: tests/AquaSynth.Dsl.Tests/Dx7ReferenceParityTests.cs espeak_ng_reference_tests: tests/AquaSynth.Dsl.Tests/EspeakNgReferenceTests.cs espeak_ng_gradient_descent_tests: tests/AquaSynth.Dsl.Tests/EspeakNgGradientDescentTests.cs @@ -81,6 +83,7 @@ boundaries: - optional eSpeak NG generated ground-truth fixture for supervised utterance-embedding and synth-driver gradient descent - Faust-rendered speech loss surface in AquaSynth.Faust, using rendered audio analysis and finite-difference controller-output gradients - compiled native Faust speech-loss surface with exported /speech/output/N controls for batch candidate rendering without recompiling DSP + - typed CultCache sound-claim document that bundles the patch database with fixture-backed patch claim cards and speech-lane claim cards dev_only: - public-domain DX7 SysEx fixtures - pinned GPL ZynAddSubFX source for parity tests diff --git a/state/scratch.md b/state/scratch.md index 816e998..98f40dd 100644 --- a/state/scratch.md +++ b/state/scratch.md @@ -2,6 +2,29 @@ Current slice: +- Added a typed CultCache sound-claim document for CultMesh distribution: + `patches/aquasynth-patch-cultcache.json`. +- Added `CultCachePatchDocument` record types in Core. The document bundles + the full `patches/library.yaml` patch database with patch claim cards and + speech claim cards. +- Patch claim cards now cover every `ReferenceRebuildCatalog.All()` fixture + patch: the three project-authored Zyn rebuilds and the three DX7 reference + rebuilds. The PRC SYNTH1 calibrated patch also has a claim card because it is + in the patch database as a hard public-domain DX7 pressure target. +- Speech claim cards cover the eSpeak NG tiny workout and the compiled Faust + speech loss surface. Both explicitly name utterance/phoneme source, target + anatomy/profile, intent, tier, proof artifact, listening receipt surface, and + known lies. +- Stock patch database entries are included as database entries, not promoted + to serious claims without references. That preserves the law: sketches may + exist, but parity/pressure/proof claims need named reference and receipt + surfaces. +- Verification: + `dotnet test tests\AquaSynth.Dsl.Tests\AquaSynth.Dsl.Tests.csproj --filter "CultCachePatchDocumentTests" -v minimal`: + 3 passed. + +Previous slice: + - Reworked the Faust-rendered speech-loss path toward the actual curriculum machine: `CompiledFaustRenderedSpeechLossSurface` compiles one native Faust patch with exported `speech/output/N` hslider controls for every neural diff --git a/tests/AquaSynth.Dsl.Tests/CultCachePatchDocumentTests.cs b/tests/AquaSynth.Dsl.Tests/CultCachePatchDocumentTests.cs new file mode 100644 index 0000000..4bbf6e0 --- /dev/null +++ b/tests/AquaSynth.Dsl.Tests/CultCachePatchDocumentTests.cs @@ -0,0 +1,84 @@ +using System.Text.Json; +using AquaSynth.Dsl; + +namespace AquaSynth.Dsl.Tests; + +public sealed class CultCachePatchDocumentTests +{ + [Fact] + public void CultCachePatchDocumentLoadsAsTypedSoundClaimBundle() + { + var root = RepositoryRoot(); + var documentPath = Path.Combine(root, "patches", "aquasynth-patch-cultcache.json"); + var document = JsonSerializer.Deserialize( + File.ReadAllText(documentPath), + new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + + Assert.NotNull(document); + Assert.Equal("cultcache.document.aquasynth.sound_claims", document!.Type); + Assert.Equal("cultcache/aquasynth/sound-claims.v1", document.Schema); + Assert.Equal(1, document.Version); + Assert.Equal(LibraryEntryCount(root), document.PatchDatabase.Entries.Count); + Assert.Contains(document.PatchClaims, claim => claim.Id == "dx7/public-domain-mc-mm-5-3/aquasynth" && claim.Tier == "parity"); + Assert.Contains(document.PatchClaims, claim => claim.Id == "zyn/project-pad-texture/aquasynth" && claim.Reference.SynthOrSource.Contains("ZynAddSubFX", StringComparison.Ordinal)); + Assert.Contains(document.SpeechClaims, claim => claim.Id == "speech/espeak-ng-tiny-workout" && claim.Target.AnatomyOrProfile.Contains("human", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(document.SpeechClaims, claim => claim.Id == "speech/compiled-faust-loss-surface" && claim.Tier == "proof"); + } + + [Fact] + public void EverySeriousClaimNamesAReferenceAndReceiptSurface() + { + var document = JsonSerializer.Deserialize( + File.ReadAllText(Path.Combine(RepositoryRoot(), "patches", "aquasynth-patch-cultcache.json")), + new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!; + + foreach (var claim in document.PatchClaims) + { + Assert.False(string.IsNullOrWhiteSpace(claim.Reference.SynthOrSource), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Reference.FixtureOrArtifact), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Intent.PerceptualClaim), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Proof.LatestRenderArtifact), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Proof.LatestListeningReceipt), claim.Id); + Assert.NotEmpty(claim.Proof.KnownLies); + } + + foreach (var claim in document.SpeechClaims) + { + Assert.False(string.IsNullOrWhiteSpace(claim.UtteranceSource.PhonemeSource), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.UtteranceSource.ReferenceRenderer), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Target.AnatomyOrProfile), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Proof.LatestRenderArtifact), claim.Id); + Assert.False(string.IsNullOrWhiteSpace(claim.Proof.LatestListeningReceipt), claim.Id); + Assert.NotEmpty(claim.Proof.KnownLies); + } + } + + [Fact] + public void CultCachePatchClaimsCoverReferenceRebuildCatalog() + { + var document = JsonSerializer.Deserialize( + File.ReadAllText(Path.Combine(RepositoryRoot(), "patches", "aquasynth-patch-cultcache.json")), + new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!; + var claimIds = document.PatchClaims.Select(claim => claim.Id).ToHashSet(StringComparer.Ordinal); + + foreach (var rebuild in ReferenceRebuildCatalog.All()) + { + Assert.Contains(rebuild.Id, claimIds); + } + } + + private static int LibraryEntryCount(string root) => + File.ReadLines(Path.Combine(root, "patches", "library.yaml")) + .Count(line => line.TrimStart().StartsWith("- path:", StringComparison.Ordinal)); + + private static string RepositoryRoot() + { + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory is not null && !File.Exists(Path.Combine(directory.FullName, "AquaSynth.sln"))) + { + directory = directory.Parent; + } + + return directory?.FullName ?? throw new InvalidOperationException("could not find repository root"); + } +}