abcjs 6.0.2 → 6.1.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 +6 -0
- package/RELEASE.md +60 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +1344 -401
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/index.js +2 -0
- package/package.json +2 -2
- package/src/const/key-accidentals.js +53 -0
- package/src/const/relative-major.js +92 -0
- package/src/parse/abc_parse.js +20 -9
- package/src/parse/abc_parse_book.js +3 -2
- package/src/parse/abc_parse_header.js +3 -3
- package/src/parse/abc_parse_key_voice.js +9 -150
- package/src/parse/abc_parse_music.js +2 -2
- package/src/parse/abc_tokenizer.js +8 -8
- package/src/parse/abc_transpose.js +31 -69
- package/src/parse/all-notes.js +22 -0
- package/src/parse/transpose-chord.js +80 -0
- package/src/str/output.js +433 -0
- package/src/synth/abc_midi_flattener.js +1 -1
- package/src/synth/create-note-map.js +4 -0
- package/src/synth/place-note.js +1 -1
- package/src/test/abc_parser_lint.js +1 -1
- package/src/write/abc_abstract_engraver.js +15 -0
- package/src/write/abc_beam_element.js +24 -0
- package/src/write/abc_decoration.js +13 -0
- package/src/write/abc_glissando_element.js +7 -0
- package/src/write/abc_tie_element.js +11 -0
- package/src/write/draw/glissando.js +75 -0
- package/src/write/draw/voice.js +4 -0
- package/src/write/format-jazz-chord.js +1 -1
- package/src/write/top-text.js +1 -1
- package/types/index.d.ts +12 -8
- package/version.js +1 -1
package/index.js
CHANGED
|
@@ -25,6 +25,7 @@ var version = require('./version');
|
|
|
25
25
|
var animation = require('./src/api/abc_animation');
|
|
26
26
|
var tuneBook = require('./src/api/abc_tunebook');
|
|
27
27
|
var sequence = require('./src/synth/abc_midi_sequencer');
|
|
28
|
+
var strTranspose = require('./src/str/output');
|
|
28
29
|
|
|
29
30
|
var abcjs = {};
|
|
30
31
|
|
|
@@ -43,6 +44,7 @@ abcjs.TimingCallbacks = require('./src/api/abc_timing_callbacks');
|
|
|
43
44
|
|
|
44
45
|
var glyphs = require('./src/write/abc_glyphs');
|
|
45
46
|
abcjs.setGlyph = glyphs.setSymbol;
|
|
47
|
+
abcjs.strTranspose = strTranspose;
|
|
46
48
|
|
|
47
49
|
var CreateSynth = require('./src/synth/create-synth');
|
|
48
50
|
var instrumentIndexToName = require('./src/synth/instrument-index-to-name');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abcjs",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Renderer for abc music notation",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"build:basic": "npm run webpack -- --mode development --config-name basic",
|
|
11
11
|
"build:basic-min": "npm run webpack -- --mode production --config-name basic",
|
|
12
12
|
"build:plugin": "npm run webpack -- --mode production --config-name plugin",
|
|
13
|
-
"test": "
|
|
13
|
+
"test": "echo 'To run tests, open the file tests/all.html in a browser.'",
|
|
14
14
|
"docs:dev": "vuepress dev docs",
|
|
15
15
|
"docs:build": "vuepress build docs",
|
|
16
16
|
"build:analyze": "npm run build:basic -- --env analyze"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
var { relativeMajor } = require("./relative-major");
|
|
2
|
+
|
|
3
|
+
var key1sharp = { acc: 'sharp', note: 'f' };
|
|
4
|
+
var key2sharp = { acc: 'sharp', note: 'c' };
|
|
5
|
+
var key3sharp = { acc: 'sharp', note: 'g' };
|
|
6
|
+
var key4sharp = { acc: 'sharp', note: 'd' };
|
|
7
|
+
var key5sharp = { acc: 'sharp', note: 'A' };
|
|
8
|
+
var key6sharp = { acc: 'sharp', note: 'e' };
|
|
9
|
+
var key7sharp = { acc: 'sharp', note: 'B' };
|
|
10
|
+
var key1flat = { acc: 'flat', note: 'B' };
|
|
11
|
+
var key2flat = { acc: 'flat', note: 'e' };
|
|
12
|
+
var key3flat = { acc: 'flat', note: 'A' };
|
|
13
|
+
var key4flat = { acc: 'flat', note: 'd' };
|
|
14
|
+
var key5flat = { acc: 'flat', note: 'G' };
|
|
15
|
+
var key6flat = { acc: 'flat', note: 'c' };
|
|
16
|
+
var key7flat = { acc: 'flat', note: 'F' };
|
|
17
|
+
|
|
18
|
+
var keys = {
|
|
19
|
+
'C#': [key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp],
|
|
20
|
+
'F#': [key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp],
|
|
21
|
+
'B': [key1sharp, key2sharp, key3sharp, key4sharp, key5sharp],
|
|
22
|
+
'E': [key1sharp, key2sharp, key3sharp, key4sharp],
|
|
23
|
+
'A': [key1sharp, key2sharp, key3sharp],
|
|
24
|
+
'D': [key1sharp, key2sharp],
|
|
25
|
+
'G': [key1sharp],
|
|
26
|
+
'C': [],
|
|
27
|
+
'F': [key1flat],
|
|
28
|
+
'Bb': [key1flat, key2flat],
|
|
29
|
+
'Eb': [key1flat, key2flat, key3flat],
|
|
30
|
+
'Cm': [key1flat, key2flat, key3flat],
|
|
31
|
+
'Ab': [key1flat, key2flat, key3flat, key4flat],
|
|
32
|
+
'Db': [key1flat, key2flat, key3flat, key4flat, key5flat],
|
|
33
|
+
'Gb': [key1flat, key2flat, key3flat, key4flat, key5flat, key6flat],
|
|
34
|
+
'Cb': [key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat],
|
|
35
|
+
|
|
36
|
+
// The following are not in the 2.0 spec, but seem normal enough.
|
|
37
|
+
// TODO-PER: These SOUND the same as what's written, but they aren't right
|
|
38
|
+
'A#': [key1flat, key2flat],
|
|
39
|
+
'B#': [],
|
|
40
|
+
'D#': [key1flat, key2flat, key3flat],
|
|
41
|
+
'E#': [key1flat],
|
|
42
|
+
'G#': [key1flat, key2flat, key3flat, key4flat],
|
|
43
|
+
'none': [],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function keyAccidentals(key) {
|
|
47
|
+
var newKey = keys[relativeMajor(key)]
|
|
48
|
+
if (!newKey) // If we don't recognize the key then there is no change
|
|
49
|
+
return null
|
|
50
|
+
return JSON.parse(JSON.stringify(newKey))
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
module.exports = keyAccidentals;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// All these keys have the same number of accidentals
|
|
2
|
+
var keys = {
|
|
3
|
+
'C': { modes: ['CMaj', 'Amin', 'Am', 'GMix', 'DDor', 'EPhr', 'FLyd', 'BLoc'], stepsFromC: 0 },
|
|
4
|
+
'Db': { modes: ['DbMaj', 'Bbmin', 'Bbm', 'AbMix', 'EbDor', 'FPhr', 'GbLyd', 'CLoc'], stepsFromC: 1 },
|
|
5
|
+
'D': { modes: ['DMaj', 'Bmin', 'Bm', 'AMix', 'EDor', 'F#Phr', 'GLyd', 'C#Loc'], stepsFromC: 2 },
|
|
6
|
+
'Eb': { modes: ['EbMaj', 'Cmin', 'Cm', 'BbMix', 'FDor', 'GPhr', 'AbLyd', 'DLoc'], stepsFromC: 3 },
|
|
7
|
+
'E': { modes: ['EMaj', 'C#min', 'C#m', 'BMix', 'F#Dor', 'G#Phr', 'ALyd', 'D#Loc'], stepsFromC: 4 },
|
|
8
|
+
'F': { modes: ['FMaj', 'Dmin', 'Dm', 'CMix', 'GDor', 'APhr', 'BbLyd', 'ELoc'], stepsFromC: 5 },
|
|
9
|
+
'Gb': { modes: ['GbMaj', 'Ebmin', 'Ebm', 'DbMix', 'AbDor', 'BbPhr', 'CbLyd', 'FLoc'], stepsFromC: 6 },
|
|
10
|
+
'G': { modes: ['GMaj', 'Emin', 'Em', 'DMix', 'ADor', 'BPhr', 'CLyd', 'F#Loc'], stepsFromC: 7 },
|
|
11
|
+
'Ab': { modes: ['AbMaj', 'Fmin', 'Fm', 'EbMix', 'BbDor', 'CPhr', 'DbLyd', 'GLoc'], stepsFromC: 8 },
|
|
12
|
+
'A': { modes: ['AMaj', 'F#min', 'F#m', 'EMix', 'BDor', 'C#Phr', 'DLyd', 'G#Loc'], stepsFromC: 9 },
|
|
13
|
+
'Bb': { modes: ['BbMaj', 'Gmin', 'Gm', 'FMix', 'CDor', 'DPhr', 'EbLyd', 'ALoc'], stepsFromC: 10 },
|
|
14
|
+
'B': { modes: ['BMaj', 'G#min', 'G#m', 'F#Mix', 'C#Dor', 'D#Phr', 'ELyd', 'A#Loc'], stepsFromC: 11 },
|
|
15
|
+
// Enharmonic keys
|
|
16
|
+
'C#': { modes: ['C#Maj', 'A#min', 'A#m', 'G#Mix', 'D#Dor', 'E#Phr', 'F#Lyd', 'B#Loc'], stepsFromC: 1 },
|
|
17
|
+
'F#': { modes: ['F#Maj', 'D#min', 'D#m', 'C#Mix', 'G#Dor', 'A#Phr', 'BLyd', 'E#Loc'], stepsFromC: 6 },
|
|
18
|
+
'Cb': { modes: ['CbMaj', 'Abmin', 'Abm', 'GbMix', 'DbDor', 'EbPhr', 'FbLyd', 'BbLoc'], stepsFromC: 11 },
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var keyReverse = null
|
|
22
|
+
|
|
23
|
+
function createKeyReverse() {
|
|
24
|
+
keyReverse = {}
|
|
25
|
+
var allKeys = Object.keys(keys)
|
|
26
|
+
for (var i = 0 ; i < allKeys.length; i++) {
|
|
27
|
+
var keyObj = keys[allKeys[i]]
|
|
28
|
+
keyReverse[allKeys[i].toLowerCase()] = allKeys[i];
|
|
29
|
+
for (var j = 0; j < keyObj.modes.length; j++) {
|
|
30
|
+
var mode = keyObj.modes[j].toLowerCase()
|
|
31
|
+
keyReverse[mode] = allKeys[i];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function relativeMajor(key) {
|
|
37
|
+
// Translate a key to its relative major. If it doesn't exist, do the best we can
|
|
38
|
+
// by just returning the original key.
|
|
39
|
+
// There are alternate spellings of these - so the search needs to be case insensitive.
|
|
40
|
+
// To make this efficient, the first time this is called the "keys" object is reversed so this search is fast in the future
|
|
41
|
+
if (!keyReverse) {
|
|
42
|
+
createKeyReverse()
|
|
43
|
+
}
|
|
44
|
+
// get the key portion itself - there might be other stuff, like extra sharps and flats, or the mode written out.
|
|
45
|
+
var mode = key.toLowerCase().match(/([a-g][b#]?)(maj|min|mix|dor|phr|lyd|loc|m)?/)
|
|
46
|
+
if (!mode || !mode[2])
|
|
47
|
+
return key;
|
|
48
|
+
mode = mode[1] + mode[2]
|
|
49
|
+
var maj = keyReverse[mode]
|
|
50
|
+
if (maj)
|
|
51
|
+
return maj;
|
|
52
|
+
return key;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function relativeMode(majorKey, mode) {
|
|
56
|
+
// The reverse of the relativeMajor. Translate it back to the original mode.
|
|
57
|
+
// If it isn't a recognized mode or it is already major, then just return the major key.
|
|
58
|
+
var group = keys[majorKey]
|
|
59
|
+
if (!group)
|
|
60
|
+
return majorKey;
|
|
61
|
+
if (mode === '')
|
|
62
|
+
return majorKey;
|
|
63
|
+
var match = mode.toLowerCase().match(/^(maj|min|mix|dor|phr|lyd|loc|m)/)
|
|
64
|
+
if (!match)
|
|
65
|
+
return majorKey
|
|
66
|
+
var regMode = match[1]
|
|
67
|
+
for (var i = 0; i < group.modes.length; i++) {
|
|
68
|
+
var thisMode = group.modes[i]
|
|
69
|
+
var ind = thisMode.toLowerCase().indexOf(regMode)
|
|
70
|
+
if (ind !== -1 && ind === thisMode.length - regMode.length)
|
|
71
|
+
return thisMode.substring(0, thisMode.length - regMode.length)
|
|
72
|
+
}
|
|
73
|
+
return majorKey;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function transposeKey(key, steps) {
|
|
77
|
+
// This takes a major key and adds the desired steps.
|
|
78
|
+
// It assigns each key a number that is the number of steps from C so that there can just be arithmetic.
|
|
79
|
+
var match = keys[key]
|
|
80
|
+
if (!match)
|
|
81
|
+
return key;
|
|
82
|
+
while (steps < 0) steps += 12;
|
|
83
|
+
var fromC = (match.stepsFromC + steps) % 12;
|
|
84
|
+
for (var i = 0; i < Object.keys(keys).length; i++) {
|
|
85
|
+
var k = Object.keys(keys)[i]
|
|
86
|
+
if (keys[k].stepsFromC === fromC)
|
|
87
|
+
return k;
|
|
88
|
+
}
|
|
89
|
+
return key;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {relativeMajor: relativeMajor, relativeMode: relativeMode, transposeKey: transposeKey};
|
package/src/parse/abc_parse.js
CHANGED
|
@@ -224,6 +224,7 @@ var Parse = function() {
|
|
|
224
224
|
var replace = false;
|
|
225
225
|
var addWord = function(i) {
|
|
226
226
|
var word = parseCommon.strip(words.substring(last_divider, i));
|
|
227
|
+
word = word.replace(/\\([-_*|~])/g, '$1')
|
|
227
228
|
last_divider = i+1;
|
|
228
229
|
if (word.length > 0) {
|
|
229
230
|
if (replace)
|
|
@@ -237,34 +238,44 @@ var Parse = function() {
|
|
|
237
238
|
}
|
|
238
239
|
return false;
|
|
239
240
|
};
|
|
241
|
+
var escNext = false;
|
|
240
242
|
for (var i = 0; i < words.length; i++) {
|
|
241
|
-
switch (words
|
|
243
|
+
switch (words[i]) {
|
|
242
244
|
case ' ':
|
|
243
245
|
case '\x12':
|
|
244
246
|
addWord(i);
|
|
245
247
|
break;
|
|
246
248
|
case '-':
|
|
247
|
-
if (!addWord(i) && word_list.length > 0) {
|
|
249
|
+
if (!escNext && !addWord(i) && word_list.length > 0) {
|
|
248
250
|
parseCommon.last(word_list).divider = '-';
|
|
249
251
|
word_list.push({skip: true, to: 'next'});
|
|
250
252
|
}
|
|
251
253
|
break;
|
|
252
254
|
case '_':
|
|
253
|
-
|
|
254
|
-
|
|
255
|
+
if (!escNext) {
|
|
256
|
+
addWord(i);
|
|
257
|
+
word_list.push({skip: true, to: 'slur'});
|
|
258
|
+
}
|
|
255
259
|
break;
|
|
256
260
|
case '*':
|
|
257
|
-
|
|
258
|
-
|
|
261
|
+
if (!escNext) {
|
|
262
|
+
addWord(i);
|
|
263
|
+
word_list.push({skip: true, to: 'next'});
|
|
264
|
+
}
|
|
259
265
|
break;
|
|
260
266
|
case '|':
|
|
261
|
-
|
|
262
|
-
|
|
267
|
+
if (!escNext) {
|
|
268
|
+
addWord(i);
|
|
269
|
+
word_list.push({skip: true, to: 'bar'});
|
|
270
|
+
}
|
|
263
271
|
break;
|
|
264
272
|
case '~':
|
|
265
|
-
|
|
273
|
+
if (!escNext) {
|
|
274
|
+
replace = true;
|
|
275
|
+
}
|
|
266
276
|
break;
|
|
267
277
|
}
|
|
278
|
+
escNext = words[i] === '\\'
|
|
268
279
|
}
|
|
269
280
|
|
|
270
281
|
var inSlur = false;
|
|
@@ -6,13 +6,14 @@ var bookParser = function(book) {
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
8
|
var directives = "";
|
|
9
|
+
var initialWhiteSpace = book.match(/(\s*)/)
|
|
9
10
|
book = parseCommon.strip(book);
|
|
10
11
|
var tuneStrings = book.split("\nX:");
|
|
11
12
|
// Put back the X: that we lost when splitting the tunes.
|
|
12
13
|
for (var i = 1; i < tuneStrings.length; i++)
|
|
13
14
|
tuneStrings[i] = "X:" + tuneStrings[i];
|
|
14
|
-
// Keep track of the character position each tune starts with.
|
|
15
|
-
var pos = 0;
|
|
15
|
+
// Keep track of the character position each tune starts with. If the string starts with white space, count that, too.
|
|
16
|
+
var pos = initialWhiteSpace ? initialWhiteSpace[0].length : 0;
|
|
16
17
|
var tunes = [];
|
|
17
18
|
parseCommon.each(tuneStrings, function(tune) {
|
|
18
19
|
tunes.push({ abc: tune, startPos: pos});
|
|
@@ -364,7 +364,7 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
364
364
|
multilineVars.meter = meter;
|
|
365
365
|
return [ e-i+1+ws ];
|
|
366
366
|
case "[K:":
|
|
367
|
-
var result = parseKeyVoice.parseKey(line.substring(i+3, e));
|
|
367
|
+
var result = parseKeyVoice.parseKey(line.substring(i+3, e), true);
|
|
368
368
|
if (result.foundClef && tuneBuilder.hasBeginMusic())
|
|
369
369
|
tuneBuilder.appendStartingElement('clef', startChar, endChar, multilineVars.clef);
|
|
370
370
|
if (result.foundKey && tuneBuilder.hasBeginMusic())
|
|
@@ -426,7 +426,7 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
426
426
|
tuneBuilder.appendStartingElement('meter', multilineVars.iChar + i, multilineVars.iChar + line.length, meter);
|
|
427
427
|
return [ line.length ];
|
|
428
428
|
case "K:":
|
|
429
|
-
var result = parseKeyVoice.parseKey(line.substring(i+2));
|
|
429
|
+
var result = parseKeyVoice.parseKey(line.substring(i+2), tuneBuilder.hasBeginMusic());
|
|
430
430
|
if (result.foundClef && tuneBuilder.hasBeginMusic())
|
|
431
431
|
tuneBuilder.appendStartingElement('clef', multilineVars.iChar + i, multilineVars.iChar + line.length, multilineVars.clef);
|
|
432
432
|
if (result.foundKey && tuneBuilder.hasBeginMusic())
|
|
@@ -498,7 +498,7 @@ var ParseHeader = function(tokenizer, warn, multilineVars, tune, tuneBuilder) {
|
|
|
498
498
|
case 'K':
|
|
499
499
|
// since the key is the last thing that can happen in the header, we can resolve the tempo now
|
|
500
500
|
this.resolveTempo();
|
|
501
|
-
var result = parseKeyVoice.parseKey(line.substring(2));
|
|
501
|
+
var result = parseKeyVoice.parseKey(line.substring(2), false);
|
|
502
502
|
if (!multilineVars.is_in_header && tuneBuilder.hasBeginMusic()) {
|
|
503
503
|
if (result.foundClef)
|
|
504
504
|
tuneBuilder.appendStartingElement('clef', startChar, endChar, multilineVars.clef);
|
|
@@ -19,154 +19,7 @@ var parseKeyVoice = {};
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
parseKeyVoice.standardKey = function(keyName, root, acc, localTranspose) {
|
|
22
|
-
|
|
23
|
-
var key2sharp = {acc: 'sharp', note: 'c'};
|
|
24
|
-
var key3sharp = {acc: 'sharp', note: 'g'};
|
|
25
|
-
var key4sharp = {acc: 'sharp', note: 'd'};
|
|
26
|
-
var key5sharp = {acc: 'sharp', note: 'A'};
|
|
27
|
-
var key6sharp = {acc: 'sharp', note: 'e'};
|
|
28
|
-
var key7sharp = {acc: 'sharp', note: 'B'};
|
|
29
|
-
var key1flat = {acc: 'flat', note: 'B'};
|
|
30
|
-
var key2flat = {acc: 'flat', note: 'e'};
|
|
31
|
-
var key3flat = {acc: 'flat', note: 'A'};
|
|
32
|
-
var key4flat = {acc: 'flat', note: 'd'};
|
|
33
|
-
var key5flat = {acc: 'flat', note: 'G'};
|
|
34
|
-
var key6flat = {acc: 'flat', note: 'c'};
|
|
35
|
-
var key7flat = {acc: 'flat', note: 'F'};
|
|
36
|
-
|
|
37
|
-
var keys = {
|
|
38
|
-
'C#': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
39
|
-
'A#m': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
40
|
-
'G#Mix': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
41
|
-
'D#Dor': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
42
|
-
'E#Phr': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
43
|
-
'F#Lyd': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
44
|
-
'B#Loc': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
45
|
-
|
|
46
|
-
'F#': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
47
|
-
'D#m': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
48
|
-
'C#Mix': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
49
|
-
'G#Dor': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
50
|
-
'A#Phr': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
51
|
-
'BLyd': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
52
|
-
'E#Loc': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp ],
|
|
53
|
-
|
|
54
|
-
'B': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
55
|
-
'G#m': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
56
|
-
'F#Mix': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
57
|
-
'C#Dor': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
58
|
-
'D#Phr': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
59
|
-
'ELyd': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
60
|
-
'A#Loc': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp ],
|
|
61
|
-
|
|
62
|
-
'E': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
63
|
-
'C#m': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
64
|
-
'BMix': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
65
|
-
'F#Dor': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
66
|
-
'G#Phr': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
67
|
-
'ALyd': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
68
|
-
'D#Loc': [ key1sharp, key2sharp, key3sharp, key4sharp ],
|
|
69
|
-
|
|
70
|
-
'A': [ key1sharp, key2sharp, key3sharp ],
|
|
71
|
-
'F#m': [ key1sharp, key2sharp, key3sharp ],
|
|
72
|
-
'EMix': [ key1sharp, key2sharp, key3sharp ],
|
|
73
|
-
'BDor': [ key1sharp, key2sharp, key3sharp ],
|
|
74
|
-
'C#Phr': [ key1sharp, key2sharp, key3sharp ],
|
|
75
|
-
'DLyd': [ key1sharp, key2sharp, key3sharp ],
|
|
76
|
-
'G#Loc': [ key1sharp, key2sharp, key3sharp ],
|
|
77
|
-
|
|
78
|
-
'D': [ key1sharp, key2sharp ],
|
|
79
|
-
'Bm': [ key1sharp, key2sharp ],
|
|
80
|
-
'AMix': [ key1sharp, key2sharp ],
|
|
81
|
-
'EDor': [ key1sharp, key2sharp ],
|
|
82
|
-
'F#Phr': [ key1sharp, key2sharp ],
|
|
83
|
-
'GLyd': [ key1sharp, key2sharp ],
|
|
84
|
-
'C#Loc': [ key1sharp, key2sharp ],
|
|
85
|
-
|
|
86
|
-
'G': [ key1sharp ],
|
|
87
|
-
'Em': [ key1sharp ],
|
|
88
|
-
'DMix': [ key1sharp ],
|
|
89
|
-
'ADor': [ key1sharp ],
|
|
90
|
-
'BPhr': [ key1sharp ],
|
|
91
|
-
'CLyd': [ key1sharp ],
|
|
92
|
-
'F#Loc': [ key1sharp ],
|
|
93
|
-
|
|
94
|
-
'C': [],
|
|
95
|
-
'Am': [],
|
|
96
|
-
'GMix': [],
|
|
97
|
-
'DDor': [],
|
|
98
|
-
'EPhr': [],
|
|
99
|
-
'FLyd': [],
|
|
100
|
-
'BLoc': [],
|
|
101
|
-
|
|
102
|
-
'F': [ key1flat ],
|
|
103
|
-
'Dm': [ key1flat ],
|
|
104
|
-
'CMix': [ key1flat ],
|
|
105
|
-
'GDor': [ key1flat ],
|
|
106
|
-
'APhr': [ key1flat ],
|
|
107
|
-
'BbLyd': [ key1flat ],
|
|
108
|
-
'ELoc': [ key1flat ],
|
|
109
|
-
|
|
110
|
-
'Bb': [ key1flat, key2flat ],
|
|
111
|
-
'Gm': [ key1flat, key2flat ],
|
|
112
|
-
'FMix': [ key1flat, key2flat ],
|
|
113
|
-
'CDor': [ key1flat, key2flat ],
|
|
114
|
-
'DPhr': [ key1flat, key2flat ],
|
|
115
|
-
'EbLyd': [ key1flat, key2flat ],
|
|
116
|
-
'ALoc': [ key1flat, key2flat ],
|
|
117
|
-
|
|
118
|
-
'Eb': [ key1flat, key2flat, key3flat ],
|
|
119
|
-
'Cm': [ key1flat, key2flat, key3flat ],
|
|
120
|
-
'BbMix': [ key1flat, key2flat, key3flat ],
|
|
121
|
-
'FDor': [ key1flat, key2flat, key3flat ],
|
|
122
|
-
'GPhr': [ key1flat, key2flat, key3flat ],
|
|
123
|
-
'AbLyd': [ key1flat, key2flat, key3flat ],
|
|
124
|
-
'DLoc': [ key1flat, key2flat, key3flat ],
|
|
125
|
-
|
|
126
|
-
'Ab': [ key1flat, key2flat, key3flat, key4flat ],
|
|
127
|
-
'Fm': [ key1flat, key2flat, key3flat, key4flat ],
|
|
128
|
-
'EbMix': [ key1flat, key2flat, key3flat, key4flat ],
|
|
129
|
-
'BbDor': [ key1flat, key2flat, key3flat, key4flat ],
|
|
130
|
-
'CPhr': [ key1flat, key2flat, key3flat, key4flat ],
|
|
131
|
-
'DbLyd': [ key1flat, key2flat, key3flat, key4flat ],
|
|
132
|
-
'GLoc': [ key1flat, key2flat, key3flat, key4flat ],
|
|
133
|
-
|
|
134
|
-
'Db': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
135
|
-
'Bbm': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
136
|
-
'AbMix': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
137
|
-
'EbDor': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
138
|
-
'FPhr': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
139
|
-
'GbLyd': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
140
|
-
'CLoc': [ key1flat, key2flat, key3flat, key4flat, key5flat ],
|
|
141
|
-
|
|
142
|
-
'Gb': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
143
|
-
'Ebm': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
144
|
-
'DbMix': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
145
|
-
'AbDor': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
146
|
-
'BbPhr': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
147
|
-
'CbLyd': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
148
|
-
'FLoc': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat ],
|
|
149
|
-
|
|
150
|
-
'Cb': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
151
|
-
'Abm': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
152
|
-
'GbMix': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
153
|
-
'DbDor': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
154
|
-
'EbPhr': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
155
|
-
'FbLyd': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
156
|
-
'BbLoc': [ key1flat, key2flat, key3flat, key4flat, key5flat, key6flat, key7flat ],
|
|
157
|
-
|
|
158
|
-
// The following are not in the 2.0 spec, but seem normal enough.
|
|
159
|
-
// TODO-PER: These SOUND the same as what's written, but they aren't right
|
|
160
|
-
'A#': [ key1flat, key2flat ],
|
|
161
|
-
'B#': [],
|
|
162
|
-
'D#': [ key1flat, key2flat, key3flat ],
|
|
163
|
-
'E#': [ key1flat ],
|
|
164
|
-
'G#': [ key1flat, key2flat, key3flat, key4flat ],
|
|
165
|
-
'Gbm': [ key1sharp, key2sharp, key3sharp, key4sharp, key5sharp, key6sharp, key7sharp ],
|
|
166
|
-
'none': []
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
return transpose.keySignature(multilineVars, keys, keyName, root, acc, localTranspose);
|
|
22
|
+
return transpose.keySignature(multilineVars, keyName, root, acc, localTranspose);
|
|
170
23
|
};
|
|
171
24
|
|
|
172
25
|
var clefLines = {
|
|
@@ -340,7 +193,7 @@ var parseKeyVoice = {};
|
|
|
340
193
|
}
|
|
341
194
|
};
|
|
342
195
|
|
|
343
|
-
parseKeyVoice.parseKey = function(str) // (and clef)
|
|
196
|
+
parseKeyVoice.parseKey = function(str, isInline) // (and clef)
|
|
344
197
|
{
|
|
345
198
|
// returns:
|
|
346
199
|
// { foundClef: true, foundKey: true }
|
|
@@ -431,8 +284,14 @@ var parseKeyVoice = {};
|
|
|
431
284
|
// We need to do a deep copy because we are going to modify it
|
|
432
285
|
var oldKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
433
286
|
//TODO-PER: HACK! To get the local transpose to work, the transposition is done for each line. This caused the global transposition variable to be factored in twice, so, instead of rewriting that right now, I'm just subtracting one of them here.
|
|
434
|
-
var keyCompensate = multilineVars.globalTranspose ? -multilineVars.globalTranspose : 0;
|
|
287
|
+
var keyCompensate = !isInline && multilineVars.globalTranspose ? -multilineVars.globalTranspose : 0;
|
|
288
|
+
//console.log("parse", JSON.stringify(multilineVars), isInline)
|
|
289
|
+
var savedOrigKey;
|
|
290
|
+
if (isInline)
|
|
291
|
+
savedOrigKey = multilineVars.globalTransposeOrigKeySig
|
|
435
292
|
multilineVars.key = parseKeyVoice.deepCopyKey(parseKeyVoice.standardKey(key, retPitch.token, acc, keyCompensate));
|
|
293
|
+
if (isInline)
|
|
294
|
+
multilineVars.globalTransposeOrigKeySig = savedOrigKey
|
|
436
295
|
multilineVars.key.mode = mode;
|
|
437
296
|
if (oldKey) {
|
|
438
297
|
// Add natural in all places that the old key had an accidental.
|
|
@@ -289,7 +289,7 @@ MusicParser.prototype.parseMusic = function(line) {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
multilineVars.addFormattingOptions(el, tune.formatting, 'bar');
|
|
292
|
-
tuneBuilder.appendElement('bar', startOfLine+
|
|
292
|
+
tuneBuilder.appendElement('bar', startOfLine+startI, startOfLine+i+ret[0], bar);
|
|
293
293
|
multilineVars.measureNotEmpty = false;
|
|
294
294
|
el = {};
|
|
295
295
|
}
|
|
@@ -732,7 +732,7 @@ var volumeDecorations = [
|
|
|
732
732
|
];
|
|
733
733
|
|
|
734
734
|
var dynamicDecorations = [
|
|
735
|
-
"crescendo(", "crescendo)", "diminuendo(", "diminuendo)"
|
|
735
|
+
"crescendo(", "crescendo)", "diminuendo(", "diminuendo)", "glissando(", "glissando)"
|
|
736
736
|
];
|
|
737
737
|
|
|
738
738
|
var accentPseudonyms = [
|
|
@@ -702,18 +702,15 @@ var Tokenizer = function(lines, multilineVars) {
|
|
|
702
702
|
}
|
|
703
703
|
switch (x.token) {
|
|
704
704
|
case 'pt': return { used: used+1, value: parseFloat(num) };
|
|
705
|
+
case 'px': return { used: used+1, value: parseFloat(num) };
|
|
705
706
|
case 'cm': return { used: used+1, value: parseFloat(num)/2.54*72 };
|
|
706
707
|
case 'in': return { used: used+1, value: parseFloat(num)*72 };
|
|
707
708
|
default: tokens.unshift(x); return { used: used, value: parseFloat(num) };
|
|
708
709
|
}
|
|
709
|
-
return { used: 0 };
|
|
710
710
|
};
|
|
711
|
-
var substInChord = function(str)
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
{
|
|
715
|
-
str = str.replace("\\n", "\n");
|
|
716
|
-
}
|
|
711
|
+
var substInChord = function(str) {
|
|
712
|
+
str = str.replace(/\\n/g, "\n");
|
|
713
|
+
str = str.replace(/\\"/g, '"');
|
|
717
714
|
return str;
|
|
718
715
|
};
|
|
719
716
|
this.getBrackettedSubstring = function(line, i, maxErrorChars, _matchChar)
|
|
@@ -728,8 +725,11 @@ var Tokenizer = function(lines, multilineVars) {
|
|
|
728
725
|
// but in the error case it might not be.
|
|
729
726
|
var matchChar = _matchChar || line.charAt(i);
|
|
730
727
|
var pos = i+1;
|
|
731
|
-
|
|
728
|
+
var esc = false;
|
|
729
|
+
while ((pos < line.length) && (esc || line[pos] !== matchChar)) {
|
|
730
|
+
esc = line[pos] === '\\';
|
|
732
731
|
++pos;
|
|
732
|
+
}
|
|
733
733
|
if (line.charAt(pos) === matchChar)
|
|
734
734
|
return [pos-i+1,substInChord(line.substring(i+1, pos)), true];
|
|
735
735
|
else // we hit the end of line, so we'll just pick an arbitrary num of chars so the line doesn't disappear.
|