Add aqua-feel: headless feel meter and gate; fix PRC SYNTH1 clipping and thruster low-rpm hiss
tools/aqua-feel renders every playground patch (thruster at four rpm) and every Ding event on every instrument offline through faustwasm, measures onset latency, attack, crest, true peak and clipping, BS.1770 loudness, centroid/flux over time, noise-to-tone ratio (flat and A-weighted) and a low-motion flag, writes report.json plus a static gallery, and gates against thresholds.json (waivers must cite a follow-up and go stale). Nothing is heard; metrics are evidence, not verdicts. Uses it: PRC SYNTH1 calibrated peaked at 2.10 (18,633 overs); shipped patch gain 1.4 to 0.45, peak 0.67. Thruster low-rpm A-weighted noise-to-tone 20.7/23.0 dB at rpm 300/600 down to 13.1/5.0 by cutting the idle rasp and rattle floors and opening the rumble low-pass at low load. Trial copy mirrored; its README notes the narrower sweep. AquaLower gains --dings to lower DingCatalog instruments and events. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d8c625c532
commit
eb35ca545d
27 changed files with 1438 additions and 19 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using System.Text.Json;
|
||||
using AquaSynth.Dings;
|
||||
using AquaSynth.Dsl;
|
||||
|
||||
// Lowers .aqua patches to Faust source for the static playground (tools/aqua-playground).
|
||||
|
|
@ -6,6 +7,25 @@ using AquaSynth.Dsl;
|
|||
// A .aqua entry goes through FaustEmitter.EmitScript, the same lowering the daemon uses; a .dsp entry
|
||||
// (the thruster) is already Faust and is copied verbatim. Writes <outDir>/<name>.dsp, and
|
||||
// catalog.json for the browser (the one non-CultNet xeno at this boundary).
|
||||
// usage: AquaLower --dings <outDir>: lowers each DingCatalog instrument to <outDir>/<id>.dsp and writes dings.json
|
||||
// (instruments with their root frequency, events with their notes) so aqua-feel can mix an event the way DingsPlaybackHost does.
|
||||
if (args.Length == 2 && args[0] == "--dings")
|
||||
{
|
||||
var dingDir = Path.GetFullPath(args[1]);
|
||||
Directory.CreateDirectory(dingDir);
|
||||
var instruments = new List<object>();
|
||||
foreach (var ins in DingCatalog.Instruments.Values.OrderBy(i => i.Id, StringComparer.Ordinal))
|
||||
{
|
||||
var export = FaustEmitter.EmitScript(ins.Script, new FaustExportOptions("dings_" + ins.Id.Replace('-', '_')));
|
||||
File.WriteAllText(Path.Combine(dingDir, ins.Id + ".dsp"), export.Source);
|
||||
instruments.Add(new { id = ins.Id, rootFrequency = ins.RootFrequency, dsp = ins.Id + ".dsp", controlPath = "/ding/frequency", warnings = export.Warnings });
|
||||
Console.WriteLine($"{ins.Id}: {export.Source.Length} chars, {export.Warnings.Count} warnings");
|
||||
}
|
||||
var events = DingCatalog.Events.Values.OrderBy(e => e.Id, StringComparer.Ordinal)
|
||||
.Select(e => new { id = e.Id, meaning = e.Meaning, notes = e.Notes.Select(n => new { semitones = n.Semitones, delayMilliseconds = n.DelayMilliseconds, gain = n.Gain }) });
|
||||
File.WriteAllText(Path.Combine(dingDir, "dings.json"), JsonSerializer.Serialize(new { instruments, events, noteSeconds = 1.5 }, new JsonSerializerOptions { WriteIndented = true }));
|
||||
return 0;
|
||||
}
|
||||
if (args.Length < 3) { Console.Error.WriteLine("usage: AquaLower <outDir> <patchesRoot> <name>=<path> ..."); return 2; }
|
||||
var outDir = Path.GetFullPath(args[0]);
|
||||
var root = Path.GetFullPath(args[1]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue