Score song instruments by owned roles
This commit is contained in:
parent
ce317de571
commit
5d3a81a1f1
15 changed files with 522 additions and 38 deletions
|
|
@ -71,9 +71,9 @@ published packages.
|
|||
- `AquaSynthNativeCompiler` remains the lower native `libfaust` compiler
|
||||
machinery behind that boundary.
|
||||
- `BuiltInScripts.ReferenceScripts()` carries readable SFXR, BFXR-flavored,
|
||||
808, FM bell, wobble bass, and advanced layered patches. They are stable
|
||||
references for testing and for judging whether the DSL can express useful
|
||||
sound designs cleanly.
|
||||
808, FM bell, wobble bass, syrinx-voice, subtractive-drum, additive/PAD, and
|
||||
advanced layered patches. They are stable references for testing and for
|
||||
judging whether the DSL can express useful sound designs cleanly.
|
||||
- `SfxrParams`, `PatchScriptScoring`, `AudioAnalyzer`, and `Presets` carry the
|
||||
reusable AquaSynth-rs-side analysis, scoring, SFXR, and preset tools.
|
||||
|
||||
|
|
|
|||
|
|
@ -333,6 +333,14 @@ voice for scene noise. Full-duration raw `wave=noise` beds with broad filters
|
|||
are failed evidence: they sound like broken subtractive synthesis because that
|
||||
is exactly what they are.
|
||||
|
||||
Song-scene instrument roles are scored as curriculum evidence. Voice-like
|
||||
leads should prefer syrinx/acoustic source ownership with pressure/opening
|
||||
motion and radiation shaping; percussion should prefer subtractive pitched body
|
||||
plus filtered noise skin; pads, beds, and drones should prefer additive/PAD
|
||||
banks through `layer`, `harmonics`, and `spectrum`. Simple oscillator blips
|
||||
without one of these owners are chip-distress-risk contrast material, not a
|
||||
strong lesson for the music generator.
|
||||
|
||||
Do not confuse high metric agreement with musical success. The game context,
|
||||
the reference sound, and the user’s ear still outrank the spreadsheet. Annoying,
|
||||
but civilization has survived worse.
|
||||
|
|
|
|||
47
patches/advanced/additive-pad.aqua
Normal file
47
patches/advanced/additive-pad.aqua
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# additive-pad
|
||||
# Family: advanced
|
||||
# Source: BuiltInScripts.ReferenceScripts
|
||||
# Notes: Additive body plus PAD spectral halo; slow controls own bloom and air.
|
||||
|
||||
patch
|
||||
gain=0.74
|
||||
soft_clip=true
|
||||
|
||||
param name=bloom path=/macro/bloom default=.72 min=0 max=1 step=.001
|
||||
param name=air path=/macro/air default=.12 min=0 max=.3 step=.001
|
||||
|
||||
mod name=slow_bloom
|
||||
wave=sine
|
||||
hz=.13
|
||||
gain=.045
|
||||
pitch=.006
|
||||
lpf=.08
|
||||
|
||||
layer name=body engine=add min_key=36 max_key=96 gain=.14 env=rl rates=.35,.62,1.1,1.4 levels=1,.92,.84,0 curves=lin,exp,lin,lin gate=2.6
|
||||
layer name=halo engine=pad min_key=48 max_key=108 gain=.10 env=rl rates=.55,.8,1.35,1.8 levels=.85,.95,.78,0 curves=lin,exp,lin,lin gate=3.0
|
||||
|
||||
harmonics layer=body root=110 partials=1:.12,2:.055,3:.032,4:.018,5:.012
|
||||
spectrum layer=halo root=110 freq=220 spread=.008 pad_mode=bandwidth pad_bandwidth=520 pad_bwscale=2 pad_profile=gaussian:88:4:10:42:127:sine:mult:72:24:yes:full partials=1:.08,1.5:.026,2:.022,2.5:.014,3:.011
|
||||
|
||||
voice
|
||||
layer=body
|
||||
wave=sine
|
||||
freq=110
|
||||
gain=.08
|
||||
attack=.32
|
||||
sustain=1.8
|
||||
decay=1.5
|
||||
lpf=@/macro/bloom
|
||||
hpf=.015
|
||||
|
||||
voice
|
||||
layer=halo
|
||||
wave=noise
|
||||
freq=1800
|
||||
gain=@/macro/air
|
||||
attack=.7
|
||||
sustain=1.6
|
||||
decay=1.9
|
||||
noise=.72
|
||||
hpf=.58
|
||||
lpf=.34
|
||||
63
patches/advanced/subtractive-drums.aqua
Normal file
63
patches/advanced/subtractive-drums.aqua
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# subtractive-drums
|
||||
# Family: advanced
|
||||
# Source: BuiltInScripts.ReferenceScripts
|
||||
# Notes: Filtered subtractive drum voices with pitched bodies, noise skins, and bright metal.
|
||||
|
||||
patch
|
||||
gain=0.72
|
||||
soft_clip=true
|
||||
|
||||
defaults
|
||||
drive=.14
|
||||
sustain_level=.62
|
||||
|
||||
voice
|
||||
wave=sine
|
||||
freq=58
|
||||
gain=.82
|
||||
sustain=.038
|
||||
decay=.38
|
||||
pitch_ramp=-3.6
|
||||
min_freq=32
|
||||
lpf=.78
|
||||
lpf_q=.28
|
||||
|
||||
voice
|
||||
wave=noise
|
||||
freq=1700
|
||||
gain=.26
|
||||
sustain=.018
|
||||
decay=.18
|
||||
noise=.95
|
||||
hpf=.48
|
||||
bpf=.38
|
||||
bpf_q=2.2
|
||||
|
||||
voice
|
||||
wave=triangle
|
||||
freq=188
|
||||
gain=.12
|
||||
sustain=.026
|
||||
decay=.13
|
||||
pitch_ramp=-1.05
|
||||
lpf=.52
|
||||
|
||||
voice
|
||||
wave=noise
|
||||
freq=8200
|
||||
gain=.11
|
||||
sustain=.005
|
||||
decay=.052
|
||||
noise=1
|
||||
hpf=.88
|
||||
lpf=.20
|
||||
|
||||
voice
|
||||
wave=square
|
||||
freq=540
|
||||
gain=.08
|
||||
sustain=.035
|
||||
decay=.16
|
||||
duty=.42
|
||||
hpf=.18
|
||||
lpf=.72
|
||||
40
patches/advanced/syrinx-voice.aqua
Normal file
40
patches/advanced/syrinx-voice.aqua
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# syrinx-voice
|
||||
# Family: advanced
|
||||
# Source: BuiltInScripts.ReferenceScripts
|
||||
# Notes: Graph-native paired-labium voice with modulated pressure, opening, and beak radiation.
|
||||
|
||||
patch
|
||||
gain=0.46
|
||||
soft_clip=true
|
||||
|
||||
param path=/voice/left/pressure default=.78 min=0 max=1.5 step=.001 rate=audio
|
||||
param path=/voice/right/pressure default=.66 min=0 max=1.5 step=.001 rate=audio
|
||||
param path=/voice/left/opening default=.23 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/right/opening default=.19 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/left/tension default=.43 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/right/tension default=.50 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/beak/opening default=.88 min=0 max=1.5 step=.001
|
||||
|
||||
curve name=left_phrase_pressure path=/voice/left/pressure points=0:.05,.04:.82,.28:.76,.56:.88,.92:.24 mode=blend depth=.92 rate=audio
|
||||
curve name=right_phrase_pressure path=/voice/right/pressure points=0:.03,.06:.68,.24:.74,.50:.58,.92:.18 mode=blend depth=.92 rate=audio
|
||||
curve name=left_phrase_opening path=/voice/left/opening points=0:.02,.035:.24,.46:.18,.92:.05 mode=blend depth=.85 rate=audio
|
||||
curve name=right_phrase_opening path=/voice/right/opening points=0:.02,.04:.20,.42:.15,.92:.05 mode=blend depth=.85 rate=audio
|
||||
curve name=beak_phrase path=/voice/beak/opening points=0:.34,.08:.94,.52:1.08,.92:.58 mode=blend depth=.72
|
||||
gesture name=syrinx_phrase curves=left_phrase_pressure,right_phrase_pressure,left_phrase_opening,right_phrase_opening,beak_phrase depth=1
|
||||
|
||||
path name=left_bronchus length_cm=3.8 diameters=.22,.30,.36,.42
|
||||
path name=right_bronchus length_cm=3.6 diameters=.20,.28,.34,.40
|
||||
path name=trachea length_cm=8.4 diameters=.38,.48,.56,.46
|
||||
|
||||
source_port name=left_labium path=left_bronchus kind=syrinx model=tissue_valve position=0 pressure=@/voice/left/pressure tension=@/voice/left/tension opening=@/voice/left/opening noise=.018 impedance=.82 mass=.30 damping=.14 stiffness=.028 saturation=.88 flow_scale=1.15 tissue_loss=.18 aperture_shape=.40 flow_loss=.35 load_coupling=.42 rest_opening=.024
|
||||
source_port name=right_labium path=right_bronchus kind=syrinx model=tissue_valve position=0 pressure=@/voice/right/pressure tension=@/voice/right/tension opening=@/voice/right/opening noise=.016 balance=.94 impedance=.78 mass=.32 damping=.16 stiffness=.032 saturation=.88 flow_scale=1.08 tissue_loss=.20 aperture_shape=.40 flow_loss=.35 load_coupling=.42 rest_opening=.024
|
||||
|
||||
terminal name=left_merge path=left_bronchus position=1 kind=junction area_scale=1
|
||||
terminal name=right_merge path=right_bronchus position=1 kind=junction area_scale=1
|
||||
terminal name=trachea_base path=trachea position=0 kind=junction area_scale=1
|
||||
connect name=syrinx_merge terminals=left_merge,right_merge,trachea_base law=area_scatter coupling=1
|
||||
|
||||
radiation_port name=beak path=trachea kind=beak model=beak position=1 opening=@/voice/beak/opening reflection=-.72 loss=.98
|
||||
wave_clock name=syrinx_clock strategy=linear max_delay=2048 smoothing_ms=2
|
||||
acoustic_network name=singing_syrinx path=trachea wave_clock=syrinx_clock sources=left_labium,right_labium radiation=beak terminals=left_merge,right_merge,trachea_base connections=syrinx_merge
|
||||
acoustic_voice network=singing_syrinx freq=920 gain=.30 sustain=.92 decay=.12 vibrato=.008 vibrato_hz=5.2 lpf=.82 hpf=.03 bpf=.36 bpf_q=1.5
|
||||
Binary file not shown.
|
|
@ -37,6 +37,11 @@ entries:
|
|||
name: "aurora-pad"
|
||||
source: "BuiltInScripts.ReferenceScripts"
|
||||
notes: "Stock reference patch exported from the in-code catalog."
|
||||
- path: patches/advanced/additive-pad.aqua
|
||||
family: advanced
|
||||
name: "additive-pad"
|
||||
source: "BuiltInScripts.ReferenceScripts"
|
||||
notes: "Additive body plus PAD spectral halo; slow controls own bloom and air."
|
||||
- path: patches/advanced/bird-syrinx.aqua
|
||||
family: advanced
|
||||
name: "bird-syrinx"
|
||||
|
|
@ -57,6 +62,16 @@ entries:
|
|||
name: "ritual-sequence"
|
||||
source: "BuiltInScripts.ReferenceScripts"
|
||||
notes: "Stock reference patch exported from the in-code catalog."
|
||||
- path: patches/advanced/subtractive-drums.aqua
|
||||
family: advanced
|
||||
name: "subtractive-drums"
|
||||
source: "BuiltInScripts.ReferenceScripts"
|
||||
notes: "Filtered subtractive drum voices with pitched bodies, noise skins, and bright metal."
|
||||
- path: patches/advanced/syrinx-voice.aqua
|
||||
family: advanced
|
||||
name: "syrinx-voice"
|
||||
source: "BuiltInScripts.ReferenceScripts"
|
||||
notes: "Graph-native paired-labium voice with modulated pressure, opening, and beak radiation."
|
||||
- path: patches/bfxr/coin-spark.aqua
|
||||
family: bfxr
|
||||
name: "coin-spark"
|
||||
|
|
|
|||
|
|
@ -602,6 +602,8 @@ public static class BuiltInScripts
|
|||
""")
|
||||
];
|
||||
|
||||
public static readonly IReadOnlyList<string> InstrumentNames = ["syrinx-voice", "subtractive-drums", "additive-pad"];
|
||||
|
||||
public static readonly IReadOnlyList<string> AdvancedNames = ["aurora-pad", "machine-breath", "glass-creature", "ritual-sequence"];
|
||||
|
||||
public static readonly IReadOnlyList<string> Dx7StyleNames = ["algo32-additive-organ", "algo8-bright-pair", "public-domain-mc-mm-5-3"];
|
||||
|
|
@ -966,6 +968,157 @@ public static class BuiltInScripts
|
|||
formant_mix=0.3
|
||||
""";
|
||||
|
||||
public const string SyrinxVoiceInstrument = """
|
||||
patch
|
||||
gain=0.46
|
||||
soft_clip=true
|
||||
|
||||
param path=/voice/left/pressure default=.78 min=0 max=1.5 step=.001 rate=audio
|
||||
param path=/voice/right/pressure default=.66 min=0 max=1.5 step=.001 rate=audio
|
||||
param path=/voice/left/opening default=.23 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/right/opening default=.19 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/left/tension default=.43 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/right/tension default=.50 min=0 max=1 step=.001 rate=audio
|
||||
param path=/voice/beak/opening default=.88 min=0 max=1.5 step=.001
|
||||
|
||||
curve name=left_phrase_pressure path=/voice/left/pressure points=0:.05,.04:.82,.28:.76,.56:.88,.92:.24 mode=blend depth=.92 rate=audio
|
||||
curve name=right_phrase_pressure path=/voice/right/pressure points=0:.03,.06:.68,.24:.74,.50:.58,.92:.18 mode=blend depth=.92 rate=audio
|
||||
curve name=left_phrase_opening path=/voice/left/opening points=0:.02,.035:.24,.46:.18,.92:.05 mode=blend depth=.85 rate=audio
|
||||
curve name=right_phrase_opening path=/voice/right/opening points=0:.02,.04:.20,.42:.15,.92:.05 mode=blend depth=.85 rate=audio
|
||||
curve name=beak_phrase path=/voice/beak/opening points=0:.34,.08:.94,.52:1.08,.92:.58 mode=blend depth=.72
|
||||
gesture name=syrinx_phrase curves=left_phrase_pressure,right_phrase_pressure,left_phrase_opening,right_phrase_opening,beak_phrase depth=1
|
||||
|
||||
path name=left_bronchus length_cm=3.8 diameters=.22,.30,.36,.42
|
||||
path name=right_bronchus length_cm=3.6 diameters=.20,.28,.34,.40
|
||||
path name=trachea length_cm=8.4 diameters=.38,.48,.56,.46
|
||||
|
||||
source_port name=left_labium path=left_bronchus kind=syrinx model=tissue_valve position=0 pressure=@/voice/left/pressure tension=@/voice/left/tension opening=@/voice/left/opening noise=.018 impedance=.82 mass=.30 damping=.14 stiffness=.028 saturation=.88 flow_scale=1.15 tissue_loss=.18 aperture_shape=.40 flow_loss=.35 load_coupling=.42 rest_opening=.024
|
||||
source_port name=right_labium path=right_bronchus kind=syrinx model=tissue_valve position=0 pressure=@/voice/right/pressure tension=@/voice/right/tension opening=@/voice/right/opening noise=.016 balance=.94 impedance=.78 mass=.32 damping=.16 stiffness=.032 saturation=.88 flow_scale=1.08 tissue_loss=.20 aperture_shape=.40 flow_loss=.35 load_coupling=.42 rest_opening=.024
|
||||
|
||||
terminal name=left_merge path=left_bronchus position=1 kind=junction area_scale=1
|
||||
terminal name=right_merge path=right_bronchus position=1 kind=junction area_scale=1
|
||||
terminal name=trachea_base path=trachea position=0 kind=junction area_scale=1
|
||||
connect name=syrinx_merge terminals=left_merge,right_merge,trachea_base law=area_scatter coupling=1
|
||||
|
||||
radiation_port name=beak path=trachea kind=beak model=beak position=1 opening=@/voice/beak/opening reflection=-.72 loss=.98
|
||||
wave_clock name=syrinx_clock strategy=linear max_delay=2048 smoothing_ms=2
|
||||
acoustic_network name=singing_syrinx path=trachea wave_clock=syrinx_clock sources=left_labium,right_labium radiation=beak terminals=left_merge,right_merge,trachea_base connections=syrinx_merge
|
||||
acoustic_voice network=singing_syrinx freq=920 gain=.30 sustain=.92 decay=.12 vibrato=.008 vibrato_hz=5.2 lpf=.82 hpf=.03 bpf=.36 bpf_q=1.5
|
||||
""";
|
||||
|
||||
public const string SubtractiveDrumsInstrument = """
|
||||
patch
|
||||
gain=0.72
|
||||
soft_clip=true
|
||||
|
||||
defaults
|
||||
drive=.14
|
||||
sustain_level=.62
|
||||
|
||||
voice
|
||||
wave=sine
|
||||
freq=58
|
||||
gain=.82
|
||||
sustain=.038
|
||||
decay=.38
|
||||
pitch_ramp=-3.6
|
||||
min_freq=32
|
||||
lpf=.78
|
||||
lpf_q=.28
|
||||
|
||||
voice
|
||||
wave=noise
|
||||
freq=1700
|
||||
gain=.26
|
||||
sustain=.018
|
||||
decay=.18
|
||||
noise=.95
|
||||
hpf=.48
|
||||
bpf=.38
|
||||
bpf_q=2.2
|
||||
|
||||
voice
|
||||
wave=triangle
|
||||
freq=188
|
||||
gain=.12
|
||||
sustain=.026
|
||||
decay=.13
|
||||
pitch_ramp=-1.05
|
||||
lpf=.52
|
||||
|
||||
voice
|
||||
wave=noise
|
||||
freq=8200
|
||||
gain=.11
|
||||
sustain=.005
|
||||
decay=.052
|
||||
noise=1
|
||||
hpf=.88
|
||||
lpf=.20
|
||||
|
||||
voice
|
||||
wave=square
|
||||
freq=540
|
||||
gain=.08
|
||||
sustain=.035
|
||||
decay=.16
|
||||
duty=.42
|
||||
hpf=.18
|
||||
lpf=.72
|
||||
""";
|
||||
|
||||
public const string AdditivePadInstrument = """
|
||||
patch
|
||||
gain=0.74
|
||||
soft_clip=true
|
||||
|
||||
param name=bloom path=/macro/bloom default=.72 min=0 max=1 step=.001
|
||||
param name=air path=/macro/air default=.12 min=0 max=.3 step=.001
|
||||
|
||||
mod name=slow_bloom
|
||||
wave=sine
|
||||
hz=.13
|
||||
gain=.045
|
||||
pitch=.006
|
||||
lpf=.08
|
||||
|
||||
layer name=body engine=add min_key=36 max_key=96 gain=.14 env=rl rates=.35,.62,1.1,1.4 levels=1,.92,.84,0 curves=lin,exp,lin,lin gate=2.6
|
||||
layer name=halo engine=pad min_key=48 max_key=108 gain=.10 env=rl rates=.55,.8,1.35,1.8 levels=.85,.95,.78,0 curves=lin,exp,lin,lin gate=3.0
|
||||
|
||||
harmonics layer=body root=110 partials=1:.12,2:.055,3:.032,4:.018,5:.012
|
||||
spectrum layer=halo root=110 freq=220 spread=.008 pad_mode=bandwidth pad_bandwidth=520 pad_bwscale=2 pad_profile=gaussian:88:4:10:42:127:sine:mult:72:24:yes:full partials=1:.08,1.5:.026,2:.022,2.5:.014,3:.011
|
||||
|
||||
voice
|
||||
layer=body
|
||||
wave=sine
|
||||
freq=110
|
||||
gain=.08
|
||||
attack=.32
|
||||
sustain=1.8
|
||||
decay=1.5
|
||||
lpf=@/macro/bloom
|
||||
hpf=.015
|
||||
|
||||
voice
|
||||
layer=halo
|
||||
wave=noise
|
||||
freq=1800
|
||||
gain=@/macro/air
|
||||
attack=.7
|
||||
sustain=1.6
|
||||
decay=1.9
|
||||
noise=.72
|
||||
hpf=.58
|
||||
lpf=.34
|
||||
""";
|
||||
|
||||
public static readonly IReadOnlyList<(string Name, string Script)> InstrumentReferenceScripts =
|
||||
[
|
||||
("syrinx-voice", SyrinxVoiceInstrument),
|
||||
("subtractive-drums", SubtractiveDrumsInstrument),
|
||||
("additive-pad", AdditivePadInstrument)
|
||||
];
|
||||
|
||||
public static readonly IReadOnlyList<(string Name, string Script)> AdvancedReferenceScripts =
|
||||
[
|
||||
("aurora-pad", """
|
||||
|
|
@ -1158,6 +1311,7 @@ public static class BuiltInScripts
|
|||
yield return ("pink-trombone", "current-aquasynth-graph", PinkTromboneProxy);
|
||||
foreach (var item in ReferenceRebuildCatalog.Dx7Rebuilds) yield return ("dx7", item.Name, item.Script);
|
||||
foreach (var item in ReferenceRebuildCatalog.ZynRebuilds) yield return ("zynaddsubfx", item.Name, item.Script);
|
||||
foreach (var item in InstrumentReferenceScripts) yield return ("advanced", item.Name, item.Script);
|
||||
foreach (var item in AdvancedReferenceScripts) yield return ("advanced", item.Name, item.Script);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,11 +139,14 @@ public static class CultCachePatchDocumentCatalog
|
|||
new("patches/808/kick.aqua", "808", "kick", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/808/snare.aqua", "808", "snare", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/808/tom.aqua", "808", "tom", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/advanced/additive-pad.aqua", "advanced", "additive-pad", "BuiltInScripts.ReferenceScripts", "Additive body plus PAD spectral halo; slow controls own bloom and air."),
|
||||
new("patches/advanced/aurora-pad.aqua", "advanced", "aurora-pad", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/advanced/bird-syrinx.aqua", "advanced", "bird-syrinx", "Graph-native syrinx patch", "Paired labial source-port bird voice for differentiable training and audition."),
|
||||
new("patches/advanced/glass-creature.aqua", "advanced", "glass-creature", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/advanced/machine-breath.aqua", "advanced", "machine-breath", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/advanced/ritual-sequence.aqua", "advanced", "ritual-sequence", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/advanced/subtractive-drums.aqua", "advanced", "subtractive-drums", "BuiltInScripts.ReferenceScripts", "Filtered subtractive drum voices with pitched bodies, noise skins, and bright metal."),
|
||||
new("patches/advanced/syrinx-voice.aqua", "advanced", "syrinx-voice", "BuiltInScripts.ReferenceScripts", "Graph-native paired-labium voice with modulated pressure, opening, and beak radiation."),
|
||||
new("patches/bfxr/coin-spark.aqua", "bfxr", "coin-spark", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/bfxr/portal-chirp.aqua", "bfxr", "portal-chirp", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
new("patches/bfxr/shield-pop.aqua", "bfxr", "shield-pop", "BuiltInScripts.ReferenceScripts", "Stock reference patch exported from the in-code catalog."),
|
||||
|
|
|
|||
|
|
@ -35,24 +35,7 @@ public static class Presets
|
|||
|
||||
public static SynthPatch AquaSynthVoice()
|
||||
{
|
||||
var voice = Simple(new Oscillator(Waveform.Triangle, 220), new Envelope(0.018f, 0, 0.9259259f, 0.28f), 0.34f, 0.1944f) with
|
||||
{
|
||||
Pitch = new PitchMotion(VibratoDepth: 0.018f, VibratoHz: 5.6f),
|
||||
Color = new VoiceColor(0.035f, 0.18f, 0.04f, 0.12f, 4.2f, 0.68f),
|
||||
Formants =
|
||||
[
|
||||
new Formant(520, 85, 0.9f),
|
||||
new Formant(1380, 180, 1),
|
||||
new Formant(2550, 300, 0.42f)
|
||||
]
|
||||
};
|
||||
|
||||
return new SynthPatch
|
||||
{
|
||||
Voices = [voice],
|
||||
Gain = 0.95f,
|
||||
SoftClip = true
|
||||
};
|
||||
return PatchScript.Parse(BuiltInScripts.SyrinxVoiceInstrument);
|
||||
}
|
||||
|
||||
public static SynthPatch Sfxr(string name) =>
|
||||
|
|
|
|||
|
|
@ -256,3 +256,4 @@
|
|||
{"date":"2026-05-31","area":"song-curriculum-dataset-distillation","lesson":"The song trial loop trains the dataset, not a single patch. Each agent now gets paired song challenges and must write one patch per target; every patch, hypothesis, metric, challenge artifact, evaluator fact, and distillation document becomes curriculum evidence in CultCache/Qdrant. The post-pass distiller writes pruned `.cc` stores with reusable scene roles, transfer rules, failure patterns, kept trials, dropped noise, and aggregate metrics, and retrieval links those distillation chunks back to kept scored trial IDs so future zero-shot production agents can actually receive the distilled context.","evidence":"tools/run-song-snippet-trial-swarm.ps1; tools/IpaTrialWorker/Program.cs; src/AquaSynth.Core/IpaTrialResults.cs; state/scratch.md"}
|
||||
{"date":"2026-05-31","area":"song-curriculum-paired-pass","lesson":"A paired song-curriculum pass completed with five agents, two targets per agent, one patch per target, ten scored trials, ten target evidence bundles, sixty Qdrant chunks, and a distilled `.cc` store. Metrics were all `pressure`: best log-mel cosine `0.502128`, mean `0.377955`, worst `0.27853`, mean audio score `0.339432`. Distillation kept all ten and identified clocked dust/hat texture plus rubber/sub bass as reusable roles, while preserving the shaped-noise owner requirement as a transfer rule rather than letting static white hiss back into the curriculum.","evidence":"artifacts/parity/song-snippet-swarms/20260531T074935298/song-trial-results.cc; artifacts/parity/song-snippet-swarms/20260531T074935298/pass-001/distillation-report.md; artifacts/parity/song-snippet-swarms/20260531T074935298/pass-001/vector-index-after.md; artifacts/parity/song-snippet-swarms/20260531T074935298/pass-001/semantic-search-after.md"}
|
||||
{"date":"2026-05-31","area":"song-curriculum-playlists-and-invalid-candidates","lesson":"Song curriculum passes now publish a playable top-candidate playlist per pass and keep invalid agent syntax as negative evidence instead of aborting the swarm. A two-pass paired run produced pass-001 best cosine `0.386098` with 8 playable candidates and 2 `render-failed` syntax casualties, then pass-002 improved to best cosine `0.502435`, mean cosine `0.352907`, 10 playable candidates, and 8 pressure verdicts after reading distilled pass-1 evidence. Playlist reports filter to candidates with actual rendered WAVs and list skipped non-playable failures separately.","evidence":"tools/run-song-snippet-trial-swarm.ps1; tools/IpaTrialWorker/Program.cs; artifacts/parity/song-snippet-swarms/20260531T084455803/pass-001/top-scoring-candidates.m3u; artifacts/parity/song-snippet-swarms/20260531T084455803/pass-002/top-scoring-candidates.m3u; artifacts/parity/song-snippet-swarms/20260531T084455803/pass-002/distillation-report.md"}
|
||||
{"date":"2026-05-31","area":"song-instrument-owner-scoring","lesson":"The song curriculum harness must teach instrument ownership, not only spectrogram proximity. `song-score` now records syrinx-voice, subtractive-drum, additive/PAD, musical-instrument-score, and chip-distress-risk metrics for every candidate; swarm prompts require voice-like leads to prefer syrinx/acoustic sources, percussion to prefer subtractive pitched body plus filtered noise skin, and pads/beds to prefer additive/PAD banks. Distillation ranking now rewards owned roles and demotes chip-distress-risk candidates unless they are explicit contrast evidence.","evidence":"tools/IpaTrialWorker/Program.cs; tools/run-song-snippet-trial-swarm.ps1; docs/audio-doctrine.md; patches/advanced/syrinx-voice.aqua; patches/advanced/subtractive-drums.aqua; patches/advanced/additive-pad.aqua; artifacts/parity/song-instrument-metric-smoke/smoke/summary.csv"}
|
||||
|
|
|
|||
|
|
@ -1802,3 +1802,30 @@ Next likely slice:
|
|||
`0.220027`, and 2 render-failed syntax casualties. Pass 2 used distilled
|
||||
pass-1 evidence, produced 10 playable candidates, best cosine `0.502435`,
|
||||
mean cosine `0.352907`, and 8 pressure verdicts.
|
||||
|
||||
2026-05-31 song instrument-owner correction:
|
||||
|
||||
- User clarified the "8-bit distress signals" problem is the procedural song
|
||||
scoring/curriculum harness, not only the stock patch catalog. The harness is
|
||||
becoming the music generator's memory feeder through CultCache and Qdrant, so
|
||||
it must store instrument-role evidence, not just log-mel winners.
|
||||
- `song-score` now analyzes every candidate script and records
|
||||
`instrument_voice_syrinx`, `instrument_drum_subtractive`,
|
||||
`instrument_pad_additive`, `musical_instrument_score`, and
|
||||
`chip_distress_risk` metrics in the trial result. Verdict selection and
|
||||
distillation ranking now include this role evidence so simple oscillator blips
|
||||
cannot quietly train the future generator unless they are explicitly useful
|
||||
contrast.
|
||||
- `run-song-snippet-trial-swarm.ps1` now tells agents the role ownership rule:
|
||||
voice-like leads should use syrinx/acoustic source ports with pressure/opening
|
||||
motion; drums/transients should use subtractive pitched bodies plus filtered
|
||||
noise skins; pads/beds should use additive/PAD `layer`, `harmonics`, and
|
||||
`spectrum` banks. Ordinary voices remain helpers, not the main answer.
|
||||
- Added stock reference patches for `syrinx-voice`, `subtractive-drums`, and
|
||||
`additive-pad`, and changed `Presets.AquaSynthVoice()` to use the syrinx
|
||||
script instead of the old triangle/formant proxy. These are examples for the
|
||||
harness and agents, not a substitute for scoring ownership.
|
||||
- Smoke proof:
|
||||
`artifacts/parity/song-instrument-metric-smoke/smoke/summary.csv` records a
|
||||
syrinx candidate with `instrument_voice_syrinx=1`,
|
||||
`musical_instrument_score=0.34`, and `chip_distress_risk=0`.
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ live_invariants:
|
|||
- `IpaTrialOrchestrator.RunAsync` is the first local render/scoring worker for IPA trials. It generates candidate patches through `IpaGestureExperiment`, renders them through Faust, compares against local PT fixture references with `AudioAnalyzer`, writes WAV/report artifacts, and stores typed `IpaTrialResult` records in `ipa-trial-results.cc`. The five-seed trial run at `tests/AquaSynth.Dsl.Tests/bin/Debug/net10.0/artifacts/parity/ipa-trials/20260529T214127955/five-seed-trials` showed voiced vowels/nasals became audible only after primitive `SourcePort` lowering gained a true oscillatory voiced carrier; sibilants are pressure, plosives remain weak. Verification: opt-in IPA trial test passed, and focused `PatchScriptTests|IpaTrialResultsRoundTripThroughCultCache` pass 94/94.
|
||||
- External IPA exploration now has a worker/tool boundary. `tools/IpaTrialWorker` owns `seed`, `score`, `search`, `show`, and audit-only `dump` commands over the typed `.cc` trial-result store; `score` renders external Codex-authored `.aqua` candidates through `IpaTrialOrchestrator.RunCandidateScriptsAsync`, while `search` is the semantic retrieval organ for hypothesis agents. `IpaTrialResult` records now embed extracted primitive timeline facts from `ProbeTimelineReport` for contact closure/reservoir/release, source load/flow, branch admittance/exchanged flow, radiation boundary/output, path area/delay/energy, and passivity; `search`, `show`, `dump`, and summary CSV output surface release/radiation/passivity witnesses directly from the `.cc` record. `search` follows VoidBot's Qdrant shape: `.cc` records plus timeline facts and referenced local artifacts become evidence chunks, local Ollama `qwen3-embedding:0.6b` produces 1024-dim vectors, Qdrant collection `aquasynth_ipa_trial_results` stores stable SHA-256 UUID points with trial/candidate payload metadata, and the report surfaces vector scores, excerpts, tags, metric facts, timeline facts, contrast candidates, `class_focus`, per-hit `class_match`, and `show` commands. Qdrant is a derived index; CultCache remains truth, and lexical/metric search is fallback when the vector stack is unavailable. Retrieval tuning added phonetic class-affinity scoring and candidate-specific mixed-lane ownership so `mix-p` can support stop seams without every mixed candidate matching stop evidence. `tools/run-ipa-trial-loop.ps1` orchestrates external `codex exec` hypothesis/evaluator workers around that store. Source-edit-enabled rounds now allow agents to golf DSL syntax, parser/model records, Faust lowering, worker evidence surfaces, and tests when evidence points at a repeated owner failure; agents must write `source-change-plan.md`, and the loop runs a focused build before scoring. `hypotheses.md` is the hypothesis worker report of record; `hypothesis-agent.md` is only the external agent's final chat summary. The first loose source-edit round produced no source edits and no aggregate metric win, then exposed a deeper learning-loop fault: family ideas were rotated across unrelated targets instead of aligned to phonetic owners. Production prompts now pass the previous evaluation path into the hypothesizer, require `Previous Round Learning`, require `Target-Class Lane Plan`, forbid round-robin family assignment, and let the evaluator fail class alignment when family/target assignments do not match phonetic owner classes or explicit transfer-test mutations. Candidate reports must include a `Scene Voice Model` naming primary-articulatory, tract-noise, release/transient, background-room, and recording-condition voices, with general AquaSynth synth primitives allowed for helper scene voices but not accepted as articulation evidence unless lower-layer witnesses move. At least one scene/noise or recording-condition family in a source-golf round must implement real auxiliary `.aqua` `voice` declarations instead of satisfying scene modeling with prose. The active trial shape is five target sets of five phoneme lanes each: vowels, nasals/approximants, fricatives, stops, and mixed generalization. Candidate names are exactly `<targetId>__<family>__<hypothesis-name>.aqua`, with lowercase kebab-case family ids. Three dry external Codex smoke passes refined hypothesizer/evaluator prompts into exact 25-lane output, retrieval receipts, claim audits, evidence-quality ledgers/verdicts, and fail-closed evaluator compliance. A later five-pass prompt optimization showed the best science comes from fixed receipt packets plus constrained reasoning; production prompts now require contrast pairs, `show` metric values, primitive timeline facts/excerpts or explicit `missing`, class-consistent reference matrices, scene voice models, `X owns Y so Z remains true` owner sentences, at least five micro-sweep perturbations before a seam is actionable, and a novelty gate rejecting loudness/dressing-only families as loss-landscape novelty. Verification: focused builds/tests pass, old-store show compatibility passes, and a fresh one-candidate smoke under `artifacts/parity/ipa-timeline-fact-smoke/20260531T233217641` proves release/radiation/passivity facts persist and retrieve through Qdrant/Ollama.
|
||||
- Song-snippet parity now treats target analysis as CultMesh database evidence. `song-prepare` writes each 30-second clip's log-mel spectrogram CSV, per-band first/second derivative stats, RMS envelope, envelope autocorrelation, and analysis report. `song-score` upserts those as typed `SongChallengeEvidenceDocument` records in the same `.cc` store as `IpaTrialResult`, adds target metrics and `cultmesh://aquasynth/song-challenge-evidence/...` artifacts to every result, and `search/index` derive Qdrant chunks from the database records. `pattern` and `scale` DSL sugar are live authoring conveniences that lower into normal parameters and hold-loop curves; prompt agents may propose richer Strudel-like syntax, but candidate patches must use implemented syntax.
|
||||
- Song-scene scoring now records instrument-role ownership so the music-generator curriculum does not learn that simple oscillator blips are good instruments by default. `song-score` emits `instrument_voice_syrinx`, `instrument_drum_subtractive`, `instrument_pad_additive`, `musical_instrument_score`, and `chip_distress_risk`; verdict/distillation ranking rewards owned roles and demotes chip-distress-risk candidates unless preserved as contrast. Swarm prompts now require voice-like leads to prefer syrinx/acoustic sources with pressure/opening/radiation motion, percussion to prefer subtractive pitched bodies plus filtered noise skins, and pads/beds to prefer additive/PAD `layer`/`harmonics`/`spectrum` banks.
|
||||
- TurbulenceJet now includes a release-timed burst-noise component in addition to the deterministic pressure pulse, but a stronger trial barely moved papa; the source is not the main remaining articulation bottleneck. Graph radiation now mixes 30% raw boundary flow with 70% high-passed flow after local admittance weighting, down from the over-bright 15/85 blend. Latest radiation/source artifact under `artifacts/parity/pink-trombone-utterance-logmel/20260527T174236049`: mama/papa/thrombosis cosine 0.6578/0.7692/0.5585, rmsRatio 3.0006/2.6153/2.3488, articulation 0.1437/0.1173/0.1191. Static `closure-release` under `artifacts/parity/pink-trombone-logmel/20260527T174139661` has rmsRatio 0.9900 and speechBandRatio 0.0842. This is still not speaking; next pressure is true tract resonance/passive scattering and pressure storage, not more burst gain.
|
||||
- Same-path two-port area discontinuities now emit `graph_area_energy_in_*` and `graph_area_energy_out_*` probes alongside the three-port branch `graph_connection_energy_*` probes. Use these to inspect passivity and formant-body failures at the scatter sites rather than judging only final output loudness.
|
||||
- `FaustExportOptions.DebugProbeUi` wraps graph probe signals in Faust `vbargraph` UI controls under `/debug/...` without changing audio output arity. Native streaming Faust patches now separate writable controls from read-only probe zones and can read/snapshot probe values after `ProcessBlock`; use this for acoustic graph passivity/radiation inspection, leave it off for normal parity renders.
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ static async Task SongScoreAsync(Dictionary<string, string> options)
|
|||
|
||||
var candidateWav = Path.Combine(audioDir, "candidate.wav");
|
||||
var metrics = new List<SpeechScoreMetric>();
|
||||
var instrumentProfile = AnalyzeSongInstrumentProfile(script);
|
||||
var artifacts = new List<SpeechRenderArtifact>
|
||||
{
|
||||
Artifact("song-challenge", challengePath),
|
||||
|
|
@ -226,6 +227,7 @@ static async Task SongScoreAsync(Dictionary<string, string> options)
|
|||
Artifact("primitive-timeline", timelinePath)
|
||||
};
|
||||
metrics.AddRange(SongTargetMetrics(challenge, challengeEvidence));
|
||||
metrics.AddRange(SongInstrumentMetrics(instrumentProfile));
|
||||
artifacts.AddRange(SongChallengeArtifacts(challenge));
|
||||
artifacts.AddRange(challengeEvidence.Select(SongChallengeEvidenceArtifact));
|
||||
var timelineFacts = Array.Empty<PrimitiveTimelineFact>();
|
||||
|
|
@ -263,10 +265,10 @@ static async Task SongScoreAsync(Dictionary<string, string> options)
|
|||
artifacts.Add(Artifact("candidate-wav", candidateWav));
|
||||
var comparison = analyzer.Compare(referenceSamples, matched);
|
||||
metrics.AddRange(SongComparisonMetrics(comparison));
|
||||
verdict = SongVerdict(comparison);
|
||||
evaluation = SongEvaluationSentence(challenge, comparison, verdict);
|
||||
verdict = SongVerdict(comparison, instrumentProfile);
|
||||
evaluation = SongEvaluationSentence(challenge, comparison, verdict, instrumentProfile);
|
||||
var comparisonPath = Path.Combine(audioDir, "comparison.txt");
|
||||
await File.WriteAllTextAsync(comparisonPath, SongComparisonReport(challenge, candidate, comparison, verdict), Encoding.UTF8);
|
||||
await File.WriteAllTextAsync(comparisonPath, SongComparisonReport(challenge, candidate, comparison, verdict, instrumentProfile), Encoding.UTF8);
|
||||
artifacts.Add(Artifact("comparison-report", comparisonPath));
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +305,10 @@ static async Task SongScoreAsync(Dictionary<string, string> options)
|
|||
"This is a local-only song clip challenge; reference audio is not redistributed by the repo.",
|
||||
$"The target is a randomly selected {challenge.DurationSeconds:0.###}-second scene-audio snippet, not IPA articulation truth.",
|
||||
"Challenge spectrogram, derivative, envelope, and autocorrelation artifacts are stored as typed CultMesh/CultCache evidence documents in the .cc database.",
|
||||
"Full-patch FM/AM/noise/scene modeling is allowed; primitive timeline facts remain diagnostic when present."
|
||||
"Full-patch FM/AM/noise/scene modeling is allowed; primitive timeline facts remain diagnostic when present.",
|
||||
instrumentProfile.ChipDistressRisk >= .6f
|
||||
? "Instrument profile is chip-distress-risky: simple oscillator/noise roles are not enough curriculum evidence for the music generator."
|
||||
: "Instrument profile uses at least some owned musical role evidence instead of only simple oscillator distress."
|
||||
],
|
||||
[
|
||||
new SpeechTimingReceipt(
|
||||
|
|
@ -1808,6 +1813,18 @@ static SongTrialDistillationDocument SongTrialDistillation(
|
|||
static IEnumerable<string> SceneRolesFrom(string text)
|
||||
{
|
||||
var lower = text.ToLowerInvariant();
|
||||
if (lower.Contains("syrinx", StringComparison.Ordinal) || lower.Contains("labium", StringComparison.Ordinal) || lower.Contains("beak", StringComparison.Ordinal))
|
||||
{
|
||||
yield return "syrinx voice: owns singing/creature/alien lead material through acoustic source ports, pressure/opening motion, and radiation filtering.";
|
||||
}
|
||||
if (lower.Contains("additive", StringComparison.Ordinal) || lower.Contains("spectrum", StringComparison.Ordinal) || lower.Contains("pad", StringComparison.Ordinal) || lower.Contains("harmonics", StringComparison.Ordinal))
|
||||
{
|
||||
yield return "additive/PAD texture: owns sustained harmonic beds through `layer`, `harmonics`, and `spectrum` banks with slow filter or gain motion.";
|
||||
}
|
||||
if (lower.Contains("subtractive", StringComparison.Ordinal) || lower.Contains("kick", StringComparison.Ordinal) || lower.Contains("snare", StringComparison.Ordinal))
|
||||
{
|
||||
yield return "subtractive drums: own rhythmic bodies through pitched sine/triangle envelopes plus filtered noise skins, not generic blips.";
|
||||
}
|
||||
if (lower.Contains("formant", StringComparison.Ordinal) || lower.Contains("vowel", StringComparison.Ordinal))
|
||||
{
|
||||
yield return "bright formant/vowel lead: owns pitched synthetic body and vocal-ish spectral peaks.";
|
||||
|
|
@ -1847,6 +1864,9 @@ static IEnumerable<string> TransferRulesFrom(IReadOnlyList<IpaTrialResult> selec
|
|||
}
|
||||
|
||||
yield return "Use `texture` for background/recording noise and reserve raw `wave=noise` for short gated transients with narrow filters.";
|
||||
yield return "When the scene wants a singing or creature voice, start with a syrinx/acoustic voice role and modulate pressure/opening/radiation before falling back to ordinary formant oscillators.";
|
||||
yield return "When the scene wants a bed or pad, start with additive/PAD banks (`layer`, `harmonics`, `spectrum`) instead of stacked simple waves.";
|
||||
yield return "When the scene wants percussion, use subtractive drum ownership: pitched body, filtered noise skin, envelope, and pattern gate.";
|
||||
yield return "Treat repeated pressure verdicts as reusable direction, not acceptance; keep the patch family but mutate timing/register/noise shaping.";
|
||||
}
|
||||
|
||||
|
|
@ -1867,10 +1887,25 @@ static IEnumerable<string> FailurePatternsFrom(IReadOnlyList<IpaTrialResult> all
|
|||
{
|
||||
yield return "Scene/noise helper voices are allowed, but only shaped role owners should transfer.";
|
||||
}
|
||||
|
||||
if (allResults.Any(result => MetricValue(result, "chip_distress_risk") >= .6f))
|
||||
{
|
||||
yield return "Chip-distress-risk candidates may be useful contrast, but they should not train the music generator unless the target explicitly calls for chip/SFX vocabulary.";
|
||||
}
|
||||
|
||||
if (selected.Any(result => MetricValue(result, "musical_instrument_score") < .34f))
|
||||
{
|
||||
yield return "Low instrument-role coverage is a scoring smell: require at least one owned role such as syrinx voice, subtractive drums, additive/PAD bed, or shaped texture.";
|
||||
}
|
||||
}
|
||||
|
||||
static float ScoreSort(IpaTrialResult result) =>
|
||||
result.Metrics.FirstOrDefault(metric => metric.Name == "log_mel_cosine")?.Value ?? float.NegativeInfinity;
|
||||
static float ScoreSort(IpaTrialResult result)
|
||||
{
|
||||
var cosine = MetricValue(result, "log_mel_cosine");
|
||||
var instrument = MetricValue(result, "musical_instrument_score");
|
||||
var chipRisk = MetricValue(result, "chip_distress_risk");
|
||||
return cosine + instrument * .10f - chipRisk * .15f;
|
||||
}
|
||||
|
||||
static string Metric(IpaTrialResult result, string name) =>
|
||||
(result.Metrics.FirstOrDefault(metric => metric.Name == name)?.Value ?? 0)
|
||||
|
|
@ -2626,8 +2661,88 @@ static IReadOnlyList<SpeechScoreMetric> SongComparisonMetrics(AudioComparison co
|
|||
new("speech_band_ratio", comparison.Articulation.SpeechBandRatio, .05f)
|
||||
];
|
||||
|
||||
static string SongVerdict(AudioComparison comparison)
|
||||
static IReadOnlyList<SpeechScoreMetric> SongInstrumentMetrics(SongInstrumentProfile profile) =>
|
||||
[
|
||||
new("instrument_voice_syrinx", profile.HasSyrinxVoice ? 1 : 0, .05f),
|
||||
new("instrument_drum_subtractive", profile.HasSubtractiveDrums ? 1 : 0, .05f),
|
||||
new("instrument_pad_additive", profile.HasAdditivePad ? 1 : 0, .05f),
|
||||
new("musical_instrument_score", profile.MusicalInstrumentScore, .10f),
|
||||
new("chip_distress_risk", profile.ChipDistressRisk, .10f)
|
||||
];
|
||||
|
||||
static SongInstrumentProfile AnalyzeSongInstrumentProfile(string script)
|
||||
{
|
||||
var lower = script.ToLowerInvariant();
|
||||
var voiceCount = CountOccurrences(lower, "voice");
|
||||
var hasTexture = lower.Contains("texture ", StringComparison.Ordinal) ||
|
||||
lower.Contains("noise_texture", StringComparison.Ordinal);
|
||||
var hasSyrinxVoice = lower.Contains("kind=syrinx", StringComparison.Ordinal) ||
|
||||
lower.Contains("kind = syrinx", StringComparison.Ordinal) ||
|
||||
lower.Contains("syrinx", StringComparison.Ordinal) && lower.Contains("acoustic_voice", StringComparison.Ordinal);
|
||||
var hasAdditivePad = lower.Contains("spectrum ", StringComparison.Ordinal) ||
|
||||
lower.Contains("harmonics ", StringComparison.Ordinal) ||
|
||||
lower.Contains("engine=pad", StringComparison.Ordinal) ||
|
||||
lower.Contains("engine = pad", StringComparison.Ordinal) ||
|
||||
lower.Contains("engine=add", StringComparison.Ordinal) ||
|
||||
lower.Contains("engine = add", StringComparison.Ordinal);
|
||||
var hasSubtractiveDrums = lower.Contains("role=dust", StringComparison.Ordinal) ||
|
||||
lower.Contains("dust_hat", StringComparison.Ordinal) ||
|
||||
lower.Contains("kick", StringComparison.Ordinal) ||
|
||||
lower.Contains("snare", StringComparison.Ordinal) ||
|
||||
lower.Contains("hat", StringComparison.Ordinal) ||
|
||||
(lower.Contains("pitch_ramp", StringComparison.Ordinal) &&
|
||||
(lower.Contains("wave=sine", StringComparison.Ordinal) || lower.Contains("wave=triangle", StringComparison.Ordinal)) &&
|
||||
(lower.Contains("wave=noise", StringComparison.Ordinal) || lower.Contains("noise=", StringComparison.Ordinal)) &&
|
||||
(lower.Contains("hpf=", StringComparison.Ordinal) || lower.Contains("bpf=", StringComparison.Ordinal)));
|
||||
var hasSimpleChipTone = lower.Contains("wave=square", StringComparison.Ordinal) ||
|
||||
lower.Contains("wave=sine", StringComparison.Ordinal) ||
|
||||
lower.Contains("wave=saw", StringComparison.Ordinal);
|
||||
var lacksOwnedRoles = !hasSyrinxVoice && !hasAdditivePad && !hasSubtractiveDrums && !hasTexture;
|
||||
var chipRisk = lacksOwnedRoles && hasSimpleChipTone
|
||||
? Math.Clamp(.45f + Math.Max(0, 4 - voiceCount) * .12f, 0, 1)
|
||||
: 0f;
|
||||
if (lower.Contains("laser", StringComparison.Ordinal) ||
|
||||
lower.Contains("blip", StringComparison.Ordinal) ||
|
||||
lower.Contains("sfxr", StringComparison.Ordinal))
|
||||
{
|
||||
chipRisk = Math.Max(chipRisk, .65f);
|
||||
}
|
||||
|
||||
var score = 0f;
|
||||
if (hasSyrinxVoice) score += .34f;
|
||||
if (hasSubtractiveDrums) score += .33f;
|
||||
if (hasAdditivePad) score += .33f;
|
||||
if (hasTexture) score = Math.Min(1, score + .10f);
|
||||
|
||||
var summary =
|
||||
$"syrinx_voice={(hasSyrinxVoice ? "yes" : "no")}; " +
|
||||
$"subtractive_drums={(hasSubtractiveDrums ? "yes" : "no")}; " +
|
||||
$"additive_pad={(hasAdditivePad ? "yes" : "no")}; " +
|
||||
$"texture={(hasTexture ? "yes" : "no")}; " +
|
||||
$"chip_distress_risk={chipRisk:0.###}";
|
||||
return new SongInstrumentProfile(hasSyrinxVoice, hasSubtractiveDrums, hasAdditivePad, hasTexture, score, chipRisk, summary);
|
||||
}
|
||||
|
||||
static int CountOccurrences(string haystack, string needle)
|
||||
{
|
||||
var count = 0;
|
||||
var index = 0;
|
||||
while ((index = haystack.IndexOf(needle, index, StringComparison.Ordinal)) >= 0)
|
||||
{
|
||||
count++;
|
||||
index += needle.Length;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static string SongVerdict(AudioComparison comparison, SongInstrumentProfile profile)
|
||||
{
|
||||
if (profile.ChipDistressRisk >= .75f && comparison.LogMelCosineSimilarity < .60f)
|
||||
{
|
||||
return "weak";
|
||||
}
|
||||
|
||||
if (comparison.LogMelCosineSimilarity >= .70f && comparison.Score >= .45f)
|
||||
{
|
||||
return "promising";
|
||||
|
|
@ -2648,8 +2763,8 @@ static float SongConfidence(IReadOnlyList<SpeechScoreMetric> metrics)
|
|||
return Math.Clamp((cosine + score) * .5f, 0, 1);
|
||||
}
|
||||
|
||||
static string SongEvaluationSentence(SongChallenge challenge, AudioComparison comparison, string verdict) =>
|
||||
$"Song snippet `{challenge.ChallengeId}` is `{verdict}`: logMelCosine={comparison.LogMelCosineSimilarity:0.0000}, logMelDistance={comparison.LogMelDistance:0.0000}, score={comparison.Score:0.0000}, rmsRatio={comparison.RmsRatio:0.0000}, centroidRatio={comparison.CentroidRatio:0.0000}.";
|
||||
static string SongEvaluationSentence(SongChallenge challenge, AudioComparison comparison, string verdict, SongInstrumentProfile profile) =>
|
||||
$"Song snippet `{challenge.ChallengeId}` is `{verdict}`: logMelCosine={comparison.LogMelCosineSimilarity:0.0000}, logMelDistance={comparison.LogMelDistance:0.0000}, score={comparison.Score:0.0000}, rmsRatio={comparison.RmsRatio:0.0000}, centroidRatio={comparison.CentroidRatio:0.0000}. Instrument profile: {profile.Summary}.";
|
||||
|
||||
static string SongAnalysisReport(SongChallenge challenge, AudioAnalysis analysis)
|
||||
{
|
||||
|
|
@ -2724,7 +2839,7 @@ static string SongChallengeReport(SongChallenge challenge) =>
|
|||
rms_envelope_autocorr_csv: `{challenge.Artifacts?.RmsEnvelopeAutocorrCsv ?? ""}`
|
||||
""";
|
||||
|
||||
static string SongComparisonReport(SongChallenge challenge, IpaTrialScriptCandidate candidate, AudioComparison comparison, string verdict) =>
|
||||
static string SongComparisonReport(SongChallenge challenge, IpaTrialScriptCandidate candidate, AudioComparison comparison, string verdict, SongInstrumentProfile profile) =>
|
||||
$"""
|
||||
candidate={candidate.CandidateId}
|
||||
challenge={challenge.ChallengeId}
|
||||
|
|
@ -2738,12 +2853,18 @@ static string SongComparisonReport(SongChallenge challenge, IpaTrialScriptCandid
|
|||
zeroCrossingRatio={comparison.ZeroCrossingRatio:0.######}
|
||||
articulation={comparison.Articulation.ArticulationScore:0.######}
|
||||
speechBandRatio={comparison.Articulation.SpeechBandRatio:0.######}
|
||||
instrumentVoiceSyrinx={(profile.HasSyrinxVoice ? 1 : 0)}
|
||||
instrumentDrumSubtractive={(profile.HasSubtractiveDrums ? 1 : 0)}
|
||||
instrumentPadAdditive={(profile.HasAdditivePad ? 1 : 0)}
|
||||
musicalInstrumentScore={profile.MusicalInstrumentScore:0.######}
|
||||
chipDistressRisk={profile.ChipDistressRisk:0.######}
|
||||
instrumentSummary={profile.Summary}
|
||||
""";
|
||||
|
||||
static string SongSummaryCsv(IReadOnlyList<IpaTrialResult> results)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine("trial_id,candidate_id,reference_id,verdict,log_mel_cosine,log_mel_distance,audio_score,envelope_distance,rms_ratio,centroid_ratio,zero_crossing_ratio,articulation_score");
|
||||
builder.AppendLine("trial_id,candidate_id,reference_id,verdict,log_mel_cosine,log_mel_distance,audio_score,envelope_distance,rms_ratio,centroid_ratio,zero_crossing_ratio,articulation_score,musical_instrument_score,chip_distress_risk,instrument_voice_syrinx,instrument_drum_subtractive,instrument_pad_additive");
|
||||
foreach (var result in results)
|
||||
{
|
||||
builder.Append(Escape(result.TrialId)).Append(',');
|
||||
|
|
@ -2757,7 +2878,12 @@ static string SongSummaryCsv(IReadOnlyList<IpaTrialResult> results)
|
|||
builder.Append(Metric(result, "rms_ratio")).Append(',');
|
||||
builder.Append(Metric(result, "centroid_ratio")).Append(',');
|
||||
builder.Append(Metric(result, "zero_crossing_ratio")).Append(',');
|
||||
builder.AppendLine(Metric(result, "articulation_score"));
|
||||
builder.Append(Metric(result, "articulation_score")).Append(',');
|
||||
builder.Append(Metric(result, "musical_instrument_score")).Append(',');
|
||||
builder.Append(Metric(result, "chip_distress_risk")).Append(',');
|
||||
builder.Append(Metric(result, "instrument_voice_syrinx")).Append(',');
|
||||
builder.Append(Metric(result, "instrument_drum_subtractive")).Append(',');
|
||||
builder.AppendLine(Metric(result, "instrument_pad_additive"));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
|
|
@ -2770,11 +2896,11 @@ static string SongEvaluatorReport(SongChallenge challenge, IReadOnlyList<IpaTria
|
|||
builder.AppendLine();
|
||||
builder.AppendLine(SongChallengeReport(challenge));
|
||||
builder.AppendLine();
|
||||
builder.AppendLine("| candidate | verdict | logMelCosine | score | envelopeDistance | rmsRatio | centroidRatio |");
|
||||
builder.AppendLine("| --- | --- | ---: | ---: | ---: | ---: | ---: |");
|
||||
builder.AppendLine("| candidate | verdict | logMelCosine | score | instrument | chipRisk | envelopeDistance | rmsRatio | centroidRatio |");
|
||||
builder.AppendLine("| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |");
|
||||
foreach (var result in results.OrderByDescending(result => MetricValue(result, "log_mel_cosine")))
|
||||
{
|
||||
builder.AppendLine(CultureInfo.InvariantCulture, $"| {result.CandidateId} | {result.Verdict} | {MetricValue(result, "log_mel_cosine"):0.######} | {MetricValue(result, "audio_score"):0.######} | {MetricValue(result, "envelope_distance"):0.######} | {MetricValue(result, "rms_ratio"):0.######} | {MetricValue(result, "centroid_ratio"):0.######} |");
|
||||
builder.AppendLine(CultureInfo.InvariantCulture, $"| {result.CandidateId} | {result.Verdict} | {MetricValue(result, "log_mel_cosine"):0.######} | {MetricValue(result, "audio_score"):0.######} | {MetricValue(result, "musical_instrument_score"):0.######} | {MetricValue(result, "chip_distress_risk"):0.######} | {MetricValue(result, "envelope_distance"):0.######} | {MetricValue(result, "rms_ratio"):0.######} | {MetricValue(result, "centroid_ratio"):0.######} |");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
|
|
@ -2954,6 +3080,15 @@ sealed record SongChallengeFeatures(
|
|||
string SuggestedScale,
|
||||
string ScaleFrequenciesHz);
|
||||
|
||||
sealed record SongInstrumentProfile(
|
||||
bool HasSyrinxVoice,
|
||||
bool HasSubtractiveDrums,
|
||||
bool HasAdditivePad,
|
||||
bool HasTexture,
|
||||
float MusicalInstrumentScore,
|
||||
float ChipDistressRisk,
|
||||
string Summary);
|
||||
|
||||
sealed record SongRegister(
|
||||
float DominantHz,
|
||||
float LowHz,
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ $agentSeedList
|
|||
- required duration: $DurationSeconds seconds
|
||||
|
||||
Goal:
|
||||
Write exactly one parseable AquaSynth `.aqua` patch for each frozen $DurationSeconds second reference clip assigned to you. This is scene-audio parity, not IPA articulation. You may use ordinary voices, FM, AM/tremolo, filters, formants, noise layers, acoustic vocal/syrinx primitives, curves, and helper voices.
|
||||
Write exactly one parseable AquaSynth `.aqua` patch for each frozen $DurationSeconds second reference clip assigned to you. This is scene-audio parity, not IPA articulation. You may use ordinary voices, FM, AM/tremolo, filters, formants, noise layers, acoustic vocal/syrinx primitives, additive/PAD layers, curves, and helper voices.
|
||||
|
||||
Generalization:
|
||||
- You own two target patches, but your report must compare both targets and state what reusable scene/instrument knowledge transfers between them.
|
||||
|
|
@ -384,6 +384,13 @@ Noise and texture:
|
|||
- Use the shaped texture owner for noise roles: `texture name=dust_hat role=dust pattern=x..x step=<beat_seconds/4> gain=.08 sustain=$DurationSeconds`, `texture name=air_wash role=air gain=.035 sustain=$DurationSeconds`, `texture name=codec_bed role=codec gain=.04 sustain=$DurationSeconds`.
|
||||
- `texture` lowers to a gated noise voice with role-specific bandpass/highpass/lowpass/tremolo defaults and a control curve or pattern gate. Raw `voice wave=noise` is only acceptable for short transients with explicit gates and narrow filters.
|
||||
|
||||
Instrument ownership:
|
||||
- This harness is feeding the music-generator curriculum, so do not solve the target with three naked oscillators and a prayer. The scorer now records instrument-role metrics and chip-distress risk in CultCache.
|
||||
- If the patch has a singing, creature, or alien lead role, use the syrinx/acoustic owner: `source_port kind=syrinx`, pressure/opening curves, `acoustic_network`, and `acoustic_voice`, then shape it with filters/modulation.
|
||||
- If the patch has drums or rhythmic transients, use subtractive ownership: pitched sine/triangle body, filtered noise skin, short envelope, and pattern gate.
|
||||
- If the patch has a pad, bed, drone, or harmonic wash, use additive/PAD ownership: `layer engine=add` or `engine=pad`, `harmonics`, `spectrum`, and slow modulation.
|
||||
- Ordinary simple voices are still legal as helpers, but a candidate built mostly from square/sine/saw blips with no syrinx, subtractive drum, additive/PAD, or shaped texture role will be treated as chip-distress-risk evidence.
|
||||
|
||||
Rhythm and tempo:
|
||||
- The challenge report includes `tempo_bpm`, `beat_seconds`, and `tempo_confidence`, estimated from spectral/RMS onset autocorrelation.
|
||||
- The challenge report also points to `analysis_report`, `log_mel_spectrogram_csv`, `log_mel_band_stats_csv`, `rms_envelope_csv`, and `rms_envelope_autocorr_csv`; read them before writing the patch.
|
||||
|
|
@ -421,7 +428,7 @@ Evidence contract:
|
|||
- Read every assigned challenge report and $preEvidence.
|
||||
- Write $agentDir/hypotheses.md with: per-target reference features, shared cross-target invariants, cited analysis artifacts, tempo/rhythm plan, register/scale plan, scene voices, synthesis owners, invented instrument roles, expected metric movement on both targets, known risks.
|
||||
- Write exactly one `.aqua` file under each target patch output directory named `<agent-id>__<family>__<hypothesis>.aqua`.
|
||||
- Include at least three scene voices or layers in the patch, such as primary alien-voice/body, rhythmic transient/noise, and background/recording color.
|
||||
- Include at least three scene voices or layers in the patch: a primary voice/body, a rhythmic drum/transient/noise role, and a pad/bed/recording-color role. Prefer syrinx for the primary voice when it is voice-like, subtractive for the drum/transient, and additive/PAD or shaped texture for the bed.
|
||||
- Background/recording-color layers must use `texture` or an equivalently gated and band-shaped explicit voice; a static full-duration white-noise bed is failed evidence.
|
||||
- Make each patch duration/gates cover its matching $DurationSeconds second target.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue