@hraness/dawg 0.4.1 → 0.5.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 +70 -0
- package/DAWG.md +293 -31
- package/README.md +4 -4
- package/core/chords.ts +288 -7
- package/core/diff.ts +37 -12
- package/core/expression.ts +1241 -0
- package/core/loop.ts +23 -0
- package/core/master.ts +455 -0
- package/core/midi.ts +452 -0
- package/core/rhythm.ts +7 -2
- package/core/score.ts +536 -56
- package/core/sdk/eval-child.ts +38 -3
- package/core/sdk/print.ts +445 -14
- package/core/sdk/v1.ts +1709 -23
- package/core/sections.ts +2046 -0
- package/core/synth.ts +11 -1
- package/core/tempo.ts +1318 -0
- package/core/tuning.ts +1180 -0
- package/guides/audition.md +26 -0
- package/guides/automation.md +26 -0
- package/guides/chords.md +28 -0
- package/guides/effects.md +27 -0
- package/guides/faders.md +29 -0
- package/guides/files.md +28 -0
- package/guides/getting-started.md +26 -0
- package/guides/index.ts +75 -0
- package/guides/keys.md +27 -0
- package/guides/media.md +27 -0
- package/guides/mix.md +23 -0
- package/guides/music.md +14 -0
- package/guides/notes.md +26 -0
- package/guides/performance.md +26 -0
- package/guides/play.md +24 -0
- package/guides/project.md +13 -0
- package/guides/providers.md +25 -0
- package/guides/rhythm.md +26 -0
- package/guides/sessions.md +21 -0
- package/guides/sound.md +15 -0
- package/guides/sounds.md +25 -0
- package/guides/tempo.md +26 -0
- package/guides/tracks.md +25 -0
- package/guides/web-search.md +21 -0
- package/package.json +3 -1
- package/src/agent/agent.ts +2 -0
- package/src/agent/brief.ts +77 -3
- package/src/agent/chord-tools.ts +9 -1
- package/src/agent/expression-tools.ts +336 -0
- package/src/agent/master-tools.ts +299 -0
- package/src/agent/models.ts +4 -4
- package/src/agent/ops.ts +29 -4
- package/src/agent/planner.ts +45 -2
- package/src/agent/preview-tool.ts +21 -3
- package/src/agent/section-tools.ts +411 -0
- package/src/agent/time-tools.ts +290 -0
- package/src/agent/tools.ts +36 -2
- package/src/agent/tuning-tools.ts +301 -0
- package/src/agent/xcb-agent.ts +2 -0
- package/src/audio/arrange.ts +471 -0
- package/src/audio/audition.ts +16 -3
- package/src/audio/click.ts +113 -1
- package/src/audio/clock.ts +71 -5
- package/src/audio/effects/bus.ts +5 -4
- package/src/audio/effects/common.ts +30 -1
- package/src/audio/effects/dynamics.ts +2 -1
- package/src/audio/effects/filter.ts +5 -3
- package/src/audio/effects/modulation.ts +5 -1
- package/src/audio/effects/space.ts +92 -2
- package/src/audio/engine.ts +90 -20
- package/src/audio/live.ts +33 -6
- package/src/audio/loudness.ts +551 -0
- package/src/audio/master.ts +660 -0
- package/src/audio/measure-worker.ts +45 -0
- package/src/audio/measure.ts +110 -0
- package/src/audio/player.ts +11 -6
- package/src/audio/preview.ts +74 -14
- package/src/audio/render-worker.ts +6 -1
- package/src/audio/renderer.ts +7 -1
- package/src/audio/sampler.ts +108 -19
- package/src/audio/synth/voice.ts +60 -13
- package/src/audio/synth/zzfx.ts +10 -4
- package/src/audio/warp.ts +86 -0
- package/src/audio/wav.ts +301 -26
- package/src/commands/arrange.ts +949 -0
- package/src/commands/expression.ts +934 -0
- package/src/commands/help.ts +281 -24
- package/src/commands/master.ts +361 -0
- package/src/commands/music.ts +6 -1
- package/src/commands/synth.ts +11 -1
- package/src/commands/time.ts +964 -0
- package/src/commands/tuning.ts +490 -0
- package/src/main.ts +709 -33
- package/src/render.ts +109 -7
- package/src/session/daemon.ts +18 -8
- package/src/session/naming.ts +8 -1
- package/src/session/rebase.ts +21 -0
- package/src/tui/arrange-menu.ts +390 -0
- package/src/tui/audition.ts +38 -5
- package/src/tui/fader.ts +409 -0
- package/src/tui/menu-time.ts +401 -0
- package/src/tui/menu.ts +635 -14
- package/src/tui/performance-menu.ts +235 -0
- package/src/tui/play-chords.ts +3 -1
- package/src/tui/play-mode.ts +150 -6
- package/src/tui/play-session.ts +414 -41
- package/tui/app.ts +262 -13
- package/tui/arrange-strip.ts +174 -0
- package/tui/drawer.ts +478 -0
- package/tui/grammar.ts +63 -1
- package/tui/guide.ts +351 -0
- package/tui/highway.ts +87 -4
- package/tui/hits.ts +68 -0
- package/tui/input.ts +7 -0
- package/tui/keys.ts +72 -0
package/src/commands/help.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* app commands take a slash (bare aliases keep working but are listed once,
|
|
5
5
|
* in their canonical form).
|
|
6
6
|
*/
|
|
7
|
+
import { EXPRESSION_USAGE } from "./expression.ts";
|
|
7
8
|
|
|
8
9
|
export type HelpGroup = "music" | "session" | "window" | "keys";
|
|
9
10
|
|
|
@@ -60,6 +61,38 @@ export const HELP_SECTIONS: readonly HelpSection[] = [
|
|
|
60
61
|
command: "synth <param> <value> | preset <name>",
|
|
61
62
|
summary: "synth voice · synth lpf 1200 · synth lists every param",
|
|
62
63
|
},
|
|
64
|
+
{
|
|
65
|
+
command: "art <articulation>|off [target]",
|
|
66
|
+
summary:
|
|
67
|
+
"staccato legato accent tenuto marcato ghost · art staccato bars 1-2",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
command: "glide <ms>|0 [legato|mono|poly] | glide <ms> <target>",
|
|
71
|
+
summary:
|
|
72
|
+
"portamento in ms · glide 60 mono · glide 0 off · SDK 0.06 (s)",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
command: "bend <cents>|scoop|fall|doit|<at:cents>... [target]",
|
|
76
|
+
summary: "pitch curve over each note · bend +200 bar 3",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
command: "vibrato <rate> <depth> [<delay>] [target]",
|
|
80
|
+
summary: "per-note vibrato · vibrato 5.5 30 0.2",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
command: "pedal <beat>-<beat>... | bars | down|half|up <beat> | off",
|
|
84
|
+
summary: "sustain pedal · pedal 0-3.5 4-7.5 · pedal bars",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
command: "velcurve linear|soft|hard|fixed [<v>]",
|
|
88
|
+
summary: "how velocity maps to level · velcurve fixed 0.6 (0..1)",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
command: "humanize <ms> [<vel%> [<len%>]] [seed <n>|<target>] | off",
|
|
92
|
+
summary:
|
|
93
|
+
"seeded feel at render · humanize 10 8 5 · humanize 20 bars 2-3",
|
|
94
|
+
},
|
|
95
|
+
{ command: "expression", summary: "this track's performance settings" },
|
|
63
96
|
{ command: "filter <hz> [res]", summary: "low-pass · filter off" },
|
|
64
97
|
{ command: "delay <beats> [fb] [mix]", summary: "ping-pong · delay off" },
|
|
65
98
|
{ command: "reverb <mix> [size]", summary: "room · reverb off" },
|
|
@@ -76,12 +109,82 @@ export const HELP_SECTIONS: readonly HelpSection[] = [
|
|
|
76
109
|
summary: "drop one point",
|
|
77
110
|
},
|
|
78
111
|
{ command: "clear [<lane>] automation", summary: "drop a lane's points" },
|
|
112
|
+
{
|
|
113
|
+
command: "master <unit> on|off | preset <name> | <param> <value>",
|
|
114
|
+
summary:
|
|
115
|
+
"song master · eq glue tape width limiter · master glue ratio 4",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
command: "master <target> | target <lufs> | measure | off",
|
|
119
|
+
summary:
|
|
120
|
+
"loudness · master streaming · master target -9 · master measure",
|
|
121
|
+
},
|
|
79
122
|
{ command: "track name <text>", summary: "rename this track" },
|
|
80
123
|
{ command: "meter <1..16>", summary: "beats per bar" },
|
|
124
|
+
{
|
|
125
|
+
command: "tempo <bpm> at <beat>|bar <n> [ramp|exp]",
|
|
126
|
+
summary: "tempo change · tempo 90 at bar 9 ramp · tempo clear",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
command: "rit|accel [<n> bars] [to <bpm>] [at bar <n>]",
|
|
130
|
+
summary: "gradual · rit 4 bars to 80 · a tempo · tempo primo",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
command: "fermata [at <beat>|at bar <n>|at end] [<extra beats>]",
|
|
134
|
+
summary: "hold a beat · fermata at 31 2 · fermata clear",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
command: "meter <n>/<d> [at bar <n>]",
|
|
138
|
+
summary: "meter change · meter 7/8 at bar 5 · meter clear",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
command: "track rate|phase|cycle <n> | off",
|
|
142
|
+
summary: "polytempo · track rate 3/2 · track cycle 3",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
command: "track phasing <beats> [over <beats>|hold <n>]",
|
|
146
|
+
summary: "Reich phasing · track phasing 3 hold 8 · track time off",
|
|
147
|
+
},
|
|
81
148
|
{
|
|
82
149
|
command: "key <tonic> <mode> | none",
|
|
83
150
|
summary: "song key · key A minor · key F# dorian",
|
|
84
151
|
},
|
|
152
|
+
{
|
|
153
|
+
command: "scale [<tonic>] <name> | list",
|
|
154
|
+
summary: "song scale · scale D hijaz · scale yaman · scale list",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
command: "tuning <name> | edo <n> | scl <file> | off",
|
|
158
|
+
summary: "song tuning · tuning 19-edo · tuning just · tuning list",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
command: "tuning ref <hz> | root <note> | map linear|nearest",
|
|
162
|
+
summary: "A4 reference · degree-0 key · keys per step",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
command: "tuning track <…> | track off",
|
|
166
|
+
summary: "this track's tuning · off follows the song",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
command: "cents <id> <±c>",
|
|
170
|
+
summary: "detune one note · cents n3 -14 · add E4-14c at 0",
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
command: "section <name> <a>-<b> | add | dup | move | rename | delete",
|
|
174
|
+
summary: "song sections · section chorus 9-16 · section lists them",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
command: "section loop | jump | mute | vary <name>",
|
|
178
|
+
summary: "section loop chorus · section mute verse drums",
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
command: "form <section…> | off | bake",
|
|
182
|
+
summary: "song form · form intro verse chorus*2 outro",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
command: "build | drop | fill [<section> | <a>-<b>]",
|
|
186
|
+
summary: "riser, roll, sweep · pre-drop cut and impact · drum fill",
|
|
187
|
+
},
|
|
85
188
|
{
|
|
86
189
|
command: "hit <voice> at <beat>",
|
|
87
190
|
summary: "kit tracks · hit kick at 0",
|
|
@@ -112,7 +215,10 @@ export const HELP_SECTIONS: readonly HelpSection[] = [
|
|
|
112
215
|
{ command: "/rename <name>|--auto", summary: "name this session" },
|
|
113
216
|
{ command: "/fork [<name>]", summary: "copy into a new session" },
|
|
114
217
|
{ command: "/status", summary: "name · revision · digest · storage" },
|
|
115
|
-
{
|
|
218
|
+
{
|
|
219
|
+
command: "/export <file>",
|
|
220
|
+
summary: "write track.loop/v1 JSON, or MIDI for .mid",
|
|
221
|
+
},
|
|
116
222
|
{ command: "/import <file>", summary: "replace the score from a file" },
|
|
117
223
|
{
|
|
118
224
|
command: "/sample [<path> [as <voice>]]",
|
|
@@ -143,6 +249,10 @@ export const HELP_SECTIONS: readonly HelpSection[] = [
|
|
|
143
249
|
},
|
|
144
250
|
{ command: "/auth [--check]", summary: "provider and audio status" },
|
|
145
251
|
{ command: "/play [on|off]", summary: "keyboard play mode · Ctrl-P" },
|
|
252
|
+
{
|
|
253
|
+
command: "/play degrees|chromatic",
|
|
254
|
+
summary: "home row plays the key's scale degrees (any tuning) · i",
|
|
255
|
+
},
|
|
146
256
|
{
|
|
147
257
|
command: "/pattern [name]",
|
|
148
258
|
summary: "drum groove picker · moving previews",
|
|
@@ -179,6 +289,10 @@ export const HELP_SECTIONS: readonly HelpSection[] = [
|
|
|
179
289
|
command: "/help [topic]",
|
|
180
290
|
summary: "start here · /help all for everything",
|
|
181
291
|
},
|
|
292
|
+
{
|
|
293
|
+
command: "/guide [topic]",
|
|
294
|
+
summary: "short how-to guides · F1",
|
|
295
|
+
},
|
|
182
296
|
],
|
|
183
297
|
},
|
|
184
298
|
{
|
|
@@ -219,13 +333,9 @@ export const HELP_GUIDE: readonly HelpSection[] = [
|
|
|
219
333
|
{ command: "ctrl-p", summary: "play notes on the computer keyboard" },
|
|
220
334
|
{
|
|
221
335
|
command: "ctrl-k",
|
|
222
|
-
summary: "menu:
|
|
223
|
-
},
|
|
224
|
-
{ command: "?", summary: "keys for the screen you are on" },
|
|
225
|
-
{
|
|
226
|
-
command: "ctrl-z · ctrl-y",
|
|
227
|
-
summary: "undo · redo (every change is one)",
|
|
336
|
+
summary: "menu: sound, effects, performance, mix, master, arrange …",
|
|
228
337
|
},
|
|
338
|
+
{ command: "? · ctrl-z · ctrl-y", summary: "keys here · undo · redo" },
|
|
229
339
|
],
|
|
230
340
|
},
|
|
231
341
|
{
|
|
@@ -244,8 +354,10 @@ export const HELP_GUIDE: readonly HelpSection[] = [
|
|
|
244
354
|
{
|
|
245
355
|
group: "make drums" as HelpGroup,
|
|
246
356
|
entries: [
|
|
247
|
-
{
|
|
248
|
-
|
|
357
|
+
{
|
|
358
|
+
command: "/pattern · /kit",
|
|
359
|
+
summary: "pick a groove · pick a drum kit",
|
|
360
|
+
},
|
|
249
361
|
{ command: "/euclid", summary: "rhythm editor: pulses, steps, rotation" },
|
|
250
362
|
],
|
|
251
363
|
},
|
|
@@ -257,35 +369,68 @@ export const HELP_GUIDE: readonly HelpSection[] = [
|
|
|
257
369
|
summary: "instrument, envelope, filter, wavetable",
|
|
258
370
|
},
|
|
259
371
|
{ command: "ctrl-k › Effects", summary: "delay, reverb, distortion …" },
|
|
260
|
-
{
|
|
372
|
+
{
|
|
373
|
+
command: "master streaming",
|
|
374
|
+
summary: "finish: -14 LUFS, limiter · master measure",
|
|
375
|
+
},
|
|
261
376
|
{ command: "/try fx reverb mix 0.6", summary: "hear it before keeping" },
|
|
262
377
|
],
|
|
263
378
|
},
|
|
379
|
+
{
|
|
380
|
+
group: "shape the performance" as HelpGroup,
|
|
381
|
+
entries: [
|
|
382
|
+
{
|
|
383
|
+
command: "art staccato bar 2",
|
|
384
|
+
summary: "humanize 8 5 · ctrl-k › Sound › performance",
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
},
|
|
264
388
|
{
|
|
265
389
|
group: "chords" as HelpGroup,
|
|
266
390
|
entries: [
|
|
267
391
|
{ command: "key A minor", summary: "set the song key" },
|
|
268
392
|
{
|
|
269
393
|
command: "ctrl-p, then q",
|
|
270
|
-
summary: "chord mode
|
|
394
|
+
summary: "chord mode · 1–4 type · 5–8 extension · n next",
|
|
271
395
|
},
|
|
396
|
+
],
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
group: "song structure" as HelpGroup,
|
|
400
|
+
entries: [
|
|
272
401
|
{
|
|
273
|
-
command: "
|
|
274
|
-
summary: "
|
|
402
|
+
command: "section verse 1-8",
|
|
403
|
+
summary: "name bars · form verse chorus*2 orders them",
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
command: "build · drop · fill",
|
|
407
|
+
summary: "transitions · ctrl-k › Arrange · /help arrange",
|
|
275
408
|
},
|
|
276
409
|
],
|
|
277
410
|
},
|
|
278
411
|
{
|
|
279
412
|
group: "more" as HelpGroup,
|
|
280
413
|
entries: [
|
|
281
|
-
{
|
|
282
|
-
|
|
414
|
+
{
|
|
415
|
+
command: "rit 4 bars to 80",
|
|
416
|
+
summary: "tempo, fermatas, meter · tuning pelog · scale yaman",
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
command: "/help all",
|
|
420
|
+
summary: "every command and key · /guide feature guides · F1",
|
|
421
|
+
},
|
|
283
422
|
],
|
|
284
423
|
},
|
|
285
424
|
];
|
|
286
425
|
|
|
287
426
|
/** Topics `/help <topic>` takes, besides `all`. */
|
|
288
|
-
export const HELP_TOPICS = [
|
|
427
|
+
export const HELP_TOPICS = [
|
|
428
|
+
"music",
|
|
429
|
+
"session",
|
|
430
|
+
"window",
|
|
431
|
+
"keys",
|
|
432
|
+
"arrange",
|
|
433
|
+
] as const;
|
|
289
434
|
|
|
290
435
|
/**
|
|
291
436
|
* Rows for `/help [topic]`: the guide with no topic, the full reference for
|
|
@@ -299,10 +444,47 @@ export function helpTopicLines(
|
|
|
299
444
|
if (!name) return sectionLines(HELP_GUIDE, width, 20);
|
|
300
445
|
if (name === "all" || name === "commands" || name === "reference")
|
|
301
446
|
return helpLines(width);
|
|
447
|
+
if (name === "arrange" || name === "arrangement" || name === "sections")
|
|
448
|
+
return sectionLines([arrangeSection()], width);
|
|
302
449
|
const group = HELP_SECTIONS.find((section) => section.group === name);
|
|
303
450
|
return group ? sectionLines([group], width) : undefined;
|
|
304
451
|
}
|
|
305
452
|
|
|
453
|
+
/** `/help arrange`: every arranging command with its full usage. */
|
|
454
|
+
function arrangeSection(): HelpSection {
|
|
455
|
+
const verbs = ["section", "sections", "form", "build", "drop", "fill"];
|
|
456
|
+
return {
|
|
457
|
+
group: "arrange" as HelpGroup,
|
|
458
|
+
entries: [
|
|
459
|
+
// Usage strings run long: wrapped onto continuation rows.
|
|
460
|
+
...verbs.flatMap((verb) =>
|
|
461
|
+
wrapWords(USAGE[verb] ?? "", 46).map((summary, index) => ({
|
|
462
|
+
command: index === 0 ? verb : "",
|
|
463
|
+
summary,
|
|
464
|
+
})),
|
|
465
|
+
),
|
|
466
|
+
{ command: "/menu arrange", summary: "the Arrange menu (ctrl-k)" },
|
|
467
|
+
{
|
|
468
|
+
command: "dawg render --section <name>",
|
|
469
|
+
summary: "export one section",
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function wrapWords(text: string, width: number): string[] {
|
|
476
|
+
const rows: string[] = [];
|
|
477
|
+
let row = "";
|
|
478
|
+
for (const word of text.split(" ")) {
|
|
479
|
+
if (row && row.length + 1 + word.length > width) {
|
|
480
|
+
rows.push(row);
|
|
481
|
+
row = word;
|
|
482
|
+
} else row = row ? `${row} ${word}` : word;
|
|
483
|
+
}
|
|
484
|
+
if (row) rows.push(row);
|
|
485
|
+
return rows;
|
|
486
|
+
}
|
|
487
|
+
|
|
306
488
|
function sectionLines(
|
|
307
489
|
sections: readonly HelpSection[],
|
|
308
490
|
width: number,
|
|
@@ -365,15 +547,31 @@ export function helpText(): string {
|
|
|
365
547
|
}
|
|
366
548
|
|
|
367
549
|
/** Usage for a known verb, shown instead of sending a near-miss to the agent. */
|
|
368
|
-
const USAGE: Readonly<Record<string, string>> = {
|
|
550
|
+
export const USAGE: Readonly<Record<string, string>> = {
|
|
369
551
|
click: "/click on|off|<volume> · /click 50%",
|
|
370
552
|
"count-in": "/count-in 0|1|2",
|
|
371
553
|
chords:
|
|
372
554
|
"/chords auto|manual|off · voicing <n> · spread · bass · perform · rate · octaves · sevenths · preset · style",
|
|
373
555
|
key: "key <tonic> <mode> | none · key A minor",
|
|
556
|
+
scale: "scale [<tonic>] <name> | list · scale D hijaz",
|
|
557
|
+
tuning:
|
|
558
|
+
"tuning <name> | edo <n> | ratios … | cents … | scl <file> [kbm <file>] | ref <hz> | root <note> | map linear|nearest | track … | off · tuning 19-edo",
|
|
559
|
+
tune: "tuning <name> | edo <n> | scl <file> | off · tuning list",
|
|
560
|
+
cents: "cents <id> <±cents> · cents n3 -14",
|
|
374
561
|
grid: "/grid 1/4|1/8|1/8T|1/16|1/16T|1/32",
|
|
375
|
-
tempo:
|
|
562
|
+
tempo:
|
|
563
|
+
"tempo takes 20…300 · tempo 120 · tempo 90 at bar 9 [ramp|exp] · tempo remove bar 9 · tempo clear · tempo map",
|
|
376
564
|
bpm: "tempo takes 20…300 · tempo 120",
|
|
565
|
+
rit: "rit [<n> bars|beats] [to <bpm>] [at bar <n>|<beat>] [exp] · rit 4 bars to 80",
|
|
566
|
+
ritardando:
|
|
567
|
+
"rit [<n> bars|beats] [to <bpm>] [at bar <n>|<beat>] [exp] · rit 4 bars to 80",
|
|
568
|
+
rall: "rit [<n> bars|beats] [to <bpm>] [at bar <n>|<beat>] [exp] · rall 2 bars",
|
|
569
|
+
accel:
|
|
570
|
+
"accel [<n> bars|beats] [to <bpm>] [at bar <n>|<beat>] [exp] · accel 8 bars to 174 at bar 9",
|
|
571
|
+
accelerando:
|
|
572
|
+
"accel [<n> bars|beats] [to <bpm>] [at bar <n>|<beat>] [exp] · accel 8 bars to 174",
|
|
573
|
+
fermata:
|
|
574
|
+
"fermata [at <beat>|at bar <n>|at end] [<extra beats>] · fermata at 31 2 · fermata remove 31 · fermata clear",
|
|
377
575
|
add: "add <note> at <beat> [for <beats>] · add C4 at 0",
|
|
378
576
|
put: "add <note> at <beat> [for <beats>] · add C4 at 0",
|
|
379
577
|
remove: "remove <id> · ids show in the transcript",
|
|
@@ -400,7 +598,8 @@ const USAGE: Readonly<Record<string, string>> = {
|
|
|
400
598
|
hit: "hit <voice> at <beat> · hit kick at 0",
|
|
401
599
|
pattern: "pattern <voice> <beats...> | every <step> · pattern kick every 1",
|
|
402
600
|
clear: "clear · clear <voice> · clear [<lane>] automation",
|
|
403
|
-
track:
|
|
601
|
+
track:
|
|
602
|
+
"/track <name> · /track drums · track rate <0.125..8>|<a>/<b>|off · track phase <beats> · track cycle <beats> · track phasing <beats> [over <beats>]",
|
|
404
603
|
tracks: "/tracks",
|
|
405
604
|
sessions: "/sessions",
|
|
406
605
|
resume: "/resume [<n>|<name>|<id>]",
|
|
@@ -422,15 +621,37 @@ const USAGE: Readonly<Record<string, string>> = {
|
|
|
422
621
|
logout: "/logout [provider]",
|
|
423
622
|
auth: "/auth [--check]",
|
|
424
623
|
help: "/help [topic] · /help all · /help music|session|window|keys",
|
|
624
|
+
guide: "/guide [topic] · /guide chords · F1",
|
|
425
625
|
fx: "fx <effect> <param> <value> | on | off | preset <name> · fx delay mix 0.3",
|
|
426
626
|
synth: "synth <param> <value> | preset <name> · synth lpf 1200",
|
|
427
627
|
pack: "/pack list | info <name> | use <pack>/<sound> | add <url>",
|
|
428
628
|
kit: "/kit [name] · /kit syn909",
|
|
429
629
|
euclid: "/euclid [voice] · euclid hat 7 16",
|
|
430
|
-
menu: "/menu [sound|effects|rhythm|chords|mix|project]",
|
|
630
|
+
menu: "/menu [sound|effects|rhythm|chords|mix|master|project|tuning]",
|
|
631
|
+
master:
|
|
632
|
+
"master <unit> on|off|preset <name>|<param> <value> · master streaming|club|loud · master target -14 · master measure · master off",
|
|
431
633
|
try: "/try <sound command> · /try fx reverb mix 0.6",
|
|
432
|
-
play: "/play [on|off] · Ctrl-P",
|
|
433
|
-
meter:
|
|
634
|
+
play: "/play [on|off|degrees|chromatic] · Ctrl-P · i toggles degrees",
|
|
635
|
+
meter:
|
|
636
|
+
"meter <1..16> · meter 3 · meter 7/8 [at bar <n>] · meter remove bar <n> · meter clear",
|
|
637
|
+
art: EXPRESSION_USAGE.art,
|
|
638
|
+
articulation: EXPRESSION_USAGE.art,
|
|
639
|
+
bend: EXPRESSION_USAGE.bend,
|
|
640
|
+
vibrato: EXPRESSION_USAGE.vibrato,
|
|
641
|
+
glide: EXPRESSION_USAGE.glide,
|
|
642
|
+
portamento: EXPRESSION_USAGE.glide,
|
|
643
|
+
pedal: EXPRESSION_USAGE.pedal,
|
|
644
|
+
sustain: EXPRESSION_USAGE.pedal,
|
|
645
|
+
velcurve: EXPRESSION_USAGE.velcurve,
|
|
646
|
+
humanize: EXPRESSION_USAGE.humanize,
|
|
647
|
+
section:
|
|
648
|
+
"section [mark] <name> <a>-<b> | add [<name>] [<n>] | dup | move <name> to <bar> | rename <name> to <new> | delete | unmark | mute | vary | reset | loop <name>|off | jump <name> · section chorus 9-16",
|
|
649
|
+
sections: "section · lists sections, the form and the loop",
|
|
650
|
+
form: "form <section…> | off | bake · form verse verse chorus verse · form verse chorus*2",
|
|
651
|
+
build:
|
|
652
|
+
"build [into <section> | <section> | <a>-<b>] [<n> bars] [riser] [roll] [sweep] [uplifter] · build into chorus",
|
|
653
|
+
drop: "drop [<section> | at <bar>] [cut <beats>] [no impact] · drop chorus",
|
|
654
|
+
fill: "fill [<section> | at <bar>] [toms|roll|kick] [<n> beats] [no crash] · fill chorus (the beats before it)",
|
|
434
655
|
undo: "undo · Ctrl-Z",
|
|
435
656
|
redo: "redo · Ctrl-Y",
|
|
436
657
|
};
|
|
@@ -530,6 +751,42 @@ export function looksLikeProse(command: string): boolean {
|
|
|
530
751
|
*/
|
|
531
752
|
export function usageHint(command: string): string | undefined {
|
|
532
753
|
if (looksLikeProse(command)) return undefined;
|
|
533
|
-
const
|
|
534
|
-
|
|
754
|
+
const words = command.trim().toLowerCase().replace(/^\//, "").split(/\s+/);
|
|
755
|
+
const verb = words[0];
|
|
756
|
+
if (!verb) return undefined;
|
|
757
|
+
// `build tension`, `drop bass`, `form a hook`: everyday words, so only
|
|
758
|
+
// arguments that look like the grammar earn a usage hint; the rest is
|
|
759
|
+
// a request for the agent.
|
|
760
|
+
if (
|
|
761
|
+
ARRANGE_VERBS.has(verb) &&
|
|
762
|
+
!command.trim().startsWith("/") &&
|
|
763
|
+
!words.slice(1).some((word) => /\d/.test(word) || ARRANGE_WORDS.has(word))
|
|
764
|
+
)
|
|
765
|
+
return undefined;
|
|
766
|
+
return USAGE[verb];
|
|
535
767
|
}
|
|
768
|
+
|
|
769
|
+
const ARRANGE_VERBS: ReadonlySet<string> = new Set([
|
|
770
|
+
"build",
|
|
771
|
+
"drop",
|
|
772
|
+
"fill",
|
|
773
|
+
"form",
|
|
774
|
+
]);
|
|
775
|
+
const ARRANGE_WORDS: ReadonlySet<string> = new Set([
|
|
776
|
+
"at",
|
|
777
|
+
"into",
|
|
778
|
+
"cut",
|
|
779
|
+
"no",
|
|
780
|
+
"impact",
|
|
781
|
+
"crash",
|
|
782
|
+
"riser",
|
|
783
|
+
"roll",
|
|
784
|
+
"sweep",
|
|
785
|
+
"uplifter",
|
|
786
|
+
"toms",
|
|
787
|
+
"kick",
|
|
788
|
+
"beats",
|
|
789
|
+
"bars",
|
|
790
|
+
"bake",
|
|
791
|
+
"off",
|
|
792
|
+
]);
|