abcjs 6.2.0 → 6.2.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/LICENSE.md +1 -1
- package/RELEASE.md +16 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic-min.js.LICENSE +1 -1
- package/dist/abcjs-basic.js +61 -19
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/dist/abcjs-plugin-min.js.LICENSE +1 -1
- package/index.js +1 -1
- package/license.js +1 -1
- package/package.json +1 -1
- package/plugin.js +1 -1
- package/src/api/abc_timing_callbacks.js +1 -1
- package/src/data/abc_tune.js +1 -1
- package/src/synth/create-synth.js +30 -4
- package/src/synth/load-note.js +1 -1
- package/src/synth/place-note.js +10 -2
- package/src/tablatures/instruments/string-patterns.js +1 -1
- package/src/write/draw/print-line.js +10 -0
- package/src/write/draw/print-stem.js +10 -0
- package/src/write/interactive/selection.js +7 -4
- package/src/write/renderer.js +1 -0
- package/test.js +1 -1
- package/types/index.d.ts +1 -1
- package/version.js +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**!
|
|
2
|
-
Copyright (c) 2009-
|
|
2
|
+
Copyright (c) 2009-2023 Paul Rosen and Gregory Dyke
|
|
3
3
|
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
of this software and associated documentation files (the "Software"), to deal
|
package/dist/abcjs-basic.js
CHANGED
|
@@ -18,7 +18,7 @@ return /******/ (function() { // webpackBootstrap
|
|
|
18
18
|
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
19
19
|
|
|
20
20
|
/**!
|
|
21
|
-
Copyright (c) 2009-
|
|
21
|
+
Copyright (c) 2009-2023 Paul Rosen and Gregory Dyke
|
|
22
22
|
|
|
23
23
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
24
24
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -352,7 +352,7 @@ var TimingCallbacks = function TimingCallbacks(target, params) {
|
|
|
352
352
|
self.joggerTimer = null;
|
|
353
353
|
self.replaceTarget = function (newTarget) {
|
|
354
354
|
self.noteTimings = newTarget.setTiming(self.qpm, self.extraMeasuresAtBeginning);
|
|
355
|
-
if (newTarget.noteTimings.length === 0) newTarget.setTiming(0, 0);
|
|
355
|
+
if (newTarget.noteTimings.length === 0) self.noteTimings = newTarget.setTiming(0, 0);
|
|
356
356
|
if (self.lineEndCallback) {
|
|
357
357
|
self.lineEndTimings = getLineEndTimings(newTarget.noteTimings, self.lineEndAnticipation);
|
|
358
358
|
}
|
|
@@ -1797,7 +1797,7 @@ var Tune = function Tune() {
|
|
|
1797
1797
|
if (!this.engraver || !this.engraver.staffgroups) {
|
|
1798
1798
|
console.log("setTiming cannot be called before the tune is drawn.");
|
|
1799
1799
|
this.noteTimings = [];
|
|
1800
|
-
return;
|
|
1800
|
+
return this.noteTimings;
|
|
1801
1801
|
}
|
|
1802
1802
|
var tempo = this.metaText ? this.metaText.tempo : null;
|
|
1803
1803
|
var naturalBpm = this.getBpm(tempo);
|
|
@@ -13881,6 +13881,8 @@ function CreateSynth() {
|
|
|
13881
13881
|
});
|
|
13882
13882
|
});
|
|
13883
13883
|
});
|
|
13884
|
+
if (self.debugCallback) self.debugCallback("notes " + JSON.stringify(notes));
|
|
13885
|
+
|
|
13884
13886
|
// If there are lots of notes, load them in batches
|
|
13885
13887
|
var batches = [];
|
|
13886
13888
|
var CHUNK = 256;
|
|
@@ -13895,8 +13897,10 @@ function CreateSynth() {
|
|
|
13895
13897
|
};
|
|
13896
13898
|
var index = 0;
|
|
13897
13899
|
var next = function next() {
|
|
13900
|
+
if (self.debugCallback) self.debugCallback("loadBatch idx=" + index + " len=" + batches.length);
|
|
13898
13901
|
if (index < batches.length) {
|
|
13899
13902
|
self._loadBatch(batches[index], self.soundFontUrl, startTime).then(function (data) {
|
|
13903
|
+
if (self.debugCallback) self.debugCallback("loadBatch then");
|
|
13900
13904
|
startTime = activeAudioContext().currentTime;
|
|
13901
13905
|
if (data) {
|
|
13902
13906
|
if (data.error) results.error = results.error.concat(data.error);
|
|
@@ -13906,6 +13910,7 @@ function CreateSynth() {
|
|
|
13906
13910
|
next();
|
|
13907
13911
|
}, reject);
|
|
13908
13912
|
} else {
|
|
13913
|
+
if (self.debugCallback) self.debugCallback("resolve init");
|
|
13909
13914
|
resolve(results);
|
|
13910
13915
|
}
|
|
13911
13916
|
};
|
|
@@ -13916,6 +13921,7 @@ function CreateSynth() {
|
|
|
13916
13921
|
// This is called recursively to see if the sounds have loaded. The "delay" parameter is how long it has been since the original call.
|
|
13917
13922
|
var promises = [];
|
|
13918
13923
|
batch.forEach(function (item) {
|
|
13924
|
+
if (self.debugCallback) self.debugCallback("getNote " + item.instrument + ':' + item.note);
|
|
13919
13925
|
promises.push(getNote(soundFontUrl, item.instrument, item.note, activeAudioContext()));
|
|
13920
13926
|
});
|
|
13921
13927
|
return Promise.all(promises).then(function (response) {
|
|
@@ -13930,6 +13936,7 @@ function CreateSynth() {
|
|
|
13930
13936
|
if (oneResponse.status === "loaded") loaded.push(which);else if (oneResponse.status === "pending") pending.push(which);else if (oneResponse.status === "cached") cached.push(which);else error.push(which + ' ' + oneResponse.message);
|
|
13931
13937
|
}
|
|
13932
13938
|
if (pending.length > 0) {
|
|
13939
|
+
if (self.debugCallback) self.debugCallback("pending " + JSON.stringify(pending));
|
|
13933
13940
|
// There was probably a second call for notes before the first one finished, so just retry a few times to see if they stop being pending.
|
|
13934
13941
|
// Retry quickly at first so that there isn't an unnecessary delay, but increase the delay each time.
|
|
13935
13942
|
if (!delay) delay = 50;else delay = delay * 2;
|
|
@@ -13944,6 +13951,7 @@ function CreateSynth() {
|
|
|
13944
13951
|
note: which[1]
|
|
13945
13952
|
});
|
|
13946
13953
|
}
|
|
13954
|
+
if (self.debugCallback) self.debugCallback("retry " + JSON.stringify(newBatch));
|
|
13947
13955
|
self._loadBatch(newBatch, soundFontUrl, startTime, delay).then(function (response) {
|
|
13948
13956
|
resolve(response);
|
|
13949
13957
|
})["catch"](function (error) {
|
|
@@ -13956,14 +13964,20 @@ function CreateSynth() {
|
|
|
13956
13964
|
for (var j = 0; j < batch.length; j++) {
|
|
13957
13965
|
list.push(batch[j].instrument + '/' + batch[j].note);
|
|
13958
13966
|
}
|
|
13967
|
+
if (self.debugCallback) self.debugCallback("loadBatch timeout");
|
|
13959
13968
|
return Promise.reject(new Error("timeout attempting to load: " + list.join(", ")));
|
|
13960
13969
|
}
|
|
13961
|
-
} else
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13970
|
+
} else {
|
|
13971
|
+
if (self.debugCallback) self.debugCallback("loadBatch resolve");
|
|
13972
|
+
return Promise.resolve({
|
|
13973
|
+
loaded: loaded,
|
|
13974
|
+
cached: cached,
|
|
13975
|
+
error: error
|
|
13976
|
+
});
|
|
13977
|
+
}
|
|
13978
|
+
})["catch"](function (error) {
|
|
13979
|
+
if (self.debugCallback) self.debugCallback("loadBatch catch " + error.message);
|
|
13980
|
+
});
|
|
13967
13981
|
};
|
|
13968
13982
|
self.prime = function () {
|
|
13969
13983
|
// At this point all of the notes are loaded. This function writes them into the output buffer.
|
|
@@ -14002,6 +14016,7 @@ function CreateSynth() {
|
|
|
14002
14016
|
var panDistance = panDistances && panDistances.length > trackNumber ? panDistances[trackNumber] : 0;
|
|
14003
14017
|
noteMap.forEach(function (note) {
|
|
14004
14018
|
var key = note.instrument + ':' + note.pitch + ':' + note.volume + ':' + Math.round((note.end - note.start) * 1000) / 1000 + ':' + panDistance + ':' + tempoMultiplier + ':' + (note.cents ? note.cents : 0);
|
|
14019
|
+
if (self.debugCallback) self.debugCallback("noteMapTrack " + key);
|
|
14005
14020
|
if (!uniqueSounds[key]) uniqueSounds[key] = [];
|
|
14006
14021
|
uniqueSounds[key].push(note.start);
|
|
14007
14022
|
});
|
|
@@ -14023,7 +14038,7 @@ function CreateSynth() {
|
|
|
14023
14038
|
tempoMultiplier: parseFloat(parts[5]),
|
|
14024
14039
|
cents: cents
|
|
14025
14040
|
};
|
|
14026
|
-
allPromises.push(placeNote(audioBuffer, activeAudioContext().sampleRate, parts, uniqueSounds[k], self.soundFontVolumeMultiplier, self.programOffsets[parts.instrument], fadeTimeSec, self.noteEnd / 1000));
|
|
14041
|
+
allPromises.push(placeNote(audioBuffer, activeAudioContext().sampleRate, parts, uniqueSounds[k], self.soundFontVolumeMultiplier, self.programOffsets[parts.instrument], fadeTimeSec, self.noteEnd / 1000, self.debugCallback));
|
|
14027
14042
|
}
|
|
14028
14043
|
self.audioBuffers = [audioBuffer];
|
|
14029
14044
|
if (self.debugCallback) {
|
|
@@ -14462,7 +14477,7 @@ var getNote = function getNote(url, instrument, name, audioContext) {
|
|
|
14462
14477
|
xhr.responseType = "arraybuffer";
|
|
14463
14478
|
xhr.onload = function () {
|
|
14464
14479
|
if (xhr.status !== 200) {
|
|
14465
|
-
reject(Error("Can't load sound at " + noteUrl));
|
|
14480
|
+
reject(Error("Can't load sound at " + noteUrl + ' status=' + xhr.status));
|
|
14466
14481
|
return;
|
|
14467
14482
|
}
|
|
14468
14483
|
var noteDecoded = function noteDecoded(audioBuffer) {
|
|
@@ -14756,7 +14771,7 @@ module.exports = pitchesToPerc;
|
|
|
14756
14771
|
var soundsCache = __webpack_require__(/*! ./sounds-cache */ "./src/synth/sounds-cache.js");
|
|
14757
14772
|
var pitchToNoteName = __webpack_require__(/*! ./pitch-to-note-name */ "./src/synth/pitch-to-note-name.js");
|
|
14758
14773
|
var centsToFactor = __webpack_require__(/*! ./cents-to-factor */ "./src/synth/cents-to-factor.js");
|
|
14759
|
-
function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMultiplier, ofsMs, fadeTimeSec, noteEndSec) {
|
|
14774
|
+
function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMultiplier, ofsMs, fadeTimeSec, noteEndSec, debugCallback) {
|
|
14760
14775
|
// sound contains { instrument, pitch, volume, len, pan, tempoMultiplier
|
|
14761
14776
|
// len is in whole notes. Multiply by tempoMultiplier to get seconds.
|
|
14762
14777
|
// ofsMs is an offset to subtract from the note to line up programs that have different length onsets.
|
|
@@ -14770,6 +14785,7 @@ function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMulti
|
|
|
14770
14785
|
var noteBufferPromise = soundsCache[sound.instrument][noteName];
|
|
14771
14786
|
if (!noteBufferPromise) {
|
|
14772
14787
|
// if the note isn't present then just skip it - it will leave a blank spot in the audio.
|
|
14788
|
+
if (debugCallback) debugCallback('placeNote skipped: ' + sound.instrument + ':' + noteName);
|
|
14773
14789
|
return Promise.resolve();
|
|
14774
14790
|
}
|
|
14775
14791
|
return noteBufferPromise.then(function (response) {
|
|
@@ -14825,13 +14841,17 @@ function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMulti
|
|
|
14825
14841
|
copyToChannel(outputAudioBuffer, e.renderedBuffer, start);
|
|
14826
14842
|
}
|
|
14827
14843
|
}
|
|
14844
|
+
if (debugCallback) debugCallback('placeNote: ' + sound.instrument + ':' + noteName);
|
|
14828
14845
|
fnResolve();
|
|
14829
14846
|
};
|
|
14830
14847
|
offlineCtx.startRendering();
|
|
14831
14848
|
return new Promise(function (resolve) {
|
|
14832
14849
|
fnResolve = resolve;
|
|
14833
14850
|
});
|
|
14834
|
-
})["catch"](function () {
|
|
14851
|
+
})["catch"](function (error) {
|
|
14852
|
+
if (debugCallback) debugCallback('placeNote catch: ' + error.message);
|
|
14853
|
+
return Promise.resolve();
|
|
14854
|
+
});
|
|
14835
14855
|
}
|
|
14836
14856
|
var copyToChannel = function copyToChannel(toBuffer, fromBuffer, start) {
|
|
14837
14857
|
for (var ch = 0; ch < 2; ch++) {
|
|
@@ -15618,7 +15638,7 @@ function StringPatterns(plugin) {
|
|
|
15618
15638
|
this.measureAccidentals = {};
|
|
15619
15639
|
this.capo = 0;
|
|
15620
15640
|
if (capo) {
|
|
15621
|
-
this.capo = capo;
|
|
15641
|
+
this.capo = parseInt(capo, 10);
|
|
15622
15642
|
}
|
|
15623
15643
|
this.transpose = plugin.transpose ? plugin.transpose : 0;
|
|
15624
15644
|
this.tuning = tuning;
|
|
@@ -21545,6 +21565,15 @@ function printLine(renderer, x1, x2, y, klass, name, dy) {
|
|
|
21545
21565
|
x2 = roundNumber(x2);
|
|
21546
21566
|
var y1 = roundNumber(y - dy);
|
|
21547
21567
|
var y2 = roundNumber(y + dy);
|
|
21568
|
+
// TODO-PER: This fixes a firefox bug where a path needs to go over the 0.5 mark or it isn't displayed
|
|
21569
|
+
if (renderer.firefox112 && dy < 1) {
|
|
21570
|
+
var _int = Math.floor(y2);
|
|
21571
|
+
var distToHalf = 0.52 - (y2 - _int);
|
|
21572
|
+
if (distToHalf > 0) {
|
|
21573
|
+
y1 += distToHalf;
|
|
21574
|
+
y2 += distToHalf;
|
|
21575
|
+
}
|
|
21576
|
+
}
|
|
21548
21577
|
var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y1, x2, y1, x2, y2, x1, y2);
|
|
21549
21578
|
var options = {
|
|
21550
21579
|
path: pathString,
|
|
@@ -21594,6 +21623,16 @@ function printStem(renderer, x, dx, y1, y2, klass, name) {
|
|
|
21594
21623
|
}
|
|
21595
21624
|
x = roundNumber(x);
|
|
21596
21625
|
var x2 = roundNumber(x + dx);
|
|
21626
|
+
// TODO-PER: This fixes a firefox bug where a path needs to go over the 0.5 mark or it isn't displayed
|
|
21627
|
+
if (renderer.firefox112 && Math.abs(dx) < 1) {
|
|
21628
|
+
var higher = Math.max(x, x2);
|
|
21629
|
+
var _int = Math.floor(higher);
|
|
21630
|
+
var distToHalf = 0.52 - (higher - _int);
|
|
21631
|
+
if (distToHalf > 0) {
|
|
21632
|
+
x += distToHalf;
|
|
21633
|
+
x2 += distToHalf;
|
|
21634
|
+
}
|
|
21635
|
+
}
|
|
21597
21636
|
var pathArray = [["M", x, y1], ["L", x, y2], ["L", x2, y2], ["L", x2, y1], ["z"]];
|
|
21598
21637
|
var attr = {
|
|
21599
21638
|
path: ""
|
|
@@ -23806,10 +23845,12 @@ function notifySelect(target, dragStep, dragMax, dragIndex, ev) {
|
|
|
23806
23845
|
while (parent && parent.dataset && !parent.dataset.index && parent.tagName.toLowerCase() !== 'svg') {
|
|
23807
23846
|
parent = parent.parentNode;
|
|
23808
23847
|
}
|
|
23809
|
-
|
|
23810
|
-
|
|
23811
|
-
|
|
23812
|
-
|
|
23848
|
+
if (parent && parent.dataset) {
|
|
23849
|
+
analysis.name = parent.dataset.name;
|
|
23850
|
+
analysis.clickedName = closest.dataset.name;
|
|
23851
|
+
analysis.parentClasses = parent.classList;
|
|
23852
|
+
}
|
|
23853
|
+
if (closest && closest.classList) analysis.clickedClasses = closest.classList;
|
|
23813
23854
|
analysis.selectableElement = target.svgEl;
|
|
23814
23855
|
for (var i = 0; i < this.listeners.length; i++) {
|
|
23815
23856
|
this.listeners[i](target.absEl.abcelem, target.absEl.tuneNumber, classes.join(' '), analysis, {
|
|
@@ -24992,6 +25033,7 @@ var Renderer = function Renderer(paper) {
|
|
|
24992
25033
|
this.space = 3 * spacing.SPACE;
|
|
24993
25034
|
this.padding = {}; // renderer's padding is managed by the controller
|
|
24994
25035
|
this.reset();
|
|
25036
|
+
this.firefox112 = navigator.userAgent.indexOf('Firefox/112.0') >= 0;
|
|
24995
25037
|
};
|
|
24996
25038
|
Renderer.prototype.reset = function () {
|
|
24997
25039
|
this.paper.clear();
|
|
@@ -25479,7 +25521,7 @@ module.exports = Svg;
|
|
|
25479
25521
|
\********************/
|
|
25480
25522
|
/***/ (function(module) {
|
|
25481
25523
|
|
|
25482
|
-
var version = '6.2.
|
|
25524
|
+
var version = '6.2.1';
|
|
25483
25525
|
module.exports = version;
|
|
25484
25526
|
|
|
25485
25527
|
/***/ })
|