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.
- package/LICENSE.md +1 -1
- package/RELEASE.md +46 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic-min.js.LICENSE +1 -1
- package/dist/abcjs-basic.js +1271 -1179
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/dist/abcjs-plugin-min.js.LICENSE +1 -1
- package/index.js +1 -1
- package/license.js +1 -1
- package/package.json +1 -1
- package/plugin.js +1 -1
- package/src/api/abc_tunebook.js +1 -2
- package/src/api/abc_tunebook_svg.js +0 -1
- package/src/data/abc_tune.js +2 -0
- package/src/midi/abc_midi_create.js +22 -7
- package/src/parse/abc_common.js +3 -11
- package/src/parse/abc_parse.js +1 -1
- package/src/parse/abc_parse_directive.js +44 -3
- package/src/parse/abc_parse_header.js +6 -4
- package/src/parse/abc_parse_key_voice.js +10 -6
- package/src/parse/abc_parse_music.js +54 -22
- package/src/parse/tune-builder.js +675 -643
- package/src/synth/abc_midi_flattener.js +3 -1
- package/src/synth/abc_midi_sequencer.js +18 -3
- package/src/synth/chord-track.js +90 -18
- package/src/synth/create-synth-control.js +1 -2
- package/src/tablatures/abc_tablatures.js +184 -0
- package/src/tablatures/instruments/string-patterns.js +266 -268
- package/src/tablatures/instruments/string-tablature.js +38 -35
- package/src/tablatures/instruments/tab-note.js +186 -181
- package/src/tablatures/instruments/tab-notes.js +30 -35
- package/src/tablatures/instruments/tab-string.js +43 -25
- package/src/tablatures/render/tab-absolute-elements.js +303 -0
- package/src/tablatures/render/tab-renderer.js +244 -0
- package/src/test/abc_parser_lint.js +2 -3
- package/src/write/creation/abstract-engraver.js +1 -1
- package/src/write/creation/elements/tie-element.js +26 -0
- package/src/write/engraver-controller.js +1 -1
- package/src/write/layout/set-upper-and-lower-elements.js +8 -0
- package/test.js +1 -1
- package/types/index.d.ts +2 -2
- package/version.js +1 -1
- package/src/api/abc_tablatures.js +0 -184
- package/src/tablatures/instruments/tab-string-patterns.js +0 -23
- package/src/tablatures/tab-absolute-elements.js +0 -301
- package/src/tablatures/tab-common.js +0 -29
- package/src/tablatures/tab-renderer.js +0 -259
|
@@ -209,6 +209,7 @@ var pitchesToPerc = require('./pitches-to-perc');
|
|
|
209
209
|
case "chordprog":
|
|
210
210
|
case "bassvol":
|
|
211
211
|
case "chordvol":
|
|
212
|
+
case "gchordbars":
|
|
212
213
|
chordTrack.paramChange(element)
|
|
213
214
|
break
|
|
214
215
|
default:
|
|
@@ -347,7 +348,8 @@ var pitchesToPerc = require('./pitches-to-perc');
|
|
|
347
348
|
return 0;
|
|
348
349
|
|
|
349
350
|
var volume;
|
|
350
|
-
|
|
351
|
+
// MAE 21 Jun 2024 - This previously wasn't allowing zero volume to be applied
|
|
352
|
+
if (nextVolume != undefined) {
|
|
351
353
|
volume = nextVolume;
|
|
352
354
|
nextVolume = undefined;
|
|
353
355
|
} else if (!doBeatAccents) {
|
|
@@ -315,7 +315,7 @@ var parseCommon = require("../parse/abc_common");
|
|
|
315
315
|
if (!e) e = voices[voiceNumber].length; // If there wasn't a first ending marker, then we copy everything.
|
|
316
316
|
// duplicate each of the elements - this has to be a deep copy.
|
|
317
317
|
for (var z = s; z < e; z++) {
|
|
318
|
-
var item =
|
|
318
|
+
var item = Object.assign({},voices[voiceNumber][z]);
|
|
319
319
|
if (item.pitches)
|
|
320
320
|
item.pitches = parseCommon.cloneArray(item.pitches);
|
|
321
321
|
voices[voiceNumber].push(item);
|
|
@@ -389,12 +389,27 @@ var parseCommon = require("../parse/abc_common");
|
|
|
389
389
|
break;
|
|
390
390
|
case "swing":
|
|
391
391
|
case "gchord":
|
|
392
|
-
case "bassprog":
|
|
393
|
-
case "chordprog":
|
|
394
392
|
case "bassvol":
|
|
395
393
|
case "chordvol":
|
|
396
394
|
voices[voiceNumber].push({ el_type: elem.cmd, param: elem.params[0] });
|
|
397
395
|
break;
|
|
396
|
+
|
|
397
|
+
case "bassprog": // MAE 22 May 2024
|
|
398
|
+
case "chordprog": // MAE 22 May 2024
|
|
399
|
+
voices[voiceNumber].push({
|
|
400
|
+
el_type: elem.cmd,
|
|
401
|
+
value: elem.params[0],
|
|
402
|
+
octaveShift: elem.params[1]
|
|
403
|
+
});
|
|
404
|
+
break;
|
|
405
|
+
|
|
406
|
+
// MAE 23 Jun 2024
|
|
407
|
+
case "gchordbars":
|
|
408
|
+
voices[voiceNumber].push({
|
|
409
|
+
el_type: elem.cmd,
|
|
410
|
+
param: elem.params[0]
|
|
411
|
+
});
|
|
412
|
+
break;
|
|
398
413
|
default:
|
|
399
414
|
console.log("MIDI seq: midi cmd not handled: ", elem.cmd, elem);
|
|
400
415
|
}
|
package/src/synth/chord-track.js
CHANGED
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
//
|
|
18
18
|
// If there is any note in the melody that has a rhythm head, then assume the melody controls the rhythm, so there is no chord added for that entire measure.
|
|
19
19
|
|
|
20
|
-
var parseCommon = require("../parse/abc_common");
|
|
21
|
-
|
|
22
20
|
var ChordTrack = function ChordTrack(numVoices, chordsOff, midiOptions, meter) {
|
|
23
21
|
this.chordTrack = [];
|
|
24
22
|
this.chordTrackFinished = false;
|
|
@@ -34,12 +32,24 @@ var ChordTrack = function ChordTrack(numVoices, chordsOff, midiOptions, meter) {
|
|
|
34
32
|
this.meter = meter;
|
|
35
33
|
this.tempoChangeFactor = 1;
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
this.
|
|
35
|
+
// MAE 17 Jun 2024 - To allow for bass and chord instrument octave shifts
|
|
36
|
+
this.bassInstrument = midiOptions.bassprog && midiOptions.bassprog.length >= 1 ? midiOptions.bassprog[0] : 0;
|
|
37
|
+
this.chordInstrument = midiOptions.chordprog && midiOptions.chordprog.length >= 1 ? midiOptions.chordprog[0] : 0;
|
|
38
|
+
|
|
39
|
+
// MAE For octave shifted bass and chords
|
|
40
|
+
this.bassOctaveShift = midiOptions.bassprog && midiOptions.bassprog.length === 2 ? midiOptions.bassprog[1] : 0;
|
|
41
|
+
this.chordOctaveShift = midiOptions.chordprog && midiOptions.chordprog.length === 2 ? midiOptions.chordprog[1] : 0;
|
|
42
|
+
|
|
39
43
|
this.boomVolume = midiOptions.bassvol && midiOptions.bassvol.length === 1 ? midiOptions.bassvol[0] : 64;
|
|
40
44
|
this.chickVolume = midiOptions.chordvol && midiOptions.chordvol.length === 1 ? midiOptions.chordvol[0] : 48;
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
// This allows for an initial %%MIDI gchord with no string
|
|
47
|
+
if (midiOptions.gchord && (midiOptions.gchord.length > 0)) {
|
|
48
|
+
this.overridePattern = parseGChord(midiOptions.gchord[0])
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.overridePattern = undefined;
|
|
52
|
+
}
|
|
43
53
|
};
|
|
44
54
|
|
|
45
55
|
ChordTrack.prototype.setMeter = function (meter) {
|
|
@@ -64,7 +74,7 @@ ChordTrack.prototype.setRhythmHead = function (isRhythmHead, elem) {
|
|
|
64
74
|
if (isRhythmHead) {
|
|
65
75
|
if (this.lastChord && this.lastChord.chick) {
|
|
66
76
|
for (var i2 = 0; i2 < this.lastChord.chick.length; i2++) {
|
|
67
|
-
var note2 =
|
|
77
|
+
var note2 = Object.assign({},elem.pitches[0]);
|
|
68
78
|
note2.actualPitch = this.lastChord.chick[i2];
|
|
69
79
|
ePitches.push(note2);
|
|
70
80
|
}
|
|
@@ -89,13 +99,32 @@ ChordTrack.prototype.gChordOn = function (element) {
|
|
|
89
99
|
ChordTrack.prototype.paramChange = function (element) {
|
|
90
100
|
switch (element.el_type) {
|
|
91
101
|
case "gchord":
|
|
92
|
-
|
|
102
|
+
// Skips gchord elements that don't have pattern strings
|
|
103
|
+
if (element.param && element.param.length > 0) {
|
|
104
|
+
this.overridePattern = parseGChord(element.param);
|
|
105
|
+
|
|
106
|
+
// Generate a default duration scale based on the pattern
|
|
107
|
+
//this.gchordduration = generateDefaultDurationScale(element.param);
|
|
108
|
+
} else
|
|
109
|
+
this.overridePattern = undefined;
|
|
93
110
|
break;
|
|
94
111
|
case "bassprog":
|
|
95
|
-
this.bassInstrument = element.
|
|
112
|
+
this.bassInstrument = element.value;
|
|
113
|
+
if ((element.octaveShift != undefined) && (element.octaveShift != null)) {
|
|
114
|
+
this.bassOctaveShift = element.octaveShift;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
this.bassOctaveShift = 0;
|
|
118
|
+
}
|
|
96
119
|
break;
|
|
97
120
|
case "chordprog":
|
|
98
|
-
this.chordInstrument = element.
|
|
121
|
+
this.chordInstrument = element.value;
|
|
122
|
+
if ((element.octaveShift != undefined) && (element.octaveShift != null)) {
|
|
123
|
+
this.chordOctaveShift = element.octaveShift;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
this.chordOctaveShift = 0;
|
|
127
|
+
}
|
|
99
128
|
break;
|
|
100
129
|
case "bassvol":
|
|
101
130
|
this.boomVolume = element.param;
|
|
@@ -169,6 +198,21 @@ ChordTrack.prototype.interpretChord = function (name) {
|
|
|
169
198
|
while (chordTranspose > 8)
|
|
170
199
|
chordTranspose -= 12;
|
|
171
200
|
bass += chordTranspose;
|
|
201
|
+
|
|
202
|
+
// MAE 31 Aug 2024 - For visual transpose backup range issue
|
|
203
|
+
// If transposed below A or above G, bring it back in the normal backup range
|
|
204
|
+
if (bass < 33){
|
|
205
|
+
bass += 12;
|
|
206
|
+
}
|
|
207
|
+
else if (bass > 44){
|
|
208
|
+
bass -= 12;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// MAE 17 Jun 2024 - Supporting octave shifted bass and chords
|
|
212
|
+
var unshiftedBass = bass;
|
|
213
|
+
|
|
214
|
+
bass += this.bassOctaveShift * 12;
|
|
215
|
+
|
|
172
216
|
var bass2 = bass - 5; // The alternating bass is a 4th below
|
|
173
217
|
var chick;
|
|
174
218
|
if (name.length === 1)
|
|
@@ -176,16 +220,18 @@ ChordTrack.prototype.interpretChord = function (name) {
|
|
|
176
220
|
var remaining = name.substring(1);
|
|
177
221
|
var acc = remaining.substring(0, 1);
|
|
178
222
|
if (acc === 'b' || acc === '♭') {
|
|
223
|
+
unshiftedBass--;
|
|
179
224
|
bass--;
|
|
180
225
|
bass2--;
|
|
181
226
|
remaining = remaining.substring(1);
|
|
182
227
|
} else if (acc === '#' || acc === '♯') {
|
|
228
|
+
unshiftedBass++;
|
|
183
229
|
bass++;
|
|
184
230
|
bass2++;
|
|
185
231
|
remaining = remaining.substring(1);
|
|
186
232
|
}
|
|
187
233
|
var arr = remaining.split('/');
|
|
188
|
-
chick = this.chordNotes(
|
|
234
|
+
chick = this.chordNotes(unshiftedBass, arr[0]);
|
|
189
235
|
// If the 5th is altered then the bass is altered. Normally the bass is 7 from the root, so adjust if it isn't.
|
|
190
236
|
if (chick.length >= 3) {
|
|
191
237
|
var fifth = chick[2] - chick[0];
|
|
@@ -198,6 +244,10 @@ ChordTrack.prototype.interpretChord = function (name) {
|
|
|
198
244
|
var bassAcc = arr[1].substring(1);
|
|
199
245
|
var bassShift = { '#': 1, '♯': 1, 'b': -1, '♭': -1 }[bassAcc] || 0;
|
|
200
246
|
bass = this.basses[arr[1].substring(0, 1)] + bassShift + chordTranspose;
|
|
247
|
+
|
|
248
|
+
// MAE 22 May 2024 - Supporting octave shifted bass and chords
|
|
249
|
+
bass += this.bassOctaveShift * 12;
|
|
250
|
+
|
|
201
251
|
bass2 = bass;
|
|
202
252
|
}
|
|
203
253
|
}
|
|
@@ -215,6 +265,10 @@ ChordTrack.prototype.chordNotes = function (bass, modifier) {
|
|
|
215
265
|
intervals = this.chordIntervals.M;
|
|
216
266
|
}
|
|
217
267
|
bass += 12; // the chord is an octave above the bass note.
|
|
268
|
+
|
|
269
|
+
// MAE 22 May 2024 - For chick octave shift
|
|
270
|
+
bass += (this.chordOctaveShift * 12);
|
|
271
|
+
|
|
218
272
|
var notes = [];
|
|
219
273
|
for (var i = 0; i < intervals.length; i++) {
|
|
220
274
|
notes.push(bass + intervals[i]);
|
|
@@ -338,25 +392,34 @@ function resolvePitch(currentChord, type, firstBoom, newBass) {
|
|
|
338
392
|
ret.push(firstBoom ? currentChord.boom : currentChord.boom2)
|
|
339
393
|
else if (newBass)
|
|
340
394
|
ret.push(currentChord.boom)
|
|
395
|
+
var numChordNotes = currentChord.chick.length
|
|
341
396
|
if (type.indexOf('chick') >= 0) {
|
|
342
|
-
for (var i = 0; i <
|
|
397
|
+
for (var i = 0; i < numChordNotes; i++)
|
|
343
398
|
ret.push(currentChord.chick[i])
|
|
344
399
|
}
|
|
345
400
|
switch (type) {
|
|
346
401
|
case 'DO': ret.push(currentChord.chick[0]); break;
|
|
347
402
|
case 'MI': ret.push(currentChord.chick[1]); break;
|
|
348
|
-
case 'SOL': ret.push(currentChord
|
|
349
|
-
case 'TI':
|
|
350
|
-
case 'TOP':
|
|
403
|
+
case 'SOL': ret.push(extractNote(currentChord,2)); break;
|
|
404
|
+
case 'TI': ret.push(extractNote(currentChord,3)); break;
|
|
405
|
+
case 'TOP': ret.push(extractNote(currentChord,4)); break;
|
|
351
406
|
case 'do': ret.push(currentChord.chick[0]+12); break;
|
|
352
407
|
case 'mi': ret.push(currentChord.chick[1]+12); break;
|
|
353
|
-
case 'sol': ret.push(currentChord
|
|
354
|
-
case 'ti':
|
|
355
|
-
case 'top':
|
|
408
|
+
case 'sol': ret.push(extractNote(currentChord,2)+12); break;
|
|
409
|
+
case 'ti': ret.push(extractNote(currentChord,3)+12); break;
|
|
410
|
+
case 'top': ret.push(extractNote(currentChord,4)+12); break;
|
|
356
411
|
}
|
|
357
412
|
return ret
|
|
358
413
|
}
|
|
359
414
|
|
|
415
|
+
function extractNote(chord, index) {
|
|
416
|
+
// This creates an arpeggio note no matter how many notes are in the chord - if it runs out of notes it continues in the next octave
|
|
417
|
+
var octave = Math.floor(index / chord.chick.length)
|
|
418
|
+
var note = chord.chick[index % chord.chick.length]
|
|
419
|
+
//console.log(chord.chick, {index, octave, note}, index % chord.chick.length)
|
|
420
|
+
return note + octave * 12
|
|
421
|
+
}
|
|
422
|
+
|
|
360
423
|
function parseGChord(gchord) {
|
|
361
424
|
// TODO-PER: The spec is more complicated than this but for now this will not try to do anything with error cases like the wrong number of beats.
|
|
362
425
|
var pattern = []
|
|
@@ -532,7 +595,12 @@ ChordTrack.prototype.chordIntervals = {
|
|
|
532
595
|
'maj7#5#11': [0, 4, 8, 11, 18],
|
|
533
596
|
'9(#5)': [0, 4, 8, 10, 14],
|
|
534
597
|
'13(#5)': [0, 4, 8, 10, 14, 21],
|
|
535
|
-
'13#5': [0, 4, 8, 10, 14, 21]
|
|
598
|
+
'13#5': [0, 4, 8, 10, 14, 21],
|
|
599
|
+
// MAE Power chords added 10 April 2024
|
|
600
|
+
'5': [0, 7],
|
|
601
|
+
'5(8)': [0, 7, 12],
|
|
602
|
+
'5add8': [0, 7, 12]
|
|
603
|
+
|
|
536
604
|
};
|
|
537
605
|
|
|
538
606
|
ChordTrack.prototype.rhythmPatterns = {
|
|
@@ -547,8 +615,12 @@ ChordTrack.prototype.rhythmPatterns = {
|
|
|
547
615
|
"6/4": ['boom', '', 'chick', '', 'boom', '', 'chick', '', 'boom', '', 'chick', ''],
|
|
548
616
|
|
|
549
617
|
"3/8": ['boom', '', 'chick'],
|
|
618
|
+
"5/8": ['boom', 'chick', 'chick', 'boom', 'chick'],
|
|
550
619
|
"6/8": ['boom', '', 'chick', 'boom', '', 'chick'],
|
|
620
|
+
"7/8": ['boom', 'chick', 'chick', 'boom', 'chick', 'boom', 'chick'],
|
|
551
621
|
"9/8": ['boom', '', 'chick', 'boom', '', 'chick', 'boom', '', 'chick'],
|
|
622
|
+
"10/8": ['boom', 'chick', 'chick', 'boom', 'chick', 'chick', 'boom', 'chick', 'boom', 'chick'],
|
|
623
|
+
"11/8": ['boom', 'chick', 'chick', 'boom', 'chick', 'chick', 'boom', 'chick', 'boom', 'chick', 'chick'],
|
|
552
624
|
"12/8": ['boom', '', 'chick', 'boom', '', 'chick', 'boom', '', 'chick', 'boom', '', 'chick'],
|
|
553
625
|
};
|
|
554
626
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var supportsAudio = require('./supports-audio');
|
|
2
2
|
var registerAudioContext = require('./register-audio-context');
|
|
3
3
|
var activeAudioContext = require('./active-audio-context');
|
|
4
|
-
var parseCommon = require('../parse/abc_common');
|
|
5
4
|
|
|
6
5
|
var loopImage = require('./images/loop.svg.js');
|
|
7
6
|
var playImage = require('./images/play.svg.js');
|
|
@@ -23,7 +22,7 @@ function CreateSynthControl(parent, options) {
|
|
|
23
22
|
self.parent = parent;
|
|
24
23
|
self.options = {};
|
|
25
24
|
if (options)
|
|
26
|
-
self.options =
|
|
25
|
+
self.options = Object.assign({},options);
|
|
27
26
|
|
|
28
27
|
// This can be called in the following cases:
|
|
29
28
|
// AC already registered and not suspended
|
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
|
|
9
|
+
// This is the only entry point to the tablatures. It is called both after parsing a tune and just before engraving
|
|
10
|
+
|
|
11
|
+
var TabString = require('./instruments/tab-string');
|
|
12
|
+
|
|
13
|
+
/* extend the table below when adding a new instrument plugin */
|
|
14
|
+
|
|
15
|
+
// Existing tab classes
|
|
16
|
+
var pluginTab = {
|
|
17
|
+
'violin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0 },
|
|
18
|
+
'fiddle': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0 },
|
|
19
|
+
'mandolin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0 },
|
|
20
|
+
'guitar': { name: 'StringTab', defaultTuning: ['E,', 'A,', 'D', 'G', 'B', 'e'], isTabBig: true, tabSymbolOffset: 0 },
|
|
21
|
+
'fiveString': { name: 'StringTab', defaultTuning: ['C,', 'G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: -.95 },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
var abcTablatures = {
|
|
25
|
+
|
|
26
|
+
inited: false,
|
|
27
|
+
plugins: {},
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* to be called once per plugin for registration
|
|
32
|
+
* @param {*} plugin
|
|
33
|
+
*/
|
|
34
|
+
register: function (plugin) {
|
|
35
|
+
var name = plugin.name;
|
|
36
|
+
var tablature = plugin.tablature;
|
|
37
|
+
this.plugins[name] = tablature;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
setError: function (tune, msg) {
|
|
41
|
+
if (tune.warnings) {
|
|
42
|
+
tune.warning.push(msg);
|
|
43
|
+
} else {
|
|
44
|
+
tune.warnings = [msg];
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* handle params for current processed score
|
|
50
|
+
* @param {*} tune current tune
|
|
51
|
+
* @param {*} tuneNumber number in tune list
|
|
52
|
+
* @param {*} params params to be processed for tablature
|
|
53
|
+
* @return prepared tablatures plugin instances for current tune
|
|
54
|
+
*/
|
|
55
|
+
preparePlugins: function (tune, tuneNumber, params) {
|
|
56
|
+
// Called after parsing a tune and before engraving it
|
|
57
|
+
if (!this.inited) {
|
|
58
|
+
// TODO-PER: I don't think this is needed - the plugin array can be hard coded, right?
|
|
59
|
+
this.register(new TabString());
|
|
60
|
+
this.inited = true;
|
|
61
|
+
}
|
|
62
|
+
var returned = null;
|
|
63
|
+
var nbPlugins = 0;
|
|
64
|
+
if (params.tablature) {
|
|
65
|
+
// validate requested plugins
|
|
66
|
+
var tabs = params.tablature;
|
|
67
|
+
returned = [];
|
|
68
|
+
for (var ii = 0; ii < tabs.length; ii++) {
|
|
69
|
+
var args = tabs[ii];
|
|
70
|
+
var instrument = args['instrument'];
|
|
71
|
+
if (instrument == null) {
|
|
72
|
+
this.setError(tune, "tablature 'instrument' is missing");
|
|
73
|
+
return returned;
|
|
74
|
+
}
|
|
75
|
+
var tabName = pluginTab[instrument];
|
|
76
|
+
var plugin = null;
|
|
77
|
+
if (tabName) {
|
|
78
|
+
plugin = this.plugins[tabName.name];
|
|
79
|
+
}
|
|
80
|
+
if (plugin) {
|
|
81
|
+
if (params.visualTranspose != 0) {
|
|
82
|
+
// populate transposition request to tabs
|
|
83
|
+
args.visualTranspose = params.visualTranspose;
|
|
84
|
+
}
|
|
85
|
+
args.abcSrc = params.tablature.abcSrc;
|
|
86
|
+
var pluginInstance = {
|
|
87
|
+
classz: plugin,
|
|
88
|
+
tuneNumber: tuneNumber,
|
|
89
|
+
params: args,
|
|
90
|
+
instance: null,
|
|
91
|
+
tabType: tabName,
|
|
92
|
+
};
|
|
93
|
+
// proceed with tab plugin init
|
|
94
|
+
// plugin.init(tune, tuneNumber, args, ii);
|
|
95
|
+
returned.push(pluginInstance);
|
|
96
|
+
nbPlugins++;
|
|
97
|
+
} else if (instrument === '') {
|
|
98
|
+
// create a placeholder - there is no tab for this staff
|
|
99
|
+
returned.push(null)
|
|
100
|
+
} else {
|
|
101
|
+
// unknown tab plugin
|
|
102
|
+
//this.emit_error('Undefined tablature plugin: ' + tabName)
|
|
103
|
+
this.setError(tune, 'Undefined tablature plugin: ' + instrument);
|
|
104
|
+
return returned;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return returned;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Call requested plugin
|
|
113
|
+
* @param {*} renderer
|
|
114
|
+
* @param {*} abcTune
|
|
115
|
+
*/
|
|
116
|
+
layoutTablatures: function layoutTablatures(renderer, abcTune) {
|
|
117
|
+
var tabs = abcTune.tablatures;
|
|
118
|
+
|
|
119
|
+
// chack tabs request for each staffs
|
|
120
|
+
var staffLineCount = 0;
|
|
121
|
+
|
|
122
|
+
// Clear the suppression flag
|
|
123
|
+
if (tabs && (tabs.length > 0)) {
|
|
124
|
+
var nTabs = tabs.length;
|
|
125
|
+
for (var kk = 0; kk < nTabs; ++kk) {
|
|
126
|
+
if (tabs[kk] && tabs[kk].params.firstStaffOnly) {
|
|
127
|
+
tabs[kk].params.suppress = false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (var ii = 0; ii < abcTune.lines.length; ii++) {
|
|
133
|
+
var line = abcTune.lines[ii];
|
|
134
|
+
|
|
135
|
+
if (line.staff) {
|
|
136
|
+
staffLineCount++;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// MAE 27Nov2023
|
|
140
|
+
// If tab param "firstStaffOnly", remove the tab label after the first staff
|
|
141
|
+
if (staffLineCount > 1) {
|
|
142
|
+
if (tabs && (tabs.length > 0)) {
|
|
143
|
+
var nTabs = tabs.length;
|
|
144
|
+
for (var kk = 0; kk < nTabs; ++kk) {
|
|
145
|
+
if (tabs[kk].params.firstStaffOnly) {
|
|
146
|
+
// Set the staff draw suppression flag
|
|
147
|
+
tabs[kk].params.suppress = true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
var curStaff = line.staff;
|
|
154
|
+
if (curStaff) {
|
|
155
|
+
var maxStaves = curStaff.length
|
|
156
|
+
for (var jj = 0; jj < curStaff.length; jj++) {
|
|
157
|
+
|
|
158
|
+
if (tabs[jj] && jj < maxStaves) {
|
|
159
|
+
// tablature requested for staff
|
|
160
|
+
var tabPlugin = tabs[jj];
|
|
161
|
+
if (tabPlugin.instance == null) {
|
|
162
|
+
//console.log("★★★★ Tab Init line: " + ii + " staff: " + jj)
|
|
163
|
+
tabPlugin.instance = new tabPlugin.classz();
|
|
164
|
+
// plugin.init(tune, tuneNumber, args, ii);
|
|
165
|
+
// call initer first
|
|
166
|
+
tabPlugin.instance.init(abcTune,
|
|
167
|
+
tabPlugin.tuneNumber,
|
|
168
|
+
tabPlugin.params,
|
|
169
|
+
tabPlugin.tabType
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
// render next
|
|
173
|
+
//console.log("★★★★ Tab Render line: " + ii + " staff: " + jj)
|
|
174
|
+
tabPlugin.instance.render(renderer, line, jj);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
module.exports = abcTablatures;
|