abcjs 6.4.1 → 6.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE.md +1 -1
  2. package/RELEASE.md +46 -0
  3. package/dist/abcjs-basic-min.js +2 -2
  4. package/dist/abcjs-basic-min.js.LICENSE +1 -1
  5. package/dist/abcjs-basic.js +1271 -1179
  6. package/dist/abcjs-basic.js.map +1 -1
  7. package/dist/abcjs-plugin-min.js +2 -2
  8. package/dist/abcjs-plugin-min.js.LICENSE +1 -1
  9. package/index.js +1 -1
  10. package/license.js +1 -1
  11. package/package.json +1 -1
  12. package/plugin.js +1 -1
  13. package/src/api/abc_tunebook.js +1 -2
  14. package/src/api/abc_tunebook_svg.js +0 -1
  15. package/src/data/abc_tune.js +2 -0
  16. package/src/midi/abc_midi_create.js +22 -7
  17. package/src/parse/abc_common.js +3 -11
  18. package/src/parse/abc_parse.js +1 -1
  19. package/src/parse/abc_parse_directive.js +44 -3
  20. package/src/parse/abc_parse_header.js +6 -4
  21. package/src/parse/abc_parse_key_voice.js +10 -6
  22. package/src/parse/abc_parse_music.js +54 -22
  23. package/src/parse/tune-builder.js +675 -643
  24. package/src/synth/abc_midi_flattener.js +3 -1
  25. package/src/synth/abc_midi_sequencer.js +18 -3
  26. package/src/synth/chord-track.js +90 -18
  27. package/src/synth/create-synth-control.js +1 -2
  28. package/src/tablatures/abc_tablatures.js +184 -0
  29. package/src/tablatures/instruments/string-patterns.js +266 -268
  30. package/src/tablatures/instruments/string-tablature.js +38 -35
  31. package/src/tablatures/instruments/tab-note.js +186 -181
  32. package/src/tablatures/instruments/tab-notes.js +30 -35
  33. package/src/tablatures/instruments/tab-string.js +43 -25
  34. package/src/tablatures/render/tab-absolute-elements.js +303 -0
  35. package/src/tablatures/render/tab-renderer.js +244 -0
  36. package/src/test/abc_parser_lint.js +2 -3
  37. package/src/write/creation/abstract-engraver.js +1 -1
  38. package/src/write/creation/elements/tie-element.js +26 -0
  39. package/src/write/engraver-controller.js +1 -1
  40. package/src/write/layout/set-upper-and-lower-elements.js +8 -0
  41. package/test.js +1 -1
  42. package/types/index.d.ts +2 -2
  43. package/version.js +1 -1
  44. package/src/api/abc_tablatures.js +0 -184
  45. package/src/tablatures/instruments/tab-string-patterns.js +0 -23
  46. package/src/tablatures/tab-absolute-elements.js +0 -301
  47. package/src/tablatures/tab-common.js +0 -29
  48. package/src/tablatures/tab-renderer.js +0 -259
@@ -1,184 +0,0 @@
1
- /*
2
- * Tablature Plugins
3
- * tablature are defined dynamically and registered inside abcjs
4
- * by calling abcTablatures.register(plugin)
5
- * where plugin represents a plugin instance
6
- *
7
- */
8
- var StringTablature = require('../tablatures/instruments/tab-string');
9
-
10
- /* extend the table below when adding a new instrument plugin */
11
-
12
- // Existing tab classes
13
- var pluginTab = {
14
- 'violin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
15
- 'fiddle': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
16
- 'mandolin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
17
- 'guitar': { name: 'StringTab', defaultTuning: ['E,', 'A,', 'D', 'G' , 'B' , 'e'], isTabBig: true, tabSymbolOffset: 0},
18
- 'fiveString': { name: 'StringTab', defaultTuning: ['C,', 'G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: -.95},
19
- };
20
-
21
- var abcTablatures = {
22
-
23
- inited: false,
24
- plugins: {},
25
-
26
-
27
- /**
28
- * to be called once per plugin for registration
29
- * @param {*} plugin
30
- */
31
- register: function (plugin) {
32
- var name = plugin.name;
33
- var tablature = plugin.tablature;
34
- this.plugins[name] = tablature;
35
- },
36
-
37
- setError: function (tune, msg) {
38
- if (tune.warnings) {
39
- tune.warning.push(msg);
40
- } else {
41
- tune.warnings = [msg];
42
- }
43
- },
44
-
45
- /**
46
- * handle params for current processed score
47
- * @param {*} tune current tune
48
- * @param {*} tuneNumber number in tune list
49
- * @param {*} params params to be processed for tablature
50
- * @return prepared tablatures plugin instances for current tune
51
- */
52
- preparePlugins: function (tune, tuneNumber, params) {
53
- var returned = null;
54
- var nbPlugins = 0;
55
- if (params.tablature) {
56
- // validate requested plugins
57
- var tabs = params.tablature;
58
- returned = [];
59
- for (var ii = 0; ii < tabs.length; ii++) {
60
- var args = tabs[ii];
61
- var instrument = args['instrument'];
62
- if (instrument == null) {
63
- this.setError(tune, "tablature 'instrument' is missing");
64
- return returned;
65
- }
66
- var tabName = pluginTab[instrument];
67
- var plugin = null;
68
- if (tabName) {
69
- plugin = this.plugins[tabName.name];
70
- }
71
- if (plugin) {
72
- if (params.visualTranspose != 0) {
73
- // populate transposition request to tabs
74
- args.visualTranspose = params.visualTranspose;
75
- }
76
- args.abcSrc = params.tablature.abcSrc;
77
- var pluginInstance = {
78
- classz: plugin,
79
- tuneNumber: tuneNumber,
80
- params: args,
81
- instance: null,
82
- tabType: tabName,
83
- };
84
- // proceed with tab plugin init
85
- // plugin.init(tune, tuneNumber, args, ii);
86
- returned.push(pluginInstance);
87
- nbPlugins++;
88
- } else if (instrument === '') {
89
- // create a placeholder - there is no tab for this staff
90
- returned.push(null)
91
- } else {
92
- // unknown tab plugin
93
- //this.emit_error('Undefined tablature plugin: ' + tabName)
94
- this.setError(tune, 'Undefined tablature plugin: ' + instrument);
95
- return returned;
96
- }
97
- }
98
- }
99
- return returned;
100
- },
101
-
102
- /**
103
- * Call requested plugin
104
- * @param {*} renderer
105
- * @param {*} abcTune
106
- */
107
- layoutTablatures: function layoutTablatures(renderer, abcTune) {
108
- var tabs = abcTune.tablatures;
109
-
110
- // chack tabs request for each staffs
111
- var staffLineCount = 0;
112
-
113
- // Clear the suppression flag
114
- if (tabs && (tabs.length > 0)){
115
- var nTabs = tabs.length;
116
- for (var kk=0;kk<nTabs;++kk){
117
- if (tabs[kk] && tabs[kk].params.firstStaffOnly){
118
- tabs[kk].params.suppress = false;
119
- }
120
- }
121
- }
122
-
123
- for (var ii = 0; ii < abcTune.lines.length; ii++) {
124
- var line = abcTune.lines[ii];
125
-
126
- if (line.staff){
127
- staffLineCount++;
128
- }
129
-
130
- // MAE 27Nov2023
131
- // If tab param "firstStaffOnly", remove the tab label after the first staff
132
- if (staffLineCount > 1){
133
- if (tabs && (tabs.length > 0)){
134
- var nTabs = tabs.length;
135
- for (var kk=0;kk<nTabs;++kk){
136
- if (tabs[kk].params.firstStaffOnly){
137
- // Set the staff draw suppression flag
138
- tabs[kk].params.suppress = true;
139
- }
140
- }
141
- }
142
- }
143
-
144
- var curStaff = line.staff;
145
- if (curStaff) {
146
- var maxStaves = curStaff.length
147
- for (var jj = 0; jj < curStaff.length; jj++) {
148
-
149
- if (tabs[jj] && jj < maxStaves) {
150
- // tablature requested for staff
151
- var tabPlugin = tabs[jj];
152
- if (tabPlugin.instance == null) {
153
- tabPlugin.instance = new tabPlugin.classz();
154
- // plugin.init(tune, tuneNumber, args, ii);
155
- // call initer first
156
- tabPlugin.instance.init(abcTune,
157
- tabPlugin.tuneNumber,
158
- tabPlugin.params,
159
- jj,
160
- tabPlugin.tabType
161
- );
162
- }
163
- // render next
164
- tabPlugin.instance.render(renderer, line, jj);
165
- }
166
- }
167
- }
168
- }
169
- },
170
-
171
- /**
172
- * called once internally to register internal plugins
173
- */
174
- init: function () {
175
- // just register plugin hosted by abcjs
176
- if (!this.inited) {
177
- this.register(new StringTablature());
178
- this.inited = true;
179
- }
180
- }
181
- };
182
-
183
-
184
- module.exports = abcTablatures ;
@@ -1,23 +0,0 @@
1
- var StringPatterns = require('./string-patterns');
2
-
3
- function TabStringPatterns(plugin, defaultTuning) {
4
- this.tuning = plugin._super.params.tuning;
5
- if (!this.tuning) {
6
- this.tuning = defaultTuning;
7
- }
8
- plugin.tuning = this.tuning;
9
- this.strings = new StringPatterns(plugin);
10
- }
11
-
12
- TabStringPatterns.prototype.notesToNumber = function (notes, graces) {
13
- var converter = this.strings;
14
- return converter.notesToNumber(notes, graces);
15
- };
16
-
17
- TabStringPatterns.prototype.stringToPitch = function (stringNumber) {
18
- var converter = this.strings;
19
- return converter.stringToPitch(stringNumber);
20
- };
21
-
22
-
23
- module.exports = TabStringPatterns;
@@ -1,301 +0,0 @@
1
- /**
2
- * Tablature Absolute elements factory
3
- */
4
- var AbsoluteElement = require('../write/creation/elements/absolute-element');
5
- var RelativeElement = require('../write/creation/elements/relative-element');
6
-
7
- function isObject(a) { return a != null && a.constructor === Object; }
8
- function cloneObject(dest, src) {
9
- for (var prop in src) {
10
- if (src.hasOwnProperty(prop)) {
11
- if (!(Array.isArray(src[prop]) || isObject(src[prop]))) {
12
- dest[prop] = src[prop];
13
- }
14
- }
15
- }
16
- }
17
-
18
- function cloneAbsolute(absSrc) {
19
- var returned = new AbsoluteElement('', 0, 0, '', 0);
20
- cloneObject(returned, absSrc);
21
- returned.top = 0;
22
- returned.bottom = -1;
23
- if (absSrc.abcelem) {
24
- returned.abcelem = {};
25
- cloneObject(returned.abcelem, absSrc.abcelem);
26
- if (returned.abcelem.el_type === "note")
27
- returned.abcelem.el_type = 'tabNumber';
28
- }
29
- // TODO-PER: This fixes the classes because the element isn't created at the right time.
30
- absSrc.cloned = returned
31
- return returned;
32
- }
33
-
34
- function cloneAbsoluteAndRelatives(absSrc, plugin) {
35
- var returned = cloneAbsolute(absSrc);
36
- if (plugin) {
37
- var children = absSrc.children;
38
- // proceed with relative as well
39
- var first = true;
40
- for (var ii = 0; ii < children.length; ii++) {
41
- var child = children[ii];
42
- var relative = new RelativeElement('', 0, 0, 0, '');
43
- cloneObject(relative, child);
44
- first = plugin.tablature.setRelative(child, relative, first);
45
- returned.children.push(relative);
46
- }
47
- }
48
- return returned;
49
- }
50
-
51
- function buildTabAbsolute(plugin, absX, relX) {
52
- var tabIcon = 'tab.tiny';
53
- var tabYPos = 7.5;
54
- if (plugin.isTabBig) {
55
- tabIcon = 'tab.big';
56
- tabYPos = 10;
57
- }
58
- var element = {
59
- el_type: "tab",
60
- icon: tabIcon,
61
- Ypos: tabYPos
62
- };
63
-
64
- // Offset the TAB symbol position if specified in the tab description
65
- tabYPos += plugin.tabSymbolOffset;
66
-
67
- // For tablature like whistle tab where you want the TAB symbol hidden
68
- if (!plugin.hideTabSymbol){
69
-
70
- var tabAbsolute = new AbsoluteElement(element, 0, 0, "symbol", 0);
71
- tabAbsolute.x = absX;
72
- var tabRelative = new RelativeElement(tabIcon, 0, 0, 7.5, "tab");
73
- tabRelative.x = relX;
74
- tabAbsolute.children.push(tabRelative);
75
- if (tabAbsolute.abcelem.el_type == 'tab') {
76
- tabRelative.pitch = tabYPos;
77
- }
78
-
79
- }
80
- return tabAbsolute;
81
- }
82
-
83
- function lyricsDim(abs) {
84
- if (abs.extra) {
85
- for (var ii = 0; ii < abs.extra.length; ii++) {
86
- var extra = abs.extra[ii];
87
- if (extra.type == 'lyric') {
88
- return {
89
- bottom: extra.bottom,
90
- height: extra.height
91
- };
92
- }
93
- }
94
- }
95
- return null;
96
- }
97
- function TabAbsoluteElements() {
98
- this.accidentals = null;
99
- }
100
-
101
- function getInitialStaffSize(staffGroup) {
102
- var returned = 0;
103
- for (var ii = 0; ii < staffGroup.length; ii++) {
104
- if (!staffGroup[ii].tabNameInfos) returned++;
105
- }
106
- return returned;
107
- }
108
-
109
- function buildRelativeTabNote(plugin, relX, def, curNote, isGrace) {
110
- var strNote = curNote.num;
111
- if (curNote.note.quarter != null) {
112
- // add tab quarter => needs to string conversion then
113
- strNote = strNote.toString();
114
- strNote += curNote.note.quarter;
115
- }
116
- var pitch = plugin.semantics.stringToPitch(curNote.str);
117
- def.notes.push({ num: strNote, str: curNote.str, pitch: curNote.note.emit() });
118
- var opt = {
119
- type: 'tabNumber'
120
- };
121
- var tabNoteRelative = new RelativeElement(
122
- strNote, 0, 0, pitch+0.3, opt);
123
- tabNoteRelative.x = relX;
124
- tabNoteRelative.isGrace = isGrace;
125
- tabNoteRelative.isAltered = curNote.note.isAltered;
126
- return tabNoteRelative;
127
- }
128
-
129
- function getXGrace(abs, index) {
130
- var found = 0;
131
- if (abs.extra) {
132
- for (var ii = 0; ii < abs.extra.length; ii++) {
133
- if (abs.extra[ii].c.indexOf('noteheads') >= 0) {
134
- if (found === index) {
135
- return abs.extra[ii].x + abs.extra[ii].w/2;
136
- } else {
137
- found++;
138
- }
139
- }
140
- }
141
- }
142
- return -1;
143
- }
144
-
145
- function graceInRest( absElem ) {
146
- if (absElem.abcelem) {
147
- var elem = absElem.abcelem;
148
- if (elem.rest) {
149
- return elem.gracenotes;
150
- }
151
- }
152
- return null;
153
- }
154
-
155
- function convertToNumber(plugin, pitches, graceNotes) {
156
- var tabPos = plugin.semantics.notesToNumber(pitches, graceNotes);
157
- if (tabPos.error) {
158
- plugin._super.setError(tabPos.error);
159
- return tabPos; // give up on error here
160
- }
161
- if (tabPos.graces && tabPos.notes) {
162
- // add graces to last note in notes
163
- var posNote = tabPos.notes.length - 1;
164
- tabPos.notes[posNote].graces = tabPos.graces;
165
- }
166
- return tabPos;
167
- }
168
-
169
- function buildGraceRelativesForRest(plugin,abs,absChild,graceNotes,tabVoice) {
170
- for (var mm = 0; mm < graceNotes.length; mm++) {
171
- var defGrace = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [], grace: true };
172
- var graceX = getXGrace(absChild, mm);
173
- var curGrace = graceNotes[mm];
174
- var tabGraceRelative = buildRelativeTabNote(plugin, graceX, defGrace, curGrace, true);
175
- abs.children.push(tabGraceRelative);
176
- tabVoice.push(defGrace);
177
- }
178
- }
179
-
180
- /**
181
- * Build tab absolutes by scanning current staff line absolute array
182
- * @param {*} staffAbsolute
183
- */
184
- TabAbsoluteElements.prototype.build = function (plugin,
185
- staffAbsolute,
186
- tabVoice,
187
- voiceIndex,
188
- staffIndex,
189
- keySig,
190
- tabVoiceIndex ) {
191
- var staffSize = getInitialStaffSize(staffAbsolute);
192
- var source = staffAbsolute[staffIndex+voiceIndex];
193
- var dest = staffAbsolute[tabVoiceIndex];
194
- var tabPos = null;
195
- var defNote = null;
196
- if (source.children[0].abcelem.el_type != 'clef') {
197
- // keysig missing => provide one for tabs
198
- if (keySig != 'none') {
199
- source.children.splice(0, 0, keySig);
200
- }
201
- }
202
- for (var ii = 0; ii < source.children.length; ii++) {
203
- var absChild = source.children[ii];
204
- var absX = absChild.x;
205
- var relX = absX;
206
- // if (absChild.children.length > 0) {
207
- // relX = absChild.children[0].x;
208
- // }
209
- if ( (absChild.isClef) ) {
210
- dest.children.push(buildTabAbsolute(plugin, absX, relX));
211
- if (absChild.abcelem.type.indexOf('-8') >= 0) plugin.semantics.strings.clefTranspose = -12
212
- if (absChild.abcelem.type.indexOf('+8') >= 0) plugin.semantics.strings.clefTranspose = 12
213
- }
214
- switch (absChild.type) {
215
- case 'staff-extra key-signature':
216
- // refresh key accidentals
217
- this.accidentals = absChild.abcelem.accidentals;
218
- plugin.semantics.strings.accidentals = this.accidentals;
219
- break;
220
- case 'bar':
221
- plugin.semantics.strings.measureAccidentals = {}
222
- var lastBar = false;
223
- if (ii === source.children.length-1) {
224
- // used for final line bar drawing
225
- // for multi tabs / multi staves
226
- lastBar = true;
227
- }
228
- var cloned = cloneAbsoluteAndRelatives(absChild, plugin);
229
- if (cloned.abcelem.barNumber) {
230
- delete cloned.abcelem.barNumber;
231
- for (var bn = 0; bn < cloned.children.length; bn++) {
232
- if (cloned.children[bn].type === "barNumber" ) {
233
- cloned.children.splice(bn, 1);
234
- break;
235
- }
236
- }
237
- }
238
- cloned.abcelem.lastBar = lastBar;
239
- dest.children.push(cloned);
240
- tabVoice.push({
241
- el_type: absChild.abcelem.el_type,
242
- type: absChild.abcelem.type,
243
- endChar: absChild.abcelem.endChar,
244
- startChar: absChild.abcelem.startChar,
245
- abselem: cloned
246
- });
247
- break;
248
- case 'rest':
249
- var restGraces = graceInRest(absChild);
250
- if (restGraces) {
251
- // to number conversion
252
- tabPos = convertToNumber(plugin, null, restGraces);
253
- if (tabPos.error) return;
254
- // build relative for grace
255
- defGrace = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [], grace: true };
256
- buildGraceRelativesForRest(plugin, abs, absChild, tabPos.graces, tabVoice);
257
- }
258
- break;
259
- case 'note':
260
- var abs = cloneAbsolute(absChild);
261
- abs.x = absChild.heads[0].x + absChild.heads[0].w / 2; // center the number
262
- abs.lyricDim = lyricsDim(absChild);
263
- var pitches = absChild.abcelem.pitches;
264
- var graceNotes = absChild.abcelem.gracenotes;
265
- abs.type = 'tabNumber';
266
- // to number conversion
267
- tabPos = convertToNumber(plugin, pitches, graceNotes);
268
- if (tabPos.error) return;
269
- if (tabPos.graces) {
270
- // add graces to last note in notes
271
- var posNote = tabPos.notes.length - 1;
272
- tabPos.notes[posNote].graces = tabPos.graces;
273
- }
274
- // build relative
275
- defNote = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [] };
276
- for (var ll = 0; ll < tabPos.notes.length; ll++) {
277
- var curNote = tabPos.notes[ll];
278
- if (curNote.graces) {
279
- for (var mm = 0; mm < curNote.graces.length; mm++) {
280
- var defGrace = { el_type: "note", startChar: absChild.abcelem.startChar, endChar: absChild.abcelem.endChar, notes: [], grace: true };
281
- var graceX = getXGrace(absChild , mm);
282
- var curGrace = curNote.graces[mm];
283
- var tabGraceRelative = buildRelativeTabNote(plugin, graceX, defGrace, curGrace, true);
284
- abs.children.push(tabGraceRelative);
285
- tabVoice.push(defGrace);
286
- }
287
- }
288
- var tabNoteRelative = buildRelativeTabNote(plugin, abs.x+absChild.heads[ll].dx, defNote, curNote, false);
289
- abs.children.push(tabNoteRelative);
290
- }
291
- if (defNote.notes.length > 0) {
292
- defNote.abselem = abs;
293
- tabVoice.push(defNote);
294
- dest.children.push(abs);
295
- }
296
- break;
297
- }
298
- }
299
- };
300
-
301
- module.exports = TabAbsoluteElements;
@@ -1,29 +0,0 @@
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;