@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/winds.ts
ADDED
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blown instruments (0.6.1 "Instruments wave 2", lane f061-gamelan-winds):
|
|
3
|
+
* flutes, reeds, saxes and brass played by one waveguide engine
|
|
4
|
+
* (`src/audio/winds/`). Pure and import-light, like `core/resonators.ts`
|
|
5
|
+
* (which re-exports this file): the parameter table, the 21 presets and the
|
|
6
|
+
* validator that the score, the prompt, the menu, the agent and the SDK
|
|
7
|
+
* printer share.
|
|
8
|
+
*
|
|
9
|
+
* A track plays this engine only when its `instrument` is `"wind"` AND it
|
|
10
|
+
* carries a `wind` object (`{ preset, ...overrides }`). A bare `"wind"`
|
|
11
|
+
* instrument without the field keeps the legacy wind tone byte for byte.
|
|
12
|
+
*
|
|
13
|
+
* Models (STK's waveguides, Cook and Scavone, corrected for exact pitch by
|
|
14
|
+
* per-rate trim tables): `jet` flutes, `reed` clarinets, `sax` conical reeds
|
|
15
|
+
* (saxes, and oboe and bassoon until a true double-reed table lands) and
|
|
16
|
+
* `lips` brass.
|
|
17
|
+
*/
|
|
18
|
+
import {
|
|
19
|
+
FxValidationError,
|
|
20
|
+
isRecord,
|
|
21
|
+
normalizeParams,
|
|
22
|
+
type EnumParam,
|
|
23
|
+
type NumberParam,
|
|
24
|
+
type ParamSpec,
|
|
25
|
+
} from "./params.ts";
|
|
26
|
+
|
|
27
|
+
/** Instrument value that selects the wind engine. */
|
|
28
|
+
export const WIND_INSTRUMENT = "wind" as const;
|
|
29
|
+
|
|
30
|
+
export const WIND_MODELS = Object.freeze(["jet", "reed", "sax", "lips"]);
|
|
31
|
+
export type WindModel = "jet" | "reed" | "sax" | "lips";
|
|
32
|
+
|
|
33
|
+
export const WIND_MUTES = Object.freeze([
|
|
34
|
+
"open",
|
|
35
|
+
"straight",
|
|
36
|
+
"cup",
|
|
37
|
+
"harmon",
|
|
38
|
+
"plunger",
|
|
39
|
+
]);
|
|
40
|
+
export type WindMute = "open" | "straight" | "cup" | "harmon" | "plunger";
|
|
41
|
+
|
|
42
|
+
export const WIND_PRESET_NAMES = Object.freeze([
|
|
43
|
+
"flute",
|
|
44
|
+
"recorder",
|
|
45
|
+
"whistle",
|
|
46
|
+
"ney",
|
|
47
|
+
"shakuhachi",
|
|
48
|
+
"panpipe",
|
|
49
|
+
"suling",
|
|
50
|
+
"bansuri",
|
|
51
|
+
"clarinet",
|
|
52
|
+
"bassclarinet",
|
|
53
|
+
"oboe",
|
|
54
|
+
"bassoon",
|
|
55
|
+
"sax",
|
|
56
|
+
"altosax",
|
|
57
|
+
"barisax",
|
|
58
|
+
"trumpet",
|
|
59
|
+
"harmon",
|
|
60
|
+
"plunger",
|
|
61
|
+
"trombone",
|
|
62
|
+
"tuba",
|
|
63
|
+
"horn",
|
|
64
|
+
] as const);
|
|
65
|
+
export type WindPresetName = (typeof WIND_PRESET_NAMES)[number];
|
|
66
|
+
|
|
67
|
+
/** Extra words that pick a preset (`wind preset saxophone`). */
|
|
68
|
+
export const WIND_ALIASES: Readonly<Record<string, WindPresetName>> =
|
|
69
|
+
Object.freeze({
|
|
70
|
+
tinwhistle: "whistle",
|
|
71
|
+
pennywhistle: "whistle",
|
|
72
|
+
nay: "ney",
|
|
73
|
+
panflute: "panpipe",
|
|
74
|
+
panpipes: "panpipe",
|
|
75
|
+
saxophone: "sax",
|
|
76
|
+
tenorsax: "sax",
|
|
77
|
+
tenor: "sax",
|
|
78
|
+
alto: "altosax",
|
|
79
|
+
bari: "barisax",
|
|
80
|
+
baritonesax: "barisax",
|
|
81
|
+
frenchhorn: "horn",
|
|
82
|
+
mutedtrumpet: "harmon",
|
|
83
|
+
wahtrumpet: "plunger",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/** The browse group "Winds and brass", in menu order. */
|
|
87
|
+
export const WIND_GROUPS: readonly Readonly<{
|
|
88
|
+
label: string;
|
|
89
|
+
presets: readonly WindPresetName[];
|
|
90
|
+
}>[] = Object.freeze([
|
|
91
|
+
{
|
|
92
|
+
label: "Flutes",
|
|
93
|
+
presets: [
|
|
94
|
+
"flute",
|
|
95
|
+
"recorder",
|
|
96
|
+
"whistle",
|
|
97
|
+
"ney",
|
|
98
|
+
"shakuhachi",
|
|
99
|
+
"panpipe",
|
|
100
|
+
"suling",
|
|
101
|
+
"bansuri",
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: "Saxophones",
|
|
106
|
+
presets: ["sax", "altosax", "barisax"],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
label: "Reeds",
|
|
110
|
+
presets: ["clarinet", "bassclarinet", "oboe", "bassoon"],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
label: "Brass",
|
|
114
|
+
presets: ["trumpet", "harmon", "plunger", "trombone", "tuba", "horn"],
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
const num = (
|
|
119
|
+
min: number,
|
|
120
|
+
max: number,
|
|
121
|
+
fallback: number,
|
|
122
|
+
step: number | "log",
|
|
123
|
+
doc: string,
|
|
124
|
+
extra: Partial<NumberParam> = {},
|
|
125
|
+
): NumberParam =>
|
|
126
|
+
Object.freeze({
|
|
127
|
+
kind: "number",
|
|
128
|
+
min,
|
|
129
|
+
max,
|
|
130
|
+
default: fallback,
|
|
131
|
+
step,
|
|
132
|
+
optional: true,
|
|
133
|
+
doc,
|
|
134
|
+
...extra,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Every wind parameter. All are optional: an absent one takes the preset's
|
|
139
|
+
* value, then the default here. `automate` ones have a `wind-<param>` lane
|
|
140
|
+
* the voice reads every 32-sample control tick.
|
|
141
|
+
*/
|
|
142
|
+
export const WIND_PARAMS: Readonly<Record<string, ParamSpec>> = Object.freeze({
|
|
143
|
+
model: Object.freeze({
|
|
144
|
+
kind: "enum",
|
|
145
|
+
values: WIND_MODELS,
|
|
146
|
+
default: "jet",
|
|
147
|
+
optional: true,
|
|
148
|
+
doc: "exciter and bore: jet (flute), reed (clarinet), sax (conical reed), lips (brass)",
|
|
149
|
+
}) as EnumParam,
|
|
150
|
+
breath: num(0, 1, 0.6, 0.05, "blowing pressure: swells, louder and fuller", {
|
|
151
|
+
automate: true,
|
|
152
|
+
}),
|
|
153
|
+
noise: num(0, 1, 0.08, 0.05, "breath noise", { automate: true }),
|
|
154
|
+
attack: num(0.001, 2, 0.04, "log", "breath rise", {
|
|
155
|
+
unit: "s",
|
|
156
|
+
strudel: ["att"],
|
|
157
|
+
}),
|
|
158
|
+
release: num(0.005, 2, 0.08, "log", "breath fall", {
|
|
159
|
+
unit: "s",
|
|
160
|
+
strudel: ["rel"],
|
|
161
|
+
}),
|
|
162
|
+
vib: num(0, 12, 5, 0.25, "vibrato rate", {
|
|
163
|
+
unit: "Hz",
|
|
164
|
+
strudel: ["vibrato"],
|
|
165
|
+
}),
|
|
166
|
+
vibmod: num(0, 1, 0, 0.02, "vibrato depth", {
|
|
167
|
+
unit: "st",
|
|
168
|
+
strudel: ["vmod", "vibdepth", "depth"],
|
|
169
|
+
}),
|
|
170
|
+
reed: num(0, 1, 0.5, 0.05, "reed stiffness, jet offset or lip tension"),
|
|
171
|
+
bright: num(0, 1, 0.5, 0.05, "bore loss: dark to bright"),
|
|
172
|
+
stopped: Object.freeze({
|
|
173
|
+
kind: "boolean",
|
|
174
|
+
default: false,
|
|
175
|
+
optional: true,
|
|
176
|
+
doc: "stopped pipe, odd harmonics (jet only)",
|
|
177
|
+
}),
|
|
178
|
+
mute: Object.freeze({
|
|
179
|
+
kind: "enum",
|
|
180
|
+
values: WIND_MUTES,
|
|
181
|
+
default: "open",
|
|
182
|
+
optional: true,
|
|
183
|
+
doc: "brass mute: open, straight, cup, harmon or plunger",
|
|
184
|
+
}) as EnumParam,
|
|
185
|
+
wah: num(0, 1, 1, 0.05, "plunger opening: 0 closed, 1 open", {
|
|
186
|
+
automate: true,
|
|
187
|
+
}),
|
|
188
|
+
wahenv: num(0, 1, 0, 0.05, "plunger opens with each note (doo-wah)"),
|
|
189
|
+
growl: num(0, 1, 0, 0.05, "hum into the horn: rough, raspy", {
|
|
190
|
+
automate: true,
|
|
191
|
+
}),
|
|
192
|
+
flutter: num(0, 1, 0, 0.05, "flutter tongue (rolled r)", { automate: true }),
|
|
193
|
+
players: num(1, 8, 1, 1, "section size, spread over chord tones", {
|
|
194
|
+
integer: true,
|
|
195
|
+
}),
|
|
196
|
+
gain: num(0, 2, 0.8, 0.05, "level"),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
/** Menu rows most people reach for. */
|
|
200
|
+
export const WIND_SIMPLE = Object.freeze([
|
|
201
|
+
"breath",
|
|
202
|
+
"bright",
|
|
203
|
+
"mute",
|
|
204
|
+
"players",
|
|
205
|
+
"growl",
|
|
206
|
+
]);
|
|
207
|
+
|
|
208
|
+
/** Resolved settings the engine plays. */
|
|
209
|
+
export type WindSettings = Readonly<{
|
|
210
|
+
model: WindModel;
|
|
211
|
+
breath: number;
|
|
212
|
+
noise: number;
|
|
213
|
+
attack: number;
|
|
214
|
+
release: number;
|
|
215
|
+
vib: number;
|
|
216
|
+
vibmod: number;
|
|
217
|
+
reed: number;
|
|
218
|
+
bright: number;
|
|
219
|
+
stopped: boolean;
|
|
220
|
+
mute: WindMute;
|
|
221
|
+
wah: number;
|
|
222
|
+
wahenv: number;
|
|
223
|
+
growl: number;
|
|
224
|
+
flutter: number;
|
|
225
|
+
players: number;
|
|
226
|
+
gain: number;
|
|
227
|
+
}>;
|
|
228
|
+
|
|
229
|
+
export const WIND_DEFAULTS: WindSettings = Object.freeze({
|
|
230
|
+
model: "jet",
|
|
231
|
+
breath: 0.6,
|
|
232
|
+
noise: 0.08,
|
|
233
|
+
attack: 0.04,
|
|
234
|
+
release: 0.08,
|
|
235
|
+
vib: 5,
|
|
236
|
+
vibmod: 0,
|
|
237
|
+
reed: 0.5,
|
|
238
|
+
bright: 0.5,
|
|
239
|
+
stopped: false,
|
|
240
|
+
mute: "open",
|
|
241
|
+
wah: 1,
|
|
242
|
+
wahenv: 0,
|
|
243
|
+
growl: 0,
|
|
244
|
+
flutter: 0,
|
|
245
|
+
players: 1,
|
|
246
|
+
gain: 0.8,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
export type WindPreset = Readonly<{
|
|
250
|
+
settings: WindSettings;
|
|
251
|
+
/** MIDI range the instrument is built for (sounding pitch). */
|
|
252
|
+
range: readonly [number, number];
|
|
253
|
+
doc: string;
|
|
254
|
+
styles: string;
|
|
255
|
+
}>;
|
|
256
|
+
|
|
257
|
+
const preset = (
|
|
258
|
+
settings: Partial<WindSettings>,
|
|
259
|
+
range: [number, number],
|
|
260
|
+
doc: string,
|
|
261
|
+
styles: string,
|
|
262
|
+
): WindPreset =>
|
|
263
|
+
Object.freeze({
|
|
264
|
+
settings: Object.freeze({ ...WIND_DEFAULTS, ...settings }),
|
|
265
|
+
range: Object.freeze(range) as readonly [number, number],
|
|
266
|
+
doc,
|
|
267
|
+
styles,
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Presets, ported from the reviewed prototype (proto/resonators/presets.ts)
|
|
272
|
+
* and extended to the 21 of the revised brief. Ranges are sounding pitch
|
|
273
|
+
* (written ranges of the transposing instruments, transposed).
|
|
274
|
+
*/
|
|
275
|
+
export const WIND_PRESETS: Readonly<Record<WindPresetName, WindPreset>> =
|
|
276
|
+
Object.freeze({
|
|
277
|
+
flute: preset(
|
|
278
|
+
{
|
|
279
|
+
model: "jet",
|
|
280
|
+
breath: 0.6,
|
|
281
|
+
noise: 0.12,
|
|
282
|
+
attack: 0.06,
|
|
283
|
+
vib: 5,
|
|
284
|
+
vibmod: 0.12,
|
|
285
|
+
bright: 0.5,
|
|
286
|
+
},
|
|
287
|
+
[60, 96],
|
|
288
|
+
"concert flute, airy with gentle vibrato",
|
|
289
|
+
"Debussy, Bach cantata, jazz flute",
|
|
290
|
+
),
|
|
291
|
+
recorder: preset(
|
|
292
|
+
{ model: "jet", breath: 0.5, noise: 0.06, attack: 0.02, bright: 0.6 },
|
|
293
|
+
[65, 93],
|
|
294
|
+
"alto recorder, pure and straight",
|
|
295
|
+
"Bach cantata, early music",
|
|
296
|
+
),
|
|
297
|
+
whistle: preset(
|
|
298
|
+
{ model: "jet", breath: 0.6, noise: 0.08, attack: 0.015, bright: 0.7 },
|
|
299
|
+
[74, 98],
|
|
300
|
+
"tin whistle, bright and reedy",
|
|
301
|
+
"celtic",
|
|
302
|
+
),
|
|
303
|
+
ney: preset(
|
|
304
|
+
{
|
|
305
|
+
model: "jet",
|
|
306
|
+
breath: 0.45,
|
|
307
|
+
noise: 0.35,
|
|
308
|
+
attack: 0.12,
|
|
309
|
+
vib: 5.5,
|
|
310
|
+
vibmod: 0.08,
|
|
311
|
+
bright: 0.3,
|
|
312
|
+
},
|
|
313
|
+
[55, 86],
|
|
314
|
+
"Persian reed flute, very breathy",
|
|
315
|
+
"Persian, Sufi, ambient",
|
|
316
|
+
),
|
|
317
|
+
shakuhachi: preset(
|
|
318
|
+
{
|
|
319
|
+
model: "jet",
|
|
320
|
+
breath: 0.55,
|
|
321
|
+
noise: 0.3,
|
|
322
|
+
attack: 0.08,
|
|
323
|
+
vib: 4,
|
|
324
|
+
vibmod: 0.2,
|
|
325
|
+
bright: 0.35,
|
|
326
|
+
},
|
|
327
|
+
[62, 86],
|
|
328
|
+
"bamboo end-blown flute, breath accents",
|
|
329
|
+
"Sakamoto, OPN, ambient",
|
|
330
|
+
),
|
|
331
|
+
panpipe: preset(
|
|
332
|
+
{
|
|
333
|
+
model: "jet",
|
|
334
|
+
stopped: true,
|
|
335
|
+
breath: 0.6,
|
|
336
|
+
noise: 0.2,
|
|
337
|
+
attack: 0.03,
|
|
338
|
+
bright: 0.5,
|
|
339
|
+
},
|
|
340
|
+
[60, 96],
|
|
341
|
+
"stopped cane pipes, hollow odd harmonics",
|
|
342
|
+
"ambient, Andean, Eno",
|
|
343
|
+
),
|
|
344
|
+
suling: preset(
|
|
345
|
+
{
|
|
346
|
+
model: "jet",
|
|
347
|
+
breath: 0.5,
|
|
348
|
+
noise: 0.25,
|
|
349
|
+
attack: 0.05,
|
|
350
|
+
vib: 5.5,
|
|
351
|
+
vibmod: 0.1,
|
|
352
|
+
bright: 0.45,
|
|
353
|
+
},
|
|
354
|
+
[67, 93],
|
|
355
|
+
"Sundanese and Balinese ring flute, soft and breathy",
|
|
356
|
+
"gamelan, degung, ambient",
|
|
357
|
+
),
|
|
358
|
+
bansuri: preset(
|
|
359
|
+
{
|
|
360
|
+
model: "jet",
|
|
361
|
+
breath: 0.55,
|
|
362
|
+
noise: 0.22,
|
|
363
|
+
attack: 0.07,
|
|
364
|
+
vib: 5,
|
|
365
|
+
vibmod: 0.15,
|
|
366
|
+
bright: 0.4,
|
|
367
|
+
},
|
|
368
|
+
[55, 84],
|
|
369
|
+
"Indian bamboo flute, warm with deep vibrato",
|
|
370
|
+
"Hindustani, Bollywood, ambient",
|
|
371
|
+
),
|
|
372
|
+
clarinet: preset(
|
|
373
|
+
{ model: "reed", breath: 0.6, noise: 0.05, attack: 0.04, reed: 0.5 },
|
|
374
|
+
[50, 91],
|
|
375
|
+
"cylindrical bore, woody odd harmonics",
|
|
376
|
+
"Brahms, jazz, klezmer, Motown",
|
|
377
|
+
),
|
|
378
|
+
bassclarinet: preset(
|
|
379
|
+
{
|
|
380
|
+
model: "reed",
|
|
381
|
+
breath: 0.6,
|
|
382
|
+
noise: 0.06,
|
|
383
|
+
attack: 0.05,
|
|
384
|
+
reed: 0.4,
|
|
385
|
+
bright: 0.4,
|
|
386
|
+
},
|
|
387
|
+
[37, 72],
|
|
388
|
+
"bass clarinet, dark and hollow",
|
|
389
|
+
"Bitches Brew, Messiaen, film",
|
|
390
|
+
),
|
|
391
|
+
oboe: preset(
|
|
392
|
+
{
|
|
393
|
+
model: "sax",
|
|
394
|
+
breath: 0.6,
|
|
395
|
+
noise: 0.04,
|
|
396
|
+
attack: 0.03,
|
|
397
|
+
vib: 5.5,
|
|
398
|
+
vibmod: 0.08,
|
|
399
|
+
reed: 0.8,
|
|
400
|
+
bright: 0.75,
|
|
401
|
+
},
|
|
402
|
+
[58, 91],
|
|
403
|
+
"double reed, nasal and singing",
|
|
404
|
+
"Bach, Ravel, Morricone",
|
|
405
|
+
),
|
|
406
|
+
bassoon: preset(
|
|
407
|
+
{
|
|
408
|
+
model: "sax",
|
|
409
|
+
breath: 0.6,
|
|
410
|
+
noise: 0.04,
|
|
411
|
+
attack: 0.04,
|
|
412
|
+
vib: 5,
|
|
413
|
+
vibmod: 0.06,
|
|
414
|
+
reed: 0.7,
|
|
415
|
+
bright: 0.35,
|
|
416
|
+
},
|
|
417
|
+
[34, 72],
|
|
418
|
+
"bassoon, reedy and woody low voice",
|
|
419
|
+
"Stravinsky, Prokofiev, orchestral",
|
|
420
|
+
),
|
|
421
|
+
sax: preset(
|
|
422
|
+
{
|
|
423
|
+
model: "sax",
|
|
424
|
+
breath: 0.65,
|
|
425
|
+
noise: 0.1,
|
|
426
|
+
attack: 0.03,
|
|
427
|
+
vib: 5.2,
|
|
428
|
+
vibmod: 0.15,
|
|
429
|
+
},
|
|
430
|
+
[44, 79],
|
|
431
|
+
"tenor sax, warm to raspy with breath",
|
|
432
|
+
"jazz, Motown, soul, funk",
|
|
433
|
+
),
|
|
434
|
+
altosax: preset(
|
|
435
|
+
{
|
|
436
|
+
model: "sax",
|
|
437
|
+
breath: 0.65,
|
|
438
|
+
noise: 0.09,
|
|
439
|
+
attack: 0.03,
|
|
440
|
+
vib: 5.4,
|
|
441
|
+
vibmod: 0.12,
|
|
442
|
+
bright: 0.55,
|
|
443
|
+
},
|
|
444
|
+
[49, 81],
|
|
445
|
+
"alto sax, bright and vocal",
|
|
446
|
+
"bebop, Motown, soul",
|
|
447
|
+
),
|
|
448
|
+
barisax: preset(
|
|
449
|
+
{
|
|
450
|
+
model: "sax",
|
|
451
|
+
breath: 0.68,
|
|
452
|
+
noise: 0.1,
|
|
453
|
+
attack: 0.04,
|
|
454
|
+
vib: 5,
|
|
455
|
+
vibmod: 0.08,
|
|
456
|
+
bright: 0.45,
|
|
457
|
+
},
|
|
458
|
+
[36, 69],
|
|
459
|
+
"baritone sax, honking low end",
|
|
460
|
+
"Motown, funk, ska",
|
|
461
|
+
),
|
|
462
|
+
trumpet: preset(
|
|
463
|
+
{
|
|
464
|
+
model: "lips",
|
|
465
|
+
breath: 0.7,
|
|
466
|
+
noise: 0.03,
|
|
467
|
+
attack: 0.03,
|
|
468
|
+
bright: 0.6,
|
|
469
|
+
vib: 5.5,
|
|
470
|
+
},
|
|
471
|
+
[52, 82],
|
|
472
|
+
"open trumpet, brightens as it gets louder",
|
|
473
|
+
"Louis Armstrong, Motown, salsa, jazz",
|
|
474
|
+
),
|
|
475
|
+
harmon: preset(
|
|
476
|
+
{
|
|
477
|
+
model: "lips",
|
|
478
|
+
breath: 0.7,
|
|
479
|
+
noise: 0.03,
|
|
480
|
+
attack: 0.03,
|
|
481
|
+
bright: 0.6,
|
|
482
|
+
mute: "harmon",
|
|
483
|
+
},
|
|
484
|
+
[52, 82],
|
|
485
|
+
"trumpet with a harmon mute, buzzy and close",
|
|
486
|
+
"jazz, Radiohead, Sakamoto",
|
|
487
|
+
),
|
|
488
|
+
plunger: preset(
|
|
489
|
+
{
|
|
490
|
+
model: "lips",
|
|
491
|
+
breath: 0.75,
|
|
492
|
+
noise: 0.04,
|
|
493
|
+
attack: 0.03,
|
|
494
|
+
bright: 0.6,
|
|
495
|
+
mute: "plunger",
|
|
496
|
+
wah: 0.3,
|
|
497
|
+
},
|
|
498
|
+
[52, 82],
|
|
499
|
+
"trumpet with a plunger: automate wah for ya-ya",
|
|
500
|
+
"Louis Armstrong, Duke Ellington, funk",
|
|
501
|
+
),
|
|
502
|
+
trombone: preset(
|
|
503
|
+
{ model: "lips", breath: 0.7, noise: 0.03, attack: 0.04, bright: 0.45 },
|
|
504
|
+
[40, 72],
|
|
505
|
+
"slide trombone, broad",
|
|
506
|
+
"salsa, Motown, jazz",
|
|
507
|
+
),
|
|
508
|
+
tuba: preset(
|
|
509
|
+
{ model: "lips", breath: 0.7, noise: 0.02, attack: 0.06, bright: 0.3 },
|
|
510
|
+
[28, 58],
|
|
511
|
+
"tuba, round and deep",
|
|
512
|
+
"New Orleans brass band, oompah, orchestral",
|
|
513
|
+
),
|
|
514
|
+
horn: preset(
|
|
515
|
+
{ model: "lips", breath: 0.6, noise: 0.02, attack: 0.06, bright: 0.25 },
|
|
516
|
+
[41, 77],
|
|
517
|
+
"French horn, dark and round",
|
|
518
|
+
"Brahms, Beethoven, orchestral",
|
|
519
|
+
),
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
/** Default preset of a `wind` field that names none. */
|
|
523
|
+
export const DEFAULT_WIND_PRESET: WindPresetName = "flute";
|
|
524
|
+
|
|
525
|
+
/** A track's stored wind settings: a preset plus overrides, all optional. */
|
|
526
|
+
export type TrackWind = Readonly<{
|
|
527
|
+
preset?: WindPresetName;
|
|
528
|
+
model?: WindModel;
|
|
529
|
+
breath?: number;
|
|
530
|
+
noise?: number;
|
|
531
|
+
attack?: number;
|
|
532
|
+
release?: number;
|
|
533
|
+
vib?: number;
|
|
534
|
+
vibmod?: number;
|
|
535
|
+
reed?: number;
|
|
536
|
+
bright?: number;
|
|
537
|
+
stopped?: boolean;
|
|
538
|
+
mute?: WindMute;
|
|
539
|
+
wah?: number;
|
|
540
|
+
wahenv?: number;
|
|
541
|
+
growl?: number;
|
|
542
|
+
flutter?: number;
|
|
543
|
+
players?: number;
|
|
544
|
+
gain?: number;
|
|
545
|
+
}>;
|
|
546
|
+
|
|
547
|
+
export function isWindPreset(name: string): name is WindPresetName {
|
|
548
|
+
return (WIND_PRESET_NAMES as readonly string[]).includes(name);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/** A preset word or alias (`saxophone`) to its preset; undefined if neither. */
|
|
552
|
+
export function windPresetFor(word: string): WindPresetName | undefined {
|
|
553
|
+
const lower = word.trim().toLowerCase();
|
|
554
|
+
if (isWindPreset(lower)) return lower;
|
|
555
|
+
return WIND_ALIASES[lower];
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export function isWindParam(name: string): boolean {
|
|
559
|
+
return Object.prototype.hasOwnProperty.call(WIND_PARAMS, name);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/** Strudel spelling (`att`, `rel`) to a wind parameter name. */
|
|
563
|
+
export function windParamName(name: string): string | undefined {
|
|
564
|
+
if (isWindParam(name)) return name;
|
|
565
|
+
for (const [key, spec] of Object.entries(WIND_PARAMS))
|
|
566
|
+
if (spec.strudel?.includes(name)) return key;
|
|
567
|
+
return undefined;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Validates a `wind` field: `{ preset?, ...overrides }`, null or absent
|
|
572
|
+
* meaning none. Keys come out in canonical order (preset, then
|
|
573
|
+
* `WIND_PARAMS` order). `{}` is kept: it means the default preset.
|
|
574
|
+
*/
|
|
575
|
+
export function normalizeWind(input: unknown): TrackWind | undefined {
|
|
576
|
+
if (input === undefined || input === null) return undefined;
|
|
577
|
+
if (!isRecord(input))
|
|
578
|
+
throw new FxValidationError("track wind must be an object or null");
|
|
579
|
+
const params: Record<string, unknown> = {};
|
|
580
|
+
let presetName: WindPresetName | undefined;
|
|
581
|
+
for (const [key, value] of Object.entries(input)) {
|
|
582
|
+
if (value === undefined || value === null) continue;
|
|
583
|
+
if (key === "preset") {
|
|
584
|
+
const resolved =
|
|
585
|
+
typeof value === "string" ? windPresetFor(value) : undefined;
|
|
586
|
+
if (!resolved)
|
|
587
|
+
throw new FxValidationError(
|
|
588
|
+
`wind preset must be one of ${WIND_PRESET_NAMES.join(", ")}`,
|
|
589
|
+
);
|
|
590
|
+
presetName = resolved;
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const name = windParamName(key);
|
|
594
|
+
if (!name)
|
|
595
|
+
throw new FxValidationError(
|
|
596
|
+
`wind has no parameter "${key.slice(0, 32)}"`,
|
|
597
|
+
);
|
|
598
|
+
params[name] = value;
|
|
599
|
+
}
|
|
600
|
+
const values = normalizeParams(WIND_PARAMS, params, "wind", false);
|
|
601
|
+
return Object.freeze({
|
|
602
|
+
...(presetName ? { preset: presetName } : {}),
|
|
603
|
+
...values,
|
|
604
|
+
}) as TrackWind;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/** The preset a `wind` field plays. */
|
|
608
|
+
export function windPresetOf(wind: TrackWind | undefined): WindPresetName {
|
|
609
|
+
return wind?.preset ?? DEFAULT_WIND_PRESET;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* The settings a `wind` field plays: defaults, then the preset, then
|
|
614
|
+
* explicit overrides, then any automation lane values from `lane`.
|
|
615
|
+
*/
|
|
616
|
+
export function windSettings(
|
|
617
|
+
wind: TrackWind | undefined,
|
|
618
|
+
lane?: (param: string) => number | undefined,
|
|
619
|
+
): WindSettings {
|
|
620
|
+
const base = WIND_PRESETS[windPresetOf(wind)].settings;
|
|
621
|
+
const out: Record<string, number | string | boolean> = { ...base };
|
|
622
|
+
if (wind)
|
|
623
|
+
for (const [key, value] of Object.entries(wind))
|
|
624
|
+
if (key !== "preset" && value !== undefined) out[key] = value;
|
|
625
|
+
if (lane)
|
|
626
|
+
for (const { param } of WIND_LANE_PARAMS) {
|
|
627
|
+
const value = lane(param);
|
|
628
|
+
if (value !== undefined) out[param] = value;
|
|
629
|
+
}
|
|
630
|
+
return Object.freeze(out) as WindSettings;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/** Parameters with a `wind-<param>` automation lane. */
|
|
634
|
+
export const WIND_LANE_PARAMS: readonly Readonly<{
|
|
635
|
+
param: string;
|
|
636
|
+
spec: NumberParam;
|
|
637
|
+
}>[] = Object.freeze(
|
|
638
|
+
Object.entries(WIND_PARAMS)
|
|
639
|
+
.filter(
|
|
640
|
+
(entry): entry is [string, NumberParam] =>
|
|
641
|
+
entry[1].kind === "number" && entry[1].automate === true,
|
|
642
|
+
)
|
|
643
|
+
.map(([param, spec]) => Object.freeze({ param, spec })),
|
|
644
|
+
);
|
|
645
|
+
|
|
646
|
+
/** Voices one wind track sounds at once; the oldest onset is stolen. */
|
|
647
|
+
export const MAX_WIND_VOICES = 24;
|
|
648
|
+
|
|
649
|
+
/** Ring after the last breath ends, in seconds. */
|
|
650
|
+
export function windTailSeconds(wind: TrackWind | undefined): number {
|
|
651
|
+
return windSettings(wind).release + 0.15;
|
|
652
|
+
}
|
package/guides/agent.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: agent
|
|
3
|
+
title: Agent
|
|
4
|
+
order: 11
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The agent is optional: commands work offline. With a provider, plain
|
|
8
|
+
requests go to it, and it types the commands it runs so you learn them.
|
|
9
|
+
|
|
10
|
+
## Ask
|
|
11
|
+
|
|
12
|
+
- "make the reverb wetter and play a C minor arpeggio"
|
|
13
|
+
|
|
14
|
+
## Type it yourself
|
|
15
|
+
|
|
16
|
+
- `model key` · `model` picker · `model fast` · `logout`
|
|
17
|
+
- `showme on` · `showme quiet` · `/auth --check`
|
|
18
|
+
|
|
19
|
+
## Menu
|
|
20
|
+
|
|
21
|
+
- Ctrl-K › Project › agent › model · show-me · model key
|
|
22
|
+
|
|
23
|
+
## Keys
|
|
24
|
+
|
|
25
|
+
- Enter sends · Alt-Enter runs next · Ctrl-Q NOW/NEXT · Esc stops
|
|
26
|
+
|
|
27
|
+
## Next
|
|
28
|
+
|
|
29
|
+
- `guide show-me` · `guide providers` · `guide web-search`
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: arrange
|
|
3
|
+
title: Arrange
|
|
4
|
+
order: 9
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Notes make tracks, tracks make sections, sections make the form.
|
|
8
|
+
|
|
9
|
+
## Ask
|
|
10
|
+
|
|
11
|
+
- "make 16 bars of deep house" · "add a chorus that lifts at bar 9"
|
|
12
|
+
|
|
13
|
+
## Type it yourself
|
|
14
|
+
|
|
15
|
+
- `add E4 at 2 for 0.5` · `track bass` · `tracks`
|
|
16
|
+
- `section chorus 9-16` · `form verse verse chorus verse`
|
|
17
|
+
- `build into chorus` · `drop chorus` · `fill chorus`
|
|
18
|
+
- `style deep-house 16` · `bars 8` · `extend 4 bars`
|
|
19
|
+
|
|
20
|
+
## Menu
|
|
21
|
+
|
|
22
|
+
- Ctrl-K › Arrange › tracks · sections · form · style
|
|
23
|
+
|
|
24
|
+
## Keys
|
|
25
|
+
|
|
26
|
+
- `view all` shows every track · Ctrl-O the transcript
|
|
27
|
+
|
|
28
|
+
## Next
|
|
29
|
+
|
|
30
|
+
- `guide notes` · `guide tracks` · `guide tempo` · `guide styles`
|