abcjs 6.4.2 → 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.
- package/LICENSE.md +1 -1
- package/RELEASE.md +28 -1
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic-min.js.LICENSE +1 -1
- package/dist/abcjs-basic.js +98 -32
- 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/data/abc_tune.js +2 -0
- package/src/parse/abc_parse_music.js +40 -21
- package/src/parse/tune-builder.js +11 -1
- package/src/synth/abc_midi_flattener.js +9 -10
- package/src/synth/chord-track.js +9 -0
- package/src/test/abc_midi_sequencer_lint.js +1 -1
- package/src/write/creation/abstract-engraver.js +2 -1
- package/src/write/creation/elements/absolute-element.js +27 -16
- package/src/write/creation/elements/tie-element.js +26 -0
- package/src/write/layout/set-upper-and-lower-elements.js +8 -0
- package/test.js +1 -1
- package/types/index.d.ts +1 -1
- package/version.js +1 -1
- package/temp.txt +0 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**!
|
|
2
|
-
Copyright (c) 2009-
|
|
2
|
+
Copyright (c) 2009-2024 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/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**!
|
|
2
|
-
Copyright (c) 2009-
|
|
2
|
+
Copyright (c) 2009-2024 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/license.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**!
|
|
2
|
-
Copyright (c) 2009-
|
|
2
|
+
Copyright (c) 2009-2024 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/package.json
CHANGED
package/plugin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**!
|
|
2
|
-
Copyright (c) 2009-
|
|
2
|
+
Copyright (c) 2009-2024 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/src/data/abc_tune.js
CHANGED
|
@@ -294,8 +294,7 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
294
294
|
else if (bar.endEnding)
|
|
295
295
|
multilineVars.barFirstEndingNum = undefined;
|
|
296
296
|
if (bar.type !== 'bar_invisible' && multilineVars.measureNotEmpty) {
|
|
297
|
-
|
|
298
|
-
if (isFirstVoice) {
|
|
297
|
+
if (isFirstVoice()) {
|
|
299
298
|
multilineVars.currBarNumber++;
|
|
300
299
|
if (multilineVars.barNumbers && multilineVars.currBarNumber % multilineVars.barNumbers === 0)
|
|
301
300
|
bar.barNumber = multilineVars.currBarNumber;
|
|
@@ -510,6 +509,8 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
510
509
|
if (el.startTie !== undefined) el.pitches[0].startTie = el.startTie;
|
|
511
510
|
} else {
|
|
512
511
|
el.rest = core.rest;
|
|
512
|
+
if (core.rest.type === 'multimeasure' && isFirstVoice())
|
|
513
|
+
multilineVars.currBarNumber += core.rest.text - 1 // The minus one is because the measure with the rest is already counted once normally.
|
|
513
514
|
if (core.endSlur !== undefined) el.endSlur = core.endSlur;
|
|
514
515
|
if (core.endTie !== undefined) el.rest.endTie = core.endTie;
|
|
515
516
|
if (core.startSlur !== undefined) el.startSlur = core.startSlur;
|
|
@@ -615,23 +616,38 @@ var letter_to_chord = function(line, i) {
|
|
|
615
616
|
chord[1] = chord[1].substring(1);
|
|
616
617
|
chord[2] = 'right';
|
|
617
618
|
} else if (chord[0] > 0 && chord[1].length > 0 && chord[1][0] === '@') {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
chord[1] = chord[1].
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
chord[1] = chord[1].
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
619
|
+
// @-15,5.7
|
|
620
|
+
chord[1] = chord[1].substring(1);
|
|
621
|
+
var x = tokenizer.getFloat(chord[1]);
|
|
622
|
+
if (x.digits === 0){
|
|
623
|
+
warn("Missing first position in absolutely positioned annotation.", line, i);
|
|
624
|
+
chord[1] = chord[1].replace("@","");
|
|
625
|
+
chord[2] = 'above';
|
|
626
|
+
return chord;
|
|
627
|
+
}
|
|
628
|
+
chord[1] = chord[1].substring(x.digits);
|
|
629
|
+
if (chord[1][0] !== ','){
|
|
630
|
+
warn("Missing comma absolutely positioned annotation.", line, i);
|
|
631
|
+
chord[1] = chord[1].replace("@","");
|
|
632
|
+
chord[2] = 'above';
|
|
633
|
+
return chord;
|
|
634
|
+
}
|
|
635
|
+
chord[1] = chord[1].substring(1);
|
|
636
|
+
var y = tokenizer.getFloat(chord[1]);
|
|
637
|
+
if (y.digits === 0){
|
|
638
|
+
warn("Missing second position in absolutely positioned annotation.", line, i);
|
|
639
|
+
chord[1] = chord[1].replace("@","");
|
|
640
|
+
chord[2] = 'above';
|
|
641
|
+
return chord;
|
|
642
|
+
}
|
|
643
|
+
chord[1] = chord[1].substring(y.digits);
|
|
644
|
+
var ws = tokenizer.skipWhiteSpace(chord[1]);
|
|
645
|
+
chord[1] = chord[1].substring(ws);
|
|
646
|
+
chord[2] = null;
|
|
647
|
+
chord[3] = {
|
|
648
|
+
x: x.value,
|
|
649
|
+
y: y.value
|
|
650
|
+
};
|
|
635
651
|
} else {
|
|
636
652
|
if (multilineVars.freegchord !== true) {
|
|
637
653
|
chord[1] = chord[1].replace(/([ABCDEFG0-9])b/g, "$1♭");
|
|
@@ -1015,8 +1031,7 @@ MusicParser.prototype.startNewLine = function() {
|
|
|
1015
1031
|
params.currentVoiceName = voices[mv]
|
|
1016
1032
|
}
|
|
1017
1033
|
}
|
|
1018
|
-
|
|
1019
|
-
if (multilineVars.barNumbers === 0 && isFirstVoice && multilineVars.currBarNumber !== 1)
|
|
1034
|
+
if (multilineVars.barNumbers === 0 && isFirstVoice() && multilineVars.currBarNumber !== 1)
|
|
1020
1035
|
params.barNumber = multilineVars.currBarNumber;
|
|
1021
1036
|
tuneBuilder.startNewLine(params);
|
|
1022
1037
|
if (multilineVars.key.impliedNaturals)
|
|
@@ -1300,4 +1315,8 @@ var getBrokenRhythm = function(line, index) {
|
|
|
1300
1315
|
return null;
|
|
1301
1316
|
};
|
|
1302
1317
|
|
|
1318
|
+
function isFirstVoice() {
|
|
1319
|
+
return multilineVars.currentVoice === undefined || (multilineVars.currentVoice.staffNum === 0 && multilineVars.currentVoice.index === 0);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1303
1322
|
module.exports = MusicParser;
|
|
@@ -382,7 +382,7 @@ var TuneBuilder = function (tune) {
|
|
|
382
382
|
|
|
383
383
|
this.getCurrentVoice = function () {
|
|
384
384
|
//console.log("getCurrentVoice", tune.lineNum)
|
|
385
|
-
var currLine = tune.lines
|
|
385
|
+
var currLine = getPrevMusicLine(tune.lines, tune.lineNum)
|
|
386
386
|
if (!currLine)
|
|
387
387
|
return null;
|
|
388
388
|
var currStaff = currLine.staff[tune.staffNum];
|
|
@@ -803,6 +803,16 @@ function wrapMusicLines(lines, barsperstaff) {
|
|
|
803
803
|
return false;
|
|
804
804
|
}
|
|
805
805
|
|
|
806
|
+
function getPrevMusicLine(lines, currentLine) {
|
|
807
|
+
// If the current line doesn't have music, search backwards until one is found.
|
|
808
|
+
while (currentLine >= 0) {
|
|
809
|
+
if (lines[currentLine].staff)
|
|
810
|
+
return lines[currentLine];
|
|
811
|
+
currentLine--;
|
|
812
|
+
}
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
|
|
806
816
|
function getNextMusicLine(lines, currentLine) {
|
|
807
817
|
currentLine++;
|
|
808
818
|
while (lines.length > currentLine) {
|
|
@@ -415,10 +415,10 @@ var pitchesToPerc = require('./pitches-to-perc');
|
|
|
415
415
|
|
|
416
416
|
switch (noteModification) {
|
|
417
417
|
case "trill":
|
|
418
|
-
var note =
|
|
418
|
+
var note = 2;
|
|
419
419
|
while (runningDuration > 0) {
|
|
420
420
|
currentTrack.push({ cmd: 'note', pitch: p.pitch+note, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
421
|
-
note = (note ===
|
|
421
|
+
note = (note === 2) ? 0 : 2;
|
|
422
422
|
runningDuration -= shortestNote;
|
|
423
423
|
start += shortestNote;
|
|
424
424
|
}
|
|
@@ -427,7 +427,7 @@ var pitchesToPerc = require('./pitches-to-perc');
|
|
|
427
427
|
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
428
428
|
runningDuration -= shortestNote;
|
|
429
429
|
start += shortestNote;
|
|
430
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch+
|
|
430
|
+
currentTrack.push({ cmd: 'note', pitch: p.pitch+2, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
431
431
|
runningDuration -= shortestNote;
|
|
432
432
|
start += shortestNote;
|
|
433
433
|
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start, duration: runningDuration, gap: 0, instrument: currentInstrument });
|
|
@@ -436,18 +436,17 @@ var pitchesToPerc = require('./pitches-to-perc');
|
|
|
436
436
|
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
437
437
|
runningDuration -= shortestNote;
|
|
438
438
|
start += shortestNote;
|
|
439
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch-
|
|
439
|
+
currentTrack.push({ cmd: 'note', pitch: p.pitch-2, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
440
440
|
runningDuration -= shortestNote;
|
|
441
441
|
start += shortestNote;
|
|
442
442
|
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start, duration: runningDuration, gap: 0, instrument: currentInstrument });
|
|
443
443
|
break;
|
|
444
444
|
case "turn":
|
|
445
|
-
shortestNote = p.duration /
|
|
446
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
447
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch
|
|
448
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start+shortestNote*2, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
449
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch
|
|
450
|
-
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start+shortestNote*4, duration: shortestNote, gap: 0, instrument: currentInstrument });
|
|
445
|
+
shortestNote = p.duration / 4;
|
|
446
|
+
currentTrack.push({ cmd: 'note', pitch: p.pitch+2, volume: p.volume, start: start, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
447
|
+
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start+shortestNote, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
448
|
+
currentTrack.push({ cmd: 'note', pitch: p.pitch-1, volume: p.volume, start: start+shortestNote*2, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
449
|
+
currentTrack.push({ cmd: 'note', pitch: p.pitch, volume: p.volume, start: start+shortestNote*3, duration: shortestNote, gap: 0, instrument: currentInstrument, style: 'decoration' });
|
|
451
450
|
break;
|
|
452
451
|
case "roll":
|
|
453
452
|
while (runningDuration > 0) {
|
package/src/synth/chord-track.js
CHANGED
|
@@ -198,6 +198,15 @@ ChordTrack.prototype.interpretChord = function (name) {
|
|
|
198
198
|
while (chordTranspose > 8)
|
|
199
199
|
chordTranspose -= 12;
|
|
200
200
|
bass += chordTranspose;
|
|
201
|
+
|
|
202
|
+
// MAE 31 Aug 2024 - For visual transpose backup range issue
|
|
203
|
+
// If transposed below A or above G, bring it back in the normal backup range
|
|
204
|
+
if (bass < 33){
|
|
205
|
+
bass += 12;
|
|
206
|
+
}
|
|
207
|
+
else if (bass > 44){
|
|
208
|
+
bass -= 12;
|
|
209
|
+
}
|
|
201
210
|
|
|
202
211
|
// MAE 17 Jun 2024 - Supporting octave shifted bass and chords
|
|
203
212
|
var unshiftedBass = bass;
|
|
@@ -943,7 +943,8 @@ AbstractEngraver.prototype.addMeasureNumber = function (number, abselem) {
|
|
|
943
943
|
var dx = 0;
|
|
944
944
|
if (abselem.isClef) // 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.
|
|
945
945
|
dx += measureNumDim.width / 2
|
|
946
|
-
|
|
946
|
+
// MAE 1 Oct 2024 - Change 13 to 13.5 since previously bar numbers were very slightly overlapping the top of the clef
|
|
947
|
+
var vert = measureNumDim.width > 10 && abselem.abcelem.type === "treble" ? 13.5 : 11
|
|
947
948
|
abselem.addFixed(new RelativeElement(number, dx, measureNumDim.width, vert + measureNumDim.height / spacing.STEP, { type: "barNumber", dim: this.getTextSize.attr("measurefont", 'bar-number') }));
|
|
948
949
|
};
|
|
949
950
|
|
|
@@ -177,22 +177,33 @@ AbsoluteElement.prototype.setLimit = function (member, child) {
|
|
|
177
177
|
};
|
|
178
178
|
|
|
179
179
|
AbsoluteElement.prototype._addChild = function (child) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
180
|
+
// console.log("Relative:",child);
|
|
181
|
+
|
|
182
|
+
// MAE 30 Sep 2024 - To avoid extra space for chords if there is only a bar number on the clef
|
|
183
|
+
var okToPushTop = true;
|
|
184
|
+
if ((this.abcelem.el_type == "clef") && (child.type == "barNumber")){
|
|
185
|
+
okToPushTop = false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
child.parent = this;
|
|
189
|
+
this.children[this.children.length] = child;
|
|
190
|
+
|
|
191
|
+
if (okToPushTop){
|
|
192
|
+
this.pushTop(child.top);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
this.pushBottom(child.bottom);
|
|
196
|
+
this.setLimit('tempoHeightAbove', child);
|
|
197
|
+
this.setLimit('partHeightAbove', child);
|
|
198
|
+
this.setLimit('volumeHeightAbove', child);
|
|
199
|
+
this.setLimit('dynamicHeightAbove', child);
|
|
200
|
+
this.setLimit('endingHeightAbove', child);
|
|
201
|
+
this.setLimit('chordHeightAbove', child);
|
|
202
|
+
this.setLimit('lyricHeightAbove', child);
|
|
203
|
+
this.setLimit('lyricHeightBelow', child);
|
|
204
|
+
this.setLimit('chordHeightBelow', child);
|
|
205
|
+
this.setLimit('volumeHeightBelow', child);
|
|
206
|
+
this.setLimit('dynamicHeightBelow', child);
|
|
196
207
|
};
|
|
197
208
|
|
|
198
209
|
AbsoluteElement.prototype.pushTop = function (top) {
|
|
@@ -225,4 +225,30 @@ TieElem.prototype.avoidCollisionAbove = function () {
|
|
|
225
225
|
}
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
+
TieElem.prototype.getYBounds = function () {
|
|
229
|
+
var lineStartX = 10 // TODO-PER: I'm not sure where to get this number from but it probably doesn't matter much
|
|
230
|
+
var lineEndX = 1000 // TODO-PER: I'm not sure where to get this number from but it probably doesn't matter much
|
|
231
|
+
if (this.isTie) {
|
|
232
|
+
this.calcTieDirection();
|
|
233
|
+
this.calcX(lineStartX, lineEndX);
|
|
234
|
+
this.calcTieY();
|
|
235
|
+
|
|
236
|
+
} else {
|
|
237
|
+
this.calcSlurDirection();
|
|
238
|
+
this.calcX(lineStartX, lineEndX);
|
|
239
|
+
this.calcSlurY();
|
|
240
|
+
}
|
|
241
|
+
var top;
|
|
242
|
+
var bottom;
|
|
243
|
+
// TODO-PER: It's hard to tell how far the arc is, so I'm just using 3 as the max
|
|
244
|
+
if (this.above) {
|
|
245
|
+
bottom = Math.min(this.startY, this.endY)
|
|
246
|
+
top = bottom + 3
|
|
247
|
+
} else {
|
|
248
|
+
top = Math.min(this.startY, this.endY)
|
|
249
|
+
bottom = top - 3
|
|
250
|
+
}
|
|
251
|
+
return [ top, bottom ]
|
|
252
|
+
};
|
|
253
|
+
|
|
228
254
|
module.exports = TieElem;
|
|
@@ -128,6 +128,14 @@ function setUpperAndLowerVoiceElements(positionY, voice, spacing) {
|
|
|
128
128
|
case 'EndingElem':
|
|
129
129
|
setUpperAndLowerEndingElements(positionY, abselem);
|
|
130
130
|
break;
|
|
131
|
+
case 'TieElem':
|
|
132
|
+
// If a tie element is the highest or lowest thing then space might need to make room for it.
|
|
133
|
+
var yBounds = abselem.getYBounds()
|
|
134
|
+
voice.staff.top = Math.max(voice.staff.top, yBounds[0])
|
|
135
|
+
voice.staff.top = Math.max(voice.staff.top, yBounds[1])
|
|
136
|
+
voice.staff.bottom = Math.min(voice.staff.bottom, yBounds[0])
|
|
137
|
+
voice.staff.bottom = Math.min(voice.staff.bottom, yBounds[1])
|
|
138
|
+
break;
|
|
131
139
|
}
|
|
132
140
|
}
|
|
133
141
|
}
|
package/test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**!
|
|
2
|
-
Copyright (c) 2009-
|
|
2
|
+
Copyright (c) 2009-2024 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/types/index.d.ts
CHANGED
|
@@ -886,7 +886,7 @@ declare module 'abcjs' {
|
|
|
886
886
|
getBarLength: NumberFunction;
|
|
887
887
|
getBeatLength: NumberFunction;
|
|
888
888
|
getBeatsPerMeasure: NumberFunction;
|
|
889
|
-
getBpm:
|
|
889
|
+
getBpm: (tempo?:TempoProperties) => number;
|
|
890
890
|
getMeter: () => Meter;
|
|
891
891
|
getMeterFraction: () => MeterFraction;
|
|
892
892
|
getPickupLength: NumberFunction;
|
package/version.js
CHANGED
package/temp.txt
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
commit 747c5538cdfbb37eb6234356944b05855ff2921a
|
|
2
|
-
Author: paulrosen <junk@paulrosen.net>
|
|
3
|
-
Date: Sun Aug 4 10:08:14 2024 -0400
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
commit 5b3d3d0f3f951e6dea3c22ded60b6baa9776e64c
|
|
8
|
-
Author: paulrosen <junk@paulrosen.net>
|
|
9
|
-
Date: Sun Jul 28 19:20:32 2024 -0400
|
|
10
|
-
|
|
11
|
-
Start to refactor tablature and flatten the structure.
|
|
12
|
-
|