abcjs 6.2.2 → 6.3.0
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/README.md +4 -0
- package/RELEASE.md +78 -0
- package/abc2xml_239/abc2xml.html +769 -0
- package/abc2xml_239/abc2xml.py +2248 -0
- package/abc2xml_239/abc2xml_changelog.html +124 -0
- package/abc2xml_239/lazy-river.abc +26 -0
- package/abc2xml_239/lazy-river.xml +3698 -0
- package/abc2xml_239/mean-to-me.abc +22 -0
- package/abc2xml_239/mean-to-me.xml +2954 -0
- package/abc2xml_239/pyparsing.py +3672 -0
- package/abc2xml_239/pyparsing.pyc +0 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +909 -485
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/index.js +2 -0
- package/package.json +1 -1
- package/plugin.js +1 -1
- package/src/api/abc_tablatures.js +51 -13
- package/src/api/abc_tunebook_svg.js +5 -3
- package/src/parse/abc_parse_directive.js +17 -16
- package/src/parse/abc_parse_header.js +22 -19
- package/src/parse/abc_parse_music.js +18 -53
- package/src/parse/abc_parse_settings.js +165 -0
- package/src/parse/abc_tokenizer.js +72 -7
- package/src/parse/tune-builder.js +60 -1
- package/src/synth/create-synth.js +4 -0
- package/src/synth/place-note.js +6 -0
- package/src/synth/play-event.js +7 -5
- package/src/synth/synth-controller.js +6 -2
- package/src/tablatures/instruments/string-patterns.js +11 -0
- package/src/tablatures/instruments/{guitar/guitar-patterns.js → tab-string-patterns.js} +6 -6
- package/src/tablatures/instruments/{violin/tab-violin.js → tab-string.js} +13 -11
- package/src/tablatures/tab-absolute-elements.js +19 -9
- package/src/tablatures/tab-renderer.js +24 -10
- package/src/test/abc_parser_lint.js +1 -0
- package/src/write/creation/abstract-engraver.js +9 -2
- package/src/write/creation/add-chord.js +102 -82
- package/src/write/creation/add-text-if.js +2 -2
- package/src/write/creation/decoration.js +16 -8
- package/src/write/creation/elements/bottom-text.js +62 -47
- package/src/write/creation/elements/rich-text.js +51 -0
- package/src/write/creation/elements/top-text.js +37 -11
- package/src/write/creation/glyphs.js +2 -2
- package/src/write/draw/absolute.js +4 -1
- package/src/write/draw/draw.js +13 -4
- package/src/write/draw/glissando.js +1 -0
- package/src/write/draw/non-music.js +3 -1
- package/src/write/draw/relative.js +1 -1
- package/src/write/draw/set-paper-size.js +1 -1
- package/src/write/draw/tempo.js +1 -1
- package/src/write/draw/text.js +10 -0
- package/src/write/draw/tie.js +9 -1
- package/src/write/engraver-controller.js +58 -11
- package/src/write/helpers/classes.js +1 -1
- package/src/write/helpers/get-font-and-attr.js +8 -1
- package/src/write/helpers/get-text-size.js +8 -1
- package/src/write/interactive/selection.js +6 -0
- package/src/write/layout/layout.js +33 -3
- package/src/write/svg.js +30 -0
- package/temp.txt +50 -0
- package/types/index.d.ts +74 -26
- package/version.js +1 -1
- package/.github/workflows/tests.yml +0 -29
- package/src/tablatures/instruments/guitar/tab-guitar.js +0 -48
- package/src/tablatures/instruments/violin/violin-patterns.js +0 -23
package/index.js
CHANGED
|
@@ -57,6 +57,7 @@ var supportsAudio = require('./src/synth/supports-audio');
|
|
|
57
57
|
var playEvent = require('./src/synth/play-event');
|
|
58
58
|
var SynthController = require('./src/synth/synth-controller');
|
|
59
59
|
var getMidiFile = require('./src/synth/get-midi-file');
|
|
60
|
+
var midiRenderer = require('./src/synth/abc_midi_renderer');
|
|
60
61
|
|
|
61
62
|
abcjs.synth = {
|
|
62
63
|
CreateSynth: CreateSynth,
|
|
@@ -71,6 +72,7 @@ abcjs.synth = {
|
|
|
71
72
|
playEvent: playEvent,
|
|
72
73
|
getMidiFile: getMidiFile,
|
|
73
74
|
sequence: sequence,
|
|
75
|
+
midiRenderer: midiRenderer,
|
|
74
76
|
};
|
|
75
77
|
|
|
76
78
|
abcjs['Editor'] = require('./src/edit/abc_editor');
|
package/package.json
CHANGED
package/plugin.js
CHANGED
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
* where plugin represents a plugin instance
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
var
|
|
9
|
-
var GuitarTablature = require('../tablatures/instruments/guitar/tab-guitar');
|
|
8
|
+
var StringTablature = require('../tablatures/instruments/tab-string');
|
|
10
9
|
|
|
11
10
|
/* extend the table below when adding a new instrument plugin */
|
|
12
11
|
|
|
13
12
|
// Existing tab classes
|
|
14
13
|
var pluginTab = {
|
|
15
|
-
'violin': '
|
|
16
|
-
'fiddle': '
|
|
17
|
-
'mandolin': '
|
|
18
|
-
'guitar': '
|
|
14
|
+
'violin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
|
|
15
|
+
'fiddle': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
|
|
16
|
+
'mandolin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
|
|
17
|
+
'guitar': { name: 'StringTab', defaultTuning: ['E,', 'A,', 'D', 'G' , 'B' , 'e'], isTabBig: true, tabSymbolOffset: 0},
|
|
18
|
+
'fiveString': { name: 'StringTab', defaultTuning: ['C,', 'G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: -.95},
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
var abcTablatures = {
|
|
@@ -66,7 +66,7 @@ var abcTablatures = {
|
|
|
66
66
|
var tabName = pluginTab[instrument];
|
|
67
67
|
var plugin = null;
|
|
68
68
|
if (tabName) {
|
|
69
|
-
plugin = this.plugins[tabName];
|
|
69
|
+
plugin = this.plugins[tabName.name];
|
|
70
70
|
}
|
|
71
71
|
if (plugin) {
|
|
72
72
|
if (params.visualTranspose != 0) {
|
|
@@ -79,11 +79,15 @@ var abcTablatures = {
|
|
|
79
79
|
tuneNumber: tuneNumber,
|
|
80
80
|
params: args,
|
|
81
81
|
instance: null,
|
|
82
|
+
tabType: tabName,
|
|
82
83
|
};
|
|
83
84
|
// proceed with tab plugin init
|
|
84
85
|
// plugin.init(tune, tuneNumber, args, ii);
|
|
85
86
|
returned.push(pluginInstance);
|
|
86
87
|
nbPlugins++;
|
|
88
|
+
} else if (instrument === '') {
|
|
89
|
+
// create a placeholder - there is no tab for this staff
|
|
90
|
+
returned.push(null)
|
|
87
91
|
} else {
|
|
88
92
|
// unknown tab plugin
|
|
89
93
|
//this.emit_error('Undefined tablature plugin: ' + tabName)
|
|
@@ -100,16 +104,50 @@ var abcTablatures = {
|
|
|
100
104
|
* @param {*} renderer
|
|
101
105
|
* @param {*} abcTune
|
|
102
106
|
*/
|
|
103
|
-
layoutTablatures: function (renderer, abcTune) {
|
|
107
|
+
layoutTablatures: function layoutTablatures(renderer, abcTune) {
|
|
104
108
|
var tabs = abcTune.tablatures;
|
|
109
|
+
|
|
105
110
|
// chack tabs request for each staffs
|
|
111
|
+
var staffLineCount = 0;
|
|
112
|
+
|
|
113
|
+
// Clear the suppression flag
|
|
114
|
+
if (tabs && (tabs.length > 0)){
|
|
115
|
+
var nTabs = tabs.length;
|
|
116
|
+
for (var kk=0;kk<nTabs;++kk){
|
|
117
|
+
if (tabs[kk] && tabs[kk].params.firstStaffOnly){
|
|
118
|
+
tabs[kk].params.suppress = false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
106
123
|
for (var ii = 0; ii < abcTune.lines.length; ii++) {
|
|
107
124
|
var line = abcTune.lines[ii];
|
|
125
|
+
|
|
126
|
+
if (line.staff){
|
|
127
|
+
staffLineCount++;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// MAE 27Nov2023
|
|
131
|
+
// If tab param "firstStaffOnly", remove the tab label after the first staff
|
|
132
|
+
if (staffLineCount > 1){
|
|
133
|
+
if (tabs && (tabs.length > 0)){
|
|
134
|
+
var nTabs = tabs.length;
|
|
135
|
+
for (var kk=0;kk<nTabs;++kk){
|
|
136
|
+
if (tabs[kk].params.firstStaffOnly){
|
|
137
|
+
// Set the staff draw suppression flag
|
|
138
|
+
tabs[kk].params.suppress = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
108
144
|
var curStaff = line.staff;
|
|
109
145
|
if (curStaff) {
|
|
146
|
+
var maxStaves = curStaff.length
|
|
110
147
|
for (var jj = 0; jj < curStaff.length; jj++) {
|
|
111
|
-
|
|
112
|
-
|
|
148
|
+
|
|
149
|
+
if (tabs[jj] && jj < maxStaves) {
|
|
150
|
+
// tablature requested for staff
|
|
113
151
|
var tabPlugin = tabs[jj];
|
|
114
152
|
if (tabPlugin.instance == null) {
|
|
115
153
|
tabPlugin.instance = new tabPlugin.classz();
|
|
@@ -118,7 +156,8 @@ var abcTablatures = {
|
|
|
118
156
|
tabPlugin.instance.init(abcTune,
|
|
119
157
|
tabPlugin.tuneNumber,
|
|
120
158
|
tabPlugin.params,
|
|
121
|
-
jj
|
|
159
|
+
jj,
|
|
160
|
+
tabPlugin.tabType
|
|
122
161
|
);
|
|
123
162
|
}
|
|
124
163
|
// render next
|
|
@@ -135,8 +174,7 @@ var abcTablatures = {
|
|
|
135
174
|
init: function () {
|
|
136
175
|
// just register plugin hosted by abcjs
|
|
137
176
|
if (!this.inited) {
|
|
138
|
-
this.register(new
|
|
139
|
-
this.register(new GuitarTablature());
|
|
177
|
+
this.register(new StringTablature());
|
|
140
178
|
this.inited = true;
|
|
141
179
|
}
|
|
142
180
|
}
|
|
@@ -117,12 +117,12 @@ var renderAbc = function(output, abc, parserParams, engraverParams, renderParams
|
|
|
117
117
|
div.setAttribute("style", "visibility: hidden;");
|
|
118
118
|
document.body.appendChild(div);
|
|
119
119
|
}
|
|
120
|
-
if (params.afterParsing)
|
|
121
|
-
params.afterParsing(tune, tuneNumber, abcString);
|
|
122
120
|
if (!removeDiv && params.wrap && params.staffwidth) {
|
|
123
|
-
|
|
121
|
+
tune = doLineWrapping(div, tune, tuneNumber, abcString, params);
|
|
124
122
|
return tune;
|
|
125
123
|
}
|
|
124
|
+
if (params.afterParsing)
|
|
125
|
+
params.afterParsing(tune, tuneNumber, abcString);
|
|
126
126
|
renderOne(div, tune, params, tuneNumber, 0);
|
|
127
127
|
if (removeDiv)
|
|
128
128
|
div.parentNode.removeChild(div);
|
|
@@ -145,6 +145,8 @@ function doLineWrapping(div, tune, tuneNumber, abcString, params) {
|
|
|
145
145
|
if (warnings)
|
|
146
146
|
tune.warnings = warnings;
|
|
147
147
|
}
|
|
148
|
+
if (params.afterParsing)
|
|
149
|
+
params.afterParsing(tune, tuneNumber, abcString);
|
|
148
150
|
renderOne(div, tune, ret.revisedParams, tuneNumber, 0);
|
|
149
151
|
tune.explanation = ret.explanation;
|
|
150
152
|
return tune;
|
|
@@ -684,27 +684,27 @@ var parseDirective = {};
|
|
|
684
684
|
};
|
|
685
685
|
|
|
686
686
|
parseDirective.parseFontChangeLine = function(textstr) {
|
|
687
|
+
// We don't want to match two dollar signs, so change those temporarily
|
|
688
|
+
textstr = textstr.replace(/\$\$/g,"\x03")
|
|
687
689
|
var textParts = textstr.split('$');
|
|
688
690
|
if (textParts.length > 1 && multilineVars.setfont) {
|
|
689
|
-
var textarr = [
|
|
691
|
+
var textarr = [ ];
|
|
692
|
+
if (textParts[0] !== '') // did the original string start with `$`?
|
|
693
|
+
textarr.push({ text: textParts[0] })
|
|
690
694
|
for (var i = 1; i < textParts.length; i++) {
|
|
691
695
|
if (textParts[i][0] === '0')
|
|
692
|
-
textarr.push({ text: textParts[i].substring(1) });
|
|
693
|
-
else
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
textarr.push({font: multilineVars.setfont[4], text: textParts[i].substring(1) });
|
|
701
|
-
else
|
|
702
|
-
textarr[textarr.length-1].text += '$' + textParts[i];
|
|
696
|
+
textarr.push({ text: textParts[i].substring(1).replace(/\x03/g,"$$") });
|
|
697
|
+
else {
|
|
698
|
+
var whichFont = parseInt(textParts[i][0],10)
|
|
699
|
+
if (multilineVars.setfont[whichFont])
|
|
700
|
+
textarr.push({font: multilineVars.setfont[whichFont], text: textParts[i].substring(1).replace(/\x03/g,"$$") });
|
|
701
|
+
else
|
|
702
|
+
textarr[textarr.length-1].text += '$' + textParts[i].replace(/\x03/g,"$$");
|
|
703
|
+
}
|
|
703
704
|
}
|
|
704
|
-
|
|
705
|
-
return textarr;
|
|
705
|
+
return textarr;
|
|
706
706
|
}
|
|
707
|
-
return textstr;
|
|
707
|
+
return textstr.replace(/\x03/g,"$$");
|
|
708
708
|
};
|
|
709
709
|
|
|
710
710
|
var positionChoices = [ 'auto', 'above', 'below', 'hidden' ];
|
|
@@ -748,6 +748,7 @@ var parseDirective = {};
|
|
|
748
748
|
case "bagpipes":tune.formatting.bagpipes = true;break;
|
|
749
749
|
case "flatbeams":tune.formatting.flatbeams = true;break;
|
|
750
750
|
case "jazzchords":tune.formatting.jazzchords = true;break;
|
|
751
|
+
case "accentAbove":tune.formatting.accentAbove = true;break;
|
|
751
752
|
case "germanAlphabet":tune.formatting.germanAlphabet = true;break;
|
|
752
753
|
case "landscape":multilineVars.landscape = true;break;
|
|
753
754
|
case "papersize":multilineVars.papersize = restOfString;break;
|
|
@@ -939,7 +940,7 @@ var parseDirective = {};
|
|
|
939
940
|
if (sfTokens.length >= 4) {
|
|
940
941
|
if (sfTokens[0].token === '-' && sfTokens[1].type === 'number') {
|
|
941
942
|
var sfNum = parseInt(sfTokens[1].token);
|
|
942
|
-
if (sfNum >= 1 && sfNum <=
|
|
943
|
+
if (sfNum >= 1 && sfNum <= 9) {
|
|
943
944
|
if (!multilineVars.setfont)
|
|
944
945
|
multilineVars.setfont = [];
|
|
945
946
|
sfTokens.shift();
|
|
@@ -11,15 +11,12 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
11
11
|
};
|
|
12
12
|
this.reset(tokenizer, warn, multilineVars, tune);
|
|
13
13
|
|
|
14
|
-
this.setTitle = function(title) {
|
|
14
|
+
this.setTitle = function(title, origSize) {
|
|
15
15
|
if (multilineVars.hasMainTitle)
|
|
16
|
-
tuneBuilder.addSubtitle(
|
|
16
|
+
tuneBuilder.addSubtitle(title, { startChar: multilineVars.iChar, endChar: multilineVars.iChar+origSize+2}); // display secondary title
|
|
17
17
|
else
|
|
18
18
|
{
|
|
19
|
-
|
|
20
|
-
if (multilineVars.titlecaps)
|
|
21
|
-
titleStr = titleStr.toUpperCase();
|
|
22
|
-
tuneBuilder.addMetaText("title", titleStr, { startChar: multilineVars.iChar, endChar: multilineVars.iChar+title.length+2});
|
|
19
|
+
tuneBuilder.addMetaText("title", title, { startChar: multilineVars.iChar, endChar: multilineVars.iChar+origSize+2});
|
|
23
20
|
multilineVars.hasMainTitle = true;
|
|
24
21
|
}
|
|
25
22
|
};
|
|
@@ -371,10 +368,11 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
371
368
|
tuneBuilder.appendStartingElement('key', startChar, endChar, parseKeyVoice.fixKey(multilineVars.clef, multilineVars.key));
|
|
372
369
|
return [ e-i+1+ws ];
|
|
373
370
|
case "[P:":
|
|
371
|
+
var part = parseDirective.parseFontChangeLine(line.substring(i+3, e))
|
|
374
372
|
if (startLine || tune.lines.length <= tune.lineNum)
|
|
375
|
-
multilineVars.partForNextLine = { title:
|
|
373
|
+
multilineVars.partForNextLine = { title: part, startChar: startChar, endChar: endChar };
|
|
376
374
|
else
|
|
377
|
-
tuneBuilder.appendElement('part', startChar, endChar, {title:
|
|
375
|
+
tuneBuilder.appendElement('part', startChar, endChar, {title: part});
|
|
378
376
|
return [ e-i+1+ws ];
|
|
379
377
|
case "[L:":
|
|
380
378
|
this.setDefaultLength(line, i+3, e);
|
|
@@ -477,23 +475,26 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
477
475
|
|
|
478
476
|
this.parseHeader = function(line) {
|
|
479
477
|
var field = metaTextHeaders[line[0]];
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
478
|
+
var origSize = line.length-2
|
|
479
|
+
var restOfLine = tokenizer.translateString(tokenizer.stripComment(line.substring(2)))
|
|
480
|
+
if (field === 'unalignedWords' || field === 'notes') {
|
|
481
|
+
// These fields can be multi-line
|
|
482
|
+
tuneBuilder.addMetaTextArray(field, parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
|
|
483
|
+
} else if (field !== undefined) {
|
|
484
|
+
// these fields are single line
|
|
485
|
+
tuneBuilder.addMetaText(field, parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
|
|
486
486
|
} else {
|
|
487
487
|
var startChar = multilineVars.iChar;
|
|
488
488
|
var endChar = startChar + line.length;
|
|
489
489
|
switch(line[0])
|
|
490
490
|
{
|
|
491
491
|
case 'H':
|
|
492
|
-
|
|
492
|
+
// History is a little different because once it starts it continues until another header field is encountered
|
|
493
|
+
tuneBuilder.addMetaTextArray("history", parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
|
|
493
494
|
line = tokenizer.peekLine()
|
|
494
495
|
while (line && line[1] !== ':') {
|
|
495
496
|
tokenizer.nextLine()
|
|
496
|
-
tuneBuilder.
|
|
497
|
+
tuneBuilder.addMetaTextArray("history", parseDirective.parseFontChangeLine(tokenizer.translateString(tokenizer.stripComment(line))), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
|
|
497
498
|
line = tokenizer.peekLine()
|
|
498
499
|
}
|
|
499
500
|
break;
|
|
@@ -518,9 +519,9 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
518
519
|
case 'P':
|
|
519
520
|
// TODO-PER: There is more to do with parts, but the writer doesn't care.
|
|
520
521
|
if (multilineVars.is_in_header)
|
|
521
|
-
tuneBuilder.addMetaText("partOrder",
|
|
522
|
+
tuneBuilder.addMetaText("partOrder", parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
|
|
522
523
|
else
|
|
523
|
-
multilineVars.partForNextLine = { title:
|
|
524
|
+
multilineVars.partForNextLine = { title: restOfLine, startChar: startChar, endChar: endChar};
|
|
524
525
|
break;
|
|
525
526
|
case 'Q':
|
|
526
527
|
var tempo = this.setTempo(line, 2, line.length, multilineVars.iChar);
|
|
@@ -533,7 +534,9 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
533
534
|
}
|
|
534
535
|
break;
|
|
535
536
|
case 'T':
|
|
536
|
-
|
|
537
|
+
if (multilineVars.titlecaps)
|
|
538
|
+
restOfLine = restOfLine.toUpperCase();
|
|
539
|
+
this.setTitle(parseDirective.parseFontChangeLine(tokenizer.theReverser(restOfLine)), origSize);
|
|
537
540
|
break;
|
|
538
541
|
case 'U':
|
|
539
542
|
this.addUserDefinition(line, 2, line.length);
|
|
@@ -9,6 +9,20 @@ var tune;
|
|
|
9
9
|
var tuneBuilder;
|
|
10
10
|
var header;
|
|
11
11
|
|
|
12
|
+
var {
|
|
13
|
+
legalAccents,
|
|
14
|
+
volumeDecorations,
|
|
15
|
+
dynamicDecorations,
|
|
16
|
+
accentPseudonyms,
|
|
17
|
+
accentDynamicPseudonyms,
|
|
18
|
+
nonDecorations,
|
|
19
|
+
durations,
|
|
20
|
+
pitches,
|
|
21
|
+
rests,
|
|
22
|
+
accMap,
|
|
23
|
+
tripletQ
|
|
24
|
+
} = require('./abc_parse_settings')
|
|
25
|
+
|
|
12
26
|
var MusicParser = function(_tokenizer, _warn, _multilineVars, _tune, _tuneBuilder, _header) {
|
|
13
27
|
tokenizer = _tokenizer;
|
|
14
28
|
warn = _warn;
|
|
@@ -76,7 +90,6 @@ var MusicParser = function(_tokenizer, _warn, _multilineVars, _tune, _tuneBuilde
|
|
|
76
90
|
// double-quote: chord symbol
|
|
77
91
|
// less-than, greater-than, slash: duration
|
|
78
92
|
// back-tick, space, tab: space
|
|
79
|
-
var nonDecorations = "ABCDEFGabcdefgxyzZ[]|^_{"; // use this to prescreen so we don't have to look for a decoration at every note.
|
|
80
93
|
|
|
81
94
|
var isInTie = function(multilineVars, overlayLevel, el) {
|
|
82
95
|
if (multilineVars.inTie[overlayLevel] === undefined)
|
|
@@ -540,15 +553,8 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
540
553
|
// Create a warning if this is not a displayable duration.
|
|
541
554
|
// The first item on a line is a regular note value, each item after that represents a dot placed after the previous note.
|
|
542
555
|
// Only durations less than a whole note are tested because whole note durations have some tricky rules.
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
0.25, 0.375, 0.4375, 0.46875, 0.484375, 0.4921875,
|
|
546
|
-
0.125, 0.1875, 0.21875, 0.234375, 0.2421875, 0.24609375,
|
|
547
|
-
0.0625, 0.09375, 0.109375, 0.1171875, 0.12109375, 0.123046875,
|
|
548
|
-
0.03125, 0.046875, 0.0546875, 0.05859375, 0.060546875, 0.0615234375,
|
|
549
|
-
0.015625, 0.0234375, 0.02734375, 0.029296875, 0.0302734375, 0.03076171875,
|
|
550
|
-
];
|
|
551
|
-
if (el.duration < 1 && durations.indexOf(el.duration) === -1 && el.duration !== 0) {
|
|
556
|
+
|
|
557
|
+
if (el.duration < 1 && durations.indexOf(el.duration) === -1 && el.duration !== 0) {
|
|
552
558
|
if (!el.rest || el.rest.type !== 'spacer')
|
|
553
559
|
warn("Duration not representable: " + line.substring(startI, i), line, i);
|
|
554
560
|
}
|
|
@@ -717,35 +723,8 @@ function durationOfMeasure(multilineVars) {
|
|
|
717
723
|
return parseInt(meter.value[0].num, 10) / parseInt(meter.value[0].den, 10);
|
|
718
724
|
}
|
|
719
725
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
"fermata", "invertedfermata", "tenuto", "0", "1", "2", "3", "4", "5", "+", "wedge",
|
|
723
|
-
"open", "thumb", "snap", "turn", "roll", "breath", "shortphrase", "mediumphrase", "longphrase",
|
|
724
|
-
"segno", "coda", "D.S.", "D.C.", "fine", "beambr1", "beambr2",
|
|
725
|
-
"slide", "marcato",
|
|
726
|
-
"upbow", "downbow", "/", "//", "///", "////", "trem1", "trem2", "trem3", "trem4",
|
|
727
|
-
"turnx", "invertedturn", "invertedturnx", "trill(", "trill)", "arpeggio", "xstem", "mark", "umarcato",
|
|
728
|
-
"style=normal", "style=harmonic", "style=rhythm", "style=x", "style=triangle", "D.C.alcoda", "D.C.alfine", "D.S.alcoda", "D.S.alfine", "editorial", "courtesy"
|
|
729
|
-
];
|
|
730
|
-
|
|
731
|
-
var volumeDecorations = [
|
|
732
|
-
"p", "pp", "f", "ff", "mf", "mp", "ppp", "pppp", "fff", "ffff", "sfz"
|
|
733
|
-
];
|
|
734
|
-
|
|
735
|
-
var dynamicDecorations = [
|
|
736
|
-
"crescendo(", "crescendo)", "diminuendo(", "diminuendo)", "glissando(", "glissando)"
|
|
737
|
-
];
|
|
738
|
-
|
|
739
|
-
var accentPseudonyms = [
|
|
740
|
-
["<", "accent"], [">", "accent"], ["tr", "trill"],
|
|
741
|
-
["plus", "+"], [ "emphasis", "accent"],
|
|
742
|
-
[ "^", "umarcato" ], [ "marcato", "umarcato" ]
|
|
743
|
-
];
|
|
744
|
-
|
|
745
|
-
var accentDynamicPseudonyms = [
|
|
746
|
-
["<(", "crescendo("], ["<)", "crescendo)"],
|
|
747
|
-
[">(", "diminuendo("], [">)", "diminuendo)"]
|
|
748
|
-
];
|
|
726
|
+
|
|
727
|
+
|
|
749
728
|
|
|
750
729
|
var letter_to_accent = function(line, i) {
|
|
751
730
|
var macro = multilineVars.macros[line[i]];
|
|
@@ -877,17 +856,6 @@ var letter_to_bar = function(line, curr_pos) {
|
|
|
877
856
|
return [ret.len+retRep.len, ret.token, retRep.token];
|
|
878
857
|
};
|
|
879
858
|
|
|
880
|
-
var tripletQ = {
|
|
881
|
-
2: 3,
|
|
882
|
-
3: 2,
|
|
883
|
-
4: 3,
|
|
884
|
-
5: 2, // TODO-PER: not handling 6/8 rhythm yet
|
|
885
|
-
6: 2,
|
|
886
|
-
7: 2, // TODO-PER: not handling 6/8 rhythm yet
|
|
887
|
-
8: 3,
|
|
888
|
-
9: 2 // TODO-PER: not handling 6/8 rhythm yet
|
|
889
|
-
};
|
|
890
|
-
|
|
891
859
|
var letter_to_open_slurs_and_triplets = function(line, i) {
|
|
892
860
|
// consume spaces, and look for all the open parens. If there is a number after the open paren,
|
|
893
861
|
// that is a triplet. Otherwise that is a slur. Collect all the slurs and the first triplet.
|
|
@@ -1050,9 +1018,6 @@ var addEndBeam = function(el) {
|
|
|
1050
1018
|
return el;
|
|
1051
1019
|
};
|
|
1052
1020
|
|
|
1053
|
-
var pitches = {A: 5, B: 6, C: 0, D: 1, E: 2, F: 3, G: 4, a: 12, b: 13, c: 7, d: 8, e: 9, f: 10, g: 11};
|
|
1054
|
-
var rests = {x: 'invisible', X: 'invisible-multimeasure', y: 'spacer', z: 'rest', Z: 'multimeasure' };
|
|
1055
|
-
var accMap = { 'dblflat': '__', 'flat': '_', 'natural': '=', 'sharp': '^', 'dblsharp': '^^', 'quarterflat': '_/', 'quartersharp': '^/'};
|
|
1056
1021
|
var getCoreNote = function(line, index, el, canHaveBrokenRhythm) {
|
|
1057
1022
|
//var el = { startChar: index };
|
|
1058
1023
|
var isComplete = function(state) {
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
module.exports.legalAccents = [
|
|
2
|
+
'trill',
|
|
3
|
+
'lowermordent',
|
|
4
|
+
'uppermordent',
|
|
5
|
+
'mordent',
|
|
6
|
+
'pralltriller',
|
|
7
|
+
'accent',
|
|
8
|
+
'fermata',
|
|
9
|
+
'invertedfermata',
|
|
10
|
+
'tenuto',
|
|
11
|
+
'0',
|
|
12
|
+
'1',
|
|
13
|
+
'2',
|
|
14
|
+
'3',
|
|
15
|
+
'4',
|
|
16
|
+
'5',
|
|
17
|
+
'+',
|
|
18
|
+
'wedge',
|
|
19
|
+
'open',
|
|
20
|
+
'thumb',
|
|
21
|
+
'snap',
|
|
22
|
+
'turn',
|
|
23
|
+
'roll',
|
|
24
|
+
'breath',
|
|
25
|
+
'shortphrase',
|
|
26
|
+
'mediumphrase',
|
|
27
|
+
'longphrase',
|
|
28
|
+
'segno',
|
|
29
|
+
'coda',
|
|
30
|
+
'D.S.',
|
|
31
|
+
'D.C.',
|
|
32
|
+
'fine',
|
|
33
|
+
'beambr1',
|
|
34
|
+
'beambr2',
|
|
35
|
+
'slide',
|
|
36
|
+
'marcato',
|
|
37
|
+
'upbow',
|
|
38
|
+
'downbow',
|
|
39
|
+
'/',
|
|
40
|
+
'//',
|
|
41
|
+
'///',
|
|
42
|
+
'////',
|
|
43
|
+
'trem1',
|
|
44
|
+
'trem2',
|
|
45
|
+
'trem3',
|
|
46
|
+
'trem4',
|
|
47
|
+
'turnx',
|
|
48
|
+
'invertedturn',
|
|
49
|
+
'invertedturnx',
|
|
50
|
+
'trill(',
|
|
51
|
+
'trill)',
|
|
52
|
+
'arpeggio',
|
|
53
|
+
'xstem',
|
|
54
|
+
'mark',
|
|
55
|
+
'umarcato',
|
|
56
|
+
'style=normal',
|
|
57
|
+
'style=harmonic',
|
|
58
|
+
'style=rhythm',
|
|
59
|
+
'style=x',
|
|
60
|
+
'style=triangle',
|
|
61
|
+
'D.C.alcoda',
|
|
62
|
+
'D.C.alfine',
|
|
63
|
+
'D.S.alcoda',
|
|
64
|
+
'D.S.alfine',
|
|
65
|
+
'editorial',
|
|
66
|
+
'courtesy'
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
module.exports.volumeDecorations = [
|
|
70
|
+
'p',
|
|
71
|
+
'pp',
|
|
72
|
+
'f',
|
|
73
|
+
'ff',
|
|
74
|
+
'mf',
|
|
75
|
+
'mp',
|
|
76
|
+
'ppp',
|
|
77
|
+
'pppp',
|
|
78
|
+
'fff',
|
|
79
|
+
'ffff',
|
|
80
|
+
'sfz'
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
module.exports.dynamicDecorations = [
|
|
84
|
+
'crescendo(',
|
|
85
|
+
'crescendo)',
|
|
86
|
+
'diminuendo(',
|
|
87
|
+
'diminuendo)',
|
|
88
|
+
'glissando(',
|
|
89
|
+
'glissando)',
|
|
90
|
+
'~(',
|
|
91
|
+
'~)'
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
module.exports.accentPseudonyms = [
|
|
95
|
+
['<', 'accent'],
|
|
96
|
+
['>', 'accent'],
|
|
97
|
+
['tr', 'trill'],
|
|
98
|
+
['plus', '+'],
|
|
99
|
+
['emphasis', 'accent'],
|
|
100
|
+
['^', 'umarcato'],
|
|
101
|
+
['marcato', 'umarcato']
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
module.exports.accentDynamicPseudonyms = [
|
|
105
|
+
['<(', 'crescendo('],
|
|
106
|
+
['<)', 'crescendo)'],
|
|
107
|
+
['>(', 'diminuendo('],
|
|
108
|
+
['>)', 'diminuendo)']
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
module.exports.nonDecorations = 'ABCDEFGabcdefgxyzZ[]|^_{'; // use this to prescreen so we don't have to look for a decoration at every note.
|
|
112
|
+
|
|
113
|
+
module.exports.durations = [
|
|
114
|
+
0.5, 0.75, 0.875, 0.9375, 0.96875, 0.984375, 0.25, 0.375, 0.4375, 0.46875,
|
|
115
|
+
0.484375, 0.4921875, 0.125, 0.1875, 0.21875, 0.234375, 0.2421875, 0.24609375,
|
|
116
|
+
0.0625, 0.09375, 0.109375, 0.1171875, 0.12109375, 0.123046875, 0.03125,
|
|
117
|
+
0.046875, 0.0546875, 0.05859375, 0.060546875, 0.0615234375, 0.015625,
|
|
118
|
+
0.0234375, 0.02734375, 0.029296875, 0.0302734375, 0.03076171875
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
module.exports.pitches = {
|
|
122
|
+
A: 5,
|
|
123
|
+
B: 6,
|
|
124
|
+
C: 0,
|
|
125
|
+
D: 1,
|
|
126
|
+
E: 2,
|
|
127
|
+
F: 3,
|
|
128
|
+
G: 4,
|
|
129
|
+
a: 12,
|
|
130
|
+
b: 13,
|
|
131
|
+
c: 7,
|
|
132
|
+
d: 8,
|
|
133
|
+
e: 9,
|
|
134
|
+
f: 10,
|
|
135
|
+
g: 11
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
module.exports.rests = {
|
|
139
|
+
x: 'invisible',
|
|
140
|
+
X: 'invisible-multimeasure',
|
|
141
|
+
y: 'spacer',
|
|
142
|
+
z: 'rest',
|
|
143
|
+
Z: 'multimeasure'
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
module.exports.accMap = {
|
|
147
|
+
dblflat: '__',
|
|
148
|
+
flat: '_',
|
|
149
|
+
natural: '=',
|
|
150
|
+
sharp: '^',
|
|
151
|
+
dblsharp: '^^',
|
|
152
|
+
quarterflat: '_/',
|
|
153
|
+
quartersharp: '^/'
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
module.exports.tripletQ = {
|
|
157
|
+
2: 3,
|
|
158
|
+
3: 2,
|
|
159
|
+
4: 3,
|
|
160
|
+
5: 2, // TODO-PER: not handling 6/8 rhythm yet
|
|
161
|
+
6: 2,
|
|
162
|
+
7: 2, // TODO-PER: not handling 6/8 rhythm yet
|
|
163
|
+
8: 3,
|
|
164
|
+
9: 2 // TODO-PER: not handling 6/8 rhythm yet
|
|
165
|
+
};
|