@sudobility/music_types 0.11.30 → 0.11.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/domain/commands/edit-commands.d.ts +3 -3
- package/dist/domain/commands/edit-commands.d.ts.map +1 -1
- package/dist/domain/commands/edit-commands.js +25 -25
- package/dist/domain/commands/edit-commands.js.map +1 -1
- package/dist/domain/commands/history.d.ts +32 -0
- package/dist/domain/commands/history.d.ts.map +1 -0
- package/dist/domain/commands/history.js +63 -0
- package/dist/domain/commands/history.js.map +1 -0
- package/dist/domain/commands/note-commands.d.ts +9 -12
- package/dist/domain/commands/note-commands.d.ts.map +1 -1
- package/dist/domain/commands/note-commands.js +42 -72
- package/dist/domain/commands/note-commands.js.map +1 -1
- package/dist/domain/commands/note-marks.d.ts +171 -0
- package/dist/domain/commands/note-marks.d.ts.map +1 -0
- package/dist/domain/commands/note-marks.js +427 -0
- package/dist/domain/commands/note-marks.js.map +1 -0
- package/dist/domain/commands/reflow.d.ts +1 -1
- package/dist/domain/commands/reflow.js +17 -17
- package/dist/domain/commands/reflow.js.map +1 -1
- package/dist/domain/commands/region-commands.d.ts +4 -4
- package/dist/domain/commands/region-commands.d.ts.map +1 -1
- package/dist/domain/commands/region-commands.js +7 -7
- package/dist/domain/commands/region-commands.js.map +1 -1
- package/dist/domain/commands/relocate-commands.d.ts +3 -3
- package/dist/domain/commands/relocate-commands.js +15 -15
- package/dist/domain/commands/relocate-commands.js.map +1 -1
- package/dist/domain/commands/ripple-commands.d.ts +2 -2
- package/dist/domain/commands/ripple-commands.js +13 -13
- package/dist/domain/commands/ripple-commands.js.map +1 -1
- package/dist/domain/commands/snapshot.d.ts +3 -3
- package/dist/domain/commands/snapshot.js +5 -5
- package/dist/domain/commands/snapshot.js.map +1 -1
- package/dist/domain/commands/structure-commands.d.ts +86 -5
- package/dist/domain/commands/structure-commands.d.ts.map +1 -1
- package/dist/domain/commands/structure-commands.js +272 -36
- package/dist/domain/commands/structure-commands.js.map +1 -1
- package/dist/domain/commands/track-commands.d.ts +2 -2
- package/dist/domain/commands/track-commands.js +7 -7
- package/dist/domain/commands/track-commands.js.map +1 -1
- package/dist/domain/commands/types.d.ts +2 -2
- package/dist/domain/generation/replacement-region.d.ts +32 -0
- package/dist/domain/generation/replacement-region.d.ts.map +1 -0
- package/dist/domain/generation/replacement-region.js +79 -0
- package/dist/domain/generation/replacement-region.js.map +1 -0
- package/dist/domain/instruments/gm-icon.d.ts +12 -0
- package/dist/domain/instruments/gm-icon.d.ts.map +1 -0
- package/dist/domain/instruments/gm-icon.js +327 -0
- package/dist/domain/instruments/gm-icon.js.map +1 -0
- package/dist/domain/instruments/gm-kit.js +9 -9
- package/dist/domain/instruments/gm-kit.js.map +1 -1
- package/dist/domain/instruments/gm-percussion.js +48 -48
- package/dist/domain/instruments/gm-percussion.js.map +1 -1
- package/dist/domain/instruments/gm-polyphony.js +6 -6
- package/dist/domain/instruments/gm-range.js +6 -6
- package/dist/domain/instruments/gm-transposition.js +1 -1
- package/dist/domain/instruments/gm.d.ts +1 -1
- package/dist/domain/instruments/gm.js +161 -161
- package/dist/domain/instruments/gm.js.map +1 -1
- package/dist/domain/instruments/icon-art.d.ts +75 -0
- package/dist/domain/instruments/icon-art.d.ts.map +1 -0
- package/dist/domain/instruments/icon-art.js +93 -0
- package/dist/domain/instruments/icon-art.js.map +1 -0
- package/dist/domain/instruments/instrument-fit.d.ts +31 -0
- package/dist/domain/instruments/instrument-fit.d.ts.map +1 -0
- package/dist/domain/instruments/instrument-fit.js +117 -0
- package/dist/domain/instruments/instrument-fit.js.map +1 -0
- package/dist/domain/instruments/instrument-options.d.ts +62 -0
- package/dist/domain/instruments/instrument-options.d.ts.map +1 -0
- package/dist/domain/instruments/instrument-options.js +69 -0
- package/dist/domain/instruments/instrument-options.js.map +1 -0
- package/dist/domain/instruments/track-instrument.d.ts +80 -0
- package/dist/domain/instruments/track-instrument.d.ts.map +1 -0
- package/dist/domain/instruments/track-instrument.js +102 -0
- package/dist/domain/instruments/track-instrument.js.map +1 -0
- package/dist/domain/notation/chord-symbol.d.ts +26 -0
- package/dist/domain/notation/chord-symbol.d.ts.map +1 -0
- package/dist/domain/notation/chord-symbol.js +32 -0
- package/dist/domain/notation/chord-symbol.js.map +1 -0
- package/dist/domain/notation/lyric-syllables.d.ts +15 -0
- package/dist/domain/notation/lyric-syllables.d.ts.map +1 -0
- package/dist/domain/notation/lyric-syllables.js +15 -0
- package/dist/domain/notation/lyric-syllables.js.map +1 -0
- package/dist/domain/notation/music-vocabulary.d.ts +59 -0
- package/dist/domain/notation/music-vocabulary.d.ts.map +1 -0
- package/dist/domain/notation/music-vocabulary.js +164 -0
- package/dist/domain/notation/music-vocabulary.js.map +1 -0
- package/dist/domain/pitch/pitch.d.ts +1 -1
- package/dist/domain/pitch/pitch.js +29 -29
- package/dist/domain/pitch/transpose.d.ts +1 -1
- package/dist/domain/pitch/transpose.js +2 -2
- package/dist/domain/quantization/quantize.d.ts +2 -2
- package/dist/domain/quantization/quantize.js +9 -9
- package/dist/domain/quantization/quantize.js.map +1 -1
- package/dist/domain/score/articulation.d.ts +56 -0
- package/dist/domain/score/articulation.d.ts.map +1 -0
- package/dist/domain/score/articulation.js +56 -0
- package/dist/domain/score/articulation.js.map +1 -0
- package/dist/domain/score/bar-numbers.d.ts +38 -0
- package/dist/domain/score/bar-numbers.d.ts.map +1 -0
- package/dist/domain/score/bar-numbers.js +49 -0
- package/dist/domain/score/bar-numbers.js.map +1 -0
- package/dist/domain/score/collapse-rests.d.ts +23 -0
- package/dist/domain/score/collapse-rests.d.ts.map +1 -0
- package/dist/domain/score/collapse-rests.js +78 -0
- package/dist/domain/score/collapse-rests.js.map +1 -0
- package/dist/domain/score/cue-notes.d.ts +24 -0
- package/dist/domain/score/cue-notes.d.ts.map +1 -0
- package/dist/domain/score/cue-notes.js +105 -0
- package/dist/domain/score/cue-notes.js.map +1 -0
- package/dist/domain/score/dynamics.d.ts +62 -0
- package/dist/domain/score/dynamics.d.ts.map +1 -0
- package/dist/domain/score/dynamics.js +142 -0
- package/dist/domain/score/dynamics.js.map +1 -0
- package/dist/domain/score/effective-clef.d.ts +42 -0
- package/dist/domain/score/effective-clef.d.ts.map +1 -0
- package/dist/domain/score/effective-clef.js +39 -0
- package/dist/domain/score/effective-clef.js.map +1 -0
- package/dist/domain/score/extract-part.d.ts +10 -0
- package/dist/domain/score/extract-part.d.ts.map +1 -0
- package/dist/domain/score/extract-part.js +44 -0
- package/dist/domain/score/extract-part.js.map +1 -0
- package/dist/domain/score/factory.d.ts +1 -1
- package/dist/domain/score/factory.js +12 -12
- package/dist/domain/score/factory.js.map +1 -1
- package/dist/domain/score/fermata-tempo.d.ts +40 -0
- package/dist/domain/score/fermata-tempo.d.ts.map +1 -0
- package/dist/domain/score/fermata-tempo.js +95 -0
- package/dist/domain/score/fermata-tempo.js.map +1 -0
- package/dist/domain/score/flatten.d.ts +32 -0
- package/dist/domain/score/flatten.d.ts.map +1 -0
- package/dist/domain/score/flatten.js +132 -0
- package/dist/domain/score/flatten.js.map +1 -0
- package/dist/domain/score/fragment.d.ts +4 -8
- package/dist/domain/score/fragment.d.ts.map +1 -1
- package/dist/domain/score/fragment.js +8 -8
- package/dist/domain/score/fragment.js.map +1 -1
- package/dist/domain/score/ids.d.ts +1 -1
- package/dist/domain/score/ids.js +6 -6
- package/dist/domain/score/ottava.d.ts +41 -0
- package/dist/domain/score/ottava.d.ts.map +1 -0
- package/dist/domain/score/ottava.js +98 -0
- package/dist/domain/score/ottava.js.map +1 -0
- package/dist/domain/score/performance-timeline.d.ts +42 -0
- package/dist/domain/score/performance-timeline.d.ts.map +1 -0
- package/dist/domain/score/performance-timeline.js +78 -0
- package/dist/domain/score/performance-timeline.js.map +1 -0
- package/dist/domain/score/queries.d.ts +2 -2
- package/dist/domain/score/queries.js +7 -7
- package/dist/domain/score/queries.js.map +1 -1
- package/dist/domain/score/rehearsal-marks.d.ts +30 -0
- package/dist/domain/score/rehearsal-marks.d.ts.map +1 -0
- package/dist/domain/score/rehearsal-marks.js +126 -0
- package/dist/domain/score/rehearsal-marks.js.map +1 -0
- package/dist/domain/score/repeat-order.d.ts +21 -0
- package/dist/domain/score/repeat-order.d.ts.map +1 -0
- package/dist/domain/score/repeat-order.js +123 -0
- package/dist/domain/score/repeat-order.js.map +1 -0
- package/dist/domain/score/snapshot-tree.d.ts +23 -0
- package/dist/domain/score/snapshot-tree.d.ts.map +1 -0
- package/dist/domain/score/snapshot-tree.js +45 -0
- package/dist/domain/score/snapshot-tree.js.map +1 -0
- package/dist/domain/score/ties.d.ts +1 -1
- package/dist/domain/score/ties.js +7 -7
- package/dist/domain/score/ties.js.map +1 -1
- package/dist/domain/score/written-pitch.d.ts +33 -0
- package/dist/domain/score/written-pitch.d.ts.map +1 -0
- package/dist/domain/score/written-pitch.js +110 -0
- package/dist/domain/score/written-pitch.js.map +1 -0
- package/dist/domain/selection/range-select.d.ts +13 -0
- package/dist/domain/selection/range-select.d.ts.map +1 -0
- package/dist/domain/selection/range-select.js +40 -0
- package/dist/domain/selection/range-select.js.map +1 -0
- package/dist/domain/selection/selection-editing.d.ts +30 -0
- package/dist/domain/selection/selection-editing.d.ts.map +1 -0
- package/dist/domain/selection/selection-editing.js +31 -0
- package/dist/domain/selection/selection-editing.js.map +1 -0
- package/dist/domain/selection/selection.d.ts +2 -2
- package/dist/domain/selection/selection.js +7 -7
- package/dist/domain/selection/selection.js.map +1 -1
- package/dist/domain/selection/types.d.ts +2 -2
- package/dist/domain/selection/types.d.ts.map +1 -1
- package/dist/domain/time/duration-modifiers.d.ts +40 -0
- package/dist/domain/time/duration-modifiers.d.ts.map +1 -0
- package/dist/domain/time/duration-modifiers.js +50 -0
- package/dist/domain/time/duration-modifiers.js.map +1 -0
- package/dist/domain/time/duration-selection.d.ts +23 -0
- package/dist/domain/time/duration-selection.d.ts.map +1 -0
- package/dist/domain/time/duration-selection.js +50 -0
- package/dist/domain/time/duration-selection.js.map +1 -0
- package/dist/domain/time/durations.js +6 -6
- package/dist/domain/time/durations.js.map +1 -1
- package/dist/domain/time/fraction.d.ts +1 -1
- package/dist/domain/time/fraction.js +1 -1
- package/dist/domain/time/tap-to-note.d.ts +21 -0
- package/dist/domain/time/tap-to-note.d.ts.map +1 -0
- package/dist/domain/time/tap-to-note.js +43 -0
- package/dist/domain/time/tap-to-note.js.map +1 -0
- package/dist/domain/time/tempo-map.d.ts +1 -1
- package/dist/domain/time/ticks.d.ts +1 -1
- package/dist/domain/time/ticks.d.ts.map +1 -1
- package/dist/domain/time/ticks.js +14 -14
- package/dist/domain/time/ticks.js.map +1 -1
- package/dist/domain/time/tuplets.d.ts +42 -0
- package/dist/domain/time/tuplets.d.ts.map +1 -0
- package/dist/domain/time/tuplets.js +53 -0
- package/dist/domain/time/tuplets.js.map +1 -0
- package/dist/domain/validation/issues.d.ts +1 -1
- package/dist/domain/validation/issues.js +20 -20
- package/dist/domain/validation/validator.d.ts +2 -2
- package/dist/domain/validation/validator.d.ts.map +1 -1
- package/dist/domain/validation/validator.js +31 -31
- package/dist/domain/validation/validator.js.map +1 -1
- package/dist/domain/voicing/allocate.d.ts +2 -2
- package/dist/domain/voicing/allocate.js +6 -6
- package/dist/domain/voicing/allocate.js.map +1 -1
- package/dist/index.d.ts +72 -5535
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +79 -462
- package/dist/index.js.map +1 -1
- package/dist/model/api.d.ts +1696 -0
- package/dist/model/api.d.ts.map +1 -0
- package/dist/model/api.js +125 -0
- package/dist/model/api.js.map +1 -0
- package/dist/model/generation.d.ts +2178 -0
- package/dist/model/generation.d.ts.map +1 -0
- package/dist/model/generation.js +142 -0
- package/dist/model/generation.js.map +1 -0
- package/dist/model/schemas.d.ts +1200 -0
- package/dist/model/schemas.d.ts.map +1 -0
- package/dist/model/schemas.js +200 -0
- package/dist/model/schemas.js.map +1 -0
- package/dist/model/score.d.ts +462 -0
- package/dist/model/score.d.ts.map +1 -0
- package/dist/model/score.js +34 -0
- package/dist/model/score.js.map +1 -0
- package/dist/platform/audio.d.ts.map +1 -1
- package/dist/platform/file.d.ts.map +1 -1
- package/dist/platform/index.d.ts +7 -7
- package/dist/platform/index.js +7 -7
- package/dist/platform/midi-input.d.ts +2 -2
- package/dist/platform/midi.d.ts.map +1 -1
- package/dist/platform/mod.d.ts +2 -2
- package/dist/platform/playback.d.ts +7 -7
- package/dist/platform/xml.js +1 -1
- package/dist/services/regeneration/controller.d.ts +6 -6
- package/dist/services/regeneration/controller.js +12 -12
- package/dist/services/regeneration/controller.js.map +1 -1
- package/dist/test/fixtures.d.ts +1 -1
- package/dist/test/fixtures.js +103 -103
- package/dist/test/fixtures.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The drawing vocabulary the instrument icons are authored in: a tiny,
|
|
3
|
+
* renderer-neutral shape list plus a parser for the path subset it allows.
|
|
4
|
+
*
|
|
5
|
+
* Two consumers draw the same art through different APIs — the canvas track
|
|
6
|
+
* gutter (`stroke-icon.ts`) and the app's `<svg>` component — so the art itself
|
|
7
|
+
* cannot be expressed in either one's terms. SVG path data is the natural
|
|
8
|
+
* authoring format, but handing it to canvas would mean `Path2D`, which jsdom
|
|
9
|
+
* does not implement; the gutter's drawing would then be untestable in the unit
|
|
10
|
+
* suite. Parsing the subset ourselves keeps one authored source and keeps both
|
|
11
|
+
* renderers testable.
|
|
12
|
+
*
|
|
13
|
+
* The subset is deliberately small: absolute `M`/`L`/`C`/`Q`/`Z` and explicit
|
|
14
|
+
* circles. No arcs (their SVG parameterisation is endpoint-based and converting
|
|
15
|
+
* it to canvas's centre-based `arc` is exactly the fiddly, bug-prone code this
|
|
16
|
+
* design avoids) and no relative commands (an icon is authored once and read
|
|
17
|
+
* many times; absolute coordinates stay readable). Anything else throws, so a
|
|
18
|
+
* malformed icon fails in the test suite rather than drawing silently wrong.
|
|
19
|
+
*/
|
|
20
|
+
/** Icons are authored on a 24x24 grid, like most line-art sets. */
|
|
21
|
+
export declare const ICON_VIEWBOX = 24;
|
|
22
|
+
/**
|
|
23
|
+
* Stroke width in viewbox units. Scales with the icon, so the weight stays
|
|
24
|
+
* proportional at any size rather than going hairline when drawn small.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ICON_STROKE_WIDTH = 1.6;
|
|
27
|
+
export type IconShape = {
|
|
28
|
+
readonly kind: "path";
|
|
29
|
+
readonly d: string;
|
|
30
|
+
} | {
|
|
31
|
+
readonly kind: "circle";
|
|
32
|
+
readonly cx: number;
|
|
33
|
+
readonly cy: number;
|
|
34
|
+
readonly r: number;
|
|
35
|
+
};
|
|
36
|
+
/** One instrument's line art. `name` is a stable id — useful in tests and debugging, never shown. */
|
|
37
|
+
export type InstrumentIconArt = {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly shapes: readonly IconShape[];
|
|
40
|
+
};
|
|
41
|
+
export type PathSegment = {
|
|
42
|
+
kind: "move";
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "line";
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
} | {
|
|
50
|
+
kind: "cubic";
|
|
51
|
+
x1: number;
|
|
52
|
+
y1: number;
|
|
53
|
+
x2: number;
|
|
54
|
+
y2: number;
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
} | {
|
|
58
|
+
kind: "quad";
|
|
59
|
+
x1: number;
|
|
60
|
+
y1: number;
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "close";
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Parses an authored path into segments any renderer can replay.
|
|
68
|
+
*
|
|
69
|
+
* Implements SVG's implicit-repetition rule (a command's operands may repeat
|
|
70
|
+
* without restating the letter) and its companion rule that the pairs after an
|
|
71
|
+
* `M` are line-tos, because both are how path data is normally written and an
|
|
72
|
+
* author would reasonably expect them to work.
|
|
73
|
+
*/
|
|
74
|
+
export declare function parseIconPath(d: string): PathSegment[];
|
|
75
|
+
//# sourceMappingURL=icon-art.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon-art.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/icon-art.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,mEAAmE;AACnE,eAAO,MAAM,YAAY,KAAK,CAAC;AAE/B;;;GAGG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN,qGAAqG;AACrG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IACE,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AA4BtB;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAwCtD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The drawing vocabulary the instrument icons are authored in: a tiny,
|
|
3
|
+
* renderer-neutral shape list plus a parser for the path subset it allows.
|
|
4
|
+
*
|
|
5
|
+
* Two consumers draw the same art through different APIs — the canvas track
|
|
6
|
+
* gutter (`stroke-icon.ts`) and the app's `<svg>` component — so the art itself
|
|
7
|
+
* cannot be expressed in either one's terms. SVG path data is the natural
|
|
8
|
+
* authoring format, but handing it to canvas would mean `Path2D`, which jsdom
|
|
9
|
+
* does not implement; the gutter's drawing would then be untestable in the unit
|
|
10
|
+
* suite. Parsing the subset ourselves keeps one authored source and keeps both
|
|
11
|
+
* renderers testable.
|
|
12
|
+
*
|
|
13
|
+
* The subset is deliberately small: absolute `M`/`L`/`C`/`Q`/`Z` and explicit
|
|
14
|
+
* circles. No arcs (their SVG parameterisation is endpoint-based and converting
|
|
15
|
+
* it to canvas's centre-based `arc` is exactly the fiddly, bug-prone code this
|
|
16
|
+
* design avoids) and no relative commands (an icon is authored once and read
|
|
17
|
+
* many times; absolute coordinates stay readable). Anything else throws, so a
|
|
18
|
+
* malformed icon fails in the test suite rather than drawing silently wrong.
|
|
19
|
+
*/
|
|
20
|
+
/** Icons are authored on a 24x24 grid, like most line-art sets. */
|
|
21
|
+
export const ICON_VIEWBOX = 24;
|
|
22
|
+
/**
|
|
23
|
+
* Stroke width in viewbox units. Scales with the icon, so the weight stays
|
|
24
|
+
* proportional at any size rather than going hairline when drawn small.
|
|
25
|
+
*/
|
|
26
|
+
export const ICON_STROKE_WIDTH = 1.6;
|
|
27
|
+
const COMMAND_ARITY = { M: 2, L: 2, C: 6, Q: 4, Z: 0 };
|
|
28
|
+
/** Command letters and numbers; anything else in the string is ignored as separator. */
|
|
29
|
+
const TOKEN = /[A-Za-z]|-?\d*\.?\d+/g;
|
|
30
|
+
function segmentFor(command, n) {
|
|
31
|
+
switch (command) {
|
|
32
|
+
case "M":
|
|
33
|
+
return { kind: "move", x: n[0], y: n[1] };
|
|
34
|
+
case "L":
|
|
35
|
+
return { kind: "line", x: n[0], y: n[1] };
|
|
36
|
+
case "C":
|
|
37
|
+
return {
|
|
38
|
+
kind: "cubic",
|
|
39
|
+
x1: n[0],
|
|
40
|
+
y1: n[1],
|
|
41
|
+
x2: n[2],
|
|
42
|
+
y2: n[3],
|
|
43
|
+
x: n[4],
|
|
44
|
+
y: n[5],
|
|
45
|
+
};
|
|
46
|
+
default:
|
|
47
|
+
return { kind: "quad", x1: n[0], y1: n[1], x: n[2], y: n[3] };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parses an authored path into segments any renderer can replay.
|
|
52
|
+
*
|
|
53
|
+
* Implements SVG's implicit-repetition rule (a command's operands may repeat
|
|
54
|
+
* without restating the letter) and its companion rule that the pairs after an
|
|
55
|
+
* `M` are line-tos, because both are how path data is normally written and an
|
|
56
|
+
* author would reasonably expect them to work.
|
|
57
|
+
*/
|
|
58
|
+
export function parseIconPath(d) {
|
|
59
|
+
const tokens = d.match(TOKEN) ?? [];
|
|
60
|
+
const segments = [];
|
|
61
|
+
let command = null;
|
|
62
|
+
let i = 0;
|
|
63
|
+
while (i < tokens.length) {
|
|
64
|
+
if (/[A-Za-z]/.test(tokens[i])) {
|
|
65
|
+
command = tokens[i];
|
|
66
|
+
i += 1;
|
|
67
|
+
if (!(command in COMMAND_ARITY)) {
|
|
68
|
+
throw new Error(`Unsupported icon path command "${command}" in "${d}"`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (command == null)
|
|
72
|
+
throw new Error(`Icon path must start with a command: "${d}"`);
|
|
73
|
+
const arity = COMMAND_ARITY[command];
|
|
74
|
+
if (arity === 0) {
|
|
75
|
+
segments.push({ kind: "close" });
|
|
76
|
+
// Nothing may follow a Z but another command, so drop back to
|
|
77
|
+
// "expecting a letter" rather than repeating the close forever.
|
|
78
|
+
command = null;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const operands = tokens.slice(i, i + arity).map(Number);
|
|
82
|
+
if (operands.length < arity || operands.some(Number.isNaN)) {
|
|
83
|
+
throw new Error(`Icon path command "${command}" wants ${arity} numbers in "${d}"`);
|
|
84
|
+
}
|
|
85
|
+
i += arity;
|
|
86
|
+
segments.push(segmentFor(command, operands));
|
|
87
|
+
// SVG: the coordinate pairs following a moveto are implicit linetos.
|
|
88
|
+
if (command === "M")
|
|
89
|
+
command = "L";
|
|
90
|
+
}
|
|
91
|
+
return segments;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=icon-art.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon-art.js","sourceRoot":"","sources":["../../../src/domain/instruments/icon-art.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Score, UUID } from "../../index.js";
|
|
2
|
+
import type { ScoreCommand } from "../commands/types.js";
|
|
3
|
+
import { type MidiRange } from "./gm-range.js";
|
|
4
|
+
/** The instrument fields that move together — the name is stored, so it must not drift from the program. */
|
|
5
|
+
export type InstrumentPatch = {
|
|
6
|
+
midiProgram: number;
|
|
7
|
+
instrumentName: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The semitone shift that brings every pitch in `midis` inside `range`, or
|
|
11
|
+
* `null` if the span is simply too wide to fit.
|
|
12
|
+
*
|
|
13
|
+
* `0` when it already fits, so a caller can tell "no move needed" from
|
|
14
|
+
* "cannot be done" — the two are very different answers.
|
|
15
|
+
*/
|
|
16
|
+
export declare function shiftToFitRange(midis: number[], range: MidiRange): number | null;
|
|
17
|
+
/**
|
|
18
|
+
* The shift `trackId`'s notes need to fit `midiProgram`, or `null` if they
|
|
19
|
+
* cannot. Ask this *before* dispatching, so a change that would be refused can
|
|
20
|
+
* be reported rather than silently doing nothing.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fitShiftForInstrument(score: Score, trackId: UUID, midiProgram: number): number | null;
|
|
23
|
+
/**
|
|
24
|
+
* Sets the instrument and moves the existing notes to suit it, as one command
|
|
25
|
+
* — so a single undo puts both back.
|
|
26
|
+
*
|
|
27
|
+
* A part that cannot be fitted leaves the score untouched; pair this with
|
|
28
|
+
* `fitShiftForInstrument` if you need to tell the user why nothing happened.
|
|
29
|
+
*/
|
|
30
|
+
export declare function changeInstrumentCommand(trackId: UUID, patch: InstrumentPatch, label: string): ScoreCommand;
|
|
31
|
+
//# sourceMappingURL=instrument-fit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument-fit.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/instrument-fit.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,KAAK,EAAS,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAMzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAElE,4GAA4G;AAC5G,MAAM,MAAM,eAAe,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAO9E;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,SAAS,GACf,MAAM,GAAG,IAAI,CAwBf;AAcD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,IAAI,EACb,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,IAAI,EACb,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,MAAM,GACZ,YAAY,CAmCd"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moving a track's music into a new instrument's compass.
|
|
3
|
+
*
|
|
4
|
+
* Changing the instrument on a track that already has notes is not just a
|
|
5
|
+
* relabelling: a bass line handed to a piccolo sits entirely below what a
|
|
6
|
+
* piccolo can play, and the result is a part that renders but cannot sound.
|
|
7
|
+
* So the notes come with it — shifted by whole **octaves** where that is
|
|
8
|
+
* enough, because an octave keeps the pitch class and a bassline still reads
|
|
9
|
+
* as that bassline. Only when no octave shift fits does it fall back to the
|
|
10
|
+
* smallest chromatic shift that does.
|
|
11
|
+
*
|
|
12
|
+
* A part wider than the instrument's own compass cannot be fitted at all, and
|
|
13
|
+
* that answer is returned rather than approximated — the caller decides what
|
|
14
|
+
* to say about it. Nothing here knows any user-facing words.
|
|
15
|
+
*/
|
|
16
|
+
import { isNoteEvent } from "../../index.js";
|
|
17
|
+
import { transformCommand } from "../commands/snapshot.js";
|
|
18
|
+
import { withTracks } from "../commands/reflow.js";
|
|
19
|
+
import { findTrack } from "../score/queries.js";
|
|
20
|
+
import { pitchToMidi } from "../pitch/pitch.js";
|
|
21
|
+
import { transposePitch } from "../pitch/transpose.js";
|
|
22
|
+
import { gmInstrumentRange } from "./gm-range.js";
|
|
23
|
+
function closestToZero(min, max) {
|
|
24
|
+
if (min <= 0 && max >= 0)
|
|
25
|
+
return 0;
|
|
26
|
+
return min > 0 ? min : max;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The semitone shift that brings every pitch in `midis` inside `range`, or
|
|
30
|
+
* `null` if the span is simply too wide to fit.
|
|
31
|
+
*
|
|
32
|
+
* `0` when it already fits, so a caller can tell "no move needed" from
|
|
33
|
+
* "cannot be done" — the two are very different answers.
|
|
34
|
+
*/
|
|
35
|
+
export function shiftToFitRange(midis, range) {
|
|
36
|
+
if (midis.length === 0)
|
|
37
|
+
return 0;
|
|
38
|
+
let min = Number.POSITIVE_INFINITY;
|
|
39
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
40
|
+
for (const midi of midis) {
|
|
41
|
+
min = Math.min(min, midi);
|
|
42
|
+
max = Math.max(max, midi);
|
|
43
|
+
}
|
|
44
|
+
if (min >= range.min && max <= range.max)
|
|
45
|
+
return 0;
|
|
46
|
+
if (max - min > range.max - range.min)
|
|
47
|
+
return null;
|
|
48
|
+
// Octaves first, and the one closest to no move at all: transposing by an
|
|
49
|
+
// octave preserves the pitch class, so the part still reads the same.
|
|
50
|
+
const minOctaves = Math.ceil((range.min - min) / 12);
|
|
51
|
+
const maxOctaves = Math.floor((range.max - max) / 12);
|
|
52
|
+
if (minOctaves <= maxOctaves)
|
|
53
|
+
return closestToZero(minOctaves, maxOctaves) * 12;
|
|
54
|
+
const minSemitones = range.min - min;
|
|
55
|
+
const maxSemitones = range.max - max;
|
|
56
|
+
return minSemitones <= maxSemitones
|
|
57
|
+
? closestToZero(minSemitones, maxSemitones)
|
|
58
|
+
: null;
|
|
59
|
+
}
|
|
60
|
+
function noteMidis(track) {
|
|
61
|
+
const midis = [];
|
|
62
|
+
for (const measure of track.measures) {
|
|
63
|
+
for (const voice of measure.voices) {
|
|
64
|
+
for (const event of voice.events) {
|
|
65
|
+
if (isNoteEvent(event))
|
|
66
|
+
midis.push(pitchToMidi(event.pitch));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return midis;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The shift `trackId`'s notes need to fit `midiProgram`, or `null` if they
|
|
74
|
+
* cannot. Ask this *before* dispatching, so a change that would be refused can
|
|
75
|
+
* be reported rather than silently doing nothing.
|
|
76
|
+
*/
|
|
77
|
+
export function fitShiftForInstrument(score, trackId, midiProgram) {
|
|
78
|
+
const track = findTrack(score, trackId);
|
|
79
|
+
return track
|
|
80
|
+
? shiftToFitRange(noteMidis(track), gmInstrumentRange(midiProgram))
|
|
81
|
+
: null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sets the instrument and moves the existing notes to suit it, as one command
|
|
85
|
+
* — so a single undo puts both back.
|
|
86
|
+
*
|
|
87
|
+
* A part that cannot be fitted leaves the score untouched; pair this with
|
|
88
|
+
* `fitShiftForInstrument` if you need to tell the user why nothing happened.
|
|
89
|
+
*/
|
|
90
|
+
export function changeInstrumentCommand(trackId, patch, label) {
|
|
91
|
+
return transformCommand(label, (score) => {
|
|
92
|
+
const shift = fitShiftForInstrument(score, trackId, patch.midiProgram);
|
|
93
|
+
if (shift === null)
|
|
94
|
+
return score;
|
|
95
|
+
const tracks = score.tracks.map((candidate) => {
|
|
96
|
+
if (candidate.id !== trackId)
|
|
97
|
+
return candidate;
|
|
98
|
+
const measures = shift === 0
|
|
99
|
+
? candidate.measures
|
|
100
|
+
: candidate.measures.map((measure) => ({
|
|
101
|
+
...measure,
|
|
102
|
+
voices: measure.voices.map((voice) => ({
|
|
103
|
+
...voice,
|
|
104
|
+
events: voice.events.map((event) => isNoteEvent(event)
|
|
105
|
+
? {
|
|
106
|
+
...event,
|
|
107
|
+
pitch: transposePitch(event.pitch, shift, measure.keySignature),
|
|
108
|
+
}
|
|
109
|
+
: event),
|
|
110
|
+
})),
|
|
111
|
+
}));
|
|
112
|
+
return { ...candidate, ...patch, measures };
|
|
113
|
+
});
|
|
114
|
+
return withTracks(score, tracks);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=instrument-fit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument-fit.js","sourceRoot":"","sources":["../../../src/domain/instruments/instrument-fit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The General MIDI catalogue, shaped for a picker.
|
|
3
|
+
*
|
|
4
|
+
* Every caller that offers "which instrument?" — a generate dialog, a track
|
|
5
|
+
* property sheet — needs the same three things: the flattened list of melodic
|
|
6
|
+
* programs grouped by family, the eight drum kits, and a way to turn whichever
|
|
7
|
+
* one was chosen back into the fields a `Track` stores. Deriving those at each
|
|
8
|
+
* call site is how the two lists get confused, so they are derived once here.
|
|
9
|
+
*
|
|
10
|
+
* Kits are tagged rather than numbered, because a kit's program means
|
|
11
|
+
* something else entirely from a melodic one: on channel 10, program 8 is the
|
|
12
|
+
* Room Kit, not Celesta. That is what `KIT_PREFIX` is for, and why a bare
|
|
13
|
+
* program number must never be handed to a control offering `KIT_OPTIONS` —
|
|
14
|
+
* it matches nothing and the control renders empty while still selecting
|
|
15
|
+
* correctly, which is a bug that looks like a styling problem.
|
|
16
|
+
*
|
|
17
|
+
* No user-facing copy lives here beyond the GM names themselves, which are
|
|
18
|
+
* fixed identifiers rather than translatable strings — "Acoustic Grand Piano"
|
|
19
|
+
* is the program's name in every locale.
|
|
20
|
+
*/
|
|
21
|
+
import type { Clef } from "../../index.js";
|
|
22
|
+
/** What a caller needs to write an instrument onto a track, or request one. */
|
|
23
|
+
export type InstrumentChoice = {
|
|
24
|
+
midiProgram: number;
|
|
25
|
+
instrumentName: string;
|
|
26
|
+
clef: Clef;
|
|
27
|
+
};
|
|
28
|
+
/** One entry in a picker: the value to round-trip, its label, and its family heading. */
|
|
29
|
+
export type InstrumentOption = {
|
|
30
|
+
value: string;
|
|
31
|
+
label: string;
|
|
32
|
+
group?: string;
|
|
33
|
+
};
|
|
34
|
+
/** The default selection: Piano, which is also the melody-carrying lead. */
|
|
35
|
+
export declare const DEFAULT_INSTRUMENT_VALUE = "0";
|
|
36
|
+
/**
|
|
37
|
+
* The `KIT_OPTIONS` value for a program.
|
|
38
|
+
*
|
|
39
|
+
* Through `gmKitAt`, so a track sitting at an address no kit is at still
|
|
40
|
+
* selects the kit it actually plays rather than showing an empty control.
|
|
41
|
+
*/
|
|
42
|
+
export declare function kitOptionValue(program: number): string;
|
|
43
|
+
/** The eight GM drum kits, for a percussion track. */
|
|
44
|
+
export declare const KIT_OPTIONS: InstrumentOption[];
|
|
45
|
+
/**
|
|
46
|
+
* Every melodic program, grouped by GM family.
|
|
47
|
+
*
|
|
48
|
+
* Built once at module load: the catalogue is 128 fixed entries, so rebuilding
|
|
49
|
+
* it per render — which a track panel once did — was pure waste.
|
|
50
|
+
*/
|
|
51
|
+
export declare const INSTRUMENT_OPTIONS: InstrumentOption[];
|
|
52
|
+
/** The same catalogue as nested groups, for a picker that draws its own headings. */
|
|
53
|
+
export declare const FAMILY_GROUPS: {
|
|
54
|
+
key: import("./gm.js").GmFamily;
|
|
55
|
+
label: string;
|
|
56
|
+
instruments: readonly import("./gm.js").GmInstrument[];
|
|
57
|
+
}[];
|
|
58
|
+
/** Turns a picker value — from either list — back into track fields. */
|
|
59
|
+
export declare function instrumentChoiceFor(value: string): InstrumentChoice;
|
|
60
|
+
/** The label shown for a catalogue value. */
|
|
61
|
+
export declare function instrumentLabelFor(value: string): string;
|
|
62
|
+
//# sourceMappingURL=instrument-options.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { GM_FAMILIES, GM_FAMILY_LABELS, gmInstrument, gmInstrumentsByFamily, } from "./gm.js";
|
|
2
|
+
import { GM_KITS, gmKit, gmKitAt } from "./gm-kit.js";
|
|
3
|
+
const KIT_PREFIX = "kit:";
|
|
4
|
+
/** The default selection: Piano, which is also the melody-carrying lead. */
|
|
5
|
+
export const DEFAULT_INSTRUMENT_VALUE = "0";
|
|
6
|
+
/**
|
|
7
|
+
* The `KIT_OPTIONS` value for a program.
|
|
8
|
+
*
|
|
9
|
+
* Through `gmKitAt`, so a track sitting at an address no kit is at still
|
|
10
|
+
* selects the kit it actually plays rather than showing an empty control.
|
|
11
|
+
*/
|
|
12
|
+
export function kitOptionValue(program) {
|
|
13
|
+
return `${KIT_PREFIX}${gmKitAt(program).program}`;
|
|
14
|
+
}
|
|
15
|
+
/** The eight GM drum kits, for a percussion track. */
|
|
16
|
+
export const KIT_OPTIONS = GM_KITS.map((kit) => ({
|
|
17
|
+
value: `${KIT_PREFIX}${kit.program}`,
|
|
18
|
+
label: kit.name,
|
|
19
|
+
}));
|
|
20
|
+
/**
|
|
21
|
+
* Every melodic program, grouped by GM family.
|
|
22
|
+
*
|
|
23
|
+
* Built once at module load: the catalogue is 128 fixed entries, so rebuilding
|
|
24
|
+
* it per render — which a track panel once did — was pure waste.
|
|
25
|
+
*/
|
|
26
|
+
export const INSTRUMENT_OPTIONS = GM_FAMILIES.flatMap((family) => gmInstrumentsByFamily(family).map((instrument) => ({
|
|
27
|
+
value: String(instrument.program),
|
|
28
|
+
label: instrument.name,
|
|
29
|
+
group: GM_FAMILY_LABELS[family],
|
|
30
|
+
})));
|
|
31
|
+
/** The same catalogue as nested groups, for a picker that draws its own headings. */
|
|
32
|
+
export const FAMILY_GROUPS = GM_FAMILIES.map((family) => ({
|
|
33
|
+
key: family,
|
|
34
|
+
label: GM_FAMILY_LABELS[family],
|
|
35
|
+
instruments: gmInstrumentsByFamily(family),
|
|
36
|
+
}));
|
|
37
|
+
/**
|
|
38
|
+
* The clef a melodic program is written on.
|
|
39
|
+
*
|
|
40
|
+
* Only the Bass family reads better on the bass staff; everything else starts
|
|
41
|
+
* on treble, which can be changed on the track afterwards.
|
|
42
|
+
*/
|
|
43
|
+
function clefForProgram(program) {
|
|
44
|
+
return program >= 32 && program <= 39 ? "bass" : "treble";
|
|
45
|
+
}
|
|
46
|
+
/** Turns a picker value — from either list — back into track fields. */
|
|
47
|
+
export function instrumentChoiceFor(value) {
|
|
48
|
+
if (value.startsWith(KIT_PREFIX)) {
|
|
49
|
+
// `gmKit` rather than the raw number: an address no kit sits on falls back
|
|
50
|
+
// to Standard instead of producing a track nothing can play.
|
|
51
|
+
const kit = gmKit(Number(value.slice(KIT_PREFIX.length))) ?? GM_KITS[0];
|
|
52
|
+
return {
|
|
53
|
+
midiProgram: kit.program,
|
|
54
|
+
instrumentName: kit.name,
|
|
55
|
+
clef: "percussion",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const program = Number(value);
|
|
59
|
+
return {
|
|
60
|
+
midiProgram: program,
|
|
61
|
+
instrumentName: gmInstrument(program)?.name ?? "Piano",
|
|
62
|
+
clef: clefForProgram(program),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The label shown for a catalogue value. */
|
|
66
|
+
export function instrumentLabelFor(value) {
|
|
67
|
+
return instrumentChoiceFor(value).instrumentName;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=instrument-options.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instrument lookups that take a **track**, not a program number.
|
|
3
|
+
*
|
|
4
|
+
* `Track.midiProgram` means one of two different things depending on the
|
|
5
|
+
* track's clef: a General MIDI instrument on a pitched track, a drum kit on a
|
|
6
|
+
* percussion one. Every table in this folder is keyed by program, so reading
|
|
7
|
+
* one without knowing the clef silently answers for the wrong thing — and the
|
|
8
|
+
* wrong answers were not obviously wrong, which is why they shipped:
|
|
9
|
+
*
|
|
10
|
+
* - Brush is kit 40, and program 40 is Violin, so `gmMaxPolyphony` capped a
|
|
11
|
+
* drum track at two simultaneous notes and the toolbar refused a three-piece
|
|
12
|
+
* crash-snare-kick hit.
|
|
13
|
+
* - Electronic and TR-808 are kits 24 and 25, and programs 24-25 are guitars,
|
|
14
|
+
* which are written an octave above where they sound — so in written mode a
|
|
15
|
+
* TR-808 part was drawn an octave off the staff position for its own drums.
|
|
16
|
+
* - Every kit is some melodic instrument's range, so the on-screen keyboard
|
|
17
|
+
* offered keys that could not sound a drum and hid the ones that could.
|
|
18
|
+
*
|
|
19
|
+
* These wrappers are the single place that distinction is encoded. Call them
|
|
20
|
+
* instead of the program-keyed tables anywhere a `Track` is in hand.
|
|
21
|
+
*/
|
|
22
|
+
import type { Score, Track } from "../../index.js";
|
|
23
|
+
import { type MidiRange } from "./gm-range.js";
|
|
24
|
+
import type { InstrumentIconArt } from "./icon-art.js";
|
|
25
|
+
/** Whether `track`'s `midiProgram` addresses a drum kit rather than an instrument. */
|
|
26
|
+
export declare function isPercussionTrack(track: Pick<Track, "clef">): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The notes worth showing for `track` — General MIDI's drum range on a
|
|
29
|
+
* percussion track, the instrument's compass otherwise.
|
|
30
|
+
*/
|
|
31
|
+
export declare function trackKeyboardRange(track: Pick<Track, "clef" | "midiProgram">): MidiRange;
|
|
32
|
+
/**
|
|
33
|
+
* How many notes `track` can sound at once.
|
|
34
|
+
*
|
|
35
|
+
* Unlimited on a drum track: the limit exists to stop a part being written that
|
|
36
|
+
* nobody could play, and a kit is played with two hands and two feet across
|
|
37
|
+
* pieces that are all struck separately. Nothing about a kit address says
|
|
38
|
+
* otherwise.
|
|
39
|
+
*/
|
|
40
|
+
export declare function trackMaxPolyphony(track: Pick<Track, "clef" | "midiProgram">): number;
|
|
41
|
+
/**
|
|
42
|
+
* Semitones between `track`'s sounding and written pitch.
|
|
43
|
+
*
|
|
44
|
+
* Always zero on a drum track. A percussion staff's positions name drums, so
|
|
45
|
+
* transposing one does not move a part into a reader's key — it renames every
|
|
46
|
+
* drum in it.
|
|
47
|
+
*/
|
|
48
|
+
export declare function trackWrittenTransposition(track: Pick<Track, "clef" | "midiProgram">): number;
|
|
49
|
+
/**
|
|
50
|
+
* `track`'s program, corrected to something its clef can actually mean.
|
|
51
|
+
*
|
|
52
|
+
* On a percussion track that is the kit whose region the address falls in; a
|
|
53
|
+
* MIDI file is free to set program 45 on channel 10, and the kit that resolves
|
|
54
|
+
* to is Brush. Off a percussion track the program is already an instrument and
|
|
55
|
+
* is returned untouched.
|
|
56
|
+
*/
|
|
57
|
+
export declare function trackProgramForClef(track: Pick<Track, "clef" | "midiProgram">): number;
|
|
58
|
+
/** The icon for `track` — a kit on a percussion track, its instrument's art otherwise. */
|
|
59
|
+
export declare function trackInstrumentIcon(track: Pick<Track, "clef" | "midiProgram">): InstrumentIconArt;
|
|
60
|
+
/** What to call `track`'s sound: its kit's name on a percussion track, its instrument's otherwise. */
|
|
61
|
+
export declare function trackInstrumentLabel(track: Pick<Track, "clef" | "midiProgram">): string;
|
|
62
|
+
/**
|
|
63
|
+
* `score` with every percussion track's program resolved to a real kit.
|
|
64
|
+
*
|
|
65
|
+
* A drum track can arrive holding an address no kit sits at: a MIDI file sets
|
|
66
|
+
* whatever program it likes on channel 10, and nothing before this treated that
|
|
67
|
+
* number as a kit at all. The picker would then have to show something the
|
|
68
|
+
* score does not say, so the score is corrected instead of the display fudged.
|
|
69
|
+
*
|
|
70
|
+
* A track already on a kit address is returned untouched — including its
|
|
71
|
+
* `instrumentName`, which is the user's description of a sound that is not
|
|
72
|
+
* changing. Only a track being corrected has its name rewritten, because the
|
|
73
|
+
* old one described a different kit.
|
|
74
|
+
*
|
|
75
|
+
* Returns the **identical object** when nothing needs correcting, which is the
|
|
76
|
+
* usual case: `computeLayout` is cached by score identity, and a fresh object
|
|
77
|
+
* on every load would also read as a change to the autosaver.
|
|
78
|
+
*/
|
|
79
|
+
export declare function scoreWithResolvedKits(score: Score): Score;
|
|
80
|
+
//# sourceMappingURL=track-instrument.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-instrument.d.ts","sourceRoot":"","sources":["../../../src/domain/instruments/track-instrument.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAMlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGvD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAErE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,GACzC,SAAS,CAGX;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,GACzC,MAAM,CAGR;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,GACzC,MAAM,CAGR;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,GACzC,MAAM,CAIR;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,GACzC,iBAAiB,CAInB;AAED,sGAAsG;AACtG,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,GACzC,MAAM,CAGR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAezD"}
|