abcjs 6.4.3 → 6.4.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.
@@ -617,6 +617,7 @@ var tunebook = {};
617
617
  }
618
618
  }
619
619
  }
620
+
620
621
  return staves;
621
622
  }
622
623
  function measuresParser(staff, tune) {
@@ -1340,6 +1341,7 @@ var Tune = function Tune() {
1340
1341
  };
1341
1342
  return this.meter; // TODO-PER: is this saved value used anywhere? A get function shouldn't change state.
1342
1343
  };
1344
+
1343
1345
  this.getKeySignature = function () {
1344
1346
  for (var i = 0; i < this.lines.length; i++) {
1345
1347
  var line = this.lines[i];
@@ -1494,6 +1496,7 @@ var Tune = function Tune() {
1494
1496
  // isTiedState = voiceTimeMilliseconds;
1495
1497
  }
1496
1498
  }
1499
+
1497
1500
  return {
1498
1501
  isTiedState: isTiedState,
1499
1502
  duration: realDuration / timeDivider,
@@ -3119,6 +3122,7 @@ var Parse = function Parse() {
3119
3122
  multilineVars.lineBreaks = switches.lineBreaks;
3120
3123
  //multilineVars.continueall = true;
3121
3124
  }
3125
+
3122
3126
  header.reset(tokenizer, warn, multilineVars, tune);
3123
3127
  try {
3124
3128
  if (switches.format) {
@@ -3208,6 +3212,7 @@ var bookParser = function bookParser(book) {
3208
3212
  });
3209
3213
  pos += tune.length + 1; // We also lost a newline when splitting, so count that.
3210
3214
  });
3215
+
3211
3216
  if (tunes.length > 1 && !parseCommon.startsWith(tunes[0].abc, 'X:')) {
3212
3217
  // If there is only one tune, the X: might be missing, otherwise assume the top of the file is "intertune"
3213
3218
  // There could be file-wide directives in this, if so, we need to insert it into each tune. We can probably get away with
@@ -4780,6 +4785,7 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
4780
4785
  }
4781
4786
  return ret; // just to suppress warning
4782
4787
  };
4788
+
4783
4789
  var parseFraction = function parseFraction() {
4784
4790
  // handles this much: parseNum slash decimal
4785
4791
  var ret = parseNum();
@@ -4810,6 +4816,7 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
4810
4816
  //var tok = tokens.shift();
4811
4817
  //if (tok.token !== '+') throw "Extra characters in M: line";
4812
4818
  }
4819
+
4813
4820
  if (multilineVars.havent_set_length === true) {
4814
4821
  multilineVars.default_length = totalLength < 0.75 ? 0.0625 : 0.125;
4815
4822
  multilineVars.havent_set_length = false;
@@ -5085,6 +5092,7 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
5085
5092
  // TODO: complain about unhandled header
5086
5093
  }
5087
5094
  }
5095
+
5088
5096
  return [0];
5089
5097
  };
5090
5098
  this.letter_to_body_header = function (line, i) {
@@ -5126,6 +5134,7 @@ var ParseHeader = function ParseHeader(tokenizer, warn, multilineVars, tune, tun
5126
5134
  // TODO: complain about unhandled header
5127
5135
  }
5128
5136
  }
5137
+
5129
5138
  return [0];
5130
5139
  };
5131
5140
  var metaTextHeaders = {
@@ -5592,6 +5601,7 @@ var parseKeyVoice = {};
5592
5601
  str: str.substring(i)
5593
5602
  }; // We get the note in the middle of the staff. We want the note that appears as the first ledger line below the staff.
5594
5603
  };
5604
+
5595
5605
  var normalizeAccidentals = function normalizeAccidentals(accs) {
5596
5606
  for (var i = 0; i < accs.length; i++) {
5597
5607
  if (accs[i].note === 'b') accs[i].note = 'B';else if (accs[i].note === 'a') accs[i].note = 'A';else if (accs[i].note === 'F') accs[i].note = 'f';else if (accs[i].note === 'E') accs[i].note = 'e';else if (accs[i].note === 'D') accs[i].note = 'd';else if (accs[i].note === 'C') accs[i].note = 'c';else if (accs[i].note === 'G' && accs[i].acc === 'sharp') accs[i].note = 'g';else if (accs[i].note === 'g' && accs[i].acc === 'flat') accs[i].note = 'G';
@@ -6008,6 +6018,7 @@ var parseKeyVoice = {};
6008
6018
  if (multilineVars.currentVoice) {
6009
6019
  if (multilineVars.currentVoice.index === currentVoice.index && multilineVars.currentVoice.staffNum === currentVoice.staffNum) return; // there was no change so don't reset it.
6010
6020
  }
6021
+
6011
6022
  multilineVars.currentVoice = currentVoice;
6012
6023
  return tuneBuilder.setCurrentVoice(currentVoice.staffNum, currentVoice.index, id);
6013
6024
  };
@@ -6223,6 +6234,7 @@ var parseKeyVoice = {};
6223
6234
  // console.log("parse voice", token, tune.metaText.title);
6224
6235
  }
6225
6236
  }
6237
+
6226
6238
  start += tokenizer.eatWhiteSpace(line, start);
6227
6239
  }
6228
6240
 
@@ -6397,6 +6409,7 @@ MusicParser.prototype.parseMusic = function (line) {
6397
6409
  // delayStartNewLine = true;
6398
6410
  // TODO-PER: Handle inline headers
6399
6411
  }
6412
+
6400
6413
  var overlayLevel = 0;
6401
6414
  while (i < line.length) {
6402
6415
  var startI = i;
@@ -6535,8 +6548,7 @@ MusicParser.prototype.parseMusic = function (line) {
6535
6548
  if (el.chord !== undefined) bar.chord = el.chord;
6536
6549
  if (bar.startEnding && multilineVars.barFirstEndingNum === undefined) multilineVars.barFirstEndingNum = multilineVars.currBarNumber;else if (bar.startEnding && bar.endEnding && multilineVars.barFirstEndingNum) multilineVars.currBarNumber = multilineVars.barFirstEndingNum;else if (bar.endEnding) multilineVars.barFirstEndingNum = undefined;
6537
6550
  if (bar.type !== 'bar_invisible' && multilineVars.measureNotEmpty) {
6538
- var isFirstVoice = multilineVars.currentVoice === undefined || multilineVars.currentVoice.staffNum === 0 && multilineVars.currentVoice.index === 0;
6539
- if (isFirstVoice) {
6551
+ if (isFirstVoice()) {
6540
6552
  multilineVars.currBarNumber++;
6541
6553
  if (multilineVars.barNumbers && multilineVars.currBarNumber % multilineVars.barNumbers === 0) bar.barNumber = multilineVars.currBarNumber;
6542
6554
  }
@@ -6731,6 +6743,7 @@ MusicParser.prototype.parseMusic = function (line) {
6731
6743
  if (el.startTie !== undefined) el.pitches[0].startTie = el.startTie;
6732
6744
  } else {
6733
6745
  el.rest = core.rest;
6746
+ if (core.rest.type === 'multimeasure' && isFirstVoice()) multilineVars.currBarNumber += core.rest.text - 1; // The minus one is because the measure with the rest is already counted once normally.
6734
6747
  if (core.endSlur !== undefined) el.endSlur = core.endSlur;
6735
6748
  if (core.endTie !== undefined) el.rest.endTie = core.endTie;
6736
6749
  if (core.startSlur !== undefined) el.startSlur = core.startSlur;
@@ -7191,8 +7204,7 @@ MusicParser.prototype.startNewLine = function () {
7191
7204
  if (params.currentVoice.staffNum === multilineVars.voices[voices[mv]].staffNum && params.currentVoice.index === multilineVars.voices[voices[mv]].index) params.currentVoiceName = voices[mv];
7192
7205
  }
7193
7206
  }
7194
- var isFirstVoice = multilineVars.currentVoice === undefined || multilineVars.currentVoice.staffNum === 0 && multilineVars.currentVoice.index === 0;
7195
- if (multilineVars.barNumbers === 0 && isFirstVoice && multilineVars.currBarNumber !== 1) params.barNumber = multilineVars.currBarNumber;
7207
+ if (multilineVars.barNumbers === 0 && isFirstVoice() && multilineVars.currBarNumber !== 1) params.barNumber = multilineVars.currBarNumber;
7196
7208
  tuneBuilder.startNewLine(params);
7197
7209
  if (multilineVars.key.impliedNaturals) delete multilineVars.key.impliedNaturals;
7198
7210
  multilineVars.partForNextLine = {};
@@ -7488,6 +7500,9 @@ var getBrokenRhythm = function getBrokenRhythm(line, index) {
7488
7500
  }
7489
7501
  return null;
7490
7502
  };
7503
+ function isFirstVoice() {
7504
+ return multilineVars.currentVoice === undefined || multilineVars.currentVoice.staffNum === 0 && multilineVars.currentVoice.index === 0;
7505
+ }
7491
7506
  module.exports = MusicParser;
7492
7507
 
7493
7508
  /***/ }),
@@ -7577,6 +7592,7 @@ var Tokenizer = function Tokenizer(lines, multilineVars) {
7577
7592
  }
7578
7593
  return str.length; // It must have been all white space
7579
7594
  };
7595
+
7580
7596
  var finished = function finished(str, i) {
7581
7597
  return i >= str.length;
7582
7598
  };
@@ -7637,6 +7653,7 @@ var Tokenizer = function Tokenizer(lines, multilineVars) {
7637
7653
  // case 'f':return {len: i+1, token: 'F'};
7638
7654
  // case 'g':return {len: i+1, token: 'G'};
7639
7655
  }
7656
+
7640
7657
  return {
7641
7658
  len: 0
7642
7659
  };
@@ -8468,6 +8485,7 @@ var Tokenizer = function Tokenizer(lines, multilineVars) {
8468
8485
 
8469
8486
  // More chars: IJ ij Ď ď Đ đ Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š Ţ ţ Ť ť Ŧ ŧ Ŵ ŵ Ź ź Ż ż Ž
8470
8487
  };
8488
+
8471
8489
  var charMap1 = {
8472
8490
  "#": "♯",
8473
8491
  "b": "♭",
@@ -9159,6 +9177,7 @@ function transposeChordName(chord, steps, preferFlats, freeGCchord) {
9159
9177
  }
9160
9178
  } else chord += bass; // Don't know what to do so do nothing
9161
9179
  }
9180
+
9162
9181
  if (extra2) chord += extra2;
9163
9182
  return chord;
9164
9183
  }
@@ -9369,6 +9388,7 @@ var TuneBuilder = function TuneBuilder(tune) {
9369
9388
  if (hashParams.rest && hashParams.rest.type === 'invisible') {
9370
9389
  delete hashParams.decoration; // the decorations on invisible rests should be invisible, too.
9371
9390
  }
9391
+
9372
9392
  if (tune.lines.length <= tune.lineNum || tune.lines[tune.lineNum].staff.length <= tune.staffNum) {
9373
9393
  //console.log("pushNote IGNORED", tune.lines[tune.lineNum])
9374
9394
  // TODO-PER: This prevents a crash, but it drops the element. Need to figure out how to start a new line, or delay adding this.
@@ -9556,7 +9576,7 @@ var TuneBuilder = function TuneBuilder(tune) {
9556
9576
  };
9557
9577
  this.getCurrentVoice = function () {
9558
9578
  //console.log("getCurrentVoice", tune.lineNum)
9559
- var currLine = tune.lines[tune.lineNum];
9579
+ var currLine = getPrevMusicLine(tune.lines, tune.lineNum);
9560
9580
  if (!currLine) return null;
9561
9581
  var currStaff = currLine.staff[tune.staffNum];
9562
9582
  if (!currStaff) return null;
@@ -9836,6 +9856,7 @@ function cleanUpSlursInLine(line, staffNum, voiceNum, currSlur) {
9836
9856
  obj.endSlur.push(slurNum);
9837
9857
  // lyr.syllable += '<' + slurNum; // TODO-PER: debugging
9838
9858
  }
9859
+
9839
9860
  if (currSlur[staffNum][voiceNum][chordPos].length === 0) delete currSlur[staffNum][voiceNum][chordPos];
9840
9861
  return slurNum;
9841
9862
  };
@@ -9978,6 +9999,14 @@ function wrapMusicLines(lines, barsperstaff) {
9978
9999
  }
9979
10000
  return false;
9980
10001
  }
10002
+ function getPrevMusicLine(lines, currentLine) {
10003
+ // If the current line doesn't have music, search backwards until one is found.
10004
+ while (currentLine >= 0) {
10005
+ if (lines[currentLine].staff) return lines[currentLine];
10006
+ currentLine--;
10007
+ }
10008
+ return null;
10009
+ }
9981
10010
  function getNextMusicLine(lines, currentLine) {
9982
10011
  currentLine++;
9983
10012
  while (lines.length > currentLine) {
@@ -11085,6 +11114,7 @@ var strTranspose;
11085
11114
  return 0;
11086
11115
  // this should never happen
11087
11116
  }
11117
+
11088
11118
  case '_':
11089
11119
  switch (thisAccidental) {
11090
11120
  case '__':
@@ -11101,6 +11131,7 @@ var strTranspose;
11101
11131
  return 0;
11102
11132
  // this should never happen
11103
11133
  }
11134
+
11104
11135
  case '^':
11105
11136
  switch (thisAccidental) {
11106
11137
  case '__':
@@ -11118,9 +11149,11 @@ var strTranspose;
11118
11149
  // this should never happen
11119
11150
  }
11120
11151
  }
11152
+
11121
11153
  return 0; // this should never happen
11122
11154
  }
11123
11155
  })();
11156
+
11124
11157
  module.exports = strTranspose;
11125
11158
 
11126
11159
  /***/ }),
@@ -11445,6 +11478,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11445
11478
  // console.log(JSON.stringify(voices))
11446
11479
  }
11447
11480
  }
11481
+
11448
11482
  function getBeatFraction(meter) {
11449
11483
  switch (parseInt(meter.den, 10)) {
11450
11484
  case 2:
@@ -11504,7 +11538,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11504
11538
  var shortestNote = durationRounded(1.0 / 32);
11505
11539
  switch (noteModification) {
11506
11540
  case "trill":
11507
- var note = 1;
11541
+ var note = 2;
11508
11542
  while (runningDuration > 0) {
11509
11543
  currentTrack.push({
11510
11544
  cmd: 'note',
@@ -11516,7 +11550,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11516
11550
  instrument: currentInstrument,
11517
11551
  style: 'decoration'
11518
11552
  });
11519
- note = note === 1 ? 0 : 1;
11553
+ note = note === 2 ? 0 : 2;
11520
11554
  runningDuration -= shortestNote;
11521
11555
  start += shortestNote;
11522
11556
  }
@@ -11536,7 +11570,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11536
11570
  start += shortestNote;
11537
11571
  currentTrack.push({
11538
11572
  cmd: 'note',
11539
- pitch: p.pitch + 1,
11573
+ pitch: p.pitch + 2,
11540
11574
  volume: p.volume,
11541
11575
  start: start,
11542
11576
  duration: shortestNote,
@@ -11571,7 +11605,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11571
11605
  start += shortestNote;
11572
11606
  currentTrack.push({
11573
11607
  cmd: 'note',
11574
- pitch: p.pitch - 1,
11608
+ pitch: p.pitch - 2,
11575
11609
  volume: p.volume,
11576
11610
  start: start,
11577
11611
  duration: shortestNote,
@@ -11592,10 +11626,10 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11592
11626
  });
11593
11627
  break;
11594
11628
  case "turn":
11595
- shortestNote = p.duration / 5;
11629
+ shortestNote = p.duration / 4;
11596
11630
  currentTrack.push({
11597
11631
  cmd: 'note',
11598
- pitch: p.pitch,
11632
+ pitch: p.pitch + 2,
11599
11633
  volume: p.volume,
11600
11634
  start: start,
11601
11635
  duration: shortestNote,
@@ -11605,7 +11639,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11605
11639
  });
11606
11640
  currentTrack.push({
11607
11641
  cmd: 'note',
11608
- pitch: p.pitch + 1,
11642
+ pitch: p.pitch,
11609
11643
  volume: p.volume,
11610
11644
  start: start + shortestNote,
11611
11645
  duration: shortestNote,
@@ -11615,7 +11649,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11615
11649
  });
11616
11650
  currentTrack.push({
11617
11651
  cmd: 'note',
11618
- pitch: p.pitch,
11652
+ pitch: p.pitch - 1,
11619
11653
  volume: p.volume,
11620
11654
  start: start + shortestNote * 2,
11621
11655
  duration: shortestNote,
@@ -11625,7 +11659,7 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11625
11659
  });
11626
11660
  currentTrack.push({
11627
11661
  cmd: 'note',
11628
- pitch: p.pitch + 1,
11662
+ pitch: p.pitch,
11629
11663
  volume: p.volume,
11630
11664
  start: start + shortestNote * 3,
11631
11665
  duration: shortestNote,
@@ -11633,15 +11667,6 @@ var pitchesToPerc = __webpack_require__(/*! ./pitches-to-perc */ "./src/synth/pi
11633
11667
  instrument: currentInstrument,
11634
11668
  style: 'decoration'
11635
11669
  });
11636
- currentTrack.push({
11637
- cmd: 'note',
11638
- pitch: p.pitch,
11639
- volume: p.volume,
11640
- start: start + shortestNote * 4,
11641
- duration: shortestNote,
11642
- gap: 0,
11643
- instrument: currentInstrument
11644
- });
11645
11670
  break;
11646
11671
  case "roll":
11647
11672
  while (runningDuration > 0) {
@@ -12220,6 +12245,7 @@ var rendererFactory;
12220
12245
  this.track += this.noteOnAndChannel;
12221
12246
  this.track += "%" + pitch.toString(16) + toHex(loudness, 2); //note
12222
12247
  };
12248
+
12223
12249
  Midi.prototype.endNote = function (pitch) {
12224
12250
  this.track += toDurationHex(this.silencelength); // only need to shift by amount of silence (if there is any)
12225
12251
  this.silencelength = 0;
@@ -12233,6 +12259,7 @@ var rendererFactory;
12233
12259
  this.track += this.noteOffAndChannel;
12234
12260
  this.track += "%" + pitch.toString(16) + "%00"; //end note
12235
12261
  };
12262
+
12236
12263
  Midi.prototype.addRest = function (length) {
12237
12264
  this.silencelength += length;
12238
12265
  if (this.silencelength < 0) this.silencelength = 0;
@@ -12269,6 +12296,7 @@ var rendererFactory;
12269
12296
  }
12270
12297
  return "%00%FF" + cmdType + toHex(nameArray.length / 3, 2) + nameArray; // Each byte is represented by three chars "%XX", so divide by 3 to get the length.
12271
12298
  }
12299
+
12272
12300
  function keySignature(key) {
12273
12301
  //00 FF 5902 03 00 - key signature
12274
12302
  if (!key || !key.accidentals) return "";
@@ -13058,6 +13086,7 @@ var parseCommon = __webpack_require__(/*! ../parse/abc_common */ "./src/parse/ab
13058
13086
  }
13059
13087
  }
13060
13088
  }
13089
+
13061
13090
  function chordVoiceOffThisBar(voices) {
13062
13091
  for (var i = 0; i < voices.length; i++) {
13063
13092
  var voice = voices[i];
@@ -13529,6 +13558,7 @@ ChordTrack.prototype.resolveChords = function (startTime, endTime) {
13529
13558
  if (newBass) newBass = false;else isBoom = false; // only the first note in a chord is a bass note. This handles the case where bass and chord are played at the same time.
13530
13559
  }
13531
13560
  }
13561
+
13532
13562
  return;
13533
13563
  };
13534
13564
  ChordTrack.prototype.processChord = function (elem) {
@@ -14584,6 +14614,7 @@ function CreateSynth() {
14584
14614
  self.directSource[trackNum].buffer = audioBuffer; // tell the source which sound to play
14585
14615
  self.directSource[trackNum].connect(activeAudioContext().destination); // connect the source to the context's destination (the speakers)
14586
14616
  });
14617
+
14587
14618
  self.directSource.forEach(function (source) {
14588
14619
  source.start(0, seconds);
14589
14620
  });
@@ -16769,6 +16800,7 @@ function convertToNumber(plugin, pitches, graceNotes) {
16769
16800
  plugin.setError(tabPos.error);
16770
16801
  return tabPos; // give up on error here
16771
16802
  }
16803
+
16772
16804
  if (tabPos.graces && tabPos.notes) {
16773
16805
  // add graces to last note in notes
16774
16806
  var posNote = tabPos.notes.length - 1;
@@ -16966,6 +16998,7 @@ function getLyricHeight(voice) {
16966
16998
  }
16967
16999
  return maxLyricHeight; // add spacing
16968
17000
  }
17001
+
16969
17002
  function buildTabName(plugin, renderer, dest) {
16970
17003
  var stringSemantics = plugin.semantics;
16971
17004
  var textSize = renderer.controller.getTextSize;
@@ -17044,6 +17077,7 @@ function getNextTabPos(tabIndex, staffGroup) {
17044
17077
  if (!staffGroup[startIndex].isTabStaff) {
17045
17078
  nbVoices = staffGroup[startIndex].voices.length; // get number of staff voices
17046
17079
  }
17080
+
17047
17081
  if (staffGroup[startIndex].isTabStaff) {
17048
17082
  handledVoices++;
17049
17083
  if (islastTabInStaff(startIndex, staffGroup)) {
@@ -17156,6 +17190,7 @@ function tabRenderer(plugin, renderer, line, staffIndex) {
17156
17190
  }
17157
17191
  linkStaffAndTabs(staffGroup.staffs); // crossreference tabs and staff
17158
17192
  }
17193
+
17159
17194
  module.exports = tabRenderer;
17160
17195
 
17161
17196
  /***/ }),
@@ -17375,6 +17410,7 @@ AbstractEngraver.prototype.createABCStaff = function (staffgroup, abcstaff, temp
17375
17410
  } else {
17376
17411
  voice.duplicate = true; // bar lines and other duplicate info need not be created
17377
17412
  }
17413
+
17378
17414
  if (abcstaff.title && abcstaff.title[v]) {
17379
17415
  voice.header = abcstaff.title[v].replace(/\\n/g, "\n");
17380
17416
  voice.headerPosition = 6 + staffgroup.getTextSize.baselineToCenter(voice.header, "voicefont", 'staff-extra voice-name', v, abcstaff.voices.length) / spacing.STEP;
@@ -17388,11 +17424,13 @@ AbstractEngraver.prototype.createABCStaff = function (staffgroup, abcstaff, temp
17388
17424
  voice.addChild(clef);
17389
17425
  this.startlimitelem = clef; // limit ties here
17390
17426
  }
17427
+
17391
17428
  var keySig = createKeySignature(abcstaff.key, this.tuneNumber);
17392
17429
  if (keySig) {
17393
17430
  voice.addChild(keySig);
17394
17431
  this.startlimitelem = keySig; // limit ties here
17395
17432
  }
17433
+
17396
17434
  if (abcstaff.meter) {
17397
17435
  if (abcstaff.meter.type === 'specified') {
17398
17436
  this.measureLength = abcstaff.meter.value[0].num / abcstaff.meter.value[0].den;
@@ -17401,6 +17439,7 @@ AbstractEngraver.prototype.createABCStaff = function (staffgroup, abcstaff, temp
17401
17439
  voice.addChild(ts);
17402
17440
  this.startlimitelem = ts; // limit ties here
17403
17441
  }
17442
+
17404
17443
  if (voice.duplicate) voice.children = []; // we shouldn't reprint the above if we're reusing the same staff. We just created them to get the right spacing.
17405
17444
  var staffLines = abcstaff.clef.stafflines || abcstaff.clef.stafflines === 0 ? abcstaff.clef.stafflines : 5;
17406
17445
  staffgroup.addVoice(voice, s, staffLines);
@@ -17564,6 +17603,7 @@ AbstractEngraver.prototype.createABCElement = function (isFirstStaff, isSingleLi
17564
17603
  elemset[0] = absKey;
17565
17604
  this.startlimitelem = elemset[0]; // limit ties here
17566
17605
  }
17606
+
17567
17607
  if (voice.duplicate && elemset.length > 0) elemset[0].invisible = true;
17568
17608
  break;
17569
17609
  case "stem":
@@ -17697,6 +17737,7 @@ AbstractEngraver.prototype.addGraceNotes = function (elem, voice, abselem, noteh
17697
17737
  if (hint) gracebeam.setHint();
17698
17738
  gracebeam.mainNote = abselem; // this gives us a reference back to the note this is attached to so that the stems can be attached somewhere.
17699
17739
  }
17740
+
17700
17741
  var i;
17701
17742
  var graceoffsets = [];
17702
17743
  for (i = elem.gracenotes.length - 1; i >= 0; i--) {
@@ -17796,6 +17837,7 @@ function addRestToAbsElement(abselem, elem, duration, dot, isMultiVoice, stemdir
17796
17837
  if (duration < 0.5) restpitch = 7;else if (duration < 1) restpitch = 7; // half rest
17797
17838
  else restpitch = 5; // whole rest
17798
17839
  }
17840
+
17799
17841
  switch (elem.rest.type) {
17800
17842
  case "whole":
17801
17843
  c = chartable.rest[0];
@@ -17934,6 +17976,7 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
17934
17976
  elem.pitches[p].highestVert = elem.pitches[pp - 1].verticalPos;
17935
17977
  if (getDuration(elem) < 1 && (stemdir === "up" || dir === "up")) elem.pitches[p].highestVert += 6; // If the stem is up, then compensate for the length of the stem
17936
17978
  }
17979
+
17937
17980
  if (elem.startSlur) {
17938
17981
  if (!elem.pitches[p].startSlur) elem.pitches[p].startSlur = []; //TODO possibly redundant, provided array is not optional
17939
17982
  for (i = 0; i < elem.startSlur.length; i++) {
@@ -18103,6 +18146,7 @@ AbstractEngraver.prototype.createNote = function (elem, nostem, isSingleLineStaf
18103
18146
  flatBeams: this.flatBeams
18104
18147
  }); // above is opposite from case of slurs
18105
18148
  }
18149
+
18106
18150
  if (elem.endTriplet && this.triplet) {
18107
18151
  this.triplet.setCloseAnchor(notehead);
18108
18152
  }
@@ -18201,7 +18245,8 @@ AbstractEngraver.prototype.addMeasureNumber = function (number, abselem) {
18201
18245
  if (abselem.isClef)
18202
18246
  // If this is a clef rather than bar line, then the number shouldn't be centered because it could overlap the left side. This is an easy way to let it be centered but move it over, too.
18203
18247
  dx += measureNumDim.width / 2;
18204
- var vert = measureNumDim.width > 10 && abselem.abcelem.type === "treble" ? 13 : 11;
18248
+ // MAE 1 Oct 2024 - Change 13 to 13.5 since previously bar numbers were very slightly overlapping the top of the clef
18249
+ var vert = measureNumDim.width > 10 && abselem.abcelem.type === "treble" ? 13.5 : 11;
18205
18250
  abselem.addFixed(new RelativeElement(number, dx, measureNumDim.width, vert + measureNumDim.height / spacing.STEP, {
18206
18251
  type: "barNumber",
18207
18252
  dim: this.getTextSize.attr("measurefont", 'bar-number')
@@ -18236,6 +18281,7 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
18236
18281
  abselem.addRight(new RelativeElement("dots.dot", dx, 1, 5));
18237
18282
  dx += 6; //2 hardcoded, twice;
18238
18283
  }
18284
+
18239
18285
  if (firstthin) {
18240
18286
  anchor = new RelativeElement(null, dx, 1, 2, {
18241
18287
  "type": "bar",
@@ -18284,6 +18330,7 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
18284
18330
  });
18285
18331
  abselem.addRight(anchor); // 3 is hardcoded
18286
18332
  }
18333
+
18287
18334
  if (seconddots) {
18288
18335
  dx += 3; //3 hardcoded;
18289
18336
  abselem.addRight(new RelativeElement("dots.dot", dx, 1, 7));
@@ -18617,6 +18664,7 @@ var createClef = function createClef(elem, tuneNumber) {
18617
18664
  //abselem.top += 2;
18618
18665
  }
18619
18666
  }
18667
+
18620
18668
  return abselem;
18621
18669
  };
18622
18670
  function clefOffsets(clef) {
@@ -18808,6 +18856,7 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
18808
18856
  }));
18809
18857
  extraLeft = glyphs.getSymbolWidth(symb) / 2; // TODO-PER: We need a little extra width if there is an accidental, but I'm not sure why it isn't the full width of the accidental.
18810
18858
  }
18859
+
18811
18860
  return {
18812
18861
  notehead: notehead,
18813
18862
  accidentalshiftx: accidentalshiftx,
@@ -19462,10 +19511,18 @@ AbsoluteElement.prototype.setLimit = function (member, child) {
19462
19511
  if (!this.specialY[member]) this.specialY[member] = child[member];else this.specialY[member] = Math.max(this.specialY[member], child[member]);
19463
19512
  };
19464
19513
  AbsoluteElement.prototype._addChild = function (child) {
19465
- // console.log("Relative:",child);
19514
+ // console.log("Relative:",child);
19515
+
19516
+ // MAE 30 Sep 2024 - To avoid extra space for chords if there is only a bar number on the clef
19517
+ var okToPushTop = true;
19518
+ if (this.abcelem.el_type == "clef" && child.type == "barNumber") {
19519
+ okToPushTop = false;
19520
+ }
19466
19521
  child.parent = this;
19467
19522
  this.children[this.children.length] = child;
19468
- this.pushTop(child.top);
19523
+ if (okToPushTop) {
19524
+ this.pushTop(child.top);
19525
+ }
19469
19526
  this.pushBottom(child.bottom);
19470
19527
  this.setLimit('tempoHeightAbove', child);
19471
19528
  this.setLimit('partHeightAbove', child);
@@ -19598,6 +19655,7 @@ BeamElem.prototype.setStemDirection = function () {
19598
19655
  var middleLine = 6; // hardcoded 6 is B
19599
19656
  this.stemsUp = this.average < middleLine; // true is up, false is down;
19600
19657
  }
19658
+
19601
19659
  delete this.count;
19602
19660
  this.total = 0;
19603
19661
  };
@@ -19611,6 +19669,7 @@ BeamElem.prototype.calcDir = function () {
19611
19669
  var middleLine = 6; // hardcoded 6 is B
19612
19670
  this.stemsUp = this.average < middleLine; // true is up, false is down;
19613
19671
  }
19672
+
19614
19673
  var dir = this.stemsUp ? 'up' : 'down';
19615
19674
  for (var i = 0; i < this.elems.length; i++) {
19616
19675
  for (var j = 0; j < this.elems[i].heads.length; j++) {
@@ -19800,6 +19859,7 @@ BraceElem.prototype.continuing = function (voice) {
19800
19859
  BraceElem.prototype.getWidth = function () {
19801
19860
  return 10; // TODO-PER: right now the drawing function doesn't vary the width at all. If it does in the future then this will change.
19802
19861
  };
19862
+
19803
19863
  BraceElem.prototype.isStartVoice = function (voice) {
19804
19864
  if (this.startVoice && this.startVoice.staff && this.startVoice.staff.voices.length > 0 && this.startVoice.staff.voices[0] === voice) return true;
19805
19865
  return false;
@@ -19824,6 +19884,7 @@ var CrescendoElem = function CrescendoElem(anchor1, anchor2, dir, positioning) {
19824
19884
  if (positioning === 'above') this.dynamicHeightAbove = 6;else this.dynamicHeightBelow = 6;
19825
19885
  this.pitch = undefined; // This will be set later
19826
19886
  };
19887
+
19827
19888
  module.exports = CrescendoElem;
19828
19889
 
19829
19890
  /***/ }),
@@ -19843,6 +19904,7 @@ var DynamicDecoration = function DynamicDecoration(anchor, dec, position) {
19843
19904
  if (position === 'below') this.volumeHeightBelow = 6;else this.volumeHeightAbove = 6;
19844
19905
  this.pitch = undefined; // This will be set later
19845
19906
  };
19907
+
19846
19908
  module.exports = DynamicDecoration;
19847
19909
 
19848
19910
  /***/ }),
@@ -19863,6 +19925,7 @@ var EndingElem = function EndingElem(text, anchor1, anchor2) {
19863
19925
  this.endingHeightAbove = 5;
19864
19926
  this.pitch = undefined; // This will be set later
19865
19927
  };
19928
+
19866
19929
  module.exports = EndingElem;
19867
19930
 
19868
19931
  /***/ }),
@@ -19968,6 +20031,7 @@ var GlissandoElem = function GlissandoElem(anchor1, anchor2) {
19968
20031
  this.anchor1 = anchor1; // must have a .x and a .parent property or be null (means starts at the "beginning" of the line - after keysig)
19969
20032
  this.anchor2 = anchor2; // must have a .x property or be null (means ends at the end of the line)
19970
20033
  };
20034
+
19971
20035
  module.exports = GlissandoElem;
19972
20036
 
19973
20037
  /***/ }),
@@ -20502,12 +20566,14 @@ TieElem.prototype.calcX = function (lineStartX, lineEndX) {
20502
20566
  if (this.anchor2) this.startX = this.anchor2.x - 20; // There is no element and no repeat mark: make a small arc
20503
20567
  else this.startX = lineStartX; // Don't have any guidance, so extend to beginning of line
20504
20568
  }
20569
+
20505
20570
  if (!this.anchor1 && this.dotted) this.startX -= 3; // The arc needs to be long enough to tell that it is dotted.
20506
20571
 
20507
20572
  if (this.anchor2) this.endX = this.anchor2.x; // The normal case where there is a starting element to attach to.
20508
20573
  else if (this.endLimitX) this.endX = this.endLimitX.x; // if there is no start element, but there is a repeat mark before the start of the line.
20509
20574
  else this.endX = lineEndX; // There is no element and no repeat mark: extend to the beginning of the line.
20510
20575
  };
20576
+
20511
20577
  TieElem.prototype.calcTieY = function () {
20512
20578
  // If the tie comes from another line, then one or both anchors will be missing.
20513
20579
  if (this.anchor1) this.startY = this.anchor1.pitch;else if (this.anchor2) this.startY = this.anchor2.pitch;else this.startY = this.above ? 14 : 0;
@@ -20644,6 +20710,7 @@ function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, padd
20644
20710
 
20645
20711
  // TopText.prototype.addTextIf = function (marginLeft, text, font, klass, marginTop, marginBottom, anchor, getTextSize, absElemType, noMove) {
20646
20712
  }
20713
+
20647
20714
  if (isPrint) this.rows.push({
20648
20715
  move: spacing.top
20649
20716
  });
@@ -21715,6 +21782,7 @@ function straightPath(renderer, xLeft, yTop, yBottom, type) {
21715
21782
  // right point
21716
21783
  -wCurve * 0.1, -hCurve * 0.3, -wCurve, -hCurve - spacing.STEP // left bottom
21717
21784
  );
21785
+
21718
21786
  return renderer.paper.path({
21719
21787
  path: pathString,
21720
21788
  stroke: renderer.foregroundColor,
@@ -22993,6 +23061,7 @@ function drawStaffGroup(renderer, params, selectables, lineNumber) {
22993
23061
  // renderer.moveY(spacing.STEP, -staff.bottom);
22994
23062
  }
22995
23063
  }
23064
+
22996
23065
  renderer.controller.classes.newMeasure();
22997
23066
 
22998
23067
  // connect all the staves together with a vertical line
@@ -23214,6 +23283,7 @@ function drawTempo(renderer, params) {
23214
23283
  // });
23215
23284
  //return [tempoGroup];
23216
23285
  }
23286
+
23217
23287
  module.exports = drawTempo;
23218
23288
 
23219
23289
  /***/ }),
@@ -23550,6 +23620,7 @@ function drawVoice(renderer, params, bartop, selectables, staffPos) {
23550
23620
  renderer.controller.classes.incrMeasure();
23551
23621
  } else drawBeam(renderer, beam, selectables); // beams must be drawn first for proper printing of triplets, slurs and ties.
23552
23622
  }
23623
+
23553
23624
  renderer.controller.classes.startMeasure();
23554
23625
  for (i = 0; i < params.otherchildren.length; i++) {
23555
23626
  child = params.otherchildren[i];
@@ -23658,6 +23729,7 @@ var EngraverController = function EngraverController(paper, params) {
23658
23729
  this.staffwidthScreen = 740; // TODO-PER: Not sure where this number comes from, but this is how it's always been.
23659
23730
  this.staffwidthPrint = 680; // The number of pixels in 8.5", after 1cm of margin has been removed.
23660
23731
  }
23732
+
23661
23733
  this.listeners = [];
23662
23734
  if (params.clickListener) this.addSelectListener(params.clickListener);
23663
23735
  this.renderer = new Renderer(paper);
@@ -24567,6 +24639,7 @@ function getMousePosition(self, ev) {
24567
24639
  clickedOn = findElementByCoord(self, x, y);
24568
24640
  //console.log("clicked near", clickedOn, x, y, printEl(ev.target));
24569
24641
  }
24642
+
24570
24643
  return {
24571
24644
  x: x,
24572
24645
  y: y,
@@ -24804,6 +24877,7 @@ function minStem(element, stemsUp, referencePitch, minStemHeight) {
24804
24877
  var elem = element.children[i];
24805
24878
  if (stemsUp && elem.top !== undefined && elem.c === "flags.ugrace") minStemHeight = Math.max(minStemHeight, elem.top - referencePitch);else if (!stemsUp && elem.bottom !== undefined && elem.c === "flags.ugrace") minStemHeight = Math.max(minStemHeight, referencePitch - elem.bottom + 7); // The extra 7 is because we are measuring the slash from the top.
24806
24879
  }
24880
+
24807
24881
  return minStemHeight;
24808
24882
  }
24809
24883
  function calcSlant(leftAveragePitch, rightAveragePitch, numStems, isFlat) {
@@ -25208,6 +25282,7 @@ function calcHorizontalSpacing(isLastLine, stretchLast, targetWidth, lineWidth,
25208
25282
  if (!stretch) return null; // don't stretch last line too much
25209
25283
  }
25210
25284
  }
25285
+
25211
25286
  if (Math.abs(targetWidth - lineWidth) < 2) return null; // if we are already near the target width, we're done.
25212
25287
  var relSpace = spacingUnits * spacing;
25213
25288
  var constSpace = lineWidth - relSpace;
@@ -25272,6 +25347,7 @@ var setUpperAndLowerElements = function setUpperAndLowerElements(renderer, staff
25272
25347
  staff.originalTop = staff.top; // This is just being stored for debugging purposes.
25273
25348
  staff.originalBottom = staff.bottom; // This is just being stored for debugging purposes.
25274
25349
  }
25350
+
25275
25351
  incTop(staff, positionY, 'lyricHeightAbove');
25276
25352
  incTop(staff, positionY, 'chordHeightAbove', staff.specialY.chordLines.above);
25277
25353
  if (staff.specialY.endingHeightAbove) {
@@ -25334,6 +25410,7 @@ var setUpperAndLowerElements = function setUpperAndLowerElements(renderer, staff
25334
25410
  }
25335
25411
  //console.log("Staff Height: ",heightInPitches,this.height);
25336
25412
  };
25413
+
25337
25414
  var margin = 1;
25338
25415
  function incTop(staff, positionY, item, count) {
25339
25416
  if (staff.specialY[item]) {
@@ -25598,6 +25675,7 @@ function finished(voices) {
25598
25675
  function getDurationIndex(element) {
25599
25676
  return element.durationindex - (element.children[element.i] && element.children[element.i].duration > 0 ? 0 : 0.0000005); // if the ith element doesn't have a duration (is not a note), its duration index is fractionally before. This enables CLEF KEYSIG TIMESIG PART, etc. to be laid out before we get to the first note of other voices
25600
25677
  }
25678
+
25601
25679
  function isSameStaff(voice1, voice2) {
25602
25680
  if (!voice1 || !voice1.staff || !voice1.staff.voices || voice1.staff.voices.length === 0) return false;
25603
25681
  if (!voice2 || !voice2.staff || !voice2.staff.voices || voice2.staff.voices.length === 0) return false;
@@ -25695,6 +25773,7 @@ VoiceElement.beginLayout = function (startx, voice) {
25695
25773
  voice.nextx = startx; // x position where the next element of this voice should be placed assuming no other voices and no fixed width constraints
25696
25774
  voice.spacingduration = 0; // duration left to be laid out in current iteration (omitting additional spacing due to other aspects, such as bars, dots, sharps and flats)
25697
25775
  };
25776
+
25698
25777
  VoiceElement.layoutEnded = function (voice) {
25699
25778
  return voice.i >= voice.children.length;
25700
25779
  };
@@ -25760,6 +25839,7 @@ VoiceElement.layoutOneItem = function (x, spacing, voice, minPadding, firstVoice
25760
25839
 
25761
25840
  return x; // where we end up having placed the child
25762
25841
  };
25842
+
25763
25843
  VoiceElement.shiftRight = function (dx, voice) {
25764
25844
  var child = voice.children[voice.i];
25765
25845
  if (!child) return;
@@ -25922,6 +26002,7 @@ function setLane(absElems, numLanesAbove, numLanesBelow) {
25922
26002
  }
25923
26003
  }
25924
26004
  }
26005
+
25925
26006
  function yAtNote(element, beam) {
25926
26007
  beam = beam.beams[0];
25927
26008
  return getBarYAt(beam.startX, beam.startY, beam.endX, beam.endY, element.x);
@@ -26080,6 +26161,7 @@ Renderer.prototype.initVerticalSpace = function () {
26080
26161
  <float> range is 0.0 to 1.0.
26081
26162
  */
26082
26163
  };
26164
+
26083
26165
  Renderer.prototype.setVerticalSpace = function (formatting) {
26084
26166
  // conversion from pts to px 4/3
26085
26167
  if (formatting.staffsep !== undefined) this.spacing.staffSeparation = formatting.staffsep * 4 / 3;
@@ -26201,6 +26283,7 @@ Svg.prototype.insertStyles = function (styles) {
26201
26283
  this.svg.insertBefore(el, this.svg.firstChild); // prepend is not available on older browsers.
26202
26284
  // this.svg.prepend(el);
26203
26285
  };
26286
+
26204
26287
  Svg.prototype.setParentStyles = function (attr) {
26205
26288
  // This is needed to get the size right when there is scaling involved.
26206
26289
  for (var key in attr) {
@@ -26343,6 +26426,7 @@ Svg.prototype.guessWidth = function (text, attr) {
26343
26426
  height: attr['font-size'] + 2
26344
26427
  }; // Just a wild guess.
26345
26428
  }
26429
+
26346
26430
  svg.removeChild(el);
26347
26431
  return size;
26348
26432
  };
@@ -26471,7 +26555,7 @@ module.exports = Svg;
26471
26555
  \********************/
26472
26556
  /***/ (function(module) {
26473
26557
 
26474
- var version = '6.4.3';
26558
+ var version = '6.4.4';
26475
26559
  module.exports = version;
26476
26560
 
26477
26561
  /***/ })