musicxml-io 0.5.0 → 0.5.1
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/index.js +177 -142
- package/dist/index.mjs +177 -142
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -214,9 +214,14 @@ var _chunkVE2KCZMAjs = require('./chunk-VE2KCZMA.js');
|
|
|
214
214
|
|
|
215
215
|
// src/importers/musicxml.ts
|
|
216
216
|
var _txml = require('txml');
|
|
217
|
+
var _entityMap = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
|
|
218
|
+
var _entityRegex = /&(?:(amp|lt|gt|quot|apos)|#(\d+)|#x([0-9a-fA-F]+));/g;
|
|
217
219
|
function decodeXmlEntities(s) {
|
|
218
220
|
if (s.indexOf("&") === -1) return s;
|
|
219
|
-
return s.replace(
|
|
221
|
+
return s.replace(
|
|
222
|
+
_entityRegex,
|
|
223
|
+
(_, named, dec, hex) => named ? _entityMap[named] : dec ? String.fromCharCode(parseInt(dec, 10)) : String.fromCharCode(parseInt(hex, 16))
|
|
224
|
+
);
|
|
220
225
|
}
|
|
221
226
|
function decodeTree(nodes) {
|
|
222
227
|
for (let i = 0; i < nodes.length; i++) {
|
|
@@ -1040,12 +1045,8 @@ function parseNote(elements, attrs) {
|
|
|
1040
1045
|
const note = {
|
|
1041
1046
|
_id: _chunkKABVHR2Pjs.generateId.call(void 0, ),
|
|
1042
1047
|
type: "note",
|
|
1043
|
-
duration:
|
|
1048
|
+
duration: 0
|
|
1044
1049
|
};
|
|
1045
|
-
const voiceValue = getElementText(elements, "voice");
|
|
1046
|
-
if (voiceValue !== void 0 && voiceValue !== "") {
|
|
1047
|
-
note.voice = voiceValue;
|
|
1048
|
-
}
|
|
1049
1050
|
if (attrs["default-x"]) note.defaultX = parseFloat(attrs["default-x"]);
|
|
1050
1051
|
if (attrs["default-y"]) note.defaultY = parseFloat(attrs["default-y"]);
|
|
1051
1052
|
if (attrs["relative-x"]) note.relativeX = parseFloat(attrs["relative-x"]);
|
|
@@ -1056,149 +1057,183 @@ function parseNote(elements, attrs) {
|
|
|
1056
1057
|
if (attrs["print-dot"] === "yes") note.printDot = true;
|
|
1057
1058
|
if (attrs["print-spacing"] === "yes") note.printSpacing = true;
|
|
1058
1059
|
if (attrs["print-spacing"] === "no") note.printSpacing = false;
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
for (const el of elements) {
|
|
1060
|
+
let dotCount = 0;
|
|
1061
|
+
let notationsIndex = 0;
|
|
1062
|
+
let tieElements;
|
|
1063
|
+
let beams;
|
|
1064
|
+
let allNotations;
|
|
1065
|
+
let lyrics;
|
|
1066
|
+
let hasGrace = false;
|
|
1067
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1068
|
+
const el = elements[i];
|
|
1069
1069
|
if (typeof el === "string") continue;
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1070
|
+
const tag = el.tagName;
|
|
1071
|
+
const elAttrs = el.attributes;
|
|
1072
|
+
const c = el.children;
|
|
1073
|
+
switch (tag) {
|
|
1074
|
+
case "duration": {
|
|
1075
|
+
const text = extractText(c);
|
|
1076
|
+
if (text) note.duration = parseInt(text, 10) || 0;
|
|
1077
|
+
break;
|
|
1078
|
+
}
|
|
1079
|
+
case "voice": {
|
|
1080
|
+
const text = extractText(c);
|
|
1081
|
+
if (text) note.voice = text;
|
|
1082
|
+
break;
|
|
1083
|
+
}
|
|
1084
|
+
case "cue":
|
|
1085
|
+
note.cue = true;
|
|
1086
|
+
break;
|
|
1087
|
+
case "chord":
|
|
1088
|
+
note.chord = true;
|
|
1089
|
+
break;
|
|
1090
|
+
case "dot":
|
|
1091
|
+
dotCount++;
|
|
1092
|
+
break;
|
|
1093
|
+
case "instrument":
|
|
1094
|
+
if (elAttrs["id"]) note.instrument = elAttrs["id"];
|
|
1095
|
+
break;
|
|
1096
|
+
case "pitch":
|
|
1097
|
+
note.pitch = parsePitch(c);
|
|
1098
|
+
break;
|
|
1099
|
+
case "rest": {
|
|
1100
|
+
const restInfo = {};
|
|
1101
|
+
if (elAttrs["measure"] === "yes") restInfo.measure = true;
|
|
1102
|
+
const displayStep = getElementText(c, "display-step");
|
|
1103
|
+
if (displayStep) restInfo.displayStep = displayStep;
|
|
1104
|
+
const displayOctave = getElementText(c, "display-octave");
|
|
1105
|
+
if (displayOctave) restInfo.displayOctave = parseInt(displayOctave, 10);
|
|
1106
|
+
note.rest = restInfo;
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
case "unpitched": {
|
|
1110
|
+
note.unpitched = {};
|
|
1111
|
+
const displayStep = getElementText(c, "display-step");
|
|
1112
|
+
if (displayStep) note.unpitched.displayStep = displayStep;
|
|
1113
|
+
const displayOctave = getElementText(c, "display-octave");
|
|
1114
|
+
if (displayOctave) note.unpitched.displayOctave = parseInt(displayOctave, 10);
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
case "staff": {
|
|
1118
|
+
const text = extractText(c);
|
|
1119
|
+
if (text) {
|
|
1120
|
+
const v = parseInt(text, 10);
|
|
1121
|
+
if (!isNaN(v)) note.staff = v;
|
|
1122
|
+
}
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
case "type": {
|
|
1126
|
+
const noteType = extractText(c);
|
|
1127
|
+
if (isValidNoteType(noteType)) note.noteType = noteType;
|
|
1128
|
+
if (elAttrs["size"]) note.noteTypeSize = elAttrs["size"];
|
|
1129
|
+
break;
|
|
1130
|
+
}
|
|
1131
|
+
case "accidental": {
|
|
1132
|
+
const accValue = extractText(c);
|
|
1133
|
+
if (isValidAccidental(accValue)) {
|
|
1134
|
+
const accInfo = { value: accValue };
|
|
1135
|
+
if (elAttrs["cautionary"] === "yes") accInfo.cautionary = true;
|
|
1136
|
+
if (elAttrs["editorial"] === "yes") accInfo.editorial = true;
|
|
1137
|
+
if (elAttrs["parentheses"] === "yes") accInfo.parentheses = true;
|
|
1138
|
+
if (elAttrs["bracket"] === "yes") accInfo.bracket = true;
|
|
1139
|
+
if (elAttrs["relative-x"]) accInfo.relativeX = parseFloat(elAttrs["relative-x"]);
|
|
1140
|
+
if (elAttrs["relative-y"]) accInfo.relativeY = parseFloat(elAttrs["relative-y"]);
|
|
1141
|
+
if (elAttrs["color"]) accInfo.color = elAttrs["color"];
|
|
1142
|
+
if (elAttrs["size"]) accInfo.size = elAttrs["size"];
|
|
1143
|
+
if (elAttrs["font-size"]) accInfo.fontSize = elAttrs["font-size"];
|
|
1144
|
+
note.accidental = accInfo;
|
|
1145
|
+
}
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
case "stem": {
|
|
1149
|
+
const stemValue = extractText(c);
|
|
1150
|
+
if (stemValue === "up" || stemValue === "down" || stemValue === "none" || stemValue === "double") {
|
|
1151
|
+
note.stem = { value: stemValue };
|
|
1152
|
+
if (elAttrs["default-x"]) note.stem.defaultX = parseFloat(elAttrs["default-x"]);
|
|
1153
|
+
if (elAttrs["default-y"]) note.stem.defaultY = parseFloat(elAttrs["default-y"]);
|
|
1154
|
+
}
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
case "notehead": {
|
|
1158
|
+
const nhValue = extractText(c);
|
|
1159
|
+
if (isValidNotehead(nhValue)) {
|
|
1160
|
+
const nhInfo = { value: nhValue };
|
|
1161
|
+
if (elAttrs["filled"] === "yes") nhInfo.filled = true;
|
|
1162
|
+
else if (elAttrs["filled"] === "no") nhInfo.filled = false;
|
|
1163
|
+
if (elAttrs["parentheses"] === "yes") nhInfo.parentheses = true;
|
|
1164
|
+
note.notehead = nhInfo;
|
|
1165
|
+
}
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
case "tie": {
|
|
1169
|
+
const t = elAttrs["type"];
|
|
1170
|
+
if (t === "start" || t === "stop" || t === "continue") {
|
|
1171
|
+
if (!tieElements) tieElements = [];
|
|
1172
|
+
tieElements.push({ type: t });
|
|
1173
|
+
}
|
|
1174
|
+
break;
|
|
1175
|
+
}
|
|
1176
|
+
case "beam": {
|
|
1177
|
+
if (!beams) beams = [];
|
|
1178
|
+
beams.push(parseBeam(c, elAttrs));
|
|
1179
|
+
break;
|
|
1180
|
+
}
|
|
1181
|
+
case "notations": {
|
|
1182
|
+
const parsedNotations = parseNotations(c, notationsIndex);
|
|
1183
|
+
if (parsedNotations.length > 0) {
|
|
1184
|
+
if (!allNotations) allNotations = [];
|
|
1185
|
+
for (let j = 0; j < parsedNotations.length; j++) allNotations.push(parsedNotations[j]);
|
|
1186
|
+
}
|
|
1187
|
+
notationsIndex++;
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
case "lyric": {
|
|
1191
|
+
if (!lyrics) lyrics = [];
|
|
1192
|
+
lyrics.push(parseLyric(c, elAttrs));
|
|
1193
|
+
break;
|
|
1194
|
+
}
|
|
1195
|
+
case "grace": {
|
|
1196
|
+
hasGrace = true;
|
|
1197
|
+
note.grace = {};
|
|
1198
|
+
if (elAttrs["slash"] === "yes") note.grace.slash = true;
|
|
1199
|
+
else if (elAttrs["slash"] === "no") note.grace.slash = false;
|
|
1200
|
+
if (elAttrs["steal-time-previous"]) {
|
|
1201
|
+
note.grace.stealTimePrevious = parseFloat(elAttrs["steal-time-previous"]);
|
|
1202
|
+
}
|
|
1203
|
+
if (elAttrs["steal-time-following"]) {
|
|
1204
|
+
note.grace.stealTimeFollowing = parseFloat(elAttrs["steal-time-following"]);
|
|
1205
|
+
}
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
case "time-modification": {
|
|
1209
|
+
const actualNotes = getElementText(c, "actual-notes");
|
|
1210
|
+
const normalNotes = getElementText(c, "normal-notes");
|
|
1211
|
+
const normalType = getElementText(c, "normal-type");
|
|
1212
|
+
note.timeModification = {
|
|
1213
|
+
actualNotes: parseInt(actualNotes || "3", 10),
|
|
1214
|
+
normalNotes: parseInt(normalNotes || "2", 10)
|
|
1215
|
+
};
|
|
1216
|
+
if (normalType && isValidNoteType(normalType)) {
|
|
1217
|
+
note.timeModification.normalType = normalType;
|
|
1218
|
+
}
|
|
1219
|
+
let ndCount = 0;
|
|
1220
|
+
for (const tm of c) {
|
|
1221
|
+
if (typeof tm !== "string" && tm.tagName === "normal-dot") ndCount++;
|
|
1222
|
+
}
|
|
1223
|
+
if (ndCount > 0) note.timeModification.normalDots = ndCount;
|
|
1224
|
+
break;
|
|
1225
|
+
}
|
|
1081
1226
|
}
|
|
1082
1227
|
}
|
|
1083
|
-
parseFirstElement(elements, "unpitched", (c) => {
|
|
1084
|
-
note.unpitched = {};
|
|
1085
|
-
const displayStep = getElementText(c, "display-step");
|
|
1086
|
-
if (displayStep) note.unpitched.displayStep = displayStep;
|
|
1087
|
-
const displayOctave = getElementText(c, "display-octave");
|
|
1088
|
-
if (displayOctave) note.unpitched.displayOctave = parseInt(displayOctave, 10);
|
|
1089
|
-
});
|
|
1090
|
-
const staff = getElementTextAsInt(elements, "staff");
|
|
1091
|
-
if (staff !== void 0) note.staff = staff;
|
|
1092
|
-
if (hasElement(elements, "chord")) {
|
|
1093
|
-
note.chord = true;
|
|
1094
|
-
}
|
|
1095
|
-
parseFirstElement(elements, "type", (c, a) => {
|
|
1096
|
-
const noteType = extractText(c);
|
|
1097
|
-
if (isValidNoteType(noteType)) note.noteType = noteType;
|
|
1098
|
-
if (a["size"]) note.noteTypeSize = a["size"];
|
|
1099
|
-
});
|
|
1100
|
-
const dotCount = elements.filter((el) => typeof el !== "string" && el.tagName === "dot").length;
|
|
1101
1228
|
if (dotCount > 0) note.dots = dotCount;
|
|
1102
|
-
|
|
1103
|
-
const accValue = extractText(c);
|
|
1104
|
-
if (isValidAccidental(accValue)) {
|
|
1105
|
-
const accInfo = { value: accValue };
|
|
1106
|
-
if (a["cautionary"] === "yes") accInfo.cautionary = true;
|
|
1107
|
-
if (a["editorial"] === "yes") accInfo.editorial = true;
|
|
1108
|
-
if (a["parentheses"] === "yes") accInfo.parentheses = true;
|
|
1109
|
-
if (a["bracket"] === "yes") accInfo.bracket = true;
|
|
1110
|
-
if (a["relative-x"]) accInfo.relativeX = parseFloat(a["relative-x"]);
|
|
1111
|
-
if (a["relative-y"]) accInfo.relativeY = parseFloat(a["relative-y"]);
|
|
1112
|
-
if (a["color"]) accInfo.color = a["color"];
|
|
1113
|
-
if (a["size"]) accInfo.size = a["size"];
|
|
1114
|
-
if (a["font-size"]) accInfo.fontSize = a["font-size"];
|
|
1115
|
-
note.accidental = accInfo;
|
|
1116
|
-
}
|
|
1117
|
-
});
|
|
1118
|
-
parseFirstElement(elements, "stem", (c, a) => {
|
|
1119
|
-
const stemValue = extractText(c);
|
|
1120
|
-
if (stemValue === "up" || stemValue === "down" || stemValue === "none" || stemValue === "double") {
|
|
1121
|
-
note.stem = { value: stemValue };
|
|
1122
|
-
if (a["default-x"]) note.stem.defaultX = parseFloat(a["default-x"]);
|
|
1123
|
-
if (a["default-y"]) note.stem.defaultY = parseFloat(a["default-y"]);
|
|
1124
|
-
}
|
|
1125
|
-
});
|
|
1126
|
-
parseFirstElement(elements, "notehead", (c, a) => {
|
|
1127
|
-
const nhValue = extractText(c);
|
|
1128
|
-
if (isValidNotehead(nhValue)) {
|
|
1129
|
-
const nhInfo = { value: nhValue };
|
|
1130
|
-
if (a["filled"] === "yes") nhInfo.filled = true;
|
|
1131
|
-
else if (a["filled"] === "no") nhInfo.filled = false;
|
|
1132
|
-
if (a["parentheses"] === "yes") nhInfo.parentheses = true;
|
|
1133
|
-
note.notehead = nhInfo;
|
|
1134
|
-
}
|
|
1135
|
-
});
|
|
1136
|
-
const tieElements = collectElements(elements, "tie", (_, a) => {
|
|
1137
|
-
const t = a["type"];
|
|
1138
|
-
return t === "start" || t === "stop" || t === "continue" ? { type: t } : null;
|
|
1139
|
-
}).filter((t) => t !== null);
|
|
1140
|
-
if (tieElements.length > 0) {
|
|
1229
|
+
if (tieElements) {
|
|
1141
1230
|
note.tie = tieElements[0];
|
|
1142
1231
|
if (tieElements.length > 1) note.ties = tieElements;
|
|
1143
1232
|
}
|
|
1144
|
-
|
|
1145
|
-
if (
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
for (const el of elements) {
|
|
1149
|
-
if (typeof el === "string") continue;
|
|
1150
|
-
if (el.tagName === "notations") {
|
|
1151
|
-
const parsedNotations = parseNotations(el.children, notationsIndex);
|
|
1152
|
-
allNotations.push(...parsedNotations);
|
|
1153
|
-
notationsIndex++;
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
if (allNotations.length > 0) {
|
|
1157
|
-
note.notations = allNotations;
|
|
1158
|
-
}
|
|
1159
|
-
const lyrics = [];
|
|
1160
|
-
for (const el of elements) {
|
|
1161
|
-
if (typeof el === "string") continue;
|
|
1162
|
-
if (el.tagName === "lyric") {
|
|
1163
|
-
lyrics.push(parseLyric(el.children, el.attributes));
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
if (lyrics.length > 0) note.lyrics = lyrics;
|
|
1167
|
-
for (const el of elements) {
|
|
1168
|
-
if (typeof el === "string") continue;
|
|
1169
|
-
if (el.tagName === "grace") {
|
|
1170
|
-
const graceAttrs = el.attributes;
|
|
1171
|
-
note.grace = {};
|
|
1172
|
-
if (graceAttrs["slash"] === "yes") note.grace.slash = true;
|
|
1173
|
-
else if (graceAttrs["slash"] === "no") note.grace.slash = false;
|
|
1174
|
-
if (graceAttrs["steal-time-previous"]) {
|
|
1175
|
-
note.grace.stealTimePrevious = parseFloat(graceAttrs["steal-time-previous"]);
|
|
1176
|
-
}
|
|
1177
|
-
if (graceAttrs["steal-time-following"]) {
|
|
1178
|
-
note.grace.stealTimeFollowing = parseFloat(graceAttrs["steal-time-following"]);
|
|
1179
|
-
}
|
|
1180
|
-
note.duration = 0;
|
|
1181
|
-
break;
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
const timeMod = getElementContent(elements, "time-modification");
|
|
1185
|
-
if (timeMod) {
|
|
1186
|
-
const actualNotes = getElementText(timeMod, "actual-notes");
|
|
1187
|
-
const normalNotes = getElementText(timeMod, "normal-notes");
|
|
1188
|
-
const normalType = getElementText(timeMod, "normal-type");
|
|
1189
|
-
note.timeModification = {
|
|
1190
|
-
actualNotes: parseInt(actualNotes || "3", 10),
|
|
1191
|
-
normalNotes: parseInt(normalNotes || "2", 10)
|
|
1192
|
-
};
|
|
1193
|
-
if (normalType && isValidNoteType(normalType)) {
|
|
1194
|
-
note.timeModification.normalType = normalType;
|
|
1195
|
-
}
|
|
1196
|
-
let dotCount2 = 0;
|
|
1197
|
-
for (const tm of timeMod) {
|
|
1198
|
-
if (typeof tm !== "string" && tm.tagName === "normal-dot") dotCount2++;
|
|
1199
|
-
}
|
|
1200
|
-
if (dotCount2 > 0) note.timeModification.normalDots = dotCount2;
|
|
1201
|
-
}
|
|
1233
|
+
if (beams) note.beam = beams;
|
|
1234
|
+
if (allNotations) note.notations = allNotations;
|
|
1235
|
+
if (lyrics) note.lyrics = lyrics;
|
|
1236
|
+
if (hasGrace) note.duration = 0;
|
|
1202
1237
|
return note;
|
|
1203
1238
|
}
|
|
1204
1239
|
function parsePitch(elements) {
|
package/dist/index.mjs
CHANGED
|
@@ -214,9 +214,14 @@ import {
|
|
|
214
214
|
|
|
215
215
|
// src/importers/musicxml.ts
|
|
216
216
|
import { parse as txmlParse } from "txml";
|
|
217
|
+
var _entityMap = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
|
|
218
|
+
var _entityRegex = /&(?:(amp|lt|gt|quot|apos)|#(\d+)|#x([0-9a-fA-F]+));/g;
|
|
217
219
|
function decodeXmlEntities(s) {
|
|
218
220
|
if (s.indexOf("&") === -1) return s;
|
|
219
|
-
return s.replace(
|
|
221
|
+
return s.replace(
|
|
222
|
+
_entityRegex,
|
|
223
|
+
(_, named, dec, hex) => named ? _entityMap[named] : dec ? String.fromCharCode(parseInt(dec, 10)) : String.fromCharCode(parseInt(hex, 16))
|
|
224
|
+
);
|
|
220
225
|
}
|
|
221
226
|
function decodeTree(nodes) {
|
|
222
227
|
for (let i = 0; i < nodes.length; i++) {
|
|
@@ -1040,12 +1045,8 @@ function parseNote(elements, attrs) {
|
|
|
1040
1045
|
const note = {
|
|
1041
1046
|
_id: generateId(),
|
|
1042
1047
|
type: "note",
|
|
1043
|
-
duration:
|
|
1048
|
+
duration: 0
|
|
1044
1049
|
};
|
|
1045
|
-
const voiceValue = getElementText(elements, "voice");
|
|
1046
|
-
if (voiceValue !== void 0 && voiceValue !== "") {
|
|
1047
|
-
note.voice = voiceValue;
|
|
1048
|
-
}
|
|
1049
1050
|
if (attrs["default-x"]) note.defaultX = parseFloat(attrs["default-x"]);
|
|
1050
1051
|
if (attrs["default-y"]) note.defaultY = parseFloat(attrs["default-y"]);
|
|
1051
1052
|
if (attrs["relative-x"]) note.relativeX = parseFloat(attrs["relative-x"]);
|
|
@@ -1056,149 +1057,183 @@ function parseNote(elements, attrs) {
|
|
|
1056
1057
|
if (attrs["print-dot"] === "yes") note.printDot = true;
|
|
1057
1058
|
if (attrs["print-spacing"] === "yes") note.printSpacing = true;
|
|
1058
1059
|
if (attrs["print-spacing"] === "no") note.printSpacing = false;
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
for (const el of elements) {
|
|
1060
|
+
let dotCount = 0;
|
|
1061
|
+
let notationsIndex = 0;
|
|
1062
|
+
let tieElements;
|
|
1063
|
+
let beams;
|
|
1064
|
+
let allNotations;
|
|
1065
|
+
let lyrics;
|
|
1066
|
+
let hasGrace = false;
|
|
1067
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1068
|
+
const el = elements[i];
|
|
1069
1069
|
if (typeof el === "string") continue;
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1070
|
+
const tag = el.tagName;
|
|
1071
|
+
const elAttrs = el.attributes;
|
|
1072
|
+
const c = el.children;
|
|
1073
|
+
switch (tag) {
|
|
1074
|
+
case "duration": {
|
|
1075
|
+
const text = extractText(c);
|
|
1076
|
+
if (text) note.duration = parseInt(text, 10) || 0;
|
|
1077
|
+
break;
|
|
1078
|
+
}
|
|
1079
|
+
case "voice": {
|
|
1080
|
+
const text = extractText(c);
|
|
1081
|
+
if (text) note.voice = text;
|
|
1082
|
+
break;
|
|
1083
|
+
}
|
|
1084
|
+
case "cue":
|
|
1085
|
+
note.cue = true;
|
|
1086
|
+
break;
|
|
1087
|
+
case "chord":
|
|
1088
|
+
note.chord = true;
|
|
1089
|
+
break;
|
|
1090
|
+
case "dot":
|
|
1091
|
+
dotCount++;
|
|
1092
|
+
break;
|
|
1093
|
+
case "instrument":
|
|
1094
|
+
if (elAttrs["id"]) note.instrument = elAttrs["id"];
|
|
1095
|
+
break;
|
|
1096
|
+
case "pitch":
|
|
1097
|
+
note.pitch = parsePitch(c);
|
|
1098
|
+
break;
|
|
1099
|
+
case "rest": {
|
|
1100
|
+
const restInfo = {};
|
|
1101
|
+
if (elAttrs["measure"] === "yes") restInfo.measure = true;
|
|
1102
|
+
const displayStep = getElementText(c, "display-step");
|
|
1103
|
+
if (displayStep) restInfo.displayStep = displayStep;
|
|
1104
|
+
const displayOctave = getElementText(c, "display-octave");
|
|
1105
|
+
if (displayOctave) restInfo.displayOctave = parseInt(displayOctave, 10);
|
|
1106
|
+
note.rest = restInfo;
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
case "unpitched": {
|
|
1110
|
+
note.unpitched = {};
|
|
1111
|
+
const displayStep = getElementText(c, "display-step");
|
|
1112
|
+
if (displayStep) note.unpitched.displayStep = displayStep;
|
|
1113
|
+
const displayOctave = getElementText(c, "display-octave");
|
|
1114
|
+
if (displayOctave) note.unpitched.displayOctave = parseInt(displayOctave, 10);
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
case "staff": {
|
|
1118
|
+
const text = extractText(c);
|
|
1119
|
+
if (text) {
|
|
1120
|
+
const v = parseInt(text, 10);
|
|
1121
|
+
if (!isNaN(v)) note.staff = v;
|
|
1122
|
+
}
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
case "type": {
|
|
1126
|
+
const noteType = extractText(c);
|
|
1127
|
+
if (isValidNoteType(noteType)) note.noteType = noteType;
|
|
1128
|
+
if (elAttrs["size"]) note.noteTypeSize = elAttrs["size"];
|
|
1129
|
+
break;
|
|
1130
|
+
}
|
|
1131
|
+
case "accidental": {
|
|
1132
|
+
const accValue = extractText(c);
|
|
1133
|
+
if (isValidAccidental(accValue)) {
|
|
1134
|
+
const accInfo = { value: accValue };
|
|
1135
|
+
if (elAttrs["cautionary"] === "yes") accInfo.cautionary = true;
|
|
1136
|
+
if (elAttrs["editorial"] === "yes") accInfo.editorial = true;
|
|
1137
|
+
if (elAttrs["parentheses"] === "yes") accInfo.parentheses = true;
|
|
1138
|
+
if (elAttrs["bracket"] === "yes") accInfo.bracket = true;
|
|
1139
|
+
if (elAttrs["relative-x"]) accInfo.relativeX = parseFloat(elAttrs["relative-x"]);
|
|
1140
|
+
if (elAttrs["relative-y"]) accInfo.relativeY = parseFloat(elAttrs["relative-y"]);
|
|
1141
|
+
if (elAttrs["color"]) accInfo.color = elAttrs["color"];
|
|
1142
|
+
if (elAttrs["size"]) accInfo.size = elAttrs["size"];
|
|
1143
|
+
if (elAttrs["font-size"]) accInfo.fontSize = elAttrs["font-size"];
|
|
1144
|
+
note.accidental = accInfo;
|
|
1145
|
+
}
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
case "stem": {
|
|
1149
|
+
const stemValue = extractText(c);
|
|
1150
|
+
if (stemValue === "up" || stemValue === "down" || stemValue === "none" || stemValue === "double") {
|
|
1151
|
+
note.stem = { value: stemValue };
|
|
1152
|
+
if (elAttrs["default-x"]) note.stem.defaultX = parseFloat(elAttrs["default-x"]);
|
|
1153
|
+
if (elAttrs["default-y"]) note.stem.defaultY = parseFloat(elAttrs["default-y"]);
|
|
1154
|
+
}
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
case "notehead": {
|
|
1158
|
+
const nhValue = extractText(c);
|
|
1159
|
+
if (isValidNotehead(nhValue)) {
|
|
1160
|
+
const nhInfo = { value: nhValue };
|
|
1161
|
+
if (elAttrs["filled"] === "yes") nhInfo.filled = true;
|
|
1162
|
+
else if (elAttrs["filled"] === "no") nhInfo.filled = false;
|
|
1163
|
+
if (elAttrs["parentheses"] === "yes") nhInfo.parentheses = true;
|
|
1164
|
+
note.notehead = nhInfo;
|
|
1165
|
+
}
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
case "tie": {
|
|
1169
|
+
const t = elAttrs["type"];
|
|
1170
|
+
if (t === "start" || t === "stop" || t === "continue") {
|
|
1171
|
+
if (!tieElements) tieElements = [];
|
|
1172
|
+
tieElements.push({ type: t });
|
|
1173
|
+
}
|
|
1174
|
+
break;
|
|
1175
|
+
}
|
|
1176
|
+
case "beam": {
|
|
1177
|
+
if (!beams) beams = [];
|
|
1178
|
+
beams.push(parseBeam(c, elAttrs));
|
|
1179
|
+
break;
|
|
1180
|
+
}
|
|
1181
|
+
case "notations": {
|
|
1182
|
+
const parsedNotations = parseNotations(c, notationsIndex);
|
|
1183
|
+
if (parsedNotations.length > 0) {
|
|
1184
|
+
if (!allNotations) allNotations = [];
|
|
1185
|
+
for (let j = 0; j < parsedNotations.length; j++) allNotations.push(parsedNotations[j]);
|
|
1186
|
+
}
|
|
1187
|
+
notationsIndex++;
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
case "lyric": {
|
|
1191
|
+
if (!lyrics) lyrics = [];
|
|
1192
|
+
lyrics.push(parseLyric(c, elAttrs));
|
|
1193
|
+
break;
|
|
1194
|
+
}
|
|
1195
|
+
case "grace": {
|
|
1196
|
+
hasGrace = true;
|
|
1197
|
+
note.grace = {};
|
|
1198
|
+
if (elAttrs["slash"] === "yes") note.grace.slash = true;
|
|
1199
|
+
else if (elAttrs["slash"] === "no") note.grace.slash = false;
|
|
1200
|
+
if (elAttrs["steal-time-previous"]) {
|
|
1201
|
+
note.grace.stealTimePrevious = parseFloat(elAttrs["steal-time-previous"]);
|
|
1202
|
+
}
|
|
1203
|
+
if (elAttrs["steal-time-following"]) {
|
|
1204
|
+
note.grace.stealTimeFollowing = parseFloat(elAttrs["steal-time-following"]);
|
|
1205
|
+
}
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
case "time-modification": {
|
|
1209
|
+
const actualNotes = getElementText(c, "actual-notes");
|
|
1210
|
+
const normalNotes = getElementText(c, "normal-notes");
|
|
1211
|
+
const normalType = getElementText(c, "normal-type");
|
|
1212
|
+
note.timeModification = {
|
|
1213
|
+
actualNotes: parseInt(actualNotes || "3", 10),
|
|
1214
|
+
normalNotes: parseInt(normalNotes || "2", 10)
|
|
1215
|
+
};
|
|
1216
|
+
if (normalType && isValidNoteType(normalType)) {
|
|
1217
|
+
note.timeModification.normalType = normalType;
|
|
1218
|
+
}
|
|
1219
|
+
let ndCount = 0;
|
|
1220
|
+
for (const tm of c) {
|
|
1221
|
+
if (typeof tm !== "string" && tm.tagName === "normal-dot") ndCount++;
|
|
1222
|
+
}
|
|
1223
|
+
if (ndCount > 0) note.timeModification.normalDots = ndCount;
|
|
1224
|
+
break;
|
|
1225
|
+
}
|
|
1081
1226
|
}
|
|
1082
1227
|
}
|
|
1083
|
-
parseFirstElement(elements, "unpitched", (c) => {
|
|
1084
|
-
note.unpitched = {};
|
|
1085
|
-
const displayStep = getElementText(c, "display-step");
|
|
1086
|
-
if (displayStep) note.unpitched.displayStep = displayStep;
|
|
1087
|
-
const displayOctave = getElementText(c, "display-octave");
|
|
1088
|
-
if (displayOctave) note.unpitched.displayOctave = parseInt(displayOctave, 10);
|
|
1089
|
-
});
|
|
1090
|
-
const staff = getElementTextAsInt(elements, "staff");
|
|
1091
|
-
if (staff !== void 0) note.staff = staff;
|
|
1092
|
-
if (hasElement(elements, "chord")) {
|
|
1093
|
-
note.chord = true;
|
|
1094
|
-
}
|
|
1095
|
-
parseFirstElement(elements, "type", (c, a) => {
|
|
1096
|
-
const noteType = extractText(c);
|
|
1097
|
-
if (isValidNoteType(noteType)) note.noteType = noteType;
|
|
1098
|
-
if (a["size"]) note.noteTypeSize = a["size"];
|
|
1099
|
-
});
|
|
1100
|
-
const dotCount = elements.filter((el) => typeof el !== "string" && el.tagName === "dot").length;
|
|
1101
1228
|
if (dotCount > 0) note.dots = dotCount;
|
|
1102
|
-
|
|
1103
|
-
const accValue = extractText(c);
|
|
1104
|
-
if (isValidAccidental(accValue)) {
|
|
1105
|
-
const accInfo = { value: accValue };
|
|
1106
|
-
if (a["cautionary"] === "yes") accInfo.cautionary = true;
|
|
1107
|
-
if (a["editorial"] === "yes") accInfo.editorial = true;
|
|
1108
|
-
if (a["parentheses"] === "yes") accInfo.parentheses = true;
|
|
1109
|
-
if (a["bracket"] === "yes") accInfo.bracket = true;
|
|
1110
|
-
if (a["relative-x"]) accInfo.relativeX = parseFloat(a["relative-x"]);
|
|
1111
|
-
if (a["relative-y"]) accInfo.relativeY = parseFloat(a["relative-y"]);
|
|
1112
|
-
if (a["color"]) accInfo.color = a["color"];
|
|
1113
|
-
if (a["size"]) accInfo.size = a["size"];
|
|
1114
|
-
if (a["font-size"]) accInfo.fontSize = a["font-size"];
|
|
1115
|
-
note.accidental = accInfo;
|
|
1116
|
-
}
|
|
1117
|
-
});
|
|
1118
|
-
parseFirstElement(elements, "stem", (c, a) => {
|
|
1119
|
-
const stemValue = extractText(c);
|
|
1120
|
-
if (stemValue === "up" || stemValue === "down" || stemValue === "none" || stemValue === "double") {
|
|
1121
|
-
note.stem = { value: stemValue };
|
|
1122
|
-
if (a["default-x"]) note.stem.defaultX = parseFloat(a["default-x"]);
|
|
1123
|
-
if (a["default-y"]) note.stem.defaultY = parseFloat(a["default-y"]);
|
|
1124
|
-
}
|
|
1125
|
-
});
|
|
1126
|
-
parseFirstElement(elements, "notehead", (c, a) => {
|
|
1127
|
-
const nhValue = extractText(c);
|
|
1128
|
-
if (isValidNotehead(nhValue)) {
|
|
1129
|
-
const nhInfo = { value: nhValue };
|
|
1130
|
-
if (a["filled"] === "yes") nhInfo.filled = true;
|
|
1131
|
-
else if (a["filled"] === "no") nhInfo.filled = false;
|
|
1132
|
-
if (a["parentheses"] === "yes") nhInfo.parentheses = true;
|
|
1133
|
-
note.notehead = nhInfo;
|
|
1134
|
-
}
|
|
1135
|
-
});
|
|
1136
|
-
const tieElements = collectElements(elements, "tie", (_, a) => {
|
|
1137
|
-
const t = a["type"];
|
|
1138
|
-
return t === "start" || t === "stop" || t === "continue" ? { type: t } : null;
|
|
1139
|
-
}).filter((t) => t !== null);
|
|
1140
|
-
if (tieElements.length > 0) {
|
|
1229
|
+
if (tieElements) {
|
|
1141
1230
|
note.tie = tieElements[0];
|
|
1142
1231
|
if (tieElements.length > 1) note.ties = tieElements;
|
|
1143
1232
|
}
|
|
1144
|
-
|
|
1145
|
-
if (
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
for (const el of elements) {
|
|
1149
|
-
if (typeof el === "string") continue;
|
|
1150
|
-
if (el.tagName === "notations") {
|
|
1151
|
-
const parsedNotations = parseNotations(el.children, notationsIndex);
|
|
1152
|
-
allNotations.push(...parsedNotations);
|
|
1153
|
-
notationsIndex++;
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
if (allNotations.length > 0) {
|
|
1157
|
-
note.notations = allNotations;
|
|
1158
|
-
}
|
|
1159
|
-
const lyrics = [];
|
|
1160
|
-
for (const el of elements) {
|
|
1161
|
-
if (typeof el === "string") continue;
|
|
1162
|
-
if (el.tagName === "lyric") {
|
|
1163
|
-
lyrics.push(parseLyric(el.children, el.attributes));
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
if (lyrics.length > 0) note.lyrics = lyrics;
|
|
1167
|
-
for (const el of elements) {
|
|
1168
|
-
if (typeof el === "string") continue;
|
|
1169
|
-
if (el.tagName === "grace") {
|
|
1170
|
-
const graceAttrs = el.attributes;
|
|
1171
|
-
note.grace = {};
|
|
1172
|
-
if (graceAttrs["slash"] === "yes") note.grace.slash = true;
|
|
1173
|
-
else if (graceAttrs["slash"] === "no") note.grace.slash = false;
|
|
1174
|
-
if (graceAttrs["steal-time-previous"]) {
|
|
1175
|
-
note.grace.stealTimePrevious = parseFloat(graceAttrs["steal-time-previous"]);
|
|
1176
|
-
}
|
|
1177
|
-
if (graceAttrs["steal-time-following"]) {
|
|
1178
|
-
note.grace.stealTimeFollowing = parseFloat(graceAttrs["steal-time-following"]);
|
|
1179
|
-
}
|
|
1180
|
-
note.duration = 0;
|
|
1181
|
-
break;
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
const timeMod = getElementContent(elements, "time-modification");
|
|
1185
|
-
if (timeMod) {
|
|
1186
|
-
const actualNotes = getElementText(timeMod, "actual-notes");
|
|
1187
|
-
const normalNotes = getElementText(timeMod, "normal-notes");
|
|
1188
|
-
const normalType = getElementText(timeMod, "normal-type");
|
|
1189
|
-
note.timeModification = {
|
|
1190
|
-
actualNotes: parseInt(actualNotes || "3", 10),
|
|
1191
|
-
normalNotes: parseInt(normalNotes || "2", 10)
|
|
1192
|
-
};
|
|
1193
|
-
if (normalType && isValidNoteType(normalType)) {
|
|
1194
|
-
note.timeModification.normalType = normalType;
|
|
1195
|
-
}
|
|
1196
|
-
let dotCount2 = 0;
|
|
1197
|
-
for (const tm of timeMod) {
|
|
1198
|
-
if (typeof tm !== "string" && tm.tagName === "normal-dot") dotCount2++;
|
|
1199
|
-
}
|
|
1200
|
-
if (dotCount2 > 0) note.timeModification.normalDots = dotCount2;
|
|
1201
|
-
}
|
|
1233
|
+
if (beams) note.beam = beams;
|
|
1234
|
+
if (allNotations) note.notations = allNotations;
|
|
1235
|
+
if (lyrics) note.lyrics = lyrics;
|
|
1236
|
+
if (hasGrace) note.duration = 0;
|
|
1202
1237
|
return note;
|
|
1203
1238
|
}
|
|
1204
1239
|
function parsePitch(elements) {
|