abcjs 6.4.1 → 6.4.3
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 +46 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic-min.js.LICENSE +1 -1
- package/dist/abcjs-basic.js +1271 -1179
- 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_tunebook.js +1 -2
- package/src/api/abc_tunebook_svg.js +0 -1
- package/src/data/abc_tune.js +2 -0
- package/src/midi/abc_midi_create.js +22 -7
- package/src/parse/abc_common.js +3 -11
- package/src/parse/abc_parse.js +1 -1
- package/src/parse/abc_parse_directive.js +44 -3
- package/src/parse/abc_parse_header.js +6 -4
- package/src/parse/abc_parse_key_voice.js +10 -6
- package/src/parse/abc_parse_music.js +54 -22
- package/src/parse/tune-builder.js +675 -643
- package/src/synth/abc_midi_flattener.js +3 -1
- package/src/synth/abc_midi_sequencer.js +18 -3
- package/src/synth/chord-track.js +90 -18
- package/src/synth/create-synth-control.js +1 -2
- package/src/tablatures/abc_tablatures.js +184 -0
- package/src/tablatures/instruments/string-patterns.js +266 -268
- package/src/tablatures/instruments/string-tablature.js +38 -35
- package/src/tablatures/instruments/tab-note.js +186 -181
- package/src/tablatures/instruments/tab-notes.js +30 -35
- package/src/tablatures/instruments/tab-string.js +43 -25
- package/src/tablatures/render/tab-absolute-elements.js +303 -0
- package/src/tablatures/render/tab-renderer.js +244 -0
- package/src/test/abc_parser_lint.js +2 -3
- package/src/write/creation/abstract-engraver.js +1 -1
- package/src/write/creation/elements/tie-element.js +26 -0
- package/src/write/engraver-controller.js +1 -1
- package/src/write/layout/set-upper-and-lower-elements.js +8 -0
- package/test.js +1 -1
- package/types/index.d.ts +2 -2
- package/version.js +1 -1
- package/src/api/abc_tablatures.js +0 -184
- package/src/tablatures/instruments/tab-string-patterns.js +0 -23
- package/src/tablatures/tab-absolute-elements.js +0 -301
- package/src/tablatures/tab-common.js +0 -29
- package/src/tablatures/tab-renderer.js +0 -259
|
@@ -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/api/abc_tunebook.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var Parse = require('../parse/abc_parse');
|
|
4
4
|
var bookParser = require('../parse/abc_parse_book');
|
|
5
|
-
var tablatures = require('
|
|
5
|
+
var tablatures = require('../tablatures/abc_tablatures');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
var tunebook = {};
|
|
@@ -87,7 +87,6 @@ var tunebook = {};
|
|
|
87
87
|
// Init tablatures plugins
|
|
88
88
|
//
|
|
89
89
|
if (params.tablature) {
|
|
90
|
-
tablatures.init();
|
|
91
90
|
tune.tablatures = tablatures.preparePlugins(tune, currentTune, params);
|
|
92
91
|
}
|
|
93
92
|
var warnings = abcParser.getWarnings();
|
|
@@ -4,7 +4,6 @@ var Tune = require('../data/abc_tune');
|
|
|
4
4
|
var EngraverController = require('../write/engraver-controller');
|
|
5
5
|
var Parse = require('../parse/abc_parse');
|
|
6
6
|
var wrap = require('../parse/wrap_lines');
|
|
7
|
-
// var tablatures = require('./abc_tablatures');
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
var resizeDivs = {};
|
package/src/data/abc_tune.js
CHANGED
|
@@ -9,20 +9,35 @@ var create;
|
|
|
9
9
|
|
|
10
10
|
var baseDuration = 480*4; // nice and divisible, equals 1 whole note
|
|
11
11
|
|
|
12
|
-
create = function(abcTune, options) {
|
|
12
|
+
create = function create(abcTune, options) {
|
|
13
13
|
if (options === undefined) options = {};
|
|
14
14
|
var commands = abcTune.setUpAudio(options);
|
|
15
15
|
var midi = rendererFactory();
|
|
16
|
-
|
|
17
16
|
var title = abcTune.metaText ? abcTune.metaText.title : undefined;
|
|
18
|
-
if (title && title.length > 128)
|
|
19
|
-
title = title.substring(0,124) + '...';
|
|
17
|
+
if (title && title.length > 128) title = title.substring(0, 124) + '...';
|
|
20
18
|
var key = abcTune.getKeySignature();
|
|
21
19
|
var time = abcTune.getMeterFraction();
|
|
22
|
-
var beatsPerSecond = commands.tempo / 60;
|
|
23
|
-
//var beatLength = abcTune.getBeatLength();
|
|
24
|
-
midi.setGlobalInfo(commands.tempo, title, key, time);
|
|
25
20
|
|
|
21
|
+
// MAE 7 July 2024 - Fix for */8 meter tempos
|
|
22
|
+
var tempo = commands.tempo;
|
|
23
|
+
|
|
24
|
+
var beatsPerSecond = tempo / 60;
|
|
25
|
+
|
|
26
|
+
// Fix tempo for */8 meters
|
|
27
|
+
if (time.den == 8){
|
|
28
|
+
|
|
29
|
+
// Compute the tempo based on the actual milliseconds per measure, scaled by the number of eight notes and halved to get tempo in bpm.
|
|
30
|
+
var msPerMeasure = abcTune.millisecondsPerMeasure();
|
|
31
|
+
|
|
32
|
+
tempo = (60000 / (msPerMeasure/time.num)) / 2;
|
|
33
|
+
|
|
34
|
+
beatsPerSecond = tempo/60;
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//var beatLength = abcTune.getBeatLength();
|
|
39
|
+
midi.setGlobalInfo(tempo, title, key, time);
|
|
40
|
+
|
|
26
41
|
for (var i = 0; i < commands.tracks.length; i++) {
|
|
27
42
|
midi.startTrack();
|
|
28
43
|
var notePlacement = {};
|
package/src/parse/abc_common.js
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
//
|
|
1
|
+
// abc_common.js: Some common utility functions.
|
|
2
2
|
|
|
3
3
|
var parseCommon = {};
|
|
4
4
|
|
|
5
|
-
parseCommon.clone = function(source) {
|
|
6
|
-
var destination = {};
|
|
7
|
-
for (var property in source)
|
|
8
|
-
if (source.hasOwnProperty(property))
|
|
9
|
-
destination[property] = source[property];
|
|
10
|
-
return destination;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
5
|
parseCommon.cloneArray = function(source) {
|
|
14
6
|
var destination = [];
|
|
15
7
|
for (var i = 0; i < source.length; i++) {
|
|
16
|
-
destination.push(
|
|
8
|
+
destination.push(Object.assign({},source[i]));
|
|
17
9
|
}
|
|
18
10
|
return destination;
|
|
19
11
|
};
|
|
@@ -22,7 +14,7 @@ parseCommon.cloneHashOfHash = function(source) {
|
|
|
22
14
|
var destination = {};
|
|
23
15
|
for (var property in source)
|
|
24
16
|
if (source.hasOwnProperty(property))
|
|
25
|
-
destination[property] =
|
|
17
|
+
destination[property] = Object.assign({},source[property]);
|
|
26
18
|
return destination;
|
|
27
19
|
};
|
|
28
20
|
|
package/src/parse/abc_parse.js
CHANGED
|
@@ -440,7 +440,7 @@ var Parse = function() {
|
|
|
440
440
|
});
|
|
441
441
|
for (var i = 0; i < nextVoice.length; i++) {
|
|
442
442
|
var element = nextVoice[i];
|
|
443
|
-
var hint =
|
|
443
|
+
var hint = Object.assign({},element);
|
|
444
444
|
voice.push(hint);
|
|
445
445
|
if (element.el_type === 'bar')
|
|
446
446
|
return;
|
|
@@ -485,8 +485,6 @@ var parseDirective = {};
|
|
|
485
485
|
var midiCmdParam1Integer = [
|
|
486
486
|
"bassvol",
|
|
487
487
|
"chordvol",
|
|
488
|
-
"bassprog",
|
|
489
|
-
"chordprog",
|
|
490
488
|
"c",
|
|
491
489
|
"channel",
|
|
492
490
|
"beatmod",
|
|
@@ -500,7 +498,8 @@ var parseDirective = {};
|
|
|
500
498
|
"transpose",
|
|
501
499
|
"rtranspose",
|
|
502
500
|
"vol",
|
|
503
|
-
"volinc"
|
|
501
|
+
"volinc",
|
|
502
|
+
"gchordbars"
|
|
504
503
|
];
|
|
505
504
|
var midiCmdParam1Integer1OptionalInteger = [
|
|
506
505
|
"program"
|
|
@@ -531,6 +530,10 @@ var parseDirective = {};
|
|
|
531
530
|
"drum",
|
|
532
531
|
"chordname"
|
|
533
532
|
];
|
|
533
|
+
var midiCmdParam1Integer1OptionalString = [
|
|
534
|
+
"bassprog", "chordprog"
|
|
535
|
+
];
|
|
536
|
+
|
|
534
537
|
|
|
535
538
|
var parseMidiCommand = function(midi, tune, restOfString) {
|
|
536
539
|
var midi_cmd = midi.shift().token;
|
|
@@ -673,6 +676,44 @@ var parseDirective = {};
|
|
|
673
676
|
}
|
|
674
677
|
}
|
|
675
678
|
}
|
|
679
|
+
else if (midiCmdParam1Integer1OptionalString.indexOf(midi_cmd) >= 0){
|
|
680
|
+
|
|
681
|
+
// ONE INT PARAMETER, ONE OPTIONAL string
|
|
682
|
+
if (midi.length !== 1 && midi.length !== 2)
|
|
683
|
+
warn("Expected one or two parameters in MIDI " + midi_cmd, restOfString, 0);
|
|
684
|
+
else if (midi[0].type !== "number")
|
|
685
|
+
warn("Expected integer parameter in MIDI " + midi_cmd, restOfString, 0);
|
|
686
|
+
else if (midi.length === 2 && midi[1].type !== "alpha")
|
|
687
|
+
warn("Expected alpha parameter in MIDI " + midi_cmd, restOfString, 0);
|
|
688
|
+
else {
|
|
689
|
+
midi_params.push(midi[0].intt);
|
|
690
|
+
|
|
691
|
+
// Currently only bassprog and chordprog with optional octave shifts use this path
|
|
692
|
+
if (midi.length === 2){
|
|
693
|
+
var cmd = midi[1].token;
|
|
694
|
+
if (cmd.indexOf("octave=") != -1){
|
|
695
|
+
cmd = cmd.replace("octave=","");
|
|
696
|
+
cmd = parseInt(cmd);
|
|
697
|
+
if (!isNaN(cmd)){
|
|
698
|
+
// Limit range from -1 to 3 octaves
|
|
699
|
+
if (cmd < -1){
|
|
700
|
+
warn("Expected octave= in MIDI " + midi_cmd + ' to be >= -1 (recv:'+cmd+')');
|
|
701
|
+
cmd = -1;
|
|
702
|
+
}
|
|
703
|
+
if (cmd > 3){
|
|
704
|
+
warn("Expected octave= in MIDI " + midi_cmd + ' to be <= 3 (recv:'+cmd+')');
|
|
705
|
+
cmd = 3;
|
|
706
|
+
}
|
|
707
|
+
midi_params.push(cmd);
|
|
708
|
+
} else
|
|
709
|
+
warn("Expected octave value in MIDI" + midi_cmd);
|
|
710
|
+
}
|
|
711
|
+
else{
|
|
712
|
+
warn("Expected octave= in MIDI" + midi_cmd);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
676
717
|
|
|
677
718
|
if (tuneBuilder.hasBeginMusic())
|
|
678
719
|
tuneBuilder.appendElement('midi', -1, -1, { cmd: midi_cmd, params: midi_params });
|
|
@@ -341,6 +341,7 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
341
341
|
|
|
342
342
|
this.letter_to_inline_header = function(line, i, startLine)
|
|
343
343
|
{
|
|
344
|
+
var needsNewLine = false
|
|
344
345
|
var ws = tokenizer.eatWhiteSpace(line, i);
|
|
345
346
|
i +=ws;
|
|
346
347
|
if (line.length >= i+5 && line[i] === '[' && line[i+2] === ':') {
|
|
@@ -396,9 +397,9 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
396
397
|
break;
|
|
397
398
|
case "[V:":
|
|
398
399
|
if (e > 0) {
|
|
399
|
-
parseKeyVoice.parseVoice(line, i+3, e);
|
|
400
|
+
needsNewLine = parseKeyVoice.parseVoice(line, i+3, e);
|
|
400
401
|
//startNewLine();
|
|
401
|
-
return [ e-i+1+ws, line[i+1], line.substring(i+3, e)];
|
|
402
|
+
return [ e-i+1+ws, line[i+1], line.substring(i+3, e), needsNewLine];
|
|
402
403
|
}
|
|
403
404
|
break;
|
|
404
405
|
case "[r:":
|
|
@@ -413,6 +414,7 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
413
414
|
|
|
414
415
|
this.letter_to_body_header = function(line, i)
|
|
415
416
|
{
|
|
417
|
+
var needsNewLine = false
|
|
416
418
|
if (line.length >= i+3) {
|
|
417
419
|
switch(line.substring(i, i+2))
|
|
418
420
|
{
|
|
@@ -447,9 +449,9 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
447
449
|
else if (tempo.type === 'immediate') tuneBuilder.appendElement('tempo', multilineVars.iChar + i, multilineVars.iChar + line.length, tempo.tempo);
|
|
448
450
|
return [ e, line[i], parseCommon.strip(line.substring(i+2))];
|
|
449
451
|
case "V:":
|
|
450
|
-
parseKeyVoice.parseVoice(line, i+2, line.length);
|
|
452
|
+
needsNewLine = parseKeyVoice.parseVoice(line, i+2, line.length);
|
|
451
453
|
// startNewLine();
|
|
452
|
-
return [ line.length, line[i], parseCommon.strip(line.substring(i+2))];
|
|
454
|
+
return [ line.length, line[i], parseCommon.strip(line.substring(i+2)), needsNewLine];
|
|
453
455
|
default:
|
|
454
456
|
// TODO: complain about unhandled header
|
|
455
457
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var parseCommon = require('./abc_common');
|
|
2
1
|
var parseDirective = require('./abc_parse_directive');
|
|
3
2
|
var transpose = require('./abc_transpose');
|
|
4
3
|
|
|
@@ -84,7 +83,7 @@ var parseKeyVoice = {};
|
|
|
84
83
|
parseKeyVoice.deepCopyKey = function(key) {
|
|
85
84
|
var ret = { accidentals: [], root: key.root, acc: key.acc, mode: key.mode };
|
|
86
85
|
key.accidentals.forEach(function(k) {
|
|
87
|
-
ret.accidentals.push(
|
|
86
|
+
ret.accidentals.push(Object.assign({},k));
|
|
88
87
|
});
|
|
89
88
|
return ret;
|
|
90
89
|
};
|
|
@@ -151,7 +150,7 @@ var parseKeyVoice = {};
|
|
|
151
150
|
};
|
|
152
151
|
|
|
153
152
|
parseKeyVoice.fixKey = function(clef, key) {
|
|
154
|
-
var fixedKey =
|
|
153
|
+
var fixedKey = Object.assign({},key);
|
|
155
154
|
parseKeyVoice.addPosToKey(clef, fixedKey);
|
|
156
155
|
return fixedKey;
|
|
157
156
|
};
|
|
@@ -494,8 +493,13 @@ var parseKeyVoice = {};
|
|
|
494
493
|
};
|
|
495
494
|
|
|
496
495
|
var setCurrentVoice = function(id) {
|
|
497
|
-
|
|
498
|
-
|
|
496
|
+
var currentVoice = multilineVars.voices[id]
|
|
497
|
+
if (multilineVars.currentVoice) {
|
|
498
|
+
if (multilineVars.currentVoice.index === currentVoice.index && multilineVars.currentVoice.staffNum === currentVoice.staffNum)
|
|
499
|
+
return // there was no change so don't reset it.
|
|
500
|
+
}
|
|
501
|
+
multilineVars.currentVoice = currentVoice;
|
|
502
|
+
return tuneBuilder.setCurrentVoice(currentVoice.staffNum, currentVoice.index, id);
|
|
499
503
|
};
|
|
500
504
|
|
|
501
505
|
parseKeyVoice.parseVoice = function(line, i, e) {
|
|
@@ -788,7 +792,7 @@ var parseKeyVoice = {};
|
|
|
788
792
|
if (staffInfo.name) {if (s.name) s.name.push(staffInfo.name); else s.name = [ staffInfo.name ];}
|
|
789
793
|
if (staffInfo.subname) {if (s.subname) s.subname.push(staffInfo.subname); else s.subname = [ staffInfo.subname ];}
|
|
790
794
|
|
|
791
|
-
setCurrentVoice(id);
|
|
795
|
+
return setCurrentVoice(id);
|
|
792
796
|
};
|
|
793
797
|
|
|
794
798
|
})();
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var parseCommon = require('./abc_common');
|
|
2
1
|
var parseKeyVoice = require('./abc_parse_key_voice');
|
|
3
2
|
var transpose = require('./abc_transpose');
|
|
4
3
|
|
|
@@ -145,6 +144,7 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
145
144
|
var retInlineHeader = header.letter_to_inline_header(line, i, delayStartNewLine);
|
|
146
145
|
if (retInlineHeader[0] > 0) {
|
|
147
146
|
i += retInlineHeader[0];
|
|
147
|
+
//console.log("inline header", retInlineHeader)
|
|
148
148
|
if (retInlineHeader[1] === 'V')
|
|
149
149
|
delayStartNewLine = true; // fixes bug on this: c[V:2]d
|
|
150
150
|
// TODO-PER: Handle inline headers
|
|
@@ -457,6 +457,9 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
457
457
|
else
|
|
458
458
|
postChordDone = true;
|
|
459
459
|
break;
|
|
460
|
+
case '0':
|
|
461
|
+
chordDuration = 0;
|
|
462
|
+
break;
|
|
460
463
|
default:
|
|
461
464
|
postChordDone = true;
|
|
462
465
|
break;
|
|
@@ -554,13 +557,17 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
554
557
|
// The first item on a line is a regular note value, each item after that represents a dot placed after the previous note.
|
|
555
558
|
// Only durations less than a whole note are tested because whole note durations have some tricky rules.
|
|
556
559
|
|
|
557
|
-
|
|
560
|
+
if (el.duration < 1 && durations.indexOf(el.duration) === -1 && el.duration !== 0) {
|
|
558
561
|
if (!el.rest || el.rest.type !== 'spacer')
|
|
559
562
|
warn("Duration not representable: " + line.substring(startI, i), line, i);
|
|
560
563
|
}
|
|
561
564
|
|
|
562
565
|
multilineVars.addFormattingOptions(el, tune.formatting, 'note');
|
|
563
|
-
tuneBuilder.appendElement('note', startOfLine+startI, startOfLine+i, el);
|
|
566
|
+
var succeeded = tuneBuilder.appendElement('note', startOfLine+startI, startOfLine+i, el);
|
|
567
|
+
if (!succeeded) {
|
|
568
|
+
this.startNewLine()
|
|
569
|
+
tuneBuilder.appendElement('note', startOfLine+startI, startOfLine+i, el);
|
|
570
|
+
}
|
|
564
571
|
multilineVars.measureNotEmpty = true;
|
|
565
572
|
el = {};
|
|
566
573
|
}
|
|
@@ -608,23 +615,38 @@ var letter_to_chord = function(line, i) {
|
|
|
608
615
|
chord[1] = chord[1].substring(1);
|
|
609
616
|
chord[2] = 'right';
|
|
610
617
|
} else if (chord[0] > 0 && chord[1].length > 0 && chord[1][0] === '@') {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
chord[1] = chord[1].
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
chord[1] = chord[1].
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
618
|
+
// @-15,5.7
|
|
619
|
+
chord[1] = chord[1].substring(1);
|
|
620
|
+
var x = tokenizer.getFloat(chord[1]);
|
|
621
|
+
if (x.digits === 0){
|
|
622
|
+
warn("Missing first position in absolutely positioned annotation.", line, i);
|
|
623
|
+
chord[1] = chord[1].replace("@","");
|
|
624
|
+
chord[2] = 'above';
|
|
625
|
+
return chord;
|
|
626
|
+
}
|
|
627
|
+
chord[1] = chord[1].substring(x.digits);
|
|
628
|
+
if (chord[1][0] !== ','){
|
|
629
|
+
warn("Missing comma absolutely positioned annotation.", line, i);
|
|
630
|
+
chord[1] = chord[1].replace("@","");
|
|
631
|
+
chord[2] = 'above';
|
|
632
|
+
return chord;
|
|
633
|
+
}
|
|
634
|
+
chord[1] = chord[1].substring(1);
|
|
635
|
+
var y = tokenizer.getFloat(chord[1]);
|
|
636
|
+
if (y.digits === 0){
|
|
637
|
+
warn("Missing second position in absolutely positioned annotation.", line, i);
|
|
638
|
+
chord[1] = chord[1].replace("@","");
|
|
639
|
+
chord[2] = 'above';
|
|
640
|
+
return chord;
|
|
641
|
+
}
|
|
642
|
+
chord[1] = chord[1].substring(y.digits);
|
|
643
|
+
var ws = tokenizer.skipWhiteSpace(chord[1]);
|
|
644
|
+
chord[1] = chord[1].substring(ws);
|
|
645
|
+
chord[2] = null;
|
|
646
|
+
chord[3] = {
|
|
647
|
+
x: x.value,
|
|
648
|
+
y: y.value
|
|
649
|
+
};
|
|
628
650
|
} else {
|
|
629
651
|
if (multilineVars.freegchord !== true) {
|
|
630
652
|
chord[1] = chord[1].replace(/([ABCDEFG0-9])b/g, "$1♭");
|
|
@@ -670,7 +692,11 @@ var letter_to_grace = function(line, i) {
|
|
|
670
692
|
note.duration = note.duration / (multilineVars.default_length * 8);
|
|
671
693
|
if (acciaccatura)
|
|
672
694
|
note.acciaccatura = true;
|
|
673
|
-
|
|
695
|
+
if (note.rest) {
|
|
696
|
+
// don't allow rests inside gracenotes
|
|
697
|
+
warn("Rests not allowed as grace notes '" + gra[1][ii] + "' while parsing grace note", line, i);
|
|
698
|
+
} else
|
|
699
|
+
gracenotes.push(note);
|
|
674
700
|
|
|
675
701
|
if (inTie) {
|
|
676
702
|
note.endTie = true;
|
|
@@ -927,7 +953,7 @@ MusicParser.prototype.startNewLine = function() {
|
|
|
927
953
|
var params = { startChar: -1, endChar: -1};
|
|
928
954
|
if (multilineVars.partForNextLine.title)
|
|
929
955
|
params.part = multilineVars.partForNextLine;
|
|
930
|
-
params.clef = multilineVars.currentVoice && multilineVars.staves[multilineVars.currentVoice.staffNum].clef !== undefined ?
|
|
956
|
+
params.clef = multilineVars.currentVoice && multilineVars.staves[multilineVars.currentVoice.staffNum].clef !== undefined ? Object.assign({},multilineVars.staves[multilineVars.currentVoice.staffNum].clef) : Object.assign({},multilineVars.clef);
|
|
931
957
|
var scoreTranspose = multilineVars.currentVoice ? multilineVars.currentVoice.scoreTranspose : 0;
|
|
932
958
|
params.key = parseKeyVoice.standardKey(multilineVars.key.root+multilineVars.key.acc+multilineVars.key.mode, multilineVars.key.root, multilineVars.key.acc, scoreTranspose);
|
|
933
959
|
params.key.mode = multilineVars.key.mode;
|
|
@@ -997,6 +1023,12 @@ MusicParser.prototype.startNewLine = function() {
|
|
|
997
1023
|
params.style = multilineVars.currentVoice.style;
|
|
998
1024
|
if (multilineVars.currentVoice.transpose)
|
|
999
1025
|
params.clef.transpose = multilineVars.currentVoice.transpose;
|
|
1026
|
+
params.currentVoice = multilineVars.currentVoice
|
|
1027
|
+
var voices = Object.keys(multilineVars.voices)
|
|
1028
|
+
for (var mv = 0; mv < voices.length; mv++) {
|
|
1029
|
+
if (params.currentVoice.staffNum === multilineVars.voices[voices[mv]].staffNum && params.currentVoice.index === multilineVars.voices[voices[mv]].index)
|
|
1030
|
+
params.currentVoiceName = voices[mv]
|
|
1031
|
+
}
|
|
1000
1032
|
}
|
|
1001
1033
|
var isFirstVoice = multilineVars.currentVoice === undefined || (multilineVars.currentVoice.staffNum === 0 && multilineVars.currentVoice.index === 0);
|
|
1002
1034
|
if (multilineVars.barNumbers === 0 && isFirstVoice && multilineVars.currBarNumber !== 1)
|