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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abcjs",
3
- "version": "6.0.2",
3
+ "version": "6.0.3",
4
4
  "description": "Renderer for abc music notation",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -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
- while ( str.indexOf("\\n") !== -1)
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
- while ((pos < line.length) && (line.charAt(pos) !== matchChar))
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
- el.pitch = el.pitch + multilineVars.localTransposeVerticalMovement;
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;
@@ -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
@@ -1,3 +1,3 @@
1
- var version = '6.0.2';
1
+ var version = '6.0.3';
2
2
 
3
3
  module.exports = version;