abcjs 6.0.3 → 6.0.4

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.3",
3
+ "version": "6.0.4",
4
4
  "description": "Renderer for abc music notation",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -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.charAt(i)) {
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
- addWord(i);
254
- word_list.push({skip: true, to: 'slur'});
255
+ if (!escNext) {
256
+ addWord(i);
257
+ word_list.push({skip: true, to: 'slur'});
258
+ }
255
259
  break;
256
260
  case '*':
257
- addWord(i);
258
- word_list.push({skip: true, to: 'next'});
261
+ if (!escNext) {
262
+ addWord(i);
263
+ word_list.push({skip: true, to: 'next'});
264
+ }
259
265
  break;
260
266
  case '|':
261
- addWord(i);
262
- word_list.push({skip: true, to: 'bar'});
267
+ if (!escNext) {
268
+ addWord(i);
269
+ word_list.push({skip: true, to: 'bar'});
270
+ }
263
271
  break;
264
272
  case '~':
265
- replace = true;
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;
@@ -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 = [
@@ -630,7 +630,7 @@ var pitchesToPerc = require('./pitches-to-perc');
630
630
  if (name && percmap[name])
631
631
  actualPitch = percmap[name].sound;
632
632
  }
633
- var p = { cmd: 'note', pitch: actualPitch, volume: velocity, start: timeToRealTime(elem.time), duration: durationRounded(note.duration), instrument: currentInstrument };
633
+ var p = { cmd: 'note', pitch: actualPitch, volume: velocity, start: timeToRealTime(elem.time), duration: durationRounded(note.duration), instrument: currentInstrument, startChar: elem.elem.startChar, endChar: elem.elem.endChar};
634
634
  p = adjustForMicroTone(p);
635
635
  if (elem.gracenotes) {
636
636
  p.duration = p.duration / 2;
@@ -29,6 +29,10 @@ var createNoteMap = function(sequence) {
29
29
  end: Math.round((ev.start + len - gap) * 1000000)/1000000,
30
30
  volume: ev.volume
31
31
  };
32
+ if (ev.startChar)
33
+ obj.startChar = ev.startChar;
34
+ if (ev.endChar)
35
+ obj.endChar = ev.endChar;
32
36
  if (ev.style)
33
37
  obj.style = ev.style;
34
38
  if (ev.cents)
@@ -57,7 +57,7 @@ var ParserLint = function() {
57
57
  "trill", "lowermordent", "uppermordent", "mordent", "pralltriller", "accent",
58
58
  "fermata", "invertedfermata", "tenuto", "0", "1", "2", "3", "4", "5", "+", "wedge",
59
59
  "open", "thumb", "snap", "turn", "roll", "irishroll", "breath", "shortphrase", "mediumphrase", "longphrase",
60
- "segno", "coda", "D.S.", "D.C.", "fine", "crescendo(", "crescendo)", "diminuendo(", "diminuendo)",
60
+ "segno", "coda", "D.S.", "D.C.", "fine", "crescendo(", "crescendo)", "diminuendo(", "diminuendo)", "glissando(", "glissando)",
61
61
  "p", "pp", "f", "ff", "mf", "mp", "ppp", "pppp", "fff", "ffff", "sfz", "repeatbar", "repeatbar2", "slide",
62
62
  "upbow", "downbow", "staccato", "trem1", "trem2", "trem3", "trem4",
63
63
  "/", "//", "///", "////", "turnx", "invertedturn", "invertedturnx", "arpeggio", "trill(", "trill)", "xstem",
@@ -390,6 +390,13 @@ AbstractEngraver.prototype.createABCElement = function(isFirstStaff, isSingleLin
390
390
  var beamelem = new BeamElem(this.stemHeight * this.voiceScale, this.stemdir, this.flatBeams, elems[0]);
391
391
  if (hint) beamelem.setHint();
392
392
  for (var i = 0; i < elems.length; i++) {
393
+ // Do a first pass to figure out the stem direction before creating the notes, so that staccatos and other decorations can be placed correctly.
394
+ beamelem.runningDirection(elems[i])
395
+ }
396
+ beamelem.setStemDirection()
397
+ var tempStemDir = this.stemdir
398
+ this.stemdir = beamelem.stemsUp ? 'up' : 'down'
399
+ for (i = 0; i < elems.length; i++) {
393
400
  var elem = elems[i];
394
401
  var abselem = this.createNote(elem, true, isSingleLineStaff, voice);
395
402
  abselemset.push(abselem);
@@ -402,6 +409,7 @@ AbstractEngraver.prototype.createABCElement = function(isFirstStaff, isSingleLin
402
409
  }
403
410
  beamelem.calcDir();
404
411
  voice.addBeam(beamelem);
412
+ this.stemdir = tempStemDir
405
413
  return abselemset;
406
414
  };
407
415
 
@@ -1004,6 +1012,10 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
1004
1012
  // Add a little space to the left of the bar line so that nothing can crowd it.
1005
1013
  abselem.extraw -= 5;
1006
1014
 
1015
+ if (elem.chord !== undefined) {
1016
+ var ret3 = addChord(this.getTextSize, abselem, elem, 0, 0, 0, false);
1017
+ }
1018
+
1007
1019
  return abselem;
1008
1020
 
1009
1021
  };
@@ -42,6 +42,15 @@ var BeamElem = function BeamElem(stemHeight, type, flat, firstElement) {
42
42
  this.hint = true;
43
43
  };
44
44
 
45
+ BeamElem.prototype.runningDirection = function (abcelem) {
46
+ var pitch = abcelem.averagepitch;
47
+ if (pitch === undefined) return; // don't include elements like spacers in beams
48
+ this.total = Math.round(this.total+pitch);
49
+ if (!this.count)
50
+ this.count = 0;
51
+ this.count++
52
+ };
53
+
45
54
  BeamElem.prototype.add = function(abselem) {
46
55
  var pitch = abselem.abcelem.averagepitch;
47
56
  if (pitch === undefined) return; // don't include elements like spacers in beams
@@ -62,6 +71,21 @@ var BeamElem = function BeamElem(stemHeight, type, flat, firstElement) {
62
71
  this.beams.push(beam);
63
72
  };
64
73
 
74
+ BeamElem.prototype.setStemDirection = function() {
75
+ // Have to figure this out before the notes are placed because placing the notes also places the decorations.
76
+ this.average = calcAverage(this.total, this.count);
77
+ if (this.forceup) {
78
+ this.stemsUp = true;
79
+ } else if (this.forcedown) {
80
+ this.stemsUp = false;
81
+ } else {
82
+ var middleLine = 6; // hardcoded 6 is B
83
+ this.stemsUp = this.average < middleLine; // true is up, false is down;
84
+ }
85
+ delete this.count;
86
+ this.total = 0;
87
+ };
88
+
65
89
  BeamElem.prototype.calcDir = function() {
66
90
  this.average = calcAverage(this.total, this.elems.length);
67
91
  if (this.forceup) {
@@ -2,6 +2,7 @@
2
2
 
3
3
  var DynamicDecoration = require('./abc_dynamic_decoration');
4
4
  var CrescendoElem = require('./abc_crescendo_element');
5
+ var GlissandoElem = require('./abc_glissando_element');
5
6
  var glyphs = require('./abc_glyphs');
6
7
  var RelativeElement = require('./abc_relative_element');
7
8
  var TieElem = require('./abc_tie_element');
@@ -277,6 +278,7 @@ var Decoration = function Decoration() {
277
278
  Decoration.prototype.dynamicDecoration = function(voice, decoration, abselem, positioning) {
278
279
  var diminuendo;
279
280
  var crescendo;
281
+ var glissando;
280
282
  for (var i=0;i<decoration.length; i++) {
281
283
  switch(decoration[i]) {
282
284
  case "diminuendo(":
@@ -295,6 +297,14 @@ var Decoration = function Decoration() {
295
297
  crescendo = { start: this.startCrescendoX, stop: abselem};
296
298
  this.startCrescendoX = undefined;
297
299
  break;
300
+ case "glissando(":
301
+ this.startGlissandoX = abselem;
302
+ glissando = undefined;
303
+ break;
304
+ case "glissando)":
305
+ glissando = { start: this.startGlissandoX, stop: abselem};
306
+ this.startGlissandoX = undefined;
307
+ break;
298
308
  }
299
309
  }
300
310
  if (diminuendo) {
@@ -303,6 +313,9 @@ var Decoration = function Decoration() {
303
313
  if (crescendo) {
304
314
  voice.addOther(new CrescendoElem(crescendo.start, crescendo.stop, "<", positioning));
305
315
  }
316
+ if (glissando) {
317
+ voice.addOther(new GlissandoElem(glissando.start, glissando.stop));
318
+ }
306
319
  };
307
320
 
308
321
  Decoration.prototype.createDecoration = function(voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch, positioning, hasVocals) {
@@ -0,0 +1,7 @@
1
+ var GlissandoElem = function GlissandoElem(anchor1, anchor2) {
2
+ this.type = "GlissandoElem";
3
+ this.anchor1 = anchor1; // must have a .x and a .parent property or be null (means starts at the "beginning" of the line - after keysig)
4
+ this.anchor2 = anchor2; // must have a .x property or be null (means ends at the end of the line)
5
+ };
6
+
7
+ module.exports = GlissandoElem;
@@ -0,0 +1,75 @@
1
+ var sprintf = require('./sprintf');
2
+ var printPath = require('./print-path');
3
+ var roundNumber = require("./round-number");
4
+
5
+ function drawGlissando(renderer, params, selectables) {
6
+ if (!params.anchor1 || !params.anchor2 || !params.anchor1.heads || !params.anchor2.heads || params.anchor1.heads.length === 0 || params.anchor2.heads.length === 0)
7
+ window.console.error("Glissando Element not set.");
8
+
9
+ var margin = 4;
10
+ var leftY = renderer.calcY(params.anchor1.heads[0].pitch)
11
+ var rightY = renderer.calcY(params.anchor2.heads[0].pitch)
12
+ var leftX = params.anchor1.x + params.anchor1.w/2
13
+ var rightX = params.anchor2.x + params.anchor2.w/2
14
+ var len = lineLength(leftX, leftY, rightX, rightY)
15
+ var marginLeft = params.anchor1.w/2 + margin
16
+ var marginRight = params.anchor2.w/2 + margin
17
+ var s = slope(leftX, leftY, rightX, rightY)
18
+ var leftYAdj = getY(leftY, s, marginLeft)
19
+ var rightYAdj = getY(rightY, s, -marginRight)
20
+ var num = numSquigglies(len-marginLeft-marginRight)
21
+
22
+ var el = drawSquiggly(renderer, leftX+marginLeft, leftYAdj, num, s)
23
+ selectables.wrapSvgEl({el_type: "glissando", startChar: -1, endChar: -1}, el);
24
+ return [el];
25
+ }
26
+
27
+ function lineLength(leftX, leftY, rightX, rightY) {
28
+ // The length from notehead center to notehead center.
29
+ var w = rightX - leftX
30
+ var h = rightY - leftY
31
+ return Math.sqrt(w*w + h*h)
32
+ }
33
+
34
+ function slope(leftX, leftY, rightX, rightY) {
35
+ return (rightY-leftY) / (rightX - leftX)
36
+ }
37
+
38
+ function getY(y, slope, xOfs) {
39
+ return roundNumber(y + (xOfs)*slope);
40
+ }
41
+
42
+ function numSquigglies(length) {
43
+ var endLen = 5; // The width of the end - that is, the non repeating part
44
+ return Math.max(2, Math.floor((length - endLen*2) / 6));
45
+ }
46
+
47
+ var leftStart = [[3.5, -4.8]]
48
+ var right = [[1.5, -1], [.3, -.3], [-3.5, 3.8]]
49
+ var leftEnd = [[-1.5, 2]]
50
+ var top = [[3, 4], [3, -4]]
51
+ var bottom = [[-3, 4], [-3, -4]]
52
+
53
+ function segment(arr, slope) {
54
+ var ret = "";
55
+ for (var i = 0; i < arr.length; i++) {
56
+ ret += 'l' + arr[i][0] + ' ' + getY(arr[i][1], slope, arr[i][0])
57
+ }
58
+ return ret
59
+ }
60
+
61
+ var drawSquiggly = function(renderer, x, y, num, slope) {
62
+ var p = sprintf("M %f %f", x, y);
63
+ p += segment(leftStart, slope)
64
+ var i
65
+ for (i = 0; i < num; i++) {
66
+ p+=segment(top, slope)
67
+ }
68
+ p += segment(right, slope)
69
+ for ( i = 0; i < num; i++)
70
+ p+=segment(bottom, slope)
71
+ p+=segment(leftEnd, slope) + 'z'
72
+ return printPath(renderer, {path:p, highlight: "stroke", stroke:renderer.foregroundColor, 'class': renderer.controller.classes.generate('decoration'), "data-name": "glissando"});
73
+ }
74
+
75
+ module.exports = drawGlissando;
@@ -1,3 +1,4 @@
1
+ var drawGlissando = require('./glissando');
1
2
  var drawCrescendo = require('./crescendo');
2
3
  var drawDynamics = require('./dynamics');
3
4
  var drawTriplet = require('./triplet');
@@ -67,6 +68,9 @@ function drawVoice(renderer, params, bartop, selectables, staffPos) {
67
68
  renderer.controller.classes.incrMeasure();
68
69
  } else {
69
70
  switch (child.type) {
71
+ case "GlissandoElem":
72
+ child.elemset = drawGlissando(renderer, child, selectables);
73
+ break;
70
74
  case "CrescendoElem":
71
75
  child.elemset = drawCrescendo(renderer, child, selectables);
72
76
  break;
@@ -32,7 +32,7 @@ function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, padd
32
32
  this.rows.push({move: spacing.composer});
33
33
  if (metaText.rhythm && metaText.rhythm.length > 0) {
34
34
  var noMove = !!(metaText.composer || metaText.origin);
35
- addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.rhythm, font: 'infofont', klass: 'meta-top rhythm', absElemType: "rhythm", noMove: true, info: metaTextInfo.rhythm, name: "rhythm"}, getTextSize);
35
+ addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.rhythm, font: 'infofont', klass: 'meta-top rhythm', absElemType: "rhythm", noMove: noMove, info: metaTextInfo.rhythm, name: "rhythm"}, getTextSize);
36
36
  }
37
37
  var composerLine = "";
38
38
  if (metaText.composer) composerLine += metaText.composer;
package/types/index.d.ts CHANGED
@@ -64,7 +64,7 @@ declare module 'abcjs' {
64
64
  export type Decorations = "trill" | "lowermordent" | "uppermordent" | "mordent" | "pralltriller" | "accent" |
65
65
  "fermata" | "invertedfermata" | "tenuto" | "0" | "1" | "2" | "3" | "4" | "5" | "+" | "wedge" |
66
66
  "open" | "thumb" | "snap" | "turn" | "roll" | "irishroll" | "breath" | "shortphrase" | "mediumphrase" | "longphrase" |
67
- "segno" | "coda" | "D.S." | "D.C." | "fine" | "crescendo(" | "crescendo)" | "diminuendo(" | "diminuendo)" |
67
+ "segno" | "coda" | "D.S." | "D.C." | "fine" | "crescendo(" | "crescendo)" | "diminuendo(" | "diminuendo)" |"glissando(" | "glissando)" |
68
68
  "p" | "pp" | "f" | "ff" | "mf" | "mp" | "ppp" | "pppp" | "fff" | "ffff" | "sfz" | "repeatbar" | "repeatbar2" | "slide" |
69
69
  "upbow" | "downbow" | "staccato" | "trem1" | "trem2" | "trem3" | "trem4" |
70
70
  "/" | "//" | "///" | "////" | "turnx" | "invertedturn" | "invertedturnx" | "arpeggio" | "trill(" | "trill)" | "xstem" |
@@ -73,13 +73,13 @@ declare module 'abcjs' {
73
73
  //
74
74
  // Basic types
75
75
  //
76
- export type Selector = String | HTMLElement
76
+ export type Selector = string | HTMLElement
77
77
 
78
78
  type NumberFunction = () => number;
79
79
 
80
80
  export interface MeterFraction {
81
- num: string;
82
- den?: string;
81
+ num: number;
82
+ den?: number;
83
83
  }
84
84
 
85
85
  export interface ClefProperties {
@@ -261,6 +261,8 @@ declare module 'abcjs' {
261
261
  instrument: number;
262
262
  start: number;
263
263
  end: number;
264
+ startChar: number;
265
+ endChar: number;
264
266
  volume: number;
265
267
  style?: string;
266
268
  cents?: number;
@@ -904,7 +906,7 @@ declare module 'abcjs' {
904
906
 
905
907
  export interface AudioTrack {
906
908
  cmd: AudioTrackCommand;
907
- [param: any]; // TODO - make this a union
909
+ [param: string]: any; // TODO - make this a union
908
910
  }
909
911
 
910
912
  export interface AudioTracks {
@@ -1042,7 +1044,7 @@ declare module 'abcjs' {
1042
1044
 
1043
1045
  export interface SynthObjectController {
1044
1046
  disable(isDisabled: boolean): void
1045
- setTune(visualObj: TuneObject, userAction: Boolean, audioParams?: AbcVisualParams): Promise<SynthInitResponse>
1047
+ setTune(visualObj: TuneObject, userAction: boolean, audioParams?: any): Promise<SynthInitResponse>
1046
1048
  load(selector: string, cursorControl?: any, visualOptions?: SynthVisualOptions): void
1047
1049
  play(): void
1048
1050
  pause(): void
@@ -1054,7 +1056,9 @@ declare module 'abcjs' {
1054
1056
  }
1055
1057
 
1056
1058
  export interface SynthSequenceClass {
1057
- // TODO
1059
+ addTrack(): AudioTrack
1060
+ setInstrument(trackNumber: number, instrumentNumber: number): void
1061
+ appendNote(trackNumber: number, pitch: number, durationInMeasures: number, volume: number, cents: number): void
1058
1062
  }
1059
1063
 
1060
1064
  export namespace synth {
@@ -1068,7 +1072,7 @@ declare module 'abcjs' {
1068
1072
  export function registerAudioContext(ac?: AudioContext): boolean
1069
1073
  export function activeAudioContext(): AudioContext
1070
1074
  export function CreateSynthControl(element: Selector, options: AbcVisualParams): AudioControl
1071
- export function getMidiFile(source: String | TuneObject, options?: MidiFileOptions): MidiFile;
1075
+ export function getMidiFile(source: string | TuneObject, options?: MidiFileOptions): MidiFile;
1072
1076
  export function playEvent(pitches: MidiPitches, graceNotes: MidiGracePitches, milliSecondsPerMeasure: number): Promise<void>;
1073
1077
  export function sequence(visualObj: TuneObject, options: AbcVisualParams): AudioSequence
1074
1078
  }
package/version.js CHANGED
@@ -1,3 +1,3 @@
1
- var version = '6.0.3';
1
+ var version = '6.0.4';
2
2
 
3
3
  module.exports = version;
package/temp.txt DELETED
@@ -1,16 +0,0 @@
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
-