abcjs 6.0.0-beta.9 → 6.0.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/.github/workflows/tests.yml +29 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/CONTRIBUTING.md +1 -0
- package/LICENSE.md +1 -1
- package/README.md +88 -7
- package/RELEASE.md +939 -1
- package/abcjs-audio.css +14 -5
- package/dist/.gitignore +1 -2
- package/dist/abcjs-basic-min.js +3 -0
- package/dist/abcjs-basic-min.js.LICENSE +23 -0
- package/dist/abcjs-basic.js +28231 -0
- package/dist/abcjs-basic.js.map +1 -0
- package/dist/abcjs-plugin-min.js +3 -0
- package/dist/abcjs-plugin-min.js.LICENSE +23 -0
- package/dist/report-basic.html +37 -0
- package/dist/report-before-glyph-compress.html +37 -0
- package/dist/report-brown-ts-target-es5.html +37 -0
- package/dist/report-dev-orig-no-babel.html +37 -0
- package/dist/report-synth.html +37 -0
- package/docker-build.sh +1 -0
- package/glyphs.json +1 -0
- package/index.js +27 -2
- package/{static-wrappers/license.js → license.js} +1 -1
- package/package.json +26 -29
- package/{src/plugin/abc_plugin.js → plugin.js} +31 -19
- package/src/api/abc_animation.js +1 -17
- package/src/api/abc_tablatures.js +144 -0
- package/src/api/abc_timing_callbacks.js +216 -117
- package/src/api/abc_tunebook.js +18 -67
- package/src/api/abc_tunebook_svg.js +38 -46
- package/src/data/abc_tune.js +232 -972
- package/src/data/deline-tune.js +199 -0
- package/src/edit/abc_editarea.js +112 -0
- package/src/edit/abc_editor.js +95 -221
- package/src/midi/abc_midi_create.js +48 -50
- package/src/parse/abc_common.js +0 -14
- package/src/parse/abc_parse.js +167 -1321
- package/src/parse/abc_parse_book.js +62 -0
- package/src/parse/abc_parse_directive.js +164 -41
- package/src/parse/abc_parse_header.js +116 -145
- package/src/parse/abc_parse_key_voice.js +26 -20
- package/src/parse/abc_parse_music.js +1337 -0
- package/src/parse/abc_tokenizer.js +21 -15
- package/src/parse/abc_transpose.js +3 -15
- package/src/parse/tune-builder.js +896 -0
- package/src/parse/wrap_lines.js +205 -453
- package/src/synth/abc_midi_flattener.js +1292 -0
- package/src/{midi → synth}/abc_midi_renderer.js +44 -17
- package/src/synth/abc_midi_sequencer.js +648 -0
- package/src/synth/active-audio-context.js +3 -14
- package/src/synth/cents-to-factor.js +10 -0
- package/src/synth/create-note-map.js +21 -32
- package/src/synth/create-synth-control.js +20 -103
- package/src/synth/create-synth.js +185 -77
- package/src/synth/download-buffer.js +7 -21
- package/src/synth/get-midi-file.js +13 -20
- package/src/synth/images/{loading.svg → loading.svg.js} +4 -0
- package/src/synth/images/loop.svg.js +65 -0
- package/src/synth/images/pause.svg.js +10 -0
- package/src/synth/images/play.svg.js +9 -0
- package/src/synth/images/{reset.svg → reset.svg.js} +5 -1
- package/src/synth/instrument-index-to-name.js +1 -16
- package/src/synth/load-note.js +37 -76
- package/src/synth/pitch-to-note-name.js +0 -15
- package/src/synth/pitches-to-perc.js +64 -0
- package/src/synth/place-note.js +78 -68
- package/src/synth/play-event.js +17 -18
- package/src/synth/register-audio-context.js +11 -23
- package/src/synth/sounds-cache.js +0 -15
- package/src/synth/supports-audio.js +9 -23
- package/src/synth/synth-controller.js +80 -49
- package/src/synth/synth-sequence.js +20 -34
- package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
- package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
- package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
- package/src/tablatures/instruments/string-patterns.js +277 -0
- package/src/tablatures/instruments/string-tablature.js +56 -0
- package/src/tablatures/instruments/tab-note.js +282 -0
- package/src/tablatures/instruments/tab-notes.js +41 -0
- package/src/tablatures/instruments/violin/tab-violin.js +47 -0
- package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
- package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
- package/src/tablatures/tab-absolute-elements.js +310 -0
- package/src/tablatures/tab-common.js +29 -0
- package/src/tablatures/tab-renderer.js +243 -0
- package/src/tablatures/transposer.js +110 -0
- package/src/test/abc_midi_lint.js +5 -22
- package/src/test/abc_midi_sequencer_lint.js +11 -14
- package/src/test/abc_parser_lint.js +136 -32
- package/src/test/abc_vertical_lint.js +94 -32
- package/src/test/rendering-lint.js +38 -5
- package/src/write/abc_absolute_element.js +112 -120
- package/src/write/abc_abstract_engraver.js +102 -253
- package/src/write/abc_beam_element.js +30 -290
- package/src/write/abc_brace_element.js +12 -121
- package/src/write/abc_create_clef.js +21 -32
- package/src/write/abc_create_key_signature.js +8 -26
- package/src/write/abc_create_note_head.js +107 -0
- package/src/write/abc_create_time_signature.js +2 -21
- package/src/write/abc_crescendo_element.js +3 -50
- package/src/write/abc_decoration.js +7 -30
- package/src/write/abc_dynamic_decoration.js +3 -37
- package/src/write/abc_ending_element.js +1 -57
- package/src/write/abc_engraver_controller.js +111 -234
- package/src/write/abc_glyphs.js +8 -18
- package/src/write/abc_relative_element.js +57 -97
- package/src/write/abc_renderer.js +10 -832
- package/src/write/abc_spacing.js +0 -15
- package/src/write/abc_staff_group_element.js +14 -349
- package/src/write/abc_tempo_element.js +9 -117
- package/src/write/abc_tie_element.js +5 -68
- package/src/write/abc_triplet_element.js +6 -124
- package/src/write/abc_voice_element.js +7 -222
- package/src/write/add-chord.js +103 -0
- package/src/write/add-text-if.js +33 -0
- package/src/write/bottom-text.js +79 -0
- package/src/write/calcHeight.js +17 -0
- package/src/write/classes.js +100 -0
- package/src/write/draw/absolute.js +68 -0
- package/src/write/draw/beam.js +56 -0
- package/src/write/draw/brace.js +106 -0
- package/src/write/draw/crescendo.js +38 -0
- package/src/write/draw/debug-box.js +8 -0
- package/src/write/draw/draw.js +56 -0
- package/src/write/draw/dynamics.js +20 -0
- package/src/write/draw/ending.js +46 -0
- package/src/write/draw/group-elements.js +66 -0
- package/src/write/draw/horizontal-line.js +25 -0
- package/src/write/draw/non-music.js +50 -0
- package/src/write/draw/print-line.js +24 -0
- package/src/write/draw/print-path.js +7 -0
- package/src/write/draw/print-stem.js +30 -0
- package/src/write/draw/print-symbol.js +59 -0
- package/src/write/draw/print-vertical-line.js +18 -0
- package/src/write/draw/relative.js +77 -0
- package/src/write/draw/round-number.js +5 -0
- package/src/write/draw/selectables.js +59 -0
- package/src/write/draw/separator.js +16 -0
- package/src/write/draw/set-paper-size.js +45 -0
- package/src/write/{sprintf.js → draw/sprintf.js} +0 -0
- package/src/write/draw/staff-group.js +226 -0
- package/src/write/draw/staff-line.js +9 -0
- package/src/write/draw/staff.js +33 -0
- package/src/write/draw/tab-line.js +40 -0
- package/src/write/draw/tempo.js +45 -0
- package/src/write/draw/text.js +71 -0
- package/src/write/draw/tie.js +97 -0
- package/src/write/draw/triplet.js +46 -0
- package/src/write/draw/voice.js +102 -0
- package/src/write/format-jazz-chord.js +15 -0
- package/src/write/free-text.js +41 -0
- package/src/write/get-font-and-attr.js +37 -0
- package/src/write/get-text-size.js +56 -0
- package/src/write/highlight.js +11 -0
- package/src/write/layout/VoiceElements.js +121 -0
- package/src/write/layout/beam.js +213 -0
- package/src/write/layout/get-left-edge-of-staff.js +56 -0
- package/src/write/layout/getBarYAt.js +6 -0
- package/src/write/layout/layout.js +94 -0
- package/src/write/layout/setUpperAndLowerElements.js +232 -0
- package/src/write/layout/staffGroup.js +146 -0
- package/src/write/layout/triplet.js +75 -0
- package/src/write/layout/voice.js +137 -0
- package/src/write/selection.js +188 -70
- package/src/write/separator.js +10 -0
- package/src/write/set-class.js +21 -0
- package/src/write/subtitle.js +12 -0
- package/src/write/svg.js +95 -43
- package/src/write/top-text.js +54 -0
- package/src/write/unhighlight.js +11 -0
- package/temp.txt +17 -0
- package/test.js +27 -64
- package/types/index.d.ts +1095 -0
- package/version.js +1 -1
- package/.babelrc +0 -5
- package/.eslintrc +0 -3
- package/.gitmodules +0 -3
- package/Dockerfile +0 -8
- package/abcjs-midi.css +0 -166
- package/build-utils/loadPresets.js +0 -14
- package/build-utils/presets/webpack.analyze.js +0 -6
- package/build-utils/presets/webpack.optimize.js +0 -30
- package/build-utils/webpack.development.js +0 -14
- package/build-utils/webpack.production.js +0 -35
- package/deploy-docs.sh +0 -25
- package/docker-compose.yml +0 -13
- package/docs/README.md +0 -33
- package/fix-versions.sh +0 -23
- package/midi.js +0 -62
- package/src/api/abc_tunebook_midi.js +0 -116
- package/src/midi/abc_midi_controls.js +0 -701
- package/src/midi/abc_midi_flattener.js +0 -1119
- package/src/midi/abc_midi_js_preparer.js +0 -243
- package/src/midi/abc_midi_sequencer.js +0 -401
- package/src/midi/abc_midi_ui_generator.js +0 -86
- package/src/plugin/abc_plugin_midi.js +0 -220
- package/src/synth/images/loop.svg +0 -61
- package/src/synth/images/pause.svg +0 -6
- package/src/synth/images/play.svg +0 -5
- package/src/transform/abc2abc_write.js +0 -395
- package/static-wrappers/basic.js +0 -2
- package/static-wrappers/midi.js +0 -2
- package/static-wrappers/plugin-midi.js +0 -6
- package/static-wrappers/plugin.js +0 -6
- package/webpack.config.js +0 -29
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
var TabNote = require('./tab-note');
|
|
2
|
+
var TabNotes = require('./tab-notes');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
function buildCapo(self) {
|
|
6
|
+
var capoTuning = null;
|
|
7
|
+
var tuning = self.tuning;
|
|
8
|
+
if (self.capo > 0) {
|
|
9
|
+
capoTuning = [];
|
|
10
|
+
for (var iii = 0; iii < tuning.length; iii++) {
|
|
11
|
+
var curNote = new TabNote.TabNote(tuning[iii]);
|
|
12
|
+
for (var jjj = 0; jjj < self.capo; jjj++) {
|
|
13
|
+
curNote = curNote.nextNote();
|
|
14
|
+
}
|
|
15
|
+
capoTuning[iii] = curNote.emit();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return capoTuning;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function buildPatterns(self) {
|
|
22
|
+
var strings = [];
|
|
23
|
+
var tuning = self.tuning;
|
|
24
|
+
if (self.capo > 0) {
|
|
25
|
+
tuning = self.capoTuning;
|
|
26
|
+
}
|
|
27
|
+
var pos = tuning.length - 1;
|
|
28
|
+
for (var iii = 0; iii < tuning.length; iii++) {
|
|
29
|
+
var nextNote = self.highestNote; // highest handled note
|
|
30
|
+
if (iii != tuning.length - 1) {
|
|
31
|
+
nextNote = tuning[iii + 1];
|
|
32
|
+
}
|
|
33
|
+
var tabNotes = new TabNotes(tuning[iii],nextNote);
|
|
34
|
+
var stringNotes = tabNotes.build();
|
|
35
|
+
if (stringNotes.error) {
|
|
36
|
+
return stringNotes;
|
|
37
|
+
}
|
|
38
|
+
strings[pos--] = stringNotes;
|
|
39
|
+
}
|
|
40
|
+
return strings;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
function buildSecond(first) {
|
|
45
|
+
var seconds = [];
|
|
46
|
+
seconds[0] = [];
|
|
47
|
+
var strings = first.strings;
|
|
48
|
+
for (var iii = 1; iii < strings.length; iii++) {
|
|
49
|
+
seconds[iii] = strings[iii - 1];
|
|
50
|
+
}
|
|
51
|
+
return seconds;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function sameString(self, chord) {
|
|
55
|
+
for (var jjjj = 0; jjjj < chord.length - 1; jjjj++) {
|
|
56
|
+
var curPos = chord[jjjj];
|
|
57
|
+
var nextPos = chord[jjjj + 1];
|
|
58
|
+
if (curPos.str == nextPos.str) {
|
|
59
|
+
// same String
|
|
60
|
+
// => change lower pos
|
|
61
|
+
if (curPos.str == self.strings.length - 1) {
|
|
62
|
+
// Invalid tab Chord position for instrument
|
|
63
|
+
curPos.num = "?";
|
|
64
|
+
nextPos.num = "?";
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// change lower pitch on lowest string
|
|
68
|
+
if (nextPos.num < curPos.num) {
|
|
69
|
+
nextPos.str++;
|
|
70
|
+
nextPos = noteToNumber(self,
|
|
71
|
+
nextPos.note,
|
|
72
|
+
nextPos.str,
|
|
73
|
+
self.secondPos,
|
|
74
|
+
self.strings[nextPos.str].length
|
|
75
|
+
);
|
|
76
|
+
} else {
|
|
77
|
+
curPos.str++;
|
|
78
|
+
curPos = noteToNumber(self,
|
|
79
|
+
curPos.note,
|
|
80
|
+
curPos.str,
|
|
81
|
+
self.secondPos,
|
|
82
|
+
self.strings[curPos.str].length
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
// update table
|
|
86
|
+
chord[jjjj] = curPos;
|
|
87
|
+
chord[jjjj + 1] = nextPos;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleChordNotes(self, notes) {
|
|
94
|
+
var retNotes = [];
|
|
95
|
+
for (var iiii = 0; iiii < notes.length; iiii++) {
|
|
96
|
+
var note = new TabNote.TabNote(notes[iiii].name);
|
|
97
|
+
var curPos = toNumber(self, note);
|
|
98
|
+
retNotes.push(curPos);
|
|
99
|
+
}
|
|
100
|
+
sameString(self, retNotes);
|
|
101
|
+
return retNotes;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function noteToNumber(self, note, stringNumber, secondPosition , firstSize) {
|
|
105
|
+
var strings = self.strings;
|
|
106
|
+
note.checkKeyAccidentals(self.accidentals) ;
|
|
107
|
+
if (secondPosition) {
|
|
108
|
+
strings = secondPosition;
|
|
109
|
+
}
|
|
110
|
+
var noteName = note.emitNoAccidentals();
|
|
111
|
+
var num = strings[stringNumber].indexOf(noteName);
|
|
112
|
+
var acc = note.acc;
|
|
113
|
+
if (num != -1) {
|
|
114
|
+
if (secondPosition) {
|
|
115
|
+
num += firstSize;
|
|
116
|
+
}
|
|
117
|
+
if ( (note.isFlat || note.acc == -1) && (num == 0)) {
|
|
118
|
+
// flat on 0 pos => previous string 7th position
|
|
119
|
+
var noteEquiv = note.getAccidentalEquiv();
|
|
120
|
+
stringNumber++;
|
|
121
|
+
num = strings[stringNumber].indexOf(noteEquiv.emit());
|
|
122
|
+
acc = 0;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
num: (num + acc),
|
|
126
|
+
str: stringNumber,
|
|
127
|
+
note: note
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function toNumber(self, note) {
|
|
134
|
+
var num = null;
|
|
135
|
+
var str = 0;
|
|
136
|
+
var lowestString = self.strings[self.strings.length - 1];
|
|
137
|
+
var lowestNote = new TabNote.TabNote(lowestString[0]);
|
|
138
|
+
if (note.isLowerThan(lowestNote) ) {
|
|
139
|
+
return {
|
|
140
|
+
num: "?",
|
|
141
|
+
str: self.strings.length - 1,
|
|
142
|
+
note: note,
|
|
143
|
+
error: note.emit() + ': unexpected note for instrument'
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
while (str < self.strings.length) {
|
|
147
|
+
num = noteToNumber(self, note, str);
|
|
148
|
+
if (num) {
|
|
149
|
+
return num;
|
|
150
|
+
}
|
|
151
|
+
str++;
|
|
152
|
+
}
|
|
153
|
+
return null; // not found
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
StringPatterns.prototype.stringToPitch = function (stringNumber) {
|
|
157
|
+
var startingPitch = 5.3;
|
|
158
|
+
var bottom = this.strings.length - 1;
|
|
159
|
+
return startingPitch + ((bottom - stringNumber) * this.linePitch);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
function invalidNumber( retNotes , note ) {
|
|
163
|
+
var number = {
|
|
164
|
+
num: "?",
|
|
165
|
+
str: 0,
|
|
166
|
+
note: note
|
|
167
|
+
};
|
|
168
|
+
retNotes.push(number);
|
|
169
|
+
retNotes.error = note.emit() + ': unexpected note for instrument' ;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
StringPatterns.prototype.notesToNumber = function (notes, graces) {
|
|
173
|
+
var note;
|
|
174
|
+
var number;
|
|
175
|
+
var error = null;
|
|
176
|
+
var retNotes = null;
|
|
177
|
+
if (notes) {
|
|
178
|
+
retNotes = [];
|
|
179
|
+
if (notes.length > 1) {
|
|
180
|
+
retNotes = handleChordNotes(this, notes);
|
|
181
|
+
if (retNotes.error) {
|
|
182
|
+
error = retNotes.error;
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
note = new TabNote.TabNote(notes[0].name);
|
|
186
|
+
number = toNumber(this, note);
|
|
187
|
+
if (number) {
|
|
188
|
+
retNotes.push(number);
|
|
189
|
+
} else {
|
|
190
|
+
invalidNumber(retNotes, note);
|
|
191
|
+
error = retNotes.error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (error) return retNotes;
|
|
196
|
+
var retGraces = null;
|
|
197
|
+
if (graces) {
|
|
198
|
+
retGraces = [];
|
|
199
|
+
for (var iiii = 0; iiii < graces.length; iiii++) {
|
|
200
|
+
note = new TabNote.TabNote(graces[iiii].name);
|
|
201
|
+
number = toNumber(this, note);
|
|
202
|
+
if (number) {
|
|
203
|
+
retGraces.push(number);
|
|
204
|
+
} else {
|
|
205
|
+
invalidNumber(retGraces, note);
|
|
206
|
+
error = retNotes.error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
notes: retNotes,
|
|
213
|
+
graces: retGraces,
|
|
214
|
+
error: error
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
StringPatterns.prototype.toString = function () {
|
|
219
|
+
return this.tuning.join('').replaceAll(',', '').toUpperCase();
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
StringPatterns.prototype.tabInfos = function (plugin) {
|
|
223
|
+
var _super = plugin._super;
|
|
224
|
+
var name = _super.params.label;
|
|
225
|
+
if (name) {
|
|
226
|
+
var tunePos = name.indexOf('%T');
|
|
227
|
+
var tuning = "";
|
|
228
|
+
if (tunePos != -1) {
|
|
229
|
+
tuning = this.toString();
|
|
230
|
+
if (plugin.capo > 0) {
|
|
231
|
+
tuning += ' capo:' + plugin.capo;
|
|
232
|
+
}
|
|
233
|
+
name = name.replace('%T', tuning);
|
|
234
|
+
}
|
|
235
|
+
return name;
|
|
236
|
+
}
|
|
237
|
+
return '';
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Common patterns for all string instruments
|
|
242
|
+
* @param {} plugin
|
|
243
|
+
* @param {} tuning
|
|
244
|
+
* @param {*} capo
|
|
245
|
+
* @param {*} highestNote
|
|
246
|
+
*/
|
|
247
|
+
function StringPatterns(plugin) {
|
|
248
|
+
var tuning = plugin.tuning;
|
|
249
|
+
var capo = plugin.capo;
|
|
250
|
+
var highestNote = plugin._super.params.highestNote;
|
|
251
|
+
this.linePitch = plugin.linePitch;
|
|
252
|
+
this.highestNote = "a'";
|
|
253
|
+
if (highestNote) {
|
|
254
|
+
// override default
|
|
255
|
+
this.highestNote = highestNote;
|
|
256
|
+
}
|
|
257
|
+
this.capo = 0;
|
|
258
|
+
if (capo) {
|
|
259
|
+
this.capo = capo;
|
|
260
|
+
}
|
|
261
|
+
this.tuning = tuning;
|
|
262
|
+
if (this.capo > 0) {
|
|
263
|
+
this.capoTuning = buildCapo(this);
|
|
264
|
+
}
|
|
265
|
+
this.strings = buildPatterns(this);
|
|
266
|
+
if (this.strings.error) {
|
|
267
|
+
plugin._super.setError(this.strings.error);
|
|
268
|
+
plugin.inError = true;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
// second position pattern per string
|
|
272
|
+
this.secondPos = buildSecond(this);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
module.exports = StringPatterns;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Layout tablature informations for draw
|
|
4
|
+
* @param {*} numLines
|
|
5
|
+
* @param {*} lineSpace
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
function StringTablature(numLines, lineSpace) {
|
|
9
|
+
this.numLines = numLines;
|
|
10
|
+
this.lineSpace = lineSpace;
|
|
11
|
+
this.verticalSize = this.numLines * this.lineSpace;
|
|
12
|
+
var pitch = 3;
|
|
13
|
+
this.bar = {
|
|
14
|
+
pitch: pitch,
|
|
15
|
+
pitch2: lineSpace * numLines,
|
|
16
|
+
height: 5,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* return true if current line should not produce a tab
|
|
22
|
+
* @param {} line
|
|
23
|
+
*/
|
|
24
|
+
StringTablature.prototype.bypass = function (line) {
|
|
25
|
+
var voices = line.staffGroup.voices;
|
|
26
|
+
if (voices.length > 0) {
|
|
27
|
+
if (voices[0].isPercussion) return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
StringTablature.prototype.setRelative = function (child, relative, first) {
|
|
34
|
+
switch (child.type) {
|
|
35
|
+
case 'bar':
|
|
36
|
+
relative.pitch = this.bar.pitch;
|
|
37
|
+
relative.pitch2 = this.bar.pitch2;
|
|
38
|
+
relative.height = this.height;
|
|
39
|
+
break;
|
|
40
|
+
case 'symbol':
|
|
41
|
+
var top = this.bar.pitch2 / 2;
|
|
42
|
+
if (child.name == 'dots.dot') {
|
|
43
|
+
if (first) {
|
|
44
|
+
relative.pitch = top;
|
|
45
|
+
return false;
|
|
46
|
+
} else {
|
|
47
|
+
relative.pitch = top + this.lineSpace;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
return first;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
module.exports = StringTablature;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Note structure for Tabs
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
var notes = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
function TabNote(note) {
|
|
10
|
+
var isFlat = false;
|
|
11
|
+
var newNote = note;
|
|
12
|
+
var isSharp = false;
|
|
13
|
+
var isAltered = false;
|
|
14
|
+
var natural = null;
|
|
15
|
+
var quarter = null;
|
|
16
|
+
var isDouble = false;
|
|
17
|
+
var acc = 0;
|
|
18
|
+
|
|
19
|
+
if (note.startsWith('_')) {
|
|
20
|
+
isFlat = true;
|
|
21
|
+
acc = -1;
|
|
22
|
+
// check quarter flat
|
|
23
|
+
if (note[1] == '/') {
|
|
24
|
+
isFlat = false;
|
|
25
|
+
quarter = "v";
|
|
26
|
+
acc = 0;
|
|
27
|
+
} else if (note[1] == '_') {
|
|
28
|
+
// double flat
|
|
29
|
+
isDouble = true;
|
|
30
|
+
acc -= 1;
|
|
31
|
+
}
|
|
32
|
+
} else if (note.startsWith('^')) {
|
|
33
|
+
isSharp = true;
|
|
34
|
+
acc = +1;
|
|
35
|
+
// check quarter sharp
|
|
36
|
+
if (note[1] == '/') {
|
|
37
|
+
isSharp = false;
|
|
38
|
+
quarter = "^";
|
|
39
|
+
acc = 0;
|
|
40
|
+
} else if (note[1] == '^') {
|
|
41
|
+
// double sharp
|
|
42
|
+
isDouble = true;
|
|
43
|
+
acc += 1;
|
|
44
|
+
}
|
|
45
|
+
} else if (note.startsWith('=')) {
|
|
46
|
+
natural = true;
|
|
47
|
+
acc = 0;
|
|
48
|
+
}
|
|
49
|
+
isAltered = isFlat || isSharp || (quarter != null);
|
|
50
|
+
if (isAltered || natural) {
|
|
51
|
+
if ((quarter != null) || (isDouble)) {
|
|
52
|
+
newNote = note.slice(2);
|
|
53
|
+
} else {
|
|
54
|
+
newNote = note.slice(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
var hasComma = (note.match(/,/g) || []).length;
|
|
58
|
+
var hasQuote = (note.match(/'/g) || []).length;
|
|
59
|
+
|
|
60
|
+
this.name = newNote;
|
|
61
|
+
this.acc = acc;
|
|
62
|
+
this.isSharp = isSharp;
|
|
63
|
+
this.isKeySharp = false;
|
|
64
|
+
this.isDouble = isDouble;
|
|
65
|
+
this.isAltered = isAltered;
|
|
66
|
+
this.isFlat = isFlat;
|
|
67
|
+
this.isKeyFlat = false;
|
|
68
|
+
this.natural = natural;
|
|
69
|
+
this.quarter = quarter;
|
|
70
|
+
this.isLower = (this.name == this.name.toLowerCase());
|
|
71
|
+
this.name = this.name[0].toUpperCase();
|
|
72
|
+
this.hasComma = hasComma;
|
|
73
|
+
this.isQuoted = hasQuote;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function cloneNote(self) {
|
|
77
|
+
var newNote = self.name;
|
|
78
|
+
var newTabNote = new TabNote(newNote);
|
|
79
|
+
newTabNote.hasComma = self.hasComma;
|
|
80
|
+
newTabNote.isLower = self.isLower;
|
|
81
|
+
newTabNote.isQuoted = self.isQuoted;
|
|
82
|
+
newTabNote.isSharp = self.isSharp;
|
|
83
|
+
newTabNote.isKeySharp = self.isKeySharp;
|
|
84
|
+
newTabNote.isFlat = self.isFlat;
|
|
85
|
+
newTabNote.isKeyFlat = self.isKeyFlat;
|
|
86
|
+
return newTabNote;
|
|
87
|
+
}
|
|
88
|
+
TabNote.prototype.sameNoteAs = function (note) {
|
|
89
|
+
if ((this.name == note.name) &&
|
|
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
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
TabNote.prototype.isLowerThan = function (note) {
|
|
102
|
+
var noteComparator = ['C','D','E','F','G','A','B'];
|
|
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;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
TabNote.prototype.checkKeyAccidentals = function(accidentals) {
|
|
119
|
+
if (accidentals) {
|
|
120
|
+
var curNote = this.name;
|
|
121
|
+
for (var iii = 0; iii < accidentals.length; iii++) {
|
|
122
|
+
var curAccidentals = accidentals[iii];
|
|
123
|
+
if (curNote == curAccidentals.note.toUpperCase()) {
|
|
124
|
+
if (curAccidentals.acc == 'flat') {
|
|
125
|
+
this.acc = -1;
|
|
126
|
+
this.isKeyFlat = true;
|
|
127
|
+
}
|
|
128
|
+
if (curAccidentals.acc == 'sharp') {
|
|
129
|
+
this.acc = +1;
|
|
130
|
+
this.isKeySharp = true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
TabNote.prototype.getAccidentalEquiv = function () {
|
|
138
|
+
var cloned = cloneNote(this);
|
|
139
|
+
if (cloned.isSharp || cloned.isKeySharp ) {
|
|
140
|
+
cloned = cloned.nextNote();
|
|
141
|
+
cloned.isFlat = true;
|
|
142
|
+
cloned.isSharp = false;
|
|
143
|
+
cloned.isKeySharp = false;
|
|
144
|
+
} else if (cloned.isFlat || cloned.isKeyFlat ) {
|
|
145
|
+
cloned = cloned.prevNote();
|
|
146
|
+
cloned.isSharp = true;
|
|
147
|
+
cloned.isFlat = false;
|
|
148
|
+
cloned.isKeyFlat = false;
|
|
149
|
+
}
|
|
150
|
+
return cloned;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
TabNote.prototype.nextNote = function () {
|
|
155
|
+
var newTabNote = cloneNote(this);
|
|
156
|
+
|
|
157
|
+
if (!this.isSharp && !this.isKeySharp ) {
|
|
158
|
+
if (this.name != 'E' && this.name != 'B') {
|
|
159
|
+
newTabNote.isSharp = true;
|
|
160
|
+
return newTabNote;
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
// cleanup
|
|
164
|
+
newTabNote.isSharp = false;
|
|
165
|
+
newTabNote.isKeySharp = false;
|
|
166
|
+
}
|
|
167
|
+
var noteIndex = notes.indexOf(this.name);
|
|
168
|
+
if (noteIndex == notes.length - 1) {
|
|
169
|
+
noteIndex = 0;
|
|
170
|
+
} else {
|
|
171
|
+
noteIndex++;
|
|
172
|
+
}
|
|
173
|
+
newTabNote.name = notes[noteIndex];
|
|
174
|
+
if (newTabNote.name == 'C') {
|
|
175
|
+
if (newTabNote.hasComma > 0) {
|
|
176
|
+
newTabNote.hasComma--;
|
|
177
|
+
} else {
|
|
178
|
+
if (!newTabNote.isLower) {
|
|
179
|
+
newTabNote.isLower = true;
|
|
180
|
+
} else {
|
|
181
|
+
newTabNote.isQuoted = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return newTabNote;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
TabNote.prototype.prevNote = function () {
|
|
189
|
+
var newTabNote = cloneNote(this);
|
|
190
|
+
|
|
191
|
+
if (this.isSharp) {
|
|
192
|
+
newTabNote.isSharp = false;
|
|
193
|
+
return newTabNote;
|
|
194
|
+
}
|
|
195
|
+
var noteIndex = notes.indexOf(this.name);
|
|
196
|
+
if (noteIndex == 0) {
|
|
197
|
+
noteIndex = notes.length - 1;
|
|
198
|
+
} else {
|
|
199
|
+
noteIndex--;
|
|
200
|
+
}
|
|
201
|
+
newTabNote.name = notes[noteIndex];
|
|
202
|
+
if (newTabNote.name == 'B') {
|
|
203
|
+
if (newTabNote.isLower) {
|
|
204
|
+
newTabNote.hasComma = 1;
|
|
205
|
+
} else {
|
|
206
|
+
if (newTabNote.hasComma > 0) {
|
|
207
|
+
newTabNote.hasComma++;
|
|
208
|
+
} else {
|
|
209
|
+
if (newTabNote.isQuoted > 0) {
|
|
210
|
+
newTabNote.isQuoted -= 1;
|
|
211
|
+
} else {
|
|
212
|
+
newTabNote.isLower = true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (this.isFlat) {
|
|
218
|
+
newTabNote.isFlat = false;
|
|
219
|
+
return newTabNote;
|
|
220
|
+
} else {
|
|
221
|
+
if (this.name != 'E' && this.name != 'B') {
|
|
222
|
+
newTabNote.isSharp = true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return newTabNote;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
TabNote.prototype.emitNoAccidentals = function ( ) {
|
|
229
|
+
var returned = this.name;
|
|
230
|
+
if (this.isLower) {
|
|
231
|
+
returned = returned.toLowerCase();
|
|
232
|
+
}
|
|
233
|
+
for (var ii = 0; ii < this.isQuoted; ii++) {
|
|
234
|
+
returned += "'";
|
|
235
|
+
}
|
|
236
|
+
for (var jj = 0; jj < this.hasComma; jj++) {
|
|
237
|
+
returned += ",";
|
|
238
|
+
}
|
|
239
|
+
return returned;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
TabNote.prototype.emit = function () {
|
|
243
|
+
var returned = this.name;
|
|
244
|
+
if (this.isSharp || this.isKeySharp ) {
|
|
245
|
+
returned = '^' + returned;
|
|
246
|
+
if (this.isDouble) {
|
|
247
|
+
returned = '^' + returned;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (this.isFlat || this.isKeyFlat) {
|
|
251
|
+
returned = '_' + returned;
|
|
252
|
+
if (this.isDouble) {
|
|
253
|
+
returned = '_' + returned;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (this.quarter) {
|
|
257
|
+
if (this.quarter == "^") {
|
|
258
|
+
returned = "^/" + returned;
|
|
259
|
+
} else {
|
|
260
|
+
returned = "_/" + returned;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (this.natural) {
|
|
264
|
+
returned = '=' + returned;
|
|
265
|
+
}
|
|
266
|
+
for (var ii = 1; ii <= this.hasComma; ii++) {
|
|
267
|
+
returned += ',';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (this.isLower) {
|
|
271
|
+
returned = returned.toLowerCase();
|
|
272
|
+
for (var jj = 1; jj <= this.isQuoted; jj++) {
|
|
273
|
+
returned += "'";
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return returned;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
module.exports = {
|
|
280
|
+
'TabNote': TabNote,
|
|
281
|
+
'notes': notes
|
|
282
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
var TabNote = require('./tab-note');
|
|
3
|
+
|
|
4
|
+
var notes = TabNote.notes;
|
|
5
|
+
|
|
6
|
+
function TabNotes(fromNote, toNote) {
|
|
7
|
+
this.fromN = new TabNote.TabNote(fromNote);
|
|
8
|
+
this.toN = new TabNote.TabNote(toNote);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
TabNotes.prototype.build = function () {
|
|
13
|
+
var fromN = this.fromN;
|
|
14
|
+
var toN = this.toN;
|
|
15
|
+
// check that toN is not lower than fromN
|
|
16
|
+
if (toN.isLowerThan(fromN)) {
|
|
17
|
+
var from = fromN.emit();
|
|
18
|
+
var tn = toN.emit();
|
|
19
|
+
return {
|
|
20
|
+
error: 'Invalid string Instrument tuning : ' +
|
|
21
|
+
tn + ' string lower than ' + from + ' string'
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
var buildReturned = [];
|
|
25
|
+
var startIndex = notes.indexOf(fromN.name);
|
|
26
|
+
var toIndex = notes.indexOf(toN.name);
|
|
27
|
+
if ((startIndex == -1) || (toIndex == -1)) {
|
|
28
|
+
return buildReturned;
|
|
29
|
+
}
|
|
30
|
+
var finished = false;
|
|
31
|
+
while (!finished) {
|
|
32
|
+
buildReturned.push(fromN.emit());
|
|
33
|
+
fromN = fromN.nextNote();
|
|
34
|
+
if (fromN.sameNoteAs(toN)) {
|
|
35
|
+
finished = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return buildReturned;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports = TabNotes;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
|
|
2
|
+
var StringTablature = require('../string-tablature');
|
|
3
|
+
var TabCommon = require('../../tab-common');
|
|
4
|
+
var TabRenderer = require('../../tab-renderer');
|
|
5
|
+
var ViolinPatterns = require('./violin-patterns');
|
|
6
|
+
var setViolinFonts = require('./violin-fonts');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* upon init mainly store provided instances for later usage
|
|
11
|
+
* @param {*} abcTune the parsed tune AST tree
|
|
12
|
+
* @param {*} tuneNumber the parsed tune AST tree
|
|
13
|
+
* @param {*} params complementary args provided to Tablature Plugin
|
|
14
|
+
*/
|
|
15
|
+
Plugin.prototype.init = function (abcTune, tuneNumber, params) {
|
|
16
|
+
var _super = new TabCommon(abcTune, tuneNumber, params);
|
|
17
|
+
this.abcTune = abcTune;
|
|
18
|
+
this._super = _super;
|
|
19
|
+
this.linePitch = 3;
|
|
20
|
+
this.nbLines = 4;
|
|
21
|
+
this.isTabBig = false;
|
|
22
|
+
this.capo = params.capo;
|
|
23
|
+
this.transpose = params.visualTranspose;
|
|
24
|
+
this.tablature = new StringTablature(this.nbLines,
|
|
25
|
+
this.linePitch);
|
|
26
|
+
var semantics = new ViolinPatterns(this);
|
|
27
|
+
this.semantics = semantics;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
Plugin.prototype.render = function (renderer, line, staffIndex) {
|
|
31
|
+
if (this._super.inError) return;
|
|
32
|
+
if (this.tablature.bypass(line)) return;
|
|
33
|
+
setViolinFonts(this.abcTune);
|
|
34
|
+
var rndrer = new TabRenderer(this, renderer, line, staffIndex);
|
|
35
|
+
rndrer.doLayout();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function Plugin() {}
|
|
39
|
+
|
|
40
|
+
//
|
|
41
|
+
// Tablature plugin definition
|
|
42
|
+
//
|
|
43
|
+
var AbcViolinTab = function () {
|
|
44
|
+
return { name: 'ViolinTab', tablature: Plugin };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
module.exports = AbcViolinTab;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Dedicated fonts for violin tabs
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Set here the fonts used by renderer/drawer
|
|
8
|
+
* for the violin plugin
|
|
9
|
+
* @param {} tune
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line no-unused-vars
|
|
12
|
+
function setViolinFonts(tune) {
|
|
13
|
+
/* enhance or change instrument fonts here */
|
|
14
|
+
// tune.formatting.tabnumberfont = { face: "\"Times New Roman\"", size: 9, weight: "normal", style: "normal", decoration: "none" };
|
|
15
|
+
// tune.formatting.tabgracefont = { face: "\"Times New Roman\"", size: 7, weight: "normal", style: "normal", decoration: "none" };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = setViolinFonts;
|
|
19
|
+
|