@sudobility/music_types 0.13.18 → 0.13.20

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 (37) hide show
  1. package/CLAUDE.md +11 -3
  2. package/dist/domain/commands/clipboard-commands.d.ts +41 -0
  3. package/dist/domain/commands/clipboard-commands.d.ts.map +1 -0
  4. package/dist/domain/commands/clipboard-commands.js +246 -0
  5. package/dist/domain/commands/clipboard-commands.js.map +1 -0
  6. package/dist/domain/generation/option-order.d.ts +20 -0
  7. package/dist/domain/generation/option-order.d.ts.map +1 -0
  8. package/dist/domain/generation/option-order.js +24 -0
  9. package/dist/domain/generation/option-order.js.map +1 -0
  10. package/dist/domain/generation/replacement-region.d.ts.map +1 -1
  11. package/dist/domain/generation/replacement-region.js +3 -0
  12. package/dist/domain/generation/replacement-region.js.map +1 -1
  13. package/dist/domain/generation/style-presets.d.ts +34 -0
  14. package/dist/domain/generation/style-presets.d.ts.map +1 -0
  15. package/dist/domain/generation/style-presets.js +274 -0
  16. package/dist/domain/generation/style-presets.js.map +1 -0
  17. package/dist/domain/instruments/arrangement-order.d.ts +17 -0
  18. package/dist/domain/instruments/arrangement-order.d.ts.map +1 -1
  19. package/dist/domain/instruments/arrangement-order.js +23 -7
  20. package/dist/domain/instruments/arrangement-order.js.map +1 -1
  21. package/dist/domain/instruments/instrument-options.d.ts +42 -1
  22. package/dist/domain/instruments/instrument-options.d.ts.map +1 -1
  23. package/dist/domain/instruments/instrument-options.js +54 -2
  24. package/dist/domain/instruments/instrument-options.js.map +1 -1
  25. package/dist/domain/notation/notation-icon-art.d.ts +10 -10
  26. package/dist/domain/notation/notation-icon-art.d.ts.map +1 -1
  27. package/dist/domain/notation/notation-icon-art.js +850 -817
  28. package/dist/domain/notation/notation-icon-art.js.map +1 -1
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/model/generation.d.ts +29 -1
  34. package/dist/model/generation.d.ts.map +1 -1
  35. package/dist/model/generation.js +33 -1
  36. package/dist/model/generation.js.map +1 -1
  37. package/package.json +1 -1
@@ -0,0 +1,274 @@
1
+ import { measuresForSeconds, SONG_SECONDS, } from "../notation/music-vocabulary.js";
2
+ /**
3
+ * The keyword values the generation prompt parser branches on.
4
+ *
5
+ * These are shared product data: the app offers them, and the backend needs to
6
+ * know that every offered prompt phrase has genre mechanics.
7
+ */
8
+ const GENERATE_SCORE_STYLE_KEYS = [
9
+ "waltz",
10
+ "jazz",
11
+ "pop",
12
+ "cinematic",
13
+ "ambient",
14
+ "battle",
15
+ "rock",
16
+ "punk",
17
+ "heavyMetal",
18
+ "blues",
19
+ "country",
20
+ "bluegrass",
21
+ "funk",
22
+ "soul",
23
+ "ragtime",
24
+ "swing",
25
+ "bossaNova",
26
+ "samba",
27
+ "salsa",
28
+ "tango",
29
+ "reggae",
30
+ "hipHop",
31
+ "trap",
32
+ "lofi",
33
+ "house",
34
+ "techno",
35
+ "trance",
36
+ "edm",
37
+ "electroSwing",
38
+ "disco",
39
+ "classical",
40
+ "baroque",
41
+ "march",
42
+ ];
43
+ export const GENERATE_SCORE_STYLE_OPTIONS = GENERATE_SCORE_STYLE_KEYS;
44
+ const KIT = "kit:0";
45
+ const STYLE_PRESET_SOURCE = {
46
+ waltz: {
47
+ prompt: 'waltz — a lilting three-four with the weight on beat one and a light "oom-pah-pah" accompaniment',
48
+ instruments: ["0", "48", "43"],
49
+ tempo: 160,
50
+ timeSignature: "3/4",
51
+ },
52
+ jazz: {
53
+ prompt: "jazz — swung eighth notes, walking bass, extended chords, and a melody that phrases across the barline rather than sitting on the beat",
54
+ instruments: ["66", "0", "32", KIT],
55
+ tempo: 132,
56
+ timeSignature: "4/4",
57
+ },
58
+ pop: {
59
+ prompt: "pop — a clear singable hook, four-bar phrases, a backbeat on two and four, and space between the phrases",
60
+ instruments: ["0", "27", "33", KIT],
61
+ tempo: 120,
62
+ timeSignature: "4/4",
63
+ },
64
+ cinematic: {
65
+ prompt: "cinematic orchestral — long sustained lines that build, a rising dynamic arc, and rhythm that serves the swell rather than a groove",
66
+ instruments: ["48", "40", "42", "60", "47"],
67
+ tempo: 90,
68
+ timeSignature: "4/4",
69
+ mode: "minor",
70
+ },
71
+ ambient: {
72
+ prompt: "ambient — slow evolving pads, very long note values, no strong pulse, and silence used as a voice",
73
+ instruments: ["89", "0", "48"],
74
+ tempo: 70,
75
+ timeSignature: "4/4",
76
+ },
77
+ battle: {
78
+ prompt: "driving battle music — insistent ostinato, hard accents, brass stabs against a relentless low pulse",
79
+ instruments: ["61", "48", "47", KIT],
80
+ tempo: 150,
81
+ timeSignature: "4/4",
82
+ mode: "minor",
83
+ },
84
+ rock: {
85
+ prompt: "rock — a hard backbeat on two and four, power-chord riffing, and a bass locked to the kick",
86
+ instruments: ["29", "27", "33", KIT],
87
+ tempo: 128,
88
+ timeSignature: "4/4",
89
+ },
90
+ punk: {
91
+ prompt: "punk — fast straight eighths on downstrokes, three chords, no ornament, and a snare driving every backbeat. The guitar figure repeats unchanged through a section; the energy comes from the tempo and the drive, never from varying the part.",
92
+ instruments: ["30", "29", "34", KIT],
93
+ tempo: 180,
94
+ timeSignature: "4/4",
95
+ },
96
+ heavyMetal: {
97
+ prompt: "heavy metal — built on ONE palm-muted galloping low riff, repeated bar after bar through a section rather than rewritten each bar; minor and modal, double-kick drive underneath, and long held high notes over the top. The riff is the song: keep it the same and let the drums and the held lead supply the variation. ONE riff means one FIGURE, not one note - the riff moves between several pitches (root, flat-7, flat-6 and back is the classic shape), and a bar of the same pitch struck eight times is a pedal, not a riff.",
98
+ instruments: ["30", "29", "34", KIT],
99
+ tempo: 152,
100
+ timeSignature: "4/4",
101
+ mode: "minor",
102
+ },
103
+ blues: {
104
+ formBars: 12,
105
+ prompt: "twelve-bar blues — shuffle feel, blue notes and bends, call-and-response between a voice-like melody and answering fills, dominant seventh chords",
106
+ instruments: ["27", "22", "33", KIT],
107
+ tempo: 88,
108
+ timeSignature: "4/4",
109
+ },
110
+ country: {
111
+ prompt: 'country — a two-beat "boom-chick" bass and guitar, bright major harmony, fiddle and steel fills answering the melody',
112
+ instruments: ["25", "110", "27", "32", KIT],
113
+ tempo: 118,
114
+ timeSignature: "4/4",
115
+ },
116
+ bluegrass: {
117
+ prompt: "bluegrass — fast acoustic picking, banjo rolls in constant eighths under a syncopated fiddle melody, driving upright bass on one and three",
118
+ instruments: ["105", "110", "25", "32"],
119
+ tempo: 160,
120
+ timeSignature: "4/4",
121
+ },
122
+ funk: {
123
+ prompt: "funk — heavily syncopated sixteenth-note groove, everything locked to a hard downbeat on the one, staccato stabs and plenty of rests",
124
+ instruments: ["36", "28", "61", "4", KIT],
125
+ tempo: 104,
126
+ timeSignature: "4/4",
127
+ },
128
+ soul: {
129
+ prompt: "soul — a laid-back backbeat sitting slightly behind the beat, gospel-tinged chords, horn stabs answering a vocal-style melody",
130
+ instruments: ["16", "4", "33", "61", KIT],
131
+ tempo: 96,
132
+ timeSignature: "4/4",
133
+ },
134
+ ragtime: {
135
+ formBars: 16,
136
+ prompt: "ragtime — a syncopated right-hand melody against a steady striding left-hand bass in two, cheerful and precise",
137
+ instruments: ["0"],
138
+ tempo: 96,
139
+ timeSignature: "2/4",
140
+ },
141
+ swing: {
142
+ prompt: "big-band swing — swung eighth notes, brass and reed sections trading riffs, walking bass, ride-cymbal pulse with accents on two and four",
143
+ instruments: ["56", "66", "57", "0", "32", KIT],
144
+ tempo: 168,
145
+ timeSignature: "4/4",
146
+ },
147
+ bossaNova: {
148
+ prompt: "bossa nova — a gentle syncopated guitar pattern, soft brushed drums, a lyrical melody sitting behind the beat, rich seventh and ninth chords",
149
+ instruments: ["24", "0", "32", KIT],
150
+ tempo: 132,
151
+ timeSignature: "4/4",
152
+ },
153
+ samba: {
154
+ prompt: "samba — fast two-beat percussion-driven groove, heavy syncopation on the offbeats, surdo pulse landing on beat two",
155
+ instruments: ["24", "61", "32", KIT],
156
+ tempo: 100,
157
+ timeSignature: "2/4",
158
+ },
159
+ salsa: {
160
+ prompt: "salsa — clave-driven, a montuno piano ostinato, syncopated brass hits, busy percussion, bass playing the tumbao rather than the downbeat",
161
+ instruments: ["0", "56", "57", "32", KIT],
162
+ tempo: 190,
163
+ timeSignature: "4/4",
164
+ },
165
+ tango: {
166
+ prompt: "tango — sharp dotted rhythms and dramatic accents, minor key, sudden stops and rubato pulls against a strict pulse",
167
+ instruments: ["23", "40", "0", "43"],
168
+ tempo: 120,
169
+ timeSignature: "4/4",
170
+ mode: "minor",
171
+ },
172
+ reggae: {
173
+ prompt: "reggae — one-drop: the kick lands on beat three, not one; guitar and organ chop the offbeat eighths; bass plays a heavy melodic line, low and sparse",
174
+ instruments: ["28", "18", "33", KIT],
175
+ tempo: 78,
176
+ timeSignature: "4/4",
177
+ },
178
+ hipHop: {
179
+ prompt: "hip-hop — a hard boom-bap drum pattern with swung sixteenths, a deep sustained sub bass, sparse looping keys, and space left for a vocal",
180
+ instruments: ["39", "4", "48", KIT],
181
+ tempo: 90,
182
+ timeSignature: "4/4",
183
+ mode: "minor",
184
+ },
185
+ trap: {
186
+ prompt: "trap — half-time: the snare lands on beat three alone, an 808 sub bass slides between long tuned notes, and hi-hats roll in fast subdivisions over large gaps",
187
+ instruments: ["38", "11", "89", KIT],
188
+ tempo: 140,
189
+ timeSignature: "4/4",
190
+ mode: "minor",
191
+ },
192
+ lofi: {
193
+ prompt: "lo-fi hip-hop — slow swung drums slightly off the grid, warm jazzy minor seventh chords, a sparse melody, unhurried and repetitive",
194
+ instruments: ["4", "33", "89", KIT],
195
+ tempo: 74,
196
+ timeSignature: "4/4",
197
+ mode: "minor",
198
+ },
199
+ house: {
200
+ prompt: "house — four-on-the-floor kick, offbeat open hats, a repetitive synth riff, and a bassline locked to the eighths between the kicks",
201
+ instruments: ["81", "38", "89", KIT],
202
+ tempo: 126,
203
+ timeSignature: "4/4",
204
+ },
205
+ techno: {
206
+ prompt: "techno — machine-like and loop-based: four-on-the-floor kick, sixteenth-note hats, one short synth-bass cell repeated, and timbre rather than chord changes carrying the track",
207
+ instruments: ["38", "81", "89", KIT],
208
+ tempo: 132,
209
+ timeSignature: "4/4",
210
+ mode: "minor",
211
+ },
212
+ trance: {
213
+ prompt: "trance — four-on-the-floor with an offbeat synth bass after every kick, supersaw arpeggios, and long builds and releases in sixteen-bar blocks",
214
+ instruments: ["81", "38", "89", KIT],
215
+ tempo: 138,
216
+ timeSignature: "4/4",
217
+ mode: "minor",
218
+ },
219
+ edm: {
220
+ prompt: "edm — electronic dance built on a clear build, drop and breakdown in eight-bar blocks, four-on-the-floor underneath and a big repeated lead hook through the drop",
221
+ instruments: ["81", "38", "89", KIT],
222
+ tempo: 128,
223
+ timeSignature: "4/4",
224
+ mode: "minor",
225
+ },
226
+ electroSwing: {
227
+ prompt: "electro swing — vintage swing horns over a modern four-on-the-floor electronic beat, minor and bluesy in a gypsy-jazz vein; hard-swung eighths, syncopated and playful, with clarinet and trumpet riffs answering each other",
228
+ instruments: ["56", "71", "38", KIT],
229
+ tempo: 122,
230
+ timeSignature: "4/4",
231
+ mode: "minor",
232
+ },
233
+ disco: {
234
+ prompt: "disco — four-on-the-floor kick, offbeat hi-hats, an octave-jumping bassline, and string and guitar figures on the sixteenths",
235
+ instruments: ["48", "28", "33", KIT],
236
+ tempo: 120,
237
+ timeSignature: "4/4",
238
+ },
239
+ classical: {
240
+ prompt: "classical — balanced four-bar phrases answering each other, an Alberti or broken-chord accompaniment under a clear diatonic melody, and a cadence every four or eight bars",
241
+ instruments: ["0", "40", "42"],
242
+ tempo: 108,
243
+ timeSignature: "4/4",
244
+ },
245
+ baroque: {
246
+ prompt: "baroque — a steady walking bass, contrapuntal interweaving voices, sequences and ornamented melodic lines, terraced dynamics",
247
+ instruments: ["6", "40", "42"],
248
+ tempo: 100,
249
+ timeSignature: "4/4",
250
+ },
251
+ march: {
252
+ prompt: "march — a firm two-beat pulse, dotted fanfare rhythms, a brass melody over a low oom-pah, crisp snare figures",
253
+ instruments: ["56", "57", "58", KIT],
254
+ tempo: 116,
255
+ timeSignature: "2/4",
256
+ },
257
+ };
258
+ /**
259
+ * The styles, each with the bars its own tempo and meter need for a song.
260
+ */
261
+ export const GENERATE_SCORE_STYLE_PRESETS = Object.fromEntries(Object.entries(STYLE_PRESET_SOURCE).map(([style, preset]) => [
262
+ style,
263
+ {
264
+ ...preset,
265
+ measures: measuresForSeconds(preset.seconds ?? SONG_SECONDS.typical, preset.tempo, beatsPerBarOf(preset.timeSignature), preset.formBars),
266
+ },
267
+ ]));
268
+ /** Beats in a bar, from a picker value like "6/8". */
269
+ function beatsPerBarOf(timeSignature) {
270
+ const [numerator] = timeSignature.split("/");
271
+ const beats = Number(numerator);
272
+ return Number.isFinite(beats) && beats > 0 ? beats : 4;
273
+ }
274
+ //# sourceMappingURL=style-presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-presets.js","sourceRoot":"","sources":["../../../src/domain/generation/style-presets.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,YAAY,GACb,MAAM,iCAAiC,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,yBAAyB,GAAG;IAChC,OAAO;IACP,MAAM;IACN,KAAK;IACL,WAAW;IACX,SAAS;IACT,QAAQ;IACR,MAAM;IACN,MAAM;IACN,YAAY;IACZ,OAAO;IACP,SAAS;IACT,WAAW;IACX,MAAM;IACN,MAAM;IACN,SAAS;IACT,OAAO;IACP,WAAW;IACX,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,cAAc;IACd,OAAO;IACP,WAAW;IACX,SAAS;IACT,OAAO;CACC,CAAC;AAIX,MAAM,CAAC,MAAM,4BAA4B,GACvC,yBAAyB,CAAC;AAqB5B,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB,MAAM,mBAAmB,GAErB;IACF,KAAK,EAAE;QACL,MAAM,EACJ,kGAAkG;QACpG,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;QAC9B,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,wIAAwI;QAC1I,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;QACnC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,GAAG,EAAE;QACH,MAAM,EACJ,0GAA0G;QAC5G,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACnC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,SAAS,EAAE;QACT,MAAM,EACJ,qIAAqI;QACvI,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QAC3C,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,OAAO,EAAE;QACP,MAAM,EACJ,mGAAmG;QACrG,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;QAC9B,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;KACrB;IACD,MAAM,EAAE;QACN,MAAM,EACJ,qGAAqG;QACvG,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,4FAA4F;QAC9F,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,gPAAgP;QAClP,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,UAAU,EAAE;QACV,MAAM,EACJ,ygBAAygB;QAC3gB,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,EAAE;QACZ,MAAM,EACJ,mJAAmJ;QACrJ,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;KACrB;IACD,OAAO,EAAE;QACP,MAAM,EACJ,sHAAsH;QACxH,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QAC3C,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,SAAS,EAAE;QACT,MAAM,EACJ,4IAA4I;QAC9I,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC;QACvC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,sIAAsI;QACxI,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;QACzC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,+HAA+H;QACjI,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACzC,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;KACrB;IACD,OAAO,EAAE;QACP,QAAQ,EAAE,EAAE;QACZ,MAAM,EACJ,gHAAgH;QAClH,WAAW,EAAE,CAAC,GAAG,CAAC;QAClB,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;KACrB;IACD,KAAK,EAAE;QACL,MAAM,EACJ,0IAA0I;QAC5I,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;QAC/C,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,SAAS,EAAE;QACT,MAAM,EACJ,8IAA8I;QAChJ,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;QACnC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,KAAK,EAAE;QACL,MAAM,EACJ,oHAAoH;QACtH,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,KAAK,EAAE;QACL,MAAM,EACJ,0IAA0I;QAC5I,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACzC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,KAAK,EAAE;QACL,MAAM,EACJ,oHAAoH;QACtH,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,MAAM,EAAE;QACN,MAAM,EACJ,sJAAsJ;QACxJ,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;KACrB;IACD,MAAM,EAAE;QACN,MAAM,EACJ,0IAA0I;QAC5I,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;QACnC,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,+JAA+J;QACjK,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,IAAI,EAAE;QACJ,MAAM,EACJ,oIAAoI;QACtI,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACnC,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,KAAK,EAAE;QACL,MAAM,EACJ,oIAAoI;QACtI,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,MAAM,EAAE;QACN,MAAM,EACJ,gLAAgL;QAClL,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,MAAM,EAAE;QACN,MAAM,EACJ,gJAAgJ;QAClJ,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,GAAG,EAAE;QACH,MAAM,EACJ,mKAAmK;QACrK,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,YAAY,EAAE;QACZ,MAAM,EACJ,8NAA8N;QAChO,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,OAAO;KACd;IACD,KAAK,EAAE;QACL,MAAM,EACJ,8HAA8H;QAChI,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,SAAS,EAAE;QACT,MAAM,EACJ,4KAA4K;QAC9K,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;QAC9B,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,OAAO,EAAE;QACP,MAAM,EACJ,8HAA8H;QAChI,WAAW,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;QAC9B,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;IACD,KAAK,EAAE;QACL,MAAM,EACJ,+GAA+G;QACjH,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;QACpC,KAAK,EAAE,GAAG;QACV,aAAa,EAAE,KAAK;KACrB;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAErC,MAAM,CAAC,WAAW,CACpB,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC3D,KAAK;IACL;QACE,GAAG,MAAM;QACT,QAAQ,EAAE,kBAAkB,CAC1B,MAAM,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,EACtC,MAAM,CAAC,KAAK,EACZ,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EACnC,MAAM,CAAC,QAAQ,CAChB;KACF;CACF,CAAC,CACH,CAAC;AAEF,sDAAsD;AACtD,SAAS,aAAa,CAAC,aAAqB;IAC1C,MAAM,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -5,6 +5,23 @@ export type RankableTrack = {
5
5
  midiProgram: number;
6
6
  clef?: string | undefined;
7
7
  };
8
+ /**
9
+ * The three General MIDI programs that are a human voice.
10
+ *
11
+ * GM files them under `ensemble`, beside String Ensemble and Orchestra Hit --
12
+ * which is a fair description of Choir Aahs used as a wash, and the wrong one
13
+ * for the part carrying the song. Named here rather than moved to another
14
+ * family because the family is GM's and is right about everything else in it.
15
+ *
16
+ * Exported because the instrument picker offers these three as a group of
17
+ * their own, and a picker that restated the numbers would be a second list to
18
+ * keep in step with this one.
19
+ *
20
+ * `Pad 4 (choir)` (91) is deliberately absent: it says pad in its name and is
21
+ * one. `Lead 6 (voice)` (85) is absent too, already reaching `lead` through
22
+ * `synth-lead`.
23
+ */
24
+ export declare const VOICE_PROGRAMS: ReadonlySet<number>;
8
25
  /** Whether this program is a sung part rather than an instrument. */
9
26
  export declare function isVocalProgram(midiProgram: number): boolean;
10
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"arrangement-order.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/arrangement-order.ts"],"names":[],"mappings":"AA2BA,oFAAoF;AACpF,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,CAAC;AAiCF,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe,CAO5D;AAqDD,gDAAgD;AAChD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,SAAS,eAAe,EAAE,CAO5B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,EAAE,CAwBV"}
1
+ {"version":3,"file":"arrangement-order.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/arrangement-order.ts"],"names":[],"mappings":"AA2BA,oFAAoF;AACpF,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE,qFAAqF;AACrF,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,CAAC;AAeF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAI7C,CAAC;AAEH,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe,CAO5D;AAqDD,gDAAgD;AAChD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,SAAS,eAAe,EAAE,CAO5B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,EAAE,CAoCV"}
@@ -43,11 +43,15 @@ const HARMONY_FAMILIES = new Set([
43
43
  * for the part carrying the song. Named here rather than moved to another
44
44
  * family because the family is GM's and is right about everything else in it.
45
45
  *
46
+ * Exported because the instrument picker offers these three as a group of
47
+ * their own, and a picker that restated the numbers would be a second list to
48
+ * keep in step with this one.
49
+ *
46
50
  * `Pad 4 (choir)` (91) is deliberately absent: it says pad in its name and is
47
51
  * one. `Lead 6 (voice)` (85) is absent too, already reaching `lead` through
48
52
  * `synth-lead`.
49
53
  */
50
- const VOICE_PROGRAMS = new Set([
54
+ export const VOICE_PROGRAMS = new Set([
51
55
  52, // Choir Aahs
52
56
  53, // Voice Oohs
53
57
  54, // Synth Voice
@@ -101,9 +105,9 @@ const DEFAULT_ORDER = [
101
105
  *
102
106
  * In reggae the bassline *is* the tune — the "riddim" is named and reused
103
107
  * across songs while melodies come and go — and the same is true of funk, hip
104
- * hop, house and disco, where the groove is the material and the melody
105
- * decorates it. Writing a melody first in those styles produces a bass that is
106
- * following a tune instead of stating the hook.
108
+ * hop, trap, house, techno, trance, EDM and disco, where the groove is the
109
+ * material and the melody decorates it. Writing a melody first in those styles
110
+ * produces a bass that is following a tune instead of stating the hook.
107
111
  */
108
112
  const GROOVE_FIRST = [
109
113
  "bass",
@@ -111,7 +115,7 @@ const GROOVE_FIRST = [
111
115
  "harmony",
112
116
  "lead",
113
117
  ];
114
- const GROOVE_LED = /\b(reggae|ska|dub|funk|disco|house|hip hop|hip-hop|lofi|lo-fi|soul|samba|salsa|bossa|tango|afrobeat)\b/i;
118
+ const GROOVE_LED = /\b(reggae|ska|dub|funk|disco|house|techno|trance|edm|electronic dance|hip hop|hip-hop|trap|lofi|lo-fi|soul|samba|salsa|bossa|tango|afrobeat)\b/i;
115
119
  /**
116
120
  * Genres built on a riff, where the riff is a lead part and goes first anyway —
117
121
  * but the kit is promoted above the harmony, because in these styles the drums
@@ -153,7 +157,7 @@ export function rankTracksForGeneration(tracks, style) {
153
157
  return index === -1 ? order.length : index;
154
158
  };
155
159
  /*
156
- Among leads, the singer goes first.
160
+ The singer goes first, ahead of the role order rather than inside it.
157
161
 
158
162
  Two parts can both be leads — a vocal and a guitar — and then role alone
159
163
  leaves the order to however the roster happened to be typed. In a song the
@@ -161,11 +165,23 @@ export function rankTracksForGeneration(tracks, style) {
161
165
  behind them are written to fit. Ranked by index instead, a guitar listed
162
166
  first got composed with no melody to sit under, and the singer then had to
163
167
  bend around it.
168
+
169
+ This outranks the genre order, and that is the correction rather than an
170
+ oversight. `GROOVE_FIRST` writes the lead LAST — in reggae the bassline is
171
+ the material and the melody decorates it, which is true of an instrumental
172
+ and inverts the moment somebody is singing over it. In those eleven genres
173
+ every backing part was composed before the voice existed, so the rule that
174
+ tells a part to accompany the singer (`vocalSupportRule` in music_api) had
175
+ no singer to point at and never fired: the arrangement was finished and the
176
+ vocal was bent to fit it, which is exactly backwards.
177
+
178
+ A percussion track is never promoted, whatever its program addresses: on
179
+ the drum channel program 53 is a kit, not a voice.
164
180
  */
165
181
  const voiceFirst = (track) => isVocalProgram(track.midiProgram) && track.clef !== "percussion" ? 0 : 1;
166
182
  return tracks
167
183
  .map((track, index) => ({ index, rank: rankOf(track), voice: voiceFirst(track) }))
168
- .sort((a, b) => a.rank - b.rank || a.voice - b.voice || a.index - b.index)
184
+ .sort((a, b) => a.voice - b.voice || a.rank - b.rank || a.index - b.index)
169
185
  .map((entry) => entry.index);
170
186
  }
171
187
  //# sourceMappingURL=arrangement-order.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"arrangement-order.js","sourceRoot":"","sources":["../../../src/domain/instruments/arrangement-order.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"arrangement-order.js","sourceRoot":"","sources":["../../../src/domain/instruments/arrangement-order.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,15 @@ export type InstrumentOption = {
33
33
  };
34
34
  /** The default selection: Piano, which is also the melody-carrying lead. */
35
35
  export declare const DEFAULT_INSTRUMENT_VALUE = "0";
36
+ /**
37
+ * The voice a song is carried by, when one is added for the reader.
38
+ *
39
+ * `Voice Oohs` rather than `Choir Aahs`: a lead vocal is one person, and the
40
+ * choir patch is what a *backing* line sounds like. This is the only place the
41
+ * distinction between the three voice programs is stated — everywhere else
42
+ * they are simply "a voice" — so it is stated once, here.
43
+ */
44
+ export declare const DEFAULT_VOCAL_INSTRUMENT_VALUE = "53";
36
45
  /**
37
46
  * The `KIT_OPTIONS` value for a program.
38
47
  *
@@ -42,6 +51,29 @@ export declare const DEFAULT_INSTRUMENT_VALUE = "0";
42
51
  export declare function kitOptionValue(program: number): string;
43
52
  /** The eight GM drum kits, for a percussion track. */
44
53
  export declare const KIT_OPTIONS: InstrumentOption[];
54
+ /**
55
+ * The three programs that are a human voice, as a group of their own.
56
+ *
57
+ * GM files them under `ensemble`, between String Ensemble and Orchestra Hit,
58
+ * which is where nobody setting out to write a song looks for a singer — so in
59
+ * practice a generated score never had one. The group is *derived* from the set
60
+ * the arranger reads (`VOICE_PROGRAMS`) rather than restating three numbers,
61
+ * because a picker offering a voice the arranger does not recognise as one is
62
+ * exactly the drift that costs a vocal-led arrangement.
63
+ *
64
+ * The default lead goes first and the rest follow in catalogue order: the first
65
+ * entry of a group is the one a reader takes as its ordinary answer, and here
66
+ * that answer is the solo voice.
67
+ */
68
+ export declare const VOICE_OPTIONS: InstrumentOption[];
69
+ /**
70
+ * Whether a picker value is a sung part.
71
+ *
72
+ * Through the value rather than the program, because `kit:52` addresses a drum
73
+ * kit and a bare number check would read it as a choir — the same confusion
74
+ * `KIT_PREFIX` exists to prevent everywhere else.
75
+ */
76
+ export declare function isVocalInstrumentValue(value: string): boolean;
45
77
  /**
46
78
  * Every melodic program, grouped by GM family.
47
79
  *
@@ -50,10 +82,19 @@ export declare const KIT_OPTIONS: InstrumentOption[];
50
82
  */
51
83
  export declare const INSTRUMENT_OPTIONS: InstrumentOption[];
52
84
  /** The same catalogue as nested groups, for a picker that draws its own headings. */
85
+ /**
86
+ * The same catalogue as nested groups, for a picker that draws its own headings.
87
+ *
88
+ * **The voices are not in it**: they are offered as `VOICE_OPTIONS` above, and
89
+ * a program appearing in two groups of one menu is an entry whose selection is
90
+ * ambiguous — the control shows whichever heading it matched first and the
91
+ * reader cannot tell the two apart. `INSTRUMENT_OPTIONS` keeps all 128, because
92
+ * that one is the catalogue rather than a menu.
93
+ */
53
94
  export declare const FAMILY_GROUPS: {
54
95
  key: "bass" | "pipe" | "piano" | "chromatic-percussion" | "organ" | "guitar" | "strings" | "ensemble" | "brass" | "reed" | "synth-lead" | "synth-pad" | "synth-effects" | "ethnic" | "percussive" | "sound-effects";
55
96
  label: string;
56
- instruments: readonly import("./gm.js").GmInstrument[];
97
+ instruments: import("./gm.js").GmInstrument[];
57
98
  }[];
58
99
  /** Turns a picker value — from either list — back into track fields. */
59
100
  export declare function instrumentChoiceFor(value: string): InstrumentChoice;
@@ -1 +1 @@
1
- {"version":3,"file":"instrument-options.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/instrument-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAS3C,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,4EAA4E;AAC5E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,sDAAsD;AACtD,eAAO,MAAM,WAAW,EAAE,gBAAgB,EAGvC,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAOhD,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,aAAa;;;;GAIvB,CAAC;AAYJ,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAiBnE;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD"}
1
+ {"version":3,"file":"instrument-options.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/instrument-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAU3C,+EAA+E;AAC/E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,4EAA4E;AAC5E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAEnD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,sDAAsD;AACtD,eAAO,MAAM,WAAW,EAAE,gBAAgB,EAGvC,CAAC;AAEJ;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,EAAE,gBAAgB,EAQzC,CAAC;AAEJ;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAOhD,CAAC;AAEF,qFAAqF;AACrF;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;;;;GAMyB,CAAC;AAYpD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAiBnE;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -1,8 +1,18 @@
1
1
  import { GM_FAMILIES, GM_FAMILY_LABELS, gmInstrument, gmInstrumentsByFamily, } from "./gm.js";
2
2
  import { GM_KITS, gmKit, gmKitAt } from "./gm-kit.js";
3
+ import { VOICE_PROGRAMS, isVocalProgram } from "./arrangement-order.js";
3
4
  const KIT_PREFIX = "kit:";
4
5
  /** The default selection: Piano, which is also the melody-carrying lead. */
5
6
  export const DEFAULT_INSTRUMENT_VALUE = "0";
7
+ /**
8
+ * The voice a song is carried by, when one is added for the reader.
9
+ *
10
+ * `Voice Oohs` rather than `Choir Aahs`: a lead vocal is one person, and the
11
+ * choir patch is what a *backing* line sounds like. This is the only place the
12
+ * distinction between the three voice programs is stated — everywhere else
13
+ * they are simply "a voice" — so it is stated once, here.
14
+ */
15
+ export const DEFAULT_VOCAL_INSTRUMENT_VALUE = "53";
6
16
  /**
7
17
  * The `KIT_OPTIONS` value for a program.
8
18
  *
@@ -17,6 +27,39 @@ export const KIT_OPTIONS = GM_KITS.map((kit) => ({
17
27
  value: `${KIT_PREFIX}${kit.program}`,
18
28
  label: kit.name,
19
29
  }));
30
+ /**
31
+ * The three programs that are a human voice, as a group of their own.
32
+ *
33
+ * GM files them under `ensemble`, between String Ensemble and Orchestra Hit,
34
+ * which is where nobody setting out to write a song looks for a singer — so in
35
+ * practice a generated score never had one. The group is *derived* from the set
36
+ * the arranger reads (`VOICE_PROGRAMS`) rather than restating three numbers,
37
+ * because a picker offering a voice the arranger does not recognise as one is
38
+ * exactly the drift that costs a vocal-led arrangement.
39
+ *
40
+ * The default lead goes first and the rest follow in catalogue order: the first
41
+ * entry of a group is the one a reader takes as its ordinary answer, and here
42
+ * that answer is the solo voice.
43
+ */
44
+ export const VOICE_OPTIONS = [
45
+ Number(DEFAULT_VOCAL_INSTRUMENT_VALUE),
46
+ ...[...VOICE_PROGRAMS].filter((program) => program !== Number(DEFAULT_VOCAL_INSTRUMENT_VALUE)),
47
+ ].map((program) => ({
48
+ value: String(program),
49
+ label: gmInstrument(program)?.name ?? "Voice",
50
+ }));
51
+ /**
52
+ * Whether a picker value is a sung part.
53
+ *
54
+ * Through the value rather than the program, because `kit:52` addresses a drum
55
+ * kit and a bare number check would read it as a choir — the same confusion
56
+ * `KIT_PREFIX` exists to prevent everywhere else.
57
+ */
58
+ export function isVocalInstrumentValue(value) {
59
+ if (value.startsWith(KIT_PREFIX))
60
+ return false;
61
+ return isVocalProgram(Number(value));
62
+ }
20
63
  /**
21
64
  * Every melodic program, grouped by GM family.
22
65
  *
@@ -29,11 +72,20 @@ export const INSTRUMENT_OPTIONS = GM_FAMILIES.flatMap((family) => gmInstrumentsB
29
72
  group: GM_FAMILY_LABELS[family],
30
73
  })));
31
74
  /** The same catalogue as nested groups, for a picker that draws its own headings. */
75
+ /**
76
+ * The same catalogue as nested groups, for a picker that draws its own headings.
77
+ *
78
+ * **The voices are not in it**: they are offered as `VOICE_OPTIONS` above, and
79
+ * a program appearing in two groups of one menu is an entry whose selection is
80
+ * ambiguous — the control shows whichever heading it matched first and the
81
+ * reader cannot tell the two apart. `INSTRUMENT_OPTIONS` keeps all 128, because
82
+ * that one is the catalogue rather than a menu.
83
+ */
32
84
  export const FAMILY_GROUPS = GM_FAMILIES.map((family) => ({
33
85
  key: family,
34
86
  label: GM_FAMILY_LABELS[family],
35
- instruments: gmInstrumentsByFamily(family),
36
- }));
87
+ instruments: gmInstrumentsByFamily(family).filter((instrument) => !isVocalProgram(instrument.program)),
88
+ })).filter((group) => group.instruments.length > 0);
37
89
  /**
38
90
  * The clef a melodic program is written on.
39
91
  *
@@ -1 +1 @@
1
- {"version":3,"file":"instrument-options.js","sourceRoot":"","sources":["../../../src/domain/instruments/instrument-options.ts"],"names":[],"mappings":"AAqBA,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAgBtD,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,4EAA4E;AAC5E,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;AACpD,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,WAAW,GAAuB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnE,KAAK,EAAE,GAAG,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE;IACpC,KAAK,EAAE,GAAG,CAAC,IAAI;CAChB,CAAC,CAAC,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAuB,WAAW,CAAC,OAAO,CACvE,CAAC,MAAM,EAAE,EAAE,CACT,qBAAqB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACjD,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;IACjC,KAAK,EAAE,UAAU,CAAC,IAAI;IACtB,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC;CAChC,CAAC,CAAC,CACN,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxD,GAAG,EAAE,MAAM;IACX,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC;IAC/B,WAAW,EAAE,qBAAqB,CAAC,MAAM,CAAC;CAC3C,CAAC,CAAC,CAAC;AAEJ;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,OAAO,OAAO,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC5D,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,2EAA2E;QAC3E,6DAA6D;QAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;QACxE,OAAO;YACL,WAAW,EAAE,GAAG,CAAC,OAAO;YACxB,cAAc,EAAE,GAAG,CAAC,IAAI;YACxB,IAAI,EAAE,YAAY;SACnB,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO;QACL,WAAW,EAAE,OAAO;QACpB,cAAc,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,OAAO;QACtD,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"instrument-options.js","sourceRoot":"","sources":["../../../src/domain/instruments/instrument-options.ts"],"names":[],"mappings":"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"}
@@ -19,8 +19,8 @@
19
19
  /** Every glyph is authored in a 24×24 box. */
20
20
  export declare const NOTATION_ICON_VIEWBOX = 24;
21
21
  /** A stroke cap/join, spelled as SVG spells it. */
22
- export type NotationLineCap = "butt" | "round" | "square";
23
- export type NotationLineJoin = "miter" | "round" | "bevel";
22
+ export type NotationLineCap = 'butt' | 'round' | 'square';
23
+ export type NotationLineJoin = 'miter' | 'round' | 'bevel';
24
24
  type Paint = {
25
25
  readonly fill?: string;
26
26
  readonly stroke?: string;
@@ -32,29 +32,29 @@ type Paint = {
32
32
  readonly transform?: string;
33
33
  };
34
34
  export type NotationIconShape = (Paint & {
35
- readonly kind: "path";
35
+ readonly kind: 'path';
36
36
  readonly d: string;
37
- readonly fillRule?: "evenodd" | "nonzero";
37
+ readonly fillRule?: 'evenodd' | 'nonzero';
38
38
  }) | (Paint & {
39
- readonly kind: "rect";
39
+ readonly kind: 'rect';
40
40
  readonly x: number;
41
41
  readonly y: number;
42
42
  readonly width: number;
43
43
  readonly height: number;
44
44
  readonly rx?: number;
45
45
  }) | (Paint & {
46
- readonly kind: "ellipse";
46
+ readonly kind: 'ellipse';
47
47
  readonly cx: number;
48
48
  readonly cy: number;
49
49
  readonly rx: number;
50
50
  readonly ry: number;
51
51
  }) | (Paint & {
52
- readonly kind: "circle";
52
+ readonly kind: 'circle';
53
53
  readonly cx: number;
54
54
  readonly cy: number;
55
55
  readonly r: number;
56
56
  }) | (Paint & {
57
- readonly kind: "text";
57
+ readonly kind: 'text';
58
58
  readonly x: number;
59
59
  readonly y: number;
60
60
  readonly content: string;
@@ -62,7 +62,7 @@ export type NotationIconShape = (Paint & {
62
62
  readonly fontStyle?: string;
63
63
  readonly textAnchor?: string;
64
64
  }) | (Paint & {
65
- readonly kind: "group";
65
+ readonly kind: 'group';
66
66
  readonly shapes: readonly NotationIconShape[];
67
67
  });
68
68
  /**
@@ -71,7 +71,7 @@ export type NotationIconShape = (Paint & {
71
71
  * A union has no runtime form, so anything that must *validate* a name would
72
72
  * otherwise write the list out again.
73
73
  */
74
- export declare const NOTATION_ICON_NAMES: readonly ["AddMeasureIcon", "ArpeggioIcon", "ArticulationIcon", "BeamBreakIcon", "BeamNoneIcon", "ChordIcon", "ContinuousLayoutIcon", "CrescendoIcon", "DeleteMeasureIcon", "DiminuendoIcon", "DottedIcon", "DoubleFlatIcon", "DoubleSharpIcon", "EighthNoteIcon", "FermataIcon", "FlatIcon", "GoToStartIcon", "HalfNoteIcon", "InsertModeIcon", "InsertNoteIcon", "InsertRestIcon", "MetronomeIcon", "NaturalIcon", "NextMeasureIcon", "OrnamentIcon", "PageLayoutIcon", "PreviousMeasureIcon", "QuantizeIcon", "QuarterNoteIcon", "ReplaceModeIcon", "SelectAllIcon", "SharpIcon", "SixteenthNoteIcon", "SlurIcon", "SoloIcon", "SunMoonIcon", "ThirtySecondNoteIcon", "TieIcon", "TripletIcon", "WholeNoteIcon"];
74
+ export declare const NOTATION_ICON_NAMES: readonly ["AddMeasureIcon", "ArpeggioIcon", "ArticulationIcon", "BeamBreakIcon", "BeamNoneIcon", "ChordIcon", "ContinuousLayoutIcon", "CrescendoIcon", "DeleteMeasureIcon", "DiminuendoIcon", "DottedIcon", "DoubleFlatIcon", "DoubleSharpIcon", "EighthNoteIcon", "FermataIcon", "FlatIcon", "GoToStartIcon", "HalfNoteIcon", "InsertModeIcon", "InsertNoteIcon", "InsertRestIcon", "MetronomeIcon", "NaturalIcon", "NextMeasureIcon", "OrnamentIcon", "PageLayoutIcon", "PianoKeysIcon", "PreviousMeasureIcon", "QuantizeIcon", "QuarterNoteIcon", "ReplaceModeIcon", "SelectAllIcon", "SharpIcon", "SixteenthNoteIcon", "SlurIcon", "SoloIcon", "SunMoonIcon", "ThirtySecondNoteIcon", "TieIcon", "TripletIcon", "WholeNoteIcon"];
75
75
  export type NotationIconName = (typeof NOTATION_ICON_NAMES)[number];
76
76
  /**
77
77
  * A record, never a parallel array: adding a name above fails to compile until