@hraness/dawg 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +126 -0
- package/DAWG.md +655 -141
- package/README.md +27 -25
- package/core/autotune.ts +1119 -0
- package/core/chords.ts +759 -23
- package/core/clips.ts +499 -0
- package/core/diff.ts +182 -99
- package/core/expression.ts +158 -6
- package/core/fx.ts +354 -32
- package/core/granular.ts +91 -0
- package/core/instruments.ts +180 -0
- package/core/keys.ts +573 -4
- package/core/loop.ts +5 -0
- package/core/lyrics.ts +297 -0
- package/core/master.ts +3 -3
- package/core/resonators.ts +306 -4
- package/core/routing.ts +165 -0
- package/core/score.ts +1181 -16
- package/core/sdk/eval-child.ts +7 -2
- package/core/sdk/eval.ts +35 -6
- package/core/sdk/print.ts +354 -6
- package/core/sdk/sync-lyrics.ts +49 -0
- package/core/sdk/v1.ts +3160 -69
- package/core/sections.ts +298 -24
- package/core/sing.ts +815 -0
- package/core/strings.ts +237 -2
- package/core/style-provenance.ts +80 -0
- package/core/styles/africa-mena-southasia.ts +2893 -0
- package/core/styles/americas.ts +3810 -0
- package/core/styles/art.ts +4993 -0
- package/core/styles/base.ts +123 -0
- package/core/styles/cycles.ts +106 -0
- package/core/styles/electronic.ts +2723 -0
- package/core/styles/europe-asia-pacific.ts +2838 -0
- package/core/styles/excerpt.ts +29 -0
- package/core/styles/gamelan.ts +283 -0
- package/core/styles/generate.ts +2199 -0
- package/core/styles/index.ts +515 -0
- package/core/styles/parts.ts +106 -0
- package/core/styles/pop.ts +3189 -0
- package/core/styles/rock.ts +2993 -0
- package/core/styles/roots.ts +4175 -0
- package/core/styles/schema.ts +429 -0
- package/core/styles/taxonomy.ts +940 -0
- package/core/styles/validate.ts +528 -0
- package/core/tempo.ts +32 -2
- package/core/tuning.ts +19 -3
- package/core/vocoder.ts +524 -0
- package/core/winds.ts +652 -0
- package/guides/agent.md +29 -0
- package/guides/arrange.md +30 -0
- package/guides/audition.md +20 -14
- package/guides/automation.md +12 -6
- package/guides/chords.md +16 -14
- package/guides/effects.md +17 -15
- package/guides/faders.md +20 -16
- package/guides/files.md +13 -9
- package/guides/getting-started.md +15 -11
- package/guides/keys.md +19 -15
- package/guides/media.md +17 -12
- package/guides/mix.md +12 -6
- package/guides/music.md +23 -8
- package/guides/notes.md +15 -9
- package/guides/performance.md +15 -10
- package/guides/play.md +21 -13
- package/guides/project.md +25 -8
- package/guides/providers.md +20 -14
- package/guides/resample.md +32 -0
- package/guides/rhythm.md +17 -13
- package/guides/sessions.md +17 -7
- package/guides/show-me.md +31 -0
- package/guides/sound.md +25 -9
- package/guides/sounds.md +15 -12
- package/guides/styles.md +31 -0
- package/guides/tempo.md +15 -10
- package/guides/tracks.md +15 -10
- package/guides/tuning.md +32 -0
- package/guides/voice.md +31 -0
- package/guides/web-search.md +18 -8
- package/native/prebuilt/darwin-arm64/libdawg_sink.dylib +0 -0
- package/native/prebuilt/darwin-x64/libdawg_sink.dylib +0 -0
- package/native/prebuilt/linux-arm64/libdawg_sink.so +0 -0
- package/native/prebuilt/linux-x64/libdawg_sink.so +0 -0
- package/native/prebuilt/manifest.json +21 -0
- package/package.json +5 -2
- package/src/agent/agent.ts +131 -13
- package/src/agent/calibration-tools.ts +53 -0
- package/src/agent/chord-tools.ts +153 -1
- package/src/agent/clip-tools.ts +453 -0
- package/src/agent/command-agent.ts +369 -0
- package/src/agent/drum-tools.ts +2 -2
- package/src/agent/expression-tools.ts +91 -0
- package/src/agent/gateway.ts +246 -60
- package/src/agent/models.ts +53 -12
- package/src/agent/ops.ts +15 -1
- package/src/agent/pack-tools.ts +1 -1
- package/src/agent/planner.ts +13 -0
- package/src/agent/portable-schema.ts +80 -0
- package/src/agent/preview-tool.ts +5 -1
- package/src/agent/provider.ts +22 -8
- package/src/agent/resample-tool.ts +131 -0
- package/src/agent/rhythm-tools.ts +1 -1
- package/src/agent/section-tools.ts +1 -1
- package/src/agent/show-me.ts +497 -0
- package/src/agent/steer.ts +15 -0
- package/src/agent/style-tools.ts +217 -0
- package/src/agent/tool-error.ts +12 -0
- package/src/agent/tools.ts +307 -37
- package/src/agent/usage.ts +2 -2
- package/src/agent/voice-tools.ts +925 -0
- package/src/agent/xcb-agent.ts +16 -6
- package/src/argv.ts +38 -0
- package/src/audio/analysis.ts +253 -0
- package/src/audio/arrange.ts +58 -3
- package/src/audio/autotune-engine.ts +101 -0
- package/src/audio/autotune.ts +640 -0
- package/src/audio/clips.ts +240 -0
- package/src/audio/doctor.ts +86 -0
- package/src/audio/dsp/bandbank.ts +138 -0
- package/src/audio/dsp/envelope.ts +171 -0
- package/src/audio/dsp/follow.ts +120 -0
- package/src/audio/dsp/formant.ts +427 -0
- package/src/audio/dsp/glottal.ts +243 -0
- package/src/audio/dsp/interp.ts +7 -2
- package/src/audio/dsp/lpc.ts +50 -0
- package/src/audio/dsp/periodicity.ts +59 -0
- package/src/audio/dsp/pitch.ts +995 -0
- package/src/audio/dsp/psola.ts +199 -0
- package/src/audio/dsp/shift.ts +256 -0
- package/src/audio/effects/chain.ts +21 -4
- package/src/audio/effects/common.ts +57 -0
- package/src/audio/effects/convolution.ts +113 -5
- package/src/audio/effects/filter.ts +48 -69
- package/src/audio/effects/formant.ts +263 -0
- package/src/audio/effects/gaze.ts +354 -0
- package/src/audio/engine.ts +206 -33
- package/src/audio/fit.ts +80 -3
- package/src/audio/granular.ts +352 -21
- package/src/audio/instrument-check.ts +67 -47
- package/src/audio/instruments.ts +36 -3
- package/src/audio/keys/calibration.ts +56 -0
- package/src/audio/keys/electric.ts +427 -0
- package/src/audio/keys/engine.ts +156 -20
- package/src/audio/keys/organ.ts +1335 -0
- package/src/audio/keys/piano.ts +72 -8
- package/src/audio/keys/sympathetic.ts +127 -0
- package/src/audio/kits.ts +135 -6
- package/src/audio/live-worker.ts +3 -1
- package/src/audio/live.ts +247 -26
- package/src/audio/native.ts +615 -0
- package/src/audio/preview.ts +45 -3
- package/src/audio/render-worker.ts +2 -0
- package/src/audio/renderer.ts +2 -0
- package/src/audio/resample.ts +286 -0
- package/src/audio/resonators.ts +10 -2
- package/src/audio/sampler.ts +252 -24
- package/src/audio/samples.ts +46 -3
- package/src/audio/sing/analysis.ts +193 -0
- package/src/audio/sing/engine.ts +949 -0
- package/src/audio/strings/body.ts +29 -16
- package/src/audio/strings/bow.ts +699 -0
- package/src/audio/strings/engine.ts +274 -22
- package/src/audio/strings/measure.test-helpers.ts +2 -0
- package/src/audio/synth/oscillators.ts +31 -21
- package/src/audio/synth/voice.ts +34 -1
- package/src/audio/vocoder/bank.ts +314 -0
- package/src/audio/vocoder/carrier.ts +165 -0
- package/src/audio/vocoder/control.ts +68 -0
- package/src/audio/vocoder/detect.ts +50 -0
- package/src/audio/vocoder/index.ts +304 -0
- package/src/audio/vocoder/talkbox.ts +143 -0
- package/src/audio/wav.ts +608 -85
- package/src/audio/winds/engine.ts +306 -0
- package/src/audio/winds/filters.ts +153 -0
- package/src/audio/winds/pitch.ts +104 -0
- package/src/audio/winds/trim.ts +104 -0
- package/src/audio/winds/trims.ts +917 -0
- package/src/audio/winds/trims1.ts +297 -0
- package/src/audio/winds/voice.ts +492 -0
- package/src/auth/cli.ts +38 -36
- package/src/auth/credentials.ts +30 -1
- package/src/auth/login.ts +15 -9
- package/src/auth/tui.ts +19 -10
- package/src/commands/arrange.ts +44 -29
- package/src/commands/autotune.ts +421 -0
- package/src/commands/calibration.ts +74 -0
- package/src/commands/clips.ts +887 -0
- package/src/commands/drums.ts +3 -2
- package/src/commands/edit.ts +11 -4
- package/src/commands/expression.ts +104 -23
- package/src/commands/formant.ts +221 -0
- package/src/commands/fx.ts +105 -33
- package/src/commands/grammar.ts +558 -0
- package/src/commands/granular.ts +7 -2
- package/src/commands/help.ts +652 -339
- package/src/commands/history.ts +18 -0
- package/src/commands/keys.ts +293 -17
- package/src/commands/modal.ts +67 -4
- package/src/commands/music.ts +1 -1
- package/src/commands/nearest.ts +53 -0
- package/src/commands/pack.ts +9 -2
- package/src/commands/param-range.ts +56 -0
- package/src/commands/parses.ts +130 -0
- package/src/commands/progression.ts +170 -0
- package/src/commands/resample.ts +281 -0
- package/src/commands/rhythm.ts +3 -0
- package/src/commands/rig.ts +8 -25
- package/src/commands/sample.ts +49 -2
- package/src/commands/shift.ts +119 -0
- package/src/commands/sing.ts +478 -0
- package/src/commands/string.ts +28 -2
- package/src/commands/strum.ts +485 -0
- package/src/commands/style.ts +415 -0
- package/src/commands/time.ts +6 -3
- package/src/commands/tuning.ts +3 -3
- package/src/commands/vocal-pitch.ts +616 -0
- package/src/commands/vocal.ts +147 -0
- package/src/commands/vocoder.ts +627 -0
- package/src/commands/wind.ts +244 -0
- package/src/fs/durable.ts +50 -0
- package/src/lang/glossary.ts +493 -0
- package/src/launch-args.ts +163 -0
- package/src/main.ts +1521 -255
- package/src/media/cli.ts +20 -3
- package/src/media/import.ts +3 -1
- package/src/project/check.ts +26 -3
- package/src/project/clip-pins.ts +72 -0
- package/src/project/init.ts +23 -8
- package/src/project/sync.ts +418 -86
- package/src/render.ts +36 -1
- package/src/session/daemon.ts +3 -0
- package/src/session/meta.ts +14 -0
- package/src/session/origin.ts +154 -0
- package/src/session/port.ts +22 -4
- package/src/session/presence.ts +50 -7
- package/src/session/protocol.ts +5 -1
- package/src/session/rebase.ts +18 -5
- package/src/session/receipt.ts +258 -0
- package/src/session/store.ts +65 -43
- package/src/tui/arrange-menu.ts +65 -31
- package/src/tui/audition.ts +1 -1
- package/src/tui/euclid.ts +18 -13
- package/src/tui/fader.ts +228 -41
- package/src/tui/granular-menu.ts +2 -4
- package/src/tui/menu-clips.ts +297 -0
- package/src/tui/menu-time.ts +20 -13
- package/src/tui/menu-voice.ts +405 -0
- package/src/tui/menu.ts +1377 -193
- package/src/tui/modal-menu.ts +38 -11
- package/src/tui/performance-menu.ts +46 -1
- package/src/tui/play-chords.ts +108 -5
- package/src/tui/play-mode.ts +16 -1
- package/src/tui/play-session.ts +81 -16
- package/src/tui/sing-menu.ts +278 -0
- package/src/tui/style-menu.ts +104 -0
- package/src/tui/vocoder-menu.ts +244 -0
- package/src/tui/wind-menu.ts +144 -0
- package/src/version.ts +8 -0
- package/src/web/fetch.ts +115 -29
- package/tui/activity.ts +180 -9
- package/tui/app.ts +274 -40
- package/tui/clip-row.ts +132 -0
- package/tui/delight.ts +144 -0
- package/tui/drawer.ts +70 -22
- package/tui/frame-gate.ts +76 -0
- package/tui/grammar.ts +112 -63
- package/tui/guide.ts +42 -4
- package/tui/highway.ts +269 -25
- package/tui/hints.ts +192 -0
- package/tui/input.ts +60 -9
- package/tui/keys.ts +1 -1
- package/tui/play-strip.ts +68 -14
- package/tui/prompt.ts +1 -1
- package/tui/screen.ts +144 -14
- package/tui/theme.ts +27 -0
package/core/strings.ts
CHANGED
|
@@ -31,9 +31,9 @@ export const STRING_PARAMS: Readonly<Record<string, ParamSpec>> = Object.freeze(
|
|
|
31
31
|
{
|
|
32
32
|
exciter: {
|
|
33
33
|
kind: "enum",
|
|
34
|
-
values: ["pick", "finger", "hammer", "noise"],
|
|
34
|
+
values: ["pick", "finger", "hammer", "noise", "bow"],
|
|
35
35
|
default: "pick",
|
|
36
|
-
doc: "how the string is set in motion",
|
|
36
|
+
doc: "how the string is set in motion (bow: the bowed voice)",
|
|
37
37
|
},
|
|
38
38
|
ring: {
|
|
39
39
|
kind: "number",
|
|
@@ -276,6 +276,63 @@ export const STRING_PARAMS: Readonly<Record<string, ParamSpec>> = Object.freeze(
|
|
|
276
276
|
doc: "output level (presets carry a calibrated trim)",
|
|
277
277
|
strudel: ["gain"],
|
|
278
278
|
},
|
|
279
|
+
// ---- bowed (f061-bowed): read only when exciter is bow ----
|
|
280
|
+
pressure: {
|
|
281
|
+
kind: "number",
|
|
282
|
+
min: 0,
|
|
283
|
+
max: 1,
|
|
284
|
+
default: 0.5,
|
|
285
|
+
step: 0.05,
|
|
286
|
+
automate: true,
|
|
287
|
+
doc: "bow force within the playable range: flautando at 0, gritty at 1",
|
|
288
|
+
},
|
|
289
|
+
speed: {
|
|
290
|
+
kind: "number",
|
|
291
|
+
min: 0,
|
|
292
|
+
max: 1,
|
|
293
|
+
default: 0.6,
|
|
294
|
+
step: 0.05,
|
|
295
|
+
automate: true,
|
|
296
|
+
doc: "bow speed at full dynamics (loudness)",
|
|
297
|
+
},
|
|
298
|
+
attack: {
|
|
299
|
+
kind: "number",
|
|
300
|
+
min: 0.005,
|
|
301
|
+
max: 4,
|
|
302
|
+
default: 0.08,
|
|
303
|
+
step: log,
|
|
304
|
+
unit: "s",
|
|
305
|
+
doc: "bow-speed ramp at the start of a stroke (swells)",
|
|
306
|
+
strudel: ["attack"],
|
|
307
|
+
},
|
|
308
|
+
tremhz: {
|
|
309
|
+
kind: "number",
|
|
310
|
+
min: 0,
|
|
311
|
+
max: 16,
|
|
312
|
+
default: 0,
|
|
313
|
+
step: 0.5,
|
|
314
|
+
unit: "Hz",
|
|
315
|
+
doc: "tremolo bowing: rapid up and down strokes per second (0 off)",
|
|
316
|
+
},
|
|
317
|
+
sord: {
|
|
318
|
+
kind: "number",
|
|
319
|
+
min: 0,
|
|
320
|
+
max: 1,
|
|
321
|
+
default: 0,
|
|
322
|
+
step: 0.05,
|
|
323
|
+
automate: true,
|
|
324
|
+
doc: "con sordino: the practice mute, darker and softer",
|
|
325
|
+
},
|
|
326
|
+
dyn: {
|
|
327
|
+
kind: "number",
|
|
328
|
+
min: 0,
|
|
329
|
+
max: 1,
|
|
330
|
+
default: 1,
|
|
331
|
+
step: 0.05,
|
|
332
|
+
automate: true,
|
|
333
|
+
doc: "dynamics on top of velocity, drives bow speed and pressure (swells)",
|
|
334
|
+
strudel: ["expression"],
|
|
335
|
+
},
|
|
279
336
|
},
|
|
280
337
|
);
|
|
281
338
|
|
|
@@ -291,6 +348,21 @@ export const STRING_SIMPLE_PARAMS: readonly string[] = Object.freeze([
|
|
|
291
348
|
"sym",
|
|
292
349
|
]);
|
|
293
350
|
|
|
351
|
+
/** Simple menu rows of a bowed track (exciter bow, 0.6.1). */
|
|
352
|
+
export const BOW_SIMPLE_PARAMS: readonly string[] = Object.freeze([
|
|
353
|
+
"pressure",
|
|
354
|
+
"speed",
|
|
355
|
+
"attack",
|
|
356
|
+
"pos",
|
|
357
|
+
"vib",
|
|
358
|
+
"tremhz",
|
|
359
|
+
"sord",
|
|
360
|
+
"dyn",
|
|
361
|
+
"bright",
|
|
362
|
+
"ring",
|
|
363
|
+
"body",
|
|
364
|
+
]);
|
|
365
|
+
|
|
294
366
|
/** Parameter name for a Strudel alias (`decay` -> `ring`), or the name. */
|
|
295
367
|
export function stringParamName(word: string): string | undefined {
|
|
296
368
|
if (STRING_PARAMS[word]) return word;
|
|
@@ -358,6 +430,37 @@ function preset(
|
|
|
358
430
|
});
|
|
359
431
|
}
|
|
360
432
|
|
|
433
|
+
// Bowed base (proto/strings/presets.ts `B`, 0.6.1): the bowed rows start
|
|
434
|
+
// here, so BASE and every plucked row stay byte-identical.
|
|
435
|
+
const BOW_BASE: StringValues = {
|
|
436
|
+
...BASE,
|
|
437
|
+
exciter: "bow",
|
|
438
|
+
ring: 0.6,
|
|
439
|
+
damp: 0.5,
|
|
440
|
+
pos: 0.12,
|
|
441
|
+
release: 0.15,
|
|
442
|
+
pressure: 0.5,
|
|
443
|
+
speed: 0.6,
|
|
444
|
+
attack: 0.08,
|
|
445
|
+
vib: 5.5,
|
|
446
|
+
vibmod: 0.18,
|
|
447
|
+
vibdelay: 0.25,
|
|
448
|
+
body: "violin",
|
|
449
|
+
voices: 4,
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
function bowed(
|
|
453
|
+
doc: string,
|
|
454
|
+
styles: string,
|
|
455
|
+
values: StringValues,
|
|
456
|
+
): StringPreset {
|
|
457
|
+
return Object.freeze({
|
|
458
|
+
doc,
|
|
459
|
+
styles,
|
|
460
|
+
values: Object.freeze({ ...BOW_BASE, ...values }),
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
361
464
|
/**
|
|
362
465
|
* The plucked presets, ported from the prototype (stiffness rewritten from
|
|
363
466
|
* B = 0.002 s^2 to the 1e-6 x 400^stiff scale, `gain` is the per-preset
|
|
@@ -738,6 +841,122 @@ export const STRING_PRESETS: Readonly<Record<string, StringPreset>> =
|
|
|
738
841
|
gain: 0.36,
|
|
739
842
|
},
|
|
740
843
|
),
|
|
844
|
+
// ---- bowed (0.6.1, f061-bowed): appended, earlier rows unchanged ----
|
|
845
|
+
violin: bowed("solo violin", "Bach, Brahms, Shostakovich, cantatas", {
|
|
846
|
+
gain: 0.393,
|
|
847
|
+
}),
|
|
848
|
+
viola: bowed("solo viola", "orchestral, chamber", {
|
|
849
|
+
vib: 5.2,
|
|
850
|
+
size: 1.22,
|
|
851
|
+
gain: 0.537,
|
|
852
|
+
}),
|
|
853
|
+
cello: bowed(
|
|
854
|
+
"solo cello",
|
|
855
|
+
"Bach suites, Brahms, Shostakovich, Mitski ballads",
|
|
856
|
+
{ ring: 0.9, pos: 0.1, vib: 5, vibmod: 0.2, size: 2.4, gain: 0.415 },
|
|
857
|
+
),
|
|
858
|
+
contrabass: bowed("arco double bass", "orchestral bass", {
|
|
859
|
+
ring: 1.2,
|
|
860
|
+
pos: 0.1,
|
|
861
|
+
vib: 4.5,
|
|
862
|
+
vibmod: 0.12,
|
|
863
|
+
body: "bass",
|
|
864
|
+
size: 1.2,
|
|
865
|
+
voices: 2,
|
|
866
|
+
gain: 0.316,
|
|
867
|
+
}),
|
|
868
|
+
fiddle: bowed("folk fiddle, straight tone, firm bow", "celtic, bluegrass", {
|
|
869
|
+
pressure: 0.65,
|
|
870
|
+
pos: 0.1,
|
|
871
|
+
attack: 0.03,
|
|
872
|
+
vib: 0,
|
|
873
|
+
gain: 0.504,
|
|
874
|
+
}),
|
|
875
|
+
erhu: bowed("erhu, skin body, wide vibrato", "Chinese, film", {
|
|
876
|
+
pressure: 0.45,
|
|
877
|
+
pos: 0.1,
|
|
878
|
+
vib: 6,
|
|
879
|
+
vibmod: 0.35,
|
|
880
|
+
vibdelay: 0.15,
|
|
881
|
+
body: "skin",
|
|
882
|
+
size: 0.77,
|
|
883
|
+
voices: 2,
|
|
884
|
+
gain: 0.347,
|
|
885
|
+
}),
|
|
886
|
+
kamancheh: bowed("kamancheh spike fiddle", "Persian", {
|
|
887
|
+
pressure: 0.55,
|
|
888
|
+
pos: 0.1,
|
|
889
|
+
vib: 6.5,
|
|
890
|
+
vibmod: 0.25,
|
|
891
|
+
vibdelay: 0.1,
|
|
892
|
+
body: "skin",
|
|
893
|
+
voices: 2,
|
|
894
|
+
gain: 0.43,
|
|
895
|
+
}),
|
|
896
|
+
violins: bowed(
|
|
897
|
+
"violin section",
|
|
898
|
+
"orchestral, Shostakovich, Beethoven, Brahms",
|
|
899
|
+
{ vibmod: 0.15, unison: 6, detune: 0.12, spread: 0.7, gain: 0.399 },
|
|
900
|
+
),
|
|
901
|
+
violas: bowed("viola section", "orchestral", {
|
|
902
|
+
vib: 5.2,
|
|
903
|
+
vibmod: 0.15,
|
|
904
|
+
size: 1.22,
|
|
905
|
+
unison: 4,
|
|
906
|
+
detune: 0.12,
|
|
907
|
+
spread: 0.6,
|
|
908
|
+
gain: 0.57,
|
|
909
|
+
}),
|
|
910
|
+
cellos: bowed("cello section", "orchestral, cantatas", {
|
|
911
|
+
ring: 0.9,
|
|
912
|
+
pos: 0.1,
|
|
913
|
+
vib: 5,
|
|
914
|
+
vibmod: 0.17,
|
|
915
|
+
size: 2.4,
|
|
916
|
+
unison: 4,
|
|
917
|
+
detune: 0.1,
|
|
918
|
+
spread: 0.6,
|
|
919
|
+
gain: 0.46,
|
|
920
|
+
}),
|
|
921
|
+
contrabasses: bowed("double bass section", "orchestral", {
|
|
922
|
+
ring: 1.2,
|
|
923
|
+
pos: 0.1,
|
|
924
|
+
vib: 4.5,
|
|
925
|
+
vibmod: 0.1,
|
|
926
|
+
body: "bass",
|
|
927
|
+
size: 1.2,
|
|
928
|
+
unison: 3,
|
|
929
|
+
detune: 0.08,
|
|
930
|
+
spread: 0.4,
|
|
931
|
+
voices: 2,
|
|
932
|
+
gain: 0.315,
|
|
933
|
+
}),
|
|
934
|
+
pizz: preset(
|
|
935
|
+
"pizzicato string section, plucked with the finger",
|
|
936
|
+
"orchestral, Motown strings, film",
|
|
937
|
+
{
|
|
938
|
+
exciter: "finger",
|
|
939
|
+
ring: 0.6,
|
|
940
|
+
damp: 0.5,
|
|
941
|
+
pos: 0.2,
|
|
942
|
+
bright: 0.45,
|
|
943
|
+
release: 0.08,
|
|
944
|
+
body: "violin",
|
|
945
|
+
unison: 4,
|
|
946
|
+
detune: 0.1,
|
|
947
|
+
spread: 0.6,
|
|
948
|
+
voices: 6,
|
|
949
|
+
gain: 0.497,
|
|
950
|
+
},
|
|
951
|
+
),
|
|
952
|
+
trem: bowed("tremolo string section, rapid bowing", "film, orchestral", {
|
|
953
|
+
tremhz: 13,
|
|
954
|
+
vibmod: 0.1,
|
|
955
|
+
unison: 4,
|
|
956
|
+
detune: 0.12,
|
|
957
|
+
spread: 0.6,
|
|
958
|
+
gain: 0.507,
|
|
959
|
+
}),
|
|
741
960
|
});
|
|
742
961
|
|
|
743
962
|
/** Preset names in table order. */
|
|
@@ -745,6 +964,17 @@ export const STRING_PRESET_NAMES: readonly string[] = Object.freeze(
|
|
|
745
964
|
Object.keys(STRING_PRESETS),
|
|
746
965
|
);
|
|
747
966
|
|
|
967
|
+
/**
|
|
968
|
+
* The bowed-family presets (0.6.1): the rows appended from `violin` on,
|
|
969
|
+
* `pizz` included (a plucked violin section, listed with its family).
|
|
970
|
+
*/
|
|
971
|
+
export const BOWED_PRESET_NAMES: readonly string[] = Object.freeze(
|
|
972
|
+
STRING_PRESET_NAMES.slice(STRING_PRESET_NAMES.indexOf("violin")),
|
|
973
|
+
);
|
|
974
|
+
|
|
975
|
+
/** The preset `bowed` with no name plays. */
|
|
976
|
+
export const DEFAULT_BOWED_PRESET = "cello";
|
|
977
|
+
|
|
748
978
|
/** The preset a bare `string: {}` plays. */
|
|
749
979
|
export const DEFAULT_STRING_PRESET = "nylon";
|
|
750
980
|
|
|
@@ -760,6 +990,11 @@ export const STRING_ALIASES: Readonly<Record<string, string>> = Object.freeze({
|
|
|
760
990
|
cembalo: "harpsichord",
|
|
761
991
|
hammered: "dulcimer",
|
|
762
992
|
sehtar: "setar",
|
|
993
|
+
// bowed (0.6.1); `strings`, `cello` and `contrabass` stay legacy words
|
|
994
|
+
kemence: "kamancheh",
|
|
995
|
+
pizzicato: "pizz",
|
|
996
|
+
tremolo: "trem",
|
|
997
|
+
"bowed-cello": "cello",
|
|
763
998
|
});
|
|
764
999
|
|
|
765
1000
|
/** A preset name for a word or alias, or undefined. */
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which style and seed made a song (quality-08). Stored as the optional
|
|
3
|
+
* `style` field of the score so `/style`, the agent and `song.ts` agree on
|
|
4
|
+
* where a song came from. Shape checks only: the id need not be a style this
|
|
5
|
+
* build knows, so a newer project still loads.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type SongStyle = Readonly<{
|
|
9
|
+
/** Style id from the taxonomy (`deep-house`, `bebop`). */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Generator seed, an integer 0..2^31-1. */
|
|
12
|
+
seed: number;
|
|
13
|
+
/** Bars generated. */
|
|
14
|
+
bars: number;
|
|
15
|
+
/** Second style and its weight 0..1 when the song is a blend. */
|
|
16
|
+
blend?: Readonly<{ id: string; weight: number }>;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
const STYLE_ID = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
20
|
+
export const MAX_STYLE_SEED = 2 ** 31 - 1;
|
|
21
|
+
|
|
22
|
+
/** Thrown for a malformed `style`; the score turns it into a validation error. */
|
|
23
|
+
export class SongStyleError extends Error {
|
|
24
|
+
override name = "SongStyleError";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function fail(message: string): never {
|
|
28
|
+
throw new SongStyleError(`style ${message}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function styleId(value: unknown, label: string): string {
|
|
32
|
+
if (typeof value !== "string" || !STYLE_ID.test(value))
|
|
33
|
+
fail(`${label} must be a style id like "deep-house"`);
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** A frozen, checked style provenance; `null`/`undefined` is none. */
|
|
38
|
+
export function normalizeSongStyle(value: unknown): SongStyle | undefined {
|
|
39
|
+
if (value === undefined || value === null) return undefined;
|
|
40
|
+
if (typeof value !== "object" || Array.isArray(value))
|
|
41
|
+
fail("must be an object { id, seed, bars }");
|
|
42
|
+
const record = value as Record<string, unknown>;
|
|
43
|
+
for (const key of Object.keys(record))
|
|
44
|
+
if (!["id", "seed", "bars", "blend"].includes(key))
|
|
45
|
+
fail(`has no "${key}"; use id, seed, bars, blend`);
|
|
46
|
+
const id = styleId(record.id, "id");
|
|
47
|
+
const seed = record.seed;
|
|
48
|
+
if (
|
|
49
|
+
typeof seed !== "number" ||
|
|
50
|
+
!Number.isInteger(seed) ||
|
|
51
|
+
seed < 0 ||
|
|
52
|
+
seed > MAX_STYLE_SEED
|
|
53
|
+
)
|
|
54
|
+
fail(`seed must be an integer 0..${MAX_STYLE_SEED}`);
|
|
55
|
+
const bars = record.bars;
|
|
56
|
+
if (
|
|
57
|
+
typeof bars !== "number" ||
|
|
58
|
+
!Number.isInteger(bars) ||
|
|
59
|
+
bars < 1 ||
|
|
60
|
+
bars > 256
|
|
61
|
+
)
|
|
62
|
+
fail("bars must be an integer 1..256");
|
|
63
|
+
let blend: SongStyle["blend"];
|
|
64
|
+
if (record.blend !== undefined && record.blend !== null) {
|
|
65
|
+
const raw = record.blend;
|
|
66
|
+
if (typeof raw !== "object" || Array.isArray(raw))
|
|
67
|
+
fail("blend must be { id, weight }");
|
|
68
|
+
const part = raw as Record<string, unknown>;
|
|
69
|
+
const weight = part.weight;
|
|
70
|
+
if (
|
|
71
|
+
typeof weight !== "number" ||
|
|
72
|
+
!Number.isFinite(weight) ||
|
|
73
|
+
weight < 0 ||
|
|
74
|
+
weight > 1
|
|
75
|
+
)
|
|
76
|
+
fail("blend weight must be 0..1");
|
|
77
|
+
blend = Object.freeze({ id: styleId(part.id, "blend id"), weight });
|
|
78
|
+
}
|
|
79
|
+
return Object.freeze({ id, seed, bars, ...(blend ? { blend } : {}) });
|
|
80
|
+
}
|