abcjs 6.0.0-beta.9 → 6.0.2

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.
Files changed (197) hide show
  1. package/.github/workflows/tests.yml +29 -0
  2. package/CODE_OF_CONDUCT.md +76 -0
  3. package/CONTRIBUTING.md +1 -0
  4. package/LICENSE.md +1 -1
  5. package/README.md +88 -7
  6. package/RELEASE.md +961 -1
  7. package/abcjs-audio.css +14 -5
  8. package/dist/.gitignore +1 -2
  9. package/dist/abcjs-basic-min.js +3 -0
  10. package/dist/abcjs-basic-min.js.LICENSE +23 -0
  11. package/dist/abcjs-basic.js +28232 -0
  12. package/dist/abcjs-basic.js.map +1 -0
  13. package/dist/abcjs-plugin-min.js +3 -0
  14. package/dist/abcjs-plugin-min.js.LICENSE +23 -0
  15. package/index.js +27 -2
  16. package/{static-wrappers/license.js → license.js} +1 -1
  17. package/package.json +26 -29
  18. package/{src/plugin/abc_plugin.js → plugin.js} +31 -19
  19. package/src/api/abc_animation.js +1 -17
  20. package/src/api/abc_tablatures.js +144 -0
  21. package/src/api/abc_timing_callbacks.js +216 -117
  22. package/src/api/abc_tunebook.js +18 -67
  23. package/src/api/abc_tunebook_svg.js +40 -48
  24. package/src/data/abc_tune.js +232 -972
  25. package/src/data/deline-tune.js +199 -0
  26. package/src/edit/abc_editarea.js +112 -0
  27. package/src/edit/abc_editor.js +95 -221
  28. package/src/midi/abc_midi_create.js +48 -50
  29. package/src/parse/abc_common.js +0 -14
  30. package/src/parse/abc_parse.js +167 -1321
  31. package/src/parse/abc_parse_book.js +62 -0
  32. package/src/parse/abc_parse_directive.js +164 -41
  33. package/src/parse/abc_parse_header.js +116 -145
  34. package/src/parse/abc_parse_key_voice.js +26 -20
  35. package/src/parse/abc_parse_music.js +1337 -0
  36. package/src/parse/abc_tokenizer.js +21 -15
  37. package/src/parse/abc_transpose.js +3 -15
  38. package/src/parse/tune-builder.js +896 -0
  39. package/src/parse/wrap_lines.js +205 -453
  40. package/src/synth/abc_midi_flattener.js +1292 -0
  41. package/src/{midi → synth}/abc_midi_renderer.js +44 -17
  42. package/src/synth/abc_midi_sequencer.js +648 -0
  43. package/src/synth/active-audio-context.js +3 -14
  44. package/src/synth/cents-to-factor.js +10 -0
  45. package/src/synth/create-note-map.js +21 -32
  46. package/src/synth/create-synth-control.js +20 -103
  47. package/src/synth/create-synth.js +185 -77
  48. package/src/synth/download-buffer.js +7 -21
  49. package/src/synth/get-midi-file.js +13 -20
  50. package/src/synth/images/{loading.svg → loading.svg.js} +4 -0
  51. package/src/synth/images/loop.svg.js +65 -0
  52. package/src/synth/images/pause.svg.js +10 -0
  53. package/src/synth/images/play.svg.js +9 -0
  54. package/src/synth/images/{reset.svg → reset.svg.js} +5 -1
  55. package/src/synth/instrument-index-to-name.js +1 -16
  56. package/src/synth/load-note.js +37 -76
  57. package/src/synth/pitch-to-note-name.js +0 -15
  58. package/src/synth/pitches-to-perc.js +64 -0
  59. package/src/synth/place-note.js +78 -68
  60. package/src/synth/play-event.js +17 -18
  61. package/src/synth/register-audio-context.js +11 -23
  62. package/src/synth/sounds-cache.js +0 -15
  63. package/src/synth/supports-audio.js +9 -23
  64. package/src/synth/synth-controller.js +80 -49
  65. package/src/synth/synth-sequence.js +20 -34
  66. package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
  67. package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
  68. package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
  69. package/src/tablatures/instruments/string-patterns.js +277 -0
  70. package/src/tablatures/instruments/string-tablature.js +56 -0
  71. package/src/tablatures/instruments/tab-note.js +282 -0
  72. package/src/tablatures/instruments/tab-notes.js +41 -0
  73. package/src/tablatures/instruments/violin/tab-violin.js +47 -0
  74. package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
  75. package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
  76. package/src/tablatures/tab-absolute-elements.js +310 -0
  77. package/src/tablatures/tab-common.js +29 -0
  78. package/src/tablatures/tab-renderer.js +243 -0
  79. package/src/tablatures/transposer.js +110 -0
  80. package/src/test/abc_midi_lint.js +5 -22
  81. package/src/test/abc_midi_sequencer_lint.js +11 -14
  82. package/src/test/abc_parser_lint.js +136 -32
  83. package/src/test/abc_vertical_lint.js +94 -32
  84. package/src/test/rendering-lint.js +38 -5
  85. package/src/write/abc_absolute_element.js +112 -120
  86. package/src/write/abc_abstract_engraver.js +102 -253
  87. package/src/write/abc_beam_element.js +30 -290
  88. package/src/write/abc_brace_element.js +12 -121
  89. package/src/write/abc_create_clef.js +21 -32
  90. package/src/write/abc_create_key_signature.js +8 -26
  91. package/src/write/abc_create_note_head.js +107 -0
  92. package/src/write/abc_create_time_signature.js +2 -21
  93. package/src/write/abc_crescendo_element.js +3 -50
  94. package/src/write/abc_decoration.js +7 -30
  95. package/src/write/abc_dynamic_decoration.js +3 -37
  96. package/src/write/abc_ending_element.js +1 -57
  97. package/src/write/abc_engraver_controller.js +111 -234
  98. package/src/write/abc_glyphs.js +8 -18
  99. package/src/write/abc_relative_element.js +57 -97
  100. package/src/write/abc_renderer.js +10 -832
  101. package/src/write/abc_spacing.js +0 -15
  102. package/src/write/abc_staff_group_element.js +14 -349
  103. package/src/write/abc_tempo_element.js +9 -117
  104. package/src/write/abc_tie_element.js +5 -68
  105. package/src/write/abc_triplet_element.js +6 -124
  106. package/src/write/abc_voice_element.js +7 -222
  107. package/src/write/add-chord.js +103 -0
  108. package/src/write/add-text-if.js +33 -0
  109. package/src/write/bottom-text.js +79 -0
  110. package/src/write/calcHeight.js +17 -0
  111. package/src/write/classes.js +100 -0
  112. package/src/write/draw/absolute.js +68 -0
  113. package/src/write/draw/beam.js +56 -0
  114. package/src/write/draw/brace.js +106 -0
  115. package/src/write/draw/crescendo.js +38 -0
  116. package/src/write/draw/debug-box.js +8 -0
  117. package/src/write/draw/draw.js +56 -0
  118. package/src/write/draw/dynamics.js +20 -0
  119. package/src/write/draw/ending.js +46 -0
  120. package/src/write/draw/group-elements.js +66 -0
  121. package/src/write/draw/horizontal-line.js +25 -0
  122. package/src/write/draw/non-music.js +50 -0
  123. package/src/write/draw/print-line.js +24 -0
  124. package/src/write/draw/print-path.js +7 -0
  125. package/src/write/draw/print-stem.js +30 -0
  126. package/src/write/draw/print-symbol.js +59 -0
  127. package/src/write/draw/print-vertical-line.js +18 -0
  128. package/src/write/draw/relative.js +77 -0
  129. package/src/write/draw/round-number.js +5 -0
  130. package/src/write/draw/selectables.js +59 -0
  131. package/src/write/draw/separator.js +16 -0
  132. package/src/write/draw/set-paper-size.js +45 -0
  133. package/src/write/{sprintf.js → draw/sprintf.js} +0 -0
  134. package/src/write/draw/staff-group.js +226 -0
  135. package/src/write/draw/staff-line.js +9 -0
  136. package/src/write/draw/staff.js +33 -0
  137. package/src/write/draw/tab-line.js +40 -0
  138. package/src/write/draw/tempo.js +45 -0
  139. package/src/write/draw/text.js +71 -0
  140. package/src/write/draw/tie.js +97 -0
  141. package/src/write/draw/triplet.js +46 -0
  142. package/src/write/draw/voice.js +102 -0
  143. package/src/write/format-jazz-chord.js +15 -0
  144. package/src/write/free-text.js +41 -0
  145. package/src/write/get-font-and-attr.js +37 -0
  146. package/src/write/get-text-size.js +56 -0
  147. package/src/write/highlight.js +11 -0
  148. package/src/write/layout/VoiceElements.js +121 -0
  149. package/src/write/layout/beam.js +213 -0
  150. package/src/write/layout/get-left-edge-of-staff.js +56 -0
  151. package/src/write/layout/getBarYAt.js +6 -0
  152. package/src/write/layout/layout.js +94 -0
  153. package/src/write/layout/setUpperAndLowerElements.js +232 -0
  154. package/src/write/layout/staffGroup.js +146 -0
  155. package/src/write/layout/triplet.js +75 -0
  156. package/src/write/layout/voice.js +137 -0
  157. package/src/write/selection.js +188 -70
  158. package/src/write/separator.js +10 -0
  159. package/src/write/set-class.js +21 -0
  160. package/src/write/subtitle.js +12 -0
  161. package/src/write/svg.js +95 -43
  162. package/src/write/top-text.js +54 -0
  163. package/src/write/unhighlight.js +11 -0
  164. package/test.js +27 -64
  165. package/types/index.d.ts +1095 -0
  166. package/version.js +1 -1
  167. package/.babelrc +0 -5
  168. package/.eslintrc +0 -3
  169. package/.gitmodules +0 -3
  170. package/Dockerfile +0 -8
  171. package/abcjs-midi.css +0 -166
  172. package/build-utils/loadPresets.js +0 -14
  173. package/build-utils/presets/webpack.analyze.js +0 -6
  174. package/build-utils/presets/webpack.optimize.js +0 -30
  175. package/build-utils/webpack.development.js +0 -14
  176. package/build-utils/webpack.production.js +0 -35
  177. package/deploy-docs.sh +0 -25
  178. package/docker-compose.yml +0 -13
  179. package/docs/README.md +0 -33
  180. package/fix-versions.sh +0 -23
  181. package/midi.js +0 -62
  182. package/src/api/abc_tunebook_midi.js +0 -116
  183. package/src/midi/abc_midi_controls.js +0 -701
  184. package/src/midi/abc_midi_flattener.js +0 -1119
  185. package/src/midi/abc_midi_js_preparer.js +0 -243
  186. package/src/midi/abc_midi_sequencer.js +0 -401
  187. package/src/midi/abc_midi_ui_generator.js +0 -86
  188. package/src/plugin/abc_plugin_midi.js +0 -220
  189. package/src/synth/images/loop.svg +0 -61
  190. package/src/synth/images/pause.svg +0 -6
  191. package/src/synth/images/play.svg +0 -5
  192. package/src/transform/abc2abc_write.js +0 -395
  193. package/static-wrappers/basic.js +0 -2
  194. package/static-wrappers/midi.js +0 -2
  195. package/static-wrappers/plugin-midi.js +0 -6
  196. package/static-wrappers/plugin.js +0 -6
  197. package/webpack.config.js +0 -29
@@ -0,0 +1,23 @@
1
+ var StringPatterns = require('../string-patterns');
2
+
3
+ function ViolinPatterns(plugin) {
4
+ this.tuning = plugin._super.params.tuning;
5
+ if (!this.tuning) {
6
+ this.tuning = ['G,', 'D', 'A', 'e'];
7
+ }
8
+ plugin.tuning = this.tuning;
9
+ this.strings = new StringPatterns(plugin);
10
+ }
11
+
12
+ ViolinPatterns.prototype.notesToNumber = function (notes, graces) {
13
+ var converter = this.strings;
14
+ return converter.notesToNumber(notes, graces);
15
+ };
16
+
17
+ ViolinPatterns.prototype.stringToPitch = function (stringNumber) {
18
+ var converter = this.strings;
19
+ return converter.stringToPitch(stringNumber);
20
+ };
21
+
22
+
23
+ module.exports = ViolinPatterns;
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Tablature Absolute elements factory
3
+ */
4
+ var AbsoluteElement = require('../write/abc_absolute_element');
5
+ var RelativeElement = require('../write/abc_relative_element');
6
+ var Transposer = require('./transposer');
7
+
8
+ function isObject(a) { return a != null && a.constructor === Object; }
9
+ function cloneObject(dest, src) {
10
+ for (var prop in src) {
11
+ if (src.hasOwnProperty(prop)) {
12
+ if (!(Array.isArray(src[prop]) || isObject(src[prop]))) {
13
+ dest[prop] = src[prop];
14
+ }
15
+ }
16
+ }
17
+ }
18
+
19
+ function cloneAbsolute(absSrc) {
20
+ var returned = new AbsoluteElement('', 0, 0, '', 0);
21
+ cloneObject(returned, absSrc);
22
+ returned.top = 0;
23
+ returned.bottom = -1;
24
+ if (absSrc.abcelem) {
25
+ returned.abcelem = {};
26
+ cloneObject(returned.abcelem, absSrc.abcelem);
27
+ if (returned.abcelem.el_type === "note")
28
+ returned.abcelem.el_type = 'tabNumber';
29
+ }
30
+ return returned;
31
+ }
32
+
33
+ function cloneAbsoluteAndRelatives(absSrc, plugin) {
34
+ var returned = cloneAbsolute(absSrc);
35
+ if (plugin) {
36
+ var children = absSrc.children;
37
+ // proceed with relative as well
38
+ var first = true;
39
+ for (var ii = 0; ii < children.length; ii++) {
40
+ var child = children[ii];
41
+ var relative = new RelativeElement('', 0, 0, 0, '');
42
+ cloneObject(relative, child);
43
+ first = plugin.tablature.setRelative(child, relative, first);
44
+ returned.children.push(relative);
45
+ }
46
+ }
47
+ return returned;
48
+ }
49
+
50
+ function buildTabAbsolute(plugin, absX, relX) {
51
+ var tabIcon = 'tab.tiny';
52
+ var tabYPos = 7.5;
53
+ if (plugin.isTabBig) {
54
+ tabIcon = 'tab.big';
55
+ tabYPos = 10;
56
+ }
57
+ var element = {
58
+ el_type: "tab",
59
+ icon: tabIcon,
60
+ Ypos: tabYPos
61
+ };
62
+ var tabAbsolute = new AbsoluteElement(element, 0, 0, "symbol", 0);
63
+ tabAbsolute.x = absX;
64
+ var tabRelative = new RelativeElement(tabIcon, 0, 0, 7.5, "tab");
65
+ tabRelative.x = relX;
66
+ tabAbsolute.children.push(tabRelative);
67
+ if (tabAbsolute.abcelem.el_type == 'tab') {
68
+ tabRelative.pitch = tabYPos;
69
+ }
70
+ return tabAbsolute;
71
+ }
72
+
73
+ function lyricsDim(abs) {
74
+ if (abs.extra) {
75
+ for (var ii = 0; ii < abs.extra.length; ii++) {
76
+ var extra = abs.extra[ii];
77
+ if (extra.type == 'lyric') {
78
+ return {
79
+ bottom: extra.bottom,
80
+ height: extra.height
81
+ };
82
+ }
83
+ }
84
+ }
85
+ return null;
86
+ }
87
+ function TabAbsoluteElements() {
88
+ this.accidentals = null;
89
+ }
90
+
91
+ function getInitialStaffSize(staffGroup) {
92
+ var returned = 0;
93
+ for (var ii = 0; ii < staffGroup.length; ii++) {
94
+ if (!staffGroup[ii].tabNameInfos) returned++;
95
+ }
96
+ return returned;
97
+ }
98
+
99
+ function buildRelativeTabNote(plugin, relX, def, curNote, isGrace) {
100
+ var strNote = curNote.num;
101
+ if (curNote.note.quarter != null) {
102
+ // add tab quarter => needs to string conversion then
103
+ strNote = strNote.toString();
104
+ strNote += curNote.note.quarter;
105
+ }
106
+ var pitch = plugin.semantics.stringToPitch(curNote.str);
107
+ def.notes.push({ num: strNote, str: curNote.str, pitch: curNote.note.emit() });
108
+ var opt = {
109
+ type: 'tabNumber'
110
+ };
111
+ var tabNoteRelative = new RelativeElement(
112
+ strNote, 0, 0, pitch+0.3, opt);
113
+ tabNoteRelative.x = relX;
114
+ tabNoteRelative.isGrace = isGrace;
115
+ tabNoteRelative.isAltered = curNote.note.isAltered;
116
+ return tabNoteRelative;
117
+ }
118
+
119
+ function getXGrace(abs, index) {
120
+ var found = 0;
121
+ if (abs.extra) {
122
+ for (var ii = 0; ii < abs.extra.length; ii++) {
123
+ if (abs.extra[ii].c.indexOf('noteheads') >= 0) {
124
+ if (found === index) {
125
+ return abs.extra[ii].x + abs.extra[ii].w/2;
126
+ } else {
127
+ found++;
128
+ }
129
+ }
130
+ }
131
+ }
132
+ return -1;
133
+ }
134
+
135
+ function graceInRest( absElem ) {
136
+ if (absElem.abcelem) {
137
+ var elem = absElem.abcelem;
138
+ if (elem.rest) {
139
+ return elem.gracenotes;
140
+ }
141
+ }
142
+ return null;
143
+ }
144
+
145
+ function checkTransposition(plugin, transposer ,pitches, graceNotes) {
146
+ if (plugin.transpose) {
147
+ //transposer.transpose(plugin.transpose);
148
+ for (var jj = 0; jj < pitches.length; jj++) {
149
+ pitches[jj] = transposer.transposeNote(pitches[jj]);
150
+ }
151
+ if (graceNotes) {
152
+ for (var kk = 0; kk < graceNotes.length; kk++) {
153
+ graceNotes[kk] = transposer.transposeNote(graceNotes[kk]);
154
+ }
155
+ }
156
+ }
157
+ }
158
+
159
+ function convertToNumber(plugin, pitches, graceNotes) {
160
+ var tabPos = plugin.semantics.notesToNumber(pitches, graceNotes);
161
+ if (tabPos.error) {
162
+ plugin._super.setError(tabPos.error);
163
+ return tabPos; // give up on error here
164
+ }
165
+ if (tabPos.graces && tabPos.notes) {
166
+ // add graces to last note in notes
167
+ var posNote = tabPos.notes.length - 1;
168
+ tabPos.notes[posNote].graces = tabPos.graces;
169
+ }
170
+ return tabPos;
171
+ }
172
+
173
+ function buildGraceRelativesForRest(plugin,abs,absChild,graceNotes,tabVoice) {
174
+ for (var mm = 0; mm < graceNotes.length; mm++) {
175
+ var defGrace = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [], grace: true };
176
+ var graceX = getXGrace(absChild, mm);
177
+ var curGrace = graceNotes[mm];
178
+ var tabGraceRelative = buildRelativeTabNote(plugin, graceX, defGrace, curGrace, true);
179
+ abs.children.push(tabGraceRelative);
180
+ tabVoice.push(defGrace);
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Build tab absolutes by scanning current staff line absolute array
186
+ * @param {*} staffAbsolute
187
+ */
188
+ TabAbsoluteElements.prototype.build = function (plugin,
189
+ staffAbsolute,
190
+ tabVoice,
191
+ voiceIndex,
192
+ staffIndex,
193
+ keySig ) {
194
+ var staffSize = getInitialStaffSize(staffAbsolute);
195
+ var source = staffAbsolute[staffIndex+voiceIndex];
196
+ var dest = staffAbsolute[staffSize+staffIndex+voiceIndex];
197
+ var transposer = null;
198
+ var tabPos = null;
199
+ var defNote = null;
200
+ if (source.children[0].abcelem.el_type != 'clef') {
201
+ // keysig missing => provide one for tabs
202
+ if (keySig != 'none') {
203
+ source.children.splice(0, 0, keySig);
204
+ }
205
+ }
206
+ for (var ii = 0; ii < source.children.length; ii++) {
207
+ var absChild = source.children[ii];
208
+ var absX = absChild.x;
209
+ var relX = absX;
210
+ // if (absChild.children.length > 0) {
211
+ // relX = absChild.children[0].x;
212
+ // }
213
+ if ( (absChild.isClef) ) {
214
+ dest.children.push(buildTabAbsolute(plugin, absX, relX));
215
+ }
216
+ switch (absChild.type) {
217
+ case 'staff-extra key-signature':
218
+ // refresh key accidentals
219
+ this.accidentals = absChild.abcelem.accidentals;
220
+ plugin.semantics.strings.accidentals = this.accidentals;
221
+ if (plugin.transpose) {
222
+ transposer = new Transposer(
223
+ absChild.abcelem.accidentals,
224
+ plugin.transpose
225
+ );
226
+ }
227
+ break;
228
+ case 'bar':
229
+ var lastBar = false;
230
+ if (ii === source.children.length-1) {
231
+ // used for final line bar drawing
232
+ // for multi tabs / multi staves
233
+ lastBar = true;
234
+ }
235
+ var cloned = cloneAbsoluteAndRelatives(absChild, plugin);
236
+ if (cloned.abcelem.barNumber) {
237
+ delete cloned.abcelem.barNumber;
238
+ for (var bn = 0; bn < cloned.children.length; bn++) {
239
+ if (cloned.children[bn].type === "barNumber" ) {
240
+ cloned.children.splice(bn, 1);
241
+ break;
242
+ }
243
+ }
244
+ }
245
+ cloned.abcelem.lastBar = lastBar;
246
+ dest.children.push(cloned);
247
+ tabVoice.push({
248
+ el_type: absChild.abcelem.el_type,
249
+ type: absChild.abcelem.type,
250
+ endChar: absChild.abcelem.endChar,
251
+ startChar: absChild.abcelem.startChar,
252
+ abselem: cloned
253
+ });
254
+ break;
255
+ case 'rest':
256
+ var restGraces = graceInRest(absChild);
257
+ if (restGraces) {
258
+ // check transpose
259
+ checkTransposition(plugin, transposer, null, restGraces);
260
+ // to number conversion
261
+ tabPos = convertToNumber(plugin, null, restGraces);
262
+ if (tabPos.error) return;
263
+ // build relative for grace
264
+ defGrace = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [], grace: true };
265
+ buildGraceRelativesForRest(plugin, abs, absChild, tabPos.graces, tabVoice);
266
+ }
267
+ break;
268
+ case 'note':
269
+ var abs = cloneAbsolute(absChild);
270
+ abs.x = absChild.heads[0].x + absChild.heads[0].w / 2; // center the number
271
+ abs.lyricDim = lyricsDim(absChild);
272
+ var pitches = absChild.abcelem.pitches;
273
+ var graceNotes = absChild.abcelem.gracenotes;
274
+ // check transpose
275
+ abs.type = 'tabNumber';
276
+ checkTransposition(plugin, transposer, pitches, graceNotes);
277
+ // to number conversion
278
+ tabPos = convertToNumber(plugin, pitches, graceNotes);
279
+ if (tabPos.error) return;
280
+ if (tabPos.graces) {
281
+ // add graces to last note in notes
282
+ var posNote = tabPos.notes.length - 1;
283
+ tabPos.notes[posNote].graces = tabPos.graces;
284
+ }
285
+ // build relative
286
+ defNote = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [] };
287
+ for (var ll = 0; ll < tabPos.notes.length; ll++) {
288
+ var curNote = tabPos.notes[ll];
289
+ if (curNote.graces) {
290
+ for (var mm = 0; mm < curNote.graces.length; mm++) {
291
+ var defGrace = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [], grace: true };
292
+ var graceX = getXGrace(absChild , mm);
293
+ var curGrace = curNote.graces[mm];
294
+ var tabGraceRelative = buildRelativeTabNote(plugin, graceX, defGrace, curGrace, true);
295
+ abs.children.push(tabGraceRelative);
296
+ tabVoice.push(defGrace);
297
+ }
298
+ }
299
+ var tabNoteRelative = buildRelativeTabNote(plugin, abs.x+absChild.heads[ll].dx, defNote, curNote, false);
300
+ abs.children.push(tabNoteRelative);
301
+ }
302
+ defNote.abselem = abs;
303
+ tabVoice.push(defNote);
304
+ dest.children.push(abs);
305
+ break;
306
+ }
307
+ }
308
+ };
309
+
310
+ module.exports = TabAbsoluteElements;
@@ -0,0 +1,29 @@
1
+ /**
2
+ *
3
+ * Common Class/Method available for all instruments
4
+ *
5
+ */
6
+
7
+ function TabCommon(abcTune, tuneNumber, params) {
8
+ this.tune = abcTune;
9
+ this.params = params;
10
+ this.tuneNumber = tuneNumber;
11
+ this.inError = false;
12
+ }
13
+
14
+
15
+ TabCommon.prototype.setError = function (error) {
16
+ var tune = this.tune;
17
+ if (error) {
18
+ this.error = error;
19
+ this.inError = true;
20
+ if (tune.warnings) {
21
+ tune.warnings.push(error);
22
+ } else {
23
+ tune.warnings = [error];
24
+ }
25
+ }
26
+ };
27
+
28
+
29
+ module.exports = TabCommon;
@@ -0,0 +1,243 @@
1
+ /* eslint-disable no-debugger */
2
+ var VoiceElement = require('../write/abc_voice_element');
3
+ var TabAbsoluteElements = require('./tab-absolute-elements');
4
+ var spacing = require('../write/abc_spacing');
5
+
6
+ function initSpecialY() {
7
+ return {
8
+ tempoHeightAbove: 0,
9
+ partHeightAbove: 0,
10
+ volumeHeightAbove: 0,
11
+ dynamicHeightAbove: 0,
12
+ endingHeightAbove: 0,
13
+ chordHeightAbove: 0,
14
+ lyricHeightAbove: 0,
15
+ lyricHeightBelow: 0,
16
+ chordHeightBelow: 0,
17
+ volumeHeightBelow: 0,
18
+ dynamicHeightBelow: 0
19
+ };
20
+ }
21
+
22
+ function getLyricHeight(voice) {
23
+ var maxLyricHeight = 0;
24
+ for (var ii = 0; ii < voice.children.length; ii++) {
25
+ var curAbs = voice.children[ii];
26
+ if (curAbs.specialY) {
27
+ if (curAbs.specialY.lyricHeightBelow > maxLyricHeight) {
28
+ maxLyricHeight = curAbs.specialY.lyricHeightBelow;
29
+ }
30
+ }
31
+ }
32
+ return maxLyricHeight; // add spacing
33
+ }
34
+
35
+ function buildTabName(self, dest) {
36
+ var stringSemantics = self.plugin.semantics.strings;
37
+ var controller = self.renderer.controller;
38
+ var textSize = controller.getTextSize;
39
+ var tabName = stringSemantics.tabInfos(self.plugin);
40
+ var size = textSize.calc(tabName, 'tablabelfont', 'text instrumentname');
41
+ dest.tabNameInfos = {
42
+ textSize: size,
43
+ name: tabName
44
+ };
45
+ return size.height;
46
+ }
47
+
48
+ /**
49
+ * Laying out tabs
50
+ * @param {*} renderer
51
+ * @param {*} line
52
+ * @param {*} staffIndex
53
+ * @param {*} tablatureLayout
54
+ */
55
+ function TabRenderer(plugin, renderer, line, staffIndex) {
56
+ this.renderer = renderer;
57
+ this.plugin = plugin;
58
+ this.line = line;
59
+ this.absolutes = new TabAbsoluteElements();
60
+ this.staffIndex = staffIndex ;
61
+ this.tabStaff = {
62
+ clef: {
63
+ type: 'TAB'
64
+ }
65
+ };
66
+ this.tabSize = (plugin.linePitch * plugin.nbLines);
67
+ }
68
+
69
+ function islastTabInStaff(index, staffGroup) {
70
+ if (staffGroup[index].isTabStaff) {
71
+ if (index === staffGroup.length - 1) return true;
72
+ if (staffGroup[index + 1].isTabStaff) {
73
+ return false;
74
+ } else {
75
+ return true;
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+
81
+ function getStaffNumbers(staffs) {
82
+ var nbStaffs = 0;
83
+ for (var ii = 0; ii < staffs.length; ii++) {
84
+ if (!staffs[ii].isTabStaff) {
85
+ nbStaffs++;
86
+ }
87
+ }
88
+ return nbStaffs;
89
+ }
90
+
91
+ function getParentStaffIndex(staffs, index) {
92
+ for (var ii = index; ii >= 0; ii--) {
93
+ if (!staffs[ii].isTabStaff) {
94
+ return ii;
95
+ }
96
+ }
97
+ return -1;
98
+ }
99
+
100
+
101
+ function linkStaffAndTabs(staffs) {
102
+ for (var ii = 0; ii < staffs.length; ii++) {
103
+ if (staffs[ii].isTabStaff) {
104
+ // link to parent staff
105
+ var parentIndex = getParentStaffIndex(staffs, ii);
106
+ staffs[ii].hasStaff = staffs[parentIndex];
107
+ if (!staffs[parentIndex].hasTab) staffs[parentIndex].hasTab = [];
108
+ staffs[parentIndex].hasTab.push(staffs[ii]);
109
+ }
110
+ }
111
+ }
112
+
113
+ function isMultiVoiceSingleStaff(staffs , parent) {
114
+ if ( getStaffNumbers(staffs) === 1) {
115
+ if (parent.voices.length > 1) return true;
116
+ }
117
+ return false;
118
+ }
119
+
120
+
121
+ function getNextTabPos(self,staffGroup) {
122
+ var tabIndex = self.staffIndex;
123
+ var startIndex = 0;
124
+ var handledVoices = 0;
125
+ var inProgress = true;
126
+ var nbVoices = 0;
127
+ while (inProgress) {
128
+ //for (var ii = 0; ii < staffGroup.length; ii++) {
129
+ if (!staffGroup[startIndex])
130
+ return -1;
131
+ if (!staffGroup[startIndex].isTabStaff) {
132
+ nbVoices = staffGroup[startIndex].voices.length; // get number of staff voices
133
+ }
134
+ if (staffGroup[startIndex].isTabStaff) {
135
+ handledVoices++;
136
+ if (islastTabInStaff(startIndex, staffGroup)) {
137
+ if (handledVoices < nbVoices) return startIndex + 1;
138
+ }
139
+ } else {
140
+ handledVoices = 0;
141
+ if (startIndex >= tabIndex) {
142
+ if (startIndex+1 == staffGroup.length) return startIndex +1;
143
+ if (!staffGroup[startIndex + 1].isTabStaff) return startIndex + 1;
144
+ }
145
+ }
146
+ startIndex++;
147
+ // out of space case
148
+ if (startIndex > staffGroup.length) return -1;
149
+ }
150
+ }
151
+
152
+ function getLastStaff(staffs, lastTab) {
153
+ for (var ii = lastTab; ii >= 0 ; ii-- ) {
154
+ if (!staffs[ii].isTabStaff) {
155
+ return staffs[ii];
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+
161
+ function checkVoiceKeySig(voices, ii) {
162
+ var curVoice = voices[ii];
163
+ // on multivoice multistaff only the first voice has key signature
164
+ // folling consecutive do not have one => we should provide the first voice key sig back then
165
+ var elem0 = curVoice.children[0].abcelem;
166
+ if (elem0.el_type === 'clef') return null;
167
+ if (ii == 0) {
168
+ // not found => clef=none case
169
+ return 'none';
170
+ }
171
+ return voices[ii-1].children[0];
172
+ }
173
+
174
+ TabRenderer.prototype.doLayout = function () {
175
+ var staffs = this.line.staff;
176
+ if (staffs) {
177
+ // give up on staffline=0 in key
178
+ var firstStaff = staffs[0];
179
+ if (firstStaff) {
180
+ if (firstStaff.clef) {
181
+ if (firstStaff.clef.stafflines == 0) {
182
+ this.plugin._super.setError("No tablatures when stafflines=0");
183
+ return;
184
+ }
185
+ }
186
+ }
187
+ staffs.splice(
188
+ staffs.length, 0,
189
+ this.tabStaff
190
+ );
191
+ }
192
+ var staffGroup = this.line.staffGroup;
193
+
194
+ var voices = staffGroup.voices;
195
+ var firstVoice = voices[0];
196
+ // take lyrics into account if any
197
+ var lyricsHeight = getLyricHeight(firstVoice);
198
+ var padd = 3;
199
+ var prevIndex = this.staffIndex;
200
+ var previousStaff = staffGroup.staffs[prevIndex];
201
+ var tabTop = previousStaff.top + padd + lyricsHeight;
202
+ if (previousStaff.isTabStaff) {
203
+ tabTop = previousStaff.top;
204
+ }
205
+ var staffGroupInfos = {
206
+ bottom: -1,
207
+ isTabStaff: true,
208
+ specialY: initSpecialY(),
209
+ lines: this.plugin.nbLines,
210
+ linePitch: this.plugin.linePitch,
211
+ dy: 0.15,
212
+ top: tabTop,
213
+ };
214
+ var nextTabPos = getNextTabPos(this,staffGroup.staffs);
215
+ if (nextTabPos === -1)
216
+ return;
217
+ staffGroupInfos.parentIndex = nextTabPos - 1;
218
+ staffGroup.staffs.splice(nextTabPos, 0, staffGroupInfos);
219
+ // staffGroup.staffs.push(staffGroupInfos);
220
+ staffGroup.height += this.tabSize + padd;
221
+ var parentStaff = getLastStaff(staffGroup.staffs, nextTabPos);
222
+ var nbVoices = 1;
223
+ if (isMultiVoiceSingleStaff(staffGroup.staffs,parentStaff)) {
224
+ nbVoices = parentStaff.voices.length;
225
+ }
226
+ // build from staff
227
+ this.tabStaff.voices = [];
228
+ for (var ii = 0; ii < nbVoices; ii++) {
229
+ var tabVoice = new VoiceElement(0, 0);
230
+ var nameHeight = buildTabName(this, tabVoice) / spacing.STEP;
231
+ staffGroup.staffs[this.staffIndex].top += nameHeight;
232
+ staffGroup.height += nameHeight * spacing.STEP;
233
+ tabVoice.staff = staffGroupInfos;
234
+ voices.splice(voices.length, 0, tabVoice);
235
+ var keySig = checkVoiceKeySig(voices, ii + this.staffIndex);
236
+ this.tabStaff.voices[ii] = [];
237
+ this.absolutes.build(this.plugin, voices, this.tabStaff.voices[ii], ii , this.staffIndex ,keySig);
238
+ }
239
+ linkStaffAndTabs(staffGroup.staffs); // crossreference tabs and staff
240
+ };
241
+
242
+
243
+ module.exports = TabRenderer;
@@ -0,0 +1,110 @@
1
+ /**
2
+ *
3
+ * generic transposer
4
+ *
5
+ */
6
+ var TabNote = require('./instruments/tab-note');
7
+
8
+
9
+
10
+ function buildAccEquiv(acc,note) {
11
+ var equiv = note.getAccidentalEquiv();
12
+ if (acc.note.toUpperCase() == equiv.name.toUpperCase()) {
13
+ equiv.isSharp = false;
14
+ equiv.isFlat = false;
15
+ return equiv;
16
+ }
17
+ return note;
18
+ }
19
+
20
+ function adjustNoteToKey(acc, note) {
21
+ if (acc.acc == 'sharp') {
22
+ if (note.isFlat) {
23
+ return buildAccEquiv(acc, note);
24
+ } else if (note.isSharp) {
25
+ if (acc.note.toUpperCase() == note.name.toUpperCase()) {
26
+ note.isSharp = false;
27
+ note.isKeySharp = true;
28
+ } else {
29
+ if (acc.note.toUpperCase() == note.name.toUpperCase()) {
30
+ note.natural = true;
31
+ }
32
+ }
33
+ }
34
+ } else if (acc.acc == 'flat') {
35
+ if (note.isSharp) {
36
+ return buildAccEquiv(acc, note);
37
+ } else if (note.isFlat) {
38
+ if (acc.note.toUpperCase() == note.name.toUpperCase()) {
39
+ note.isFlat = false;
40
+ note.isKeyFlat = true;
41
+ }
42
+ } else {
43
+ if (acc.note.toUpperCase() == note.name.toUpperCase()) {
44
+ note.natural = true;
45
+ }
46
+ }
47
+ }
48
+ return note;
49
+ }
50
+
51
+
52
+ function replaceNote(self, newNote, start, end) {
53
+ if (self.lastEnd) {
54
+ while (start > self.lastEnd) {
55
+ self.updatedSrc.push(self.abcSrc[self.lastEnd]);
56
+ self.lastEnd++;
57
+ }
58
+ }
59
+ var nNote = newNote.split('');
60
+ for (var ii = 0; ii < nNote.length; ii++) {
61
+ self.updatedSrc.push(nNote[ii]);
62
+ }
63
+ var curPos = start + ii;
64
+ while (end >= curPos) {
65
+ self.updatedSrc.push(nNote[curPos]);
66
+ curPos++;
67
+ }
68
+ self.lastEnd = end;
69
+ }
70
+
71
+
72
+ function checkKeys(self, note) {
73
+ var accs = self.transposedKey;
74
+ for (var ii = 0; ii < accs.length; ii++) {
75
+ note = adjustNoteToKey(accs[ii], note);
76
+ }
77
+ return note;
78
+ }
79
+
80
+ Transposer.prototype.transposeNote = function (note) {
81
+ var returned = note;
82
+ var curNote = new TabNote.TabNote(returned.name);
83
+ if (this.transposeBy > 0) {
84
+ for (var ii = 0; ii < this.transposeBy; ii++) {
85
+ curNote = checkKeys(this,curNote.nextNote());
86
+ }
87
+
88
+ } else if ( this.transposeBy < 0) {
89
+ for (var jj = this.transposeBy; jj < 0; jj++) {
90
+ curNote = checkKeys(this,curNote.prevNote());
91
+ }
92
+ }
93
+ returned.name = curNote.emit();
94
+ return returned;
95
+ };
96
+
97
+ Transposer.prototype.upgradeSource = function (note, startChar, endChar ) {
98
+ var n = new TabNote.TabNote(note.name);
99
+ var newNote = n.emit();
100
+ replaceNote(this, newNote, startChar, endChar-1);
101
+ };
102
+
103
+ function Transposer(transposedKey , transposeBy ) {
104
+ this.transposeBy = transposeBy;
105
+ this.transposedKey = transposedKey;
106
+ this.lastEnd = this.kEnd+1;
107
+ }
108
+
109
+
110
+ module.exports = Transposer;