abcjs 6.0.2 → 6.0.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/README.md +2 -0
- package/RELEASE.md +22 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +87 -21
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/package.json +1 -1
- package/src/parse/abc_parse_header.js +3 -3
- package/src/parse/abc_parse_key_voice.js +8 -2
- package/src/parse/abc_tokenizer.js +8 -8
- package/src/parse/abc_transpose.js +23 -2
- package/src/parse/all-notes.js +22 -0
- package/src/synth/place-note.js +1 -1
- package/src/write/abc_abstract_engraver.js +3 -0
- package/src/write/abc_tie_element.js +11 -0
- package/src/write/format-jazz-chord.js +1 -1
- package/temp.txt +16 -0
- package/version.js +1 -1
package/package.json
CHANGED
|
@@ -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);
|
|
@@ -340,7 +340,7 @@ var parseKeyVoice = {};
|
|
|
340
340
|
}
|
|
341
341
|
};
|
|
342
342
|
|
|
343
|
-
parseKeyVoice.parseKey = function(str) // (and clef)
|
|
343
|
+
parseKeyVoice.parseKey = function(str, isInline) // (and clef)
|
|
344
344
|
{
|
|
345
345
|
// returns:
|
|
346
346
|
// { foundClef: true, foundKey: true }
|
|
@@ -431,8 +431,14 @@ var parseKeyVoice = {};
|
|
|
431
431
|
// We need to do a deep copy because we are going to modify it
|
|
432
432
|
var oldKey = parseKeyVoice.deepCopyKey(multilineVars.key);
|
|
433
433
|
//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;
|
|
434
|
+
var keyCompensate = !isInline && multilineVars.globalTranspose ? -multilineVars.globalTranspose : 0;
|
|
435
|
+
//console.log("parse", JSON.stringify(multilineVars), isInline)
|
|
436
|
+
var savedOrigKey;
|
|
437
|
+
if (isInline)
|
|
438
|
+
savedOrigKey = multilineVars.globalTransposeOrigKeySig
|
|
435
439
|
multilineVars.key = parseKeyVoice.deepCopyKey(parseKeyVoice.standardKey(key, retPitch.token, acc, keyCompensate));
|
|
440
|
+
if (isInline)
|
|
441
|
+
multilineVars.globalTransposeOrigKeySig = savedOrigKey
|
|
436
442
|
multilineVars.key.mode = mode;
|
|
437
443
|
if (oldKey) {
|
|
438
444
|
// Add natural in all places that the old key had an accidental.
|
|
@@ -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.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// abc_transpose.js: Handles the automatic transposition of key signatures, chord symbols, and notes.
|
|
2
2
|
|
|
3
|
+
const allNotes = require("./all-notes");
|
|
3
4
|
var transpose = {};
|
|
4
5
|
|
|
5
6
|
var keyIndex = {
|
|
@@ -196,19 +197,39 @@ var accidentals2 = {
|
|
|
196
197
|
"1": "sharp",
|
|
197
198
|
"2": "dblsharp"
|
|
198
199
|
};
|
|
200
|
+
var accidentals3 = {
|
|
201
|
+
"-2": "__",
|
|
202
|
+
"-1": "_",
|
|
203
|
+
"0": "=",
|
|
204
|
+
"1": "^",
|
|
205
|
+
"2": "^^"
|
|
206
|
+
};
|
|
207
|
+
var count = 0
|
|
199
208
|
transpose.note = function(multilineVars, el) {
|
|
200
|
-
// the "el" that is passed in has el.accidental, and el.pitch. "pitch" is the vertical position (0=middle C)
|
|
209
|
+
// the "el" that is passed in has el.name, el.accidental, and el.pitch. "pitch" is the vertical position (0=middle C)
|
|
201
210
|
// localTranspose is the number of half steps
|
|
202
211
|
// localTransposeVerticalMovement is the vertical distance to move.
|
|
212
|
+
//console.log(count++,multilineVars.localTranspose, el)
|
|
203
213
|
if (!multilineVars.localTranspose || multilineVars.clef.type === "perc")
|
|
204
214
|
return;
|
|
205
215
|
var origPitch = el.pitch;
|
|
206
|
-
|
|
216
|
+
if (multilineVars.localTransposeVerticalMovement) {
|
|
217
|
+
el.pitch = el.pitch + multilineVars.localTransposeVerticalMovement;
|
|
218
|
+
if (el.name) {
|
|
219
|
+
var actual = el.accidental ? el.name.substring(1) : el.name
|
|
220
|
+
var acc = el.accidental ? el.name[0] : ''
|
|
221
|
+
var p = allNotes.pitchIndex(actual)
|
|
222
|
+
el.name = acc + allNotes.noteName(p+multilineVars.localTransposeVerticalMovement)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
207
225
|
|
|
208
226
|
if (el.accidental) {
|
|
209
227
|
var ret = accidentalChange(origPitch, el.pitch, el.accidental, multilineVars.globalTransposeOrigKeySig, multilineVars.targetKey);
|
|
210
228
|
el.pitch = ret[0];
|
|
211
229
|
el.accidental = accidentals2[ret[1]];
|
|
230
|
+
if (el.name) {
|
|
231
|
+
el.name = accidentals3[ret[1]] + el.name.replace(/[_^=]/g,'');
|
|
232
|
+
}
|
|
212
233
|
}
|
|
213
234
|
|
|
214
235
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
var allNotes = {};
|
|
2
|
+
|
|
3
|
+
const allPitches = [
|
|
4
|
+
'C,,,', 'D,,,', 'E,,,', 'F,,,', 'G,,,', 'A,,,', 'B,,,',
|
|
5
|
+
'C,,', 'D,,', 'E,,', 'F,,', 'G,,', 'A,,', 'B,,',
|
|
6
|
+
'C,', 'D,', 'E,', 'F,', 'G,', 'A,', 'B,',
|
|
7
|
+
'C', 'D', 'E', 'F', 'G', 'A', 'B',
|
|
8
|
+
'c', 'd', 'e', 'f', 'g', 'a', 'b',
|
|
9
|
+
"c'", "d'", "e'", "f'", "g'", "a'", "b'",
|
|
10
|
+
"c''", "d''", "e''", "f''", "g''", "a''", "b''",
|
|
11
|
+
"c'''", "d'''", "e'''", "f'''", "g'''", "a'''", "b'''",
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
allNotes.pitchIndex = function(noteName) {
|
|
15
|
+
return allPitches.indexOf(noteName)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
allNotes.noteName = function(pitchIndex) {
|
|
19
|
+
return allPitches[pitchIndex]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = allNotes;
|
package/src/synth/place-note.js
CHANGED
|
@@ -69,7 +69,7 @@ function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMulti
|
|
|
69
69
|
}
|
|
70
70
|
var fnResolve;
|
|
71
71
|
offlineCtx.oncomplete = function(e) {
|
|
72
|
-
if (e.renderedBuffer) { // If the system gets overloaded then this can start failing. Just drop the note if so.
|
|
72
|
+
if (e.renderedBuffer && e.renderedBuffer.getChannelData) { // If the system gets overloaded or there are network problems then this can start failing. Just drop the note if so.
|
|
73
73
|
for (var i = 0; i < startArray.length; i++) {
|
|
74
74
|
//Math.floor(startArray[i] * sound.tempoMultiplier * sampleRate)
|
|
75
75
|
var start = startArray[i] * sound.tempoMultiplier;
|
|
@@ -845,6 +845,7 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
845
845
|
for (var j = 0; j < this.ties.length; j++) {
|
|
846
846
|
if (this.ties[j].anchor1 && this.ties[j].anchor1.pitch === notehead.pitch) {
|
|
847
847
|
this.ties[j].setEndAnchor(notehead);
|
|
848
|
+
voice.setRange(this.ties[j])
|
|
848
849
|
this.ties.splice(j, 1);
|
|
849
850
|
found = true;
|
|
850
851
|
break;
|
|
@@ -852,6 +853,7 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
852
853
|
}
|
|
853
854
|
if (!found) {
|
|
854
855
|
this.ties[0].setEndAnchor(notehead);
|
|
856
|
+
voice.setRange(this.ties[0])
|
|
855
857
|
this.ties.splice(0, 1);
|
|
856
858
|
}
|
|
857
859
|
}
|
|
@@ -878,6 +880,7 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
878
880
|
if (this.slurs[slurid]) {
|
|
879
881
|
slur = this.slurs[slurid];
|
|
880
882
|
slur.setEndAnchor(notehead);
|
|
883
|
+
voice.setRange(slur)
|
|
881
884
|
delete this.slurs[slurid];
|
|
882
885
|
} else {
|
|
883
886
|
slur = new TieElem({ anchor2: notehead, stemDir: this.stemdir, voiceNumber: voiceNumber});
|
|
@@ -25,6 +25,17 @@ TieElem.prototype.addInternalNote = function(note) {
|
|
|
25
25
|
TieElem.prototype.setEndAnchor = function(anchor2) {
|
|
26
26
|
// console.log("end", this.anchor1 ? this.anchor1.pitch : "N/A", anchor2 ? anchor2.pitch : "N/A", this.isTie, this.isGrace);
|
|
27
27
|
this.anchor2 = anchor2; // must have a .x and a .pitch property or be null (means ends at the end of the line)
|
|
28
|
+
|
|
29
|
+
// we don't really have enough info to know what the vertical extent is yet and we won't until drawing. This will just give it enough
|
|
30
|
+
// room on either side (we don't even know if the slur will be above yet). We need to set this so that we can make sure the voice has
|
|
31
|
+
// at least enough room that the line doesn't get cut off if the tie or slur is the lowest thing.
|
|
32
|
+
if (this.anchor1) {
|
|
33
|
+
this.top = Math.max(this.anchor1.pitch, this.anchor2.pitch) + 4
|
|
34
|
+
this.bottom = Math.min(this.anchor1.pitch, this.anchor2.pitch) - 4
|
|
35
|
+
} else {
|
|
36
|
+
this.top = this.anchor2.pitch + 4
|
|
37
|
+
this.bottom = this.anchor2.pitch - 4
|
|
38
|
+
}
|
|
28
39
|
};
|
|
29
40
|
|
|
30
41
|
// If we encounter a repeat sign, then we don't want to extend either a tie or a slur past it, so these are called to be a limit.
|
|
@@ -5,7 +5,7 @@ function formatJazzChord(chordString) {
|
|
|
5
5
|
for (var i = 0; i < lines.length; i++) {
|
|
6
6
|
var chord = lines[i];
|
|
7
7
|
// If the chord isn't in a recognizable format then just skip the formatting.
|
|
8
|
-
var reg = chord.match(/^([ABCDEFG][♯♭]?)?([^\/]+)?(\/[ABCDEFG][#b]?)?/);
|
|
8
|
+
var reg = chord.match(/^([ABCDEFG][♯♭]?)?([^\/]+)?(\/[ABCDEFG][#b♯♭]?)?/);
|
|
9
9
|
if (reg)
|
|
10
10
|
lines[i] = (reg[1]?reg[1]:'') + "\x03" + (reg[2]?reg[2]:'') + "\x03" + (reg[3]?reg[3]:'');
|
|
11
11
|
}
|
package/temp.txt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Fix unhandled rejection if there is a problem with an input note when creating notes.
|
|
2
|
+
|
|
3
|
+
put the height of ties/slurs in the line height calculation
|
|
4
|
+
|
|
5
|
+
Add transposition tests.
|
|
6
|
+
|
|
7
|
+
Add example of reusing created synth buffers.
|
|
8
|
+
|
|
9
|
+
Measurements that used "px" were reporting a warning.
|
|
10
|
+
|
|
11
|
+
Add quote to be escaped in chord.
|
|
12
|
+
|
|
13
|
+
Fix example in docs on creating a drum rhythm
|
|
14
|
+
|
|
15
|
+
Fix bass note in jazz chord when it contains a sharp or flat
|
|
16
|
+
|
package/version.js
CHANGED