abcjs 6.1.9 → 6.2.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/RELEASE.md +42 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +4318 -4411
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/index.js +1 -1
- package/package.json +1 -1
- package/plugin.js +1 -1
- package/src/api/abc_timing_callbacks.js +7 -3
- package/src/api/abc_tunebook_svg.js +1 -2
- package/src/data/abc_tune.js +2 -2
- package/src/parse/abc_common.js +0 -47
- package/src/parse/abc_parse.js +16 -16
- package/src/parse/abc_parse_book.js +3 -3
- package/src/parse/abc_parse_directive.js +26 -7
- package/src/parse/abc_parse_header.js +11 -9
- package/src/parse/abc_parse_key_voice.js +17 -17
- package/src/parse/abc_parse_music.js +88 -105
- package/src/parse/abc_tokenizer.js +60 -60
- package/src/parse/tune-builder.js +19 -14
- package/src/synth/abc_midi_flattener.js +25 -9
- package/src/synth/create-synth.js +41 -0
- package/src/synth/note-to-midi.js +50 -0
- package/src/tablatures/instruments/guitar/tab-guitar.js +0 -2
- package/src/tablatures/instruments/string-patterns.js +46 -28
- package/src/tablatures/instruments/tab-note.js +26 -103
- package/src/tablatures/instruments/violin/tab-violin.js +0 -2
- package/src/tablatures/tab-absolute-elements.js +9 -31
- package/src/tablatures/tab-renderer.js +2 -2
- package/src/test/abc_parser_lint.js +7 -4
- package/src/write/README.md +31 -0
- package/src/write/creation/abstract-engraver.js +1036 -0
- package/src/write/creation/add-chord.js +102 -0
- package/src/write/{add-text-if.js → creation/add-text-if.js} +6 -6
- package/src/write/{calcHeight.js → creation/calc-height.js} +2 -2
- package/src/write/creation/create-clef.js +72 -0
- package/src/write/creation/create-key-signature.js +31 -0
- package/src/write/creation/create-note-head.js +107 -0
- package/src/write/creation/create-time-signature.js +55 -0
- package/src/write/creation/decoration.js +357 -0
- package/src/write/{abc_absolute_element.js → creation/elements/absolute-element.js} +14 -15
- package/src/write/creation/elements/beam-element.js +113 -0
- package/src/write/{bottom-text.js → creation/elements/bottom-text.js} +14 -15
- package/src/write/{abc_brace_element.js → creation/elements/brace-element.js} +5 -5
- package/src/write/creation/elements/free-text.js +41 -0
- package/src/write/{abc_relative_element.js → creation/elements/relative-element.js} +7 -7
- package/src/write/{separator.js → creation/elements/separator.js} +2 -2
- package/src/write/{abc_staff_group_element.js → creation/elements/staff-group-element.js} +4 -4
- package/src/write/{subtitle.js → creation/elements/subtitle.js} +3 -3
- package/src/write/creation/elements/tempo-element.js +63 -0
- package/src/write/{abc_tie_element.js → creation/elements/tie-element.js} +15 -11
- package/src/write/{top-text.js → creation/elements/top-text.js} +12 -12
- package/src/write/creation/elements/triplet-element.js +28 -0
- package/src/write/{abc_voice_element.js → creation/elements/voice-element.js} +3 -3
- package/src/write/creation/glyphs.js +226 -0
- package/src/write/creation/translate-chord.js +37 -0
- package/src/write/draw/absolute.js +5 -5
- package/src/write/draw/beam.js +8 -8
- package/src/write/draw/brace.js +33 -33
- package/src/write/draw/crescendo.js +4 -4
- package/src/write/draw/debug-box.js +1 -1
- package/src/write/draw/draw.js +7 -7
- package/src/write/draw/dynamics.js +2 -2
- package/src/write/draw/ending.js +6 -6
- package/src/write/draw/glissando.js +17 -17
- package/src/write/draw/group-elements.js +51 -51
- package/src/write/draw/horizontal-line.js +9 -9
- package/src/write/draw/non-music.js +1 -1
- package/src/write/draw/print-line.js +15 -16
- package/src/write/draw/print-stem.js +5 -5
- package/src/write/draw/print-symbol.js +12 -12
- package/src/write/draw/print-vertical-line.js +8 -8
- package/src/write/draw/relative.js +17 -16
- package/src/write/draw/selectables.js +5 -5
- package/src/write/draw/separator.js +4 -4
- package/src/write/draw/set-paper-size.js +2 -2
- package/src/write/draw/sprintf.js +31 -31
- package/src/write/draw/staff-group.js +36 -30
- package/src/write/draw/staff-line.js +2 -2
- package/src/write/draw/staff.js +4 -4
- package/src/write/draw/tab-line.js +26 -26
- package/src/write/draw/tempo.js +30 -30
- package/src/write/draw/text.js +5 -5
- package/src/write/draw/tie.js +18 -18
- package/src/write/draw/triplet.js +6 -6
- package/src/write/draw/voice.js +16 -17
- package/src/write/{abc_engraver_controller.js → engraver-controller.js} +58 -51
- package/src/write/{classes.js → helpers/classes.js} +6 -6
- package/src/write/{get-font-and-attr.js → helpers/get-font-and-attr.js} +9 -7
- package/src/write/{get-text-size.js → helpers/get-text-size.js} +5 -5
- package/src/write/{set-class.js → helpers/set-class.js} +1 -1
- package/src/write/{abc_spacing.js → helpers/spacing.js} +1 -1
- package/src/write/{highlight.js → interactive/highlight.js} +1 -1
- package/src/write/{selection.js → interactive/selection.js} +27 -27
- package/src/write/{unhighlight.js → interactive/unhighlight.js} +1 -1
- package/src/write/layout/beam.js +13 -13
- package/src/write/layout/get-left-edge-of-staff.js +4 -4
- package/src/write/layout/layout.js +74 -74
- package/src/write/layout/{setUpperAndLowerElements.js → set-upper-and-lower-elements.js} +8 -8
- package/src/write/layout/{staffGroup.js → staff-group.js} +32 -32
- package/src/write/layout/triplet.js +4 -4
- package/src/write/layout/{VoiceElements.js → voice-elements.js} +23 -23
- package/src/write/layout/voice.js +6 -6
- package/src/write/{abc_renderer.js → renderer.js} +35 -32
- package/src/write/svg.js +35 -35
- package/test.js +1 -1
- package/types/index.d.ts +36 -7
- package/version.js +1 -1
- package/src/tablatures/instruments/guitar/guitar-fonts.js +0 -19
- package/src/tablatures/instruments/violin/violin-fonts.js +0 -19
- package/src/tablatures/transposer.js +0 -110
- package/src/write/abc_abstract_engraver.js +0 -1026
- package/src/write/abc_beam_element.js +0 -113
- package/src/write/abc_create_clef.js +0 -72
- package/src/write/abc_create_key_signature.js +0 -33
- package/src/write/abc_create_note_head.js +0 -107
- package/src/write/abc_create_time_signature.js +0 -55
- package/src/write/abc_decoration.js +0 -357
- package/src/write/abc_glyphs.js +0 -224
- package/src/write/abc_tempo_element.js +0 -63
- package/src/write/abc_triplet_element.js +0 -28
- package/src/write/add-chord.js +0 -103
- package/src/write/format-jazz-chord.js +0 -15
- package/src/write/free-text.js +0 -41
- /package/src/write/{abc_crescendo_element.js → creation/elements/crescendo-element.js} +0 -0
- /package/src/write/{abc_dynamic_decoration.js → creation/elements/dynamic-decoration.js} +0 -0
- /package/src/write/{abc_ending_element.js → creation/elements/ending-element.js} +0 -0
- /package/src/write/{abc_glissando_element.js → creation/elements/glissando-element.js} +0 -0
- /package/src/write/layout/{getBarYAt.js → get-bar-y-at.js} +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var accidentals = {
|
|
2
|
+
"__": -2,
|
|
3
|
+
"_": -1,
|
|
4
|
+
"_/": -0.5,
|
|
5
|
+
"=": 0,
|
|
6
|
+
"": 0,
|
|
7
|
+
"^/": 0.5,
|
|
8
|
+
"^": 1,
|
|
9
|
+
"^^": 2
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var notesInOrder = ['C', '-', 'D', '-', 'E', 'F', '-', 'G', '-', 'A', '-', 'B', 'c', '-', 'd', '-', 'e', 'f', '-', 'g', '-', 'a', '-', 'b']
|
|
13
|
+
|
|
14
|
+
function noteToMidi(note) {
|
|
15
|
+
var reg = note.match(/([_^\/]*)([ABCDEFGabcdefg])(,*)('*)/)
|
|
16
|
+
if (reg && reg.length === 5) {
|
|
17
|
+
var acc = accidentals[reg[1]]
|
|
18
|
+
var pitch = notesInOrder.indexOf(reg[2])
|
|
19
|
+
var octave = reg[4].length - reg[3].length
|
|
20
|
+
return 48 + pitch + acc + octave * 12;
|
|
21
|
+
}
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function midiToNote(midi) {
|
|
26
|
+
midi = parseInt(midi, 10) // TODO-PER: not sure how to handle quarter sharps and flats, so strip them for now.
|
|
27
|
+
var octave = Math.floor(midi / 12)
|
|
28
|
+
var pitch = midi % 12
|
|
29
|
+
var name = notesInOrder[pitch]
|
|
30
|
+
if (name === '-') {
|
|
31
|
+
name = '^' + notesInOrder[pitch-1]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (octave > 4) {
|
|
35
|
+
name = name.toLowerCase()
|
|
36
|
+
octave -= 5
|
|
37
|
+
while (octave > 0) {
|
|
38
|
+
name += "'"
|
|
39
|
+
octave--
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
while (octave < 4) {
|
|
43
|
+
name += ','
|
|
44
|
+
octave++
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return name
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = {noteToMidi: noteToMidi, midiToNote: midiToNote};
|
|
@@ -5,7 +5,6 @@ var StringTablature = require('../string-tablature');
|
|
|
5
5
|
var TabCommon = require('../../tab-common');
|
|
6
6
|
var TabRenderer = require('../../tab-renderer');
|
|
7
7
|
var GuitarPatterns = require('./guitar-patterns');
|
|
8
|
-
var setGuitarFonts = require('./guitar-fonts');
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* upon init mainly store provided instances for later usage
|
|
@@ -32,7 +31,6 @@ Plugin.prototype.init = function (abcTune, tuneNumber, params) {
|
|
|
32
31
|
Plugin.prototype.render = function (renderer, line, staffIndex) {
|
|
33
32
|
if (this._super.inError) return;
|
|
34
33
|
if (this.tablature.bypass(line)) return;
|
|
35
|
-
setGuitarFonts(this.abcTune);
|
|
36
34
|
var rndrer = new TabRenderer(this, renderer, line, staffIndex);
|
|
37
35
|
rndrer.doLayout();
|
|
38
36
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const {noteToMidi} = require('../../synth/note-to-midi');
|
|
1
2
|
var TabNote = require('./tab-note');
|
|
2
3
|
var TabNotes = require('./tab-notes');
|
|
3
4
|
|
|
@@ -93,7 +94,10 @@ function sameString(self, chord) {
|
|
|
93
94
|
function handleChordNotes(self, notes) {
|
|
94
95
|
var retNotes = [];
|
|
95
96
|
for (var iiii = 0; iiii < notes.length; iiii++) {
|
|
96
|
-
|
|
97
|
+
if (notes[iiii].endTie)
|
|
98
|
+
continue;
|
|
99
|
+
var note = new TabNote.TabNote(notes[iiii].name, self.clefTranspose);
|
|
100
|
+
note.checkKeyAccidentals(self.accidentals, self.measureAccidentals)
|
|
97
101
|
var curPos = toNumber(self, note);
|
|
98
102
|
retNotes.push(curPos);
|
|
99
103
|
}
|
|
@@ -147,26 +151,23 @@ function toNumber(self, note) {
|
|
|
147
151
|
acc = "="
|
|
148
152
|
self.measureAccidentals[note.name.toUpperCase()] = acc
|
|
149
153
|
}
|
|
150
|
-
var
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
while (str < self.strings.length) {
|
|
163
|
-
num = noteToNumber(self, note, str);
|
|
164
|
-
if (num) {
|
|
165
|
-
return num;
|
|
154
|
+
for (var i = self.stringPitches.length-1; i >= 0; i--) {
|
|
155
|
+
if (note.pitch + note.pitchAltered >= self.stringPitches[i]) {
|
|
156
|
+
var num = note.pitch + note.pitchAltered - self.stringPitches[i]
|
|
157
|
+
if (note.quarter === '^') num -= 0.5
|
|
158
|
+
else if (note.quarter === "v") num += 0.5
|
|
159
|
+
return {
|
|
160
|
+
num: Math.round(num),
|
|
161
|
+
str: self.stringPitches.length-1-i, // reverse the strings because string 0 is on the bottom
|
|
162
|
+
note: note
|
|
163
|
+
}
|
|
166
164
|
}
|
|
167
|
-
str++;
|
|
168
165
|
}
|
|
169
|
-
return
|
|
166
|
+
return {
|
|
167
|
+
num: "?",
|
|
168
|
+
str: self.stringPitches.length-1,
|
|
169
|
+
note: note,
|
|
170
|
+
};
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
StringPatterns.prototype.stringToPitch = function (stringNumber) {
|
|
@@ -198,13 +199,16 @@ StringPatterns.prototype.notesToNumber = function (notes, graces) {
|
|
|
198
199
|
error = retNotes.error;
|
|
199
200
|
}
|
|
200
201
|
} else {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
if (!notes[0].endTie) {
|
|
203
|
+
note = new TabNote.TabNote(notes[0].name, this.clefTranspose);
|
|
204
|
+
note.checkKeyAccidentals(this.accidentals, this.measureAccidentals)
|
|
205
|
+
number = toNumber(this, note);
|
|
206
|
+
if (number) {
|
|
207
|
+
retNotes.push(number);
|
|
208
|
+
} else {
|
|
209
|
+
invalidNumber(retNotes, note);
|
|
210
|
+
error = retNotes.error;
|
|
211
|
+
}
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
}
|
|
@@ -213,7 +217,8 @@ StringPatterns.prototype.notesToNumber = function (notes, graces) {
|
|
|
213
217
|
if (graces) {
|
|
214
218
|
retGraces = [];
|
|
215
219
|
for (var iiii = 0; iiii < graces.length; iiii++) {
|
|
216
|
-
note = new TabNote.TabNote(graces[iiii].name);
|
|
220
|
+
note = new TabNote.TabNote(graces[iiii].name, this.clefTranspose);
|
|
221
|
+
note.checkKeyAccidentals(this.accidentals, this.measureAccidentals)
|
|
217
222
|
number = toNumber(this, note);
|
|
218
223
|
if (number) {
|
|
219
224
|
retGraces.push(number);
|
|
@@ -232,7 +237,14 @@ StringPatterns.prototype.notesToNumber = function (notes, graces) {
|
|
|
232
237
|
};
|
|
233
238
|
|
|
234
239
|
StringPatterns.prototype.toString = function () {
|
|
235
|
-
|
|
240
|
+
var arr = []
|
|
241
|
+
for (var i = 0; i < this.tuning.length; i++) {
|
|
242
|
+
var str = this.tuning[i].replaceAll(',', '').replaceAll("'", '').toUpperCase();
|
|
243
|
+
if (str[0] === '_') str = str[1] + 'b '
|
|
244
|
+
else if (str[0] === '^') str = str[1] + "# "
|
|
245
|
+
arr.push(str)
|
|
246
|
+
}
|
|
247
|
+
return arr.join('');
|
|
236
248
|
};
|
|
237
249
|
|
|
238
250
|
StringPatterns.prototype.tabInfos = function (plugin) {
|
|
@@ -275,7 +287,13 @@ function StringPatterns(plugin) {
|
|
|
275
287
|
if (capo) {
|
|
276
288
|
this.capo = capo;
|
|
277
289
|
}
|
|
290
|
+
this.transpose = plugin.transpose ? plugin.transpose : 0
|
|
278
291
|
this.tuning = tuning;
|
|
292
|
+
this.stringPitches = []
|
|
293
|
+
for (var i = 0; i < this.tuning.length; i++) {
|
|
294
|
+
var pitch = noteToMidi(this.tuning[i]) + this.capo
|
|
295
|
+
this.stringPitches.push(pitch)
|
|
296
|
+
}
|
|
279
297
|
if (this.capo > 0) {
|
|
280
298
|
this.capoTuning = buildCapo(this);
|
|
281
299
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var {noteToMidi, midiToNote} = require('../../synth/note-to-midi');
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
*
|
|
3
5
|
* Note structure for Tabs
|
|
@@ -6,9 +8,12 @@
|
|
|
6
8
|
var notes = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
|
|
7
9
|
|
|
8
10
|
|
|
9
|
-
function TabNote(note) {
|
|
11
|
+
function TabNote(note, clefTranspose) {
|
|
12
|
+
var pitch = noteToMidi(note)
|
|
13
|
+
if (clefTranspose)
|
|
14
|
+
pitch += clefTranspose
|
|
15
|
+
var newNote = midiToNote(pitch);
|
|
10
16
|
var isFlat = false;
|
|
11
|
-
var newNote = note;
|
|
12
17
|
var isSharp = false;
|
|
13
18
|
var isAltered = false;
|
|
14
19
|
var natural = null;
|
|
@@ -54,9 +59,11 @@ function TabNote(note) {
|
|
|
54
59
|
newNote = note.slice(1);
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
|
-
var hasComma = (
|
|
58
|
-
var hasQuote = (
|
|
62
|
+
var hasComma = (newNote.match(/,/g) || []).length;
|
|
63
|
+
var hasQuote = (newNote.match(/'/g) || []).length;
|
|
59
64
|
|
|
65
|
+
this.pitch = pitch
|
|
66
|
+
this.pitchAltered = 0
|
|
60
67
|
this.name = newNote;
|
|
61
68
|
this.acc = acc;
|
|
62
69
|
this.isSharp = isSharp;
|
|
@@ -76,6 +83,7 @@ function TabNote(note) {
|
|
|
76
83
|
function cloneNote(self) {
|
|
77
84
|
var newNote = self.name;
|
|
78
85
|
var newTabNote = new TabNote(newNote);
|
|
86
|
+
newTabNote.pitch = self.pitch;
|
|
79
87
|
newTabNote.hasComma = self.hasComma;
|
|
80
88
|
newTabNote.isLower = self.isLower;
|
|
81
89
|
newTabNote.isQuoted = self.isQuoted;
|
|
@@ -86,33 +94,11 @@ function cloneNote(self) {
|
|
|
86
94
|
return newTabNote;
|
|
87
95
|
}
|
|
88
96
|
TabNote.prototype.sameNoteAs = function (note) {
|
|
89
|
-
|
|
90
|
-
(this.hasComma == note.hasComma) &&
|
|
91
|
-
(this.isLower == note.isLower) &&
|
|
92
|
-
(this.isQuoted == note.isQuoted) &&
|
|
93
|
-
(this.isSharp == note.isSharp) &&
|
|
94
|
-
(this.isFlat == note.isFlat)) {
|
|
95
|
-
return true;
|
|
96
|
-
} else {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
97
|
+
return note.pitch === this.pitch
|
|
99
98
|
};
|
|
100
99
|
|
|
101
100
|
TabNote.prototype.isLowerThan = function (note) {
|
|
102
|
-
|
|
103
|
-
if (this.hasComma > note.hasComma) return true;
|
|
104
|
-
if (note.hasComma > this.hasComma) return false;
|
|
105
|
-
if (this.isQuoted > note.isQuoted) return false;
|
|
106
|
-
if (note.isQuoted > this.isQuoted) return true;
|
|
107
|
-
if (this.isLower) {
|
|
108
|
-
if (!note.isLower) return false;
|
|
109
|
-
} else {
|
|
110
|
-
if (note.isLower) return true;
|
|
111
|
-
}
|
|
112
|
-
var noteName = note.name[0].toUpperCase();
|
|
113
|
-
var thisName = this.name[0].toUpperCase();
|
|
114
|
-
if (noteComparator.indexOf(thisName) < noteComparator.indexOf(noteName)) return true;
|
|
115
|
-
return false;
|
|
101
|
+
return note.pitch > this.pitch
|
|
116
102
|
};
|
|
117
103
|
|
|
118
104
|
TabNote.prototype.checkKeyAccidentals = function(accidentals, measureAccidentals) {
|
|
@@ -120,14 +106,13 @@ TabNote.prototype.checkKeyAccidentals = function(accidentals, measureAccidentals
|
|
|
120
106
|
return
|
|
121
107
|
if (measureAccidentals[this.name.toUpperCase()]) {
|
|
122
108
|
switch (measureAccidentals[this.name.toUpperCase()]) {
|
|
123
|
-
case "__": this.acc = -2; return;
|
|
124
|
-
case "_": this.acc = -1; return;
|
|
125
|
-
case "=": this.acc = 0; return;
|
|
126
|
-
case "^": this.acc = 1; return;
|
|
127
|
-
case "^^": this.acc = 2; return;
|
|
109
|
+
case "__": this.acc = -2; this.pitchAltered = -2; return;
|
|
110
|
+
case "_": this.acc = -1; this.pitchAltered = -1; return;
|
|
111
|
+
case "=": this.acc = 0; this.pitchAltered = 0; return;
|
|
112
|
+
case "^": this.acc = 1; this.pitchAltered = 1; return;
|
|
113
|
+
case "^^": this.acc = 2; this.pitchAltered = 2; return;
|
|
128
114
|
}
|
|
129
|
-
}
|
|
130
|
-
if (accidentals) {
|
|
115
|
+
} else if (accidentals) {
|
|
131
116
|
var curNote = this.name;
|
|
132
117
|
for (var iii = 0; iii < accidentals.length; iii++) {
|
|
133
118
|
var curAccidentals = accidentals[iii];
|
|
@@ -135,10 +120,12 @@ TabNote.prototype.checkKeyAccidentals = function(accidentals, measureAccidentals
|
|
|
135
120
|
if (curAccidentals.acc == 'flat') {
|
|
136
121
|
this.acc = -1;
|
|
137
122
|
this.isKeyFlat = true;
|
|
123
|
+
this.pitchAltered = -1
|
|
138
124
|
}
|
|
139
125
|
if (curAccidentals.acc == 'sharp') {
|
|
140
126
|
this.acc = +1;
|
|
141
127
|
this.isKeySharp = true;
|
|
128
|
+
this.pitchAltered = 1
|
|
142
129
|
}
|
|
143
130
|
}
|
|
144
131
|
}
|
|
@@ -163,77 +150,13 @@ TabNote.prototype.getAccidentalEquiv = function () {
|
|
|
163
150
|
|
|
164
151
|
|
|
165
152
|
TabNote.prototype.nextNote = function () {
|
|
166
|
-
var
|
|
167
|
-
|
|
168
|
-
if (!this.isSharp && !this.isKeySharp ) {
|
|
169
|
-
if (this.name != 'E' && this.name != 'B') {
|
|
170
|
-
newTabNote.isSharp = true;
|
|
171
|
-
return newTabNote;
|
|
172
|
-
}
|
|
173
|
-
} else {
|
|
174
|
-
// cleanup
|
|
175
|
-
newTabNote.isSharp = false;
|
|
176
|
-
newTabNote.isKeySharp = false;
|
|
177
|
-
}
|
|
178
|
-
var noteIndex = notes.indexOf(this.name);
|
|
179
|
-
if (noteIndex == notes.length - 1) {
|
|
180
|
-
noteIndex = 0;
|
|
181
|
-
} else {
|
|
182
|
-
noteIndex++;
|
|
183
|
-
}
|
|
184
|
-
newTabNote.name = notes[noteIndex];
|
|
185
|
-
if (newTabNote.name == 'C') {
|
|
186
|
-
if (newTabNote.hasComma > 0) {
|
|
187
|
-
newTabNote.hasComma--;
|
|
188
|
-
} else {
|
|
189
|
-
if (!newTabNote.isLower) {
|
|
190
|
-
newTabNote.isLower = true;
|
|
191
|
-
} else {
|
|
192
|
-
newTabNote.isQuoted = true;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return newTabNote;
|
|
153
|
+
var note = midiToNote(this.pitch+1+this.pitchAltered)
|
|
154
|
+
return new TabNote(note)
|
|
197
155
|
};
|
|
198
156
|
|
|
199
157
|
TabNote.prototype.prevNote = function () {
|
|
200
|
-
var
|
|
201
|
-
|
|
202
|
-
if (this.isSharp) {
|
|
203
|
-
newTabNote.isSharp = false;
|
|
204
|
-
return newTabNote;
|
|
205
|
-
}
|
|
206
|
-
var noteIndex = notes.indexOf(this.name);
|
|
207
|
-
if (noteIndex == 0) {
|
|
208
|
-
noteIndex = notes.length - 1;
|
|
209
|
-
} else {
|
|
210
|
-
noteIndex--;
|
|
211
|
-
}
|
|
212
|
-
newTabNote.name = notes[noteIndex];
|
|
213
|
-
if (newTabNote.name == 'B') {
|
|
214
|
-
if (newTabNote.isLower) {
|
|
215
|
-
newTabNote.hasComma = 1;
|
|
216
|
-
} else {
|
|
217
|
-
if (newTabNote.hasComma > 0) {
|
|
218
|
-
newTabNote.hasComma++;
|
|
219
|
-
} else {
|
|
220
|
-
if (newTabNote.isQuoted > 0) {
|
|
221
|
-
newTabNote.isQuoted -= 1;
|
|
222
|
-
} else {
|
|
223
|
-
newTabNote.isLower = true;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
if (this.isFlat) {
|
|
229
|
-
newTabNote.isFlat = false;
|
|
230
|
-
return newTabNote;
|
|
231
|
-
} else {
|
|
232
|
-
if (this.name != 'E' && this.name != 'B') {
|
|
233
|
-
newTabNote.isSharp = true;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return newTabNote;
|
|
158
|
+
var note = midiToNote(this.pitch-1+this.pitchAltered)
|
|
159
|
+
return new TabNote(note)
|
|
237
160
|
};
|
|
238
161
|
|
|
239
162
|
TabNote.prototype.emitNoAccidentals = function ( ) {
|
|
@@ -3,7 +3,6 @@ var StringTablature = require('../string-tablature');
|
|
|
3
3
|
var TabCommon = require('../../tab-common');
|
|
4
4
|
var TabRenderer = require('../../tab-renderer');
|
|
5
5
|
var ViolinPatterns = require('./violin-patterns');
|
|
6
|
-
var setViolinFonts = require('./violin-fonts');
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -30,7 +29,6 @@ Plugin.prototype.init = function (abcTune, tuneNumber, params) {
|
|
|
30
29
|
Plugin.prototype.render = function (renderer, line, staffIndex) {
|
|
31
30
|
if (this._super.inError) return;
|
|
32
31
|
if (this.tablature.bypass(line)) return;
|
|
33
|
-
setViolinFonts(this.abcTune);
|
|
34
32
|
var rndrer = new TabRenderer(this, renderer, line, staffIndex);
|
|
35
33
|
rndrer.doLayout();
|
|
36
34
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tablature Absolute elements factory
|
|
3
3
|
*/
|
|
4
|
-
var AbsoluteElement = require('../write/
|
|
5
|
-
var RelativeElement = require('../write/
|
|
6
|
-
var Transposer = require('./transposer');
|
|
4
|
+
var AbsoluteElement = require('../write/creation/elements/absolute-element');
|
|
5
|
+
var RelativeElement = require('../write/creation/elements/relative-element');
|
|
7
6
|
|
|
8
7
|
function isObject(a) { return a != null && a.constructor === Object; }
|
|
9
8
|
function cloneObject(dest, src) {
|
|
@@ -144,20 +143,6 @@ function graceInRest( absElem ) {
|
|
|
144
143
|
return null;
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
function checkTransposition(plugin, transposer ,pitches, graceNotes) {
|
|
148
|
-
if (plugin.transpose) {
|
|
149
|
-
//transposer.transpose(plugin.transpose);
|
|
150
|
-
for (var jj = 0; jj < pitches.length; jj++) {
|
|
151
|
-
pitches[jj] = transposer.transposeNote(pitches[jj]);
|
|
152
|
-
}
|
|
153
|
-
if (graceNotes) {
|
|
154
|
-
for (var kk = 0; kk < graceNotes.length; kk++) {
|
|
155
|
-
graceNotes[kk] = transposer.transposeNote(graceNotes[kk]);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
146
|
function convertToNumber(plugin, pitches, graceNotes) {
|
|
162
147
|
var tabPos = plugin.semantics.notesToNumber(pitches, graceNotes);
|
|
163
148
|
if (tabPos.error) {
|
|
@@ -196,7 +181,6 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
196
181
|
var staffSize = getInitialStaffSize(staffAbsolute);
|
|
197
182
|
var source = staffAbsolute[staffIndex+voiceIndex];
|
|
198
183
|
var dest = staffAbsolute[staffSize+staffIndex+voiceIndex];
|
|
199
|
-
var transposer = null;
|
|
200
184
|
var tabPos = null;
|
|
201
185
|
var defNote = null;
|
|
202
186
|
if (source.children[0].abcelem.el_type != 'clef') {
|
|
@@ -214,18 +198,14 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
214
198
|
// }
|
|
215
199
|
if ( (absChild.isClef) ) {
|
|
216
200
|
dest.children.push(buildTabAbsolute(plugin, absX, relX));
|
|
201
|
+
if (absChild.abcelem.type.indexOf('-8') >= 0) plugin.semantics.strings.clefTranspose = -12
|
|
202
|
+
if (absChild.abcelem.type.indexOf('+8') >= 0) plugin.semantics.strings.clefTranspose = 12
|
|
217
203
|
}
|
|
218
204
|
switch (absChild.type) {
|
|
219
205
|
case 'staff-extra key-signature':
|
|
220
206
|
// refresh key accidentals
|
|
221
207
|
this.accidentals = absChild.abcelem.accidentals;
|
|
222
208
|
plugin.semantics.strings.accidentals = this.accidentals;
|
|
223
|
-
if (plugin.transpose) {
|
|
224
|
-
transposer = new Transposer(
|
|
225
|
-
absChild.abcelem.accidentals,
|
|
226
|
-
plugin.transpose
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
209
|
break;
|
|
230
210
|
case 'bar':
|
|
231
211
|
plugin.semantics.strings.measureAccidentals = {}
|
|
@@ -258,8 +238,6 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
258
238
|
case 'rest':
|
|
259
239
|
var restGraces = graceInRest(absChild);
|
|
260
240
|
if (restGraces) {
|
|
261
|
-
// check transpose
|
|
262
|
-
checkTransposition(plugin, transposer, null, restGraces);
|
|
263
241
|
// to number conversion
|
|
264
242
|
tabPos = convertToNumber(plugin, null, restGraces);
|
|
265
243
|
if (tabPos.error) return;
|
|
@@ -274,9 +252,7 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
274
252
|
abs.lyricDim = lyricsDim(absChild);
|
|
275
253
|
var pitches = absChild.abcelem.pitches;
|
|
276
254
|
var graceNotes = absChild.abcelem.gracenotes;
|
|
277
|
-
// check transpose
|
|
278
255
|
abs.type = 'tabNumber';
|
|
279
|
-
checkTransposition(plugin, transposer, pitches, graceNotes);
|
|
280
256
|
// to number conversion
|
|
281
257
|
tabPos = convertToNumber(plugin, pitches, graceNotes);
|
|
282
258
|
if (tabPos.error) return;
|
|
@@ -302,9 +278,11 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
302
278
|
var tabNoteRelative = buildRelativeTabNote(plugin, abs.x+absChild.heads[ll].dx, defNote, curNote, false);
|
|
303
279
|
abs.children.push(tabNoteRelative);
|
|
304
280
|
}
|
|
305
|
-
defNote.
|
|
306
|
-
|
|
307
|
-
|
|
281
|
+
if (defNote.notes.length > 0) {
|
|
282
|
+
defNote.abselem = abs;
|
|
283
|
+
tabVoice.push(defNote);
|
|
284
|
+
dest.children.push(abs);
|
|
285
|
+
}
|
|
308
286
|
break;
|
|
309
287
|
}
|
|
310
288
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-debugger */
|
|
2
|
-
var VoiceElement = require('../write/
|
|
2
|
+
var VoiceElement = require('../write/creation/elements/voice-element');
|
|
3
3
|
var TabAbsoluteElements = require('./tab-absolute-elements');
|
|
4
|
-
var spacing = require('../write/
|
|
4
|
+
var spacing = require('../write/helpers/spacing');
|
|
5
5
|
|
|
6
6
|
function initSpecialY() {
|
|
7
7
|
return {
|
|
@@ -318,7 +318,7 @@ var ParserLint = function() {
|
|
|
318
318
|
var midiProperties = {
|
|
319
319
|
cmd: { type: 'string', Enum: [
|
|
320
320
|
"nobarlines", "barlines", "beataccents", "nobeataccents", "droneon", "droneoff", "noportamento", "channel", "c",
|
|
321
|
-
"drumon", "drumoff", "fermatafixed", "fermataproportional", "gchordon", "gchordoff", "bassvol", "chordvol",
|
|
321
|
+
"drumon", "drumoff", "fermatafixed", "fermataproportional", "gchordon", "gchordoff", "bassvol", "chordvol", "bassprog", "chordprog",
|
|
322
322
|
"controlcombo", "temperamentnormal", "gchord", "ptstress", "beatmod", "deltaloudness", "drumbars", "pitchbend",
|
|
323
323
|
"gracedivider", "makechordchannels", "randomchordattack", "chordattack", "stressmodel", "transpose",
|
|
324
324
|
"rtranspose", "volinc", "program", "ratio", "snt", "bendvelocity", "control", "temperamentlinear", "beat", "beatstring",
|
|
@@ -335,6 +335,7 @@ var ParserLint = function() {
|
|
|
335
335
|
field: "el_type",
|
|
336
336
|
types: [
|
|
337
337
|
{ value: "clef", properties: appendPositioning(clefProperties) },
|
|
338
|
+
{ value: "color", properties: { color: {type: "string", optional: true } } },
|
|
338
339
|
{ value: "bar", properties: prependPositioning(barProperties) },
|
|
339
340
|
{ value: "gap", properties: { type: "number", optional: true } }, // staffbreak
|
|
340
341
|
{ value: "key", properties: appendPositioning(keyProperties) },
|
|
@@ -462,9 +463,11 @@ var ParserLint = function() {
|
|
|
462
463
|
infospace: { type: "number", optional: true },
|
|
463
464
|
// landscape: { type: "boolean", optional: true },
|
|
464
465
|
jazzchords: { type: "boolean", optional: true },
|
|
466
|
+
germanAlphabet: { type: "boolean", optional: true },
|
|
465
467
|
leftmargin: { type: "number", optional: true },
|
|
466
468
|
linesep: { type: "number", optional: true },
|
|
467
469
|
lineskipfac: { type: "number", optional: true },
|
|
470
|
+
lineThickness: { type: "number", optional: true },
|
|
468
471
|
map: { type: "string", optional: true },
|
|
469
472
|
maxshrink: { type: "number", optional: true },
|
|
470
473
|
maxstaffsep: { type: "number", optional: true },
|
|
@@ -741,14 +744,14 @@ var ParserLint = function() {
|
|
|
741
744
|
this.lint = function(tune, warnings) {
|
|
742
745
|
var ret = JSONSchema.validate(tune, musicSchema);
|
|
743
746
|
var err = "";
|
|
744
|
-
|
|
747
|
+
ret.errors.forEach(function(e) {
|
|
745
748
|
err += e.property + ": " + e.message + "\n";
|
|
746
749
|
});
|
|
747
750
|
var out = ret.output.join("\n");
|
|
748
751
|
|
|
749
752
|
var warn = warnings === undefined ? "No errors" : warnings.join('\n');
|
|
750
|
-
warn =
|
|
751
|
-
warn =
|
|
753
|
+
warn = warn.replace(/<span style="text-decoration:underline;font-size:1.3em;font-weight:bold;">/g, '$$$$$$$$');
|
|
754
|
+
warn = warn.replace(/<\/span>/g, '$$$$$$$$');
|
|
752
755
|
return "Error:------\n" + err + "\nObj:-------\n" + out + "\nWarn:------\n" + warn;
|
|
753
756
|
};
|
|
754
757
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Architecture of the engraver
|
|
2
|
+
|
|
3
|
+
The engraver code is handled here. This accepts the output of the parser and does three things:
|
|
4
|
+
|
|
5
|
+
* Creates an SVG
|
|
6
|
+
* Adds data to the parser input
|
|
7
|
+
* Makes the visual elements interactive
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
There are separate passes and sub-passes to the processing. The separate passes match the subfolder organization here.
|
|
12
|
+
|
|
13
|
+
They are:
|
|
14
|
+
|
|
15
|
+
### Element Creation
|
|
16
|
+
|
|
17
|
+
The structure passed in from the parser is traversed and all elements are created. An element consists of two parts:
|
|
18
|
+
|
|
19
|
+
* The Absolute Element: a visual piece of music that is always moved together. For instance, in the key signature of D, the absolute element is an object that contains two sharp symbols. The absolute element has an X- and Y- position in the SVG, and an array of Relative Elements.
|
|
20
|
+
|
|
21
|
+
* Relative Element: These are always attached to an absolute element. They have a relative position to the absolute element and consist of all the glyphs needed. For instance, a dotted eighth note of Bb that is trilled is an absolute element that contains an array of relative elements consisting of a trill, a flat sign, a filled note head, a stem, a flag, and a dot.
|
|
22
|
+
|
|
23
|
+
Each of these elements is a separate object, created with `new` and placed in the structure passed in from the parser.
|
|
24
|
+
|
|
25
|
+
### Layout
|
|
26
|
+
|
|
27
|
+
After all the elements are created the size of all of them are known, so the layout process begins. There are separate layout algorithms for the horizontal and the vertical positioning.
|
|
28
|
+
|
|
29
|
+
### Drawing
|
|
30
|
+
|
|
31
|
+
After the layout is finished, it is a rote process to draw the music. All decisions have been made. The structure is then traversed and each element is created in the SVG.
|