@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
package/CLAUDE.md CHANGED
@@ -35,7 +35,7 @@ Everything exports from a single sectioned `src/index.ts`:
35
35
  8. Zod schemas for the project API
36
36
  9. Response envelope (`ApiResponse<T>`, `successResponse`, `errorResponse`, `API_ERROR_CODES`)
37
37
 
38
- `src/test-helpers.ts` is a test-only factory stand-in (excluded from the published build); the real factories live in `@sudobility/music_lib`.
38
+ `src/test-helpers.ts` is a test-only fixture helper (excluded from the published build); shared score factories live in this package under `domain/score/`.
39
39
 
40
40
  ## Gotchas
41
41
 
@@ -65,7 +65,11 @@ Everything exports from a single sectioned `src/index.ts`:
65
65
  `PlaybackObserver` and `AuditionVoice` did move, because that package is the
66
66
  only thing that implements or calls them.
67
67
 
68
- - No domain logic here: tick math, factories, commands, validation logic all live in `@sudobility/music_lib`. This package must never depend on music_lib (music_api depends on this package and must not pull in UI/audio code).
68
+ - Pure shared domain logic belongs here when both frontend and backend need it:
69
+ tick math, factories, commands, validation, instrument knowledge, generation
70
+ presets and prompt-facing shared data. This package must never depend on
71
+ `music_lib`, and `music_api` must never pull in frontend UI/audio code just
72
+ to reach a shared rule.
69
73
  - `noteEventSchema`/`restEventSchema` are `.strict()` on purpose (a stray `pitch` key must not pass as a rest); other schemas strip unknown keys for forward compatibility.
70
74
  - Ticks are integers at 480 PPQ by convention; `startTick` is absolute.
71
75
  - **A picker's option list belongs beside the vocabulary it is built from**
@@ -112,11 +116,15 @@ Everything exports from a single sectioned `src/index.ts`:
112
116
 
113
117
  - **A guard test enforces that this package runs on React Native** (`src/platform-free.test.ts`): no web-only global and no `import.meta`. This matters more here than anywhere else — these are the platform *interfaces* every other repo implements, so one DOM type in a signature spreads to all of them. That is why `FileExporter.save` takes `Uint8Array | string` rather than a `Blob`, and the codecs take `ArrayBuffer`. `tsconfig.json` still sets `lib: [..., "DOM"]` (for `AbortSignal`) and `eslint.config.js` still spreads `globals.browser`, so nothing else would object.
114
118
 
119
+ - **A singer is a picker group, not a hunt through Ensemble.** General MIDI files the three voice programs (52 Choir Aahs, 53 Voice Oohs, 54 Synth Voice) under *ensemble*, between String Ensemble and Orchestra Hit — so in practice no generated score ever had one in it, while the backend carries several hundred lines of lyric and vocal-support rules for a part nobody could ask for. `VOICE_OPTIONS` lifts them into a group of their own at the top of the generation pickers, **derived from `VOICE_PROGRAMS`** in `arrangement-order.ts` rather than restating three numbers: a picker offering a voice the arranger does not recognise as one is exactly the drift that costs a vocal-led arrangement. They leave `FAMILY_GROUPS` in the same move, because a program in two groups of one menu is a selection the control cannot show unambiguously — but `INSTRUMENT_OPTIONS` keeps all 128, since that one is the catalogue and not a menu. `isVocalInstrumentValue` answers on the picker *value*, so `kit:52` is a drum kit rather than a choir.
120
+ - **The singer is written first, ahead of the genre order.** In `rankTracksForGeneration`, `voiceFirst` used to be a tiebreak among equally ranked parts, so it only did anything where `lead` already came first. `GROOVE_FIRST` writes the lead **last** — in reggae the bassline is the material and the melody decorates it, which is true of an instrumental and inverts the moment somebody is singing over it — so in eleven genres every backing part was composed before the voice existed, `vocalSupportRule` in music_api had no singer to point at, and the vocal was bent to fit a finished arrangement instead of the other way round. It is now the primary sort key, and `roleOrderForStyle` is untouched, so a roster with no voice is arranged exactly as it was. A percussion track is never promoted, whatever its program addresses: on the drum channel, program 53 is a kit.
121
+ - **A closed vocabulary is offered in the order it is read, not the order it was declared.** `sortOptionsByLabel` sorts on the **translated** label under the active language. Both halves matter: the value is `electroSwing` while the reader sees "Electro Swing", so sorting the keys puts entries wherever their camel-case identifier happens to fall; and collating Chinese labels by the English they were translated from produces an order with no visible logic at all. The 33 styles and 6 moods go through it in both apps — an ordering rule written twice is one that eventually disagrees with itself.
122
+
115
123
  ## Related Projects
116
124
 
117
125
  - `music_api` — backend (Hono/Drizzle/OpenAI proxy), consumes schemas for validation
118
126
  - `music_client` — typed network client + React Query hooks
119
- - `music_lib` — domain logic, adapters, store
127
+ - `music_lib` — frontend app logic, adapters, store
120
128
  - `music_app` — web app (UI/routing only)
121
129
 
122
130
  ## Git Workflow
@@ -0,0 +1,41 @@
1
+ import type { ScoreCommand } from "./types.js";
2
+ import type { Measure, Track, UUID } from "../../model/score.js";
3
+ /**
4
+ * The bars at one span of indices, across every track.
5
+ *
6
+ * `tracks[i]` holds the measures copied from `score.tracks[i]`, so putting a
7
+ * slice back is a positional match. A score with fewer tracks than the slice
8
+ * takes what fits and drops the rest, rather than refusing: pasting four bars
9
+ * of a quartet into a piano part should give you the piano's two staves' worth,
10
+ * not an error.
11
+ */
12
+ export type MeasureSlice = {
13
+ /** How many bars the slice is long. Every entry in `tracks` has this many. */
14
+ count: number;
15
+ tracks: Measure[][];
16
+ };
17
+ /** Empties the named bars, keeping the bars themselves and their markings. */
18
+ export declare function clearMeasuresCommand(measureIds: readonly UUID[], label: string): ScoreCommand;
19
+ /** Empties every bar of a track, keeping the track, its instrument and its mix. */
20
+ export declare function clearTrackCommand(trackId: UUID, label: string): ScoreCommand;
21
+ /**
22
+ * Inserts the slice before `atIndex`, in every track.
23
+ *
24
+ * Everything from that bar on moves later by `slice.count` bars — which is what
25
+ * "insert" means and why this is not `replaceMeasuresCommand` with a longer
26
+ * score afterwards.
27
+ */
28
+ export declare function insertMeasuresCommand(atIndex: number, slice: MeasureSlice, label: string): ScoreCommand;
29
+ /**
30
+ * Overwrites `slice.count` bars starting at `atIndex`, in every track.
31
+ *
32
+ * The score's length does not change and nothing moves, so a slice running past
33
+ * the end simply stops — replacing bars that are not there would be an insert
34
+ * wearing the wrong name.
35
+ */
36
+ export declare function replaceMeasuresCommand(atIndex: number, slice: MeasureSlice, label: string): ScoreCommand;
37
+ /** Adds the track at `atIndex`, fitted to the score's own measure grid. */
38
+ export declare function insertTrackCommand(source: Track, atIndex: number, label: string): ScoreCommand;
39
+ /** Replaces one track with a copied one, in place, keeping the score's grid. */
40
+ export declare function replaceTrackCommand(trackId: UUID, source: Track, label: string): ScoreCommand;
41
+ //# sourceMappingURL=clipboard-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard-commands.d.ts","sourceRoot":"","sources":["../../../src/domain/commands/clipboard-commands.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EACV,OAAO,EAEP,KAAK,EACL,IAAI,EAEL,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;CACrB,CAAC;AAgCF,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,SAAS,IAAI,EAAE,EAC3B,KAAK,EAAE,MAAM,GACZ,YAAY,CAad;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,EACb,KAAK,EAAE,MAAM,GACZ,YAAY,CAgBd;AA6ED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,MAAM,GACZ,YAAY,CAsBd;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,MAAM,GACZ,YAAY,CAiBd;AA2BD,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,YAAY,CAUd;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,IAAI,EACb,MAAM,EAAE,KAAK,EACb,KAAK,EAAE,MAAM,GACZ,YAAY,CAWd"}
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Clearing, and pasting a whole object.
3
+ *
4
+ * These are the score half of the context menu: the commands behind Clear,
5
+ * Delete and the two shapes of Paste, for each of the three things a reader can
6
+ * select. Delete already existed at every level (`deleteEventsCommand`,
7
+ * `deleteMeasureCommand`, `deleteTrackCommand`); what did not was **Clear**,
8
+ * and the two are genuinely different edits rather than two names for one.
9
+ *
10
+ * **Clear keeps the container and empties it.** A cleared bar is still a bar —
11
+ * it keeps its number, its signatures, its barline, its repeats and its clef
12
+ * change, and only the notes become a rest; a cleared track is still a track,
13
+ * with its instrument, clef and mix intact. Delete removes the container, and
14
+ * everything behind it moves up. Offering only Delete meant "empty these four
15
+ * bars" had to be done by deleting them and adding four back, which loses every
16
+ * marking on them and renumbers the rest of the score twice.
17
+ *
18
+ * **A bar is the same bar on every stave, so anything that changes the grid
19
+ * changes it everywhere.** `deleteMeasureCommand` already worked that way. The
20
+ * measure clipboard is therefore a *vertical slice* — the bars at those indices
21
+ * across every track, not one part's — and inserting or replacing puts the
22
+ * slice back across every track. A slice that inserted into one part would
23
+ * leave the score's parts disagreeing about where bar 40 is, which is the thing
24
+ * `changeRepeatsCommand` and `setPickupCommand` both refuse to allow.
25
+ *
26
+ * Nothing here is a store action: each is a pure `(Score) => Score` like every
27
+ * other command, so `music_api` can apply one with no store, and the deciding —
28
+ * insert or replace, clear or delete — stays with whoever asked.
29
+ */
30
+ import { createId } from "../score/ids.js";
31
+ import { rebuildMeasureTicks } from "../score/factory.js";
32
+ import { transformCommand } from "./snapshot.js";
33
+ import { withTracks } from "./reflow.js";
34
+ /** One rest filling a whole bar — what an emptied measure holds. */
35
+ function restVoice(measure, trackId) {
36
+ const voiceId = createId();
37
+ return {
38
+ id: voiceId,
39
+ name: "Voice 1",
40
+ events: [
41
+ {
42
+ id: createId(),
43
+ startTick: measure.startTick,
44
+ durationTicks: measure.durationTicks,
45
+ voiceId,
46
+ trackId,
47
+ },
48
+ ],
49
+ };
50
+ }
51
+ /**
52
+ * The same bar with nothing played in it.
53
+ *
54
+ * Spread rather than rebuilt, so every field this module does not know about
55
+ * survives — a barline, a repeat, an ending, a clef change, a pickup flag, and
56
+ * whatever is added to `Measure` next. Rebuilding the measure from its known
57
+ * fields is how a clear comes to silently drop a marking somebody added later.
58
+ */
59
+ function clearedMeasure(measure, trackId) {
60
+ return { ...measure, voices: [restVoice(measure, trackId)] };
61
+ }
62
+ /** Empties the named bars, keeping the bars themselves and their markings. */
63
+ export function clearMeasuresCommand(measureIds, label) {
64
+ const wanted = new Set(measureIds);
65
+ return transformCommand(label, (score) => withTracks(score, score.tracks.map((track) => ({
66
+ ...track,
67
+ measures: track.measures.map((measure) => wanted.has(measure.id) ? clearedMeasure(measure, track.id) : measure),
68
+ }))));
69
+ }
70
+ /** Empties every bar of a track, keeping the track, its instrument and its mix. */
71
+ export function clearTrackCommand(trackId, label) {
72
+ return transformCommand(label, (score) => withTracks(score, score.tracks.map((track) => track.id === trackId
73
+ ? {
74
+ ...track,
75
+ measures: track.measures.map((measure) => clearedMeasure(measure, track.id)),
76
+ }
77
+ : track)));
78
+ }
79
+ /**
80
+ * A copied event, re-identified for the track it is landing in.
81
+ *
82
+ * Fresh ids on every paste, because an id is what the caret lights, what the
83
+ * selection holds and what `findEvent` resolves — two events sharing one would
84
+ * make a paste select its own source.
85
+ */
86
+ function adoptEvent(event, voiceId, trackId) {
87
+ return { ...event, id: createId(), voiceId, trackId };
88
+ }
89
+ /**
90
+ * A copied bar, re-identified for the track it is landing in.
91
+ *
92
+ * **Its `startTick` is deliberately left as the source's.** A measure and its
93
+ * events state absolute ticks and have to agree with each other;
94
+ * `rebuildMeasureTicks` re-times the whole score afterwards by shifting each
95
+ * measure *and its events* by the same delta, so a bar that arrives internally
96
+ * consistent lands correctly wherever it is spliced. Stamping the destination's
97
+ * tick on the measure alone breaks that agreement and leaves every pasted note
98
+ * sitting outside the bar that holds it — which looks like an empty bar, not
99
+ * like an error.
100
+ *
101
+ * A pasted bar arrives **whole**: its notes, its signatures and its length. That
102
+ * is plainly what inserting a bar means, and it is what keeps replace honest
103
+ * too — a 3/4 bar pasted over a 4/4 one replaces the bar, not just its
104
+ * contents. The grid stays consistent because a slice is a vertical one, so
105
+ * every track receives the same lengths.
106
+ */
107
+ function adoptMeasure(source, trackId) {
108
+ return {
109
+ ...source,
110
+ id: createId(),
111
+ voices: source.voices.map((voice) => {
112
+ const voiceId = createId();
113
+ return {
114
+ ...voice,
115
+ id: voiceId,
116
+ events: voice.events.map((event) => adoptEvent(event, voiceId, trackId)),
117
+ };
118
+ }),
119
+ };
120
+ }
121
+ /**
122
+ * A silent bar of the same shape, for a track the slice has nothing for.
123
+ *
124
+ * Pasting a two-track slice into a four-track score still has to give all four
125
+ * the same bar, or the parts stop agreeing about where each bar is — so the
126
+ * shape comes from the *slice*, never from the destination. Taking the
127
+ * destination's shape is the subtle version of the same bug: two tracks would
128
+ * get the pasted 3/4 bar and the rest would keep a 4/4 one.
129
+ */
130
+ function blankLike(shape, trackId) {
131
+ const blank = { ...shape, id: createId() };
132
+ return { ...blank, voices: [restVoice(blank, trackId)] };
133
+ }
134
+ /**
135
+ * The bar every track should receive at this offset.
136
+ *
137
+ * The first track the slice actually has something for: they all came from one
138
+ * score's grid, so any of them states the length and signatures the whole
139
+ * column must share.
140
+ */
141
+ function shapeAt(slice, offset) {
142
+ for (const measures of slice.tracks) {
143
+ const measure = measures?.[offset];
144
+ if (measure)
145
+ return measure;
146
+ }
147
+ return undefined;
148
+ }
149
+ /**
150
+ * Inserts the slice before `atIndex`, in every track.
151
+ *
152
+ * Everything from that bar on moves later by `slice.count` bars — which is what
153
+ * "insert" means and why this is not `replaceMeasuresCommand` with a longer
154
+ * score afterwards.
155
+ */
156
+ export function insertMeasuresCommand(atIndex, slice, label) {
157
+ return transformCommand(label, (score) => {
158
+ if (slice.count <= 0)
159
+ return score;
160
+ const tracks = score.tracks.map((track, trackIndex) => {
161
+ const source = slice.tracks[trackIndex];
162
+ const added = [];
163
+ for (let offset = 0; offset < slice.count; offset += 1) {
164
+ const from = source?.[offset];
165
+ if (from) {
166
+ added.push(adoptMeasure(from, track.id));
167
+ continue;
168
+ }
169
+ const shape = shapeAt(slice, offset);
170
+ if (shape)
171
+ added.push(blankLike(shape, track.id));
172
+ }
173
+ if (added.length === 0)
174
+ return track;
175
+ const measures = [...track.measures];
176
+ measures.splice(Math.max(0, atIndex), 0, ...added);
177
+ return { ...track, measures };
178
+ });
179
+ return rebuildMeasureTicks(withTracks(score, tracks));
180
+ });
181
+ }
182
+ /**
183
+ * Overwrites `slice.count` bars starting at `atIndex`, in every track.
184
+ *
185
+ * The score's length does not change and nothing moves, so a slice running past
186
+ * the end simply stops — replacing bars that are not there would be an insert
187
+ * wearing the wrong name.
188
+ */
189
+ export function replaceMeasuresCommand(atIndex, slice, label) {
190
+ return transformCommand(label, (score) => {
191
+ if (slice.count <= 0)
192
+ return score;
193
+ const tracks = score.tracks.map((track, trackIndex) => {
194
+ const source = slice.tracks[trackIndex];
195
+ const measures = track.measures.map((measure, index) => {
196
+ const offset = index - atIndex;
197
+ if (offset < 0 || offset >= slice.count)
198
+ return measure;
199
+ const from = source?.[offset];
200
+ if (from)
201
+ return adoptMeasure(from, track.id);
202
+ const shape = shapeAt(slice, offset);
203
+ return shape ? blankLike(shape, track.id) : clearedMeasure(measure, track.id);
204
+ });
205
+ return { ...track, measures };
206
+ });
207
+ return rebuildMeasureTicks(withTracks(score, tracks));
208
+ });
209
+ }
210
+ /**
211
+ * A copied track, re-identified and fitted to the score it is joining.
212
+ *
213
+ * The bars are matched to the destination's grid by position: the score decides
214
+ * how many bars there are and how long each is, and a pasted part fills what it
215
+ * can. A part longer than the score is truncated rather than lengthening it,
216
+ * because adding bars is `insertMeasuresCommand`'s job and doing it here would
217
+ * make "paste a track" silently change every other part's length.
218
+ */
219
+ function adoptTrack(source, grid) {
220
+ const trackId = createId();
221
+ const measures = (grid?.measures ?? source.measures).map((at, index) => {
222
+ const from = source.measures[index];
223
+ // Shaped by the *destination's* grid here, unlike a measure paste: a part
224
+ // joining a score adopts that score's bars, where a pasted bar brings its
225
+ // own and every part receives it.
226
+ return from
227
+ ? { ...adoptMeasure(from, trackId), startTick: at.startTick, index: at.index,
228
+ durationTicks: at.durationTicks, timeSignature: at.timeSignature,
229
+ keySignature: at.keySignature }
230
+ : blankLike(at, trackId);
231
+ });
232
+ return { ...source, id: trackId, measures };
233
+ }
234
+ /** Adds the track at `atIndex`, fitted to the score's own measure grid. */
235
+ export function insertTrackCommand(source, atIndex, label) {
236
+ return transformCommand(label, (score) => {
237
+ const tracks = [...score.tracks];
238
+ tracks.splice(Math.max(0, Math.min(atIndex, tracks.length)), 0, adoptTrack(source, score.tracks[0]));
239
+ return rebuildMeasureTicks(withTracks(score, tracks));
240
+ });
241
+ }
242
+ /** Replaces one track with a copied one, in place, keeping the score's grid. */
243
+ export function replaceTrackCommand(trackId, source, label) {
244
+ return transformCommand(label, (score) => rebuildMeasureTicks(withTracks(score, score.tracks.map((track) => track.id === trackId ? adoptTrack(source, score.tracks[0]) : track))));
245
+ }
246
+ //# sourceMappingURL=clipboard-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard-commands.js","sourceRoot":"","sources":["../../../src/domain/commands/clipboard-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The order a closed vocabulary is *offered* in, which is not the order it is
3
+ * declared in.
4
+ *
5
+ * A vocabulary is declared in whatever order it grew — the styles run waltz,
6
+ * jazz, pop, cinematic, ambient, battle — and that is the right order for the
7
+ * source and no order for a reader hunting through thirty-three of them.
8
+ *
9
+ * Sorted on the **label**, not the value: the value is `electroSwing` and the
10
+ * reader sees "Electro Swing", so sorting the keys puts entries wherever their
11
+ * camel-case identifier happens to fall. And sorted with `localeCompare` under
12
+ * the language actually on screen, because the label a Chinese reader is
13
+ * scanning is Chinese — collating those by the English they were translated
14
+ * from produces an order with no visible logic at all.
15
+ *
16
+ * Here rather than in either app because both apps draw these pickers, and an
17
+ * ordering rule written twice is one that eventually disagrees with itself.
18
+ */
19
+ export declare function sortOptionsByLabel<T extends string>(values: readonly T[], labelOf: (value: T) => string, locale?: string): T[];
20
+ //# sourceMappingURL=option-order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option-order.d.ts","sourceRoot":"","sources":["../../../src/domain/generation/option-order.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,CAAC,EAAE,CAML"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The order a closed vocabulary is *offered* in, which is not the order it is
3
+ * declared in.
4
+ *
5
+ * A vocabulary is declared in whatever order it grew — the styles run waltz,
6
+ * jazz, pop, cinematic, ambient, battle — and that is the right order for the
7
+ * source and no order for a reader hunting through thirty-three of them.
8
+ *
9
+ * Sorted on the **label**, not the value: the value is `electroSwing` and the
10
+ * reader sees "Electro Swing", so sorting the keys puts entries wherever their
11
+ * camel-case identifier happens to fall. And sorted with `localeCompare` under
12
+ * the language actually on screen, because the label a Chinese reader is
13
+ * scanning is Chinese — collating those by the English they were translated
14
+ * from produces an order with no visible logic at all.
15
+ *
16
+ * Here rather than in either app because both apps draw these pickers, and an
17
+ * ordering rule written twice is one that eventually disagrees with itself.
18
+ */
19
+ export function sortOptionsByLabel(values, labelOf, locale) {
20
+ // A copy: the vocabularies are module-level constants shared by every caller,
21
+ // and `sort` is in place.
22
+ return [...values].sort((a, b) => labelOf(a).localeCompare(labelOf(b), locale));
23
+ }
24
+ //# sourceMappingURL=option-order.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option-order.js","sourceRoot":"","sources":["../../../src/domain/generation/option-order.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAoB,EACpB,OAA6B,EAC7B,MAAe;IAEf,8EAA8E;IAC9E,0BAA0B;IAC1B,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC/B,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAC7C,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"replacement-region.d.ts","sourceRoot":"","sources":["../../../src/domain/generation/replacement-region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAC;IACxB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAoCF;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,cAAc,EACzB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,KAAK,EAAE,YAAY,GAClB,iBAAiB,GAAG,IAAI,CAkE1B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,KAAK,CAYzE"}
1
+ {"version":3,"file":"replacement-region.d.ts","sourceRoot":"","sources":["../../../src/domain/generation/replacement-region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAExE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAE1D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,UAAU,CAAC;IAClB,2EAA2E;IAC3E,cAAc,EAAE,OAAO,CAAC;IACxB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAoCF;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,cAAc,EACzB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,KAAK,EAAE,YAAY,GAClB,iBAAiB,GAAG,IAAI,CAkE1B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,KAAK,CAezE"}
@@ -92,6 +92,9 @@ export function emptyScoreForRequest(request) {
92
92
  tracks: request.tracks.map((t) => ({
93
93
  name: t.name,
94
94
  instrumentName: t.instrumentName,
95
+ // `createTrack` defaults this to 0, so leaving it off made every
96
+ // placeholder an all-piano score whatever ensemble was asked for.
97
+ midiProgram: t.midiProgram,
95
98
  clef: t.clef,
96
99
  })),
97
100
  ...(request.timeSignature ? { timeSignature: request.timeSignature } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"replacement-region.js","sourceRoot":"","sources":["../../../src/domain/generation/replacement-region.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replacement-region.js","sourceRoot":"","sources":["../../../src/domain/generation/replacement-region.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { KeySignature } from "../../model/score.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
+ declare const GENERATE_SCORE_STYLE_KEYS: readonly ["waltz", "jazz", "pop", "cinematic", "ambient", "battle", "rock", "punk", "heavyMetal", "blues", "country", "bluegrass", "funk", "soul", "ragtime", "swing", "bossaNova", "samba", "salsa", "tango", "reggae", "hipHop", "trap", "lofi", "house", "techno", "trance", "edm", "electroSwing", "disco", "classical", "baroque", "march"];
9
+ export type GenerateScoreStyle = (typeof GENERATE_SCORE_STYLE_KEYS)[number];
10
+ export declare const GENERATE_SCORE_STYLE_OPTIONS: readonly string[];
11
+ export type GenerateScoreStylePreset = {
12
+ /** What the model is told the style is. */
13
+ prompt: string;
14
+ /** Picker values, in ensemble order. */
15
+ instruments: readonly string[];
16
+ /** Beats per minute, in the middle of the range the genre is played at. */
17
+ tempo: number;
18
+ /** Bars the piece runs for, derived from the preset's tempo and meter. */
19
+ measures: number;
20
+ /** How long this style's pieces run, in seconds. Defaults to a typical song. */
21
+ seconds?: number;
22
+ /** The genre's form in bars, where it has one. */
23
+ formBars?: number;
24
+ /** A key of the app's generate-score time signature options. */
25
+ timeSignature: string;
26
+ /** The mode the genre usually sits in; absent where it is not typical. */
27
+ mode?: KeySignature["mode"];
28
+ };
29
+ /**
30
+ * The styles, each with the bars its own tempo and meter need for a song.
31
+ */
32
+ export declare const GENERATE_SCORE_STYLE_PRESETS: Readonly<Record<string, GenerateScoreStylePreset>>;
33
+ export {};
34
+ //# sourceMappingURL=style-presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-presets.d.ts","sourceRoot":"","sources":["../../../src/domain/generation/style-presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMzD;;;;;GAKG;AACH,QAAA,MAAM,yBAAyB,kVAkCrB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,4BAA4B,EAAE,SAAS,MAAM,EAC/B,CAAC;AAE5B,MAAM,MAAM,wBAAwB,GAAG;IACrC,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;CAC7B,CAAC;AA6PF;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CACjD,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAczC,CAAC"}