musicxml-io 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/accessors/index.d.mts +82 -0
- package/dist/accessors/index.d.ts +82 -0
- package/dist/accessors/index.js +239 -0
- package/dist/accessors/index.js.map +1 -0
- package/dist/accessors/index.mjs +198 -0
- package/dist/accessors/index.mjs.map +1 -0
- package/dist/index.d.mts +285 -0
- package/dist/index.d.ts +285 -0
- package/dist/index.js +6033 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +5932 -0
- package/dist/index.mjs.map +1 -0
- package/dist/operations/index.d.mts +92 -0
- package/dist/operations/index.d.ts +92 -0
- package/dist/operations/index.js +352 -0
- package/dist/operations/index.js.map +1 -0
- package/dist/operations/index.mjs +315 -0
- package/dist/operations/index.mjs.map +1 -0
- package/dist/query/index.d.mts +103 -0
- package/dist/query/index.d.ts +103 -0
- package/dist/query/index.js +272 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/index.mjs +232 -0
- package/dist/query/index.mjs.map +1 -0
- package/dist/types-DC_TnJu_.d.mts +797 -0
- package/dist/types-DC_TnJu_.d.ts +797 -0
- package/package.json +80 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { S as Score, N as NoteEntry, K as KeySignature, T as TimeSignature, a as Pitch } from '../types-DC_TnJu_.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transpose all notes in a score by a number of semitones
|
|
5
|
+
*/
|
|
6
|
+
declare function transpose(score: Score, semitones: number): Score;
|
|
7
|
+
/**
|
|
8
|
+
* Options for adding a note
|
|
9
|
+
*/
|
|
10
|
+
interface AddNoteOptions {
|
|
11
|
+
partIndex: number;
|
|
12
|
+
measureIndex: number;
|
|
13
|
+
staff?: number;
|
|
14
|
+
voice: number;
|
|
15
|
+
position: number;
|
|
16
|
+
note: Omit<NoteEntry, 'type' | 'voice' | 'staff'>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Add a note to a measure
|
|
20
|
+
* Automatically handles backup/forward insertion
|
|
21
|
+
*/
|
|
22
|
+
declare function addNote(score: Score, options: AddNoteOptions): Score;
|
|
23
|
+
/**
|
|
24
|
+
* Delete a note from a measure
|
|
25
|
+
*/
|
|
26
|
+
declare function deleteNote(score: Score, options: {
|
|
27
|
+
partIndex: number;
|
|
28
|
+
measureIndex: number;
|
|
29
|
+
noteIndex: number;
|
|
30
|
+
}): Score;
|
|
31
|
+
/**
|
|
32
|
+
* Change key signature from a specific measure
|
|
33
|
+
*/
|
|
34
|
+
declare function changeKey(score: Score, key: KeySignature, options: {
|
|
35
|
+
fromMeasure: string | number;
|
|
36
|
+
}): Score;
|
|
37
|
+
/**
|
|
38
|
+
* Change time signature from a specific measure
|
|
39
|
+
*/
|
|
40
|
+
declare function changeTime(score: Score, time: TimeSignature, options: {
|
|
41
|
+
fromMeasure: string | number;
|
|
42
|
+
}): Score;
|
|
43
|
+
/**
|
|
44
|
+
* Insert a new measure after a specific measure number
|
|
45
|
+
*/
|
|
46
|
+
declare function insertMeasure(score: Score, options: {
|
|
47
|
+
afterMeasure: string | number;
|
|
48
|
+
copyAttributes?: boolean;
|
|
49
|
+
}): Score;
|
|
50
|
+
/**
|
|
51
|
+
* Delete a measure
|
|
52
|
+
*/
|
|
53
|
+
declare function deleteMeasure(score: Score, measureNumber: string | number): Score;
|
|
54
|
+
/**
|
|
55
|
+
* Set divisions for a measure
|
|
56
|
+
*/
|
|
57
|
+
declare function setDivisions(score: Score, options: {
|
|
58
|
+
partIndex: number;
|
|
59
|
+
measureIndex: number;
|
|
60
|
+
divisions: number;
|
|
61
|
+
}): Score;
|
|
62
|
+
/**
|
|
63
|
+
* Add a chord note (note that sounds simultaneously with the previous note)
|
|
64
|
+
*/
|
|
65
|
+
declare function addChordNote(score: Score, options: {
|
|
66
|
+
partIndex: number;
|
|
67
|
+
measureIndex: number;
|
|
68
|
+
afterNoteIndex: number;
|
|
69
|
+
pitch: Pitch;
|
|
70
|
+
}): Score;
|
|
71
|
+
/**
|
|
72
|
+
* Modify a note's pitch
|
|
73
|
+
*/
|
|
74
|
+
declare function modifyNotePitch(score: Score, options: {
|
|
75
|
+
partIndex: number;
|
|
76
|
+
measureIndex: number;
|
|
77
|
+
noteIndex: number;
|
|
78
|
+
pitch: Pitch;
|
|
79
|
+
}): Score;
|
|
80
|
+
/**
|
|
81
|
+
* Modify a note's duration
|
|
82
|
+
*/
|
|
83
|
+
declare function modifyNoteDuration(score: Score, options: {
|
|
84
|
+
partIndex: number;
|
|
85
|
+
measureIndex: number;
|
|
86
|
+
noteIndex: number;
|
|
87
|
+
duration: number;
|
|
88
|
+
noteType?: NoteEntry['noteType'];
|
|
89
|
+
dots?: number;
|
|
90
|
+
}): Score;
|
|
91
|
+
|
|
92
|
+
export { type AddNoteOptions, addChordNote, addNote, changeKey, changeTime, deleteMeasure, deleteNote, insertMeasure, modifyNoteDuration, modifyNotePitch, setDivisions, transpose };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { S as Score, N as NoteEntry, K as KeySignature, T as TimeSignature, a as Pitch } from '../types-DC_TnJu_.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Transpose all notes in a score by a number of semitones
|
|
5
|
+
*/
|
|
6
|
+
declare function transpose(score: Score, semitones: number): Score;
|
|
7
|
+
/**
|
|
8
|
+
* Options for adding a note
|
|
9
|
+
*/
|
|
10
|
+
interface AddNoteOptions {
|
|
11
|
+
partIndex: number;
|
|
12
|
+
measureIndex: number;
|
|
13
|
+
staff?: number;
|
|
14
|
+
voice: number;
|
|
15
|
+
position: number;
|
|
16
|
+
note: Omit<NoteEntry, 'type' | 'voice' | 'staff'>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Add a note to a measure
|
|
20
|
+
* Automatically handles backup/forward insertion
|
|
21
|
+
*/
|
|
22
|
+
declare function addNote(score: Score, options: AddNoteOptions): Score;
|
|
23
|
+
/**
|
|
24
|
+
* Delete a note from a measure
|
|
25
|
+
*/
|
|
26
|
+
declare function deleteNote(score: Score, options: {
|
|
27
|
+
partIndex: number;
|
|
28
|
+
measureIndex: number;
|
|
29
|
+
noteIndex: number;
|
|
30
|
+
}): Score;
|
|
31
|
+
/**
|
|
32
|
+
* Change key signature from a specific measure
|
|
33
|
+
*/
|
|
34
|
+
declare function changeKey(score: Score, key: KeySignature, options: {
|
|
35
|
+
fromMeasure: string | number;
|
|
36
|
+
}): Score;
|
|
37
|
+
/**
|
|
38
|
+
* Change time signature from a specific measure
|
|
39
|
+
*/
|
|
40
|
+
declare function changeTime(score: Score, time: TimeSignature, options: {
|
|
41
|
+
fromMeasure: string | number;
|
|
42
|
+
}): Score;
|
|
43
|
+
/**
|
|
44
|
+
* Insert a new measure after a specific measure number
|
|
45
|
+
*/
|
|
46
|
+
declare function insertMeasure(score: Score, options: {
|
|
47
|
+
afterMeasure: string | number;
|
|
48
|
+
copyAttributes?: boolean;
|
|
49
|
+
}): Score;
|
|
50
|
+
/**
|
|
51
|
+
* Delete a measure
|
|
52
|
+
*/
|
|
53
|
+
declare function deleteMeasure(score: Score, measureNumber: string | number): Score;
|
|
54
|
+
/**
|
|
55
|
+
* Set divisions for a measure
|
|
56
|
+
*/
|
|
57
|
+
declare function setDivisions(score: Score, options: {
|
|
58
|
+
partIndex: number;
|
|
59
|
+
measureIndex: number;
|
|
60
|
+
divisions: number;
|
|
61
|
+
}): Score;
|
|
62
|
+
/**
|
|
63
|
+
* Add a chord note (note that sounds simultaneously with the previous note)
|
|
64
|
+
*/
|
|
65
|
+
declare function addChordNote(score: Score, options: {
|
|
66
|
+
partIndex: number;
|
|
67
|
+
measureIndex: number;
|
|
68
|
+
afterNoteIndex: number;
|
|
69
|
+
pitch: Pitch;
|
|
70
|
+
}): Score;
|
|
71
|
+
/**
|
|
72
|
+
* Modify a note's pitch
|
|
73
|
+
*/
|
|
74
|
+
declare function modifyNotePitch(score: Score, options: {
|
|
75
|
+
partIndex: number;
|
|
76
|
+
measureIndex: number;
|
|
77
|
+
noteIndex: number;
|
|
78
|
+
pitch: Pitch;
|
|
79
|
+
}): Score;
|
|
80
|
+
/**
|
|
81
|
+
* Modify a note's duration
|
|
82
|
+
*/
|
|
83
|
+
declare function modifyNoteDuration(score: Score, options: {
|
|
84
|
+
partIndex: number;
|
|
85
|
+
measureIndex: number;
|
|
86
|
+
noteIndex: number;
|
|
87
|
+
duration: number;
|
|
88
|
+
noteType?: NoteEntry['noteType'];
|
|
89
|
+
dots?: number;
|
|
90
|
+
}): Score;
|
|
91
|
+
|
|
92
|
+
export { type AddNoteOptions, addChordNote, addNote, changeKey, changeTime, deleteMeasure, deleteNote, insertMeasure, modifyNoteDuration, modifyNotePitch, setDivisions, transpose };
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/operations/index.ts
|
|
21
|
+
var operations_exports = {};
|
|
22
|
+
__export(operations_exports, {
|
|
23
|
+
addChordNote: () => addChordNote,
|
|
24
|
+
addNote: () => addNote,
|
|
25
|
+
changeKey: () => changeKey,
|
|
26
|
+
changeTime: () => changeTime,
|
|
27
|
+
deleteMeasure: () => deleteMeasure,
|
|
28
|
+
deleteNote: () => deleteNote,
|
|
29
|
+
insertMeasure: () => insertMeasure,
|
|
30
|
+
modifyNoteDuration: () => modifyNoteDuration,
|
|
31
|
+
modifyNotePitch: () => modifyNotePitch,
|
|
32
|
+
setDivisions: () => setDivisions,
|
|
33
|
+
transpose: () => transpose
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(operations_exports);
|
|
36
|
+
|
|
37
|
+
// src/utils/index.ts
|
|
38
|
+
var STEPS = ["C", "D", "E", "F", "G", "A", "B"];
|
|
39
|
+
var STEP_SEMITONES = {
|
|
40
|
+
"C": 0,
|
|
41
|
+
"D": 2,
|
|
42
|
+
"E": 4,
|
|
43
|
+
"F": 5,
|
|
44
|
+
"G": 7,
|
|
45
|
+
"A": 9,
|
|
46
|
+
"B": 11
|
|
47
|
+
};
|
|
48
|
+
function createPositionState() {
|
|
49
|
+
return { position: 0, lastNonChordPosition: 0 };
|
|
50
|
+
}
|
|
51
|
+
function updatePositionForEntry(state, entry) {
|
|
52
|
+
const pos = state.position;
|
|
53
|
+
switch (entry.type) {
|
|
54
|
+
case "note": {
|
|
55
|
+
const note = entry;
|
|
56
|
+
if (!note.chord) {
|
|
57
|
+
state.lastNonChordPosition = state.position;
|
|
58
|
+
state.position += note.duration;
|
|
59
|
+
}
|
|
60
|
+
return note.chord ? state.lastNonChordPosition : pos;
|
|
61
|
+
}
|
|
62
|
+
case "backup":
|
|
63
|
+
state.position -= entry.duration;
|
|
64
|
+
state.lastNonChordPosition = state.position;
|
|
65
|
+
return pos;
|
|
66
|
+
case "forward":
|
|
67
|
+
state.position += entry.duration;
|
|
68
|
+
state.lastNonChordPosition = state.position;
|
|
69
|
+
return pos;
|
|
70
|
+
default:
|
|
71
|
+
return pos;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function getMeasureEndPosition(measure) {
|
|
75
|
+
const state = createPositionState();
|
|
76
|
+
for (const entry of measure.entries) updatePositionForEntry(state, entry);
|
|
77
|
+
return state.position;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/operations/index.ts
|
|
81
|
+
function cloneScore(score) {
|
|
82
|
+
return JSON.parse(JSON.stringify(score));
|
|
83
|
+
}
|
|
84
|
+
function transposePitch(pitch, semitones) {
|
|
85
|
+
const currentSemitone = STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0) + pitch.octave * 12;
|
|
86
|
+
const targetSemitone = currentSemitone + semitones;
|
|
87
|
+
const targetOctave = Math.floor(targetSemitone / 12);
|
|
88
|
+
const targetPitchClass = (targetSemitone % 12 + 12) % 12;
|
|
89
|
+
let bestStep = "C";
|
|
90
|
+
let bestAlter = 99;
|
|
91
|
+
for (const step of STEPS) {
|
|
92
|
+
const stepSemitone = STEP_SEMITONES[step];
|
|
93
|
+
let diff = targetPitchClass - stepSemitone;
|
|
94
|
+
if (diff > 6) diff -= 12;
|
|
95
|
+
if (diff < -6) diff += 12;
|
|
96
|
+
if (diff >= -2 && diff <= 2) {
|
|
97
|
+
if (Math.abs(diff) < Math.abs(bestAlter)) {
|
|
98
|
+
bestStep = step;
|
|
99
|
+
bestAlter = diff;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
step: bestStep,
|
|
105
|
+
octave: targetOctave,
|
|
106
|
+
alter: bestAlter !== 0 ? bestAlter : void 0
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function transpose(score, semitones) {
|
|
110
|
+
if (semitones === 0) return score;
|
|
111
|
+
const result = cloneScore(score);
|
|
112
|
+
for (const part of result.parts) {
|
|
113
|
+
for (const measure of part.measures) {
|
|
114
|
+
for (const entry of measure.entries) {
|
|
115
|
+
if (entry.type === "note" && entry.pitch) {
|
|
116
|
+
entry.pitch = transposePitch(entry.pitch, semitones);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
function addNote(score, options) {
|
|
124
|
+
const result = cloneScore(score);
|
|
125
|
+
const part = result.parts[options.partIndex];
|
|
126
|
+
if (!part) return result;
|
|
127
|
+
const measure = part.measures[options.measureIndex];
|
|
128
|
+
if (!measure) return result;
|
|
129
|
+
const newNote = {
|
|
130
|
+
type: "note",
|
|
131
|
+
voice: options.voice,
|
|
132
|
+
staff: options.staff,
|
|
133
|
+
...options.note
|
|
134
|
+
};
|
|
135
|
+
const currentPosition = getMeasureEndPosition(measure);
|
|
136
|
+
const positionDiff = options.position - currentPosition;
|
|
137
|
+
if (positionDiff < 0) {
|
|
138
|
+
measure.entries.push({
|
|
139
|
+
type: "backup",
|
|
140
|
+
duration: -positionDiff
|
|
141
|
+
});
|
|
142
|
+
} else if (positionDiff > 0) {
|
|
143
|
+
measure.entries.push({
|
|
144
|
+
type: "forward",
|
|
145
|
+
duration: positionDiff,
|
|
146
|
+
voice: options.voice,
|
|
147
|
+
staff: options.staff
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
measure.entries.push(newNote);
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
function deleteNote(score, options) {
|
|
154
|
+
const result = cloneScore(score);
|
|
155
|
+
const part = result.parts[options.partIndex];
|
|
156
|
+
if (!part) return result;
|
|
157
|
+
const measure = part.measures[options.measureIndex];
|
|
158
|
+
if (!measure) return result;
|
|
159
|
+
let noteCount = 0;
|
|
160
|
+
let entryIndex = -1;
|
|
161
|
+
for (let i = 0; i < measure.entries.length; i++) {
|
|
162
|
+
if (measure.entries[i].type === "note") {
|
|
163
|
+
if (noteCount === options.noteIndex) {
|
|
164
|
+
entryIndex = i;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
noteCount++;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (entryIndex !== -1) {
|
|
171
|
+
measure.entries.splice(entryIndex, 1);
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
function changeKey(score, key, options) {
|
|
176
|
+
const result = cloneScore(score);
|
|
177
|
+
const targetMeasure = String(options.fromMeasure);
|
|
178
|
+
for (const part of result.parts) {
|
|
179
|
+
for (const measure of part.measures) {
|
|
180
|
+
if (measure.number === targetMeasure) {
|
|
181
|
+
if (!measure.attributes) {
|
|
182
|
+
measure.attributes = {};
|
|
183
|
+
}
|
|
184
|
+
measure.attributes.key = key;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
function changeTime(score, time, options) {
|
|
191
|
+
const result = cloneScore(score);
|
|
192
|
+
const targetMeasure = String(options.fromMeasure);
|
|
193
|
+
for (const part of result.parts) {
|
|
194
|
+
for (const measure of part.measures) {
|
|
195
|
+
if (measure.number === targetMeasure) {
|
|
196
|
+
if (!measure.attributes) {
|
|
197
|
+
measure.attributes = {};
|
|
198
|
+
}
|
|
199
|
+
measure.attributes.time = time;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
function insertMeasure(score, options) {
|
|
206
|
+
const result = cloneScore(score);
|
|
207
|
+
const targetMeasure = String(options.afterMeasure);
|
|
208
|
+
for (const part of result.parts) {
|
|
209
|
+
const insertIndex = part.measures.findIndex((m) => m.number === targetMeasure);
|
|
210
|
+
if (insertIndex === -1) continue;
|
|
211
|
+
const numericPart = parseInt(targetMeasure, 10);
|
|
212
|
+
const newMeasureNumber = String(isNaN(numericPart) ? insertIndex + 2 : numericPart + 1);
|
|
213
|
+
const newMeasure = {
|
|
214
|
+
number: newMeasureNumber,
|
|
215
|
+
entries: []
|
|
216
|
+
};
|
|
217
|
+
if (options.copyAttributes) {
|
|
218
|
+
const sourceMeasure = part.measures[insertIndex];
|
|
219
|
+
if (sourceMeasure.attributes) {
|
|
220
|
+
newMeasure.attributes = { ...sourceMeasure.attributes };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
part.measures.splice(insertIndex + 1, 0, newMeasure);
|
|
224
|
+
for (let i = insertIndex + 2; i < part.measures.length; i++) {
|
|
225
|
+
const currentNum = parseInt(part.measures[i].number, 10);
|
|
226
|
+
if (!isNaN(currentNum)) {
|
|
227
|
+
part.measures[i].number = String(currentNum + 1);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
function deleteMeasure(score, measureNumber) {
|
|
234
|
+
const result = cloneScore(score);
|
|
235
|
+
const targetMeasure = String(measureNumber);
|
|
236
|
+
for (const part of result.parts) {
|
|
237
|
+
const deleteIndex = part.measures.findIndex((m) => m.number === targetMeasure);
|
|
238
|
+
if (deleteIndex === -1) continue;
|
|
239
|
+
part.measures.splice(deleteIndex, 1);
|
|
240
|
+
for (let i = deleteIndex; i < part.measures.length; i++) {
|
|
241
|
+
const currentNum = parseInt(part.measures[i].number, 10);
|
|
242
|
+
if (!isNaN(currentNum)) {
|
|
243
|
+
part.measures[i].number = String(currentNum - 1);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
function setDivisions(score, options) {
|
|
250
|
+
const result = cloneScore(score);
|
|
251
|
+
const part = result.parts[options.partIndex];
|
|
252
|
+
if (!part) return result;
|
|
253
|
+
const measure = part.measures[options.measureIndex];
|
|
254
|
+
if (!measure) return result;
|
|
255
|
+
if (!measure.attributes) {
|
|
256
|
+
measure.attributes = {};
|
|
257
|
+
}
|
|
258
|
+
measure.attributes.divisions = options.divisions;
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
function addChordNote(score, options) {
|
|
262
|
+
const result = cloneScore(score);
|
|
263
|
+
const part = result.parts[options.partIndex];
|
|
264
|
+
if (!part) return result;
|
|
265
|
+
const measure = part.measures[options.measureIndex];
|
|
266
|
+
if (!measure) return result;
|
|
267
|
+
let noteCount = 0;
|
|
268
|
+
let entryIndex = -1;
|
|
269
|
+
let targetNote = null;
|
|
270
|
+
for (let i = 0; i < measure.entries.length; i++) {
|
|
271
|
+
const entry = measure.entries[i];
|
|
272
|
+
if (entry.type === "note") {
|
|
273
|
+
if (noteCount === options.afterNoteIndex) {
|
|
274
|
+
entryIndex = i;
|
|
275
|
+
targetNote = entry;
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
noteCount++;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (entryIndex !== -1 && targetNote) {
|
|
282
|
+
const chordNote = {
|
|
283
|
+
type: "note",
|
|
284
|
+
pitch: options.pitch,
|
|
285
|
+
duration: targetNote.duration,
|
|
286
|
+
voice: targetNote.voice,
|
|
287
|
+
staff: targetNote.staff,
|
|
288
|
+
chord: true,
|
|
289
|
+
noteType: targetNote.noteType,
|
|
290
|
+
dots: targetNote.dots
|
|
291
|
+
};
|
|
292
|
+
measure.entries.splice(entryIndex + 1, 0, chordNote);
|
|
293
|
+
}
|
|
294
|
+
return result;
|
|
295
|
+
}
|
|
296
|
+
function modifyNotePitch(score, options) {
|
|
297
|
+
const result = cloneScore(score);
|
|
298
|
+
const part = result.parts[options.partIndex];
|
|
299
|
+
if (!part) return result;
|
|
300
|
+
const measure = part.measures[options.measureIndex];
|
|
301
|
+
if (!measure) return result;
|
|
302
|
+
let noteCount = 0;
|
|
303
|
+
for (const entry of measure.entries) {
|
|
304
|
+
if (entry.type === "note") {
|
|
305
|
+
if (noteCount === options.noteIndex) {
|
|
306
|
+
entry.pitch = options.pitch;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
noteCount++;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
function modifyNoteDuration(score, options) {
|
|
315
|
+
const result = cloneScore(score);
|
|
316
|
+
const part = result.parts[options.partIndex];
|
|
317
|
+
if (!part) return result;
|
|
318
|
+
const measure = part.measures[options.measureIndex];
|
|
319
|
+
if (!measure) return result;
|
|
320
|
+
let noteCount = 0;
|
|
321
|
+
for (const entry of measure.entries) {
|
|
322
|
+
if (entry.type === "note") {
|
|
323
|
+
if (noteCount === options.noteIndex) {
|
|
324
|
+
entry.duration = options.duration;
|
|
325
|
+
if (options.noteType !== void 0) {
|
|
326
|
+
entry.noteType = options.noteType;
|
|
327
|
+
}
|
|
328
|
+
if (options.dots !== void 0) {
|
|
329
|
+
entry.dots = options.dots;
|
|
330
|
+
}
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
noteCount++;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
339
|
+
0 && (module.exports = {
|
|
340
|
+
addChordNote,
|
|
341
|
+
addNote,
|
|
342
|
+
changeKey,
|
|
343
|
+
changeTime,
|
|
344
|
+
deleteMeasure,
|
|
345
|
+
deleteNote,
|
|
346
|
+
insertMeasure,
|
|
347
|
+
modifyNoteDuration,
|
|
348
|
+
modifyNotePitch,
|
|
349
|
+
setDivisions,
|
|
350
|
+
transpose
|
|
351
|
+
});
|
|
352
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/operations/index.ts","../../src/utils/index.ts"],"sourcesContent":["import type {\n Score,\n Measure,\n NoteEntry,\n Pitch,\n KeySignature,\n TimeSignature,\n} from '../types';\nimport { STEPS, STEP_SEMITONES, getMeasureEndPosition } from '../utils';\n\n/**\n * Deep clone a score\n */\nfunction cloneScore(score: Score): Score {\n return JSON.parse(JSON.stringify(score));\n}\n\n/**\n * Transpose a pitch by a number of semitones\n */\nfunction transposePitch(pitch: Pitch, semitones: number): Pitch {\n const currentSemitone = STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0) + pitch.octave * 12;\n const targetSemitone = currentSemitone + semitones;\n\n const targetOctave = Math.floor(targetSemitone / 12);\n const targetPitchClass = ((targetSemitone % 12) + 12) % 12;\n\n // Find the closest natural step with smallest alteration\n let bestStep: Pitch['step'] = 'C';\n let bestAlter = 99; // Start with large value so any real alter is smaller\n\n for (const step of STEPS) {\n const stepSemitone = STEP_SEMITONES[step];\n // Calculate the alteration needed to reach target from this step\n let diff = targetPitchClass - stepSemitone;\n\n // Normalize to range -6 to +6 for smallest alteration\n if (diff > 6) diff -= 12;\n if (diff < -6) diff += 12;\n\n // Only consider alterations within -2 to +2 (double flat to double sharp)\n if (diff >= -2 && diff <= 2) {\n if (Math.abs(diff) < Math.abs(bestAlter)) {\n bestStep = step;\n bestAlter = diff;\n }\n }\n }\n\n return {\n step: bestStep,\n octave: targetOctave,\n alter: bestAlter !== 0 ? bestAlter : undefined,\n };\n}\n\n/**\n * Transpose all notes in a score by a number of semitones\n */\nexport function transpose(score: Score, semitones: number): Score {\n if (semitones === 0) return score;\n\n const result = cloneScore(score);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type === 'note' && entry.pitch) {\n entry.pitch = transposePitch(entry.pitch, semitones);\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Options for adding a note\n */\nexport interface AddNoteOptions {\n partIndex: number;\n measureIndex: number;\n staff?: number;\n voice: number;\n position: number;\n note: Omit<NoteEntry, 'type' | 'voice' | 'staff'>;\n}\n\n/**\n * Add a note to a measure\n * Automatically handles backup/forward insertion\n */\nexport function addNote(score: Score, options: AddNoteOptions): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n const newNote: NoteEntry = {\n type: 'note',\n voice: options.voice,\n staff: options.staff,\n ...options.note,\n };\n\n // Find the current position at the end of the measure using shared utility\n const currentPosition = getMeasureEndPosition(measure);\n\n // Calculate backup/forward needed\n const positionDiff = options.position - currentPosition;\n\n if (positionDiff < 0) {\n // Need to backup\n measure.entries.push({\n type: 'backup',\n duration: -positionDiff,\n });\n } else if (positionDiff > 0) {\n // Need to forward\n measure.entries.push({\n type: 'forward',\n duration: positionDiff,\n voice: options.voice,\n staff: options.staff,\n });\n }\n\n measure.entries.push(newNote);\n\n return result;\n}\n\n/**\n * Delete a note from a measure\n */\nexport function deleteNote(score: Score, options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n}): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n let entryIndex = -1;\n\n for (let i = 0; i < measure.entries.length; i++) {\n if (measure.entries[i].type === 'note') {\n if (noteCount === options.noteIndex) {\n entryIndex = i;\n break;\n }\n noteCount++;\n }\n }\n\n if (entryIndex !== -1) {\n measure.entries.splice(entryIndex, 1);\n }\n\n return result;\n}\n\n/**\n * Change key signature from a specific measure\n */\nexport function changeKey(\n score: Score,\n key: KeySignature,\n options: { fromMeasure: string | number }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.fromMeasure);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n if (measure.number === targetMeasure) {\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.key = key;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Change time signature from a specific measure\n */\nexport function changeTime(\n score: Score,\n time: TimeSignature,\n options: { fromMeasure: string | number }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.fromMeasure);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n if (measure.number === targetMeasure) {\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.time = time;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Insert a new measure after a specific measure number\n */\nexport function insertMeasure(\n score: Score,\n options: {\n afterMeasure: string | number;\n copyAttributes?: boolean;\n }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.afterMeasure);\n\n for (const part of result.parts) {\n const insertIndex = part.measures.findIndex((m) => m.number === targetMeasure);\n if (insertIndex === -1) continue;\n\n // Parse target measure number and increment for new measure\n const numericPart = parseInt(targetMeasure, 10);\n const newMeasureNumber = String(isNaN(numericPart) ? insertIndex + 2 : numericPart + 1);\n\n // Create new empty measure\n const newMeasure: Measure = {\n number: newMeasureNumber,\n entries: [],\n };\n\n // Copy attributes if requested\n if (options.copyAttributes) {\n const sourceMeasure = part.measures[insertIndex];\n if (sourceMeasure.attributes) {\n newMeasure.attributes = { ...sourceMeasure.attributes };\n }\n }\n\n // Insert the new measure\n part.measures.splice(insertIndex + 1, 0, newMeasure);\n\n // Update measure numbers for subsequent measures\n for (let i = insertIndex + 2; i < part.measures.length; i++) {\n const currentNum = parseInt(part.measures[i].number, 10);\n if (!isNaN(currentNum)) {\n part.measures[i].number = String(currentNum + 1);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Delete a measure\n */\nexport function deleteMeasure(score: Score, measureNumber: string | number): Score {\n const result = cloneScore(score);\n const targetMeasure = String(measureNumber);\n\n for (const part of result.parts) {\n const deleteIndex = part.measures.findIndex((m) => m.number === targetMeasure);\n if (deleteIndex === -1) continue;\n\n // Remove the measure\n part.measures.splice(deleteIndex, 1);\n\n // Update measure numbers for subsequent measures\n for (let i = deleteIndex; i < part.measures.length; i++) {\n const currentNum = parseInt(part.measures[i].number, 10);\n if (!isNaN(currentNum)) {\n part.measures[i].number = String(currentNum - 1);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Set divisions for a measure\n */\nexport function setDivisions(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n divisions: number;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.divisions = options.divisions;\n\n return result;\n}\n\n/**\n * Add a chord note (note that sounds simultaneously with the previous note)\n */\nexport function addChordNote(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n afterNoteIndex: number;\n pitch: Pitch;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n let entryIndex = -1;\n let targetNote: NoteEntry | null = null;\n\n for (let i = 0; i < measure.entries.length; i++) {\n const entry = measure.entries[i];\n if (entry.type === 'note') {\n if (noteCount === options.afterNoteIndex) {\n entryIndex = i;\n targetNote = entry;\n break;\n }\n noteCount++;\n }\n }\n\n if (entryIndex !== -1 && targetNote) {\n const chordNote: NoteEntry = {\n type: 'note',\n pitch: options.pitch,\n duration: targetNote.duration,\n voice: targetNote.voice,\n staff: targetNote.staff,\n chord: true,\n noteType: targetNote.noteType,\n dots: targetNote.dots,\n };\n\n measure.entries.splice(entryIndex + 1, 0, chordNote);\n }\n\n return result;\n}\n\n/**\n * Modify a note's pitch\n */\nexport function modifyNotePitch(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n pitch: Pitch;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n if (noteCount === options.noteIndex) {\n entry.pitch = options.pitch;\n break;\n }\n noteCount++;\n }\n }\n\n return result;\n}\n\n/**\n * Modify a note's duration\n */\nexport function modifyNoteDuration(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n duration: number;\n noteType?: NoteEntry['noteType'];\n dots?: number;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n if (noteCount === options.noteIndex) {\n entry.duration = options.duration;\n if (options.noteType !== undefined) {\n entry.noteType = options.noteType;\n }\n if (options.dots !== undefined) {\n entry.dots = options.dots;\n }\n break;\n }\n noteCount++;\n }\n }\n\n return result;\n}\n","import type { Pitch, Measure, MeasureEntry, NoteEntry } from '../types';\n\n// Pitch constants\nexport const STEPS: Pitch['step'][] = ['C', 'D', 'E', 'F', 'G', 'A', 'B'];\nexport const STEP_SEMITONES: Record<Pitch['step'], number> = {\n 'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11,\n};\n\n/** Convert pitch to semitone value (MIDI-like) */\nexport function pitchToSemitone(pitch: Pitch): number {\n return pitch.octave * 12 + STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0);\n}\n\n// Position tracking for measure iteration\nexport interface PositionState {\n position: number;\n lastNonChordPosition: number;\n}\n\nexport function createPositionState(): PositionState {\n return { position: 0, lastNonChordPosition: 0 };\n}\n\n/** Update position state for entry, returns position before update */\nexport function updatePositionForEntry(state: PositionState, entry: MeasureEntry): number {\n const pos = state.position;\n switch (entry.type) {\n case 'note': {\n const note = entry as NoteEntry;\n if (!note.chord) {\n state.lastNonChordPosition = state.position;\n state.position += note.duration;\n }\n return note.chord ? state.lastNonChordPosition : pos;\n }\n case 'backup':\n state.position -= entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n case 'forward':\n state.position += entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n default:\n return pos;\n }\n}\n\n/** Get absolute position of a note within a measure */\nexport function getAbsolutePositionForNote(note: NoteEntry, measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) {\n if (entry === note) return entry.chord ? state.lastNonChordPosition : state.position;\n updatePositionForEntry(state, entry);\n }\n return state.position;\n}\n\n/** Get position at end of measure */\nexport function getMeasureEndPosition(measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) updatePositionForEntry(state, entry);\n return state.position;\n}\n"],"mappings":"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","names":[]}
|