@coderline/alphatab 1.7.0-alpha.1515 → 1.7.0-alpha.1522
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/dist/alphaTab.core.min.mjs +2 -2
- package/dist/alphaTab.core.mjs +813 -488
- package/dist/alphaTab.d.ts +80 -25
- package/dist/alphaTab.js +813 -488
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.vite.js +1 -1
- package/dist/alphaTab.vite.mjs +1 -1
- package/dist/alphaTab.webpack.js +1 -1
- package/dist/alphaTab.webpack.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +1 -1
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.7.0-alpha.
|
|
2
|
+
* alphaTab v1.7.0-alpha.1522 (develop, build 1522)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -203,9 +203,9 @@
|
|
|
203
203
|
print(`build date: ${VersionInfo.date}`);
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
-
VersionInfo.version = '1.7.0-alpha.
|
|
207
|
-
VersionInfo.date = '2025-08-
|
|
208
|
-
VersionInfo.commit = '
|
|
206
|
+
VersionInfo.version = '1.7.0-alpha.1522';
|
|
207
|
+
VersionInfo.date = '2025-08-24T02:21:16.522Z';
|
|
208
|
+
VersionInfo.commit = 'c80b4a66eae6b73cb2d7dacaaf74c8f9cce16318';
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* This public class provides names for all general midi instruments.
|
|
@@ -232,6 +232,14 @@
|
|
|
232
232
|
static isGuitar(program) {
|
|
233
233
|
return (program >= 24 && program <= 39) || program === 105 || program === 43;
|
|
234
234
|
}
|
|
235
|
+
static isBass(program) {
|
|
236
|
+
return program >= 32 && program <= 39;
|
|
237
|
+
}
|
|
238
|
+
static bankToLsbMsb(bank) {
|
|
239
|
+
const lsb = bank & 0x7f;
|
|
240
|
+
const msb = (bank >> 7) & 0x7f;
|
|
241
|
+
return [lsb, msb];
|
|
242
|
+
}
|
|
235
243
|
}
|
|
236
244
|
GeneralMidi._values = new Map([
|
|
237
245
|
['acousticgrandpiano', 0],
|
|
@@ -1426,6 +1434,10 @@
|
|
|
1426
1434
|
* A sync point for synchronizing the internal time axis with an external audio track.
|
|
1427
1435
|
*/
|
|
1428
1436
|
AutomationType[AutomationType["SyncPoint"] = 4] = "SyncPoint";
|
|
1437
|
+
/**
|
|
1438
|
+
* Midi Bank change.
|
|
1439
|
+
*/
|
|
1440
|
+
AutomationType[AutomationType["Bank"] = 4] = "Bank";
|
|
1429
1441
|
})(AutomationType || (AutomationType = {}));
|
|
1430
1442
|
/**
|
|
1431
1443
|
* Represents the data of a sync point for synchronizing the internal time axis with
|
|
@@ -3393,6 +3405,49 @@
|
|
|
3393
3405
|
MusicFontSymbol[MusicFontSymbol["FingeringCLower"] = 60700] = "FingeringCLower";
|
|
3394
3406
|
})(MusicFontSymbol || (MusicFontSymbol = {}));
|
|
3395
3407
|
|
|
3408
|
+
/**
|
|
3409
|
+
* Defines all possible accidentals for notes.
|
|
3410
|
+
*/
|
|
3411
|
+
var AccidentalType;
|
|
3412
|
+
(function (AccidentalType) {
|
|
3413
|
+
/**
|
|
3414
|
+
* No accidental
|
|
3415
|
+
*/
|
|
3416
|
+
AccidentalType[AccidentalType["None"] = 0] = "None";
|
|
3417
|
+
/**
|
|
3418
|
+
* Naturalize
|
|
3419
|
+
*/
|
|
3420
|
+
AccidentalType[AccidentalType["Natural"] = 1] = "Natural";
|
|
3421
|
+
/**
|
|
3422
|
+
* Sharp
|
|
3423
|
+
*/
|
|
3424
|
+
AccidentalType[AccidentalType["Sharp"] = 2] = "Sharp";
|
|
3425
|
+
/**
|
|
3426
|
+
* Flat
|
|
3427
|
+
*/
|
|
3428
|
+
AccidentalType[AccidentalType["Flat"] = 3] = "Flat";
|
|
3429
|
+
/**
|
|
3430
|
+
* Natural for smear bends
|
|
3431
|
+
*/
|
|
3432
|
+
AccidentalType[AccidentalType["NaturalQuarterNoteUp"] = 4] = "NaturalQuarterNoteUp";
|
|
3433
|
+
/**
|
|
3434
|
+
* Sharp for smear bends
|
|
3435
|
+
*/
|
|
3436
|
+
AccidentalType[AccidentalType["SharpQuarterNoteUp"] = 5] = "SharpQuarterNoteUp";
|
|
3437
|
+
/**
|
|
3438
|
+
* Flat for smear bends
|
|
3439
|
+
*/
|
|
3440
|
+
AccidentalType[AccidentalType["FlatQuarterNoteUp"] = 6] = "FlatQuarterNoteUp";
|
|
3441
|
+
/**
|
|
3442
|
+
* Double Sharp, indicated by an 'x'
|
|
3443
|
+
*/
|
|
3444
|
+
AccidentalType[AccidentalType["DoubleSharp"] = 7] = "DoubleSharp";
|
|
3445
|
+
/**
|
|
3446
|
+
* Double Flat, indicated by 'bb'
|
|
3447
|
+
*/
|
|
3448
|
+
AccidentalType[AccidentalType["DoubleFlat"] = 8] = "DoubleFlat";
|
|
3449
|
+
})(AccidentalType || (AccidentalType = {}));
|
|
3450
|
+
|
|
3396
3451
|
class TuningParseResult {
|
|
3397
3452
|
constructor() {
|
|
3398
3453
|
this.note = null;
|
|
@@ -3898,6 +3953,150 @@
|
|
|
3898
3953
|
}
|
|
3899
3954
|
return ModelUtils.allMusicFontSymbols;
|
|
3900
3955
|
}
|
|
3956
|
+
/**
|
|
3957
|
+
* @internal
|
|
3958
|
+
*/
|
|
3959
|
+
static flooredDivision(a, b) {
|
|
3960
|
+
return a - b * Math.floor(a / b);
|
|
3961
|
+
}
|
|
3962
|
+
// NOTE: haven't figured out yet what exact formula is applied when transposing key signatures
|
|
3963
|
+
// this table is simply created by checking the Guitar Pro behavior,
|
|
3964
|
+
// The table is organized as [<transpose>][<key signature>] to match the table above
|
|
3965
|
+
// it's also easier to read as we list every key signature per row, transposed by the same value
|
|
3966
|
+
// this gives typically just a shifted list according to the transpose (with some special treatments)
|
|
3967
|
+
/**
|
|
3968
|
+
* Converts the key transpose table to actual key signatures.
|
|
3969
|
+
* @param texts An array where every item indicates the number of accidentals and which accidental
|
|
3970
|
+
* placed for the key signature.
|
|
3971
|
+
*
|
|
3972
|
+
* e.g. 3# is 3-sharps -> KeySignature.A
|
|
3973
|
+
*/
|
|
3974
|
+
static translateKeyTransposeTable(texts) {
|
|
3975
|
+
const keySignatures = [];
|
|
3976
|
+
for (const transpose of texts) {
|
|
3977
|
+
const transposeValues = [];
|
|
3978
|
+
keySignatures.push(transposeValues);
|
|
3979
|
+
for (const keySignatureText of transpose) {
|
|
3980
|
+
const keySignature =
|
|
3981
|
+
// digit
|
|
3982
|
+
(Number.parseInt(keySignatureText.charAt(0)) *
|
|
3983
|
+
// b -> negative, # positive
|
|
3984
|
+
(keySignatureText.charAt(1) === 'b' ? -1 : 1));
|
|
3985
|
+
transposeValues.push(keySignature);
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
return keySignatures;
|
|
3989
|
+
}
|
|
3990
|
+
/**
|
|
3991
|
+
* Transposes the given key signature.
|
|
3992
|
+
* @internal
|
|
3993
|
+
* @param keySignature The key signature to transpose
|
|
3994
|
+
* @param transpose The number of semitones to transpose (+/- 0-11)
|
|
3995
|
+
* @returns
|
|
3996
|
+
*/
|
|
3997
|
+
static transposeKey(keySignature, transpose) {
|
|
3998
|
+
if (transpose === 0) {
|
|
3999
|
+
return keySignature;
|
|
4000
|
+
}
|
|
4001
|
+
if (transpose < 0) {
|
|
4002
|
+
const lookup = ModelUtils.keyTransposeTable[-transpose];
|
|
4003
|
+
const keySignatureIndex = lookup.indexOf(keySignature);
|
|
4004
|
+
if (keySignatureIndex === -1) {
|
|
4005
|
+
return keySignature;
|
|
4006
|
+
}
|
|
4007
|
+
return (keySignatureIndex - 7);
|
|
4008
|
+
}
|
|
4009
|
+
else {
|
|
4010
|
+
return ModelUtils.keyTransposeTable[transpose][keySignature + 7];
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
/**
|
|
4014
|
+
* @internal
|
|
4015
|
+
*/
|
|
4016
|
+
static computeAccidental(keySignature, accidentalMode, noteValue, quarterBend, currentAccidental = null) {
|
|
4017
|
+
const ks = keySignature;
|
|
4018
|
+
const ksi = ks + 7;
|
|
4019
|
+
const index = noteValue % 12;
|
|
4020
|
+
const accidentalForKeySignature = ksi < 7 ? AccidentalType.Flat : AccidentalType.Sharp;
|
|
4021
|
+
const hasKeySignatureAccidentalSetForNote = ModelUtils.KeySignatureLookup[ksi][index];
|
|
4022
|
+
const hasNoteAccidentalWithinOctave = ModelUtils.AccidentalNotes[index];
|
|
4023
|
+
// the general logic is like this:
|
|
4024
|
+
// - we check if the key signature has an accidental defined
|
|
4025
|
+
// - we calculate which accidental a note needs according to its index in the octave
|
|
4026
|
+
// - if the accidental is already placed at this line, nothing needs to be done, otherwise we place it
|
|
4027
|
+
// - if there should not be an accidental, but there is one in the key signature, we clear it.
|
|
4028
|
+
// the exceptions are:
|
|
4029
|
+
// - for quarter bends we just place the corresponding accidental
|
|
4030
|
+
// - the accidental mode can enforce the accidentals for the note
|
|
4031
|
+
let accidentalToSet = AccidentalType.None;
|
|
4032
|
+
if (quarterBend) {
|
|
4033
|
+
accidentalToSet = hasNoteAccidentalWithinOctave ? accidentalForKeySignature : AccidentalType.Natural;
|
|
4034
|
+
switch (accidentalToSet) {
|
|
4035
|
+
case AccidentalType.Natural:
|
|
4036
|
+
accidentalToSet = AccidentalType.NaturalQuarterNoteUp;
|
|
4037
|
+
break;
|
|
4038
|
+
case AccidentalType.Sharp:
|
|
4039
|
+
accidentalToSet = AccidentalType.SharpQuarterNoteUp;
|
|
4040
|
+
break;
|
|
4041
|
+
case AccidentalType.Flat:
|
|
4042
|
+
accidentalToSet = AccidentalType.FlatQuarterNoteUp;
|
|
4043
|
+
break;
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
else {
|
|
4047
|
+
// define which accidental should be shown ignoring what might be set on the KS already
|
|
4048
|
+
switch (accidentalMode) {
|
|
4049
|
+
case NoteAccidentalMode.ForceSharp:
|
|
4050
|
+
accidentalToSet = AccidentalType.Sharp;
|
|
4051
|
+
break;
|
|
4052
|
+
case NoteAccidentalMode.ForceDoubleSharp:
|
|
4053
|
+
accidentalToSet = AccidentalType.DoubleSharp;
|
|
4054
|
+
break;
|
|
4055
|
+
case NoteAccidentalMode.ForceFlat:
|
|
4056
|
+
accidentalToSet = AccidentalType.Flat;
|
|
4057
|
+
break;
|
|
4058
|
+
case NoteAccidentalMode.ForceDoubleFlat:
|
|
4059
|
+
accidentalToSet = AccidentalType.DoubleFlat;
|
|
4060
|
+
break;
|
|
4061
|
+
default:
|
|
4062
|
+
// if note has an accidental in the octave, we place a symbol
|
|
4063
|
+
// according to the Key Signature
|
|
4064
|
+
if (hasNoteAccidentalWithinOctave) {
|
|
4065
|
+
accidentalToSet = accidentalForKeySignature;
|
|
4066
|
+
}
|
|
4067
|
+
else if (hasKeySignatureAccidentalSetForNote) {
|
|
4068
|
+
// note does not get an accidental, but KS defines one -> Naturalize
|
|
4069
|
+
accidentalToSet = AccidentalType.Natural;
|
|
4070
|
+
}
|
|
4071
|
+
break;
|
|
4072
|
+
}
|
|
4073
|
+
// do we need an accidental on the note?
|
|
4074
|
+
if (accidentalToSet !== AccidentalType.None) {
|
|
4075
|
+
// if there is no accidental on the line, and the key signature has it set already, we clear it on the note
|
|
4076
|
+
if (currentAccidental != null) {
|
|
4077
|
+
if (currentAccidental === accidentalToSet) {
|
|
4078
|
+
accidentalToSet = AccidentalType.None;
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
else if (hasKeySignatureAccidentalSetForNote && accidentalToSet === accidentalForKeySignature) {
|
|
4082
|
+
accidentalToSet = AccidentalType.None;
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
else {
|
|
4086
|
+
// if we don't want an accidental, but there is already one applied, we place a naturalize accidental
|
|
4087
|
+
// and clear the registration
|
|
4088
|
+
if (currentAccidental !== null) {
|
|
4089
|
+
if (currentAccidental === AccidentalType.Natural) {
|
|
4090
|
+
accidentalToSet = AccidentalType.None;
|
|
4091
|
+
}
|
|
4092
|
+
else {
|
|
4093
|
+
accidentalToSet = AccidentalType.Natural;
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
return accidentalToSet;
|
|
4099
|
+
}
|
|
3901
4100
|
}
|
|
3902
4101
|
ModelUtils.TuningLetters = new Set([
|
|
3903
4102
|
0x43 /* C */, 0x44 /* D */, 0x45 /* E */, 0x46 /* F */, 0x47 /* G */, 0x41 /* A */, 0x42 /* B */, 0x63 /* c */,
|
|
@@ -3950,6 +4149,66 @@
|
|
|
3950
4149
|
// Contrabass
|
|
3951
4150
|
[43, -12]
|
|
3952
4151
|
]);
|
|
4152
|
+
/**
|
|
4153
|
+
* @internal
|
|
4154
|
+
*/
|
|
4155
|
+
ModelUtils.keyTransposeTable = ModelUtils.translateKeyTransposeTable([
|
|
4156
|
+
/* Cb Gb Db Ab Eb Bb F C G D A E B F C# */
|
|
4157
|
+
/* C 0 */ ['7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#'],
|
|
4158
|
+
/* Db 1 */ ['2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b', '2b', '1b', '0#'],
|
|
4159
|
+
/* D 2 */ ['3#', '4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#'],
|
|
4160
|
+
/* Eb 3 */ ['4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b', '2b'],
|
|
4161
|
+
/* E 4 */ ['1#', '2#', '3#', '4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#'],
|
|
4162
|
+
/* F 5 */ ['6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b'],
|
|
4163
|
+
/* Gb 6 */ ['1b', '0#', '1#', '2#', '3#', '4#', '7b', '6#', '7#', '4b', '3b', '2b', '1b', '0#', '1#'],
|
|
4164
|
+
/* G 7 */ ['4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#'],
|
|
4165
|
+
/* Ab 8 */ ['3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b', '2b', '1b'],
|
|
4166
|
+
/* A 9 */ ['2#', '3#', '4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#'],
|
|
4167
|
+
/* Bb 10 */ ['5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b'],
|
|
4168
|
+
/* B 11 */ ['0#', '1#', '2#', '3#', '4#', '7b', '6b', '6#', '4b', '3b', '2b', '1b', '0#', '1#', '2#']
|
|
4169
|
+
]);
|
|
4170
|
+
/**
|
|
4171
|
+
* a lookup list containing an info whether the notes within an octave
|
|
4172
|
+
* need an accidental rendered. the accidental symbol is determined based on the type of key signature.
|
|
4173
|
+
*/
|
|
4174
|
+
ModelUtils.KeySignatureLookup = [
|
|
4175
|
+
// Flats (where the value is true, a flat accidental is required for the notes)
|
|
4176
|
+
[true, true, true, true, true, true, true, true, true, true, true, true],
|
|
4177
|
+
[true, true, true, true, true, false, true, true, true, true, true, true],
|
|
4178
|
+
[false, true, true, true, true, false, true, true, true, true, true, true],
|
|
4179
|
+
[false, true, true, true, true, false, false, false, true, true, true, true],
|
|
4180
|
+
[false, false, false, true, true, false, false, false, true, true, true, true],
|
|
4181
|
+
[false, false, false, true, true, false, false, false, false, false, true, true],
|
|
4182
|
+
[false, false, false, false, false, false, false, false, false, false, true, true],
|
|
4183
|
+
// natural
|
|
4184
|
+
[false, false, false, false, false, false, false, false, false, false, false, false],
|
|
4185
|
+
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
4186
|
+
[false, false, false, false, false, true, true, false, false, false, false, false],
|
|
4187
|
+
[true, true, false, false, false, true, true, false, false, false, false, false],
|
|
4188
|
+
[true, true, false, false, false, true, true, true, true, false, false, false],
|
|
4189
|
+
[true, true, true, true, false, true, true, true, true, false, false, false],
|
|
4190
|
+
[true, true, true, true, false, true, true, true, true, true, true, false],
|
|
4191
|
+
[true, true, true, true, true, true, true, true, true, true, true, false],
|
|
4192
|
+
[true, true, true, true, true, true, true, true, true, true, true, true]
|
|
4193
|
+
];
|
|
4194
|
+
/**
|
|
4195
|
+
* Contains the list of notes within an octave have accidentals set.
|
|
4196
|
+
* @internal
|
|
4197
|
+
*/
|
|
4198
|
+
ModelUtils.AccidentalNotes = [
|
|
4199
|
+
false,
|
|
4200
|
+
true,
|
|
4201
|
+
false,
|
|
4202
|
+
true,
|
|
4203
|
+
false,
|
|
4204
|
+
false,
|
|
4205
|
+
true,
|
|
4206
|
+
false,
|
|
4207
|
+
true,
|
|
4208
|
+
false,
|
|
4209
|
+
true,
|
|
4210
|
+
false
|
|
4211
|
+
];
|
|
3953
4212
|
|
|
3954
4213
|
/**
|
|
3955
4214
|
* Lists all types of pick strokes.
|
|
@@ -7920,6 +8179,10 @@
|
|
|
7920
8179
|
* Gets or sets the midi program to use.
|
|
7921
8180
|
*/
|
|
7922
8181
|
this.program = 0;
|
|
8182
|
+
/**
|
|
8183
|
+
* The midi bank to use.
|
|
8184
|
+
*/
|
|
8185
|
+
this.bank = 0;
|
|
7923
8186
|
/**
|
|
7924
8187
|
* Gets or sets the primary channel for all normal midi events.
|
|
7925
8188
|
*/
|
|
@@ -7952,7 +8215,7 @@
|
|
|
7952
8215
|
static getTextPartsForTuning(tuning, octaveShift = -1) {
|
|
7953
8216
|
const octave = (tuning / 12) | 0;
|
|
7954
8217
|
const note = tuning % 12;
|
|
7955
|
-
const notes =
|
|
8218
|
+
const notes = Tuning.noteNames;
|
|
7956
8219
|
return [notes[note], (octave + octaveShift).toString()];
|
|
7957
8220
|
}
|
|
7958
8221
|
/**
|
|
@@ -8091,8 +8354,7 @@
|
|
|
8091
8354
|
Tuning._fiveStrings = [];
|
|
8092
8355
|
Tuning._fourStrings = [];
|
|
8093
8356
|
Tuning._defaultTunings = new Map();
|
|
8094
|
-
Tuning.
|
|
8095
|
-
Tuning.defaultSteps = ['C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B'];
|
|
8357
|
+
Tuning.noteNames = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
|
|
8096
8358
|
Tuning.initialize();
|
|
8097
8359
|
|
|
8098
8360
|
/**
|
|
@@ -8315,6 +8577,12 @@
|
|
|
8315
8577
|
*/
|
|
8316
8578
|
this.percussionArticulations = [];
|
|
8317
8579
|
}
|
|
8580
|
+
/**
|
|
8581
|
+
* Gets whether this track is a percussion track.
|
|
8582
|
+
*/
|
|
8583
|
+
get isPercussion() {
|
|
8584
|
+
return this.staves.some(s => s.isPercussion);
|
|
8585
|
+
}
|
|
8318
8586
|
/**
|
|
8319
8587
|
* Adds a new line break.
|
|
8320
8588
|
* @param index The index of the bar before which a line break should happen.
|
|
@@ -9018,8 +9286,7 @@
|
|
|
9018
9286
|
}
|
|
9019
9287
|
// unicode handling
|
|
9020
9288
|
// https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-ecmascript-language-types-string-type
|
|
9021
|
-
if (IOHelper.isLeadingSurrogate(previousCodepoint) &&
|
|
9022
|
-
IOHelper.isTrailingSurrogate(codepoint)) {
|
|
9289
|
+
if (IOHelper.isLeadingSurrogate(previousCodepoint) && IOHelper.isTrailingSurrogate(codepoint)) {
|
|
9023
9290
|
codepoint = (previousCodepoint - 0xd800) * 0x400 + (codepoint - 0xdc00) + 0x10000;
|
|
9024
9291
|
s += String.fromCodePoint(codepoint);
|
|
9025
9292
|
}
|
|
@@ -9454,10 +9721,10 @@
|
|
|
9454
9721
|
case 'bass':
|
|
9455
9722
|
return Clef.F4;
|
|
9456
9723
|
case 'c3':
|
|
9457
|
-
case '
|
|
9724
|
+
case 'alto':
|
|
9458
9725
|
return Clef.C3;
|
|
9459
9726
|
case 'c4':
|
|
9460
|
-
case '
|
|
9727
|
+
case 'tenor':
|
|
9461
9728
|
return Clef.C4;
|
|
9462
9729
|
case 'n':
|
|
9463
9730
|
case 'neutral':
|
|
@@ -9474,6 +9741,8 @@
|
|
|
9474
9741
|
*/
|
|
9475
9742
|
parseClefFromInt(i) {
|
|
9476
9743
|
switch (i) {
|
|
9744
|
+
case 0:
|
|
9745
|
+
return Clef.Neutral;
|
|
9477
9746
|
case 43:
|
|
9478
9747
|
return Clef.G2;
|
|
9479
9748
|
case 65:
|
|
@@ -9978,33 +10247,15 @@
|
|
|
9978
10247
|
}
|
|
9979
10248
|
return StaffMetaResult.KnownStaffMeta;
|
|
9980
10249
|
case 'instrument':
|
|
9981
|
-
this.sy = this.newSy();
|
|
9982
10250
|
this._staffTuningApplied = false;
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
9990
|
-
}
|
|
9991
|
-
}
|
|
9992
|
-
else if (this.sy === AlphaTexSymbols.String) {
|
|
9993
|
-
const instrumentName = this.syData.toLowerCase();
|
|
9994
|
-
if (instrumentName === 'percussion') {
|
|
9995
|
-
for (const staff of this._currentTrack.staves) {
|
|
9996
|
-
this.applyPercussionStaff(staff);
|
|
9997
|
-
}
|
|
9998
|
-
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
9999
|
-
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10000
|
-
}
|
|
10001
|
-
else {
|
|
10002
|
-
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10003
|
-
}
|
|
10004
|
-
}
|
|
10005
|
-
else {
|
|
10006
|
-
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10251
|
+
this.readTrackInstrument();
|
|
10252
|
+
return StaffMetaResult.KnownStaffMeta;
|
|
10253
|
+
case 'bank':
|
|
10254
|
+
this.sy = this.newSy();
|
|
10255
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10256
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10007
10257
|
}
|
|
10258
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10008
10259
|
this.sy = this.newSy();
|
|
10009
10260
|
return StaffMetaResult.KnownStaffMeta;
|
|
10010
10261
|
case 'lyrics':
|
|
@@ -10115,6 +10366,35 @@
|
|
|
10115
10366
|
return StaffMetaResult.UnknownStaffMeta;
|
|
10116
10367
|
}
|
|
10117
10368
|
}
|
|
10369
|
+
readTrackInstrument() {
|
|
10370
|
+
this.sy = this.newSy();
|
|
10371
|
+
if (this.sy === AlphaTexSymbols.Number) {
|
|
10372
|
+
const instrument = this.syData;
|
|
10373
|
+
if (instrument >= 0 && instrument <= 127) {
|
|
10374
|
+
this._currentTrack.playbackInfo.program = this.syData;
|
|
10375
|
+
}
|
|
10376
|
+
else {
|
|
10377
|
+
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
10378
|
+
}
|
|
10379
|
+
}
|
|
10380
|
+
else if (this.sy === AlphaTexSymbols.String) {
|
|
10381
|
+
const instrumentName = this.syData.toLowerCase();
|
|
10382
|
+
if (instrumentName === 'percussion') {
|
|
10383
|
+
for (const staff of this._currentTrack.staves) {
|
|
10384
|
+
this.applyPercussionStaff(staff);
|
|
10385
|
+
}
|
|
10386
|
+
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
10387
|
+
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10388
|
+
}
|
|
10389
|
+
else {
|
|
10390
|
+
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10391
|
+
}
|
|
10392
|
+
}
|
|
10393
|
+
else {
|
|
10394
|
+
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10395
|
+
}
|
|
10396
|
+
this.sy = this.newSy();
|
|
10397
|
+
}
|
|
10118
10398
|
handleAccidentalMode() {
|
|
10119
10399
|
this.sy = this.newSy();
|
|
10120
10400
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -10387,6 +10667,17 @@
|
|
|
10387
10667
|
}
|
|
10388
10668
|
this._score.stylesheet.perTrackMultiBarRest.add(this._currentTrack.index);
|
|
10389
10669
|
break;
|
|
10670
|
+
case 'instrument':
|
|
10671
|
+
this.readTrackInstrument();
|
|
10672
|
+
break;
|
|
10673
|
+
case 'bank':
|
|
10674
|
+
this.sy = this.newSy();
|
|
10675
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10676
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10677
|
+
}
|
|
10678
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10679
|
+
this.sy = this.newSy();
|
|
10680
|
+
break;
|
|
10390
10681
|
default:
|
|
10391
10682
|
this.error('track-properties', AlphaTexSymbols.String, false);
|
|
10392
10683
|
break;
|
|
@@ -10731,6 +11022,25 @@
|
|
|
10731
11022
|
}
|
|
10732
11023
|
beat.text = this.syData;
|
|
10733
11024
|
}
|
|
11025
|
+
else if (syData === 'lyrics') {
|
|
11026
|
+
this.sy = this.newSy();
|
|
11027
|
+
let lyricsLine = 0;
|
|
11028
|
+
if (this.sy === AlphaTexSymbols.Number) {
|
|
11029
|
+
lyricsLine = this.syData;
|
|
11030
|
+
this.sy = this.newSy();
|
|
11031
|
+
}
|
|
11032
|
+
if (this.sy !== AlphaTexSymbols.String) {
|
|
11033
|
+
this.error('lyrics', AlphaTexSymbols.String, true);
|
|
11034
|
+
return false;
|
|
11035
|
+
}
|
|
11036
|
+
if (!beat.lyrics) {
|
|
11037
|
+
beat.lyrics = [];
|
|
11038
|
+
}
|
|
11039
|
+
while (beat.lyrics.length <= lyricsLine) {
|
|
11040
|
+
beat.lyrics.push('');
|
|
11041
|
+
}
|
|
11042
|
+
beat.lyrics[lyricsLine] = this.syData;
|
|
11043
|
+
}
|
|
10734
11044
|
else if (syData === 'dd') {
|
|
10735
11045
|
beat.dots = 2;
|
|
10736
11046
|
}
|
|
@@ -11168,6 +11478,17 @@
|
|
|
11168
11478
|
automation.value = program;
|
|
11169
11479
|
beat.automations.push(automation);
|
|
11170
11480
|
}
|
|
11481
|
+
else if (syData === 'bank') {
|
|
11482
|
+
this.sy = this.newSy();
|
|
11483
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
11484
|
+
this.error('bank-change', AlphaTexSymbols.Number, true);
|
|
11485
|
+
}
|
|
11486
|
+
const automation = new Automation();
|
|
11487
|
+
automation.isLinear = false;
|
|
11488
|
+
automation.type = AutomationType.Bank;
|
|
11489
|
+
automation.value = this.syData;
|
|
11490
|
+
beat.automations.push(automation);
|
|
11491
|
+
}
|
|
11171
11492
|
else if (syData === 'fermata') {
|
|
11172
11493
|
this.sy = this.newSy();
|
|
11173
11494
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -11178,7 +11499,7 @@
|
|
|
11178
11499
|
this.sy = this.newSy(true);
|
|
11179
11500
|
if (this.sy === AlphaTexSymbols.Number) {
|
|
11180
11501
|
fermata.length = this.syData;
|
|
11181
|
-
this.sy = this.newSy(
|
|
11502
|
+
this.sy = this.newSy();
|
|
11182
11503
|
}
|
|
11183
11504
|
beat.fermata = fermata;
|
|
11184
11505
|
return true;
|
|
@@ -11211,13 +11532,9 @@
|
|
|
11211
11532
|
beat.beamingMode = BeatBeamingMode.ForceSplitOnSecondaryToNext;
|
|
11212
11533
|
break;
|
|
11213
11534
|
}
|
|
11214
|
-
this.sy = this.newSy();
|
|
11215
|
-
return true;
|
|
11216
11535
|
}
|
|
11217
11536
|
else if (syData === 'timer') {
|
|
11218
11537
|
beat.showTimer = true;
|
|
11219
|
-
this.sy = this.newSy();
|
|
11220
|
-
return true;
|
|
11221
11538
|
}
|
|
11222
11539
|
else {
|
|
11223
11540
|
// string didn't match any beat effect syntax
|
|
@@ -14777,6 +15094,7 @@
|
|
|
14777
15094
|
this._trackCount = 0;
|
|
14778
15095
|
this._playbackInfos = [];
|
|
14779
15096
|
this._doubleBars = new Set();
|
|
15097
|
+
this._clefsPerTrack = new Map();
|
|
14780
15098
|
this._keySignatures = new Map();
|
|
14781
15099
|
this._beatTextChunksByTrack = new Map();
|
|
14782
15100
|
this._directionLookup = new Map();
|
|
@@ -15161,26 +15479,74 @@
|
|
|
15161
15479
|
mainStaff.capo = IOHelper.readInt32LE(this.data);
|
|
15162
15480
|
newTrack.color = GpBinaryHelpers.gpReadColor(this.data, false);
|
|
15163
15481
|
if (this._versionNumber >= 500) {
|
|
15164
|
-
const
|
|
15165
|
-
mainStaff.showTablature = (
|
|
15166
|
-
mainStaff.showStandardNotation = (
|
|
15167
|
-
const showChordDiagramListOnTopOfScore = (
|
|
15482
|
+
const staffFlags = this.data.readByte();
|
|
15483
|
+
mainStaff.showTablature = (staffFlags & 0x01) !== 0;
|
|
15484
|
+
mainStaff.showStandardNotation = (staffFlags & 0x02) !== 0;
|
|
15485
|
+
const showChordDiagramListOnTopOfScore = (staffFlags & 0x64) !== 0;
|
|
15168
15486
|
if (this._score.stylesheet.perTrackChordDiagramsOnTop === null) {
|
|
15169
15487
|
this._score.stylesheet.perTrackChordDiagramsOnTop = new Map();
|
|
15170
15488
|
}
|
|
15171
15489
|
this._score.stylesheet.perTrackChordDiagramsOnTop.set(newTrack.index, showChordDiagramListOnTopOfScore);
|
|
15172
|
-
//
|
|
15490
|
+
// MIDI: Automatic
|
|
15491
|
+
// 0x01 -> always set (unknown)
|
|
15173
15492
|
// 0x02 -> auto let ring
|
|
15174
15493
|
// 0x04 -> auto brush
|
|
15175
15494
|
this.data.readByte();
|
|
15176
|
-
//
|
|
15177
|
-
|
|
15495
|
+
// RSE: Auto-Accentuation on the Beat
|
|
15496
|
+
// 0 - None
|
|
15497
|
+
// 1 - Very Soft
|
|
15498
|
+
// 2 - Soft
|
|
15499
|
+
// 3 - Medium
|
|
15500
|
+
// 4 - Strong
|
|
15501
|
+
// 5 - Very Strong
|
|
15502
|
+
this.data.readByte();
|
|
15503
|
+
newTrack.playbackInfo.bank = this.data.readByte();
|
|
15504
|
+
// RSE: Human Playing (1 byte, 0-100%)
|
|
15505
|
+
this.data.readByte();
|
|
15506
|
+
// `12` for all tunings which have bass clefs
|
|
15507
|
+
const clefMode = IOHelper.readInt32LE(this.data);
|
|
15508
|
+
if (clefMode === 12) {
|
|
15509
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15510
|
+
}
|
|
15511
|
+
else {
|
|
15512
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15513
|
+
}
|
|
15514
|
+
// Unknown, no UI setting seem to affect this
|
|
15515
|
+
IOHelper.readInt32LE(this.data);
|
|
15516
|
+
// Unknown, no UI setting seem to affect this
|
|
15517
|
+
// typically: 100
|
|
15518
|
+
IOHelper.readInt32LE(this.data);
|
|
15519
|
+
// Unknown, no UI setting seem to affect this
|
|
15520
|
+
// typically: 1 2 3 4 5 6 7 8 9 10
|
|
15521
|
+
this.data.skip(10);
|
|
15522
|
+
// Unknown, no UI setting seem to affect this
|
|
15523
|
+
// typically: 255
|
|
15524
|
+
this.data.readByte();
|
|
15525
|
+
// Unknown, no UI setting seem to affect this
|
|
15526
|
+
// typically: 3
|
|
15527
|
+
this.data.readByte();
|
|
15528
|
+
this.readRseBank();
|
|
15529
|
+
// this.data.skip(42);
|
|
15530
|
+
if (this._versionNumber >= 510) {
|
|
15531
|
+
// RSE: 3-band EQ
|
|
15532
|
+
// 1 byte Low
|
|
15533
|
+
// 1 byte Mid
|
|
15534
|
+
// 1 byte High
|
|
15535
|
+
// 1 byte PRE
|
|
15536
|
+
this.data.skip(4);
|
|
15537
|
+
// RSE: effect name
|
|
15538
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15539
|
+
// RSE: effect category
|
|
15540
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15541
|
+
}
|
|
15178
15542
|
}
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
|
|
15182
|
-
|
|
15183
|
-
|
|
15543
|
+
else {
|
|
15544
|
+
if (GeneralMidi.isBass(newTrack.playbackInfo.program)) {
|
|
15545
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15546
|
+
}
|
|
15547
|
+
else {
|
|
15548
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15549
|
+
}
|
|
15184
15550
|
}
|
|
15185
15551
|
}
|
|
15186
15552
|
readBars() {
|
|
@@ -15196,6 +15562,9 @@
|
|
|
15196
15562
|
if (mainStaff.isPercussion) {
|
|
15197
15563
|
newBar.clef = Clef.Neutral;
|
|
15198
15564
|
}
|
|
15565
|
+
else if (this._clefsPerTrack.has(track.index)) {
|
|
15566
|
+
newBar.clef = this._clefsPerTrack.get(track.index);
|
|
15567
|
+
}
|
|
15199
15568
|
mainStaff.addBar(newBar);
|
|
15200
15569
|
if (this._keySignatures.has(newBar.index)) {
|
|
15201
15570
|
const newKeySignature = this._keySignatures.get(newBar.index);
|
|
@@ -15617,11 +15986,29 @@
|
|
|
15617
15986
|
return 0;
|
|
15618
15987
|
}
|
|
15619
15988
|
}
|
|
15989
|
+
readRseBank() {
|
|
15990
|
+
// RSE Banks on disk are having filenames like this: 033_2_002.ini
|
|
15991
|
+
// 033 is the RSE instrument (selected in the instrument list)
|
|
15992
|
+
// 2 seem to be some sort of style variation. e.g. bass has multiple variations (1,2), guitars have only 1, percussion has only 0
|
|
15993
|
+
// likely for organizational purposes
|
|
15994
|
+
// 002 is the effective soundbank (selected in the soundbank dropdown)
|
|
15995
|
+
// RSE Instrument
|
|
15996
|
+
this.data.skip(4); // IOHelper.readInt32LE(this.data);
|
|
15997
|
+
// RSE Style/Variation
|
|
15998
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15999
|
+
// RSE Soundbank
|
|
16000
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
16001
|
+
// Unknown, no UI setting seem to affect this
|
|
16002
|
+
// typically: -1
|
|
16003
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
16004
|
+
}
|
|
15620
16005
|
readMixTableChange(beat) {
|
|
15621
16006
|
const tableChange = new MixTableChange();
|
|
15622
16007
|
tableChange.instrument = IOHelper.readSInt8(this.data);
|
|
16008
|
+
// NOTE: The UI shows a Midi Bank selection, but this information is not stored in the file
|
|
16009
|
+
// when reopening the file the bank is always 0
|
|
15623
16010
|
if (this._versionNumber >= 500) {
|
|
15624
|
-
this.
|
|
16011
|
+
this.readRseBank();
|
|
15625
16012
|
}
|
|
15626
16013
|
tableChange.volume = IOHelper.readSInt8(this.data);
|
|
15627
16014
|
tableChange.balance = IOHelper.readSInt8(this.data);
|
|
@@ -15633,7 +16020,7 @@
|
|
|
15633
16020
|
tableChange.tempoName = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15634
16021
|
}
|
|
15635
16022
|
tableChange.tempo = IOHelper.readInt32LE(this.data);
|
|
15636
|
-
// durations
|
|
16023
|
+
// durations (in number of beats)
|
|
15637
16024
|
if (tableChange.volume >= 0) {
|
|
15638
16025
|
this.data.readByte();
|
|
15639
16026
|
}
|
|
@@ -15763,11 +16150,11 @@
|
|
|
15763
16150
|
newNote.fret = -1;
|
|
15764
16151
|
}
|
|
15765
16152
|
if (swapAccidentals) {
|
|
15766
|
-
const accidental =
|
|
15767
|
-
if (accidental ===
|
|
16153
|
+
const accidental = ModelUtils.computeAccidental(bar.keySignature, NoteAccidentalMode.Default, newNote.realValueWithoutHarmonic, false);
|
|
16154
|
+
if (accidental === AccidentalType.Sharp) {
|
|
15768
16155
|
newNote.accidentalMode = NoteAccidentalMode.ForceFlat;
|
|
15769
16156
|
}
|
|
15770
|
-
else if (accidental ===
|
|
16157
|
+
else if (accidental === AccidentalType.Flat) {
|
|
15771
16158
|
newNote.accidentalMode = NoteAccidentalMode.ForceSharp;
|
|
15772
16159
|
}
|
|
15773
16160
|
}
|
|
@@ -16616,9 +17003,7 @@
|
|
|
16616
17003
|
return writer.toArray();
|
|
16617
17004
|
}
|
|
16618
17005
|
static addHeaderAndFooter(binaryStylesheet, style, prefix, name) {
|
|
16619
|
-
|
|
16620
|
-
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16621
|
-
}
|
|
17006
|
+
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16622
17007
|
binaryStylesheet.addValue(`${prefix}${name}Alignment`, style.textAlign, DataType.Integer);
|
|
16623
17008
|
if (style.isVisible !== undefined) {
|
|
16624
17009
|
binaryStylesheet.addValue(`${prefix}draw${name}`, style.isVisible, DataType.Boolean);
|
|
@@ -16652,6 +17037,7 @@
|
|
|
16652
17037
|
this.path = '';
|
|
16653
17038
|
this.role = '';
|
|
16654
17039
|
this.program = 0;
|
|
17040
|
+
this.bank = 0;
|
|
16655
17041
|
}
|
|
16656
17042
|
get uniqueId() {
|
|
16657
17043
|
return `${this.path};${this.name};${this.role}`;
|
|
@@ -16667,6 +17053,7 @@
|
|
|
16667
17053
|
this._backingTrackPadding = 0;
|
|
16668
17054
|
this._doubleBars = new Set();
|
|
16669
17055
|
this._keySignatures = new Map();
|
|
17056
|
+
this._transposeKeySignaturePerTrack = new Map();
|
|
16670
17057
|
}
|
|
16671
17058
|
parseXml(xml, settings) {
|
|
16672
17059
|
this._masterTrackAutomations = new Map();
|
|
@@ -16897,7 +17284,8 @@
|
|
|
16897
17284
|
assetId = c.innerText;
|
|
16898
17285
|
break;
|
|
16899
17286
|
case 'FramePadding':
|
|
16900
|
-
this._backingTrackPadding =
|
|
17287
|
+
this._backingTrackPadding =
|
|
17288
|
+
(GpifParser.parseIntSafe(c.innerText, 0) / GpifParser.SampleRate) * 1000;
|
|
16901
17289
|
break;
|
|
16902
17290
|
}
|
|
16903
17291
|
}
|
|
@@ -17004,21 +17392,28 @@
|
|
|
17004
17392
|
if (!type) {
|
|
17005
17393
|
return;
|
|
17006
17394
|
}
|
|
17007
|
-
|
|
17395
|
+
const newAutomations = [];
|
|
17008
17396
|
switch (type) {
|
|
17009
17397
|
case 'Tempo':
|
|
17010
|
-
|
|
17398
|
+
newAutomations.push(Automation.buildTempoAutomation(isLinear, ratioPosition, numberValue, reference));
|
|
17011
17399
|
break;
|
|
17012
17400
|
case 'SyncPoint':
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17401
|
+
const syncPoint = new Automation();
|
|
17402
|
+
syncPoint.type = AutomationType.SyncPoint;
|
|
17403
|
+
syncPoint.isLinear = isLinear;
|
|
17404
|
+
syncPoint.ratioPosition = ratioPosition;
|
|
17405
|
+
syncPoint.syncPointValue = syncPointValue;
|
|
17406
|
+
newAutomations.push(syncPoint);
|
|
17018
17407
|
break;
|
|
17019
17408
|
case 'Sound':
|
|
17020
17409
|
if (textValue && sounds && sounds.has(textValue)) {
|
|
17021
|
-
|
|
17410
|
+
const bankChange = new Automation();
|
|
17411
|
+
bankChange.type = AutomationType.Bank;
|
|
17412
|
+
bankChange.ratioPosition = ratioPosition;
|
|
17413
|
+
bankChange.value = sounds.get(textValue).bank;
|
|
17414
|
+
newAutomations.push(bankChange);
|
|
17415
|
+
const programChange = Automation.buildInstrumentAutomation(isLinear, ratioPosition, sounds.get(textValue).program);
|
|
17416
|
+
newAutomations.push(programChange);
|
|
17022
17417
|
}
|
|
17023
17418
|
break;
|
|
17024
17419
|
case 'SustainPedal':
|
|
@@ -17046,15 +17441,19 @@
|
|
|
17046
17441
|
}
|
|
17047
17442
|
break;
|
|
17048
17443
|
}
|
|
17049
|
-
if (
|
|
17444
|
+
if (newAutomations.length) {
|
|
17050
17445
|
if (text) {
|
|
17051
|
-
|
|
17446
|
+
for (const a of newAutomations) {
|
|
17447
|
+
a.text = text;
|
|
17448
|
+
}
|
|
17052
17449
|
}
|
|
17053
17450
|
if (barIndex >= 0) {
|
|
17054
17451
|
if (!automations.has(barIndex)) {
|
|
17055
17452
|
automations.set(barIndex, []);
|
|
17056
17453
|
}
|
|
17057
|
-
|
|
17454
|
+
for (const a of newAutomations) {
|
|
17455
|
+
automations.get(barIndex).push(a);
|
|
17456
|
+
}
|
|
17058
17457
|
}
|
|
17059
17458
|
}
|
|
17060
17459
|
}
|
|
@@ -17133,13 +17532,13 @@
|
|
|
17133
17532
|
track.playbackInfo.isMute = state === 'Mute';
|
|
17134
17533
|
break;
|
|
17135
17534
|
case 'PartSounding':
|
|
17136
|
-
this.parsePartSounding(track, c);
|
|
17535
|
+
this.parsePartSounding(trackId, track, c);
|
|
17137
17536
|
break;
|
|
17138
17537
|
case 'Staves':
|
|
17139
17538
|
this.parseStaves(track, c);
|
|
17140
17539
|
break;
|
|
17141
17540
|
case 'Transpose':
|
|
17142
|
-
this.parseTranspose(track, c);
|
|
17541
|
+
this.parseTranspose(trackId, track, c);
|
|
17143
17542
|
break;
|
|
17144
17543
|
case 'RSE':
|
|
17145
17544
|
this.parseRSE(track, c);
|
|
@@ -17646,24 +18045,33 @@
|
|
|
17646
18045
|
break;
|
|
17647
18046
|
}
|
|
17648
18047
|
}
|
|
17649
|
-
if (sound.role === 'Factory' || track.playbackInfo.program === 0) {
|
|
17650
|
-
track.playbackInfo.program = sound.program;
|
|
17651
|
-
}
|
|
17652
18048
|
if (!this._soundsByTrack.has(trackId)) {
|
|
17653
18049
|
this._soundsByTrack.set(trackId, new Map());
|
|
18050
|
+
// apply first sound
|
|
18051
|
+
track.playbackInfo.program = sound.program;
|
|
18052
|
+
track.playbackInfo.bank = sound.bank;
|
|
17654
18053
|
}
|
|
17655
18054
|
this._soundsByTrack.get(trackId).set(sound.uniqueId, sound);
|
|
17656
18055
|
}
|
|
17657
18056
|
parseSoundMidi(sound, node) {
|
|
18057
|
+
let bankMsb = 0;
|
|
18058
|
+
let bankLsb = 0;
|
|
17658
18059
|
for (const c of node.childElements()) {
|
|
17659
18060
|
switch (c.localName) {
|
|
17660
18061
|
case 'Program':
|
|
17661
18062
|
sound.program = GpifParser.parseIntSafe(c.innerText, 0);
|
|
17662
18063
|
break;
|
|
18064
|
+
case 'MSB': // coarse
|
|
18065
|
+
bankMsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18066
|
+
break;
|
|
18067
|
+
case 'LSB': // Fine
|
|
18068
|
+
bankLsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18069
|
+
break;
|
|
17663
18070
|
}
|
|
17664
18071
|
}
|
|
18072
|
+
sound.bank = ((bankMsb & 0x7f) << 7) | bankLsb;
|
|
17665
18073
|
}
|
|
17666
|
-
parsePartSounding(track, node) {
|
|
18074
|
+
parsePartSounding(trackId, track, node) {
|
|
17667
18075
|
for (const c of node.childElements()) {
|
|
17668
18076
|
switch (c.localName) {
|
|
17669
18077
|
case 'TranspositionPitch':
|
|
@@ -17671,10 +18079,14 @@
|
|
|
17671
18079
|
staff.displayTranspositionPitch = GpifParser.parseIntSafe(c.innerText, 0);
|
|
17672
18080
|
}
|
|
17673
18081
|
break;
|
|
18082
|
+
case 'NominalKey':
|
|
18083
|
+
const transposeIndex = Math.max(0, Tuning.noteNames.indexOf(c.innerText));
|
|
18084
|
+
this._transposeKeySignaturePerTrack.set(trackId, transposeIndex);
|
|
18085
|
+
break;
|
|
17674
18086
|
}
|
|
17675
18087
|
}
|
|
17676
18088
|
}
|
|
17677
|
-
parseTranspose(track, node) {
|
|
18089
|
+
parseTranspose(trackId, track, node) {
|
|
17678
18090
|
let octave = 0;
|
|
17679
18091
|
let chromatic = 0;
|
|
17680
18092
|
for (const c of node.childElements()) {
|
|
@@ -17687,9 +18099,14 @@
|
|
|
17687
18099
|
break;
|
|
17688
18100
|
}
|
|
17689
18101
|
}
|
|
18102
|
+
const pitch = octave * 12 + chromatic;
|
|
17690
18103
|
for (const staff of track.staves) {
|
|
17691
|
-
staff.displayTranspositionPitch =
|
|
18104
|
+
staff.displayTranspositionPitch = pitch;
|
|
17692
18105
|
}
|
|
18106
|
+
// the chromatic transpose also causes an alternative key signature to be adjusted
|
|
18107
|
+
// In Guitar Pro this feature is hidden in the track properties (more -> Transposition tonality -> 'C played as:' ).
|
|
18108
|
+
const transposeIndex = ModelUtils.flooredDivision(pitch, 12);
|
|
18109
|
+
this._transposeKeySignaturePerTrack.set(trackId, transposeIndex);
|
|
17693
18110
|
}
|
|
17694
18111
|
parseRSE(track, node) {
|
|
17695
18112
|
for (const c of node.childElements()) {
|
|
@@ -18653,6 +19070,7 @@
|
|
|
18653
19070
|
// GP6 had percussion as element+variation
|
|
18654
19071
|
let element = -1;
|
|
18655
19072
|
let variation = -1;
|
|
19073
|
+
let hasTransposedPitch = false;
|
|
18656
19074
|
for (const c of node.childElements()) {
|
|
18657
19075
|
switch (c.localName) {
|
|
18658
19076
|
case 'Property':
|
|
@@ -18733,7 +19151,15 @@
|
|
|
18733
19151
|
note.tone = GpifParser.parseIntSafe(c.findChildElement('Step')?.innerText, 0);
|
|
18734
19152
|
break;
|
|
18735
19153
|
case 'ConcertPitch':
|
|
19154
|
+
if (!hasTransposedPitch) {
|
|
19155
|
+
this.parseConcertPitch(c, note);
|
|
19156
|
+
}
|
|
19157
|
+
break;
|
|
19158
|
+
case 'TransposedPitch':
|
|
19159
|
+
// clear potential value from concert pitch
|
|
19160
|
+
note.accidentalMode = NoteAccidentalMode.Default;
|
|
18736
19161
|
this.parseConcertPitch(c, note);
|
|
19162
|
+
hasTransposedPitch = true;
|
|
18737
19163
|
break;
|
|
18738
19164
|
case 'Bended':
|
|
18739
19165
|
isBended = true;
|
|
@@ -18947,20 +19373,29 @@
|
|
|
18947
19373
|
lastMasterBar.isDoubleBar = false;
|
|
18948
19374
|
}
|
|
18949
19375
|
// add tracks to score
|
|
19376
|
+
const trackIndexToTrackId = [];
|
|
18950
19377
|
for (const trackId of this._tracksMapping) {
|
|
18951
19378
|
if (!trackId) {
|
|
18952
19379
|
continue;
|
|
18953
19380
|
}
|
|
18954
19381
|
const track = this._tracksById.get(trackId);
|
|
18955
19382
|
this.score.addTrack(track);
|
|
19383
|
+
trackIndexToTrackId.push(trackId);
|
|
18956
19384
|
}
|
|
18957
19385
|
// process all masterbars
|
|
18958
19386
|
let keySignature;
|
|
18959
19387
|
for (const barIds of this._barsOfMasterBar) {
|
|
18960
19388
|
// add all bars of masterbar vertically to all tracks
|
|
18961
19389
|
let staffIndex = 0;
|
|
19390
|
+
let trackIndex = 0;
|
|
18962
19391
|
keySignature = [KeySignature.C, KeySignatureType.Major];
|
|
18963
|
-
|
|
19392
|
+
if (this._transposeKeySignaturePerTrack.has(trackIndexToTrackId[0])) {
|
|
19393
|
+
keySignature = [
|
|
19394
|
+
ModelUtils.transposeKey(keySignature[0], this._transposeKeySignaturePerTrack.get(trackIndexToTrackId[0])),
|
|
19395
|
+
keySignature[1]
|
|
19396
|
+
];
|
|
19397
|
+
}
|
|
19398
|
+
for (let barIndex = 0; barIndex < barIds.length && trackIndex < this.score.tracks.length; barIndex++) {
|
|
18964
19399
|
const barId = barIds[barIndex];
|
|
18965
19400
|
if (barId !== GpifParser.InvalidId) {
|
|
18966
19401
|
const bar = this._barsById.get(barId);
|
|
@@ -18970,6 +19405,12 @@
|
|
|
18970
19405
|
const masterBarIndex = staff.bars.length - 1;
|
|
18971
19406
|
if (this._keySignatures.has(masterBarIndex)) {
|
|
18972
19407
|
keySignature = this._keySignatures.get(masterBarIndex);
|
|
19408
|
+
if (this._transposeKeySignaturePerTrack.has(trackIndexToTrackId[trackIndex])) {
|
|
19409
|
+
keySignature = [
|
|
19410
|
+
ModelUtils.transposeKey(keySignature[0], this._transposeKeySignaturePerTrack.get(trackIndexToTrackId[trackIndex])),
|
|
19411
|
+
keySignature[1]
|
|
19412
|
+
];
|
|
19413
|
+
}
|
|
18973
19414
|
}
|
|
18974
19415
|
bar.keySignature = keySignature[0];
|
|
18975
19416
|
bar.keySignatureType = keySignature[1];
|
|
@@ -19036,11 +19477,17 @@
|
|
|
19036
19477
|
if (staffIndex === track.staves.length - 1) {
|
|
19037
19478
|
trackIndex++;
|
|
19038
19479
|
staffIndex = 0;
|
|
19039
|
-
keySignature = [KeySignature.C, KeySignatureType.Major];
|
|
19040
19480
|
}
|
|
19041
19481
|
else {
|
|
19042
19482
|
staffIndex++;
|
|
19043
|
-
|
|
19483
|
+
}
|
|
19484
|
+
keySignature = [KeySignature.C, KeySignatureType.Major];
|
|
19485
|
+
if (trackIndex < trackIndexToTrackId.length &&
|
|
19486
|
+
this._transposeKeySignaturePerTrack.has(trackIndexToTrackId[trackIndex])) {
|
|
19487
|
+
keySignature = [
|
|
19488
|
+
ModelUtils.transposeKey(keySignature[0], this._transposeKeySignaturePerTrack.get(trackIndexToTrackId[trackIndex])),
|
|
19489
|
+
keySignature[1]
|
|
19490
|
+
];
|
|
19044
19491
|
}
|
|
19045
19492
|
}
|
|
19046
19493
|
else {
|
|
@@ -19076,7 +19523,12 @@
|
|
|
19076
19523
|
for (const a of automations) {
|
|
19077
19524
|
// NOTE: currently the automations of a bar are applied to the
|
|
19078
19525
|
// first beat of a bar
|
|
19079
|
-
|
|
19526
|
+
const skip =
|
|
19527
|
+
// skip bank automations if they are 0 at start
|
|
19528
|
+
a.type === AutomationType.Bank && a.value === 0 && bar.index === 0;
|
|
19529
|
+
if (!skip) {
|
|
19530
|
+
beat.automations.push(a);
|
|
19531
|
+
}
|
|
19080
19532
|
}
|
|
19081
19533
|
}
|
|
19082
19534
|
}
|
|
@@ -19128,7 +19580,7 @@
|
|
|
19128
19580
|
*/
|
|
19129
19581
|
GpifParser.BendPointValueFactor = 1 / 25.0;
|
|
19130
19582
|
// tests have shown that Guitar Pro seem to always work with 44100hz for the frame offsets,
|
|
19131
|
-
// they are NOT using the sample rate of the input file.
|
|
19583
|
+
// they are NOT using the sample rate of the input file.
|
|
19132
19584
|
// Downsampling a 44100hz ogg to 8000hz and using it in as audio track resulted in the same frame offset when placing sync points.
|
|
19133
19585
|
GpifParser.SampleRate = 44100;
|
|
19134
19586
|
|
|
@@ -19823,49 +20275,6 @@
|
|
|
19823
20275
|
}
|
|
19824
20276
|
}
|
|
19825
20277
|
|
|
19826
|
-
/**
|
|
19827
|
-
* Defines all possible accidentals for notes.
|
|
19828
|
-
*/
|
|
19829
|
-
var AccidentalType;
|
|
19830
|
-
(function (AccidentalType) {
|
|
19831
|
-
/**
|
|
19832
|
-
* No accidental
|
|
19833
|
-
*/
|
|
19834
|
-
AccidentalType[AccidentalType["None"] = 0] = "None";
|
|
19835
|
-
/**
|
|
19836
|
-
* Naturalize
|
|
19837
|
-
*/
|
|
19838
|
-
AccidentalType[AccidentalType["Natural"] = 1] = "Natural";
|
|
19839
|
-
/**
|
|
19840
|
-
* Sharp
|
|
19841
|
-
*/
|
|
19842
|
-
AccidentalType[AccidentalType["Sharp"] = 2] = "Sharp";
|
|
19843
|
-
/**
|
|
19844
|
-
* Flat
|
|
19845
|
-
*/
|
|
19846
|
-
AccidentalType[AccidentalType["Flat"] = 3] = "Flat";
|
|
19847
|
-
/**
|
|
19848
|
-
* Natural for smear bends
|
|
19849
|
-
*/
|
|
19850
|
-
AccidentalType[AccidentalType["NaturalQuarterNoteUp"] = 4] = "NaturalQuarterNoteUp";
|
|
19851
|
-
/**
|
|
19852
|
-
* Sharp for smear bends
|
|
19853
|
-
*/
|
|
19854
|
-
AccidentalType[AccidentalType["SharpQuarterNoteUp"] = 5] = "SharpQuarterNoteUp";
|
|
19855
|
-
/**
|
|
19856
|
-
* Flat for smear bends
|
|
19857
|
-
*/
|
|
19858
|
-
AccidentalType[AccidentalType["FlatQuarterNoteUp"] = 6] = "FlatQuarterNoteUp";
|
|
19859
|
-
/**
|
|
19860
|
-
* Double Sharp, indicated by an 'x'
|
|
19861
|
-
*/
|
|
19862
|
-
AccidentalType[AccidentalType["DoubleSharp"] = 7] = "DoubleSharp";
|
|
19863
|
-
/**
|
|
19864
|
-
* Double Flat, indicated by 'bb'
|
|
19865
|
-
*/
|
|
19866
|
-
AccidentalType[AccidentalType["DoubleFlat"] = 8] = "DoubleFlat";
|
|
19867
|
-
})(AccidentalType || (AccidentalType = {}));
|
|
19868
|
-
|
|
19869
20278
|
class BeatLines {
|
|
19870
20279
|
constructor() {
|
|
19871
20280
|
this.maxLine = -1e3;
|
|
@@ -19968,90 +20377,6 @@
|
|
|
19968
20377
|
}
|
|
19969
20378
|
return line;
|
|
19970
20379
|
}
|
|
19971
|
-
static computeAccidental(keySignature, accidentalMode, noteValue, quarterBend, currentAccidental = null) {
|
|
19972
|
-
const ks = keySignature;
|
|
19973
|
-
const ksi = ks + 7;
|
|
19974
|
-
const index = noteValue % 12;
|
|
19975
|
-
const accidentalForKeySignature = ksi < 7 ? AccidentalType.Flat : AccidentalType.Sharp;
|
|
19976
|
-
const hasKeySignatureAccidentalSetForNote = AccidentalHelper.KeySignatureLookup[ksi][index];
|
|
19977
|
-
const hasNoteAccidentalWithinOctave = AccidentalHelper.AccidentalNotes[index];
|
|
19978
|
-
// the general logic is like this:
|
|
19979
|
-
// - we check if the key signature has an accidental defined
|
|
19980
|
-
// - we calculate which accidental a note needs according to its index in the octave
|
|
19981
|
-
// - if the accidental is already placed at this line, nothing needs to be done, otherwise we place it
|
|
19982
|
-
// - if there should not be an accidental, but there is one in the key signature, we clear it.
|
|
19983
|
-
// the exceptions are:
|
|
19984
|
-
// - for quarter bends we just place the corresponding accidental
|
|
19985
|
-
// - the accidental mode can enforce the accidentals for the note
|
|
19986
|
-
let accidentalToSet = AccidentalType.None;
|
|
19987
|
-
if (quarterBend) {
|
|
19988
|
-
accidentalToSet = hasNoteAccidentalWithinOctave ? accidentalForKeySignature : AccidentalType.Natural;
|
|
19989
|
-
switch (accidentalToSet) {
|
|
19990
|
-
case AccidentalType.Natural:
|
|
19991
|
-
accidentalToSet = AccidentalType.NaturalQuarterNoteUp;
|
|
19992
|
-
break;
|
|
19993
|
-
case AccidentalType.Sharp:
|
|
19994
|
-
accidentalToSet = AccidentalType.SharpQuarterNoteUp;
|
|
19995
|
-
break;
|
|
19996
|
-
case AccidentalType.Flat:
|
|
19997
|
-
accidentalToSet = AccidentalType.FlatQuarterNoteUp;
|
|
19998
|
-
break;
|
|
19999
|
-
}
|
|
20000
|
-
}
|
|
20001
|
-
else {
|
|
20002
|
-
// define which accidental should be shown ignoring what might be set on the KS already
|
|
20003
|
-
switch (accidentalMode) {
|
|
20004
|
-
case NoteAccidentalMode.ForceSharp:
|
|
20005
|
-
accidentalToSet = AccidentalType.Sharp;
|
|
20006
|
-
break;
|
|
20007
|
-
case NoteAccidentalMode.ForceDoubleSharp:
|
|
20008
|
-
accidentalToSet = AccidentalType.DoubleSharp;
|
|
20009
|
-
break;
|
|
20010
|
-
case NoteAccidentalMode.ForceFlat:
|
|
20011
|
-
accidentalToSet = AccidentalType.Flat;
|
|
20012
|
-
break;
|
|
20013
|
-
case NoteAccidentalMode.ForceDoubleFlat:
|
|
20014
|
-
accidentalToSet = AccidentalType.DoubleFlat;
|
|
20015
|
-
break;
|
|
20016
|
-
default:
|
|
20017
|
-
// if note has an accidental in the octave, we place a symbol
|
|
20018
|
-
// according to the Key Signature
|
|
20019
|
-
if (hasNoteAccidentalWithinOctave) {
|
|
20020
|
-
accidentalToSet = accidentalForKeySignature;
|
|
20021
|
-
}
|
|
20022
|
-
else if (hasKeySignatureAccidentalSetForNote) {
|
|
20023
|
-
// note does not get an accidental, but KS defines one -> Naturalize
|
|
20024
|
-
accidentalToSet = AccidentalType.Natural;
|
|
20025
|
-
}
|
|
20026
|
-
break;
|
|
20027
|
-
}
|
|
20028
|
-
// do we need an accidental on the note?
|
|
20029
|
-
if (accidentalToSet !== AccidentalType.None) {
|
|
20030
|
-
// if there is no accidental on the line, and the key signature has it set already, we clear it on the note
|
|
20031
|
-
if (currentAccidental != null) {
|
|
20032
|
-
if (currentAccidental === accidentalToSet) {
|
|
20033
|
-
accidentalToSet = AccidentalType.None;
|
|
20034
|
-
}
|
|
20035
|
-
}
|
|
20036
|
-
else if (hasKeySignatureAccidentalSetForNote && accidentalToSet === accidentalForKeySignature) {
|
|
20037
|
-
accidentalToSet = AccidentalType.None;
|
|
20038
|
-
}
|
|
20039
|
-
}
|
|
20040
|
-
else {
|
|
20041
|
-
// if we don't want an accidental, but there is already one applied, we place a naturalize accidental
|
|
20042
|
-
// and clear the registration
|
|
20043
|
-
if (currentAccidental !== null) {
|
|
20044
|
-
if (currentAccidental === AccidentalType.Natural) {
|
|
20045
|
-
accidentalToSet = AccidentalType.None;
|
|
20046
|
-
}
|
|
20047
|
-
else {
|
|
20048
|
-
accidentalToSet = AccidentalType.Natural;
|
|
20049
|
-
}
|
|
20050
|
-
}
|
|
20051
|
-
}
|
|
20052
|
-
}
|
|
20053
|
-
return accidentalToSet;
|
|
20054
|
-
}
|
|
20055
20380
|
getAccidental(noteValue, quarterBend, relatedBeat, isHelperNote, note = null) {
|
|
20056
20381
|
let steps = 0;
|
|
20057
20382
|
let accidentalToSet = AccidentalType.None;
|
|
@@ -20065,7 +20390,7 @@
|
|
|
20065
20390
|
const currentAccidental = this._registeredAccidentals.has(steps)
|
|
20066
20391
|
? this._registeredAccidentals.get(steps)
|
|
20067
20392
|
: null;
|
|
20068
|
-
accidentalToSet =
|
|
20393
|
+
accidentalToSet = ModelUtils.computeAccidental(this._bar.keySignature, accidentalMode, noteValue, quarterBend, currentAccidental);
|
|
20069
20394
|
let skipAccidental = false;
|
|
20070
20395
|
switch (accidentalToSet) {
|
|
20071
20396
|
case AccidentalType.NaturalQuarterNoteUp:
|
|
@@ -20179,48 +20504,6 @@
|
|
|
20179
20504
|
return 0;
|
|
20180
20505
|
}
|
|
20181
20506
|
}
|
|
20182
|
-
/**
|
|
20183
|
-
* a lookup list containing an info whether the notes within an octave
|
|
20184
|
-
* need an accidental rendered. the accidental symbol is determined based on the type of key signature.
|
|
20185
|
-
*/
|
|
20186
|
-
AccidentalHelper.KeySignatureLookup = [
|
|
20187
|
-
// Flats (where the value is true, a flat accidental is required for the notes)
|
|
20188
|
-
[true, true, true, true, true, true, true, true, true, true, true, true],
|
|
20189
|
-
[true, true, true, true, true, false, true, true, true, true, true, true],
|
|
20190
|
-
[false, true, true, true, true, false, true, true, true, true, true, true],
|
|
20191
|
-
[false, true, true, true, true, false, false, false, true, true, true, true],
|
|
20192
|
-
[false, false, false, true, true, false, false, false, true, true, true, true],
|
|
20193
|
-
[false, false, false, true, true, false, false, false, false, false, true, true],
|
|
20194
|
-
[false, false, false, false, false, false, false, false, false, false, true, true],
|
|
20195
|
-
// natural
|
|
20196
|
-
[false, false, false, false, false, false, false, false, false, false, false, false],
|
|
20197
|
-
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
20198
|
-
[false, false, false, false, false, true, true, false, false, false, false, false],
|
|
20199
|
-
[true, true, false, false, false, true, true, false, false, false, false, false],
|
|
20200
|
-
[true, true, false, false, false, true, true, true, true, false, false, false],
|
|
20201
|
-
[true, true, true, true, false, true, true, true, true, false, false, false],
|
|
20202
|
-
[true, true, true, true, false, true, true, true, true, true, true, false],
|
|
20203
|
-
[true, true, true, true, true, true, true, true, true, true, true, false],
|
|
20204
|
-
[true, true, true, true, true, true, true, true, true, true, true, true]
|
|
20205
|
-
];
|
|
20206
|
-
/**
|
|
20207
|
-
* Contains the list of notes within an octave have accidentals set.
|
|
20208
|
-
*/
|
|
20209
|
-
// prettier-ignore
|
|
20210
|
-
AccidentalHelper.AccidentalNotes = [
|
|
20211
|
-
false,
|
|
20212
|
-
true,
|
|
20213
|
-
false,
|
|
20214
|
-
true,
|
|
20215
|
-
false,
|
|
20216
|
-
false,
|
|
20217
|
-
true,
|
|
20218
|
-
false,
|
|
20219
|
-
true,
|
|
20220
|
-
false,
|
|
20221
|
-
true,
|
|
20222
|
-
false
|
|
20223
|
-
];
|
|
20224
20507
|
/**
|
|
20225
20508
|
* We always have 7 steps per octave.
|
|
20226
20509
|
* (by a step the offsets inbetween score lines is meant,
|
|
@@ -20265,6 +20548,10 @@
|
|
|
20265
20548
|
* The midi channel program to use when playing the note (-1 if using the default track program).
|
|
20266
20549
|
*/
|
|
20267
20550
|
this.outputMidiProgram = -1;
|
|
20551
|
+
/**
|
|
20552
|
+
* The midi bank to use when playing the note (-1 if using the default track bank).
|
|
20553
|
+
*/
|
|
20554
|
+
this.outputMidiBank = -1;
|
|
20268
20555
|
/**
|
|
20269
20556
|
* The volume to use when playing the note (-1 if using the default track volume).
|
|
20270
20557
|
*/
|
|
@@ -20763,6 +21050,9 @@
|
|
|
20763
21050
|
if (trackInfo.firstArticulation.outputMidiProgram >= 0) {
|
|
20764
21051
|
track.playbackInfo.program = trackInfo.firstArticulation.outputMidiProgram;
|
|
20765
21052
|
}
|
|
21053
|
+
if (trackInfo.firstArticulation.outputMidiBank >= 0) {
|
|
21054
|
+
track.playbackInfo.bank = trackInfo.firstArticulation.outputMidiBank;
|
|
21055
|
+
}
|
|
20766
21056
|
if (trackInfo.firstArticulation.outputBalance >= 0) {
|
|
20767
21057
|
track.playbackInfo.balance = trackInfo.firstArticulation.outputBalance;
|
|
20768
21058
|
}
|
|
@@ -20794,7 +21084,9 @@
|
|
|
20794
21084
|
articulation.outputMidiChannel = Number.parseInt(c.innerText) - 1;
|
|
20795
21085
|
break;
|
|
20796
21086
|
// case 'midi-name': Ignored
|
|
20797
|
-
|
|
21087
|
+
case 'midi-bank':
|
|
21088
|
+
articulation.outputMidiBank = Number.parseInt(c.innerText) - 1;
|
|
21089
|
+
break;
|
|
20798
21090
|
case 'midi-program':
|
|
20799
21091
|
articulation.outputMidiProgram = Number.parseInt(c.innerText) - 1;
|
|
20800
21092
|
break;
|
|
@@ -21324,7 +21616,15 @@
|
|
|
21324
21616
|
switch (c.localName) {
|
|
21325
21617
|
// case 'midi-channel': Ignored
|
|
21326
21618
|
// case 'midi-name': Ignored
|
|
21327
|
-
|
|
21619
|
+
case 'midi-bank':
|
|
21620
|
+
if (!this._nextBeatAutomations) {
|
|
21621
|
+
this._nextBeatAutomations = [];
|
|
21622
|
+
}
|
|
21623
|
+
automation = new Automation();
|
|
21624
|
+
automation.type = AutomationType.Bank;
|
|
21625
|
+
automation.value = Number.parseInt(c.innerText) - 1;
|
|
21626
|
+
this._nextBeatAutomations.push(automation);
|
|
21627
|
+
break;
|
|
21328
21628
|
case 'midi-program':
|
|
21329
21629
|
if (!this._nextBeatAutomations) {
|
|
21330
21630
|
this._nextBeatAutomations = [];
|
|
@@ -23595,11 +23895,15 @@
|
|
|
23595
23895
|
}
|
|
23596
23896
|
|
|
23597
23897
|
class EventEmitter {
|
|
23598
|
-
constructor() {
|
|
23898
|
+
constructor(fireOnRegister = undefined) {
|
|
23599
23899
|
this._listeners = [];
|
|
23900
|
+
this._fireOnRegister = fireOnRegister;
|
|
23600
23901
|
}
|
|
23601
23902
|
on(value) {
|
|
23602
23903
|
this._listeners.push(value);
|
|
23904
|
+
if (this._fireOnRegister?.()) {
|
|
23905
|
+
value();
|
|
23906
|
+
}
|
|
23603
23907
|
return () => {
|
|
23604
23908
|
this.off(value);
|
|
23605
23909
|
};
|
|
@@ -23617,11 +23921,18 @@
|
|
|
23617
23921
|
* @partial
|
|
23618
23922
|
*/
|
|
23619
23923
|
class EventEmitterOfT {
|
|
23620
|
-
constructor() {
|
|
23924
|
+
constructor(fireOnRegister = undefined) {
|
|
23621
23925
|
this._listeners = [];
|
|
23926
|
+
this._fireOnRegister = fireOnRegister;
|
|
23622
23927
|
}
|
|
23623
23928
|
on(value) {
|
|
23624
23929
|
this._listeners.push(value);
|
|
23930
|
+
if (this._fireOnRegister) {
|
|
23931
|
+
const arg = this._fireOnRegister();
|
|
23932
|
+
if (arg !== null) {
|
|
23933
|
+
value(arg);
|
|
23934
|
+
}
|
|
23935
|
+
}
|
|
23625
23936
|
return () => {
|
|
23626
23937
|
this.off(value);
|
|
23627
23938
|
};
|
|
@@ -30662,6 +30973,12 @@
|
|
|
30662
30973
|
this.sequencer.playbackSpeed = value;
|
|
30663
30974
|
this.timePosition = this.timePosition * (oldSpeed / value);
|
|
30664
30975
|
}
|
|
30976
|
+
get loadedMidiInfo() {
|
|
30977
|
+
return this._loadedMidiInfo;
|
|
30978
|
+
}
|
|
30979
|
+
get currentPosition() {
|
|
30980
|
+
return this._currentPosition;
|
|
30981
|
+
}
|
|
30665
30982
|
get tickPosition() {
|
|
30666
30983
|
return this._tickPosition;
|
|
30667
30984
|
}
|
|
@@ -30719,22 +31036,38 @@
|
|
|
30719
31036
|
this._midiEventsPlayedFilter = new Set();
|
|
30720
31037
|
this._notPlayedSamples = 0;
|
|
30721
31038
|
this._synthStopping = false;
|
|
31039
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
30722
31040
|
this.isReady = false;
|
|
30723
31041
|
this.state = PlayerState.Paused;
|
|
30724
31042
|
this._loadedSoundFonts = [];
|
|
30725
|
-
this.ready = new EventEmitter();
|
|
30726
31043
|
this.readyForPlayback = new EventEmitter();
|
|
30727
31044
|
this.finished = new EventEmitter();
|
|
30728
31045
|
this.soundFontLoaded = new EventEmitter();
|
|
30729
31046
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
30730
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
30731
31047
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
30732
|
-
this.stateChanged = new EventEmitterOfT();
|
|
30733
|
-
this.positionChanged = new EventEmitterOfT();
|
|
30734
31048
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
30735
|
-
this.playbackRangeChanged = new EventEmitterOfT();
|
|
30736
31049
|
Logger.debug('AlphaSynth', 'Initializing player');
|
|
30737
31050
|
this.state = PlayerState.Paused;
|
|
31051
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
31052
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
31053
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
31054
|
+
if (this._loadedMidiInfo) {
|
|
31055
|
+
return this._loadedMidiInfo;
|
|
31056
|
+
}
|
|
31057
|
+
return null;
|
|
31058
|
+
});
|
|
31059
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
31060
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
31061
|
+
});
|
|
31062
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
31063
|
+
return this._currentPosition;
|
|
31064
|
+
});
|
|
31065
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
31066
|
+
if (this.playbackRange) {
|
|
31067
|
+
return new PlaybackRangeChangedEventArgs(this.playbackRange);
|
|
31068
|
+
}
|
|
31069
|
+
return null;
|
|
31070
|
+
});
|
|
30738
31071
|
Logger.debug('AlphaSynth', 'Creating output');
|
|
30739
31072
|
this._output = output;
|
|
30740
31073
|
Logger.debug('AlphaSynth', 'Creating synthesizer');
|
|
@@ -30912,7 +31245,8 @@
|
|
|
30912
31245
|
Logger.debug('AlphaSynth', 'Loading midi from model');
|
|
30913
31246
|
this.sequencer.loadMidi(midi);
|
|
30914
31247
|
this._isMidiLoaded = true;
|
|
30915
|
-
this.
|
|
31248
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(0, this.sequencer.currentEndTime, 0, this.sequencer.currentEndTick, false, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31249
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
30916
31250
|
Logger.debug('AlphaSynth', 'Midi successfully loaded');
|
|
30917
31251
|
this.checkReadyForPlayback();
|
|
30918
31252
|
this.tickPosition = 0;
|
|
@@ -31015,23 +31349,28 @@
|
|
|
31015
31349
|
this.sequencer.resetOneTimeMidi();
|
|
31016
31350
|
this.timePosition = this.sequencer.currentTime;
|
|
31017
31351
|
}
|
|
31018
|
-
|
|
31019
|
-
//
|
|
31020
|
-
let currentTime =
|
|
31021
|
-
this._timePosition = currentTime;
|
|
31352
|
+
createPositionChangedEventArgs(isSeek) {
|
|
31353
|
+
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31354
|
+
let currentTime = this._timePosition;
|
|
31022
31355
|
let currentTick = this.sequencer.currentTimePositionToTickPosition(currentTime);
|
|
31023
|
-
this._tickPosition = currentTick;
|
|
31024
31356
|
const endTime = this.sequencer.currentEndTime;
|
|
31025
31357
|
const endTick = this.sequencer.currentEndTick;
|
|
31026
|
-
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31027
31358
|
if (currentTime > endTime) {
|
|
31028
31359
|
currentTime = endTime;
|
|
31029
31360
|
currentTick = endTick;
|
|
31030
31361
|
}
|
|
31362
|
+
return new PositionChangedEventArgs(currentTime, endTime, currentTick, endTick, isSeek, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31363
|
+
}
|
|
31364
|
+
updateTimePosition(timePosition, isSeek) {
|
|
31365
|
+
// update the real positions
|
|
31366
|
+
this._timePosition = timePosition;
|
|
31367
|
+
const args = this.createPositionChangedEventArgs(isSeek);
|
|
31368
|
+
this._tickPosition = args.currentTick;
|
|
31031
31369
|
const mode = this.sequencer.isPlayingMain ? 'main' : this.sequencer.isPlayingCountIn ? 'count-in' : 'one-time';
|
|
31032
|
-
Logger.debug('AlphaSynth', `Position changed: (time: ${currentTime}/${endTime}, tick: ${currentTick}/${endTick}, Active Voices: ${this.synthesizer.activeVoiceCount} (${mode}), Tempo original: ${this.sequencer.currentTempo}, Tempo modified: ${this.sequencer.modifiedTempo})`);
|
|
31370
|
+
Logger.debug('AlphaSynth', `Position changed: (time: ${args.currentTime}/${args.endTime}, tick: ${args.currentTick}/${args.endTick}, Active Voices: ${this.synthesizer.activeVoiceCount} (${mode}), Tempo original: ${this.sequencer.currentTempo}, Tempo modified: ${this.sequencer.modifiedTempo})`);
|
|
31033
31371
|
if (this.sequencer.isPlayingMain) {
|
|
31034
|
-
this.
|
|
31372
|
+
this._currentPosition = args;
|
|
31373
|
+
this.positionChanged.trigger(args);
|
|
31035
31374
|
}
|
|
31036
31375
|
// build events which were actually played
|
|
31037
31376
|
if (isSeek) {
|
|
@@ -31039,7 +31378,7 @@
|
|
|
31039
31378
|
}
|
|
31040
31379
|
else {
|
|
31041
31380
|
const playedEvents = [];
|
|
31042
|
-
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < currentTime) {
|
|
31381
|
+
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < args.currentTime) {
|
|
31043
31382
|
const synthEvent = this._playedEventsQueue.dequeue();
|
|
31044
31383
|
playedEvents.push(synthEvent.event);
|
|
31045
31384
|
}
|
|
@@ -36490,6 +36829,15 @@
|
|
|
36490
36829
|
fillFromJson(json) {
|
|
36491
36830
|
SettingsSerializer.fromJson(this, json);
|
|
36492
36831
|
}
|
|
36832
|
+
/**
|
|
36833
|
+
* handles backwards compatibility aspects on the settings, removed in 2.0
|
|
36834
|
+
* @internal
|
|
36835
|
+
*/
|
|
36836
|
+
handleBackwardsCompatibility() {
|
|
36837
|
+
if (this.player.playerMode === exports.PlayerMode.Disabled && this.player.enablePlayer) {
|
|
36838
|
+
this.player.playerMode = exports.PlayerMode.EnabledAutomatic;
|
|
36839
|
+
}
|
|
36840
|
+
}
|
|
36493
36841
|
}
|
|
36494
36842
|
|
|
36495
36843
|
class SectionSerializer {
|
|
@@ -37707,6 +38055,7 @@
|
|
|
37707
38055
|
o.set("balance", obj.balance);
|
|
37708
38056
|
o.set("port", obj.port);
|
|
37709
38057
|
o.set("program", obj.program);
|
|
38058
|
+
o.set("bank", obj.bank);
|
|
37710
38059
|
o.set("primarychannel", obj.primaryChannel);
|
|
37711
38060
|
o.set("secondarychannel", obj.secondaryChannel);
|
|
37712
38061
|
o.set("ismute", obj.isMute);
|
|
@@ -37727,6 +38076,9 @@
|
|
|
37727
38076
|
case "program":
|
|
37728
38077
|
obj.program = v;
|
|
37729
38078
|
return true;
|
|
38079
|
+
case "bank":
|
|
38080
|
+
obj.bank = v;
|
|
38081
|
+
return true;
|
|
37730
38082
|
case "primarychannel":
|
|
37731
38083
|
obj.primaryChannel = v;
|
|
37732
38084
|
return true;
|
|
@@ -41385,6 +41737,11 @@
|
|
|
41385
41737
|
this._programsPerChannel.set(channel, program);
|
|
41386
41738
|
}
|
|
41387
41739
|
}
|
|
41740
|
+
addBankChange(track, tick, channel, bank) {
|
|
41741
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
41742
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectCoarse, lsbMsb[1]);
|
|
41743
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectFine, lsbMsb[0]);
|
|
41744
|
+
}
|
|
41388
41745
|
static buildTranspositionPitches(score, settings) {
|
|
41389
41746
|
const transpositionPitches = new Map();
|
|
41390
41747
|
for (const track of score.tracks) {
|
|
@@ -41412,6 +41769,7 @@
|
|
|
41412
41769
|
// Set PitchBendRangeCoarse to 12
|
|
41413
41770
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryFine, 0);
|
|
41414
41771
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryCoarse, MidiFileGenerator.PitchBendRangeInSemitones);
|
|
41772
|
+
this.addBankChange(track, 0, channel, playbackInfo.bank);
|
|
41415
41773
|
this.addProgramChange(track, 0, channel, playbackInfo.program);
|
|
41416
41774
|
}
|
|
41417
41775
|
/**
|
|
@@ -42707,6 +43065,10 @@
|
|
|
42707
43065
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, (automation.value | 0) & 0xff);
|
|
42708
43066
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, (automation.value | 0) & 0xff);
|
|
42709
43067
|
break;
|
|
43068
|
+
case AutomationType.Bank:
|
|
43069
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, automation.value);
|
|
43070
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, automation.value);
|
|
43071
|
+
break;
|
|
42710
43072
|
case AutomationType.Balance:
|
|
42711
43073
|
const balance = MidiFileGenerator.toChannelShort(automation.value);
|
|
42712
43074
|
this._handler.addControlChange(beat.voice.bar.staff.track.index, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, ControllerType.PanCoarse, balance);
|
|
@@ -43656,17 +44018,29 @@
|
|
|
43656
44018
|
this._playbackSpeed = 1;
|
|
43657
44019
|
this._isLooping = false;
|
|
43658
44020
|
this._midiEventsPlayedFilter = [];
|
|
43659
|
-
this.ready = new EventEmitter();
|
|
43660
|
-
this.readyForPlayback = new EventEmitter();
|
|
43661
44021
|
this.finished = new EventEmitter();
|
|
43662
44022
|
this.soundFontLoaded = new EventEmitter();
|
|
43663
44023
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
43664
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
43665
44024
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
43666
|
-
this.stateChanged = new EventEmitterOfT();
|
|
43667
|
-
this.positionChanged = new EventEmitterOfT();
|
|
43668
44025
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
43669
|
-
this.
|
|
44026
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
44027
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
44028
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
44029
|
+
return this._instance?.loadedMidiInfo ?? null;
|
|
44030
|
+
});
|
|
44031
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
44032
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
44033
|
+
});
|
|
44034
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
44035
|
+
return this.currentPosition;
|
|
44036
|
+
});
|
|
44037
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
44038
|
+
const range = this.playbackRange;
|
|
44039
|
+
if (range) {
|
|
44040
|
+
return new PlaybackRangeChangedEventArgs(range);
|
|
44041
|
+
}
|
|
44042
|
+
return null;
|
|
44043
|
+
});
|
|
43670
44044
|
}
|
|
43671
44045
|
get instance() {
|
|
43672
44046
|
return this._instance;
|
|
@@ -43688,10 +44062,14 @@
|
|
|
43688
44062
|
newUnregister.push(value.finished.on(() => this.finished.trigger()));
|
|
43689
44063
|
newUnregister.push(value.soundFontLoaded.on(() => this.soundFontLoaded.trigger()));
|
|
43690
44064
|
newUnregister.push(value.soundFontLoadFailed.on(e => this.soundFontLoadFailed.trigger(e)));
|
|
43691
|
-
newUnregister.push(value.midiLoaded.on(e =>
|
|
44065
|
+
newUnregister.push(value.midiLoaded.on(e => {
|
|
44066
|
+
this.midiLoaded.trigger(e);
|
|
44067
|
+
}));
|
|
43692
44068
|
newUnregister.push(value.midiLoadFailed.on(e => this.midiLoadFailed.trigger(e)));
|
|
43693
44069
|
newUnregister.push(value.stateChanged.on(e => this.stateChanged.trigger(e)));
|
|
43694
|
-
newUnregister.push(value.positionChanged.on(e =>
|
|
44070
|
+
newUnregister.push(value.positionChanged.on(e => {
|
|
44071
|
+
this.positionChanged.trigger(e);
|
|
44072
|
+
}));
|
|
43695
44073
|
newUnregister.push(value.midiEventsPlayed.on(e => this.midiEventsPlayed.trigger(e)));
|
|
43696
44074
|
newUnregister.push(value.playbackRangeChanged.on(e => this.playbackRangeChanged.trigger(e)));
|
|
43697
44075
|
this._instanceEventUnregister = newUnregister;
|
|
@@ -43770,6 +44148,14 @@
|
|
|
43770
44148
|
this._instance.playbackSpeed = value;
|
|
43771
44149
|
}
|
|
43772
44150
|
}
|
|
44151
|
+
get loadedMidiInfo() {
|
|
44152
|
+
return this._instance ? this._instance.loadedMidiInfo : undefined;
|
|
44153
|
+
}
|
|
44154
|
+
get currentPosition() {
|
|
44155
|
+
return this._instance
|
|
44156
|
+
? this._instance.currentPosition
|
|
44157
|
+
: new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
44158
|
+
}
|
|
43773
44159
|
get tickPosition() {
|
|
43774
44160
|
return this._instance ? this._instance.tickPosition : 0;
|
|
43775
44161
|
}
|
|
@@ -44111,83 +44497,6 @@
|
|
|
44111
44497
|
this._previousStateForCursor = PlayerState.Paused;
|
|
44112
44498
|
this._previousCursorCache = null;
|
|
44113
44499
|
this._lastScroll = 0;
|
|
44114
|
-
/**
|
|
44115
|
-
* This event is fired when the played beat changed.
|
|
44116
|
-
*
|
|
44117
|
-
* @eventProperty
|
|
44118
|
-
* @category Events - Player
|
|
44119
|
-
* @since 0.9.4
|
|
44120
|
-
*
|
|
44121
|
-
* @example
|
|
44122
|
-
* JavaScript
|
|
44123
|
-
* ```js
|
|
44124
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44125
|
-
* api.playedBeatChanged.on((beat) => {
|
|
44126
|
-
* updateFretboard(beat);
|
|
44127
|
-
* });
|
|
44128
|
-
* ```
|
|
44129
|
-
*
|
|
44130
|
-
* @example
|
|
44131
|
-
* C#
|
|
44132
|
-
* ```cs
|
|
44133
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44134
|
-
* api.PlayedBeatChanged.On(beat =>
|
|
44135
|
-
* {
|
|
44136
|
-
* UpdateFretboard(beat);
|
|
44137
|
-
* });
|
|
44138
|
-
* ```
|
|
44139
|
-
*
|
|
44140
|
-
* @example
|
|
44141
|
-
* Android
|
|
44142
|
-
* ```kotlin
|
|
44143
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44144
|
-
* api.playedBeatChanged.on { beat ->
|
|
44145
|
-
* updateFretboard(beat)
|
|
44146
|
-
* }
|
|
44147
|
-
* ```
|
|
44148
|
-
*
|
|
44149
|
-
*/
|
|
44150
|
-
this.playedBeatChanged = new EventEmitterOfT();
|
|
44151
|
-
/**
|
|
44152
|
-
* This event is fired when the currently active beats across all tracks change.
|
|
44153
|
-
*
|
|
44154
|
-
* @remarks
|
|
44155
|
-
* Unlike the {@link playedBeatChanged} event this event contains the beats of all tracks and voices independent of them being rendered.
|
|
44156
|
-
*
|
|
44157
|
-
* @eventProperty
|
|
44158
|
-
* @category Events - Player
|
|
44159
|
-
* @since 1.2.3
|
|
44160
|
-
*
|
|
44161
|
-
* @example
|
|
44162
|
-
* JavaScript
|
|
44163
|
-
* ```js
|
|
44164
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44165
|
-
* api.activeBeatsChanged.on(args => {
|
|
44166
|
-
* updateHighlights(args.activeBeats);
|
|
44167
|
-
* });
|
|
44168
|
-
* ```
|
|
44169
|
-
*
|
|
44170
|
-
* @example
|
|
44171
|
-
* C#
|
|
44172
|
-
* ```cs
|
|
44173
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44174
|
-
* api.ActiveBeatsChanged.On(args =>
|
|
44175
|
-
* {
|
|
44176
|
-
* UpdateHighlights(args.ActiveBeats);
|
|
44177
|
-
* });
|
|
44178
|
-
* ```
|
|
44179
|
-
*
|
|
44180
|
-
* @example
|
|
44181
|
-
* Android
|
|
44182
|
-
* ```kotlin
|
|
44183
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44184
|
-
* api.activeBeatsChanged.on { args ->
|
|
44185
|
-
* updateHighlights(args.activeBeats)
|
|
44186
|
-
* }
|
|
44187
|
-
* ```
|
|
44188
|
-
*
|
|
44189
|
-
*/
|
|
44190
|
-
this.activeBeatsChanged = new EventEmitterOfT();
|
|
44191
44500
|
this._beatMouseDown = false;
|
|
44192
44501
|
this._noteMouseDown = false;
|
|
44193
44502
|
this._selectionStart = null;
|
|
@@ -44426,47 +44735,6 @@
|
|
|
44426
44735
|
*
|
|
44427
44736
|
*/
|
|
44428
44737
|
this.noteMouseUp = new EventEmitterOfT();
|
|
44429
|
-
/**
|
|
44430
|
-
* This event is fired whenever a new song is loaded.
|
|
44431
|
-
* @remarks
|
|
44432
|
-
* This event is fired whenever a new song is loaded or changing due to {@link renderScore} or {@link renderTracks} calls.
|
|
44433
|
-
* It is fired after the transposition midi pitches from the settings were applied, but before any midi is generated or rendering is started.
|
|
44434
|
-
* This allows any modification of the score before further processing.
|
|
44435
|
-
*
|
|
44436
|
-
* @eventProperty
|
|
44437
|
-
* @category Events - Core
|
|
44438
|
-
* @since 0.9.4
|
|
44439
|
-
*
|
|
44440
|
-
* @example
|
|
44441
|
-
* JavaScript
|
|
44442
|
-
* ```js
|
|
44443
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44444
|
-
* api.scoreLoaded.on((score) => {
|
|
44445
|
-
* updateSongInformationInUi(score);
|
|
44446
|
-
* });
|
|
44447
|
-
* ```
|
|
44448
|
-
*
|
|
44449
|
-
* @example
|
|
44450
|
-
* C#
|
|
44451
|
-
* ```cs
|
|
44452
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44453
|
-
* api.ScoreLoaded.On(score =>
|
|
44454
|
-
* {
|
|
44455
|
-
* UpdateSongInformationInUi(score);
|
|
44456
|
-
* });
|
|
44457
|
-
* ```
|
|
44458
|
-
*
|
|
44459
|
-
* @example
|
|
44460
|
-
* Android
|
|
44461
|
-
* ```kotlin
|
|
44462
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44463
|
-
* api.scoreLoaded.on { score ->
|
|
44464
|
-
* updateSongInformationInUi(score)
|
|
44465
|
-
* }
|
|
44466
|
-
* ```
|
|
44467
|
-
*
|
|
44468
|
-
*/
|
|
44469
|
-
this.scoreLoaded = new EventEmitterOfT();
|
|
44470
44738
|
/**
|
|
44471
44739
|
* This event is fired when alphaTab was resized and is about to rerender the music notation.
|
|
44472
44740
|
* @remarks
|
|
@@ -44725,46 +44993,6 @@
|
|
|
44725
44993
|
*
|
|
44726
44994
|
*/
|
|
44727
44995
|
this.midiLoad = new EventEmitterOfT();
|
|
44728
|
-
/**
|
|
44729
|
-
* This event is fired when the Midi file needed for playback was loaded.
|
|
44730
|
-
*
|
|
44731
|
-
* @eventProperty
|
|
44732
|
-
* @category Events - Player
|
|
44733
|
-
* @since 0.9.4
|
|
44734
|
-
*
|
|
44735
|
-
* @example
|
|
44736
|
-
* JavaScript
|
|
44737
|
-
* ```js
|
|
44738
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44739
|
-
* api.midiLoaded.on(e => {
|
|
44740
|
-
* hideGeneratingAudioIndicator();
|
|
44741
|
-
* updateSongDuration(e.endTime);
|
|
44742
|
-
* });
|
|
44743
|
-
* ```
|
|
44744
|
-
*
|
|
44745
|
-
* @example
|
|
44746
|
-
* C#
|
|
44747
|
-
* ```cs
|
|
44748
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44749
|
-
* api.MidiLoaded.On(e =>
|
|
44750
|
-
* {
|
|
44751
|
-
* HideGeneratingAudioIndicator();
|
|
44752
|
-
* UpdateSongDuration(e.EndTime);
|
|
44753
|
-
* });
|
|
44754
|
-
* ```
|
|
44755
|
-
*
|
|
44756
|
-
* @example
|
|
44757
|
-
* Android
|
|
44758
|
-
* ```kotlin
|
|
44759
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44760
|
-
* api.midiLoaded.on { e ->
|
|
44761
|
-
* hideGeneratingAudioIndicator()
|
|
44762
|
-
* updateSongDuration(e.endTime)
|
|
44763
|
-
* }
|
|
44764
|
-
* ```
|
|
44765
|
-
*
|
|
44766
|
-
*/
|
|
44767
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
44768
44996
|
/**
|
|
44769
44997
|
* This event is fired when a settings update was requested.
|
|
44770
44998
|
*
|
|
@@ -44804,12 +45032,30 @@
|
|
|
44804
45032
|
this.settingsUpdated = new EventEmitter();
|
|
44805
45033
|
this.uiFacade = uiFacade;
|
|
44806
45034
|
this.container = uiFacade.rootContainer;
|
|
45035
|
+
this.activeBeatsChanged = new EventEmitterOfT(() => {
|
|
45036
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45037
|
+
return new ActiveBeatsChangedEventArgs(this._currentBeat.beatLookup.highlightedBeats.map(h => h.beat));
|
|
45038
|
+
}
|
|
45039
|
+
return null;
|
|
45040
|
+
});
|
|
45041
|
+
this.playedBeatChanged = new EventEmitterOfT(() => {
|
|
45042
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45043
|
+
return this._currentBeat.beat;
|
|
45044
|
+
}
|
|
45045
|
+
return null;
|
|
45046
|
+
});
|
|
45047
|
+
this.scoreLoaded = new EventEmitterOfT(() => {
|
|
45048
|
+
if (this._score) {
|
|
45049
|
+
return this._score;
|
|
45050
|
+
}
|
|
45051
|
+
return null;
|
|
45052
|
+
});
|
|
45053
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
45054
|
+
return this._player.loadedMidiInfo ?? null;
|
|
45055
|
+
});
|
|
44807
45056
|
uiFacade.initialize(this, settings);
|
|
44808
45057
|
Logger.logLevel = this.settings.core.logLevel;
|
|
44809
|
-
|
|
44810
|
-
if (this.settings.player.playerMode === exports.PlayerMode.Disabled && this.settings.player.enablePlayer) {
|
|
44811
|
-
this.settings.player.playerMode = exports.PlayerMode.EnabledAutomatic;
|
|
44812
|
-
}
|
|
45058
|
+
this.settings.handleBackwardsCompatibility();
|
|
44813
45059
|
Environment.printEnvironmentInfo(false);
|
|
44814
45060
|
this.canvasElement = uiFacade.createCanvasElement();
|
|
44815
45061
|
this.container.appendChild(this.canvasElement);
|
|
@@ -44968,6 +45214,7 @@
|
|
|
44968
45214
|
* ```
|
|
44969
45215
|
*/
|
|
44970
45216
|
updateSettings() {
|
|
45217
|
+
this.settings.handleBackwardsCompatibility();
|
|
44971
45218
|
const score = this.score;
|
|
44972
45219
|
if (score) {
|
|
44973
45220
|
ModelUtils.applyPitchOffsets(this.settings, score);
|
|
@@ -45775,6 +46022,22 @@
|
|
|
45775
46022
|
set timePosition(value) {
|
|
45776
46023
|
this._player.timePosition = value;
|
|
45777
46024
|
}
|
|
46025
|
+
/**
|
|
46026
|
+
* The total length of the song in midi ticks.
|
|
46027
|
+
* @category Properties - Player
|
|
46028
|
+
* @since 1.6.2
|
|
46029
|
+
*/
|
|
46030
|
+
get endTick() {
|
|
46031
|
+
return this._player.currentPosition.endTick;
|
|
46032
|
+
}
|
|
46033
|
+
/**
|
|
46034
|
+
* The total length of the song in milliseconds.
|
|
46035
|
+
* @category Properties - Player
|
|
46036
|
+
* @since 1.6.2
|
|
46037
|
+
*/
|
|
46038
|
+
get endTime() {
|
|
46039
|
+
return this._player.currentPosition.endTime;
|
|
46040
|
+
}
|
|
45778
46041
|
/**
|
|
45779
46042
|
* The range of the song that should be played.
|
|
45780
46043
|
* @remarks
|
|
@@ -48099,27 +48362,33 @@
|
|
|
48099
48362
|
value: value
|
|
48100
48363
|
});
|
|
48101
48364
|
}
|
|
48365
|
+
get loadedMidiInfo() {
|
|
48366
|
+
return this.loadedMidiInfo;
|
|
48367
|
+
}
|
|
48368
|
+
get currentPosition() {
|
|
48369
|
+
return this._currentPosition;
|
|
48370
|
+
}
|
|
48102
48371
|
get tickPosition() {
|
|
48103
|
-
return this.
|
|
48372
|
+
return this._currentPosition.currentTick;
|
|
48104
48373
|
}
|
|
48105
48374
|
set tickPosition(value) {
|
|
48106
48375
|
if (value < 0) {
|
|
48107
48376
|
value = 0;
|
|
48108
48377
|
}
|
|
48109
|
-
this.
|
|
48378
|
+
this._currentPosition = new PositionChangedEventArgs(this._currentPosition.currentTime, this._currentPosition.endTime, value, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48110
48379
|
this._synth.postMessage({
|
|
48111
48380
|
cmd: 'alphaSynth.setTickPosition',
|
|
48112
48381
|
value: value
|
|
48113
48382
|
});
|
|
48114
48383
|
}
|
|
48115
48384
|
get timePosition() {
|
|
48116
|
-
return this.
|
|
48385
|
+
return this._currentPosition.currentTime;
|
|
48117
48386
|
}
|
|
48118
48387
|
set timePosition(value) {
|
|
48119
48388
|
if (value < 0) {
|
|
48120
48389
|
value = 0;
|
|
48121
48390
|
}
|
|
48122
|
-
this.
|
|
48391
|
+
this._currentPosition = new PositionChangedEventArgs(value, this._currentPosition.endTime, this._currentPosition.currentTick, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48123
48392
|
this._synth.postMessage({
|
|
48124
48393
|
cmd: 'alphaSynth.setTimePosition',
|
|
48125
48394
|
value: value
|
|
@@ -48162,11 +48431,10 @@
|
|
|
48162
48431
|
this._metronomeVolume = 0;
|
|
48163
48432
|
this._countInVolume = 0;
|
|
48164
48433
|
this._playbackSpeed = 0;
|
|
48165
|
-
this._tickPosition = 0;
|
|
48166
|
-
this._timePosition = 0;
|
|
48167
48434
|
this._isLooping = false;
|
|
48168
48435
|
this._playbackRange = null;
|
|
48169
48436
|
this._midiEventsPlayedFilter = [];
|
|
48437
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
48170
48438
|
this.ready = new EventEmitter();
|
|
48171
48439
|
this.readyForPlayback = new EventEmitter();
|
|
48172
48440
|
this.finished = new EventEmitter();
|
|
@@ -48185,8 +48453,6 @@
|
|
|
48185
48453
|
this._masterVolume = 0.0;
|
|
48186
48454
|
this._metronomeVolume = 0.0;
|
|
48187
48455
|
this._playbackSpeed = 0.0;
|
|
48188
|
-
this._tickPosition = 0;
|
|
48189
|
-
this._timePosition = 0.0;
|
|
48190
48456
|
this._isLooping = false;
|
|
48191
48457
|
this._playbackRange = null;
|
|
48192
48458
|
this._output = player;
|
|
@@ -48321,9 +48587,8 @@
|
|
|
48321
48587
|
this.checkReadyForPlayback();
|
|
48322
48588
|
break;
|
|
48323
48589
|
case 'alphaSynth.positionChanged':
|
|
48324
|
-
this.
|
|
48325
|
-
this.
|
|
48326
|
-
this.positionChanged.trigger(new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo));
|
|
48590
|
+
this._currentPosition = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48591
|
+
this.positionChanged.trigger(this._currentPosition);
|
|
48327
48592
|
break;
|
|
48328
48593
|
case 'alphaSynth.midiEventsPlayed':
|
|
48329
48594
|
this.midiEventsPlayed.trigger(new MidiEventsPlayedEventArgs(data.events.map(JsonConverter.jsObjectToMidiEvent)));
|
|
@@ -48347,7 +48612,8 @@
|
|
|
48347
48612
|
break;
|
|
48348
48613
|
case 'alphaSynth.midiLoaded':
|
|
48349
48614
|
this.checkReadyForPlayback();
|
|
48350
|
-
this.
|
|
48615
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48616
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
48351
48617
|
break;
|
|
48352
48618
|
case 'alphaSynth.midiLoadFailed':
|
|
48353
48619
|
this.checkReadyForPlayback();
|
|
@@ -59059,7 +59325,7 @@
|
|
|
59059
59325
|
// - when the standard notation naturalizes the accidental from the key signature, the numbered notation has the reversed accidental
|
|
59060
59326
|
const accidentalMode = note ? note.accidentalMode : NoteAccidentalMode.Default;
|
|
59061
59327
|
const noteValue = AccidentalHelper.getNoteValue(note);
|
|
59062
|
-
let accidentalToSet =
|
|
59328
|
+
let accidentalToSet = ModelUtils.computeAccidental(this.renderer.bar.keySignature, accidentalMode, noteValue, note.hasQuarterToneOffset);
|
|
59063
59329
|
if (accidentalToSet === AccidentalType.Natural) {
|
|
59064
59330
|
const ks = this.renderer.bar.keySignature;
|
|
59065
59331
|
const ksi = ks + 7;
|
|
@@ -59218,7 +59484,7 @@
|
|
|
59218
59484
|
? AccidentalHelper.FlatNoteSteps
|
|
59219
59485
|
: AccidentalHelper.SharpNoteSteps;
|
|
59220
59486
|
let steps = stepList[index] + 1;
|
|
59221
|
-
const hasAccidental =
|
|
59487
|
+
const hasAccidental = ModelUtils.AccidentalNotes[index];
|
|
59222
59488
|
if (hasAccidental &&
|
|
59223
59489
|
!this.container.preNotes.isNaturalizeAccidental) {
|
|
59224
59490
|
if (ksi < 7) {
|
|
@@ -66431,6 +66697,30 @@
|
|
|
66431
66697
|
if (stylesheet.useSystemSignSeparator) {
|
|
66432
66698
|
writer.writeMeta('useSystemSignSeparator');
|
|
66433
66699
|
}
|
|
66700
|
+
if (stylesheet.multiTrackMultiBarRest) {
|
|
66701
|
+
writer.writeMeta('multiBarRest');
|
|
66702
|
+
}
|
|
66703
|
+
if (stylesheet.singleTrackTrackNamePolicy !==
|
|
66704
|
+
AlphaTexExporter.DefaultScore.stylesheet.singleTrackTrackNamePolicy) {
|
|
66705
|
+
writer.writeMeta('singleTrackTrackNamePolicy', TrackNamePolicy[stylesheet.singleTrackTrackNamePolicy]);
|
|
66706
|
+
}
|
|
66707
|
+
if (stylesheet.multiTrackTrackNamePolicy !== AlphaTexExporter.DefaultScore.stylesheet.multiTrackTrackNamePolicy) {
|
|
66708
|
+
writer.writeMeta('multiTrackTrackNamePolicy', TrackNamePolicy[stylesheet.multiTrackTrackNamePolicy]);
|
|
66709
|
+
}
|
|
66710
|
+
if (stylesheet.firstSystemTrackNameMode !== AlphaTexExporter.DefaultScore.stylesheet.firstSystemTrackNameMode) {
|
|
66711
|
+
writer.writeMeta('firstSystemTrackNameMode', TrackNameMode[stylesheet.firstSystemTrackNameMode]);
|
|
66712
|
+
}
|
|
66713
|
+
if (stylesheet.otherSystemsTrackNameMode !== AlphaTexExporter.DefaultScore.stylesheet.otherSystemsTrackNameMode) {
|
|
66714
|
+
writer.writeMeta('otherSystemsTrackNameMode', TrackNameMode[stylesheet.otherSystemsTrackNameMode]);
|
|
66715
|
+
}
|
|
66716
|
+
if (stylesheet.firstSystemTrackNameOrientation !==
|
|
66717
|
+
AlphaTexExporter.DefaultScore.stylesheet.firstSystemTrackNameOrientation) {
|
|
66718
|
+
writer.writeMeta('firstSystemTrackNameOrientation', TrackNameOrientation[stylesheet.firstSystemTrackNameOrientation]);
|
|
66719
|
+
}
|
|
66720
|
+
if (stylesheet.otherSystemsTrackNameOrientation !==
|
|
66721
|
+
AlphaTexExporter.DefaultScore.stylesheet.otherSystemsTrackNameOrientation) {
|
|
66722
|
+
writer.writeMeta('otherSystemsTrackNameOrientation', TrackNameOrientation[stylesheet.otherSystemsTrackNameOrientation]);
|
|
66723
|
+
}
|
|
66434
66724
|
}
|
|
66435
66725
|
writeTrackTo(writer, track) {
|
|
66436
66726
|
writer.write('\\track ');
|
|
@@ -66466,6 +66756,10 @@
|
|
|
66466
66756
|
track.score.stylesheet.perTrackMultiBarRest.has(track.index)) {
|
|
66467
66757
|
writer.writeLine(` multibarrest`);
|
|
66468
66758
|
}
|
|
66759
|
+
writer.writeLine(` instrument ${track.isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program)}`);
|
|
66760
|
+
if (track.playbackInfo.bank > 0) {
|
|
66761
|
+
writer.writeLine(` bank ${track.playbackInfo.bank}`);
|
|
66762
|
+
}
|
|
66469
66763
|
writer.outdent();
|
|
66470
66764
|
writer.writeLine('}');
|
|
66471
66765
|
writer.indent();
|
|
@@ -66524,13 +66818,7 @@
|
|
|
66524
66818
|
writer.writeLine('|');
|
|
66525
66819
|
}
|
|
66526
66820
|
if (voiceIndex === 0) {
|
|
66527
|
-
// Track meta on first bar
|
|
66528
66821
|
let anyWritten = false;
|
|
66529
|
-
if (bar.index === 0 && bar.staff.index === 0) {
|
|
66530
|
-
const l = writer.tex.length;
|
|
66531
|
-
this.writeTrackMetaTo(writer, bar.staff.track);
|
|
66532
|
-
anyWritten = writer.tex.length > l;
|
|
66533
|
-
}
|
|
66534
66822
|
// Staff meta on first bar
|
|
66535
66823
|
if (bar.index === 0) {
|
|
66536
66824
|
const l = writer.tex.length;
|
|
@@ -66560,14 +66848,6 @@
|
|
|
66560
66848
|
}
|
|
66561
66849
|
writer.outdent();
|
|
66562
66850
|
}
|
|
66563
|
-
writeTrackMetaTo(writer, track) {
|
|
66564
|
-
writer.writeSingleLineComment(`Track ${track.index + 1} Metadata`);
|
|
66565
|
-
this.writePlaybackInfoTo(writer, track);
|
|
66566
|
-
}
|
|
66567
|
-
writePlaybackInfoTo(writer, track) {
|
|
66568
|
-
const isPercussion = track.staves.some(s => s.isPercussion);
|
|
66569
|
-
writer.writeMeta('instrument', isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program));
|
|
66570
|
-
}
|
|
66571
66851
|
writeStaffMetaTo(writer, staff) {
|
|
66572
66852
|
writer.writeSingleLineComment(`Staff ${staff.index + 1} Metadata`);
|
|
66573
66853
|
if (staff.capo !== 0) {
|
|
@@ -66600,6 +66880,7 @@
|
|
|
66600
66880
|
if (staff.displayTranspositionPitch !== defaultTransposition) {
|
|
66601
66881
|
writer.writeMeta('displaytranspose', `${-staff.displayTranspositionPitch}`);
|
|
66602
66882
|
}
|
|
66883
|
+
writer.writeMeta('accidentals', 'auto');
|
|
66603
66884
|
if (staff.chords != null) {
|
|
66604
66885
|
for (const [_, chord] of staff.chords) {
|
|
66605
66886
|
this.writeChordTo(writer, chord);
|
|
@@ -66967,6 +67248,18 @@
|
|
|
66967
67248
|
writer.writeGroupItem('txt ');
|
|
66968
67249
|
writer.writeString(beat.text);
|
|
66969
67250
|
}
|
|
67251
|
+
if (beat.lyrics != null && beat.lyrics.length > 0) {
|
|
67252
|
+
if (beat.lyrics.length > 1) {
|
|
67253
|
+
for (let i = 0; i < beat.lyrics.length; i++) {
|
|
67254
|
+
writer.writeGroupItem(`lyrics ${i} `);
|
|
67255
|
+
writer.writeString(beat.lyrics[i]);
|
|
67256
|
+
}
|
|
67257
|
+
}
|
|
67258
|
+
else {
|
|
67259
|
+
writer.writeGroupItem('lyrics ');
|
|
67260
|
+
writer.writeString(beat.lyrics[0]);
|
|
67261
|
+
}
|
|
67262
|
+
}
|
|
66970
67263
|
switch (beat.graceType) {
|
|
66971
67264
|
case GraceType.OnBeat:
|
|
66972
67265
|
writer.writeGroupItem('gr ob');
|
|
@@ -67601,7 +67894,7 @@
|
|
|
67601
67894
|
this.writePitch(properties, 'ConcertPitch', 'C', '-1', '');
|
|
67602
67895
|
}
|
|
67603
67896
|
else {
|
|
67604
|
-
this.writePitchForValue(properties, 'TransposedPitch', note.displayValueWithoutBend, note.accidentalMode);
|
|
67897
|
+
this.writePitchForValue(properties, 'TransposedPitch', note.displayValueWithoutBend, note.accidentalMode, note.beat.voice.bar.keySignature);
|
|
67605
67898
|
}
|
|
67606
67899
|
}
|
|
67607
67900
|
writeConcertPitch(properties, note) {
|
|
@@ -67609,10 +67902,10 @@
|
|
|
67609
67902
|
this.writePitch(properties, 'ConcertPitch', 'C', '-1', '');
|
|
67610
67903
|
}
|
|
67611
67904
|
else {
|
|
67612
|
-
this.writePitchForValue(properties, 'ConcertPitch', note.realValueWithoutHarmonic, note.accidentalMode);
|
|
67905
|
+
this.writePitchForValue(properties, 'ConcertPitch', note.realValueWithoutHarmonic, note.accidentalMode, note.beat.voice.bar.keySignature);
|
|
67613
67906
|
}
|
|
67614
67907
|
}
|
|
67615
|
-
writePitchForValue(properties, propertyName, value, accidentalMode) {
|
|
67908
|
+
writePitchForValue(properties, propertyName, value, accidentalMode, keySignature) {
|
|
67616
67909
|
let index = 0;
|
|
67617
67910
|
let octave = 0;
|
|
67618
67911
|
let step = '';
|
|
@@ -67620,8 +67913,25 @@
|
|
|
67620
67913
|
const updateParts = () => {
|
|
67621
67914
|
index = value % 12;
|
|
67622
67915
|
octave = (value / 12) | 0;
|
|
67623
|
-
step =
|
|
67624
|
-
|
|
67916
|
+
step = GpifWriter.defaultSteps[index];
|
|
67917
|
+
switch (ModelUtils.computeAccidental(keySignature, NoteAccidentalMode.Default, value, false)) {
|
|
67918
|
+
case AccidentalType.None:
|
|
67919
|
+
case AccidentalType.Natural:
|
|
67920
|
+
accidental = '';
|
|
67921
|
+
break;
|
|
67922
|
+
case AccidentalType.Sharp:
|
|
67923
|
+
accidental = '#';
|
|
67924
|
+
break;
|
|
67925
|
+
case AccidentalType.Flat:
|
|
67926
|
+
accidental = 'b';
|
|
67927
|
+
break;
|
|
67928
|
+
case AccidentalType.DoubleSharp:
|
|
67929
|
+
accidental = 'x';
|
|
67930
|
+
break;
|
|
67931
|
+
case AccidentalType.DoubleFlat:
|
|
67932
|
+
accidental = 'bb';
|
|
67933
|
+
break;
|
|
67934
|
+
}
|
|
67625
67935
|
};
|
|
67626
67936
|
updateParts();
|
|
67627
67937
|
switch (accidentalMode) {
|
|
@@ -68096,10 +68406,12 @@
|
|
|
68096
68406
|
const value = syncPointAutomation.addElement('Value');
|
|
68097
68407
|
value.addElement('BarIndex').innerText = mb.index.toString();
|
|
68098
68408
|
value.addElement('BarOccurrence').innerText = syncPoint.syncPointValue.barOccurence.toString();
|
|
68099
|
-
value.addElement('ModifiedTempo').innerText = modifiedTempoLookup.value
|
|
68409
|
+
value.addElement('ModifiedTempo').innerText = modifiedTempoLookup.value
|
|
68410
|
+
.get(syncPoint)
|
|
68411
|
+
.syncBpm.toString();
|
|
68100
68412
|
value.addElement('OriginalTempo').innerText = score.tempo.toString();
|
|
68101
|
-
let frameOffset = ((
|
|
68102
|
-
GpifWriter.SampleRate
|
|
68413
|
+
let frameOffset = ((syncPoint.syncPointValue.millisecondOffset - millisecondPadding) / 1000) *
|
|
68414
|
+
GpifWriter.SampleRate;
|
|
68103
68415
|
frameOffset = Math.floor(frameOffset + 0.5);
|
|
68104
68416
|
value.addElement('FrameOffset').innerText = frameOffset.toString();
|
|
68105
68417
|
}
|
|
@@ -68158,15 +68470,16 @@
|
|
|
68158
68470
|
}
|
|
68159
68471
|
return GpifIconIds.SteelGuitar;
|
|
68160
68472
|
}
|
|
68161
|
-
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, ratioPosition = 0) {
|
|
68473
|
+
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, bank, ratioPosition = 0) {
|
|
68162
68474
|
const soundNode = soundsNode.addElement('Sound');
|
|
68163
68475
|
soundNode.addElement('Name').setCData(name);
|
|
68164
68476
|
soundNode.addElement('Label').setCData(name);
|
|
68165
68477
|
soundNode.addElement('Path').setCData(path);
|
|
68166
68478
|
soundNode.addElement('Role').setCData(role);
|
|
68167
68479
|
const midi = soundNode.addElement('MIDI');
|
|
68168
|
-
|
|
68169
|
-
midi.addElement('
|
|
68480
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
68481
|
+
midi.addElement('LSB').innerText = lsbMsb[0].toString();
|
|
68482
|
+
midi.addElement('MSB').innerText = lsbMsb[1].toString();
|
|
68170
68483
|
midi.addElement('Program').innerText = program.toString();
|
|
68171
68484
|
const automationNode = automationsNode.addElement('Automation');
|
|
68172
68485
|
automationNode.addElement('Type').innerText = 'Sound';
|
|
@@ -68184,21 +68497,26 @@
|
|
|
68184
68497
|
const trackSoundPath = `Midi/${track.playbackInfo.program}`;
|
|
68185
68498
|
const trackSoundRole = 'Factory';
|
|
68186
68499
|
let trackSoundWritten = false;
|
|
68500
|
+
let bank = track.playbackInfo.bank;
|
|
68187
68501
|
for (const staff of track.staves) {
|
|
68188
68502
|
for (const bar of staff.bars) {
|
|
68189
68503
|
for (const voice of bar.voices) {
|
|
68190
68504
|
for (const beat of voice.beats) {
|
|
68191
68505
|
const soundAutomation = beat.getAutomation(AutomationType.Instrument);
|
|
68192
68506
|
const isTrackSound = bar.index === 0 && beat.index === 0;
|
|
68507
|
+
const bankAutomation = beat.getAutomation(AutomationType.Bank);
|
|
68508
|
+
if (bankAutomation) {
|
|
68509
|
+
bank = bankAutomation.value;
|
|
68510
|
+
}
|
|
68193
68511
|
if (soundAutomation) {
|
|
68194
68512
|
const name = isTrackSound ? trackSoundName : `ProgramChange_${beat.id}`;
|
|
68195
68513
|
const path = isTrackSound ? trackSoundPath : `Midi/${soundAutomation.value}`;
|
|
68196
68514
|
const role = isTrackSound ? trackSoundRole : 'User';
|
|
68197
68515
|
if (!isTrackSound && !trackSoundWritten) {
|
|
68198
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program);
|
|
68516
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program, track.playbackInfo.bank);
|
|
68199
68517
|
trackSoundWritten = true;
|
|
68200
68518
|
}
|
|
68201
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, soundAutomation.ratioPosition);
|
|
68519
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, bank, soundAutomation.ratioPosition);
|
|
68202
68520
|
if (isTrackSound) {
|
|
68203
68521
|
trackSoundWritten = true;
|
|
68204
68522
|
}
|
|
@@ -68581,8 +68899,13 @@
|
|
|
68581
68899
|
writeMasterBarNode(parent, masterBar) {
|
|
68582
68900
|
const masterBarNode = parent.addElement('MasterBar');
|
|
68583
68901
|
const key = masterBarNode.addElement('Key');
|
|
68584
|
-
|
|
68585
|
-
|
|
68902
|
+
let keySignature = masterBar.score.tracks[0].staves[0].bars[masterBar.index].keySignature;
|
|
68903
|
+
const keySignatureType = masterBar.score.tracks[0].staves[0].bars[masterBar.index].keySignatureType;
|
|
68904
|
+
// reverse transpose
|
|
68905
|
+
const transposeIndex = ModelUtils.flooredDivision(masterBar.score.tracks[0].staves[0].displayTranspositionPitch, 12);
|
|
68906
|
+
keySignature = ModelUtils.transposeKey(keySignature, -transposeIndex);
|
|
68907
|
+
key.addElement('AccidentalCount').innerText = keySignature.toString();
|
|
68908
|
+
key.addElement('Mode').innerText = KeySignatureType[keySignatureType];
|
|
68586
68909
|
key.addElement('Sharps').innerText = 'Sharps';
|
|
68587
68910
|
masterBarNode.addElement('Time').innerText =
|
|
68588
68911
|
`${masterBar.timeSignatureNumerator}/${masterBar.timeSignatureDenominator}`;
|
|
@@ -68892,6 +69215,7 @@
|
|
|
68892
69215
|
[127, new GpifMidiProgramInfo(GpifIconIds.Fx, 'Timpani')]
|
|
68893
69216
|
]);
|
|
68894
69217
|
GpifWriter.DrumKitProgramInfo = new GpifMidiProgramInfo(GpifIconIds.PercussionKit, 'Drums', 'drumKit');
|
|
69218
|
+
GpifWriter.defaultSteps = ['C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B'];
|
|
68895
69219
|
|
|
68896
69220
|
/**
|
|
68897
69221
|
* CRC-32 with reversed data and unreversed output
|
|
@@ -70770,6 +71094,7 @@
|
|
|
70770
71094
|
SustainPedalMarker,
|
|
70771
71095
|
get SustainPedalMarkerType () { return SustainPedalMarkerType; },
|
|
70772
71096
|
SyncPointData,
|
|
71097
|
+
get TechniqueSymbolPlacement () { return TechniqueSymbolPlacement; },
|
|
70773
71098
|
Track,
|
|
70774
71099
|
get TrackNameMode () { return TrackNameMode; },
|
|
70775
71100
|
get TrackNameOrientation () { return TrackNameOrientation; },
|