abcjs 6.6.3 → 6.6.4
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/RELEASE.md +29 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +460 -143
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/package.json +1 -1
- package/src/api/abc_timing_callbacks.js +45 -15
- package/src/parse/abc_parse.js +2 -0
- package/src/parse/abc_parse_header.js +3 -1
- package/src/parse/abc_parse_key_voice.js +35 -0
- package/src/synth/chord-track.js +379 -130
- package/src/synth/create-synth.js +14 -8
- package/src/synth/repeats.js +2 -2
- package/src/write/draw/print-line.js +1 -2
- package/src/write/draw/print-stem.js +1 -1
- package/src/write/engraver-controller.js +1 -1
- package/src/write/renderer.js +1 -1
- package/types/index.d.ts +133 -34
- package/version.js +1 -1
package/package.json
CHANGED
|
@@ -2,10 +2,6 @@ var TimingCallbacks = function(target, params) {
|
|
|
2
2
|
var self = this;
|
|
3
3
|
if (!params) params = {};
|
|
4
4
|
self.qpm = params.qpm ? parseInt(params.qpm, 10) : null;
|
|
5
|
-
if (!self.qpm) {
|
|
6
|
-
var tempo = target.metaText ? target.metaText.tempo : null;
|
|
7
|
-
self.qpm = target.getBpm(tempo);
|
|
8
|
-
}
|
|
9
5
|
self.extraMeasuresAtBeginning = params.extraMeasuresAtBeginning ? parseInt(params.extraMeasuresAtBeginning, 10) : 0;
|
|
10
6
|
self.beatCallback = params.beatCallback; // This is called for each beat.
|
|
11
7
|
self.eventCallback = params.eventCallback; // This is called for each note or rest encountered.
|
|
@@ -16,6 +12,10 @@ var TimingCallbacks = function(target, params) {
|
|
|
16
12
|
self.joggerTimer = null;
|
|
17
13
|
|
|
18
14
|
self.replaceTarget = function(newTarget) {
|
|
15
|
+
if (!params.qpm) {
|
|
16
|
+
var tempo = newTarget.metaText ? newTarget.metaText.tempo : null;
|
|
17
|
+
self.qpm = newTarget.getBpm(tempo);
|
|
18
|
+
}
|
|
19
19
|
self.noteTimings = newTarget.setTiming(self.qpm, self.extraMeasuresAtBeginning);
|
|
20
20
|
if (newTarget.noteTimings.length === 0)
|
|
21
21
|
self.noteTimings = newTarget.setTiming(0,0);
|
|
@@ -245,17 +245,47 @@ var TimingCallbacks = function(target, params) {
|
|
|
245
245
|
};
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
|
|
249
|
-
self.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
248
|
+
// there is a case where self.beatStarts[self.currentBeat] doesn't exist, but I don't know how. Give more info in that case for better debugging.
|
|
249
|
+
if (self.currentBeat < 0 || self.currentBeat >= self.beatStarts.length || !self.beatStarts[self.currentBeat]) {
|
|
250
|
+
var obj = {
|
|
251
|
+
currentBeat: self.currentBeat,
|
|
252
|
+
beatStartLength: self.beatStarts.length,
|
|
253
|
+
totalBeats: self.totalBeats,
|
|
254
|
+
|
|
255
|
+
startTime: self.startTime,
|
|
256
|
+
currentTime: self.currentTime,
|
|
257
|
+
lastMoment: self.lastMoment,
|
|
258
|
+
lastTimestamp: self.lastTimestamp,
|
|
259
|
+
|
|
260
|
+
qpm: self.qpm,
|
|
261
|
+
millisecondsPerBeat: self.millisecondsPerBeat,
|
|
262
|
+
beatSubdivisions: self.beatSubdivisions,
|
|
263
|
+
|
|
264
|
+
currentEvent: self.currentEvent,
|
|
265
|
+
currentLine: self.currentLine,
|
|
266
|
+
|
|
267
|
+
isPaused: self.isPaused,
|
|
268
|
+
isRunning: self.isRunning,
|
|
269
|
+
pausedPercent: self.pausedPercent,
|
|
270
|
+
justUnpaused: self.justUnpaused,
|
|
271
|
+
newSeekPercent: self.newSeekPercent,
|
|
272
|
+
}
|
|
273
|
+
setTimeout(function() {
|
|
274
|
+
// throw the error outside of the normal processing so that everything else continues working.
|
|
275
|
+
throw new Error("abcjs-timing-callback error: " + JSON.stringify(obj))
|
|
276
|
+
}, 1)
|
|
277
|
+
} else {
|
|
278
|
+
var thisStartTime = self.startTime; // the beat callback can call seek and change the position from beneath us.
|
|
279
|
+
self.beatCallback(
|
|
280
|
+
self.beatStarts[self.currentBeat].b,
|
|
281
|
+
self.totalBeats / self.beatSubdivisions,
|
|
282
|
+
self.lastMoment,
|
|
283
|
+
position,
|
|
284
|
+
debugInfo);
|
|
285
|
+
if (thisStartTime !== self.startTime) {
|
|
286
|
+
return timestamp - self.startTime;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
259
289
|
}
|
|
260
290
|
return null;
|
|
261
291
|
};
|
package/src/parse/abc_parse.js
CHANGED
|
@@ -508,6 +508,8 @@ var Parse = function() {
|
|
|
508
508
|
}
|
|
509
509
|
strTune = arr.join(" "); //. the split removed two characters, so this puts them back
|
|
510
510
|
}
|
|
511
|
+
// If there is an escaped percent, then temporarily change it so it doesn't affect the processing.
|
|
512
|
+
strTune = strTune.replace(/\\%/g,"\u200B\uFF05")
|
|
511
513
|
// take care of line continuations right away, but keep the same number of characters
|
|
512
514
|
strTune = strTune.replace(/\\([ \t]*)(%.*)*\n/g, function(all, backslash, comment){
|
|
513
515
|
var padding = comment ? Array(comment.length +1).join(' ') : "";
|
|
@@ -356,7 +356,9 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
356
356
|
return [ e-i+1+ws ];
|
|
357
357
|
case "[M:":
|
|
358
358
|
var meter = this.setMeter(line.substring(i+3, e));
|
|
359
|
-
if (
|
|
359
|
+
if (startLine && multilineVars.currentVoice && meter)
|
|
360
|
+
multilineVars.staves[multilineVars.currentVoice.staffNum].meter = meter;
|
|
361
|
+
else if (tuneBuilder.hasBeginMusic() && meter)
|
|
360
362
|
tuneBuilder.appendStartingElement('meter', startChar, endChar, meter);
|
|
361
363
|
else
|
|
362
364
|
multilineVars.meter = meter;
|
|
@@ -85,9 +85,20 @@ var parseKeyVoice = {};
|
|
|
85
85
|
key.accidentals.forEach(function(k) {
|
|
86
86
|
ret.accidentals.push(Object.assign({},k));
|
|
87
87
|
});
|
|
88
|
+
if (key.explicitAccidentals) {
|
|
89
|
+
ret.explicitAccidentals = [];
|
|
90
|
+
key.explicitAccidentals.forEach(function(k) {
|
|
91
|
+
ret.explicitAccidentals.push(Object.assign({},k));
|
|
92
|
+
});
|
|
93
|
+
}
|
|
88
94
|
return ret;
|
|
89
95
|
};
|
|
90
96
|
|
|
97
|
+
var setVoiceKey = function() {
|
|
98
|
+
if (multilineVars.currentVoice)
|
|
99
|
+
multilineVars.currentVoice.key = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
100
|
+
};
|
|
101
|
+
|
|
91
102
|
var pitches = {A: 5, B: 6, C: 0, D: 1, E: 2, F: 3, G: 4, a: 12, b: 13, c: 7, d: 8, e: 9, f: 10, g: 11};
|
|
92
103
|
|
|
93
104
|
parseKeyVoice.addPosToKey = function(clef, key) {
|
|
@@ -230,18 +241,30 @@ var parseKeyVoice = {};
|
|
|
230
241
|
multilineVars.key = { root: "HP", accidentals: [], acc: "", mode: "" };
|
|
231
242
|
ret.foundKey = true;
|
|
232
243
|
tokens.shift();
|
|
244
|
+
if (!isInline) {
|
|
245
|
+
multilineVars.globalKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
246
|
+
}
|
|
247
|
+
setVoiceKey();
|
|
233
248
|
break;
|
|
234
249
|
case 'Hp':
|
|
235
250
|
parseDirective.addDirective("bagpipes");
|
|
236
251
|
multilineVars.key = { root: "Hp", accidentals: [{acc: 'natural', note: 'g'}, {acc: 'sharp', note: 'f'}, {acc: 'sharp', note: 'c'}], acc: "", mode: "" };
|
|
237
252
|
ret.foundKey = true;
|
|
238
253
|
tokens.shift();
|
|
254
|
+
if (!isInline) {
|
|
255
|
+
multilineVars.globalKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
256
|
+
}
|
|
257
|
+
setVoiceKey();
|
|
239
258
|
break;
|
|
240
259
|
case 'none':
|
|
241
260
|
// we got the none key - that's the same as C to us
|
|
242
261
|
multilineVars.key = { root: "none", accidentals: [], acc: "", mode: "" };
|
|
243
262
|
ret.foundKey = true;
|
|
244
263
|
tokens.shift();
|
|
264
|
+
if (!isInline) {
|
|
265
|
+
multilineVars.globalKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
266
|
+
}
|
|
267
|
+
setVoiceKey();
|
|
245
268
|
break;
|
|
246
269
|
default:
|
|
247
270
|
var retPitch = tokenizer.getKeyPitch(tokens[0].token);
|
|
@@ -309,6 +332,10 @@ var parseKeyVoice = {};
|
|
|
309
332
|
}
|
|
310
333
|
}
|
|
311
334
|
}
|
|
335
|
+
if (!isInline) {
|
|
336
|
+
multilineVars.globalKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
337
|
+
}
|
|
338
|
+
setVoiceKey();
|
|
312
339
|
}
|
|
313
340
|
break;
|
|
314
341
|
}
|
|
@@ -358,6 +385,10 @@ var parseKeyVoice = {};
|
|
|
358
385
|
}
|
|
359
386
|
}
|
|
360
387
|
}
|
|
388
|
+
if (!isInline) {
|
|
389
|
+
multilineVars.globalKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
390
|
+
}
|
|
391
|
+
setVoiceKey();
|
|
361
392
|
}
|
|
362
393
|
|
|
363
394
|
// Now see if any optional parameters are present. They have the form "key=value", except that "clef=" is optional
|
|
@@ -499,6 +530,10 @@ var parseKeyVoice = {};
|
|
|
499
530
|
return // there was no change so don't reset it.
|
|
500
531
|
}
|
|
501
532
|
multilineVars.currentVoice = currentVoice;
|
|
533
|
+
if (currentVoice.key)
|
|
534
|
+
multilineVars.key = parseKeyVoice.deepCopyKey(currentVoice.key);
|
|
535
|
+
else if (multilineVars.globalKey)
|
|
536
|
+
multilineVars.key = parseKeyVoice.deepCopyKey(multilineVars.globalKey);
|
|
502
537
|
return tuneBuilder.setCurrentVoice(currentVoice.staffNum, currentVoice.index, id);
|
|
503
538
|
};
|
|
504
539
|
|