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.
@@ -1,5 +1,5 @@
1
1
  /**!
2
- Copyright (c) 2009-2022 Paul Rosen and Gregory Dyke
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
@@ -18,7 +18,7 @@ return /******/ (function() { // webpackBootstrap
18
18
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
19
19
 
20
20
  /**!
21
- Copyright (c) 2009-2022 Paul Rosen and Gregory Dyke
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 return Promise.resolve({
13962
- loaded: loaded,
13963
- cached: cached,
13964
- error: error
13965
- });
13966
- })["catch"](function (error) {});
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
- analysis.name = parent.dataset.name;
23810
- analysis.clickedName = closest.dataset.name;
23811
- analysis.parentClasses = parent.classList;
23812
- analysis.clickedClasses = closest.classList;
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.0';
25524
+ var version = '6.2.1';
25483
25525
  module.exports = version;
25484
25526
 
25485
25527
  /***/ })