vibe-editor 0.0.4 → 0.0.5
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/package.json +65 -61
- package/src/scripts/js/Core.js +28 -9
- package/src/scripts/js/entry.js +6 -5
- package/src/scripts/js/gui/Annotations.js +27 -12
- package/src/scripts/js/gui/ScoreManipulator.js +6 -4
- package/src/scripts/js/gui/Tabbar.js +13 -4
- package/src/scripts/js/handlers/AnnotationChangeHandler.js +13 -1
- package/src/scripts/js/handlers/InsertModeHandler.js +3 -3
- package/src/scripts/js/handlers/PhantomElementHandler.js +3 -10
- package/src/scripts/js/handlers/WindowHandler.js +7 -7
- package/src/scripts/js/scripts/Core.js +932 -0
- package/src/scripts/js/scripts/MusicProcessor.js +810 -0
- package/src/scripts/js/scripts/VIBE.js +219 -0
- package/src/scripts/js/scripts/datastructures/MeasureMatrix.js +156 -0
- package/src/scripts/js/scripts/gui/Annotations.js +549 -0
- package/src/scripts/js/scripts/gui/Cursor.js +203 -0
- package/src/scripts/js/scripts/gui/PhantomElement.js +132 -0
- package/src/scripts/js/scripts/gui/ScoreManipulator.js +188 -0
- package/src/scripts/js/scripts/gui/Tabbar.js +705 -0
- package/src/scripts/js/{gui/Toolbar copy.js → scripts/gui/Toolbar.js} +15 -11
- package/src/scripts/js/scripts/handlers/AnnotationChangeHandler.js +650 -0
- package/src/scripts/js/scripts/handlers/ClickModeHandler.js +535 -0
- package/src/scripts/js/{gui → scripts/handlers}/CustomAnnotationShapeDrawer.js +34 -17
- package/src/scripts/js/{handlers/ModHandler.js → scripts/handlers/CustomToolbarHandler.js} +54 -66
- package/src/scripts/js/scripts/handlers/GlobalKeyboardHandler.js +372 -0
- package/src/scripts/js/scripts/handlers/Handler.js +2 -0
- package/src/scripts/js/{handlers/InsertModeHandler_deprecated.js → scripts/handlers/InsertModeHandler.js} +117 -164
- package/src/scripts/js/scripts/handlers/KeyModeHandler.js +405 -0
- package/src/scripts/js/scripts/handlers/LabelHandler.js +463 -0
- package/src/scripts/js/scripts/handlers/NoteDragHandler.js +97 -0
- package/src/scripts/js/scripts/handlers/PhantomElementHandler.js +168 -0
- package/src/scripts/js/scripts/handlers/ScoreManipulatorHandler.js +233 -0
- package/src/scripts/js/scripts/handlers/SidebarHandler.js +506 -0
- package/src/scripts/js/scripts/handlers/TooltipHandler.js +132 -0
- package/src/scripts/js/scripts/handlers/WindowHandler.js +278 -0
- package/src/scripts/js/scripts/utils/MEIOperations.js +2121 -0
- package/src/scripts/js/{utils/Mouse2MEI.js → scripts/utils/Mouse2SVG.js} +225 -57
- package/src/scripts/js/scripts/utils/SVGEditor.js +453 -0
- package/src/scripts/js/scripts/utils/Types.js +2 -0
- package/src/scripts/js/{utils/VerovioWrapper copy.js → scripts/utils/VerovioWrapper.js} +35 -21
- package/src/scripts/js/scripts/utils/coordinates.js +54 -0
- package/src/scripts/js/utils/Mouse2SVG.js +11 -4
- package/src/scripts/js/utils/VerovioWrapper.js +4 -4
- package/src/scripts/js/utils/coordinates.js +26 -2
- package/src/scripts/js/.DS_Store +0 -0
- package/src/scripts/js/MusicPlayer.js +0 -572
- package/src/scripts/js/datastructures/ScoreGraph copy.js +0 -432
- package/src/scripts/js/gui/CustomAnnotationDrawer.js +0 -114
- package/src/scripts/js/handlers/AnnotationDragHandler.js +0 -113
- package/src/scripts/js/handlers/AnnotationLineHandler.js +0 -113
- package/src/scripts/js/handlers/ArticulationHandler.js +0 -20
- package/src/scripts/js/handlers/HarmonyHandler.js +0 -282
- package/src/scripts/js/handlers/InsertModeHandler copy.js +0 -423
- package/src/scripts/js/handlers/KeyModeHandler copy.js +0 -407
- package/src/scripts/js/handlers/KeyModeHandler_deprecated.js +0 -411
- package/src/scripts/js/handlers/NoteDragHandler copy.js +0 -148
- package/src/scripts/js/handlers/NoteDragHandler_deprecated.js +0 -150
- package/src/scripts/js/handlers/SelectionHandler.js +0 -262
- package/src/scripts/js/utils/RectWrapper.js +0 -10
- package/src/scripts/js/utils/SVGFiller.js +0 -245
- package/src/scripts/js/utils/VerovioWrapperLocal.js +0 -156
- package/src/scripts/js/utils/firefoxBBoxes.js +0 -143
- package/src/styles/vibe.css +0 -785
- /package/src/scripts/js/{assets → scripts/assets}/mei_template.js +0 -0
- /package/src/scripts/js/{constants.js → scripts/constants.js} +0 -0
- /package/src/scripts/js/{datastructures → scripts/datastructures}/ScoreGraph.js +0 -0
- /package/src/scripts/js/{datastructures → scripts/datastructures}/ScoreGraph_deprecated.js +0 -0
- /package/src/scripts/js/{datastructures → scripts/datastructures}/ScoreNode.js +0 -0
- /package/src/scripts/js/{gui → scripts/gui}/HarmonyLabel.js +0 -0
- /package/src/scripts/js/{gui → scripts/gui}/Label.js +0 -0
- /package/src/scripts/js/{gui → scripts/gui}/TempoLabel.js +0 -0
- /package/src/scripts/js/{handlers → scripts/handlers}/DeleteHandler.js +0 -0
- /package/src/scripts/js/{utils → scripts/utils}/DOMCreator.js +0 -0
- /package/src/scripts/js/{utils → scripts/utils}/MEIConverter.js +0 -0
- /package/src/scripts/js/{utils → scripts/utils}/ReactWrapper.js +0 -0
- /package/src/scripts/js/{utils → scripts/utils}/convenienceQueries.js +0 -0
- /package/src/scripts/js/{utils → scripts/utils}/mappings.js +0 -0
- /package/src/scripts/js/{utils → scripts/utils}/random.js +0 -0
@@ -12,9 +12,9 @@ class VerovioWrapper {
|
|
12
12
|
//@ts-ignore
|
13
13
|
this.vrvToolkit = new verovio.toolkit() || null;
|
14
14
|
this.r = 1;
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
if (this.isRetina()) {
|
16
|
+
this.r = 2;
|
17
|
+
}
|
18
18
|
this.widthValue = 1500;
|
19
19
|
var pageWidth = (this.widthValue / (window.devicePixelRatio / this.r)) / (screen.availHeight / window.innerWidth);
|
20
20
|
this.options = {
|
@@ -24,7 +24,7 @@ class VerovioWrapper {
|
|
24
24
|
pageMarginTop: 50,
|
25
25
|
adjustPageHeight: true,
|
26
26
|
font: 'Bravura',
|
27
|
-
pageWidth: pageWidth,
|
27
|
+
//pageWidth: pageWidth, // adjust size with window size
|
28
28
|
//pageHeight: pageWidth / 4,
|
29
29
|
//justifyVertically: true,
|
30
30
|
svgViewBox: true,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.transformToDOMMatrixCoordinates = exports.getDOMMatrixCoordinates = void 0;
|
3
|
+
exports.transformToDOMMatrixCoordinates = exports.getCanvasCordinates = exports.getDOMMatrixCoordinates = void 0;
|
4
4
|
/**
|
5
5
|
* Get DOMMatrix coordnates of element according to parent canvas class. Returns null if no canvas is found. If element is DOMRect, canvas must be provided
|
6
6
|
* @param element
|
@@ -33,9 +33,33 @@ function getDOMMatrixCoordinates(element, canvas = null) {
|
|
33
33
|
ptRB = ptRB.matrixTransform(canvasMatrix);
|
34
34
|
var width = ptRB.x - ptLT.x;
|
35
35
|
var height = ptRB.y - ptLT.y;
|
36
|
-
return { left: ptLT.x, top: ptLT.y, right: ptRB.x, bottom: ptRB.y, width: width, height: height, x: ptLT.x, y: ptLT.y };
|
36
|
+
return { left: ptLT.x, top: ptLT.y, right: ptRB.x, bottom: ptRB.y, width: width, height: height, x: ptLT.x, y: ptLT.y, matrix: canvasMatrix };
|
37
37
|
}
|
38
38
|
exports.getDOMMatrixCoordinates = getDOMMatrixCoordinates;
|
39
|
+
function getCanvasCordinates(coords, canvas = null) {
|
40
|
+
if (!coords.matrix) {
|
41
|
+
throw new Error("DOMMatrix is missing.");
|
42
|
+
}
|
43
|
+
if (canvas === null) {
|
44
|
+
canvas = canvas instanceof Element ? canvas.closest(".canvas") : null;
|
45
|
+
if (canvas instanceof DOMRect) {
|
46
|
+
throw new Error("Canvas must be provided, if input is instance of DOMRect. Actual instance: " + canvas.constructor.name);
|
47
|
+
}
|
48
|
+
if (canvas === null)
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
// Reverse the transformation
|
52
|
+
var canvasMatrix = coords.matrix.inverse();
|
53
|
+
var ptLT = new DOMPoint(coords.left, coords.top);
|
54
|
+
ptLT = ptLT.matrixTransform(canvasMatrix);
|
55
|
+
var ptRB = new DOMPoint(coords.right, coords.bottom);
|
56
|
+
ptRB = ptRB.matrixTransform(canvasMatrix);
|
57
|
+
var width = ptRB.x - ptLT.x;
|
58
|
+
var height = ptRB.y - ptLT.y;
|
59
|
+
// Create and return the DOMRect
|
60
|
+
return new DOMRect(ptLT.x, ptLT.y, width, height);
|
61
|
+
}
|
62
|
+
exports.getCanvasCordinates = getCanvasCordinates;
|
39
63
|
/**
|
40
64
|
* Transforms the given coordinates for a given canvas
|
41
65
|
* @param x
|
package/src/scripts/js/.DS_Store
DELETED
Binary file
|
@@ -1,572 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const Tone = require("tone");
|
4
|
-
const mappings_1 = require("./utils/mappings");
|
5
|
-
const midi_player_js_1 = require("midi-player-js");
|
6
|
-
const Soundfont = require("soundfont-player");
|
7
|
-
const constants_1 = require("./constants");
|
8
|
-
const coordinates = require("./utils/coordinates");
|
9
|
-
const cq = require("./utils/convenienceQueries");
|
10
|
-
const buffer_1 = require("buffer");
|
11
|
-
const currentlyPlayingFlag = "currentlyPlaying";
|
12
|
-
const followerRectID = "followerRect";
|
13
|
-
const ac = window.AudioContext;
|
14
|
-
const synth = new Tone.Synth().toDestination();
|
15
|
-
class MusicPlayer {
|
16
|
-
constructor(containerId) {
|
17
|
-
this.playBtn = (function playBtn(e) {
|
18
|
-
e.preventDefault();
|
19
|
-
this.context.resume().then(() => this.playMidi());
|
20
|
-
}).bind(this);
|
21
|
-
this.rewindBtn = (function rewindBtn(e) {
|
22
|
-
e.preventDefault();
|
23
|
-
this.rewind();
|
24
|
-
}).bind(this);
|
25
|
-
this.playHandler = (function playHandler(e) {
|
26
|
-
if (!this.hasContainerFocus())
|
27
|
-
return;
|
28
|
-
this.playFunction(e);
|
29
|
-
}).bind(this);
|
30
|
-
this.setCurrentNoteHandler = (function setCurrentNoteHandler(e) {
|
31
|
-
this.currentNote = e.target;
|
32
|
-
}).bind(this);
|
33
|
-
/**
|
34
|
-
* Set last clicked element to restartpoint
|
35
|
-
*/
|
36
|
-
this.startPointHandler = (function startPointHandler(e) {
|
37
|
-
if (!this.hasContainerFocus())
|
38
|
-
return;
|
39
|
-
var playingNote = e.target;
|
40
|
-
playingNote = cq.getVrvSVG(this.containerId).querySelector("#" + playingNote.closest("[refId]").getAttribute("refId"));
|
41
|
-
playingNote = playingNote.closest(".note") || playingNote.closest(".rest") || playingNote.closest(".mRest");
|
42
|
-
if (playingNote !== null) {
|
43
|
-
var it = this.durationMap.values();
|
44
|
-
var res = it.next();
|
45
|
-
while (!res.done) {
|
46
|
-
if (playingNote.id === res.value.note.id) {
|
47
|
-
this.restartTime = res.value.tick;
|
48
|
-
break;
|
49
|
-
}
|
50
|
-
res = it.next();
|
51
|
-
}
|
52
|
-
}
|
53
|
-
}).bind(this);
|
54
|
-
/**
|
55
|
-
* Adds Class to be highlighted.
|
56
|
-
* Dispatches event for every Note which was started most currently
|
57
|
-
*/
|
58
|
-
this.addClass = (function addClass(n, className) {
|
59
|
-
return new Promise(resolve => {
|
60
|
-
n.classList.add(className);
|
61
|
-
n.dispatchEvent(this.noteEvent);
|
62
|
-
resolve(true);
|
63
|
-
});
|
64
|
-
}).bind(this);
|
65
|
-
this.setContainerId(containerId);
|
66
|
-
this.noteEvent = new Event("currentNote");
|
67
|
-
this.playStartEvent = new Event("playStart");
|
68
|
-
this.playEndEvent = new Event("playEnd");
|
69
|
-
this.restartTime = 0;
|
70
|
-
this.setPlayListener();
|
71
|
-
if (navigator.userAgent.toLocaleLowerCase().indexOf("firefox") > 0) {
|
72
|
-
this.isFirefox = true;
|
73
|
-
}
|
74
|
-
else {
|
75
|
-
this.isFirefox = false;
|
76
|
-
}
|
77
|
-
this.getMidiInput();
|
78
|
-
}
|
79
|
-
/**
|
80
|
-
* Add Canvas in which all MusicPlayer SVGs are contained
|
81
|
-
*/
|
82
|
-
addCanvas() {
|
83
|
-
//this.root = this.interactionOverlay //document.getElementById(c._vrvSVGID_)
|
84
|
-
this.rootBBox = this.interactionOverlay.getBoundingClientRect();
|
85
|
-
var rootWidth = this.rootBBox.width.toString();
|
86
|
-
var rootHeigth = this.rootBBox.height.toString();
|
87
|
-
if (this.canvasMP == undefined) {
|
88
|
-
this.canvasMP = document.createElementNS(constants_1.constants._SVGNS_, "svg");
|
89
|
-
this.canvasMP.setAttribute("id", "canvasMusicPlayer");
|
90
|
-
this.canvasMP.classList.add("canvas");
|
91
|
-
this.canvasMP.setAttribute("viewBox", ["0", "0", rootWidth, rootHeigth].join(" "));
|
92
|
-
}
|
93
|
-
this.canvasMP.innerHTML = ""; // will delete followerRect if present (usually when score is loaded)
|
94
|
-
this.interactionOverlay = cq.getInteractOverlay(this.containerId);
|
95
|
-
this.interactionOverlay.insertBefore(this.canvasMP, this.interactionOverlay.firstChild);
|
96
|
-
}
|
97
|
-
/**
|
98
|
-
* Initialize Player
|
99
|
-
*/
|
100
|
-
initPlayer() {
|
101
|
-
var that = this;
|
102
|
-
//@ts-ignore
|
103
|
-
this.player = new midi_player_js_1.default.Player(function (event) {
|
104
|
-
if (event.name === "Set Tempo") {
|
105
|
-
that.tempo = event.data;
|
106
|
-
//that.pulse = (60000/ (event.data / 2 * 24))/10 //(60000/ (event.data * 24))/10000 //duration is in seconds
|
107
|
-
that.pulse = ((60 / event.data) * 1000) / 120;
|
108
|
-
}
|
109
|
-
if (event.name === 'Note on' && event.velocity !== 0) {
|
110
|
-
var track = event.track;
|
111
|
-
var time = event.tick;
|
112
|
-
var key = track.toString() + "," + event.byteIndex.toString();
|
113
|
-
if (!that.durationMap.has(key)) {
|
114
|
-
return;
|
115
|
-
}
|
116
|
-
var duration = that.durationMap.get(key).duration;
|
117
|
-
that.restartTime = event.tick;
|
118
|
-
that.highlight(time, duration * 1000);
|
119
|
-
if (!that.isFirefox) {
|
120
|
-
that.drawFollowerRect();
|
121
|
-
}
|
122
|
-
if (that.instruments != undefined) {
|
123
|
-
var instr = that.instruments[track - 2];
|
124
|
-
instr.play(event.noteName, that.context.currentTime, { gain: event.velocity / 100, duration: duration });
|
125
|
-
}
|
126
|
-
}
|
127
|
-
});
|
128
|
-
this.player.loadArrayBuffer(buffer_1.Buffer.from(this.midi, "base64"));
|
129
|
-
this.mapDurations();
|
130
|
-
if (this.instruments == undefined) { // instruments only have to be updated, when new instrument (= track) is added
|
131
|
-
this.context = new ac();
|
132
|
-
this.instruments = new Array(this.player.getEvents().length - 1);
|
133
|
-
this.initInstruments();
|
134
|
-
}
|
135
|
-
}
|
136
|
-
//some change
|
137
|
-
/**
|
138
|
-
* Stop playing
|
139
|
-
*/
|
140
|
-
stopInstruments() {
|
141
|
-
var _a;
|
142
|
-
document.dispatchEvent(this.playEndEvent);
|
143
|
-
this.player.stop();
|
144
|
-
(_a = this.instruments) === null || _a === void 0 ? void 0 : _a.forEach(instr => instr.stop(this.context.currentTime));
|
145
|
-
this.player = undefined;
|
146
|
-
this.stopTimeouts();
|
147
|
-
if (this.restartTime === 0) {
|
148
|
-
if (document.getElementById(followerRectID) !== null) {
|
149
|
-
document.getElementById(followerRectID).remove();
|
150
|
-
}
|
151
|
-
Array.from(document.getElementsByClassName(currentlyPlayingFlag)).forEach(element => {
|
152
|
-
element.classList.remove(currentlyPlayingFlag);
|
153
|
-
});
|
154
|
-
}
|
155
|
-
this.initPlayer();
|
156
|
-
}
|
157
|
-
rewind() {
|
158
|
-
if (this.player != undefined) {
|
159
|
-
this.restartTime = 0;
|
160
|
-
this.stopInstruments();
|
161
|
-
}
|
162
|
-
}
|
163
|
-
/**
|
164
|
-
* Initialize Instrument for
|
165
|
-
*/
|
166
|
-
initInstruments() {
|
167
|
-
this.setSoundfontsRecursive();
|
168
|
-
}
|
169
|
-
setSoundfontsRecursive(counter = 0) {
|
170
|
-
var i = counter;
|
171
|
-
var that = this;
|
172
|
-
if (i < this.instruments.length) {
|
173
|
-
Soundfont.instrument(this.context, "acoustic_grand_piano").then((instrument) => {
|
174
|
-
that.instruments[i] = instrument;
|
175
|
-
i += 1;
|
176
|
-
that.setSoundfontsRecursive(i);
|
177
|
-
});
|
178
|
-
}
|
179
|
-
}
|
180
|
-
playMidi() {
|
181
|
-
if (!cq.hasActiveElement(this.containerId))
|
182
|
-
return;
|
183
|
-
if (this.player.isPlaying()) {
|
184
|
-
this.stopInstruments();
|
185
|
-
}
|
186
|
-
else {
|
187
|
-
this.player.on("endOfFile", () => {
|
188
|
-
this.rewind();
|
189
|
-
});
|
190
|
-
this.player.division = 120;
|
191
|
-
//this.player.tempo = this.tempo
|
192
|
-
this.player.tick = this.restartTime;
|
193
|
-
this.player.skipToTick(this.restartTime);
|
194
|
-
this.player.play();
|
195
|
-
document.dispatchEvent(this.playStartEvent);
|
196
|
-
}
|
197
|
-
}
|
198
|
-
///// LISTENERS ////
|
199
|
-
setListeners() {
|
200
|
-
var that = this;
|
201
|
-
if (this.midiTimes == undefined) {
|
202
|
-
return;
|
203
|
-
}
|
204
|
-
var it = this.midiTimes.values();
|
205
|
-
var result = it.next();
|
206
|
-
while (!result.done) {
|
207
|
-
var arr = result.value;
|
208
|
-
arr.forEach(note => {
|
209
|
-
var _a;
|
210
|
-
if (note == undefined)
|
211
|
-
return;
|
212
|
-
note.addEventListener("currentNote", this.setCurrentNoteHandler);
|
213
|
-
var id = ((_a = note.querySelector(".notehead")) === null || _a === void 0 ? void 0 : _a.id) || note.id;
|
214
|
-
var interactRect = cq.getInteractOverlay(that.containerId).querySelector("#scoreRects g[refId=\"" + id + "\"]");
|
215
|
-
interactRect.addEventListener("click", this.startPointHandler);
|
216
|
-
});
|
217
|
-
result = it.next();
|
218
|
-
}
|
219
|
-
this.container.querySelector("#playBtn").addEventListener("click", this.playBtn);
|
220
|
-
this.container.querySelector("#rewindBtn").addEventListener("click", this.rewindBtn);
|
221
|
-
}
|
222
|
-
removeListeners() {
|
223
|
-
var that = this;
|
224
|
-
if (this.midiTimes == undefined) {
|
225
|
-
return;
|
226
|
-
}
|
227
|
-
var it = this.midiTimes.values();
|
228
|
-
var result = it.next();
|
229
|
-
while (!result.done) {
|
230
|
-
var arr = result.value;
|
231
|
-
arr.forEach(note => {
|
232
|
-
var _a;
|
233
|
-
note.removeEventListener("currentNote", this.setCurrentNoteHandler);
|
234
|
-
var id = ((_a = note.querySelector(".notehead")) === null || _a === void 0 ? void 0 : _a.id) || note.id;
|
235
|
-
var interactRect = cq.getInteractOverlay(that.containerId).querySelector("#scoreRects g[refId=\"" + id + "\"]");
|
236
|
-
interactRect.removeEventListener("click", this.startPointHandler);
|
237
|
-
});
|
238
|
-
result = it.next();
|
239
|
-
}
|
240
|
-
}
|
241
|
-
resetListeners() {
|
242
|
-
this.removeListeners();
|
243
|
-
this.setListeners();
|
244
|
-
}
|
245
|
-
/**
|
246
|
-
* Separate Listeners to set player options externally
|
247
|
-
*/
|
248
|
-
setPlayListener() {
|
249
|
-
document.addEventListener("keydown", this.playHandler);
|
250
|
-
}
|
251
|
-
removePlayListener() {
|
252
|
-
document.removeEventListener("keydown", this.playHandler);
|
253
|
-
}
|
254
|
-
playFunction(e) {
|
255
|
-
if (!this.hasContainerFocus())
|
256
|
-
return;
|
257
|
-
if (e.code === "Space") {
|
258
|
-
e.preventDefault();
|
259
|
-
if (e.shiftKey || document.getElementById("followerRect") !== null) {
|
260
|
-
this.context.resume().then(() => this.playMidi());
|
261
|
-
}
|
262
|
-
else if (typeof this.player != undefined) {
|
263
|
-
this.stopInstruments();
|
264
|
-
}
|
265
|
-
}
|
266
|
-
}
|
267
|
-
/**
|
268
|
-
* Map all durations and notes to make them available asynchronically
|
269
|
-
*/
|
270
|
-
mapDurations() {
|
271
|
-
var durationMap = new Map(); // key: tracknumber,byteindex
|
272
|
-
var mapByNote = new Map();
|
273
|
-
var eventTracks = this.player.getEvents();
|
274
|
-
eventTracks.forEach(eventArray => {
|
275
|
-
//@ts-ignore
|
276
|
-
Array.from(eventArray).forEach((event, eventIdx) => {
|
277
|
-
var e = event;
|
278
|
-
if (e.name === "Set Tempo") {
|
279
|
-
this.tempo = e.data;
|
280
|
-
this.pulse = ((60 / e.data) * 1000) / 120;
|
281
|
-
}
|
282
|
-
else if (e.name === "Note on") {
|
283
|
-
var time = e.tick; //* this.pulse //* 1000 * 2
|
284
|
-
var notes = this.getClosestEntry(time);
|
285
|
-
if (notes == undefined) {
|
286
|
-
return;
|
287
|
-
}
|
288
|
-
//iterate because notes can be in a chord
|
289
|
-
notes.forEach(note => {
|
290
|
-
var meiNote = this.mei.getElementById(note.id);
|
291
|
-
var staffNumber = parseInt(meiNote.closest("staff").getAttribute("n")) + 1;
|
292
|
-
if (!meiNote.hasAttribute("grace")) {
|
293
|
-
var key = e.track.toString() + "," + e.byteIndex.toString();
|
294
|
-
if (!durationMap.has(key) && e.track === staffNumber) {
|
295
|
-
if (!meiNote.hasAttribute("dur")) {
|
296
|
-
meiNote = meiNote.closest("chord");
|
297
|
-
}
|
298
|
-
var baseDur = this.getDur(parseInt(meiNote.getAttribute("dur")), parseInt(meiNote.getAttribute("dots")) || 0, 4);
|
299
|
-
//find any prolongated Notes
|
300
|
-
var tie = this.mei.querySelector("tie[startid='#" + note.id + "']");
|
301
|
-
if (tie !== null) {
|
302
|
-
var endid = tie.getAttribute("endid"); //endid alway includes # at beginnig
|
303
|
-
var prolongNote = this.mei.querySelector(endid);
|
304
|
-
if (prolongNote !== null) {
|
305
|
-
var pnDur = prolongNote.getAttribute("dur");
|
306
|
-
var pnDot = prolongNote.getAttribute("dots");
|
307
|
-
baseDur += this.getDur(parseInt(pnDur), parseInt(pnDot) || 0, 4);
|
308
|
-
}
|
309
|
-
}
|
310
|
-
//concat duration
|
311
|
-
var dur = baseDur * 60 / this.tempo;
|
312
|
-
var valueFound = false;
|
313
|
-
var it = durationMap.values();
|
314
|
-
var res = it.next();
|
315
|
-
if (!valueFound) { // why do I check here?
|
316
|
-
durationMap.set(key, { note: note, duration: dur, tick: e.tick });
|
317
|
-
mapByNote.set(note, { duration: dur, tick: e.tick });
|
318
|
-
}
|
319
|
-
else {
|
320
|
-
//console.log(key, note, dur, e.tick)
|
321
|
-
//console.log(durationMap.get(key))
|
322
|
-
}
|
323
|
-
}
|
324
|
-
}
|
325
|
-
});
|
326
|
-
}
|
327
|
-
});
|
328
|
-
});
|
329
|
-
this.durationMap = durationMap;
|
330
|
-
this.durationMapByNote = mapByNote;
|
331
|
-
//console.log(this.durationMap, this.durationMapByNote)
|
332
|
-
}
|
333
|
-
/**
|
334
|
-
* Computation of time and midi times have some divergence (by floating number)
|
335
|
-
* Finding closest entry is sufficient, but has to be made for all entries, since the miditimes-iterator is not ordered.
|
336
|
-
* @param time
|
337
|
-
* @returns
|
338
|
-
*/
|
339
|
-
getClosestEntry(time) {
|
340
|
-
var targetEntry;
|
341
|
-
var temp = Infinity;
|
342
|
-
for (const [key, value] of this.midiTimes.entries()) {
|
343
|
-
var diff = Math.abs(time - key);
|
344
|
-
if (diff < temp) {
|
345
|
-
targetEntry = value;
|
346
|
-
temp = diff;
|
347
|
-
}
|
348
|
-
}
|
349
|
-
return targetEntry;
|
350
|
-
}
|
351
|
-
getDur(dur, dots, base) {
|
352
|
-
var baseDur = base / dur;
|
353
|
-
var add = baseDur;
|
354
|
-
if (dots > 0) {
|
355
|
-
for (var i = 0; i < dots; i++) {
|
356
|
-
add = add / 2;
|
357
|
-
baseDur += add;
|
358
|
-
}
|
359
|
-
}
|
360
|
-
return baseDur;
|
361
|
-
}
|
362
|
-
setAudioContext() {
|
363
|
-
var that = this;
|
364
|
-
return new Promise((resolve, reject) => {
|
365
|
-
window.onload = function () {
|
366
|
-
resolve();
|
367
|
-
};
|
368
|
-
});
|
369
|
-
}
|
370
|
-
setMidi(midi) {
|
371
|
-
this.midi = midi;
|
372
|
-
return this;
|
373
|
-
}
|
374
|
-
/**
|
375
|
-
* Highlight playing Elements
|
376
|
-
* @param time Time at which Element is played (in ms)
|
377
|
-
* @param duration Duration of Element (in ms)
|
378
|
-
*/
|
379
|
-
highlight(time, duration) {
|
380
|
-
var notes = this.getClosestEntry(time);
|
381
|
-
this.timeouts = new Array();
|
382
|
-
notes.forEach(n => {
|
383
|
-
this.addClass(n, currentlyPlayingFlag).then(() => {
|
384
|
-
var to = setTimeout(() => { n.classList.remove(currentlyPlayingFlag); }, duration);
|
385
|
-
this.timeouts.push(to);
|
386
|
-
});
|
387
|
-
});
|
388
|
-
}
|
389
|
-
/**
|
390
|
-
* Draw follower rectangle over all staves for last sounding element
|
391
|
-
*/
|
392
|
-
drawFollowerRect() {
|
393
|
-
// var canvas = document.getElementById(this.containerId).querySelector("#canvasMusicPlayer") //document.getElementById("canvasMusicPlayer")
|
394
|
-
// var canvasBBox = canvas.getBoundingClientRect();
|
395
|
-
var followerRect;
|
396
|
-
if (document.getElementById(followerRectID) !== null) {
|
397
|
-
followerRect = document.getElementById(followerRectID);
|
398
|
-
}
|
399
|
-
else {
|
400
|
-
followerRect = document.createElementNS(constants_1.constants._SVGNS_, "rect");
|
401
|
-
this.canvasMP.appendChild(followerRect);
|
402
|
-
}
|
403
|
-
var margin = 5;
|
404
|
-
var ptCurrentNote = coordinates.getDOMMatrixCoordinates(this.currentNote, this.canvasMP);
|
405
|
-
var parentMeasureRect = this.currentNote.closest(".measure").getBoundingClientRect();
|
406
|
-
var ptParentMeasure = coordinates.getDOMMatrixCoordinates(parentMeasureRect, this.canvasMP);
|
407
|
-
var upperBound = (ptParentMeasure.top - margin);
|
408
|
-
var lowerBound = (ptParentMeasure.bottom + margin);
|
409
|
-
var leftBound = (ptCurrentNote.left - margin);
|
410
|
-
var rightBound = (ptCurrentNote.right + margin);
|
411
|
-
followerRect.setAttribute("id", followerRectID);
|
412
|
-
followerRect.setAttribute("y", upperBound.toString());
|
413
|
-
followerRect.setAttribute("x", leftBound.toString());
|
414
|
-
followerRect.setAttribute("width", (rightBound - leftBound).toString());
|
415
|
-
followerRect.setAttribute("height", (lowerBound - upperBound).toString());
|
416
|
-
}
|
417
|
-
hasContainerFocus() {
|
418
|
-
return document.getElementById(this.containerId).classList.contains("activeContainer");
|
419
|
-
}
|
420
|
-
///SYNTH////
|
421
|
-
generateTone(newNote) {
|
422
|
-
if (newNote.rest) {
|
423
|
-
return;
|
424
|
-
}
|
425
|
-
let note = newNote.pname;
|
426
|
-
let dur = newNote.dur + "n";
|
427
|
-
if (typeof newNote.keysig !== "undefined" && newNote.keysig !== "0") {
|
428
|
-
let signMap;
|
429
|
-
if (newNote.keysig.charAt(1) === "s") {
|
430
|
-
signMap = mappings_1.noteToCross;
|
431
|
-
}
|
432
|
-
else if (newNote.keysig.charAt(1) === "f") {
|
433
|
-
signMap = mappings_1.noteToB;
|
434
|
-
}
|
435
|
-
let signCount = parseInt(newNote.keysig.charAt(0));
|
436
|
-
let submap = new Map();
|
437
|
-
let i = 0;
|
438
|
-
for (const [key, value] of signMap.entries()) {
|
439
|
-
if (i < signCount) {
|
440
|
-
submap.set(key, value);
|
441
|
-
}
|
442
|
-
i += 1;
|
443
|
-
}
|
444
|
-
if (submap.has(note)) {
|
445
|
-
note = submap.get(note);
|
446
|
-
note = note.charAt(0).toUpperCase() + note.charAt(1).toUpperCase() + newNote.oct;
|
447
|
-
}
|
448
|
-
else {
|
449
|
-
note = note.toUpperCase() + newNote.oct;
|
450
|
-
}
|
451
|
-
}
|
452
|
-
else {
|
453
|
-
note = note.toUpperCase() + newNote.oct;
|
454
|
-
}
|
455
|
-
if (!note.includes("undefined") && !dur.includes("undefined")) {
|
456
|
-
dur = "16n";
|
457
|
-
synth.triggerAttackRelease(note, dur);
|
458
|
-
Tone.start();
|
459
|
-
}
|
460
|
-
}
|
461
|
-
// UTILS
|
462
|
-
setMEI(mei) {
|
463
|
-
this.mei = mei;
|
464
|
-
return this;
|
465
|
-
}
|
466
|
-
setMidiTimes(midiTimes) {
|
467
|
-
this.midiTimes = midiTimes;
|
468
|
-
return this;
|
469
|
-
}
|
470
|
-
setScoreGraph(scoreGraph) {
|
471
|
-
this.scoreGraph = scoreGraph;
|
472
|
-
return this;
|
473
|
-
}
|
474
|
-
stopTimeouts() {
|
475
|
-
if (typeof this.timeouts !== "undefined") {
|
476
|
-
this.timeouts.forEach(to => {
|
477
|
-
clearTimeout(to);
|
478
|
-
});
|
479
|
-
}
|
480
|
-
}
|
481
|
-
setContainerId(containerId) {
|
482
|
-
this.containerId = containerId;
|
483
|
-
this.interactionOverlay = cq.getInteractOverlay(containerId);
|
484
|
-
this.vrvSVG = cq.getVrvSVG(containerId);
|
485
|
-
this.container = document.getElementById(containerId);
|
486
|
-
return this;
|
487
|
-
}
|
488
|
-
resetInstruments() {
|
489
|
-
this.instruments = undefined;
|
490
|
-
}
|
491
|
-
getRestartTime() {
|
492
|
-
return this.restartTime;
|
493
|
-
}
|
494
|
-
setRestartTimeBySeconds(time) {
|
495
|
-
return this.restartTime = time;
|
496
|
-
}
|
497
|
-
setRestartTimeByElement(el) {
|
498
|
-
throw Error("Not yet implemented");
|
499
|
-
}
|
500
|
-
getIsPlaying() {
|
501
|
-
var _a;
|
502
|
-
return (_a = this.player) === null || _a === void 0 ? void 0 : _a.isPlaying();
|
503
|
-
}
|
504
|
-
update() {
|
505
|
-
this.resetInstruments();
|
506
|
-
this.resetListeners();
|
507
|
-
this.initPlayer();
|
508
|
-
return this;
|
509
|
-
}
|
510
|
-
//// Experimantal
|
511
|
-
getMidiInput() {
|
512
|
-
var navigator = require('web-midi-api');
|
513
|
-
// consider using var navigator = require('jzz');
|
514
|
-
var midi;
|
515
|
-
var inputs;
|
516
|
-
var outputs;
|
517
|
-
function onMIDIFailure(msg) {
|
518
|
-
console.log('Failed to get MIDI access - ' + msg);
|
519
|
-
process.exit(1);
|
520
|
-
}
|
521
|
-
function onMIDISuccess(midiAccess) {
|
522
|
-
midi = midiAccess;
|
523
|
-
inputs = midi.inputs;
|
524
|
-
outputs = midi.outputs;
|
525
|
-
console.log("general midi info:", midi);
|
526
|
-
setTimeout(testOutputs, 500);
|
527
|
-
}
|
528
|
-
function testOutputs() {
|
529
|
-
console.log('Testing MIDI-Out ports...');
|
530
|
-
outputs.forEach(function (port) {
|
531
|
-
console.log('id:', port.id, 'manufacturer:', port.manufacturer, 'name:', port.name, 'version:', port.version);
|
532
|
-
port.open();
|
533
|
-
port.send([0x90, 60, 0x7f]);
|
534
|
-
});
|
535
|
-
setTimeout(stopOutputs, 1000);
|
536
|
-
}
|
537
|
-
function stopOutputs() {
|
538
|
-
outputs.forEach(function (port) {
|
539
|
-
port.send([0x80, 60, 0]);
|
540
|
-
});
|
541
|
-
testInputs();
|
542
|
-
}
|
543
|
-
function onMidiIn(ev) {
|
544
|
-
var arr = [];
|
545
|
-
for (var i = 0; i < ev.data.length; i++) {
|
546
|
-
arr.push((ev.data[i] < 16 ? '0' : '') + ev.data[i].toString(16));
|
547
|
-
}
|
548
|
-
console.log('MIDI:', arr.join(' '));
|
549
|
-
console.log(ev.data);
|
550
|
-
}
|
551
|
-
function testInputs() {
|
552
|
-
console.log('Testing MIDI-In ports...');
|
553
|
-
inputs.forEach(function (port) {
|
554
|
-
console.log('id:', port.id, 'manufacturer:', port.manufacturer, 'name:', port.name, 'version:', port.version);
|
555
|
-
port.onmidimessage = onMidiIn;
|
556
|
-
});
|
557
|
-
setTimeout(stopInputs, 5000);
|
558
|
-
}
|
559
|
-
function stopInputs() {
|
560
|
-
console.log('Thank you!');
|
561
|
-
navigator.close(); // This will close MIDI inputs, otherwise Node.js will wait for MIDI input forever.
|
562
|
-
process.exit(0);
|
563
|
-
}
|
564
|
-
navigator.requestMIDIAccess().then(access => {
|
565
|
-
console.log(access);
|
566
|
-
access.onstatechange = (e) => { console.log("State Changed", e); };
|
567
|
-
onMIDISuccess(access);
|
568
|
-
onMIDIFailure(access);
|
569
|
-
});
|
570
|
-
}
|
571
|
-
}
|
572
|
-
exports.default = MusicPlayer;
|