@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.
Files changed (275) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/DAWG.md +655 -141
  3. package/README.md +27 -25
  4. package/core/autotune.ts +1119 -0
  5. package/core/chords.ts +759 -23
  6. package/core/clips.ts +499 -0
  7. package/core/diff.ts +182 -99
  8. package/core/expression.ts +158 -6
  9. package/core/fx.ts +354 -32
  10. package/core/granular.ts +91 -0
  11. package/core/instruments.ts +180 -0
  12. package/core/keys.ts +573 -4
  13. package/core/loop.ts +5 -0
  14. package/core/lyrics.ts +297 -0
  15. package/core/master.ts +3 -3
  16. package/core/resonators.ts +306 -4
  17. package/core/routing.ts +165 -0
  18. package/core/score.ts +1181 -16
  19. package/core/sdk/eval-child.ts +7 -2
  20. package/core/sdk/eval.ts +35 -6
  21. package/core/sdk/print.ts +354 -6
  22. package/core/sdk/sync-lyrics.ts +49 -0
  23. package/core/sdk/v1.ts +3160 -69
  24. package/core/sections.ts +298 -24
  25. package/core/sing.ts +815 -0
  26. package/core/strings.ts +237 -2
  27. package/core/style-provenance.ts +80 -0
  28. package/core/styles/africa-mena-southasia.ts +2893 -0
  29. package/core/styles/americas.ts +3810 -0
  30. package/core/styles/art.ts +4993 -0
  31. package/core/styles/base.ts +123 -0
  32. package/core/styles/cycles.ts +106 -0
  33. package/core/styles/electronic.ts +2723 -0
  34. package/core/styles/europe-asia-pacific.ts +2838 -0
  35. package/core/styles/excerpt.ts +29 -0
  36. package/core/styles/gamelan.ts +283 -0
  37. package/core/styles/generate.ts +2199 -0
  38. package/core/styles/index.ts +515 -0
  39. package/core/styles/parts.ts +106 -0
  40. package/core/styles/pop.ts +3189 -0
  41. package/core/styles/rock.ts +2993 -0
  42. package/core/styles/roots.ts +4175 -0
  43. package/core/styles/schema.ts +429 -0
  44. package/core/styles/taxonomy.ts +940 -0
  45. package/core/styles/validate.ts +528 -0
  46. package/core/tempo.ts +32 -2
  47. package/core/tuning.ts +19 -3
  48. package/core/vocoder.ts +524 -0
  49. package/core/winds.ts +652 -0
  50. package/guides/agent.md +29 -0
  51. package/guides/arrange.md +30 -0
  52. package/guides/audition.md +20 -14
  53. package/guides/automation.md +12 -6
  54. package/guides/chords.md +16 -14
  55. package/guides/effects.md +17 -15
  56. package/guides/faders.md +20 -16
  57. package/guides/files.md +13 -9
  58. package/guides/getting-started.md +15 -11
  59. package/guides/keys.md +19 -15
  60. package/guides/media.md +17 -12
  61. package/guides/mix.md +12 -6
  62. package/guides/music.md +23 -8
  63. package/guides/notes.md +15 -9
  64. package/guides/performance.md +15 -10
  65. package/guides/play.md +21 -13
  66. package/guides/project.md +25 -8
  67. package/guides/providers.md +20 -14
  68. package/guides/resample.md +32 -0
  69. package/guides/rhythm.md +17 -13
  70. package/guides/sessions.md +17 -7
  71. package/guides/show-me.md +31 -0
  72. package/guides/sound.md +25 -9
  73. package/guides/sounds.md +15 -12
  74. package/guides/styles.md +31 -0
  75. package/guides/tempo.md +15 -10
  76. package/guides/tracks.md +15 -10
  77. package/guides/tuning.md +32 -0
  78. package/guides/voice.md +31 -0
  79. package/guides/web-search.md +18 -8
  80. package/native/prebuilt/darwin-arm64/libdawg_sink.dylib +0 -0
  81. package/native/prebuilt/darwin-x64/libdawg_sink.dylib +0 -0
  82. package/native/prebuilt/linux-arm64/libdawg_sink.so +0 -0
  83. package/native/prebuilt/linux-x64/libdawg_sink.so +0 -0
  84. package/native/prebuilt/manifest.json +21 -0
  85. package/package.json +5 -2
  86. package/src/agent/agent.ts +131 -13
  87. package/src/agent/calibration-tools.ts +53 -0
  88. package/src/agent/chord-tools.ts +153 -1
  89. package/src/agent/clip-tools.ts +453 -0
  90. package/src/agent/command-agent.ts +369 -0
  91. package/src/agent/drum-tools.ts +2 -2
  92. package/src/agent/expression-tools.ts +91 -0
  93. package/src/agent/gateway.ts +246 -60
  94. package/src/agent/models.ts +53 -12
  95. package/src/agent/ops.ts +15 -1
  96. package/src/agent/pack-tools.ts +1 -1
  97. package/src/agent/planner.ts +13 -0
  98. package/src/agent/portable-schema.ts +80 -0
  99. package/src/agent/preview-tool.ts +5 -1
  100. package/src/agent/provider.ts +22 -8
  101. package/src/agent/resample-tool.ts +131 -0
  102. package/src/agent/rhythm-tools.ts +1 -1
  103. package/src/agent/section-tools.ts +1 -1
  104. package/src/agent/show-me.ts +497 -0
  105. package/src/agent/steer.ts +15 -0
  106. package/src/agent/style-tools.ts +217 -0
  107. package/src/agent/tool-error.ts +12 -0
  108. package/src/agent/tools.ts +307 -37
  109. package/src/agent/usage.ts +2 -2
  110. package/src/agent/voice-tools.ts +925 -0
  111. package/src/agent/xcb-agent.ts +16 -6
  112. package/src/argv.ts +38 -0
  113. package/src/audio/analysis.ts +253 -0
  114. package/src/audio/arrange.ts +58 -3
  115. package/src/audio/autotune-engine.ts +101 -0
  116. package/src/audio/autotune.ts +640 -0
  117. package/src/audio/clips.ts +240 -0
  118. package/src/audio/doctor.ts +86 -0
  119. package/src/audio/dsp/bandbank.ts +138 -0
  120. package/src/audio/dsp/envelope.ts +171 -0
  121. package/src/audio/dsp/follow.ts +120 -0
  122. package/src/audio/dsp/formant.ts +427 -0
  123. package/src/audio/dsp/glottal.ts +243 -0
  124. package/src/audio/dsp/interp.ts +7 -2
  125. package/src/audio/dsp/lpc.ts +50 -0
  126. package/src/audio/dsp/periodicity.ts +59 -0
  127. package/src/audio/dsp/pitch.ts +995 -0
  128. package/src/audio/dsp/psola.ts +199 -0
  129. package/src/audio/dsp/shift.ts +256 -0
  130. package/src/audio/effects/chain.ts +21 -4
  131. package/src/audio/effects/common.ts +57 -0
  132. package/src/audio/effects/convolution.ts +113 -5
  133. package/src/audio/effects/filter.ts +48 -69
  134. package/src/audio/effects/formant.ts +263 -0
  135. package/src/audio/effects/gaze.ts +354 -0
  136. package/src/audio/engine.ts +206 -33
  137. package/src/audio/fit.ts +80 -3
  138. package/src/audio/granular.ts +352 -21
  139. package/src/audio/instrument-check.ts +67 -47
  140. package/src/audio/instruments.ts +36 -3
  141. package/src/audio/keys/calibration.ts +56 -0
  142. package/src/audio/keys/electric.ts +427 -0
  143. package/src/audio/keys/engine.ts +156 -20
  144. package/src/audio/keys/organ.ts +1335 -0
  145. package/src/audio/keys/piano.ts +72 -8
  146. package/src/audio/keys/sympathetic.ts +127 -0
  147. package/src/audio/kits.ts +135 -6
  148. package/src/audio/live-worker.ts +3 -1
  149. package/src/audio/live.ts +247 -26
  150. package/src/audio/native.ts +615 -0
  151. package/src/audio/preview.ts +45 -3
  152. package/src/audio/render-worker.ts +2 -0
  153. package/src/audio/renderer.ts +2 -0
  154. package/src/audio/resample.ts +286 -0
  155. package/src/audio/resonators.ts +10 -2
  156. package/src/audio/sampler.ts +252 -24
  157. package/src/audio/samples.ts +46 -3
  158. package/src/audio/sing/analysis.ts +193 -0
  159. package/src/audio/sing/engine.ts +949 -0
  160. package/src/audio/strings/body.ts +29 -16
  161. package/src/audio/strings/bow.ts +699 -0
  162. package/src/audio/strings/engine.ts +274 -22
  163. package/src/audio/strings/measure.test-helpers.ts +2 -0
  164. package/src/audio/synth/oscillators.ts +31 -21
  165. package/src/audio/synth/voice.ts +34 -1
  166. package/src/audio/vocoder/bank.ts +314 -0
  167. package/src/audio/vocoder/carrier.ts +165 -0
  168. package/src/audio/vocoder/control.ts +68 -0
  169. package/src/audio/vocoder/detect.ts +50 -0
  170. package/src/audio/vocoder/index.ts +304 -0
  171. package/src/audio/vocoder/talkbox.ts +143 -0
  172. package/src/audio/wav.ts +608 -85
  173. package/src/audio/winds/engine.ts +306 -0
  174. package/src/audio/winds/filters.ts +153 -0
  175. package/src/audio/winds/pitch.ts +104 -0
  176. package/src/audio/winds/trim.ts +104 -0
  177. package/src/audio/winds/trims.ts +917 -0
  178. package/src/audio/winds/trims1.ts +297 -0
  179. package/src/audio/winds/voice.ts +492 -0
  180. package/src/auth/cli.ts +38 -36
  181. package/src/auth/credentials.ts +30 -1
  182. package/src/auth/login.ts +15 -9
  183. package/src/auth/tui.ts +19 -10
  184. package/src/commands/arrange.ts +44 -29
  185. package/src/commands/autotune.ts +421 -0
  186. package/src/commands/calibration.ts +74 -0
  187. package/src/commands/clips.ts +887 -0
  188. package/src/commands/drums.ts +3 -2
  189. package/src/commands/edit.ts +11 -4
  190. package/src/commands/expression.ts +104 -23
  191. package/src/commands/formant.ts +221 -0
  192. package/src/commands/fx.ts +105 -33
  193. package/src/commands/grammar.ts +558 -0
  194. package/src/commands/granular.ts +7 -2
  195. package/src/commands/help.ts +652 -339
  196. package/src/commands/history.ts +18 -0
  197. package/src/commands/keys.ts +293 -17
  198. package/src/commands/modal.ts +67 -4
  199. package/src/commands/music.ts +1 -1
  200. package/src/commands/nearest.ts +53 -0
  201. package/src/commands/pack.ts +9 -2
  202. package/src/commands/param-range.ts +56 -0
  203. package/src/commands/parses.ts +130 -0
  204. package/src/commands/progression.ts +170 -0
  205. package/src/commands/resample.ts +281 -0
  206. package/src/commands/rhythm.ts +3 -0
  207. package/src/commands/rig.ts +8 -25
  208. package/src/commands/sample.ts +49 -2
  209. package/src/commands/shift.ts +119 -0
  210. package/src/commands/sing.ts +478 -0
  211. package/src/commands/string.ts +28 -2
  212. package/src/commands/strum.ts +485 -0
  213. package/src/commands/style.ts +415 -0
  214. package/src/commands/time.ts +6 -3
  215. package/src/commands/tuning.ts +3 -3
  216. package/src/commands/vocal-pitch.ts +616 -0
  217. package/src/commands/vocal.ts +147 -0
  218. package/src/commands/vocoder.ts +627 -0
  219. package/src/commands/wind.ts +244 -0
  220. package/src/fs/durable.ts +50 -0
  221. package/src/lang/glossary.ts +493 -0
  222. package/src/launch-args.ts +163 -0
  223. package/src/main.ts +1521 -255
  224. package/src/media/cli.ts +20 -3
  225. package/src/media/import.ts +3 -1
  226. package/src/project/check.ts +26 -3
  227. package/src/project/clip-pins.ts +72 -0
  228. package/src/project/init.ts +23 -8
  229. package/src/project/sync.ts +418 -86
  230. package/src/render.ts +36 -1
  231. package/src/session/daemon.ts +3 -0
  232. package/src/session/meta.ts +14 -0
  233. package/src/session/origin.ts +154 -0
  234. package/src/session/port.ts +22 -4
  235. package/src/session/presence.ts +50 -7
  236. package/src/session/protocol.ts +5 -1
  237. package/src/session/rebase.ts +18 -5
  238. package/src/session/receipt.ts +258 -0
  239. package/src/session/store.ts +65 -43
  240. package/src/tui/arrange-menu.ts +65 -31
  241. package/src/tui/audition.ts +1 -1
  242. package/src/tui/euclid.ts +18 -13
  243. package/src/tui/fader.ts +228 -41
  244. package/src/tui/granular-menu.ts +2 -4
  245. package/src/tui/menu-clips.ts +297 -0
  246. package/src/tui/menu-time.ts +20 -13
  247. package/src/tui/menu-voice.ts +405 -0
  248. package/src/tui/menu.ts +1377 -193
  249. package/src/tui/modal-menu.ts +38 -11
  250. package/src/tui/performance-menu.ts +46 -1
  251. package/src/tui/play-chords.ts +108 -5
  252. package/src/tui/play-mode.ts +16 -1
  253. package/src/tui/play-session.ts +81 -16
  254. package/src/tui/sing-menu.ts +278 -0
  255. package/src/tui/style-menu.ts +104 -0
  256. package/src/tui/vocoder-menu.ts +244 -0
  257. package/src/tui/wind-menu.ts +144 -0
  258. package/src/version.ts +8 -0
  259. package/src/web/fetch.ts +115 -29
  260. package/tui/activity.ts +180 -9
  261. package/tui/app.ts +274 -40
  262. package/tui/clip-row.ts +132 -0
  263. package/tui/delight.ts +144 -0
  264. package/tui/drawer.ts +70 -22
  265. package/tui/frame-gate.ts +76 -0
  266. package/tui/grammar.ts +112 -63
  267. package/tui/guide.ts +42 -4
  268. package/tui/highway.ts +269 -25
  269. package/tui/hints.ts +192 -0
  270. package/tui/input.ts +60 -9
  271. package/tui/keys.ts +1 -1
  272. package/tui/play-strip.ts +68 -14
  273. package/tui/prompt.ts +1 -1
  274. package/tui/screen.ts +144 -14
  275. package/tui/theme.ts +27 -0
@@ -4,11 +4,12 @@
4
4
  * fx list the focused track's effects
5
5
  * fx <effect> on|off|reset enable with defaults, remove, reset
6
6
  * fx <effect> preset <name> load a named preset (FX_PRESETS)
7
+ * fx <effect> turn it on (same as `on`)
7
8
  * fx <effect> <param> <value> set one parameter (enables it)
8
9
  * fx <effect> <number> set its first parameter (`fx orbit 2`)
9
10
  * fx <effect> <param> <value> <param> <value>… several at once
10
11
  * fx reverb ir <impulse>|off convolution reverb (Strudel `ir`):
11
- * room|hall|plate, a pack sound or a
12
+ * room|hall|plate|reverse|gate|spring, a pack sound or a
12
13
  * project file; `fx ir hall` too
13
14
  *
14
15
  * Effects are every `FX_CHAIN` stage except pan (see core/fx.ts), plus
@@ -18,7 +19,7 @@
18
19
  * on/off/true/false; enums take one of their values. Each command is one
19
20
  * `updateTrack` revision and one undo step.
20
21
  */
21
- import { nearestWord } from "../audio/instrument-check.ts";
22
+ import { nearest } from "./nearest.ts";
22
23
  import {
23
24
  EFFECT_NAMES,
24
25
  FX_PRESETS,
@@ -28,6 +29,7 @@ import {
28
29
  isEffectName,
29
30
  normalizeParam,
30
31
  FxValidationError,
32
+ VOWEL_VALUES,
31
33
  type EffectName,
32
34
  type FxName,
33
35
  type FxValues,
@@ -56,37 +58,69 @@ export type FxCommand =
56
58
  type: "fx-set";
57
59
  effect: EffectName;
58
60
  values: Readonly<Record<string, number | string | boolean>>;
61
+ }
62
+ /** Store exactly these values (`/vowel a` drops a previous morph). */
63
+ | {
64
+ type: "fx-replace";
65
+ effect: EffectName;
66
+ values: Readonly<Record<string, number | string | boolean>>;
59
67
  };
60
68
 
61
- const EFFECT_ALIASES: Readonly<Record<string, EffectName>> = Object.freeze({
62
- lpf: "filter",
63
- hpf: "filter",
64
- bpf: "filter",
65
- dj: "djf",
66
- "dj-filter": "djf",
67
- "auto-filter": "autofilter",
68
- autof: "autofilter",
69
- formant: "vowel",
70
- bitcrush: "crush",
71
- bitcrusher: "crush",
72
- coarse: "crush",
73
- distortion: "distort",
74
- dist: "distort",
75
- drive: "distort",
76
- shape: "distort",
77
- trem: "tremolo",
78
- comp: "compressor",
79
- compress: "compressor",
80
- rotary: "leslie",
81
- gain: "postgain",
82
- echo: "delay",
83
- bus: "orbit",
84
- o: "orbit",
85
- sidechain: "duck",
86
- duckorbit: "duck",
87
- room: "reverb",
88
- verb: "reverb",
89
- });
69
+ export const EFFECT_ALIASES: Readonly<Record<string, EffectName>> =
70
+ Object.freeze({
71
+ lpf: "filter",
72
+ hpf: "filter",
73
+ bpf: "filter",
74
+ dj: "djf",
75
+ "dj-filter": "djf",
76
+ "auto-filter": "autofilter",
77
+ autof: "autofilter",
78
+ bitcrush: "crush",
79
+ bitcrusher: "crush",
80
+ coarse: "crush",
81
+ distortion: "distort",
82
+ dist: "distort",
83
+ drive: "distort",
84
+ shape: "distort",
85
+ trem: "tremolo",
86
+ comp: "compressor",
87
+ compress: "compressor",
88
+ rotary: "leslie",
89
+ gain: "postgain",
90
+ echo: "delay",
91
+ bus: "orbit",
92
+ o: "orbit",
93
+ sidechain: "duck",
94
+ duckorbit: "duck",
95
+ room: "reverb",
96
+ verb: "reverb",
97
+ });
98
+
99
+ /**
100
+ * 0.7: `formant` was an alias of the vowel filter; it now shifts formants.
101
+ * A vowel given to it gets this answer instead of a silent change.
102
+ */
103
+ export const FORMANT_FX_USAGE =
104
+ "formant · shift -12..12 st, mix 0..1 · presets deep giant bright tiny";
105
+
106
+ /** `/vowel morph`, `fx vowel morph` and set_fx all refuse a morph with no target. */
107
+ export const VOWEL_MORPH_NEEDS_TO =
108
+ "set a target first: /vowel a o 0.5 or /vowel to o";
109
+
110
+ export const FORMANT_VOWEL_HINT =
111
+ "formant now shifts formants at constant pitch; the vowel filter is `vowel`";
112
+
113
+ /** Whether `fx formant …` words or set_fx params name a vowel. */
114
+ export function formantGotVowel(
115
+ words: readonly (string | number | boolean)[],
116
+ ): boolean {
117
+ return words.some(
118
+ (word) =>
119
+ typeof word === "string" &&
120
+ (word.toLowerCase() === "vowel" ||
121
+ (VOWEL_VALUES as readonly string[]).includes(word.toLowerCase())),
122
+ );
123
+ }
90
124
 
91
125
  export function parseEffectName(name: string): EffectName | undefined {
92
126
  const lower = name.toLowerCase();
@@ -133,10 +167,25 @@ export function parseParamValue(
133
167
  }
134
168
  }
135
169
 
170
+ /** The effects people reach for first, for the empty `fx` read. */
171
+ const COMMON_FIRST: readonly string[] = [
172
+ "reverb",
173
+ "delay",
174
+ "filter",
175
+ "distort",
176
+ "chorus",
177
+ "compressor",
178
+ ];
179
+
180
+ const FX_LIST_WORDS: readonly string[] = ["list", "ls", "presets"];
181
+
136
182
  export function parseFxCommand(prompt: string): FxCommand | undefined {
137
183
  const words = prompt.trim().split(/\s+/);
138
184
  if (words[0]?.toLowerCase() !== "fx") return undefined;
139
185
  if (words.length === 1) return { type: "fx-list" };
186
+ // `fx list`, `fx ls`, `fx presets`: the same read as bare `fx`.
187
+ if (words.length === 2 && FX_LIST_WORDS.includes(words[1]!.toLowerCase()))
188
+ return { type: "fx-list" };
140
189
  if (prompt.length > 1_024) return undefined;
141
190
  const irWord = (word: string | undefined) =>
142
191
  word !== undefined && ["ir", "iresponse"].includes(word.toLowerCase());
@@ -147,6 +196,8 @@ export function parseFxCommand(prompt: string): FxCommand | undefined {
147
196
  if (effect === "reverb" && irWord(words[2]) && words.length === 4)
148
197
  return irCommand(words[3]!);
149
198
  const rest = words.slice(2).map((word) => word.toLowerCase());
199
+ // `fx wobble`, `fx double`: a bare effect name turns it on.
200
+ if (rest.length === 0) return { type: "fx-on", effect };
150
201
  if (rest.length === 1 && (rest[0] === "on" || rest[0] === "off"))
151
202
  return { type: rest[0] === "on" ? "fx-on" : "fx-off", effect };
152
203
  if (rest.length === 1 && rest[0] === "reset")
@@ -200,9 +251,16 @@ export function unknownFxMessage(prompt: string): string | undefined {
200
251
  const words = prompt.trim().split(/\s+/);
201
252
  if (words[0]?.toLowerCase() !== "fx" || words.length < 2) return undefined;
202
253
  const name = words[1]!.toLowerCase();
254
+ if (name === "formant" && formantGotVowel(words.slice(2)))
255
+ return FORMANT_VOWEL_HINT;
256
+ // A new numeric-first effect: out-of-range values and preset typos get its
257
+ // ranges and presets instead of the generic unknown-command path.
258
+ if (name === "formant" && words.length <= 6 && !parseFxCommand(prompt))
259
+ return FORMANT_FX_USAGE;
203
260
  if (parseEffectName(name) || ["ir", "iresponse", "amp"].includes(name))
204
261
  return undefined;
205
- const near = nearestWord(name, [
262
+ if (words.length === 2 && FX_LIST_WORDS.includes(name)) return undefined;
263
+ const near = nearest(name, [
206
264
  ...EFFECT_NAMES,
207
265
  ...Object.keys(EFFECT_ALIASES),
208
266
  "reverb",
@@ -239,6 +297,11 @@ export function effectDefaults(effect: EffectName): FxValues {
239
297
  delete out.sag;
240
298
  delete out.gate;
241
299
  }
300
+ // The vowel morph stays absent until set: `fx vowel on` stores 0.6 data.
301
+ if (effect === "vowel") {
302
+ delete out.to;
303
+ delete out.morph;
304
+ }
242
305
  return out;
243
306
  }
244
307
 
@@ -301,7 +364,7 @@ export function applyFxCommand(
301
364
  ok: true,
302
365
  message: on.length
303
366
  ? `fx · ${on.map((effect) => `${effect} (${describe(effect, effectValues(track, effect)!)})`).join(" → ")}`
304
- : `fx · none · chain ${FX_CHAIN.join(" → ")}`,
367
+ : `fx · none · ${COMMON_FIRST.join(" ")} … · fx list`,
305
368
  };
306
369
  }
307
370
  if (command.type === "fx-ir")
@@ -321,7 +384,16 @@ export function applyFxCommand(
321
384
  ...effectDefaults(effect),
322
385
  ...FX_PRESETS[effect]![command.preset],
323
386
  };
387
+ else if (command.type === "fx-replace") values = { ...command.values };
324
388
  else values = { ...(current ?? effectDefaults(effect)), ...command.values };
389
+ if (
390
+ values &&
391
+ effect === "vowel" &&
392
+ command.type === "fx-set" &&
393
+ command.values.morph !== undefined &&
394
+ values.to === undefined
395
+ )
396
+ return { ok: false, message: `vowel · ${VOWEL_MORPH_NEEDS_TO}` };
325
397
  if (values && effect === "delay" && values.time === 0) {
326
398
  const { time: _time, ...rest } = values;
327
399
  values = rest;