@hraness/dawg 0.6.1 → 0.8.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 (277) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DAWG.md +454 -140
  3. package/README.md +30 -26
  4. package/core/autotune.ts +1119 -0
  5. package/core/chords.ts +271 -23
  6. package/core/clips.ts +499 -0
  7. package/core/diff.ts +184 -104
  8. package/core/expression.ts +15 -0
  9. package/core/fx.ts +99 -29
  10. package/core/ids.ts +52 -0
  11. package/core/instruments.ts +19 -0
  12. package/core/keys.ts +3 -3
  13. package/core/loop.ts +8 -0
  14. package/core/lyrics.ts +297 -0
  15. package/core/master.ts +3 -3
  16. package/core/range.ts +581 -0
  17. package/core/resonators.ts +16 -2
  18. package/core/routing.ts +165 -0
  19. package/core/score.ts +955 -14
  20. package/core/sdk/eval-child.ts +7 -2
  21. package/core/sdk/eval.ts +35 -6
  22. package/core/sdk/print.ts +287 -5
  23. package/core/sdk/sync-lyrics.ts +49 -0
  24. package/core/sdk/v1.ts +2132 -46
  25. package/core/sections.ts +480 -35
  26. package/core/sing.ts +815 -0
  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/guides/agent.md +29 -0
  50. package/guides/arrange.md +31 -0
  51. package/guides/audio.md +31 -0
  52. package/guides/audition.md +20 -14
  53. package/guides/automation.md +12 -7
  54. package/guides/chords.md +15 -15
  55. package/guides/effects.md +17 -16
  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 +15 -7
  62. package/guides/music.md +23 -8
  63. package/guides/notes.md +15 -9
  64. package/guides/panes.md +32 -0
  65. package/guides/performance.md +15 -13
  66. package/guides/play.md +21 -13
  67. package/guides/project.md +26 -8
  68. package/guides/providers.md +20 -14
  69. package/guides/resample.md +15 -9
  70. package/guides/rhythm.md +18 -13
  71. package/guides/sessions.md +17 -7
  72. package/guides/show-me.md +31 -0
  73. package/guides/sound.md +25 -9
  74. package/guides/sounds.md +15 -13
  75. package/guides/styles.md +31 -0
  76. package/guides/tape.md +32 -0
  77. package/guides/tempo.md +15 -10
  78. package/guides/tracks.md +15 -10
  79. package/guides/tuning.md +32 -0
  80. package/guides/voice.md +31 -0
  81. package/guides/web-search.md +18 -8
  82. package/native/prebuilt/darwin-arm64/libdawg_sink.dylib +0 -0
  83. package/native/prebuilt/darwin-x64/libdawg_sink.dylib +0 -0
  84. package/native/prebuilt/linux-arm64/libdawg_sink.so +0 -0
  85. package/native/prebuilt/linux-x64/libdawg_sink.so +0 -0
  86. package/native/prebuilt/manifest.json +21 -0
  87. package/package.json +6 -2
  88. package/src/agent/agent.ts +130 -18
  89. package/src/agent/calibration-tools.ts +53 -0
  90. package/src/agent/clip-tools.ts +453 -0
  91. package/src/agent/command-agent.ts +378 -0
  92. package/src/agent/drum-tools.ts +2 -2
  93. package/src/agent/expression-tools.ts +1 -1
  94. package/src/agent/gateway.ts +246 -60
  95. package/src/agent/models.ts +53 -12
  96. package/src/agent/ops.ts +27 -1
  97. package/src/agent/pack-tools.ts +1 -1
  98. package/src/agent/planner.ts +25 -0
  99. package/src/agent/portable-schema.ts +80 -0
  100. package/src/agent/preview-tool.ts +4 -1
  101. package/src/agent/provider.ts +22 -8
  102. package/src/agent/range-tools.ts +216 -0
  103. package/src/agent/rhythm-tools.ts +1 -1
  104. package/src/agent/section-tools.ts +1 -1
  105. package/src/agent/show-me.ts +497 -0
  106. package/src/agent/steer.ts +15 -0
  107. package/src/agent/style-tools.ts +217 -0
  108. package/src/agent/tool-error.ts +12 -0
  109. package/src/agent/tools.ts +110 -23
  110. package/src/agent/usage.ts +2 -2
  111. package/src/agent/voice-tools.ts +925 -0
  112. package/src/agent/xcb-agent.ts +13 -10
  113. package/src/argv.ts +38 -0
  114. package/src/audio/analysis.ts +253 -0
  115. package/src/audio/arrange.ts +49 -5
  116. package/src/audio/audio-command.ts +218 -0
  117. package/src/audio/autotune-engine.ts +101 -0
  118. package/src/audio/autotune.ts +640 -0
  119. package/src/audio/clips.ts +240 -0
  120. package/src/audio/devices.ts +264 -0
  121. package/src/audio/doctor.ts +157 -0
  122. package/src/audio/dsp/bandbank.ts +138 -0
  123. package/src/audio/dsp/envelope.ts +10 -0
  124. package/src/audio/dsp/follow.ts +120 -0
  125. package/src/audio/dsp/formant.ts +427 -0
  126. package/src/audio/dsp/glottal.ts +243 -0
  127. package/src/audio/dsp/interp.ts +7 -2
  128. package/src/audio/dsp/lpc.ts +50 -0
  129. package/src/audio/dsp/periodicity.ts +59 -0
  130. package/src/audio/dsp/pitch.ts +995 -0
  131. package/src/audio/dsp/psola.ts +199 -0
  132. package/src/audio/effects/chain.ts +3 -1
  133. package/src/audio/effects/common.ts +43 -0
  134. package/src/audio/effects/convolution.ts +7 -4
  135. package/src/audio/effects/filter.ts +48 -69
  136. package/src/audio/effects/formant.ts +263 -0
  137. package/src/audio/engine.ts +360 -40
  138. package/src/audio/fit.ts +35 -3
  139. package/src/audio/instrument-check.ts +59 -43
  140. package/src/audio/instruments.ts +4 -0
  141. package/src/audio/keys/calibration.ts +56 -0
  142. package/src/audio/keys/electric.ts +8 -1
  143. package/src/audio/keys/engine.ts +13 -1
  144. package/src/audio/keys/piano.ts +22 -2
  145. package/src/audio/kits.ts +135 -6
  146. package/src/audio/live.ts +114 -20
  147. package/src/audio/native.ts +615 -0
  148. package/src/audio/preview.ts +30 -2
  149. package/src/audio/render-worker.ts +2 -0
  150. package/src/audio/renderer.ts +2 -0
  151. package/src/audio/resample.ts +2 -1
  152. package/src/audio/sampler.ts +85 -4
  153. package/src/audio/samples.ts +20 -2
  154. package/src/audio/sing/analysis.ts +193 -0
  155. package/src/audio/sing/engine.ts +949 -0
  156. package/src/audio/strings/bow.ts +48 -5
  157. package/src/audio/strings/engine.ts +8 -2
  158. package/src/audio/synth/oscillators.ts +31 -21
  159. package/src/audio/synth/voice.ts +34 -1
  160. package/src/audio/vocoder/bank.ts +314 -0
  161. package/src/audio/vocoder/carrier.ts +165 -0
  162. package/src/audio/vocoder/control.ts +68 -0
  163. package/src/audio/vocoder/detect.ts +50 -0
  164. package/src/audio/vocoder/index.ts +304 -0
  165. package/src/audio/vocoder/talkbox.ts +143 -0
  166. package/src/audio/wav.ts +500 -77
  167. package/src/audio/winds/engine.ts +5 -1
  168. package/src/audio/winds/trim.ts +28 -4
  169. package/src/audio/winds/trims1.ts +297 -0
  170. package/src/audio/winds/voice.ts +15 -2
  171. package/src/auth/cli.ts +38 -36
  172. package/src/auth/credentials.ts +30 -1
  173. package/src/auth/login.ts +15 -9
  174. package/src/auth/tui.ts +19 -10
  175. package/src/commands/arrange.ts +82 -32
  176. package/src/commands/autotune.ts +421 -0
  177. package/src/commands/calibration.ts +74 -0
  178. package/src/commands/clips.ts +887 -0
  179. package/src/commands/drums.ts +3 -2
  180. package/src/commands/edit.ts +11 -4
  181. package/src/commands/expression.ts +1 -1
  182. package/src/commands/formant.ts +221 -0
  183. package/src/commands/fx.ts +101 -32
  184. package/src/commands/grammar.ts +560 -0
  185. package/src/commands/help.ts +774 -366
  186. package/src/commands/history.ts +139 -10
  187. package/src/commands/keys.ts +25 -8
  188. package/src/commands/modal.ts +1 -1
  189. package/src/commands/music.ts +1 -1
  190. package/src/commands/nearest.ts +53 -0
  191. package/src/commands/pack.ts +9 -2
  192. package/src/commands/param-range.ts +56 -0
  193. package/src/commands/parses.ts +135 -0
  194. package/src/commands/progression.ts +170 -0
  195. package/src/commands/range.ts +763 -0
  196. package/src/commands/resample.ts +13 -10
  197. package/src/commands/rhythm.ts +3 -0
  198. package/src/commands/rig.ts +3 -24
  199. package/src/commands/sample.ts +11 -1
  200. package/src/commands/sing.ts +474 -0
  201. package/src/commands/strum.ts +13 -1
  202. package/src/commands/style.ts +415 -0
  203. package/src/commands/time.ts +6 -3
  204. package/src/commands/tuning.ts +3 -3
  205. package/src/commands/vocal-pitch.ts +617 -0
  206. package/src/commands/vocal.ts +147 -0
  207. package/src/commands/vocoder.ts +627 -0
  208. package/src/commands/wind.ts +2 -2
  209. package/src/fs/durable.ts +50 -0
  210. package/src/identity/actor.ts +127 -0
  211. package/src/lang/glossary.ts +511 -0
  212. package/src/launch-args.ts +267 -0
  213. package/src/main.ts +2508 -308
  214. package/src/media/cli.ts +20 -3
  215. package/src/media/import.ts +3 -1
  216. package/src/project/check.ts +21 -2
  217. package/src/project/clip-pins.ts +72 -0
  218. package/src/project/init.ts +23 -8
  219. package/src/project/sync.ts +418 -86
  220. package/src/render.ts +20 -1
  221. package/src/session/client.ts +107 -3
  222. package/src/session/clipboard.ts +79 -0
  223. package/src/session/daemon.ts +199 -5
  224. package/src/session/live-host.ts +232 -0
  225. package/src/session/meta.ts +14 -0
  226. package/src/session/origin.ts +174 -0
  227. package/src/session/port.ts +109 -14
  228. package/src/session/presence.ts +34 -4
  229. package/src/session/protocol.ts +365 -7
  230. package/src/session/rebase.ts +63 -12
  231. package/src/session/receipt.ts +265 -0
  232. package/src/session/shared-live.ts +131 -0
  233. package/src/session/store.ts +126 -45
  234. package/src/tui/arrange-menu.ts +225 -23
  235. package/src/tui/audition.ts +1 -1
  236. package/src/tui/euclid.ts +113 -27
  237. package/src/tui/fader.ts +282 -42
  238. package/src/tui/granular-menu.ts +2 -4
  239. package/src/tui/knob-fields.ts +107 -0
  240. package/src/tui/knob-map.ts +198 -0
  241. package/src/tui/menu-clips.ts +297 -0
  242. package/src/tui/menu-time.ts +20 -13
  243. package/src/tui/menu-voice.ts +405 -0
  244. package/src/tui/menu.ts +987 -179
  245. package/src/tui/modal-menu.ts +6 -6
  246. package/src/tui/performance-menu.ts +5 -2
  247. package/src/tui/play-chords.ts +4 -2
  248. package/src/tui/play-mode.ts +15 -1
  249. package/src/tui/play-session.ts +243 -28
  250. package/src/tui/sing-menu.ts +278 -0
  251. package/src/tui/style-menu.ts +104 -0
  252. package/src/tui/tape-mode.ts +580 -0
  253. package/src/tui/tape-view.ts +263 -0
  254. package/src/tui/vocoder-menu.ts +244 -0
  255. package/src/tui/wind-menu.ts +3 -3
  256. package/src/version.ts +8 -0
  257. package/src/web/fetch.ts +115 -29
  258. package/tui/activity.ts +180 -9
  259. package/tui/app.ts +491 -84
  260. package/tui/clip-row.ts +132 -0
  261. package/tui/delight.ts +193 -0
  262. package/tui/drawer.ts +233 -27
  263. package/tui/frame-gate.ts +76 -0
  264. package/tui/grammar.ts +143 -65
  265. package/tui/guide.ts +50 -5
  266. package/tui/highway.ts +309 -30
  267. package/tui/hints.ts +197 -0
  268. package/tui/hits.ts +7 -1
  269. package/tui/input.ts +60 -9
  270. package/tui/keys.ts +1 -1
  271. package/tui/knobs.ts +268 -0
  272. package/tui/play-strip.ts +80 -14
  273. package/tui/prompt.ts +1 -1
  274. package/tui/screen.ts +151 -18
  275. package/tui/tape.ts +439 -0
  276. package/tui/text.ts +35 -2
  277. package/tui/theme.ts +46 -1
@@ -0,0 +1,429 @@
1
+ /**
2
+ * StyleCard schema (quality-08). A card holds a style's theory as numbers:
3
+ * meter and cycles, tempo, groove templates, onset probability grids per
4
+ * role, the pitch system, a harmonic grammar, melody statistics, bass
5
+ * behaviour, form plans, a texture of dawg instruments, expression and mix.
6
+ * Generators (`generate.ts`) sample these numbers with a seeded PRNG and
7
+ * validators (`validate.ts`) measure the same numbers on the result.
8
+ *
9
+ * Cards form the taxonomy tree (`taxonomy.ts`). A root or branch card holds
10
+ * what its leaves share; a leaf holds only its deltas. `resolveStyle(id)`
11
+ * (index.ts) folds BASE_STYLE and the cards on the path root..leaf into one
12
+ * frozen `ResolvedStyle`. Merge rules (`mergeCard`):
13
+ *
14
+ * - scalars, ranges and arrays: the child replaces the parent
15
+ * - records (roles, onsets, chain, fx, levels): merged per key, `null`
16
+ * deletes the key
17
+ * - `{ "+": Weighted<T> }` in place of a weighted list appends to the
18
+ * parent's list (same value: the weight adds)
19
+ *
20
+ * Theory, not material: cards hold grids, distributions and grammars, never
21
+ * melodies, lyrics, transcriptions or audio. Every instrument, preset, kit,
22
+ * rig, tuning, scale, progression, stroke, section and fx name must exist on
23
+ * main; `styles.test.ts` checks them against the registries.
24
+ */
25
+
26
+ /** A taxonomy id (kebab-case), node or leaf. */
27
+ import type { SongStyle } from "../style-provenance.ts";
28
+
29
+ export type StyleId = string;
30
+ /** Inclusive `[min, max]`. */
31
+ export type Range = readonly [min: number, max: number];
32
+ /** Weighted choices; weights are positive and renormalised when sampled. */
33
+ export type Weighted<T> = readonly (readonly [value: T, weight: number])[];
34
+
35
+ export const ROLE_NAMES = Object.freeze([
36
+ "kick",
37
+ "snare",
38
+ "clap",
39
+ "hat",
40
+ "openhat",
41
+ "rim",
42
+ "tom",
43
+ "perc",
44
+ "shaker",
45
+ "bell",
46
+ "bass",
47
+ "chords",
48
+ "pad",
49
+ "lead",
50
+ "counter",
51
+ "drone",
52
+ "arp",
53
+ ] as const);
54
+ export type RoleName = (typeof ROLE_NAMES)[number];
55
+
56
+ /** Roles played by the drum kit track (the seven kit voices). */
57
+ export const KIT_ROLES = Object.freeze([
58
+ "kick",
59
+ "snare",
60
+ "clap",
61
+ "rim",
62
+ "tom",
63
+ "hat",
64
+ "openhat",
65
+ ] as const satisfies readonly RoleName[]);
66
+ export type KitRole = (typeof KIT_ROLES)[number];
67
+
68
+ /** Percussion roles on their own track (pitched hand drums, bells). */
69
+ export const PERC_ROLES = Object.freeze([
70
+ "perc",
71
+ "shaker",
72
+ "bell",
73
+ ] as const satisfies readonly RoleName[]);
74
+
75
+ /** Pitched roles: one track each. */
76
+ export const PITCHED_ROLES = Object.freeze([
77
+ "bass",
78
+ "chords",
79
+ "pad",
80
+ "lead",
81
+ "counter",
82
+ "drone",
83
+ "arp",
84
+ ] as const satisfies readonly RoleName[]);
85
+ export type PitchedRole = (typeof PITCHED_ROLES)[number];
86
+
87
+ // ---------------------------------------------------------------------------
88
+ // Meter, cycle, tempo
89
+
90
+ export type CycleSpec = Readonly<{
91
+ kind: "tala" | "iqa" | "gongan" | "timeline" | "usul" | "compas";
92
+ /** Theory name of the cycle ("tintal", "maqsum", "lancaran"). */
93
+ name: string;
94
+ /** Pulses per cycle. */
95
+ beats: number;
96
+ /** Section lengths summing to `beats` (tintal [4,4,4,4]). */
97
+ divisions: readonly number[];
98
+ /**
99
+ * One stroke per pulse, `"."` for a rest. Strokes in `low` (default
100
+ * dum, dha, dhin, ge, gong, kempul, doum, bum) play the low voice of the
101
+ * perc role; others play the high voice.
102
+ */
103
+ strokes: readonly string[];
104
+ low?: readonly string[];
105
+ /** Stressed pulses, 1-based (sam = 1). */
106
+ stress: readonly number[];
107
+ /** Released (khali, wave) pulses, 1-based. */
108
+ release?: readonly number[];
109
+ }>;
110
+
111
+ export type MeterSpec = Readonly<{
112
+ /** Weighted time signatures: [["4/4", 1]], [["7/8", 0.6], ["9/8", 0.4]]. */
113
+ signatures: Weighted<string>;
114
+ /**
115
+ * Beat grouping for additive meters in the signature's denominator
116
+ * units: 7/8 [2,2,3]. Sums to the numerator. Drives the accent profile.
117
+ */
118
+ grouping?: Weighted<readonly number[]>;
119
+ /** Bars per hypermetric unit (phrase grid): 4 pop, 8 EDM, 12 blues. */
120
+ hypermeter: Weighted<number>;
121
+ /** A cyclic time system (tala, iqa', gongan) played by the perc role. */
122
+ cycle?: CycleSpec;
123
+ }>;
124
+
125
+ export type TempoSpec = Readonly<{
126
+ /** Quarter-note BPM, inclusive; also clamped to dawg's 20..300. */
127
+ bpm: Range;
128
+ /** The mode of the tempo distribution. */
129
+ typical: number;
130
+ }>;
131
+
132
+ // ---------------------------------------------------------------------------
133
+ // Groove and rhythm
134
+
135
+ export type GrooveSpec = Readonly<{
136
+ /** Template steps per quarter beat: 4 (16ths), 3 (triplets), 2 (8ths). */
137
+ subdivision: number;
138
+ /**
139
+ * Long:short ratio of each off-beat pair: 1 straight, 1.5 light,
140
+ * 2 triplet, 2.5 hard shuffle. Only meaningful for even subdivisions.
141
+ */
142
+ swingRatio: Range;
143
+ /** Per-step offsets over one beat in fractions of a step (-0.5..0.5). */
144
+ microtiming?: readonly number[];
145
+ /** Per-step velocity multipliers over one beat (0..1.5). */
146
+ velocity?: readonly number[];
147
+ /** Per-role timing bias in fractions of a step (snare 0.08 lays back). */
148
+ roleOffset?: Readonly<Partial<Record<RoleName, number>>>;
149
+ /** Seeded humanisation: timing sd in ms (0..30), velocity sd (0..0.2). */
150
+ humanize: Readonly<{ timingMs: number; velocity: number }>;
151
+ }>;
152
+
153
+ export type RhythmLock = Readonly<{
154
+ /** with: b only where a; avoid: b never where a. */
155
+ kind: "with" | "avoid";
156
+ a: RoleName;
157
+ b: RoleName;
158
+ }>;
159
+
160
+ export type RhythmSpec = Readonly<{
161
+ /**
162
+ * Onset probability per step over one bar (steps = bar beats ×
163
+ * subdivision; for a cycle, cycle beats × subdivision). 1 is a defining
164
+ * hit, 0.3 an optional ghost. The pattern is stretched to the actual
165
+ * grid when the bar length differs (`gridFor`).
166
+ */
167
+ onsets: Readonly<Partial<Record<RoleName, readonly number[]>>>;
168
+ /** Locks the generator enforces and the validator checks. */
169
+ locks?: readonly RhythmLock[];
170
+ /** A fill on the kit's toms and snare every `every` bars at phrase ends. */
171
+ fills?: Readonly<{ every: number; density: Range }>;
172
+ }>;
173
+
174
+ // ---------------------------------------------------------------------------
175
+ // Pitch, harmony, melody, bass
176
+
177
+ export type RagaSpec = Readonly<{
178
+ /** Ascent and descent as semitone degrees above Sa (0..12). */
179
+ aroha: readonly number[];
180
+ avaroha: readonly number[];
181
+ /** Most important degree and its partner (semitones from Sa). */
182
+ vadi: number;
183
+ samvadi: number;
184
+ /** Characteristic cells (theory, not a quotation), semitone degrees. */
185
+ pakad?: readonly (readonly number[])[];
186
+ }>;
187
+
188
+ export type MaqamSpec = Readonly<{
189
+ /** Sayr: register targets in scale degrees (0-based) the phrases visit in order. */
190
+ sayr: readonly number[];
191
+ /** Degree (0-based) of the ghammaz, the upper jins's tonic. */
192
+ ghammaz: number;
193
+ }>;
194
+
195
+ export type PitchSpec = Readonly<{
196
+ /** A TUNING_NAMES entry; absent is 12-TET. */
197
+ tuning?: string;
198
+ /**
199
+ * Weighted SCALES or MODES names (12-note tunings). Fractional steps
200
+ * (maqam quarter tones) play as cents offsets on the nearest key.
201
+ */
202
+ scales: Weighted<string>;
203
+ /**
204
+ * For a tuning whose period is not 12 notes (pelog, slendro): the tuning
205
+ * degrees (0-based) the style uses, e.g. pelog nem [0,1,2,4,5]. Notes
206
+ * are keys `root + octave × size + degree`.
207
+ */
208
+ degrees?: readonly number[];
209
+ /** Weighted tonic pitch classes, or "any". */
210
+ tonic: Weighted<number> | "any";
211
+ maqam?: MaqamSpec;
212
+ raga?: RagaSpec;
213
+ }>;
214
+
215
+ export type VoicingSpec = Readonly<{
216
+ /** close, open, wide (chord engine spreads), shell (3+7), power (1+5), quartal. */
217
+ types: Weighted<string>;
218
+ /** MIDI range of the chord role. */
219
+ range: Range;
220
+ /** Sounding notes per chord. */
221
+ notes: Range;
222
+ /** A STROKE_PATTERNS name for a strummed chord role. */
223
+ strokes?: Weighted<string>;
224
+ }>;
225
+
226
+ export type HarmonySpec = Readonly<{
227
+ /**
228
+ * functional: numeral grammar (presets, chain, forms); modal: a vamp on
229
+ * the tonic and neighbours; drone: tonic and fifth only; none: no chords.
230
+ */
231
+ model: "functional" | "modal" | "drone" | "none";
232
+ /** Weighted PROGRESSION_PRESETS names. */
233
+ presets?: Weighted<string>;
234
+ /** Weighted fixed changes (12-bar blues) as numerals, one per bar unit. */
235
+ forms?: Weighted<readonly string[]>;
236
+ /** Markov chain over numerals: from -> weighted next. */
237
+ chain?: Readonly<Record<string, Weighted<string>>>;
238
+ /** Weights of presets : forms : chain when several are set. */
239
+ sources?: Readonly<{ presets?: number; forms?: number; chain?: number }>;
240
+ /** Phrase-final cadences: "V-I", "IV-I", "bVII-I", "V-vi", "iv-I", "bII-I", "half". */
241
+ cadences: Weighted<string>;
242
+ /** Chords per bar (0.5 = one chord per two bars). */
243
+ rhythm: Weighted<number>;
244
+ /** Seventh rate: chance a triad numeral gets its diatonic seventh. */
245
+ sevenths: number;
246
+ voicing: VoicingSpec;
247
+ }>;
248
+
249
+ export type MelodySpec = Readonly<{
250
+ /** arch, ascending, descending, wave, flat, terraced. */
251
+ contour: Weighted<string>;
252
+ /** Semitone span of one phrase. */
253
+ ambitus: Range;
254
+ /** MIDI range of the lead. */
255
+ range: Range;
256
+ /** Signed step weights for -12..12 semitones (25 bins). */
257
+ intervals: readonly number[];
258
+ /** Chance a strong-beat note is a chord tone (functional harmony only). */
259
+ chordToneRate: number;
260
+ /** Onsets per beat. */
261
+ density: Range;
262
+ /** Phrase lengths in bars. */
263
+ phraseBars: Weighted<number>;
264
+ /** Chance a phrase repeats the previous phrase's rhythm. */
265
+ repetition: number;
266
+ /** Phrase-final scale degrees (0-based scale indices). */
267
+ finals: Weighted<number>;
268
+ /**
269
+ * Serial pitch order (12-note scales only). "pitch": every pitched role
270
+ * takes its pitch classes, in time order, from a seeded twelve-tone row
271
+ * and its P, I, R and RI forms, so each aggregate completes before a
272
+ * pitch class repeats. "integral": the row also orders a twelve-step
273
+ * duration series and a twelve-step dynamics series.
274
+ */
275
+ row?: "pitch" | "integral";
276
+ }>;
277
+
278
+ export type BassSpec = Readonly<{
279
+ /** root, root-fifth, walking, octave, arpeggio, pedal, ostinato, none. */
280
+ behaviour: Weighted<string>;
281
+ range: Range;
282
+ /** Onset probability grid (same steps as rhythm); walking ignores it. */
283
+ onsets?: readonly number[];
284
+ /** Walking: chord tone on beat 1 rate and chromatic approach rate. */
285
+ walk?: Readonly<{ chordToneOnOne: number; chromaticApproach: number }>;
286
+ /** Fraction of bass onsets that must coincide with a kick (validator). */
287
+ kickLock?: number;
288
+ }>;
289
+
290
+ // ---------------------------------------------------------------------------
291
+ // Form, texture, expression, mix
292
+
293
+ /** SECTION_KINDS from core/sections.ts. */
294
+ export type SectionKind =
295
+ | "intro"
296
+ | "verse"
297
+ | "pre"
298
+ | "chorus"
299
+ | "build"
300
+ | "drop"
301
+ | "breakdown"
302
+ | "bridge"
303
+ | "outro";
304
+
305
+ export type FormSpec = Readonly<{
306
+ /** Weighted section plans. */
307
+ plans: Weighted<readonly SectionKind[]>;
308
+ /** Energy 0..1 per section kind: density and role entry. */
309
+ energy?: Readonly<Partial<Record<SectionKind, number>>>;
310
+ /** Roles that play in a section kind (absent: every role). */
311
+ roleMap?: Readonly<Partial<Record<SectionKind, readonly RoleName[]>>>;
312
+ /** Named archetype for the agent: aaba, 12-bar, strophic, alap-jor-jhala. */
313
+ archetype?: string;
314
+ }>;
315
+
316
+ export type RoleVoice = Readonly<{
317
+ /**
318
+ * An instrument word on main (`core/instruments.ts`): a legacy word
319
+ * (piano, bass, lead...), a row word (upright, rhodes, oud, tabla,
320
+ * flute, choir...), or "drums" for the kit.
321
+ */
322
+ instrument: string;
323
+ /** Drum kit: a SYNTH_KIT_NAMES entry. */
324
+ kit?: string;
325
+ /** Guitar rig: a RIG_PRESETS name. */
326
+ rig?: string;
327
+ weight: number;
328
+ }>;
329
+
330
+ export type RoleTexture = Readonly<{
331
+ required: boolean;
332
+ voices: readonly RoleVoice[];
333
+ }>;
334
+
335
+ export type TextureSpec = Readonly<{
336
+ roles: Readonly<Partial<Record<RoleName, RoleTexture | null>>>;
337
+ kind:
338
+ | "monophonic"
339
+ | "homophonic"
340
+ | "polyphonic"
341
+ | "heterophonic"
342
+ | "interlocking";
343
+ }>;
344
+
345
+ export type ExpressionSpec = Readonly<{
346
+ /** Velocity range across the song, 0..1. */
347
+ dynamics: Range;
348
+ /** ARTICULATIONS weights per pitched role. */
349
+ articulation?: Readonly<Partial<Record<RoleName, Weighted<string>>>>;
350
+ }>;
351
+
352
+ export type MixSpec = Readonly<{
353
+ /** FX_PRESETS per role: effect -> preset name. */
354
+ fx?: Readonly<Partial<Record<RoleName, Readonly<Record<string, string>>>>>;
355
+ /** Role levels in dB relative to 0 (lead). */
356
+ levels?: Readonly<Partial<Record<RoleName, number>>>;
357
+ /** Pan -1..1. */
358
+ pan?: Readonly<Partial<Record<RoleName, number>>>;
359
+ /** Overall reverb amount 0..1. */
360
+ space: number;
361
+ /**
362
+ * Loudness target the song master normalises to (core/master.ts
363
+ * LOUDNESS_TARGETS: streaming, club, loud, classical, ambient...). The
364
+ * generated song always carries a limiter, so it never clips.
365
+ */
366
+ loudness?: string;
367
+ }>;
368
+
369
+ // ---------------------------------------------------------------------------
370
+ // Cards
371
+
372
+ /** A full style: every section present (BASE_STYLE plus the card path). */
373
+ export type ResolvedStyle = Readonly<{
374
+ id: StyleId;
375
+ title: string;
376
+ /** Root..leaf ids whose cards were merged (cards only). */
377
+ lineage: readonly StyleId[];
378
+ summary: string;
379
+ seedSalt: number;
380
+ meter: MeterSpec;
381
+ tempo: TempoSpec;
382
+ groove: GrooveSpec;
383
+ rhythm: RhythmSpec;
384
+ pitch: PitchSpec;
385
+ harmony: HarmonySpec;
386
+ melody: MelodySpec;
387
+ bass: BassSpec;
388
+ form: FormSpec;
389
+ texture: TextureSpec;
390
+ expression: ExpressionSpec;
391
+ mix: MixSpec;
392
+ wants: readonly string[];
393
+ }>;
394
+
395
+ /** Deep partial with `null` deletions for records. */
396
+ export type Patch<T> = T extends readonly unknown[]
397
+ ? T | Readonly<{ "+": T }>
398
+ : T extends object
399
+ ? { readonly [K in keyof T]?: Patch<T[K]> | null }
400
+ : T;
401
+
402
+ /** The fields of a resolved style a card may set. */
403
+ export type StyleBody = Omit<ResolvedStyle, "id" | "title" | "lineage">;
404
+
405
+ export type StyleCard = Readonly<{
406
+ /** A taxonomy id. */
407
+ id: StyleId;
408
+ /** Abstract cards (branch nodes) resolve but are flagged in /style list. */
409
+ abstract?: boolean;
410
+ }> &
411
+ Patch<StyleBody>;
412
+
413
+ /** Identity helper for card literals (type checks the patch). */
414
+ export function card(value: StyleCard): StyleCard {
415
+ return Object.freeze(value);
416
+ }
417
+
418
+ /** Generation options shared by /style, the agent tool and the SDK. */
419
+ export type StyleOptions = Readonly<{
420
+ seed?: number;
421
+ bars?: number;
422
+ /** Tonic pitch class override (0 = C). */
423
+ tonic?: number;
424
+ /** Tempo override (clamped into the style's range). */
425
+ bpm?: number;
426
+ }>;
427
+
428
+ /** Provenance stored on a song: which style and seed made it (`score.style`). */
429
+ export type StyleProvenance = SongStyle;