Seed music knowledge manuals
This commit is contained in:
parent
94cf7174f7
commit
16ed4084ff
6 changed files with 337 additions and 1 deletions
112
docs/music-production-knowledge/aqua-dsp-usage-manual.md
Normal file
112
docs/music-production-knowledge/aqua-dsp-usage-manual.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# AquaSynth DSP Usage Manual For Music Agents
|
||||
|
||||
kind: manual
|
||||
tier: core-doctrine
|
||||
topic: AquaSynth DSP usage for composition and production
|
||||
|
||||
## Owner
|
||||
|
||||
This manual owns the minimum practical DSP and DSL knowledge a musician agent
|
||||
needs before writing a song candidate, so retrieval starts from usable
|
||||
AquaSynth technique instead of copying weak prior patches.
|
||||
|
||||
## Transfer Rules
|
||||
|
||||
- Start with form, not timbre. Declare `meter`, harmonic center or progression,
|
||||
lane gates, section-level mix motion, and target duration before building
|
||||
voices.
|
||||
- Treat every sound as a role owner. Leads, bass, drums, pads, and texture need
|
||||
separate control surfaces so the next agent can adjust them without surgery.
|
||||
- Use reference analysis as constraints: tempo/autocorrelation for gates,
|
||||
register/root/scale for pitch lanes, band stats for filtering, and RMS/motion
|
||||
coverage for arrangement density.
|
||||
- Write the simplest patch that makes ownership inspectable. Do not hide a song
|
||||
in one giant voice or one full-duration noise bed.
|
||||
|
||||
## Current AquaSynth Authoring Surface
|
||||
|
||||
Composition sugar:
|
||||
|
||||
```aqua
|
||||
meter bpm=128 beats=4
|
||||
sequence name=kick pattern=x...x...x...x... step=.125 high=.9 low=0
|
||||
scale name=hook path=/seq/lead/freq root=220 scale=minor degrees=0,2,3,5,3,2 step=.25
|
||||
chords name=pad root=220 scale=minor progression=0,5,3,4 voicing=0,2,4 paths=/chords/pad/root,/chords/pad/third,/chords/pad/fifth step=bar
|
||||
mix name=pad points=0:.10,4:.22,8:.15,12:.30,16:.12
|
||||
```
|
||||
|
||||
The sugar lowers into visible `param` and `curve` owners. Bind those paths from
|
||||
voices with `gain=@/seq/kick`, `freq=@/seq/lead/freq`, or
|
||||
`gain=@/mix/pad/gain`.
|
||||
|
||||
Voice-like leads:
|
||||
|
||||
```aqua
|
||||
source_port name=lead_src kind=syrinx pressure=.75 opening=.42
|
||||
acoustic_network name=lead_body source=lead_src radiation=beak
|
||||
acoustic_voice name=lead network=lead_body freq=@/seq/lead/freq gain=@/mix/lead/gain
|
||||
```
|
||||
|
||||
Use syrinx/acoustic ownership when the reference has singing, vocal chops,
|
||||
creature calls, reed-like lead, or expressive vowel motion. Move pressure,
|
||||
opening, filter/formant color, and pitch. A static syrinx badge is not a vocal
|
||||
line.
|
||||
|
||||
Subtractive drums:
|
||||
|
||||
```aqua
|
||||
sequence name=kick pattern=x...x...x...x... step=.125 high=1 low=0
|
||||
voice name=kick_body wave=sine freq=54 gain=@/seq/kick env=ad attack=.002 decay=.14
|
||||
voice name=kick_click wave=noise gain=@/seq/kick hpf=2500 lpf=7000 env=ad attack=.001 decay=.035
|
||||
```
|
||||
|
||||
Drums need body plus skin. Use sine/triangle bodies for kick/snare weight,
|
||||
filtered noise only for click, skin, dust, or air, and gates from target tempo.
|
||||
Noise alone is a placeholder unless it has band limits, a gate, and a musical
|
||||
job.
|
||||
|
||||
Additive/PAD beds:
|
||||
|
||||
```aqua
|
||||
layer name=pad engine=pad freq=@/chords/pad/root gain=@/mix/pad/gain
|
||||
harmonics name=pad_bank source=pad partials=1:.7,2:.25,3:.18,5:.08
|
||||
spectrum name=pad_air source=pad_bank centroid=1800 bandwidth=.35
|
||||
```
|
||||
|
||||
Pads own harmonic field and emotional bed. Use harmonic banks and slow
|
||||
brightness/gain motion. Do not let a pad occupy every band for the full target
|
||||
unless the reference really does.
|
||||
|
||||
Texture and recording color:
|
||||
|
||||
```aqua
|
||||
texture name=dust_hat role=dust pattern=x..x..x. step=.125 gain=.08 sustain=30
|
||||
texture name=air_wash role=air gain=.035 sustain=30
|
||||
texture name=codec_bed role=codec gain=.04 sustain=30
|
||||
```
|
||||
|
||||
Texture owns band-limited color, not arrangement. It should support a scene with
|
||||
motion, gates, or slow modulation. A static broadband noise voice is failure
|
||||
pressure.
|
||||
|
||||
## Production Checklist
|
||||
|
||||
- Producer brief: target feel, energy contour, meter, tonal center, section map,
|
||||
role map, and mix priority.
|
||||
- First attempt: prove parsing, duration coverage, and audible lane ownership.
|
||||
- Later attempts: change one hypothesis at a time: timing, register, role
|
||||
assignment, filter band, envelope, or section/mix motion.
|
||||
- Listening journal: write what sounded alive, fake, static, missing, or too
|
||||
generic after every render.
|
||||
- Gap ledger: name missing AquaSynth primitives or sugar only when a concrete
|
||||
production problem forced the workaround.
|
||||
|
||||
## Failure Modes
|
||||
|
||||
- Naming `kick`, `hat`, `pad`, or `syrinx` without audible role behavior.
|
||||
- Copying one stock drum grid across unrelated targets.
|
||||
- Letting texture keep the tail non-silent while composition dies.
|
||||
- Hand-writing isolated frequencies when the reference suggests a tonal center
|
||||
or progression.
|
||||
- Treating a metric bump as a lesson without a reusable owner sentence.
|
||||
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
# Open Music Theory And Production Textbook Distill
|
||||
|
||||
kind: source-distillation
|
||||
tier: core-doctrine
|
||||
topic: open music theory and digital production lessons for AquaSynth
|
||||
|
||||
## Sources
|
||||
|
||||
- Open Music Theory, https://viva.pressbooks.pub/openmusictheory/
|
||||
- Music Theory for the 21st-Century Classroom, https://musictheory.pugetsound.edu/mt21c/
|
||||
- Miller Puckette, The Theory and Technique of Electronic Music, https://msp.ucsd.edu/techniques.htm
|
||||
- Hack Audio, https://www.hackaudio.com/
|
||||
|
||||
## Owner
|
||||
|
||||
This distillation owns source-grounded general music and production knowledge
|
||||
for AquaSynth agents, so the music generator can reason from composition and
|
||||
signal-production fundamentals instead of imitating previous weak candidates.
|
||||
|
||||
## Transfer Rules
|
||||
|
||||
- Meter is a promise about expectation. Use it to place accents, repetition,
|
||||
syncopation, fills, and section boundaries, not just to calculate step
|
||||
seconds.
|
||||
- Melody needs contour, register, motive, and variation. A lead line should have
|
||||
a recognizable shape, then repeat, answer, invert, truncate, sequence, or
|
||||
intensify.
|
||||
- Harmony is motion plus gravity. Even simple progressions should imply
|
||||
departure and return. Use roots, chord tones, pedal tones, and bass movement
|
||||
deliberately.
|
||||
- Rhythm works through pattern, contrast, and hierarchy. Kick/snare/hat lanes
|
||||
should form a groove with strong and weak positions, not independent blinking
|
||||
lights.
|
||||
- Timbre is spectrum over time. Envelopes, filters, modulation, and saturation
|
||||
should move the sound from attack to body to tail.
|
||||
- Mixing is arrangement made audible. Gain lanes, frequency separation, and
|
||||
automation decide which role owns attention at each section.
|
||||
|
||||
## AquaSynth Patterns
|
||||
|
||||
Melodic motive:
|
||||
|
||||
```aqua
|
||||
meter bpm=132 beats=4
|
||||
scale name=lead path=/seq/lead/freq root=220 scale=minor degrees=0,2,3,5,3,2,0,-2 step=.25
|
||||
sequence name=lead_gate pattern=x.x.xx.. step=.25 high=.75 low=0
|
||||
mix name=lead points=0:.00,2:.25,6:.18,10:.32,14:.12
|
||||
```
|
||||
|
||||
Harmonic field:
|
||||
|
||||
```aqua
|
||||
chords name=prog root=110 scale=minor progression=0,6,3,5 voicing=0,2,4 paths=/chords/prog/root,/chords/prog/third,/chords/prog/fifth step=bar
|
||||
mix name=pad points=0:.08,4:.18,8:.11,12:.24,16:.08
|
||||
```
|
||||
|
||||
Groove hierarchy:
|
||||
|
||||
```aqua
|
||||
sequence name=kick pattern=x...x..x....x... step=.125 high=1 low=0
|
||||
sequence name=snare pattern=....x.......x... step=.125 high=.8 low=0
|
||||
sequence name=hat pattern=x.x.x.xx.x.x.xxx step=.125 high=.18 low=.03
|
||||
```
|
||||
|
||||
Production automation:
|
||||
|
||||
```aqua
|
||||
mix name=bass points=0:.20,4:.26,8:.14,12:.31,16:.18
|
||||
mix name=air points=0:.02,4:.05,8:.03,12:.07,16:.02
|
||||
```
|
||||
|
||||
## Composition Moves
|
||||
|
||||
- Repeat with change: keep one parameter stable while another evolves. Examples:
|
||||
same rhythm with different degrees, same degrees with a denser gate, same pad
|
||||
chord with brighter filter motion.
|
||||
- Call and response: a lead phrase should leave space for bass, percussion,
|
||||
chord stab, or texture answer.
|
||||
- Register contrast: keep bass low, lead in a bounded melodic register, and pads
|
||||
wide but not louder than the role carrying attention.
|
||||
- Section contrast: intro, main groove, break, rise, drop, and outro can be
|
||||
represented by lane gain curves before timbre gets fancy.
|
||||
- Energy contour: density, brightness, loudness, and rhythmic subdivision are
|
||||
separate levers. Move one or two deliberately.
|
||||
|
||||
## Digital Production Moves
|
||||
|
||||
- Attack/body/tail: split percussive sounds into transient click/skin and tonal
|
||||
body; filter each component differently.
|
||||
- Subtractive shaping: start rich or noisy, then use filters/envelopes to carve
|
||||
the useful band. Do not confuse raw oscillator choice with final timbre.
|
||||
- Additive shaping: build sustained tones from harmonic relationships, then
|
||||
automate gain/brightness slowly.
|
||||
- Modulation: use LFO/tremolo/FM/AM for motion, but keep rate and depth tied to
|
||||
the song grid or expressive gesture.
|
||||
- Space and air: model ambience as low-gain shaped texture or delayed motion,
|
||||
not as a full-band noise floor.
|
||||
|
||||
## Failure Modes
|
||||
|
||||
- A loop with no phrase contour is not melody.
|
||||
- A progression with no role using its chord tones is metadata, not harmony.
|
||||
- A drum grid with no body/skin separation becomes weak noisy ticking.
|
||||
- A pad with no entrance, exit, or brightness motion becomes wallpaper.
|
||||
- A mix with every lane always on has no foreground.
|
||||
- A source citation is not a lesson unless it lowers to a current AquaSynth
|
||||
action.
|
||||
|
||||
|
|
@ -265,3 +265,4 @@
|
|||
{"timestamp":"2026-05-31T22:25:00+01:00","topic":"composition-curriculum-redirect","claim":"The song CultCache run learned transferable sound-production role owners, but not composition. Next passes should require meter, progression or tonal center, note-degree sampling, instrument-lane gates, section events, composition-scale automation, and mix movement. AquaSynth now has small Strudel-ish sugar for `meter`, `sequence`, `chords`, and `mix`, all lowering to visible `param`/`curve` owners alongside existing `pattern` and `scale`.","evidence":"Trawl of pass-003 music-production quality standard, distillation report, and abstraction ledgers showed 56 of 75 official candidates had mode-collapse risk while ledgers repeatedly converged on role owners and sugar candidates. Added parser/test coverage for composition-scale sugar and redirected the song swarm prompt toward Composition Map evidence."}
|
||||
{"timestamp":"2026-05-31T23:15:00+01:00","topic":"producer-apprenticeship-curriculum-gate","claim":"Song curriculum admission must be owned by producer evidence and audible structure, not syntax attendance. `song-score` now records studio document coverage, producer musicianship, composition section score, template-loop risk, noise-percussion risk, and Aqua gap count; verdicts can fail as `weak-producer-missing` or `weak-slop-template`. `music-distill` promotes candidate and role doctrine only from rendered rows that clear the producer gate, while slop/noise/template rows become failure pressure.","evidence":"tools/IpaTrialWorker/Program.cs; tools/run-song-snippet-trial-swarm.ps1; docs/audio-doctrine.md; state/scratch.md"}
|
||||
{"timestamp":"2026-06-01T00:12:00+01:00","topic":"qdrant-music-knowledge-and-curator-pass","claim":"Music-production knowledge injection is now Qdrant-backed instead of lexical summary matching. `music-index` embeds full knowledge packets in `aquasynth_music_production_knowledge`; `music-search` defaults to Qdrant/Ollama retrieval and emits full owner, transfer rules, patterns, failure modes, and retrieved chunks. The song swarm now runs a dedicated knowledge-curator agent after each musician phase, and `music-distill` ingests `knowledge-curation.md` as curator-distillation doctrine pressure before indexing the next pass store.","evidence":"tools/IpaTrialWorker/Program.cs; tools/run-song-snippet-trial-swarm.ps1; docs/audio-doctrine.md; artifacts/parity/music-qdrant-smoke/20260601T000755/music-search.md"}
|
||||
{"timestamp":"2026-06-01T00:22:00+01:00","topic":"music-production-manual-ingestion","claim":"Fresh music knowledge stores now include repo-native manuals before agent-derived pressure. `docs/music-production-knowledge/aqua-dsp-usage-manual.md` teaches AquaSynth composition/DSP lowering, and `docs/music-production-knowledge/open-music-theory-production-distill.md` distills open music theory and digital production sources into actionable AquaSynth patterns. `music-distill` ingests these as `manual` documents, and Qdrant search retrieves them as full context packets.","evidence":"docs/music-production-knowledge/aqua-dsp-usage-manual.md; docs/music-production-knowledge/open-music-theory-production-distill.md; tools/IpaTrialWorker/Program.cs; artifacts/parity/manual-knowledge-smoke/20260601T001932/music-search.md"}
|
||||
|
|
|
|||
|
|
@ -1969,3 +1969,17 @@ Next likely slice:
|
|||
- `music-distill` ingests those curator files as `curator-distillation`
|
||||
documents, then the pass indexes the resulting `.cc` into Qdrant before the
|
||||
next phase uses it.
|
||||
|
||||
2026-06-01 manual/textbook music curriculum slice:
|
||||
|
||||
- Added repo-native manuals under `docs/music-production-knowledge/`:
|
||||
`aqua-dsp-usage-manual.md` and
|
||||
`open-music-theory-production-distill.md`.
|
||||
- `music-distill` now ingests those manuals as `manual` knowledge documents in
|
||||
every fresh music `.cc`, so musician agents retrieve AquaSynth DSP usage,
|
||||
music theory, arrangement, groove, harmony, melody, production, and failure
|
||||
modes before prior-run candidate pressure.
|
||||
- Smoke proof: `artifacts/parity/manual-knowledge-smoke/20260601T001932`
|
||||
produced a 16-document knowledge store with 2 manuals, indexed it into
|
||||
Qdrant, and `music-search` retrieved the AquaSynth DSP manual with
|
||||
`retrieval: qdrant-ollama`.
|
||||
|
|
|
|||
|
|
@ -1957,6 +1957,11 @@ static IEnumerable<MusicProductionKnowledgeDocument> BuildMusicKnowledgeDocument
|
|||
{
|
||||
yield return curatorDocument;
|
||||
}
|
||||
|
||||
foreach (var manualDocument in MusicManualDocuments(created))
|
||||
{
|
||||
yield return manualDocument;
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<MusicProductionKnowledgeDocument> MusicRoleDocuments(IReadOnlyList<SongSummaryRow> rendered, string created)
|
||||
|
|
@ -2204,6 +2209,102 @@ static IEnumerable<MusicProductionKnowledgeDocument> MusicCuratorDocuments(strin
|
|||
}
|
||||
}
|
||||
|
||||
static IEnumerable<MusicProductionKnowledgeDocument> MusicManualDocuments(string created)
|
||||
{
|
||||
var manualRoot = Path.Combine(Directory.GetCurrentDirectory(), "docs", "music-production-knowledge");
|
||||
if (!Directory.Exists(manualRoot))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var manual in Directory.EnumerateFiles(manualRoot, "*.md", SearchOption.TopDirectoryOnly).Order(StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
var text = ReadBoundedText(manual, 12000);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var id = $"music-manual-{SafeName(Path.GetFileNameWithoutExtension(manual))}-{StableUuid(manual)[..8]}";
|
||||
var topic = ManualField(text, "topic") ?? Path.GetFileNameWithoutExtension(manual).Replace('-', ' ');
|
||||
var tier = ManualField(text, "tier") ?? "manual-doctrine";
|
||||
yield return new MusicProductionKnowledgeDocument(
|
||||
id,
|
||||
"manual",
|
||||
topic,
|
||||
tier,
|
||||
LinesAfterHeading(text, "Owner", 900).DefaultIfEmpty("Manual owns reusable music-production knowledge for AquaSynth agents.").First(),
|
||||
text,
|
||||
LinesAfterHeading(text, "Transfer Rules", 16).ToArray(),
|
||||
LinesContaining(text, "meter ", "sequence ", "scale ", "chords ", "mix ", "voice ", "texture ", "source_port", "layer ", "harmonics ", "spectrum ").Take(24).ToArray(),
|
||||
LinesAfterHeading(text, "Failure Modes", 16).ToArray(),
|
||||
[],
|
||||
[],
|
||||
[new SpeechScoreMetric("manual_chars", text.Length, 0)],
|
||||
[manual],
|
||||
created);
|
||||
}
|
||||
}
|
||||
|
||||
static string? ManualField(string text, string field)
|
||||
{
|
||||
var prefix = $"{field}:";
|
||||
return text.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.FirstOrDefault(line => line.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))?
|
||||
.Substring(prefix.Length)
|
||||
.Trim();
|
||||
}
|
||||
|
||||
static IEnumerable<string> LinesAfterHeading(string text, string heading, int maxItemsOrChars)
|
||||
{
|
||||
var lines = text.Split(['\r', '\n']);
|
||||
var start = Array.FindIndex(lines, line => line.Trim().Equals($"## {heading}", StringComparison.OrdinalIgnoreCase));
|
||||
if (start < 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
var collected = new List<string>();
|
||||
for (var index = start + 1; index < lines.Length; index++)
|
||||
{
|
||||
var line = lines[index].Trim();
|
||||
if (line.StartsWith("## ", StringComparison.Ordinal))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith("- ", StringComparison.Ordinal))
|
||||
{
|
||||
collected.Add(line[2..].Trim());
|
||||
}
|
||||
else if (!line.StartsWith("```", StringComparison.Ordinal))
|
||||
{
|
||||
collected.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxItemsOrChars > 32)
|
||||
{
|
||||
var paragraph = TrimForReport(string.Join(' ', collected), maxItemsOrChars);
|
||||
if (!string.IsNullOrWhiteSpace(paragraph))
|
||||
{
|
||||
yield return paragraph;
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var item in collected.Take(maxItemsOrChars))
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
static IReadOnlyList<MusicKnowledgeHit> RankMusicKnowledge(IReadOnlyList<MusicProductionKnowledgeDocument> documents, string query, int limit, string retrievalMode = "lexical")
|
||||
{
|
||||
var terms = ExpandTerms(Tokenize(query)).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ for ($pass = 1; $pass -le $Passes; $pass++) {
|
|||
"--store",
|
||||
$latestMusicKnowledgeStore,
|
||||
"--query",
|
||||
"producer brief listening journal actionable composition arrangement groove harmony melody bass drums syrinx subtractive additive pad texture mix automation failure novelty AquaSynth",
|
||||
"AquaSynth DSP manual music theory production arrangement groove harmony melody bass drums syrinx subtractive additive pad texture mix automation failure novelty",
|
||||
"--limit",
|
||||
"40",
|
||||
"--require-vector",
|
||||
|
|
|
|||
Loading…
Reference in a new issue