@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.core.mjs
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
|
*
|
|
@@ -197,9 +197,9 @@ class VersionInfo {
|
|
|
197
197
|
print(`build date: ${VersionInfo.date}`);
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
|
-
VersionInfo.version = '1.7.0-alpha.
|
|
201
|
-
VersionInfo.date = '2025-08-
|
|
202
|
-
VersionInfo.commit = '
|
|
200
|
+
VersionInfo.version = '1.7.0-alpha.1522';
|
|
201
|
+
VersionInfo.date = '2025-08-24T02:21:16.522Z';
|
|
202
|
+
VersionInfo.commit = 'c80b4a66eae6b73cb2d7dacaaf74c8f9cce16318';
|
|
203
203
|
|
|
204
204
|
/**
|
|
205
205
|
* This public class provides names for all general midi instruments.
|
|
@@ -226,6 +226,14 @@ class GeneralMidi {
|
|
|
226
226
|
static isGuitar(program) {
|
|
227
227
|
return (program >= 24 && program <= 39) || program === 105 || program === 43;
|
|
228
228
|
}
|
|
229
|
+
static isBass(program) {
|
|
230
|
+
return program >= 32 && program <= 39;
|
|
231
|
+
}
|
|
232
|
+
static bankToLsbMsb(bank) {
|
|
233
|
+
const lsb = bank & 0x7f;
|
|
234
|
+
const msb = (bank >> 7) & 0x7f;
|
|
235
|
+
return [lsb, msb];
|
|
236
|
+
}
|
|
229
237
|
}
|
|
230
238
|
GeneralMidi._values = new Map([
|
|
231
239
|
['acousticgrandpiano', 0],
|
|
@@ -1420,6 +1428,10 @@ var AutomationType;
|
|
|
1420
1428
|
* A sync point for synchronizing the internal time axis with an external audio track.
|
|
1421
1429
|
*/
|
|
1422
1430
|
AutomationType[AutomationType["SyncPoint"] = 4] = "SyncPoint";
|
|
1431
|
+
/**
|
|
1432
|
+
* Midi Bank change.
|
|
1433
|
+
*/
|
|
1434
|
+
AutomationType[AutomationType["Bank"] = 4] = "Bank";
|
|
1423
1435
|
})(AutomationType || (AutomationType = {}));
|
|
1424
1436
|
/**
|
|
1425
1437
|
* Represents the data of a sync point for synchronizing the internal time axis with
|
|
@@ -3387,6 +3399,49 @@ var MusicFontSymbol;
|
|
|
3387
3399
|
MusicFontSymbol[MusicFontSymbol["FingeringCLower"] = 60700] = "FingeringCLower";
|
|
3388
3400
|
})(MusicFontSymbol || (MusicFontSymbol = {}));
|
|
3389
3401
|
|
|
3402
|
+
/**
|
|
3403
|
+
* Defines all possible accidentals for notes.
|
|
3404
|
+
*/
|
|
3405
|
+
var AccidentalType;
|
|
3406
|
+
(function (AccidentalType) {
|
|
3407
|
+
/**
|
|
3408
|
+
* No accidental
|
|
3409
|
+
*/
|
|
3410
|
+
AccidentalType[AccidentalType["None"] = 0] = "None";
|
|
3411
|
+
/**
|
|
3412
|
+
* Naturalize
|
|
3413
|
+
*/
|
|
3414
|
+
AccidentalType[AccidentalType["Natural"] = 1] = "Natural";
|
|
3415
|
+
/**
|
|
3416
|
+
* Sharp
|
|
3417
|
+
*/
|
|
3418
|
+
AccidentalType[AccidentalType["Sharp"] = 2] = "Sharp";
|
|
3419
|
+
/**
|
|
3420
|
+
* Flat
|
|
3421
|
+
*/
|
|
3422
|
+
AccidentalType[AccidentalType["Flat"] = 3] = "Flat";
|
|
3423
|
+
/**
|
|
3424
|
+
* Natural for smear bends
|
|
3425
|
+
*/
|
|
3426
|
+
AccidentalType[AccidentalType["NaturalQuarterNoteUp"] = 4] = "NaturalQuarterNoteUp";
|
|
3427
|
+
/**
|
|
3428
|
+
* Sharp for smear bends
|
|
3429
|
+
*/
|
|
3430
|
+
AccidentalType[AccidentalType["SharpQuarterNoteUp"] = 5] = "SharpQuarterNoteUp";
|
|
3431
|
+
/**
|
|
3432
|
+
* Flat for smear bends
|
|
3433
|
+
*/
|
|
3434
|
+
AccidentalType[AccidentalType["FlatQuarterNoteUp"] = 6] = "FlatQuarterNoteUp";
|
|
3435
|
+
/**
|
|
3436
|
+
* Double Sharp, indicated by an 'x'
|
|
3437
|
+
*/
|
|
3438
|
+
AccidentalType[AccidentalType["DoubleSharp"] = 7] = "DoubleSharp";
|
|
3439
|
+
/**
|
|
3440
|
+
* Double Flat, indicated by 'bb'
|
|
3441
|
+
*/
|
|
3442
|
+
AccidentalType[AccidentalType["DoubleFlat"] = 8] = "DoubleFlat";
|
|
3443
|
+
})(AccidentalType || (AccidentalType = {}));
|
|
3444
|
+
|
|
3390
3445
|
class TuningParseResult {
|
|
3391
3446
|
constructor() {
|
|
3392
3447
|
this.note = null;
|
|
@@ -3892,6 +3947,150 @@ class ModelUtils {
|
|
|
3892
3947
|
}
|
|
3893
3948
|
return ModelUtils.allMusicFontSymbols;
|
|
3894
3949
|
}
|
|
3950
|
+
/**
|
|
3951
|
+
* @internal
|
|
3952
|
+
*/
|
|
3953
|
+
static flooredDivision(a, b) {
|
|
3954
|
+
return a - b * Math.floor(a / b);
|
|
3955
|
+
}
|
|
3956
|
+
// NOTE: haven't figured out yet what exact formula is applied when transposing key signatures
|
|
3957
|
+
// this table is simply created by checking the Guitar Pro behavior,
|
|
3958
|
+
// The table is organized as [<transpose>][<key signature>] to match the table above
|
|
3959
|
+
// it's also easier to read as we list every key signature per row, transposed by the same value
|
|
3960
|
+
// this gives typically just a shifted list according to the transpose (with some special treatments)
|
|
3961
|
+
/**
|
|
3962
|
+
* Converts the key transpose table to actual key signatures.
|
|
3963
|
+
* @param texts An array where every item indicates the number of accidentals and which accidental
|
|
3964
|
+
* placed for the key signature.
|
|
3965
|
+
*
|
|
3966
|
+
* e.g. 3# is 3-sharps -> KeySignature.A
|
|
3967
|
+
*/
|
|
3968
|
+
static translateKeyTransposeTable(texts) {
|
|
3969
|
+
const keySignatures = [];
|
|
3970
|
+
for (const transpose of texts) {
|
|
3971
|
+
const transposeValues = [];
|
|
3972
|
+
keySignatures.push(transposeValues);
|
|
3973
|
+
for (const keySignatureText of transpose) {
|
|
3974
|
+
const keySignature =
|
|
3975
|
+
// digit
|
|
3976
|
+
(Number.parseInt(keySignatureText.charAt(0)) *
|
|
3977
|
+
// b -> negative, # positive
|
|
3978
|
+
(keySignatureText.charAt(1) === 'b' ? -1 : 1));
|
|
3979
|
+
transposeValues.push(keySignature);
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3982
|
+
return keySignatures;
|
|
3983
|
+
}
|
|
3984
|
+
/**
|
|
3985
|
+
* Transposes the given key signature.
|
|
3986
|
+
* @internal
|
|
3987
|
+
* @param keySignature The key signature to transpose
|
|
3988
|
+
* @param transpose The number of semitones to transpose (+/- 0-11)
|
|
3989
|
+
* @returns
|
|
3990
|
+
*/
|
|
3991
|
+
static transposeKey(keySignature, transpose) {
|
|
3992
|
+
if (transpose === 0) {
|
|
3993
|
+
return keySignature;
|
|
3994
|
+
}
|
|
3995
|
+
if (transpose < 0) {
|
|
3996
|
+
const lookup = ModelUtils.keyTransposeTable[-transpose];
|
|
3997
|
+
const keySignatureIndex = lookup.indexOf(keySignature);
|
|
3998
|
+
if (keySignatureIndex === -1) {
|
|
3999
|
+
return keySignature;
|
|
4000
|
+
}
|
|
4001
|
+
return (keySignatureIndex - 7);
|
|
4002
|
+
}
|
|
4003
|
+
else {
|
|
4004
|
+
return ModelUtils.keyTransposeTable[transpose][keySignature + 7];
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
/**
|
|
4008
|
+
* @internal
|
|
4009
|
+
*/
|
|
4010
|
+
static computeAccidental(keySignature, accidentalMode, noteValue, quarterBend, currentAccidental = null) {
|
|
4011
|
+
const ks = keySignature;
|
|
4012
|
+
const ksi = ks + 7;
|
|
4013
|
+
const index = noteValue % 12;
|
|
4014
|
+
const accidentalForKeySignature = ksi < 7 ? AccidentalType.Flat : AccidentalType.Sharp;
|
|
4015
|
+
const hasKeySignatureAccidentalSetForNote = ModelUtils.KeySignatureLookup[ksi][index];
|
|
4016
|
+
const hasNoteAccidentalWithinOctave = ModelUtils.AccidentalNotes[index];
|
|
4017
|
+
// the general logic is like this:
|
|
4018
|
+
// - we check if the key signature has an accidental defined
|
|
4019
|
+
// - we calculate which accidental a note needs according to its index in the octave
|
|
4020
|
+
// - if the accidental is already placed at this line, nothing needs to be done, otherwise we place it
|
|
4021
|
+
// - if there should not be an accidental, but there is one in the key signature, we clear it.
|
|
4022
|
+
// the exceptions are:
|
|
4023
|
+
// - for quarter bends we just place the corresponding accidental
|
|
4024
|
+
// - the accidental mode can enforce the accidentals for the note
|
|
4025
|
+
let accidentalToSet = AccidentalType.None;
|
|
4026
|
+
if (quarterBend) {
|
|
4027
|
+
accidentalToSet = hasNoteAccidentalWithinOctave ? accidentalForKeySignature : AccidentalType.Natural;
|
|
4028
|
+
switch (accidentalToSet) {
|
|
4029
|
+
case AccidentalType.Natural:
|
|
4030
|
+
accidentalToSet = AccidentalType.NaturalQuarterNoteUp;
|
|
4031
|
+
break;
|
|
4032
|
+
case AccidentalType.Sharp:
|
|
4033
|
+
accidentalToSet = AccidentalType.SharpQuarterNoteUp;
|
|
4034
|
+
break;
|
|
4035
|
+
case AccidentalType.Flat:
|
|
4036
|
+
accidentalToSet = AccidentalType.FlatQuarterNoteUp;
|
|
4037
|
+
break;
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
else {
|
|
4041
|
+
// define which accidental should be shown ignoring what might be set on the KS already
|
|
4042
|
+
switch (accidentalMode) {
|
|
4043
|
+
case NoteAccidentalMode.ForceSharp:
|
|
4044
|
+
accidentalToSet = AccidentalType.Sharp;
|
|
4045
|
+
break;
|
|
4046
|
+
case NoteAccidentalMode.ForceDoubleSharp:
|
|
4047
|
+
accidentalToSet = AccidentalType.DoubleSharp;
|
|
4048
|
+
break;
|
|
4049
|
+
case NoteAccidentalMode.ForceFlat:
|
|
4050
|
+
accidentalToSet = AccidentalType.Flat;
|
|
4051
|
+
break;
|
|
4052
|
+
case NoteAccidentalMode.ForceDoubleFlat:
|
|
4053
|
+
accidentalToSet = AccidentalType.DoubleFlat;
|
|
4054
|
+
break;
|
|
4055
|
+
default:
|
|
4056
|
+
// if note has an accidental in the octave, we place a symbol
|
|
4057
|
+
// according to the Key Signature
|
|
4058
|
+
if (hasNoteAccidentalWithinOctave) {
|
|
4059
|
+
accidentalToSet = accidentalForKeySignature;
|
|
4060
|
+
}
|
|
4061
|
+
else if (hasKeySignatureAccidentalSetForNote) {
|
|
4062
|
+
// note does not get an accidental, but KS defines one -> Naturalize
|
|
4063
|
+
accidentalToSet = AccidentalType.Natural;
|
|
4064
|
+
}
|
|
4065
|
+
break;
|
|
4066
|
+
}
|
|
4067
|
+
// do we need an accidental on the note?
|
|
4068
|
+
if (accidentalToSet !== AccidentalType.None) {
|
|
4069
|
+
// if there is no accidental on the line, and the key signature has it set already, we clear it on the note
|
|
4070
|
+
if (currentAccidental != null) {
|
|
4071
|
+
if (currentAccidental === accidentalToSet) {
|
|
4072
|
+
accidentalToSet = AccidentalType.None;
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
else if (hasKeySignatureAccidentalSetForNote && accidentalToSet === accidentalForKeySignature) {
|
|
4076
|
+
accidentalToSet = AccidentalType.None;
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
else {
|
|
4080
|
+
// if we don't want an accidental, but there is already one applied, we place a naturalize accidental
|
|
4081
|
+
// and clear the registration
|
|
4082
|
+
if (currentAccidental !== null) {
|
|
4083
|
+
if (currentAccidental === AccidentalType.Natural) {
|
|
4084
|
+
accidentalToSet = AccidentalType.None;
|
|
4085
|
+
}
|
|
4086
|
+
else {
|
|
4087
|
+
accidentalToSet = AccidentalType.Natural;
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
return accidentalToSet;
|
|
4093
|
+
}
|
|
3895
4094
|
}
|
|
3896
4095
|
ModelUtils.TuningLetters = new Set([
|
|
3897
4096
|
0x43 /* C */, 0x44 /* D */, 0x45 /* E */, 0x46 /* F */, 0x47 /* G */, 0x41 /* A */, 0x42 /* B */, 0x63 /* c */,
|
|
@@ -3944,6 +4143,66 @@ ModelUtils.displayTranspositionPitches = new Map([
|
|
|
3944
4143
|
// Contrabass
|
|
3945
4144
|
[43, -12]
|
|
3946
4145
|
]);
|
|
4146
|
+
/**
|
|
4147
|
+
* @internal
|
|
4148
|
+
*/
|
|
4149
|
+
ModelUtils.keyTransposeTable = ModelUtils.translateKeyTransposeTable([
|
|
4150
|
+
/* Cb Gb Db Ab Eb Bb F C G D A E B F C# */
|
|
4151
|
+
/* C 0 */ ['7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#'],
|
|
4152
|
+
/* Db 1 */ ['2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b', '2b', '1b', '0#'],
|
|
4153
|
+
/* D 2 */ ['3#', '4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#'],
|
|
4154
|
+
/* Eb 3 */ ['4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b', '2b'],
|
|
4155
|
+
/* E 4 */ ['1#', '2#', '3#', '4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#'],
|
|
4156
|
+
/* F 5 */ ['6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b'],
|
|
4157
|
+
/* Gb 6 */ ['1b', '0#', '1#', '2#', '3#', '4#', '7b', '6#', '7#', '4b', '3b', '2b', '1b', '0#', '1#'],
|
|
4158
|
+
/* G 7 */ ['4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#'],
|
|
4159
|
+
/* Ab 8 */ ['3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b', '2b', '1b'],
|
|
4160
|
+
/* A 9 */ ['2#', '3#', '4#', '7b', '6b', '5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#'],
|
|
4161
|
+
/* Bb 10 */ ['5b', '4b', '3b', '2b', '1b', '0#', '1#', '2#', '3#', '4#', '5#', '6#', '7#', '4b', '3b'],
|
|
4162
|
+
/* B 11 */ ['0#', '1#', '2#', '3#', '4#', '7b', '6b', '6#', '4b', '3b', '2b', '1b', '0#', '1#', '2#']
|
|
4163
|
+
]);
|
|
4164
|
+
/**
|
|
4165
|
+
* a lookup list containing an info whether the notes within an octave
|
|
4166
|
+
* need an accidental rendered. the accidental symbol is determined based on the type of key signature.
|
|
4167
|
+
*/
|
|
4168
|
+
ModelUtils.KeySignatureLookup = [
|
|
4169
|
+
// Flats (where the value is true, a flat accidental is required for the notes)
|
|
4170
|
+
[true, true, true, true, true, true, true, true, true, true, true, true],
|
|
4171
|
+
[true, true, true, true, true, false, true, true, true, true, true, true],
|
|
4172
|
+
[false, true, true, true, true, false, true, true, true, true, true, true],
|
|
4173
|
+
[false, true, true, true, true, false, false, false, true, true, true, true],
|
|
4174
|
+
[false, false, false, true, true, false, false, false, true, true, true, true],
|
|
4175
|
+
[false, false, false, true, true, false, false, false, false, false, true, true],
|
|
4176
|
+
[false, false, false, false, false, false, false, false, false, false, true, true],
|
|
4177
|
+
// natural
|
|
4178
|
+
[false, false, false, false, false, false, false, false, false, false, false, false],
|
|
4179
|
+
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
4180
|
+
[false, false, false, false, false, true, true, false, false, false, false, false],
|
|
4181
|
+
[true, true, false, false, false, true, true, false, false, false, false, false],
|
|
4182
|
+
[true, true, false, false, false, true, true, true, true, false, false, false],
|
|
4183
|
+
[true, true, true, true, false, true, true, true, true, false, false, false],
|
|
4184
|
+
[true, true, true, true, false, true, true, true, true, true, true, false],
|
|
4185
|
+
[true, true, true, true, true, true, true, true, true, true, true, false],
|
|
4186
|
+
[true, true, true, true, true, true, true, true, true, true, true, true]
|
|
4187
|
+
];
|
|
4188
|
+
/**
|
|
4189
|
+
* Contains the list of notes within an octave have accidentals set.
|
|
4190
|
+
* @internal
|
|
4191
|
+
*/
|
|
4192
|
+
ModelUtils.AccidentalNotes = [
|
|
4193
|
+
false,
|
|
4194
|
+
true,
|
|
4195
|
+
false,
|
|
4196
|
+
true,
|
|
4197
|
+
false,
|
|
4198
|
+
false,
|
|
4199
|
+
true,
|
|
4200
|
+
false,
|
|
4201
|
+
true,
|
|
4202
|
+
false,
|
|
4203
|
+
true,
|
|
4204
|
+
false
|
|
4205
|
+
];
|
|
3947
4206
|
|
|
3948
4207
|
/**
|
|
3949
4208
|
* Lists all types of pick strokes.
|
|
@@ -7914,6 +8173,10 @@ class PlaybackInformation {
|
|
|
7914
8173
|
* Gets or sets the midi program to use.
|
|
7915
8174
|
*/
|
|
7916
8175
|
this.program = 0;
|
|
8176
|
+
/**
|
|
8177
|
+
* The midi bank to use.
|
|
8178
|
+
*/
|
|
8179
|
+
this.bank = 0;
|
|
7917
8180
|
/**
|
|
7918
8181
|
* Gets or sets the primary channel for all normal midi events.
|
|
7919
8182
|
*/
|
|
@@ -7946,7 +8209,7 @@ class Tuning {
|
|
|
7946
8209
|
static getTextPartsForTuning(tuning, octaveShift = -1) {
|
|
7947
8210
|
const octave = (tuning / 12) | 0;
|
|
7948
8211
|
const note = tuning % 12;
|
|
7949
|
-
const notes =
|
|
8212
|
+
const notes = Tuning.noteNames;
|
|
7950
8213
|
return [notes[note], (octave + octaveShift).toString()];
|
|
7951
8214
|
}
|
|
7952
8215
|
/**
|
|
@@ -8085,8 +8348,7 @@ Tuning._sixStrings = [];
|
|
|
8085
8348
|
Tuning._fiveStrings = [];
|
|
8086
8349
|
Tuning._fourStrings = [];
|
|
8087
8350
|
Tuning._defaultTunings = new Map();
|
|
8088
|
-
Tuning.
|
|
8089
|
-
Tuning.defaultSteps = ['C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B'];
|
|
8351
|
+
Tuning.noteNames = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'];
|
|
8090
8352
|
Tuning.initialize();
|
|
8091
8353
|
|
|
8092
8354
|
/**
|
|
@@ -8309,6 +8571,12 @@ class Track {
|
|
|
8309
8571
|
*/
|
|
8310
8572
|
this.percussionArticulations = [];
|
|
8311
8573
|
}
|
|
8574
|
+
/**
|
|
8575
|
+
* Gets whether this track is a percussion track.
|
|
8576
|
+
*/
|
|
8577
|
+
get isPercussion() {
|
|
8578
|
+
return this.staves.some(s => s.isPercussion);
|
|
8579
|
+
}
|
|
8312
8580
|
/**
|
|
8313
8581
|
* Adds a new line break.
|
|
8314
8582
|
* @param index The index of the bar before which a line break should happen.
|
|
@@ -9012,8 +9280,7 @@ class AlphaTexLexer {
|
|
|
9012
9280
|
}
|
|
9013
9281
|
// unicode handling
|
|
9014
9282
|
// https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-ecmascript-language-types-string-type
|
|
9015
|
-
if (IOHelper.isLeadingSurrogate(previousCodepoint) &&
|
|
9016
|
-
IOHelper.isTrailingSurrogate(codepoint)) {
|
|
9283
|
+
if (IOHelper.isLeadingSurrogate(previousCodepoint) && IOHelper.isTrailingSurrogate(codepoint)) {
|
|
9017
9284
|
codepoint = (previousCodepoint - 0xd800) * 0x400 + (codepoint - 0xdc00) + 0x10000;
|
|
9018
9285
|
s += String.fromCodePoint(codepoint);
|
|
9019
9286
|
}
|
|
@@ -9448,10 +9715,10 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
9448
9715
|
case 'bass':
|
|
9449
9716
|
return Clef.F4;
|
|
9450
9717
|
case 'c3':
|
|
9451
|
-
case '
|
|
9718
|
+
case 'alto':
|
|
9452
9719
|
return Clef.C3;
|
|
9453
9720
|
case 'c4':
|
|
9454
|
-
case '
|
|
9721
|
+
case 'tenor':
|
|
9455
9722
|
return Clef.C4;
|
|
9456
9723
|
case 'n':
|
|
9457
9724
|
case 'neutral':
|
|
@@ -9468,6 +9735,8 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
9468
9735
|
*/
|
|
9469
9736
|
parseClefFromInt(i) {
|
|
9470
9737
|
switch (i) {
|
|
9738
|
+
case 0:
|
|
9739
|
+
return Clef.Neutral;
|
|
9471
9740
|
case 43:
|
|
9472
9741
|
return Clef.G2;
|
|
9473
9742
|
case 65:
|
|
@@ -9972,33 +10241,15 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
9972
10241
|
}
|
|
9973
10242
|
return StaffMetaResult.KnownStaffMeta;
|
|
9974
10243
|
case 'instrument':
|
|
9975
|
-
this.sy = this.newSy();
|
|
9976
10244
|
this._staffTuningApplied = false;
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
9984
|
-
}
|
|
9985
|
-
}
|
|
9986
|
-
else if (this.sy === AlphaTexSymbols.String) {
|
|
9987
|
-
const instrumentName = this.syData.toLowerCase();
|
|
9988
|
-
if (instrumentName === 'percussion') {
|
|
9989
|
-
for (const staff of this._currentTrack.staves) {
|
|
9990
|
-
this.applyPercussionStaff(staff);
|
|
9991
|
-
}
|
|
9992
|
-
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
9993
|
-
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
9994
|
-
}
|
|
9995
|
-
else {
|
|
9996
|
-
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
9997
|
-
}
|
|
9998
|
-
}
|
|
9999
|
-
else {
|
|
10000
|
-
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10245
|
+
this.readTrackInstrument();
|
|
10246
|
+
return StaffMetaResult.KnownStaffMeta;
|
|
10247
|
+
case 'bank':
|
|
10248
|
+
this.sy = this.newSy();
|
|
10249
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10250
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10001
10251
|
}
|
|
10252
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10002
10253
|
this.sy = this.newSy();
|
|
10003
10254
|
return StaffMetaResult.KnownStaffMeta;
|
|
10004
10255
|
case 'lyrics':
|
|
@@ -10109,6 +10360,35 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
10109
10360
|
return StaffMetaResult.UnknownStaffMeta;
|
|
10110
10361
|
}
|
|
10111
10362
|
}
|
|
10363
|
+
readTrackInstrument() {
|
|
10364
|
+
this.sy = this.newSy();
|
|
10365
|
+
if (this.sy === AlphaTexSymbols.Number) {
|
|
10366
|
+
const instrument = this.syData;
|
|
10367
|
+
if (instrument >= 0 && instrument <= 127) {
|
|
10368
|
+
this._currentTrack.playbackInfo.program = this.syData;
|
|
10369
|
+
}
|
|
10370
|
+
else {
|
|
10371
|
+
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
10372
|
+
}
|
|
10373
|
+
}
|
|
10374
|
+
else if (this.sy === AlphaTexSymbols.String) {
|
|
10375
|
+
const instrumentName = this.syData.toLowerCase();
|
|
10376
|
+
if (instrumentName === 'percussion') {
|
|
10377
|
+
for (const staff of this._currentTrack.staves) {
|
|
10378
|
+
this.applyPercussionStaff(staff);
|
|
10379
|
+
}
|
|
10380
|
+
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
10381
|
+
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10382
|
+
}
|
|
10383
|
+
else {
|
|
10384
|
+
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10385
|
+
}
|
|
10386
|
+
}
|
|
10387
|
+
else {
|
|
10388
|
+
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10389
|
+
}
|
|
10390
|
+
this.sy = this.newSy();
|
|
10391
|
+
}
|
|
10112
10392
|
handleAccidentalMode() {
|
|
10113
10393
|
this.sy = this.newSy();
|
|
10114
10394
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -10381,6 +10661,17 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
10381
10661
|
}
|
|
10382
10662
|
this._score.stylesheet.perTrackMultiBarRest.add(this._currentTrack.index);
|
|
10383
10663
|
break;
|
|
10664
|
+
case 'instrument':
|
|
10665
|
+
this.readTrackInstrument();
|
|
10666
|
+
break;
|
|
10667
|
+
case 'bank':
|
|
10668
|
+
this.sy = this.newSy();
|
|
10669
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10670
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10671
|
+
}
|
|
10672
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10673
|
+
this.sy = this.newSy();
|
|
10674
|
+
break;
|
|
10384
10675
|
default:
|
|
10385
10676
|
this.error('track-properties', AlphaTexSymbols.String, false);
|
|
10386
10677
|
break;
|
|
@@ -10725,6 +11016,25 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
10725
11016
|
}
|
|
10726
11017
|
beat.text = this.syData;
|
|
10727
11018
|
}
|
|
11019
|
+
else if (syData === 'lyrics') {
|
|
11020
|
+
this.sy = this.newSy();
|
|
11021
|
+
let lyricsLine = 0;
|
|
11022
|
+
if (this.sy === AlphaTexSymbols.Number) {
|
|
11023
|
+
lyricsLine = this.syData;
|
|
11024
|
+
this.sy = this.newSy();
|
|
11025
|
+
}
|
|
11026
|
+
if (this.sy !== AlphaTexSymbols.String) {
|
|
11027
|
+
this.error('lyrics', AlphaTexSymbols.String, true);
|
|
11028
|
+
return false;
|
|
11029
|
+
}
|
|
11030
|
+
if (!beat.lyrics) {
|
|
11031
|
+
beat.lyrics = [];
|
|
11032
|
+
}
|
|
11033
|
+
while (beat.lyrics.length <= lyricsLine) {
|
|
11034
|
+
beat.lyrics.push('');
|
|
11035
|
+
}
|
|
11036
|
+
beat.lyrics[lyricsLine] = this.syData;
|
|
11037
|
+
}
|
|
10728
11038
|
else if (syData === 'dd') {
|
|
10729
11039
|
beat.dots = 2;
|
|
10730
11040
|
}
|
|
@@ -11162,6 +11472,17 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
11162
11472
|
automation.value = program;
|
|
11163
11473
|
beat.automations.push(automation);
|
|
11164
11474
|
}
|
|
11475
|
+
else if (syData === 'bank') {
|
|
11476
|
+
this.sy = this.newSy();
|
|
11477
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
11478
|
+
this.error('bank-change', AlphaTexSymbols.Number, true);
|
|
11479
|
+
}
|
|
11480
|
+
const automation = new Automation();
|
|
11481
|
+
automation.isLinear = false;
|
|
11482
|
+
automation.type = AutomationType.Bank;
|
|
11483
|
+
automation.value = this.syData;
|
|
11484
|
+
beat.automations.push(automation);
|
|
11485
|
+
}
|
|
11165
11486
|
else if (syData === 'fermata') {
|
|
11166
11487
|
this.sy = this.newSy();
|
|
11167
11488
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -11172,7 +11493,7 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
11172
11493
|
this.sy = this.newSy(true);
|
|
11173
11494
|
if (this.sy === AlphaTexSymbols.Number) {
|
|
11174
11495
|
fermata.length = this.syData;
|
|
11175
|
-
this.sy = this.newSy(
|
|
11496
|
+
this.sy = this.newSy();
|
|
11176
11497
|
}
|
|
11177
11498
|
beat.fermata = fermata;
|
|
11178
11499
|
return true;
|
|
@@ -11205,13 +11526,9 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
11205
11526
|
beat.beamingMode = BeatBeamingMode.ForceSplitOnSecondaryToNext;
|
|
11206
11527
|
break;
|
|
11207
11528
|
}
|
|
11208
|
-
this.sy = this.newSy();
|
|
11209
|
-
return true;
|
|
11210
11529
|
}
|
|
11211
11530
|
else if (syData === 'timer') {
|
|
11212
11531
|
beat.showTimer = true;
|
|
11213
|
-
this.sy = this.newSy();
|
|
11214
|
-
return true;
|
|
11215
11532
|
}
|
|
11216
11533
|
else {
|
|
11217
11534
|
// string didn't match any beat effect syntax
|
|
@@ -14771,6 +15088,7 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
14771
15088
|
this._trackCount = 0;
|
|
14772
15089
|
this._playbackInfos = [];
|
|
14773
15090
|
this._doubleBars = new Set();
|
|
15091
|
+
this._clefsPerTrack = new Map();
|
|
14774
15092
|
this._keySignatures = new Map();
|
|
14775
15093
|
this._beatTextChunksByTrack = new Map();
|
|
14776
15094
|
this._directionLookup = new Map();
|
|
@@ -15155,26 +15473,74 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15155
15473
|
mainStaff.capo = IOHelper.readInt32LE(this.data);
|
|
15156
15474
|
newTrack.color = GpBinaryHelpers.gpReadColor(this.data, false);
|
|
15157
15475
|
if (this._versionNumber >= 500) {
|
|
15158
|
-
const
|
|
15159
|
-
mainStaff.showTablature = (
|
|
15160
|
-
mainStaff.showStandardNotation = (
|
|
15161
|
-
const showChordDiagramListOnTopOfScore = (
|
|
15476
|
+
const staffFlags = this.data.readByte();
|
|
15477
|
+
mainStaff.showTablature = (staffFlags & 0x01) !== 0;
|
|
15478
|
+
mainStaff.showStandardNotation = (staffFlags & 0x02) !== 0;
|
|
15479
|
+
const showChordDiagramListOnTopOfScore = (staffFlags & 0x64) !== 0;
|
|
15162
15480
|
if (this._score.stylesheet.perTrackChordDiagramsOnTop === null) {
|
|
15163
15481
|
this._score.stylesheet.perTrackChordDiagramsOnTop = new Map();
|
|
15164
15482
|
}
|
|
15165
15483
|
this._score.stylesheet.perTrackChordDiagramsOnTop.set(newTrack.index, showChordDiagramListOnTopOfScore);
|
|
15166
|
-
//
|
|
15484
|
+
// MIDI: Automatic
|
|
15485
|
+
// 0x01 -> always set (unknown)
|
|
15167
15486
|
// 0x02 -> auto let ring
|
|
15168
15487
|
// 0x04 -> auto brush
|
|
15169
15488
|
this.data.readByte();
|
|
15170
|
-
//
|
|
15171
|
-
|
|
15489
|
+
// RSE: Auto-Accentuation on the Beat
|
|
15490
|
+
// 0 - None
|
|
15491
|
+
// 1 - Very Soft
|
|
15492
|
+
// 2 - Soft
|
|
15493
|
+
// 3 - Medium
|
|
15494
|
+
// 4 - Strong
|
|
15495
|
+
// 5 - Very Strong
|
|
15496
|
+
this.data.readByte();
|
|
15497
|
+
newTrack.playbackInfo.bank = this.data.readByte();
|
|
15498
|
+
// RSE: Human Playing (1 byte, 0-100%)
|
|
15499
|
+
this.data.readByte();
|
|
15500
|
+
// `12` for all tunings which have bass clefs
|
|
15501
|
+
const clefMode = IOHelper.readInt32LE(this.data);
|
|
15502
|
+
if (clefMode === 12) {
|
|
15503
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15504
|
+
}
|
|
15505
|
+
else {
|
|
15506
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15507
|
+
}
|
|
15508
|
+
// Unknown, no UI setting seem to affect this
|
|
15509
|
+
IOHelper.readInt32LE(this.data);
|
|
15510
|
+
// Unknown, no UI setting seem to affect this
|
|
15511
|
+
// typically: 100
|
|
15512
|
+
IOHelper.readInt32LE(this.data);
|
|
15513
|
+
// Unknown, no UI setting seem to affect this
|
|
15514
|
+
// typically: 1 2 3 4 5 6 7 8 9 10
|
|
15515
|
+
this.data.skip(10);
|
|
15516
|
+
// Unknown, no UI setting seem to affect this
|
|
15517
|
+
// typically: 255
|
|
15518
|
+
this.data.readByte();
|
|
15519
|
+
// Unknown, no UI setting seem to affect this
|
|
15520
|
+
// typically: 3
|
|
15521
|
+
this.data.readByte();
|
|
15522
|
+
this.readRseBank();
|
|
15523
|
+
// this.data.skip(42);
|
|
15524
|
+
if (this._versionNumber >= 510) {
|
|
15525
|
+
// RSE: 3-band EQ
|
|
15526
|
+
// 1 byte Low
|
|
15527
|
+
// 1 byte Mid
|
|
15528
|
+
// 1 byte High
|
|
15529
|
+
// 1 byte PRE
|
|
15530
|
+
this.data.skip(4);
|
|
15531
|
+
// RSE: effect name
|
|
15532
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15533
|
+
// RSE: effect category
|
|
15534
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15535
|
+
}
|
|
15172
15536
|
}
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15537
|
+
else {
|
|
15538
|
+
if (GeneralMidi.isBass(newTrack.playbackInfo.program)) {
|
|
15539
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15540
|
+
}
|
|
15541
|
+
else {
|
|
15542
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15543
|
+
}
|
|
15178
15544
|
}
|
|
15179
15545
|
}
|
|
15180
15546
|
readBars() {
|
|
@@ -15190,6 +15556,9 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15190
15556
|
if (mainStaff.isPercussion) {
|
|
15191
15557
|
newBar.clef = Clef.Neutral;
|
|
15192
15558
|
}
|
|
15559
|
+
else if (this._clefsPerTrack.has(track.index)) {
|
|
15560
|
+
newBar.clef = this._clefsPerTrack.get(track.index);
|
|
15561
|
+
}
|
|
15193
15562
|
mainStaff.addBar(newBar);
|
|
15194
15563
|
if (this._keySignatures.has(newBar.index)) {
|
|
15195
15564
|
const newKeySignature = this._keySignatures.get(newBar.index);
|
|
@@ -15611,11 +15980,29 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15611
15980
|
return 0;
|
|
15612
15981
|
}
|
|
15613
15982
|
}
|
|
15983
|
+
readRseBank() {
|
|
15984
|
+
// RSE Banks on disk are having filenames like this: 033_2_002.ini
|
|
15985
|
+
// 033 is the RSE instrument (selected in the instrument list)
|
|
15986
|
+
// 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
|
|
15987
|
+
// likely for organizational purposes
|
|
15988
|
+
// 002 is the effective soundbank (selected in the soundbank dropdown)
|
|
15989
|
+
// RSE Instrument
|
|
15990
|
+
this.data.skip(4); // IOHelper.readInt32LE(this.data);
|
|
15991
|
+
// RSE Style/Variation
|
|
15992
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15993
|
+
// RSE Soundbank
|
|
15994
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15995
|
+
// Unknown, no UI setting seem to affect this
|
|
15996
|
+
// typically: -1
|
|
15997
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15998
|
+
}
|
|
15614
15999
|
readMixTableChange(beat) {
|
|
15615
16000
|
const tableChange = new MixTableChange();
|
|
15616
16001
|
tableChange.instrument = IOHelper.readSInt8(this.data);
|
|
16002
|
+
// NOTE: The UI shows a Midi Bank selection, but this information is not stored in the file
|
|
16003
|
+
// when reopening the file the bank is always 0
|
|
15617
16004
|
if (this._versionNumber >= 500) {
|
|
15618
|
-
this.
|
|
16005
|
+
this.readRseBank();
|
|
15619
16006
|
}
|
|
15620
16007
|
tableChange.volume = IOHelper.readSInt8(this.data);
|
|
15621
16008
|
tableChange.balance = IOHelper.readSInt8(this.data);
|
|
@@ -15627,7 +16014,7 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15627
16014
|
tableChange.tempoName = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15628
16015
|
}
|
|
15629
16016
|
tableChange.tempo = IOHelper.readInt32LE(this.data);
|
|
15630
|
-
// durations
|
|
16017
|
+
// durations (in number of beats)
|
|
15631
16018
|
if (tableChange.volume >= 0) {
|
|
15632
16019
|
this.data.readByte();
|
|
15633
16020
|
}
|
|
@@ -15757,11 +16144,11 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15757
16144
|
newNote.fret = -1;
|
|
15758
16145
|
}
|
|
15759
16146
|
if (swapAccidentals) {
|
|
15760
|
-
const accidental =
|
|
15761
|
-
if (accidental ===
|
|
16147
|
+
const accidental = ModelUtils.computeAccidental(bar.keySignature, NoteAccidentalMode.Default, newNote.realValueWithoutHarmonic, false);
|
|
16148
|
+
if (accidental === AccidentalType.Sharp) {
|
|
15762
16149
|
newNote.accidentalMode = NoteAccidentalMode.ForceFlat;
|
|
15763
16150
|
}
|
|
15764
|
-
else if (accidental ===
|
|
16151
|
+
else if (accidental === AccidentalType.Flat) {
|
|
15765
16152
|
newNote.accidentalMode = NoteAccidentalMode.ForceSharp;
|
|
15766
16153
|
}
|
|
15767
16154
|
}
|
|
@@ -16610,9 +16997,7 @@ class BinaryStylesheet {
|
|
|
16610
16997
|
return writer.toArray();
|
|
16611
16998
|
}
|
|
16612
16999
|
static addHeaderAndFooter(binaryStylesheet, style, prefix, name) {
|
|
16613
|
-
|
|
16614
|
-
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16615
|
-
}
|
|
17000
|
+
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16616
17001
|
binaryStylesheet.addValue(`${prefix}${name}Alignment`, style.textAlign, DataType.Integer);
|
|
16617
17002
|
if (style.isVisible !== undefined) {
|
|
16618
17003
|
binaryStylesheet.addValue(`${prefix}draw${name}`, style.isVisible, DataType.Boolean);
|
|
@@ -16646,6 +17031,7 @@ class GpifSound {
|
|
|
16646
17031
|
this.path = '';
|
|
16647
17032
|
this.role = '';
|
|
16648
17033
|
this.program = 0;
|
|
17034
|
+
this.bank = 0;
|
|
16649
17035
|
}
|
|
16650
17036
|
get uniqueId() {
|
|
16651
17037
|
return `${this.path};${this.name};${this.role}`;
|
|
@@ -16661,6 +17047,7 @@ class GpifParser {
|
|
|
16661
17047
|
this._backingTrackPadding = 0;
|
|
16662
17048
|
this._doubleBars = new Set();
|
|
16663
17049
|
this._keySignatures = new Map();
|
|
17050
|
+
this._transposeKeySignaturePerTrack = new Map();
|
|
16664
17051
|
}
|
|
16665
17052
|
parseXml(xml, settings) {
|
|
16666
17053
|
this._masterTrackAutomations = new Map();
|
|
@@ -16891,7 +17278,8 @@ class GpifParser {
|
|
|
16891
17278
|
assetId = c.innerText;
|
|
16892
17279
|
break;
|
|
16893
17280
|
case 'FramePadding':
|
|
16894
|
-
this._backingTrackPadding =
|
|
17281
|
+
this._backingTrackPadding =
|
|
17282
|
+
(GpifParser.parseIntSafe(c.innerText, 0) / GpifParser.SampleRate) * 1000;
|
|
16895
17283
|
break;
|
|
16896
17284
|
}
|
|
16897
17285
|
}
|
|
@@ -16998,21 +17386,28 @@ class GpifParser {
|
|
|
16998
17386
|
if (!type) {
|
|
16999
17387
|
return;
|
|
17000
17388
|
}
|
|
17001
|
-
|
|
17389
|
+
const newAutomations = [];
|
|
17002
17390
|
switch (type) {
|
|
17003
17391
|
case 'Tempo':
|
|
17004
|
-
|
|
17392
|
+
newAutomations.push(Automation.buildTempoAutomation(isLinear, ratioPosition, numberValue, reference));
|
|
17005
17393
|
break;
|
|
17006
17394
|
case 'SyncPoint':
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
|
|
17011
|
-
|
|
17395
|
+
const syncPoint = new Automation();
|
|
17396
|
+
syncPoint.type = AutomationType.SyncPoint;
|
|
17397
|
+
syncPoint.isLinear = isLinear;
|
|
17398
|
+
syncPoint.ratioPosition = ratioPosition;
|
|
17399
|
+
syncPoint.syncPointValue = syncPointValue;
|
|
17400
|
+
newAutomations.push(syncPoint);
|
|
17012
17401
|
break;
|
|
17013
17402
|
case 'Sound':
|
|
17014
17403
|
if (textValue && sounds && sounds.has(textValue)) {
|
|
17015
|
-
|
|
17404
|
+
const bankChange = new Automation();
|
|
17405
|
+
bankChange.type = AutomationType.Bank;
|
|
17406
|
+
bankChange.ratioPosition = ratioPosition;
|
|
17407
|
+
bankChange.value = sounds.get(textValue).bank;
|
|
17408
|
+
newAutomations.push(bankChange);
|
|
17409
|
+
const programChange = Automation.buildInstrumentAutomation(isLinear, ratioPosition, sounds.get(textValue).program);
|
|
17410
|
+
newAutomations.push(programChange);
|
|
17016
17411
|
}
|
|
17017
17412
|
break;
|
|
17018
17413
|
case 'SustainPedal':
|
|
@@ -17040,15 +17435,19 @@ class GpifParser {
|
|
|
17040
17435
|
}
|
|
17041
17436
|
break;
|
|
17042
17437
|
}
|
|
17043
|
-
if (
|
|
17438
|
+
if (newAutomations.length) {
|
|
17044
17439
|
if (text) {
|
|
17045
|
-
|
|
17440
|
+
for (const a of newAutomations) {
|
|
17441
|
+
a.text = text;
|
|
17442
|
+
}
|
|
17046
17443
|
}
|
|
17047
17444
|
if (barIndex >= 0) {
|
|
17048
17445
|
if (!automations.has(barIndex)) {
|
|
17049
17446
|
automations.set(barIndex, []);
|
|
17050
17447
|
}
|
|
17051
|
-
|
|
17448
|
+
for (const a of newAutomations) {
|
|
17449
|
+
automations.get(barIndex).push(a);
|
|
17450
|
+
}
|
|
17052
17451
|
}
|
|
17053
17452
|
}
|
|
17054
17453
|
}
|
|
@@ -17127,13 +17526,13 @@ class GpifParser {
|
|
|
17127
17526
|
track.playbackInfo.isMute = state === 'Mute';
|
|
17128
17527
|
break;
|
|
17129
17528
|
case 'PartSounding':
|
|
17130
|
-
this.parsePartSounding(track, c);
|
|
17529
|
+
this.parsePartSounding(trackId, track, c);
|
|
17131
17530
|
break;
|
|
17132
17531
|
case 'Staves':
|
|
17133
17532
|
this.parseStaves(track, c);
|
|
17134
17533
|
break;
|
|
17135
17534
|
case 'Transpose':
|
|
17136
|
-
this.parseTranspose(track, c);
|
|
17535
|
+
this.parseTranspose(trackId, track, c);
|
|
17137
17536
|
break;
|
|
17138
17537
|
case 'RSE':
|
|
17139
17538
|
this.parseRSE(track, c);
|
|
@@ -17640,24 +18039,33 @@ class GpifParser {
|
|
|
17640
18039
|
break;
|
|
17641
18040
|
}
|
|
17642
18041
|
}
|
|
17643
|
-
if (sound.role === 'Factory' || track.playbackInfo.program === 0) {
|
|
17644
|
-
track.playbackInfo.program = sound.program;
|
|
17645
|
-
}
|
|
17646
18042
|
if (!this._soundsByTrack.has(trackId)) {
|
|
17647
18043
|
this._soundsByTrack.set(trackId, new Map());
|
|
18044
|
+
// apply first sound
|
|
18045
|
+
track.playbackInfo.program = sound.program;
|
|
18046
|
+
track.playbackInfo.bank = sound.bank;
|
|
17648
18047
|
}
|
|
17649
18048
|
this._soundsByTrack.get(trackId).set(sound.uniqueId, sound);
|
|
17650
18049
|
}
|
|
17651
18050
|
parseSoundMidi(sound, node) {
|
|
18051
|
+
let bankMsb = 0;
|
|
18052
|
+
let bankLsb = 0;
|
|
17652
18053
|
for (const c of node.childElements()) {
|
|
17653
18054
|
switch (c.localName) {
|
|
17654
18055
|
case 'Program':
|
|
17655
18056
|
sound.program = GpifParser.parseIntSafe(c.innerText, 0);
|
|
17656
18057
|
break;
|
|
18058
|
+
case 'MSB': // coarse
|
|
18059
|
+
bankMsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18060
|
+
break;
|
|
18061
|
+
case 'LSB': // Fine
|
|
18062
|
+
bankLsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18063
|
+
break;
|
|
17657
18064
|
}
|
|
17658
18065
|
}
|
|
18066
|
+
sound.bank = ((bankMsb & 0x7f) << 7) | bankLsb;
|
|
17659
18067
|
}
|
|
17660
|
-
parsePartSounding(track, node) {
|
|
18068
|
+
parsePartSounding(trackId, track, node) {
|
|
17661
18069
|
for (const c of node.childElements()) {
|
|
17662
18070
|
switch (c.localName) {
|
|
17663
18071
|
case 'TranspositionPitch':
|
|
@@ -17665,10 +18073,14 @@ class GpifParser {
|
|
|
17665
18073
|
staff.displayTranspositionPitch = GpifParser.parseIntSafe(c.innerText, 0);
|
|
17666
18074
|
}
|
|
17667
18075
|
break;
|
|
18076
|
+
case 'NominalKey':
|
|
18077
|
+
const transposeIndex = Math.max(0, Tuning.noteNames.indexOf(c.innerText));
|
|
18078
|
+
this._transposeKeySignaturePerTrack.set(trackId, transposeIndex);
|
|
18079
|
+
break;
|
|
17668
18080
|
}
|
|
17669
18081
|
}
|
|
17670
18082
|
}
|
|
17671
|
-
parseTranspose(track, node) {
|
|
18083
|
+
parseTranspose(trackId, track, node) {
|
|
17672
18084
|
let octave = 0;
|
|
17673
18085
|
let chromatic = 0;
|
|
17674
18086
|
for (const c of node.childElements()) {
|
|
@@ -17681,9 +18093,14 @@ class GpifParser {
|
|
|
17681
18093
|
break;
|
|
17682
18094
|
}
|
|
17683
18095
|
}
|
|
18096
|
+
const pitch = octave * 12 + chromatic;
|
|
17684
18097
|
for (const staff of track.staves) {
|
|
17685
|
-
staff.displayTranspositionPitch =
|
|
18098
|
+
staff.displayTranspositionPitch = pitch;
|
|
17686
18099
|
}
|
|
18100
|
+
// the chromatic transpose also causes an alternative key signature to be adjusted
|
|
18101
|
+
// In Guitar Pro this feature is hidden in the track properties (more -> Transposition tonality -> 'C played as:' ).
|
|
18102
|
+
const transposeIndex = ModelUtils.flooredDivision(pitch, 12);
|
|
18103
|
+
this._transposeKeySignaturePerTrack.set(trackId, transposeIndex);
|
|
17687
18104
|
}
|
|
17688
18105
|
parseRSE(track, node) {
|
|
17689
18106
|
for (const c of node.childElements()) {
|
|
@@ -18647,6 +19064,7 @@ class GpifParser {
|
|
|
18647
19064
|
// GP6 had percussion as element+variation
|
|
18648
19065
|
let element = -1;
|
|
18649
19066
|
let variation = -1;
|
|
19067
|
+
let hasTransposedPitch = false;
|
|
18650
19068
|
for (const c of node.childElements()) {
|
|
18651
19069
|
switch (c.localName) {
|
|
18652
19070
|
case 'Property':
|
|
@@ -18727,7 +19145,15 @@ class GpifParser {
|
|
|
18727
19145
|
note.tone = GpifParser.parseIntSafe(c.findChildElement('Step')?.innerText, 0);
|
|
18728
19146
|
break;
|
|
18729
19147
|
case 'ConcertPitch':
|
|
19148
|
+
if (!hasTransposedPitch) {
|
|
19149
|
+
this.parseConcertPitch(c, note);
|
|
19150
|
+
}
|
|
19151
|
+
break;
|
|
19152
|
+
case 'TransposedPitch':
|
|
19153
|
+
// clear potential value from concert pitch
|
|
19154
|
+
note.accidentalMode = NoteAccidentalMode.Default;
|
|
18730
19155
|
this.parseConcertPitch(c, note);
|
|
19156
|
+
hasTransposedPitch = true;
|
|
18731
19157
|
break;
|
|
18732
19158
|
case 'Bended':
|
|
18733
19159
|
isBended = true;
|
|
@@ -18941,20 +19367,29 @@ class GpifParser {
|
|
|
18941
19367
|
lastMasterBar.isDoubleBar = false;
|
|
18942
19368
|
}
|
|
18943
19369
|
// add tracks to score
|
|
19370
|
+
const trackIndexToTrackId = [];
|
|
18944
19371
|
for (const trackId of this._tracksMapping) {
|
|
18945
19372
|
if (!trackId) {
|
|
18946
19373
|
continue;
|
|
18947
19374
|
}
|
|
18948
19375
|
const track = this._tracksById.get(trackId);
|
|
18949
19376
|
this.score.addTrack(track);
|
|
19377
|
+
trackIndexToTrackId.push(trackId);
|
|
18950
19378
|
}
|
|
18951
19379
|
// process all masterbars
|
|
18952
19380
|
let keySignature;
|
|
18953
19381
|
for (const barIds of this._barsOfMasterBar) {
|
|
18954
19382
|
// add all bars of masterbar vertically to all tracks
|
|
18955
19383
|
let staffIndex = 0;
|
|
19384
|
+
let trackIndex = 0;
|
|
18956
19385
|
keySignature = [KeySignature.C, KeySignatureType.Major];
|
|
18957
|
-
|
|
19386
|
+
if (this._transposeKeySignaturePerTrack.has(trackIndexToTrackId[0])) {
|
|
19387
|
+
keySignature = [
|
|
19388
|
+
ModelUtils.transposeKey(keySignature[0], this._transposeKeySignaturePerTrack.get(trackIndexToTrackId[0])),
|
|
19389
|
+
keySignature[1]
|
|
19390
|
+
];
|
|
19391
|
+
}
|
|
19392
|
+
for (let barIndex = 0; barIndex < barIds.length && trackIndex < this.score.tracks.length; barIndex++) {
|
|
18958
19393
|
const barId = barIds[barIndex];
|
|
18959
19394
|
if (barId !== GpifParser.InvalidId) {
|
|
18960
19395
|
const bar = this._barsById.get(barId);
|
|
@@ -18964,6 +19399,12 @@ class GpifParser {
|
|
|
18964
19399
|
const masterBarIndex = staff.bars.length - 1;
|
|
18965
19400
|
if (this._keySignatures.has(masterBarIndex)) {
|
|
18966
19401
|
keySignature = this._keySignatures.get(masterBarIndex);
|
|
19402
|
+
if (this._transposeKeySignaturePerTrack.has(trackIndexToTrackId[trackIndex])) {
|
|
19403
|
+
keySignature = [
|
|
19404
|
+
ModelUtils.transposeKey(keySignature[0], this._transposeKeySignaturePerTrack.get(trackIndexToTrackId[trackIndex])),
|
|
19405
|
+
keySignature[1]
|
|
19406
|
+
];
|
|
19407
|
+
}
|
|
18967
19408
|
}
|
|
18968
19409
|
bar.keySignature = keySignature[0];
|
|
18969
19410
|
bar.keySignatureType = keySignature[1];
|
|
@@ -19030,11 +19471,17 @@ class GpifParser {
|
|
|
19030
19471
|
if (staffIndex === track.staves.length - 1) {
|
|
19031
19472
|
trackIndex++;
|
|
19032
19473
|
staffIndex = 0;
|
|
19033
|
-
keySignature = [KeySignature.C, KeySignatureType.Major];
|
|
19034
19474
|
}
|
|
19035
19475
|
else {
|
|
19036
19476
|
staffIndex++;
|
|
19037
|
-
|
|
19477
|
+
}
|
|
19478
|
+
keySignature = [KeySignature.C, KeySignatureType.Major];
|
|
19479
|
+
if (trackIndex < trackIndexToTrackId.length &&
|
|
19480
|
+
this._transposeKeySignaturePerTrack.has(trackIndexToTrackId[trackIndex])) {
|
|
19481
|
+
keySignature = [
|
|
19482
|
+
ModelUtils.transposeKey(keySignature[0], this._transposeKeySignaturePerTrack.get(trackIndexToTrackId[trackIndex])),
|
|
19483
|
+
keySignature[1]
|
|
19484
|
+
];
|
|
19038
19485
|
}
|
|
19039
19486
|
}
|
|
19040
19487
|
else {
|
|
@@ -19070,7 +19517,12 @@ class GpifParser {
|
|
|
19070
19517
|
for (const a of automations) {
|
|
19071
19518
|
// NOTE: currently the automations of a bar are applied to the
|
|
19072
19519
|
// first beat of a bar
|
|
19073
|
-
|
|
19520
|
+
const skip =
|
|
19521
|
+
// skip bank automations if they are 0 at start
|
|
19522
|
+
a.type === AutomationType.Bank && a.value === 0 && bar.index === 0;
|
|
19523
|
+
if (!skip) {
|
|
19524
|
+
beat.automations.push(a);
|
|
19525
|
+
}
|
|
19074
19526
|
}
|
|
19075
19527
|
}
|
|
19076
19528
|
}
|
|
@@ -19122,7 +19574,7 @@ GpifParser.BendPointPositionFactor = BendPoint.MaxPosition / 100.0;
|
|
|
19122
19574
|
*/
|
|
19123
19575
|
GpifParser.BendPointValueFactor = 1 / 25.0;
|
|
19124
19576
|
// tests have shown that Guitar Pro seem to always work with 44100hz for the frame offsets,
|
|
19125
|
-
// they are NOT using the sample rate of the input file.
|
|
19577
|
+
// they are NOT using the sample rate of the input file.
|
|
19126
19578
|
// Downsampling a 44100hz ogg to 8000hz and using it in as audio track resulted in the same frame offset when placing sync points.
|
|
19127
19579
|
GpifParser.SampleRate = 44100;
|
|
19128
19580
|
|
|
@@ -19817,49 +20269,6 @@ class GpxImporter extends ScoreImporter {
|
|
|
19817
20269
|
}
|
|
19818
20270
|
}
|
|
19819
20271
|
|
|
19820
|
-
/**
|
|
19821
|
-
* Defines all possible accidentals for notes.
|
|
19822
|
-
*/
|
|
19823
|
-
var AccidentalType;
|
|
19824
|
-
(function (AccidentalType) {
|
|
19825
|
-
/**
|
|
19826
|
-
* No accidental
|
|
19827
|
-
*/
|
|
19828
|
-
AccidentalType[AccidentalType["None"] = 0] = "None";
|
|
19829
|
-
/**
|
|
19830
|
-
* Naturalize
|
|
19831
|
-
*/
|
|
19832
|
-
AccidentalType[AccidentalType["Natural"] = 1] = "Natural";
|
|
19833
|
-
/**
|
|
19834
|
-
* Sharp
|
|
19835
|
-
*/
|
|
19836
|
-
AccidentalType[AccidentalType["Sharp"] = 2] = "Sharp";
|
|
19837
|
-
/**
|
|
19838
|
-
* Flat
|
|
19839
|
-
*/
|
|
19840
|
-
AccidentalType[AccidentalType["Flat"] = 3] = "Flat";
|
|
19841
|
-
/**
|
|
19842
|
-
* Natural for smear bends
|
|
19843
|
-
*/
|
|
19844
|
-
AccidentalType[AccidentalType["NaturalQuarterNoteUp"] = 4] = "NaturalQuarterNoteUp";
|
|
19845
|
-
/**
|
|
19846
|
-
* Sharp for smear bends
|
|
19847
|
-
*/
|
|
19848
|
-
AccidentalType[AccidentalType["SharpQuarterNoteUp"] = 5] = "SharpQuarterNoteUp";
|
|
19849
|
-
/**
|
|
19850
|
-
* Flat for smear bends
|
|
19851
|
-
*/
|
|
19852
|
-
AccidentalType[AccidentalType["FlatQuarterNoteUp"] = 6] = "FlatQuarterNoteUp";
|
|
19853
|
-
/**
|
|
19854
|
-
* Double Sharp, indicated by an 'x'
|
|
19855
|
-
*/
|
|
19856
|
-
AccidentalType[AccidentalType["DoubleSharp"] = 7] = "DoubleSharp";
|
|
19857
|
-
/**
|
|
19858
|
-
* Double Flat, indicated by 'bb'
|
|
19859
|
-
*/
|
|
19860
|
-
AccidentalType[AccidentalType["DoubleFlat"] = 8] = "DoubleFlat";
|
|
19861
|
-
})(AccidentalType || (AccidentalType = {}));
|
|
19862
|
-
|
|
19863
20272
|
class BeatLines {
|
|
19864
20273
|
constructor() {
|
|
19865
20274
|
this.maxLine = -1e3;
|
|
@@ -19962,90 +20371,6 @@ class AccidentalHelper {
|
|
|
19962
20371
|
}
|
|
19963
20372
|
return line;
|
|
19964
20373
|
}
|
|
19965
|
-
static computeAccidental(keySignature, accidentalMode, noteValue, quarterBend, currentAccidental = null) {
|
|
19966
|
-
const ks = keySignature;
|
|
19967
|
-
const ksi = ks + 7;
|
|
19968
|
-
const index = noteValue % 12;
|
|
19969
|
-
const accidentalForKeySignature = ksi < 7 ? AccidentalType.Flat : AccidentalType.Sharp;
|
|
19970
|
-
const hasKeySignatureAccidentalSetForNote = AccidentalHelper.KeySignatureLookup[ksi][index];
|
|
19971
|
-
const hasNoteAccidentalWithinOctave = AccidentalHelper.AccidentalNotes[index];
|
|
19972
|
-
// the general logic is like this:
|
|
19973
|
-
// - we check if the key signature has an accidental defined
|
|
19974
|
-
// - we calculate which accidental a note needs according to its index in the octave
|
|
19975
|
-
// - if the accidental is already placed at this line, nothing needs to be done, otherwise we place it
|
|
19976
|
-
// - if there should not be an accidental, but there is one in the key signature, we clear it.
|
|
19977
|
-
// the exceptions are:
|
|
19978
|
-
// - for quarter bends we just place the corresponding accidental
|
|
19979
|
-
// - the accidental mode can enforce the accidentals for the note
|
|
19980
|
-
let accidentalToSet = AccidentalType.None;
|
|
19981
|
-
if (quarterBend) {
|
|
19982
|
-
accidentalToSet = hasNoteAccidentalWithinOctave ? accidentalForKeySignature : AccidentalType.Natural;
|
|
19983
|
-
switch (accidentalToSet) {
|
|
19984
|
-
case AccidentalType.Natural:
|
|
19985
|
-
accidentalToSet = AccidentalType.NaturalQuarterNoteUp;
|
|
19986
|
-
break;
|
|
19987
|
-
case AccidentalType.Sharp:
|
|
19988
|
-
accidentalToSet = AccidentalType.SharpQuarterNoteUp;
|
|
19989
|
-
break;
|
|
19990
|
-
case AccidentalType.Flat:
|
|
19991
|
-
accidentalToSet = AccidentalType.FlatQuarterNoteUp;
|
|
19992
|
-
break;
|
|
19993
|
-
}
|
|
19994
|
-
}
|
|
19995
|
-
else {
|
|
19996
|
-
// define which accidental should be shown ignoring what might be set on the KS already
|
|
19997
|
-
switch (accidentalMode) {
|
|
19998
|
-
case NoteAccidentalMode.ForceSharp:
|
|
19999
|
-
accidentalToSet = AccidentalType.Sharp;
|
|
20000
|
-
break;
|
|
20001
|
-
case NoteAccidentalMode.ForceDoubleSharp:
|
|
20002
|
-
accidentalToSet = AccidentalType.DoubleSharp;
|
|
20003
|
-
break;
|
|
20004
|
-
case NoteAccidentalMode.ForceFlat:
|
|
20005
|
-
accidentalToSet = AccidentalType.Flat;
|
|
20006
|
-
break;
|
|
20007
|
-
case NoteAccidentalMode.ForceDoubleFlat:
|
|
20008
|
-
accidentalToSet = AccidentalType.DoubleFlat;
|
|
20009
|
-
break;
|
|
20010
|
-
default:
|
|
20011
|
-
// if note has an accidental in the octave, we place a symbol
|
|
20012
|
-
// according to the Key Signature
|
|
20013
|
-
if (hasNoteAccidentalWithinOctave) {
|
|
20014
|
-
accidentalToSet = accidentalForKeySignature;
|
|
20015
|
-
}
|
|
20016
|
-
else if (hasKeySignatureAccidentalSetForNote) {
|
|
20017
|
-
// note does not get an accidental, but KS defines one -> Naturalize
|
|
20018
|
-
accidentalToSet = AccidentalType.Natural;
|
|
20019
|
-
}
|
|
20020
|
-
break;
|
|
20021
|
-
}
|
|
20022
|
-
// do we need an accidental on the note?
|
|
20023
|
-
if (accidentalToSet !== AccidentalType.None) {
|
|
20024
|
-
// if there is no accidental on the line, and the key signature has it set already, we clear it on the note
|
|
20025
|
-
if (currentAccidental != null) {
|
|
20026
|
-
if (currentAccidental === accidentalToSet) {
|
|
20027
|
-
accidentalToSet = AccidentalType.None;
|
|
20028
|
-
}
|
|
20029
|
-
}
|
|
20030
|
-
else if (hasKeySignatureAccidentalSetForNote && accidentalToSet === accidentalForKeySignature) {
|
|
20031
|
-
accidentalToSet = AccidentalType.None;
|
|
20032
|
-
}
|
|
20033
|
-
}
|
|
20034
|
-
else {
|
|
20035
|
-
// if we don't want an accidental, but there is already one applied, we place a naturalize accidental
|
|
20036
|
-
// and clear the registration
|
|
20037
|
-
if (currentAccidental !== null) {
|
|
20038
|
-
if (currentAccidental === AccidentalType.Natural) {
|
|
20039
|
-
accidentalToSet = AccidentalType.None;
|
|
20040
|
-
}
|
|
20041
|
-
else {
|
|
20042
|
-
accidentalToSet = AccidentalType.Natural;
|
|
20043
|
-
}
|
|
20044
|
-
}
|
|
20045
|
-
}
|
|
20046
|
-
}
|
|
20047
|
-
return accidentalToSet;
|
|
20048
|
-
}
|
|
20049
20374
|
getAccidental(noteValue, quarterBend, relatedBeat, isHelperNote, note = null) {
|
|
20050
20375
|
let steps = 0;
|
|
20051
20376
|
let accidentalToSet = AccidentalType.None;
|
|
@@ -20059,7 +20384,7 @@ class AccidentalHelper {
|
|
|
20059
20384
|
const currentAccidental = this._registeredAccidentals.has(steps)
|
|
20060
20385
|
? this._registeredAccidentals.get(steps)
|
|
20061
20386
|
: null;
|
|
20062
|
-
accidentalToSet =
|
|
20387
|
+
accidentalToSet = ModelUtils.computeAccidental(this._bar.keySignature, accidentalMode, noteValue, quarterBend, currentAccidental);
|
|
20063
20388
|
let skipAccidental = false;
|
|
20064
20389
|
switch (accidentalToSet) {
|
|
20065
20390
|
case AccidentalType.NaturalQuarterNoteUp:
|
|
@@ -20173,48 +20498,6 @@ class AccidentalHelper {
|
|
|
20173
20498
|
return 0;
|
|
20174
20499
|
}
|
|
20175
20500
|
}
|
|
20176
|
-
/**
|
|
20177
|
-
* a lookup list containing an info whether the notes within an octave
|
|
20178
|
-
* need an accidental rendered. the accidental symbol is determined based on the type of key signature.
|
|
20179
|
-
*/
|
|
20180
|
-
AccidentalHelper.KeySignatureLookup = [
|
|
20181
|
-
// Flats (where the value is true, a flat accidental is required for the notes)
|
|
20182
|
-
[true, true, true, true, true, true, true, true, true, true, true, true],
|
|
20183
|
-
[true, true, true, true, true, false, true, true, true, true, true, true],
|
|
20184
|
-
[false, true, true, true, true, false, true, true, true, true, true, true],
|
|
20185
|
-
[false, true, true, true, true, false, false, false, true, true, true, true],
|
|
20186
|
-
[false, false, false, true, true, false, false, false, true, true, true, true],
|
|
20187
|
-
[false, false, false, true, true, false, false, false, false, false, true, true],
|
|
20188
|
-
[false, false, false, false, false, false, false, false, false, false, true, true],
|
|
20189
|
-
// natural
|
|
20190
|
-
[false, false, false, false, false, false, false, false, false, false, false, false],
|
|
20191
|
-
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
20192
|
-
[false, false, false, false, false, true, true, false, false, false, false, false],
|
|
20193
|
-
[true, true, false, false, false, true, true, false, false, false, false, false],
|
|
20194
|
-
[true, true, false, false, false, true, true, true, true, false, false, false],
|
|
20195
|
-
[true, true, true, true, false, true, true, true, true, false, false, false],
|
|
20196
|
-
[true, true, true, true, false, true, true, true, true, true, true, false],
|
|
20197
|
-
[true, true, true, true, true, true, true, true, true, true, true, false],
|
|
20198
|
-
[true, true, true, true, true, true, true, true, true, true, true, true]
|
|
20199
|
-
];
|
|
20200
|
-
/**
|
|
20201
|
-
* Contains the list of notes within an octave have accidentals set.
|
|
20202
|
-
*/
|
|
20203
|
-
// prettier-ignore
|
|
20204
|
-
AccidentalHelper.AccidentalNotes = [
|
|
20205
|
-
false,
|
|
20206
|
-
true,
|
|
20207
|
-
false,
|
|
20208
|
-
true,
|
|
20209
|
-
false,
|
|
20210
|
-
false,
|
|
20211
|
-
true,
|
|
20212
|
-
false,
|
|
20213
|
-
true,
|
|
20214
|
-
false,
|
|
20215
|
-
true,
|
|
20216
|
-
false
|
|
20217
|
-
];
|
|
20218
20501
|
/**
|
|
20219
20502
|
* We always have 7 steps per octave.
|
|
20220
20503
|
* (by a step the offsets inbetween score lines is meant,
|
|
@@ -20259,6 +20542,10 @@ class InstrumentArticulationWithPlaybackInfo extends InstrumentArticulation {
|
|
|
20259
20542
|
* The midi channel program to use when playing the note (-1 if using the default track program).
|
|
20260
20543
|
*/
|
|
20261
20544
|
this.outputMidiProgram = -1;
|
|
20545
|
+
/**
|
|
20546
|
+
* The midi bank to use when playing the note (-1 if using the default track bank).
|
|
20547
|
+
*/
|
|
20548
|
+
this.outputMidiBank = -1;
|
|
20262
20549
|
/**
|
|
20263
20550
|
* The volume to use when playing the note (-1 if using the default track volume).
|
|
20264
20551
|
*/
|
|
@@ -20757,6 +21044,9 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
20757
21044
|
if (trackInfo.firstArticulation.outputMidiProgram >= 0) {
|
|
20758
21045
|
track.playbackInfo.program = trackInfo.firstArticulation.outputMidiProgram;
|
|
20759
21046
|
}
|
|
21047
|
+
if (trackInfo.firstArticulation.outputMidiBank >= 0) {
|
|
21048
|
+
track.playbackInfo.bank = trackInfo.firstArticulation.outputMidiBank;
|
|
21049
|
+
}
|
|
20760
21050
|
if (trackInfo.firstArticulation.outputBalance >= 0) {
|
|
20761
21051
|
track.playbackInfo.balance = trackInfo.firstArticulation.outputBalance;
|
|
20762
21052
|
}
|
|
@@ -20788,7 +21078,9 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
20788
21078
|
articulation.outputMidiChannel = Number.parseInt(c.innerText) - 1;
|
|
20789
21079
|
break;
|
|
20790
21080
|
// case 'midi-name': Ignored
|
|
20791
|
-
|
|
21081
|
+
case 'midi-bank':
|
|
21082
|
+
articulation.outputMidiBank = Number.parseInt(c.innerText) - 1;
|
|
21083
|
+
break;
|
|
20792
21084
|
case 'midi-program':
|
|
20793
21085
|
articulation.outputMidiProgram = Number.parseInt(c.innerText) - 1;
|
|
20794
21086
|
break;
|
|
@@ -21318,7 +21610,15 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
21318
21610
|
switch (c.localName) {
|
|
21319
21611
|
// case 'midi-channel': Ignored
|
|
21320
21612
|
// case 'midi-name': Ignored
|
|
21321
|
-
|
|
21613
|
+
case 'midi-bank':
|
|
21614
|
+
if (!this._nextBeatAutomations) {
|
|
21615
|
+
this._nextBeatAutomations = [];
|
|
21616
|
+
}
|
|
21617
|
+
automation = new Automation();
|
|
21618
|
+
automation.type = AutomationType.Bank;
|
|
21619
|
+
automation.value = Number.parseInt(c.innerText) - 1;
|
|
21620
|
+
this._nextBeatAutomations.push(automation);
|
|
21621
|
+
break;
|
|
21322
21622
|
case 'midi-program':
|
|
21323
21623
|
if (!this._nextBeatAutomations) {
|
|
21324
21624
|
this._nextBeatAutomations = [];
|
|
@@ -23589,11 +23889,15 @@ class CircularSampleBuffer {
|
|
|
23589
23889
|
}
|
|
23590
23890
|
|
|
23591
23891
|
class EventEmitter {
|
|
23592
|
-
constructor() {
|
|
23892
|
+
constructor(fireOnRegister = undefined) {
|
|
23593
23893
|
this._listeners = [];
|
|
23894
|
+
this._fireOnRegister = fireOnRegister;
|
|
23594
23895
|
}
|
|
23595
23896
|
on(value) {
|
|
23596
23897
|
this._listeners.push(value);
|
|
23898
|
+
if (this._fireOnRegister?.()) {
|
|
23899
|
+
value();
|
|
23900
|
+
}
|
|
23597
23901
|
return () => {
|
|
23598
23902
|
this.off(value);
|
|
23599
23903
|
};
|
|
@@ -23611,11 +23915,18 @@ class EventEmitter {
|
|
|
23611
23915
|
* @partial
|
|
23612
23916
|
*/
|
|
23613
23917
|
class EventEmitterOfT {
|
|
23614
|
-
constructor() {
|
|
23918
|
+
constructor(fireOnRegister = undefined) {
|
|
23615
23919
|
this._listeners = [];
|
|
23920
|
+
this._fireOnRegister = fireOnRegister;
|
|
23616
23921
|
}
|
|
23617
23922
|
on(value) {
|
|
23618
23923
|
this._listeners.push(value);
|
|
23924
|
+
if (this._fireOnRegister) {
|
|
23925
|
+
const arg = this._fireOnRegister();
|
|
23926
|
+
if (arg !== null) {
|
|
23927
|
+
value(arg);
|
|
23928
|
+
}
|
|
23929
|
+
}
|
|
23619
23930
|
return () => {
|
|
23620
23931
|
this.off(value);
|
|
23621
23932
|
};
|
|
@@ -30656,6 +30967,12 @@ class AlphaSynthBase {
|
|
|
30656
30967
|
this.sequencer.playbackSpeed = value;
|
|
30657
30968
|
this.timePosition = this.timePosition * (oldSpeed / value);
|
|
30658
30969
|
}
|
|
30970
|
+
get loadedMidiInfo() {
|
|
30971
|
+
return this._loadedMidiInfo;
|
|
30972
|
+
}
|
|
30973
|
+
get currentPosition() {
|
|
30974
|
+
return this._currentPosition;
|
|
30975
|
+
}
|
|
30659
30976
|
get tickPosition() {
|
|
30660
30977
|
return this._tickPosition;
|
|
30661
30978
|
}
|
|
@@ -30713,22 +31030,38 @@ class AlphaSynthBase {
|
|
|
30713
31030
|
this._midiEventsPlayedFilter = new Set();
|
|
30714
31031
|
this._notPlayedSamples = 0;
|
|
30715
31032
|
this._synthStopping = false;
|
|
31033
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
30716
31034
|
this.isReady = false;
|
|
30717
31035
|
this.state = PlayerState.Paused;
|
|
30718
31036
|
this._loadedSoundFonts = [];
|
|
30719
|
-
this.ready = new EventEmitter();
|
|
30720
31037
|
this.readyForPlayback = new EventEmitter();
|
|
30721
31038
|
this.finished = new EventEmitter();
|
|
30722
31039
|
this.soundFontLoaded = new EventEmitter();
|
|
30723
31040
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
30724
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
30725
31041
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
30726
|
-
this.stateChanged = new EventEmitterOfT();
|
|
30727
|
-
this.positionChanged = new EventEmitterOfT();
|
|
30728
31042
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
30729
|
-
this.playbackRangeChanged = new EventEmitterOfT();
|
|
30730
31043
|
Logger.debug('AlphaSynth', 'Initializing player');
|
|
30731
31044
|
this.state = PlayerState.Paused;
|
|
31045
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
31046
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
31047
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
31048
|
+
if (this._loadedMidiInfo) {
|
|
31049
|
+
return this._loadedMidiInfo;
|
|
31050
|
+
}
|
|
31051
|
+
return null;
|
|
31052
|
+
});
|
|
31053
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
31054
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
31055
|
+
});
|
|
31056
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
31057
|
+
return this._currentPosition;
|
|
31058
|
+
});
|
|
31059
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
31060
|
+
if (this.playbackRange) {
|
|
31061
|
+
return new PlaybackRangeChangedEventArgs(this.playbackRange);
|
|
31062
|
+
}
|
|
31063
|
+
return null;
|
|
31064
|
+
});
|
|
30732
31065
|
Logger.debug('AlphaSynth', 'Creating output');
|
|
30733
31066
|
this._output = output;
|
|
30734
31067
|
Logger.debug('AlphaSynth', 'Creating synthesizer');
|
|
@@ -30906,7 +31239,8 @@ class AlphaSynthBase {
|
|
|
30906
31239
|
Logger.debug('AlphaSynth', 'Loading midi from model');
|
|
30907
31240
|
this.sequencer.loadMidi(midi);
|
|
30908
31241
|
this._isMidiLoaded = true;
|
|
30909
|
-
this.
|
|
31242
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(0, this.sequencer.currentEndTime, 0, this.sequencer.currentEndTick, false, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31243
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
30910
31244
|
Logger.debug('AlphaSynth', 'Midi successfully loaded');
|
|
30911
31245
|
this.checkReadyForPlayback();
|
|
30912
31246
|
this.tickPosition = 0;
|
|
@@ -31009,23 +31343,28 @@ class AlphaSynthBase {
|
|
|
31009
31343
|
this.sequencer.resetOneTimeMidi();
|
|
31010
31344
|
this.timePosition = this.sequencer.currentTime;
|
|
31011
31345
|
}
|
|
31012
|
-
|
|
31013
|
-
//
|
|
31014
|
-
let currentTime =
|
|
31015
|
-
this._timePosition = currentTime;
|
|
31346
|
+
createPositionChangedEventArgs(isSeek) {
|
|
31347
|
+
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31348
|
+
let currentTime = this._timePosition;
|
|
31016
31349
|
let currentTick = this.sequencer.currentTimePositionToTickPosition(currentTime);
|
|
31017
|
-
this._tickPosition = currentTick;
|
|
31018
31350
|
const endTime = this.sequencer.currentEndTime;
|
|
31019
31351
|
const endTick = this.sequencer.currentEndTick;
|
|
31020
|
-
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31021
31352
|
if (currentTime > endTime) {
|
|
31022
31353
|
currentTime = endTime;
|
|
31023
31354
|
currentTick = endTick;
|
|
31024
31355
|
}
|
|
31356
|
+
return new PositionChangedEventArgs(currentTime, endTime, currentTick, endTick, isSeek, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31357
|
+
}
|
|
31358
|
+
updateTimePosition(timePosition, isSeek) {
|
|
31359
|
+
// update the real positions
|
|
31360
|
+
this._timePosition = timePosition;
|
|
31361
|
+
const args = this.createPositionChangedEventArgs(isSeek);
|
|
31362
|
+
this._tickPosition = args.currentTick;
|
|
31025
31363
|
const mode = this.sequencer.isPlayingMain ? 'main' : this.sequencer.isPlayingCountIn ? 'count-in' : 'one-time';
|
|
31026
|
-
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})`);
|
|
31364
|
+
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})`);
|
|
31027
31365
|
if (this.sequencer.isPlayingMain) {
|
|
31028
|
-
this.
|
|
31366
|
+
this._currentPosition = args;
|
|
31367
|
+
this.positionChanged.trigger(args);
|
|
31029
31368
|
}
|
|
31030
31369
|
// build events which were actually played
|
|
31031
31370
|
if (isSeek) {
|
|
@@ -31033,7 +31372,7 @@ class AlphaSynthBase {
|
|
|
31033
31372
|
}
|
|
31034
31373
|
else {
|
|
31035
31374
|
const playedEvents = [];
|
|
31036
|
-
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < currentTime) {
|
|
31375
|
+
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < args.currentTime) {
|
|
31037
31376
|
const synthEvent = this._playedEventsQueue.dequeue();
|
|
31038
31377
|
playedEvents.push(synthEvent.event);
|
|
31039
31378
|
}
|
|
@@ -36484,6 +36823,15 @@ class Settings {
|
|
|
36484
36823
|
fillFromJson(json) {
|
|
36485
36824
|
SettingsSerializer.fromJson(this, json);
|
|
36486
36825
|
}
|
|
36826
|
+
/**
|
|
36827
|
+
* handles backwards compatibility aspects on the settings, removed in 2.0
|
|
36828
|
+
* @internal
|
|
36829
|
+
*/
|
|
36830
|
+
handleBackwardsCompatibility() {
|
|
36831
|
+
if (this.player.playerMode === PlayerMode.Disabled && this.player.enablePlayer) {
|
|
36832
|
+
this.player.playerMode = PlayerMode.EnabledAutomatic;
|
|
36833
|
+
}
|
|
36834
|
+
}
|
|
36487
36835
|
}
|
|
36488
36836
|
|
|
36489
36837
|
class SectionSerializer {
|
|
@@ -37701,6 +38049,7 @@ class PlaybackInformationSerializer {
|
|
|
37701
38049
|
o.set("balance", obj.balance);
|
|
37702
38050
|
o.set("port", obj.port);
|
|
37703
38051
|
o.set("program", obj.program);
|
|
38052
|
+
o.set("bank", obj.bank);
|
|
37704
38053
|
o.set("primarychannel", obj.primaryChannel);
|
|
37705
38054
|
o.set("secondarychannel", obj.secondaryChannel);
|
|
37706
38055
|
o.set("ismute", obj.isMute);
|
|
@@ -37721,6 +38070,9 @@ class PlaybackInformationSerializer {
|
|
|
37721
38070
|
case "program":
|
|
37722
38071
|
obj.program = v;
|
|
37723
38072
|
return true;
|
|
38073
|
+
case "bank":
|
|
38074
|
+
obj.bank = v;
|
|
38075
|
+
return true;
|
|
37724
38076
|
case "primarychannel":
|
|
37725
38077
|
obj.primaryChannel = v;
|
|
37726
38078
|
return true;
|
|
@@ -41379,6 +41731,11 @@ class MidiFileGenerator {
|
|
|
41379
41731
|
this._programsPerChannel.set(channel, program);
|
|
41380
41732
|
}
|
|
41381
41733
|
}
|
|
41734
|
+
addBankChange(track, tick, channel, bank) {
|
|
41735
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
41736
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectCoarse, lsbMsb[1]);
|
|
41737
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectFine, lsbMsb[0]);
|
|
41738
|
+
}
|
|
41382
41739
|
static buildTranspositionPitches(score, settings) {
|
|
41383
41740
|
const transpositionPitches = new Map();
|
|
41384
41741
|
for (const track of score.tracks) {
|
|
@@ -41406,6 +41763,7 @@ class MidiFileGenerator {
|
|
|
41406
41763
|
// Set PitchBendRangeCoarse to 12
|
|
41407
41764
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryFine, 0);
|
|
41408
41765
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryCoarse, MidiFileGenerator.PitchBendRangeInSemitones);
|
|
41766
|
+
this.addBankChange(track, 0, channel, playbackInfo.bank);
|
|
41409
41767
|
this.addProgramChange(track, 0, channel, playbackInfo.program);
|
|
41410
41768
|
}
|
|
41411
41769
|
/**
|
|
@@ -42701,6 +43059,10 @@ class MidiFileGenerator {
|
|
|
42701
43059
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, (automation.value | 0) & 0xff);
|
|
42702
43060
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, (automation.value | 0) & 0xff);
|
|
42703
43061
|
break;
|
|
43062
|
+
case AutomationType.Bank:
|
|
43063
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, automation.value);
|
|
43064
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, automation.value);
|
|
43065
|
+
break;
|
|
42704
43066
|
case AutomationType.Balance:
|
|
42705
43067
|
const balance = MidiFileGenerator.toChannelShort(automation.value);
|
|
42706
43068
|
this._handler.addControlChange(beat.voice.bar.staff.track.index, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, ControllerType.PanCoarse, balance);
|
|
@@ -43650,17 +44012,29 @@ class AlphaSynthWrapper {
|
|
|
43650
44012
|
this._playbackSpeed = 1;
|
|
43651
44013
|
this._isLooping = false;
|
|
43652
44014
|
this._midiEventsPlayedFilter = [];
|
|
43653
|
-
this.ready = new EventEmitter();
|
|
43654
|
-
this.readyForPlayback = new EventEmitter();
|
|
43655
44015
|
this.finished = new EventEmitter();
|
|
43656
44016
|
this.soundFontLoaded = new EventEmitter();
|
|
43657
44017
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
43658
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
43659
44018
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
43660
|
-
this.stateChanged = new EventEmitterOfT();
|
|
43661
|
-
this.positionChanged = new EventEmitterOfT();
|
|
43662
44019
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
43663
|
-
this.
|
|
44020
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
44021
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
44022
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
44023
|
+
return this._instance?.loadedMidiInfo ?? null;
|
|
44024
|
+
});
|
|
44025
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
44026
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
44027
|
+
});
|
|
44028
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
44029
|
+
return this.currentPosition;
|
|
44030
|
+
});
|
|
44031
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
44032
|
+
const range = this.playbackRange;
|
|
44033
|
+
if (range) {
|
|
44034
|
+
return new PlaybackRangeChangedEventArgs(range);
|
|
44035
|
+
}
|
|
44036
|
+
return null;
|
|
44037
|
+
});
|
|
43664
44038
|
}
|
|
43665
44039
|
get instance() {
|
|
43666
44040
|
return this._instance;
|
|
@@ -43682,10 +44056,14 @@ class AlphaSynthWrapper {
|
|
|
43682
44056
|
newUnregister.push(value.finished.on(() => this.finished.trigger()));
|
|
43683
44057
|
newUnregister.push(value.soundFontLoaded.on(() => this.soundFontLoaded.trigger()));
|
|
43684
44058
|
newUnregister.push(value.soundFontLoadFailed.on(e => this.soundFontLoadFailed.trigger(e)));
|
|
43685
|
-
newUnregister.push(value.midiLoaded.on(e =>
|
|
44059
|
+
newUnregister.push(value.midiLoaded.on(e => {
|
|
44060
|
+
this.midiLoaded.trigger(e);
|
|
44061
|
+
}));
|
|
43686
44062
|
newUnregister.push(value.midiLoadFailed.on(e => this.midiLoadFailed.trigger(e)));
|
|
43687
44063
|
newUnregister.push(value.stateChanged.on(e => this.stateChanged.trigger(e)));
|
|
43688
|
-
newUnregister.push(value.positionChanged.on(e =>
|
|
44064
|
+
newUnregister.push(value.positionChanged.on(e => {
|
|
44065
|
+
this.positionChanged.trigger(e);
|
|
44066
|
+
}));
|
|
43689
44067
|
newUnregister.push(value.midiEventsPlayed.on(e => this.midiEventsPlayed.trigger(e)));
|
|
43690
44068
|
newUnregister.push(value.playbackRangeChanged.on(e => this.playbackRangeChanged.trigger(e)));
|
|
43691
44069
|
this._instanceEventUnregister = newUnregister;
|
|
@@ -43764,6 +44142,14 @@ class AlphaSynthWrapper {
|
|
|
43764
44142
|
this._instance.playbackSpeed = value;
|
|
43765
44143
|
}
|
|
43766
44144
|
}
|
|
44145
|
+
get loadedMidiInfo() {
|
|
44146
|
+
return this._instance ? this._instance.loadedMidiInfo : undefined;
|
|
44147
|
+
}
|
|
44148
|
+
get currentPosition() {
|
|
44149
|
+
return this._instance
|
|
44150
|
+
? this._instance.currentPosition
|
|
44151
|
+
: new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
44152
|
+
}
|
|
43767
44153
|
get tickPosition() {
|
|
43768
44154
|
return this._instance ? this._instance.tickPosition : 0;
|
|
43769
44155
|
}
|
|
@@ -44105,83 +44491,6 @@ class AlphaTabApiBase {
|
|
|
44105
44491
|
this._previousStateForCursor = PlayerState.Paused;
|
|
44106
44492
|
this._previousCursorCache = null;
|
|
44107
44493
|
this._lastScroll = 0;
|
|
44108
|
-
/**
|
|
44109
|
-
* This event is fired when the played beat changed.
|
|
44110
|
-
*
|
|
44111
|
-
* @eventProperty
|
|
44112
|
-
* @category Events - Player
|
|
44113
|
-
* @since 0.9.4
|
|
44114
|
-
*
|
|
44115
|
-
* @example
|
|
44116
|
-
* JavaScript
|
|
44117
|
-
* ```js
|
|
44118
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44119
|
-
* api.playedBeatChanged.on((beat) => {
|
|
44120
|
-
* updateFretboard(beat);
|
|
44121
|
-
* });
|
|
44122
|
-
* ```
|
|
44123
|
-
*
|
|
44124
|
-
* @example
|
|
44125
|
-
* C#
|
|
44126
|
-
* ```cs
|
|
44127
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44128
|
-
* api.PlayedBeatChanged.On(beat =>
|
|
44129
|
-
* {
|
|
44130
|
-
* UpdateFretboard(beat);
|
|
44131
|
-
* });
|
|
44132
|
-
* ```
|
|
44133
|
-
*
|
|
44134
|
-
* @example
|
|
44135
|
-
* Android
|
|
44136
|
-
* ```kotlin
|
|
44137
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44138
|
-
* api.playedBeatChanged.on { beat ->
|
|
44139
|
-
* updateFretboard(beat)
|
|
44140
|
-
* }
|
|
44141
|
-
* ```
|
|
44142
|
-
*
|
|
44143
|
-
*/
|
|
44144
|
-
this.playedBeatChanged = new EventEmitterOfT();
|
|
44145
|
-
/**
|
|
44146
|
-
* This event is fired when the currently active beats across all tracks change.
|
|
44147
|
-
*
|
|
44148
|
-
* @remarks
|
|
44149
|
-
* Unlike the {@link playedBeatChanged} event this event contains the beats of all tracks and voices independent of them being rendered.
|
|
44150
|
-
*
|
|
44151
|
-
* @eventProperty
|
|
44152
|
-
* @category Events - Player
|
|
44153
|
-
* @since 1.2.3
|
|
44154
|
-
*
|
|
44155
|
-
* @example
|
|
44156
|
-
* JavaScript
|
|
44157
|
-
* ```js
|
|
44158
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44159
|
-
* api.activeBeatsChanged.on(args => {
|
|
44160
|
-
* updateHighlights(args.activeBeats);
|
|
44161
|
-
* });
|
|
44162
|
-
* ```
|
|
44163
|
-
*
|
|
44164
|
-
* @example
|
|
44165
|
-
* C#
|
|
44166
|
-
* ```cs
|
|
44167
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44168
|
-
* api.ActiveBeatsChanged.On(args =>
|
|
44169
|
-
* {
|
|
44170
|
-
* UpdateHighlights(args.ActiveBeats);
|
|
44171
|
-
* });
|
|
44172
|
-
* ```
|
|
44173
|
-
*
|
|
44174
|
-
* @example
|
|
44175
|
-
* Android
|
|
44176
|
-
* ```kotlin
|
|
44177
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44178
|
-
* api.activeBeatsChanged.on { args ->
|
|
44179
|
-
* updateHighlights(args.activeBeats)
|
|
44180
|
-
* }
|
|
44181
|
-
* ```
|
|
44182
|
-
*
|
|
44183
|
-
*/
|
|
44184
|
-
this.activeBeatsChanged = new EventEmitterOfT();
|
|
44185
44494
|
this._beatMouseDown = false;
|
|
44186
44495
|
this._noteMouseDown = false;
|
|
44187
44496
|
this._selectionStart = null;
|
|
@@ -44420,47 +44729,6 @@ class AlphaTabApiBase {
|
|
|
44420
44729
|
*
|
|
44421
44730
|
*/
|
|
44422
44731
|
this.noteMouseUp = new EventEmitterOfT();
|
|
44423
|
-
/**
|
|
44424
|
-
* This event is fired whenever a new song is loaded.
|
|
44425
|
-
* @remarks
|
|
44426
|
-
* This event is fired whenever a new song is loaded or changing due to {@link renderScore} or {@link renderTracks} calls.
|
|
44427
|
-
* It is fired after the transposition midi pitches from the settings were applied, but before any midi is generated or rendering is started.
|
|
44428
|
-
* This allows any modification of the score before further processing.
|
|
44429
|
-
*
|
|
44430
|
-
* @eventProperty
|
|
44431
|
-
* @category Events - Core
|
|
44432
|
-
* @since 0.9.4
|
|
44433
|
-
*
|
|
44434
|
-
* @example
|
|
44435
|
-
* JavaScript
|
|
44436
|
-
* ```js
|
|
44437
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44438
|
-
* api.scoreLoaded.on((score) => {
|
|
44439
|
-
* updateSongInformationInUi(score);
|
|
44440
|
-
* });
|
|
44441
|
-
* ```
|
|
44442
|
-
*
|
|
44443
|
-
* @example
|
|
44444
|
-
* C#
|
|
44445
|
-
* ```cs
|
|
44446
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44447
|
-
* api.ScoreLoaded.On(score =>
|
|
44448
|
-
* {
|
|
44449
|
-
* UpdateSongInformationInUi(score);
|
|
44450
|
-
* });
|
|
44451
|
-
* ```
|
|
44452
|
-
*
|
|
44453
|
-
* @example
|
|
44454
|
-
* Android
|
|
44455
|
-
* ```kotlin
|
|
44456
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44457
|
-
* api.scoreLoaded.on { score ->
|
|
44458
|
-
* updateSongInformationInUi(score)
|
|
44459
|
-
* }
|
|
44460
|
-
* ```
|
|
44461
|
-
*
|
|
44462
|
-
*/
|
|
44463
|
-
this.scoreLoaded = new EventEmitterOfT();
|
|
44464
44732
|
/**
|
|
44465
44733
|
* This event is fired when alphaTab was resized and is about to rerender the music notation.
|
|
44466
44734
|
* @remarks
|
|
@@ -44719,46 +44987,6 @@ class AlphaTabApiBase {
|
|
|
44719
44987
|
*
|
|
44720
44988
|
*/
|
|
44721
44989
|
this.midiLoad = new EventEmitterOfT();
|
|
44722
|
-
/**
|
|
44723
|
-
* This event is fired when the Midi file needed for playback was loaded.
|
|
44724
|
-
*
|
|
44725
|
-
* @eventProperty
|
|
44726
|
-
* @category Events - Player
|
|
44727
|
-
* @since 0.9.4
|
|
44728
|
-
*
|
|
44729
|
-
* @example
|
|
44730
|
-
* JavaScript
|
|
44731
|
-
* ```js
|
|
44732
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44733
|
-
* api.midiLoaded.on(e => {
|
|
44734
|
-
* hideGeneratingAudioIndicator();
|
|
44735
|
-
* updateSongDuration(e.endTime);
|
|
44736
|
-
* });
|
|
44737
|
-
* ```
|
|
44738
|
-
*
|
|
44739
|
-
* @example
|
|
44740
|
-
* C#
|
|
44741
|
-
* ```cs
|
|
44742
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44743
|
-
* api.MidiLoaded.On(e =>
|
|
44744
|
-
* {
|
|
44745
|
-
* HideGeneratingAudioIndicator();
|
|
44746
|
-
* UpdateSongDuration(e.EndTime);
|
|
44747
|
-
* });
|
|
44748
|
-
* ```
|
|
44749
|
-
*
|
|
44750
|
-
* @example
|
|
44751
|
-
* Android
|
|
44752
|
-
* ```kotlin
|
|
44753
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44754
|
-
* api.midiLoaded.on { e ->
|
|
44755
|
-
* hideGeneratingAudioIndicator()
|
|
44756
|
-
* updateSongDuration(e.endTime)
|
|
44757
|
-
* }
|
|
44758
|
-
* ```
|
|
44759
|
-
*
|
|
44760
|
-
*/
|
|
44761
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
44762
44990
|
/**
|
|
44763
44991
|
* This event is fired when a settings update was requested.
|
|
44764
44992
|
*
|
|
@@ -44798,12 +45026,30 @@ class AlphaTabApiBase {
|
|
|
44798
45026
|
this.settingsUpdated = new EventEmitter();
|
|
44799
45027
|
this.uiFacade = uiFacade;
|
|
44800
45028
|
this.container = uiFacade.rootContainer;
|
|
45029
|
+
this.activeBeatsChanged = new EventEmitterOfT(() => {
|
|
45030
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45031
|
+
return new ActiveBeatsChangedEventArgs(this._currentBeat.beatLookup.highlightedBeats.map(h => h.beat));
|
|
45032
|
+
}
|
|
45033
|
+
return null;
|
|
45034
|
+
});
|
|
45035
|
+
this.playedBeatChanged = new EventEmitterOfT(() => {
|
|
45036
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45037
|
+
return this._currentBeat.beat;
|
|
45038
|
+
}
|
|
45039
|
+
return null;
|
|
45040
|
+
});
|
|
45041
|
+
this.scoreLoaded = new EventEmitterOfT(() => {
|
|
45042
|
+
if (this._score) {
|
|
45043
|
+
return this._score;
|
|
45044
|
+
}
|
|
45045
|
+
return null;
|
|
45046
|
+
});
|
|
45047
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
45048
|
+
return this._player.loadedMidiInfo ?? null;
|
|
45049
|
+
});
|
|
44801
45050
|
uiFacade.initialize(this, settings);
|
|
44802
45051
|
Logger.logLevel = this.settings.core.logLevel;
|
|
44803
|
-
|
|
44804
|
-
if (this.settings.player.playerMode === PlayerMode.Disabled && this.settings.player.enablePlayer) {
|
|
44805
|
-
this.settings.player.playerMode = PlayerMode.EnabledAutomatic;
|
|
44806
|
-
}
|
|
45052
|
+
this.settings.handleBackwardsCompatibility();
|
|
44807
45053
|
Environment.printEnvironmentInfo(false);
|
|
44808
45054
|
this.canvasElement = uiFacade.createCanvasElement();
|
|
44809
45055
|
this.container.appendChild(this.canvasElement);
|
|
@@ -44962,6 +45208,7 @@ class AlphaTabApiBase {
|
|
|
44962
45208
|
* ```
|
|
44963
45209
|
*/
|
|
44964
45210
|
updateSettings() {
|
|
45211
|
+
this.settings.handleBackwardsCompatibility();
|
|
44965
45212
|
const score = this.score;
|
|
44966
45213
|
if (score) {
|
|
44967
45214
|
ModelUtils.applyPitchOffsets(this.settings, score);
|
|
@@ -45769,6 +46016,22 @@ class AlphaTabApiBase {
|
|
|
45769
46016
|
set timePosition(value) {
|
|
45770
46017
|
this._player.timePosition = value;
|
|
45771
46018
|
}
|
|
46019
|
+
/**
|
|
46020
|
+
* The total length of the song in midi ticks.
|
|
46021
|
+
* @category Properties - Player
|
|
46022
|
+
* @since 1.6.2
|
|
46023
|
+
*/
|
|
46024
|
+
get endTick() {
|
|
46025
|
+
return this._player.currentPosition.endTick;
|
|
46026
|
+
}
|
|
46027
|
+
/**
|
|
46028
|
+
* The total length of the song in milliseconds.
|
|
46029
|
+
* @category Properties - Player
|
|
46030
|
+
* @since 1.6.2
|
|
46031
|
+
*/
|
|
46032
|
+
get endTime() {
|
|
46033
|
+
return this._player.currentPosition.endTime;
|
|
46034
|
+
}
|
|
45772
46035
|
/**
|
|
45773
46036
|
* The range of the song that should be played.
|
|
45774
46037
|
* @remarks
|
|
@@ -48093,27 +48356,33 @@ class AlphaSynthWebWorkerApi {
|
|
|
48093
48356
|
value: value
|
|
48094
48357
|
});
|
|
48095
48358
|
}
|
|
48359
|
+
get loadedMidiInfo() {
|
|
48360
|
+
return this.loadedMidiInfo;
|
|
48361
|
+
}
|
|
48362
|
+
get currentPosition() {
|
|
48363
|
+
return this._currentPosition;
|
|
48364
|
+
}
|
|
48096
48365
|
get tickPosition() {
|
|
48097
|
-
return this.
|
|
48366
|
+
return this._currentPosition.currentTick;
|
|
48098
48367
|
}
|
|
48099
48368
|
set tickPosition(value) {
|
|
48100
48369
|
if (value < 0) {
|
|
48101
48370
|
value = 0;
|
|
48102
48371
|
}
|
|
48103
|
-
this.
|
|
48372
|
+
this._currentPosition = new PositionChangedEventArgs(this._currentPosition.currentTime, this._currentPosition.endTime, value, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48104
48373
|
this._synth.postMessage({
|
|
48105
48374
|
cmd: 'alphaSynth.setTickPosition',
|
|
48106
48375
|
value: value
|
|
48107
48376
|
});
|
|
48108
48377
|
}
|
|
48109
48378
|
get timePosition() {
|
|
48110
|
-
return this.
|
|
48379
|
+
return this._currentPosition.currentTime;
|
|
48111
48380
|
}
|
|
48112
48381
|
set timePosition(value) {
|
|
48113
48382
|
if (value < 0) {
|
|
48114
48383
|
value = 0;
|
|
48115
48384
|
}
|
|
48116
|
-
this.
|
|
48385
|
+
this._currentPosition = new PositionChangedEventArgs(value, this._currentPosition.endTime, this._currentPosition.currentTick, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48117
48386
|
this._synth.postMessage({
|
|
48118
48387
|
cmd: 'alphaSynth.setTimePosition',
|
|
48119
48388
|
value: value
|
|
@@ -48156,11 +48425,10 @@ class AlphaSynthWebWorkerApi {
|
|
|
48156
48425
|
this._metronomeVolume = 0;
|
|
48157
48426
|
this._countInVolume = 0;
|
|
48158
48427
|
this._playbackSpeed = 0;
|
|
48159
|
-
this._tickPosition = 0;
|
|
48160
|
-
this._timePosition = 0;
|
|
48161
48428
|
this._isLooping = false;
|
|
48162
48429
|
this._playbackRange = null;
|
|
48163
48430
|
this._midiEventsPlayedFilter = [];
|
|
48431
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
48164
48432
|
this.ready = new EventEmitter();
|
|
48165
48433
|
this.readyForPlayback = new EventEmitter();
|
|
48166
48434
|
this.finished = new EventEmitter();
|
|
@@ -48179,8 +48447,6 @@ class AlphaSynthWebWorkerApi {
|
|
|
48179
48447
|
this._masterVolume = 0.0;
|
|
48180
48448
|
this._metronomeVolume = 0.0;
|
|
48181
48449
|
this._playbackSpeed = 0.0;
|
|
48182
|
-
this._tickPosition = 0;
|
|
48183
|
-
this._timePosition = 0.0;
|
|
48184
48450
|
this._isLooping = false;
|
|
48185
48451
|
this._playbackRange = null;
|
|
48186
48452
|
this._output = player;
|
|
@@ -48315,9 +48581,8 @@ class AlphaSynthWebWorkerApi {
|
|
|
48315
48581
|
this.checkReadyForPlayback();
|
|
48316
48582
|
break;
|
|
48317
48583
|
case 'alphaSynth.positionChanged':
|
|
48318
|
-
this.
|
|
48319
|
-
this.
|
|
48320
|
-
this.positionChanged.trigger(new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo));
|
|
48584
|
+
this._currentPosition = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48585
|
+
this.positionChanged.trigger(this._currentPosition);
|
|
48321
48586
|
break;
|
|
48322
48587
|
case 'alphaSynth.midiEventsPlayed':
|
|
48323
48588
|
this.midiEventsPlayed.trigger(new MidiEventsPlayedEventArgs(data.events.map(JsonConverter.jsObjectToMidiEvent)));
|
|
@@ -48341,7 +48606,8 @@ class AlphaSynthWebWorkerApi {
|
|
|
48341
48606
|
break;
|
|
48342
48607
|
case 'alphaSynth.midiLoaded':
|
|
48343
48608
|
this.checkReadyForPlayback();
|
|
48344
|
-
this.
|
|
48609
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48610
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
48345
48611
|
break;
|
|
48346
48612
|
case 'alphaSynth.midiLoadFailed':
|
|
48347
48613
|
this.checkReadyForPlayback();
|
|
@@ -59053,7 +59319,7 @@ class NumberedBeatPreNotesGlyph extends BeatGlyphBase {
|
|
|
59053
59319
|
// - when the standard notation naturalizes the accidental from the key signature, the numbered notation has the reversed accidental
|
|
59054
59320
|
const accidentalMode = note ? note.accidentalMode : NoteAccidentalMode.Default;
|
|
59055
59321
|
const noteValue = AccidentalHelper.getNoteValue(note);
|
|
59056
|
-
let accidentalToSet =
|
|
59322
|
+
let accidentalToSet = ModelUtils.computeAccidental(this.renderer.bar.keySignature, accidentalMode, noteValue, note.hasQuarterToneOffset);
|
|
59057
59323
|
if (accidentalToSet === AccidentalType.Natural) {
|
|
59058
59324
|
const ks = this.renderer.bar.keySignature;
|
|
59059
59325
|
const ksi = ks + 7;
|
|
@@ -59212,7 +59478,7 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
59212
59478
|
? AccidentalHelper.FlatNoteSteps
|
|
59213
59479
|
: AccidentalHelper.SharpNoteSteps;
|
|
59214
59480
|
let steps = stepList[index] + 1;
|
|
59215
|
-
const hasAccidental =
|
|
59481
|
+
const hasAccidental = ModelUtils.AccidentalNotes[index];
|
|
59216
59482
|
if (hasAccidental &&
|
|
59217
59483
|
!this.container.preNotes.isNaturalizeAccidental) {
|
|
59218
59484
|
if (ksi < 7) {
|
|
@@ -66425,6 +66691,30 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66425
66691
|
if (stylesheet.useSystemSignSeparator) {
|
|
66426
66692
|
writer.writeMeta('useSystemSignSeparator');
|
|
66427
66693
|
}
|
|
66694
|
+
if (stylesheet.multiTrackMultiBarRest) {
|
|
66695
|
+
writer.writeMeta('multiBarRest');
|
|
66696
|
+
}
|
|
66697
|
+
if (stylesheet.singleTrackTrackNamePolicy !==
|
|
66698
|
+
AlphaTexExporter.DefaultScore.stylesheet.singleTrackTrackNamePolicy) {
|
|
66699
|
+
writer.writeMeta('singleTrackTrackNamePolicy', TrackNamePolicy[stylesheet.singleTrackTrackNamePolicy]);
|
|
66700
|
+
}
|
|
66701
|
+
if (stylesheet.multiTrackTrackNamePolicy !== AlphaTexExporter.DefaultScore.stylesheet.multiTrackTrackNamePolicy) {
|
|
66702
|
+
writer.writeMeta('multiTrackTrackNamePolicy', TrackNamePolicy[stylesheet.multiTrackTrackNamePolicy]);
|
|
66703
|
+
}
|
|
66704
|
+
if (stylesheet.firstSystemTrackNameMode !== AlphaTexExporter.DefaultScore.stylesheet.firstSystemTrackNameMode) {
|
|
66705
|
+
writer.writeMeta('firstSystemTrackNameMode', TrackNameMode[stylesheet.firstSystemTrackNameMode]);
|
|
66706
|
+
}
|
|
66707
|
+
if (stylesheet.otherSystemsTrackNameMode !== AlphaTexExporter.DefaultScore.stylesheet.otherSystemsTrackNameMode) {
|
|
66708
|
+
writer.writeMeta('otherSystemsTrackNameMode', TrackNameMode[stylesheet.otherSystemsTrackNameMode]);
|
|
66709
|
+
}
|
|
66710
|
+
if (stylesheet.firstSystemTrackNameOrientation !==
|
|
66711
|
+
AlphaTexExporter.DefaultScore.stylesheet.firstSystemTrackNameOrientation) {
|
|
66712
|
+
writer.writeMeta('firstSystemTrackNameOrientation', TrackNameOrientation[stylesheet.firstSystemTrackNameOrientation]);
|
|
66713
|
+
}
|
|
66714
|
+
if (stylesheet.otherSystemsTrackNameOrientation !==
|
|
66715
|
+
AlphaTexExporter.DefaultScore.stylesheet.otherSystemsTrackNameOrientation) {
|
|
66716
|
+
writer.writeMeta('otherSystemsTrackNameOrientation', TrackNameOrientation[stylesheet.otherSystemsTrackNameOrientation]);
|
|
66717
|
+
}
|
|
66428
66718
|
}
|
|
66429
66719
|
writeTrackTo(writer, track) {
|
|
66430
66720
|
writer.write('\\track ');
|
|
@@ -66460,6 +66750,10 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66460
66750
|
track.score.stylesheet.perTrackMultiBarRest.has(track.index)) {
|
|
66461
66751
|
writer.writeLine(` multibarrest`);
|
|
66462
66752
|
}
|
|
66753
|
+
writer.writeLine(` instrument ${track.isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program)}`);
|
|
66754
|
+
if (track.playbackInfo.bank > 0) {
|
|
66755
|
+
writer.writeLine(` bank ${track.playbackInfo.bank}`);
|
|
66756
|
+
}
|
|
66463
66757
|
writer.outdent();
|
|
66464
66758
|
writer.writeLine('}');
|
|
66465
66759
|
writer.indent();
|
|
@@ -66518,13 +66812,7 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66518
66812
|
writer.writeLine('|');
|
|
66519
66813
|
}
|
|
66520
66814
|
if (voiceIndex === 0) {
|
|
66521
|
-
// Track meta on first bar
|
|
66522
66815
|
let anyWritten = false;
|
|
66523
|
-
if (bar.index === 0 && bar.staff.index === 0) {
|
|
66524
|
-
const l = writer.tex.length;
|
|
66525
|
-
this.writeTrackMetaTo(writer, bar.staff.track);
|
|
66526
|
-
anyWritten = writer.tex.length > l;
|
|
66527
|
-
}
|
|
66528
66816
|
// Staff meta on first bar
|
|
66529
66817
|
if (bar.index === 0) {
|
|
66530
66818
|
const l = writer.tex.length;
|
|
@@ -66554,14 +66842,6 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66554
66842
|
}
|
|
66555
66843
|
writer.outdent();
|
|
66556
66844
|
}
|
|
66557
|
-
writeTrackMetaTo(writer, track) {
|
|
66558
|
-
writer.writeSingleLineComment(`Track ${track.index + 1} Metadata`);
|
|
66559
|
-
this.writePlaybackInfoTo(writer, track);
|
|
66560
|
-
}
|
|
66561
|
-
writePlaybackInfoTo(writer, track) {
|
|
66562
|
-
const isPercussion = track.staves.some(s => s.isPercussion);
|
|
66563
|
-
writer.writeMeta('instrument', isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program));
|
|
66564
|
-
}
|
|
66565
66845
|
writeStaffMetaTo(writer, staff) {
|
|
66566
66846
|
writer.writeSingleLineComment(`Staff ${staff.index + 1} Metadata`);
|
|
66567
66847
|
if (staff.capo !== 0) {
|
|
@@ -66594,6 +66874,7 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66594
66874
|
if (staff.displayTranspositionPitch !== defaultTransposition) {
|
|
66595
66875
|
writer.writeMeta('displaytranspose', `${-staff.displayTranspositionPitch}`);
|
|
66596
66876
|
}
|
|
66877
|
+
writer.writeMeta('accidentals', 'auto');
|
|
66597
66878
|
if (staff.chords != null) {
|
|
66598
66879
|
for (const [_, chord] of staff.chords) {
|
|
66599
66880
|
this.writeChordTo(writer, chord);
|
|
@@ -66961,6 +67242,18 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66961
67242
|
writer.writeGroupItem('txt ');
|
|
66962
67243
|
writer.writeString(beat.text);
|
|
66963
67244
|
}
|
|
67245
|
+
if (beat.lyrics != null && beat.lyrics.length > 0) {
|
|
67246
|
+
if (beat.lyrics.length > 1) {
|
|
67247
|
+
for (let i = 0; i < beat.lyrics.length; i++) {
|
|
67248
|
+
writer.writeGroupItem(`lyrics ${i} `);
|
|
67249
|
+
writer.writeString(beat.lyrics[i]);
|
|
67250
|
+
}
|
|
67251
|
+
}
|
|
67252
|
+
else {
|
|
67253
|
+
writer.writeGroupItem('lyrics ');
|
|
67254
|
+
writer.writeString(beat.lyrics[0]);
|
|
67255
|
+
}
|
|
67256
|
+
}
|
|
66964
67257
|
switch (beat.graceType) {
|
|
66965
67258
|
case GraceType.OnBeat:
|
|
66966
67259
|
writer.writeGroupItem('gr ob');
|
|
@@ -67595,7 +67888,7 @@ class GpifWriter {
|
|
|
67595
67888
|
this.writePitch(properties, 'ConcertPitch', 'C', '-1', '');
|
|
67596
67889
|
}
|
|
67597
67890
|
else {
|
|
67598
|
-
this.writePitchForValue(properties, 'TransposedPitch', note.displayValueWithoutBend, note.accidentalMode);
|
|
67891
|
+
this.writePitchForValue(properties, 'TransposedPitch', note.displayValueWithoutBend, note.accidentalMode, note.beat.voice.bar.keySignature);
|
|
67599
67892
|
}
|
|
67600
67893
|
}
|
|
67601
67894
|
writeConcertPitch(properties, note) {
|
|
@@ -67603,10 +67896,10 @@ class GpifWriter {
|
|
|
67603
67896
|
this.writePitch(properties, 'ConcertPitch', 'C', '-1', '');
|
|
67604
67897
|
}
|
|
67605
67898
|
else {
|
|
67606
|
-
this.writePitchForValue(properties, 'ConcertPitch', note.realValueWithoutHarmonic, note.accidentalMode);
|
|
67899
|
+
this.writePitchForValue(properties, 'ConcertPitch', note.realValueWithoutHarmonic, note.accidentalMode, note.beat.voice.bar.keySignature);
|
|
67607
67900
|
}
|
|
67608
67901
|
}
|
|
67609
|
-
writePitchForValue(properties, propertyName, value, accidentalMode) {
|
|
67902
|
+
writePitchForValue(properties, propertyName, value, accidentalMode, keySignature) {
|
|
67610
67903
|
let index = 0;
|
|
67611
67904
|
let octave = 0;
|
|
67612
67905
|
let step = '';
|
|
@@ -67614,8 +67907,25 @@ class GpifWriter {
|
|
|
67614
67907
|
const updateParts = () => {
|
|
67615
67908
|
index = value % 12;
|
|
67616
67909
|
octave = (value / 12) | 0;
|
|
67617
|
-
step =
|
|
67618
|
-
|
|
67910
|
+
step = GpifWriter.defaultSteps[index];
|
|
67911
|
+
switch (ModelUtils.computeAccidental(keySignature, NoteAccidentalMode.Default, value, false)) {
|
|
67912
|
+
case AccidentalType.None:
|
|
67913
|
+
case AccidentalType.Natural:
|
|
67914
|
+
accidental = '';
|
|
67915
|
+
break;
|
|
67916
|
+
case AccidentalType.Sharp:
|
|
67917
|
+
accidental = '#';
|
|
67918
|
+
break;
|
|
67919
|
+
case AccidentalType.Flat:
|
|
67920
|
+
accidental = 'b';
|
|
67921
|
+
break;
|
|
67922
|
+
case AccidentalType.DoubleSharp:
|
|
67923
|
+
accidental = 'x';
|
|
67924
|
+
break;
|
|
67925
|
+
case AccidentalType.DoubleFlat:
|
|
67926
|
+
accidental = 'bb';
|
|
67927
|
+
break;
|
|
67928
|
+
}
|
|
67619
67929
|
};
|
|
67620
67930
|
updateParts();
|
|
67621
67931
|
switch (accidentalMode) {
|
|
@@ -68090,10 +68400,12 @@ class GpifWriter {
|
|
|
68090
68400
|
const value = syncPointAutomation.addElement('Value');
|
|
68091
68401
|
value.addElement('BarIndex').innerText = mb.index.toString();
|
|
68092
68402
|
value.addElement('BarOccurrence').innerText = syncPoint.syncPointValue.barOccurence.toString();
|
|
68093
|
-
value.addElement('ModifiedTempo').innerText = modifiedTempoLookup.value
|
|
68403
|
+
value.addElement('ModifiedTempo').innerText = modifiedTempoLookup.value
|
|
68404
|
+
.get(syncPoint)
|
|
68405
|
+
.syncBpm.toString();
|
|
68094
68406
|
value.addElement('OriginalTempo').innerText = score.tempo.toString();
|
|
68095
|
-
let frameOffset = ((
|
|
68096
|
-
GpifWriter.SampleRate
|
|
68407
|
+
let frameOffset = ((syncPoint.syncPointValue.millisecondOffset - millisecondPadding) / 1000) *
|
|
68408
|
+
GpifWriter.SampleRate;
|
|
68097
68409
|
frameOffset = Math.floor(frameOffset + 0.5);
|
|
68098
68410
|
value.addElement('FrameOffset').innerText = frameOffset.toString();
|
|
68099
68411
|
}
|
|
@@ -68152,15 +68464,16 @@ class GpifWriter {
|
|
|
68152
68464
|
}
|
|
68153
68465
|
return GpifIconIds.SteelGuitar;
|
|
68154
68466
|
}
|
|
68155
|
-
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, ratioPosition = 0) {
|
|
68467
|
+
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, bank, ratioPosition = 0) {
|
|
68156
68468
|
const soundNode = soundsNode.addElement('Sound');
|
|
68157
68469
|
soundNode.addElement('Name').setCData(name);
|
|
68158
68470
|
soundNode.addElement('Label').setCData(name);
|
|
68159
68471
|
soundNode.addElement('Path').setCData(path);
|
|
68160
68472
|
soundNode.addElement('Role').setCData(role);
|
|
68161
68473
|
const midi = soundNode.addElement('MIDI');
|
|
68162
|
-
|
|
68163
|
-
midi.addElement('
|
|
68474
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
68475
|
+
midi.addElement('LSB').innerText = lsbMsb[0].toString();
|
|
68476
|
+
midi.addElement('MSB').innerText = lsbMsb[1].toString();
|
|
68164
68477
|
midi.addElement('Program').innerText = program.toString();
|
|
68165
68478
|
const automationNode = automationsNode.addElement('Automation');
|
|
68166
68479
|
automationNode.addElement('Type').innerText = 'Sound';
|
|
@@ -68178,21 +68491,26 @@ class GpifWriter {
|
|
|
68178
68491
|
const trackSoundPath = `Midi/${track.playbackInfo.program}`;
|
|
68179
68492
|
const trackSoundRole = 'Factory';
|
|
68180
68493
|
let trackSoundWritten = false;
|
|
68494
|
+
let bank = track.playbackInfo.bank;
|
|
68181
68495
|
for (const staff of track.staves) {
|
|
68182
68496
|
for (const bar of staff.bars) {
|
|
68183
68497
|
for (const voice of bar.voices) {
|
|
68184
68498
|
for (const beat of voice.beats) {
|
|
68185
68499
|
const soundAutomation = beat.getAutomation(AutomationType.Instrument);
|
|
68186
68500
|
const isTrackSound = bar.index === 0 && beat.index === 0;
|
|
68501
|
+
const bankAutomation = beat.getAutomation(AutomationType.Bank);
|
|
68502
|
+
if (bankAutomation) {
|
|
68503
|
+
bank = bankAutomation.value;
|
|
68504
|
+
}
|
|
68187
68505
|
if (soundAutomation) {
|
|
68188
68506
|
const name = isTrackSound ? trackSoundName : `ProgramChange_${beat.id}`;
|
|
68189
68507
|
const path = isTrackSound ? trackSoundPath : `Midi/${soundAutomation.value}`;
|
|
68190
68508
|
const role = isTrackSound ? trackSoundRole : 'User';
|
|
68191
68509
|
if (!isTrackSound && !trackSoundWritten) {
|
|
68192
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program);
|
|
68510
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program, track.playbackInfo.bank);
|
|
68193
68511
|
trackSoundWritten = true;
|
|
68194
68512
|
}
|
|
68195
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, soundAutomation.ratioPosition);
|
|
68513
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, bank, soundAutomation.ratioPosition);
|
|
68196
68514
|
if (isTrackSound) {
|
|
68197
68515
|
trackSoundWritten = true;
|
|
68198
68516
|
}
|
|
@@ -68575,8 +68893,13 @@ class GpifWriter {
|
|
|
68575
68893
|
writeMasterBarNode(parent, masterBar) {
|
|
68576
68894
|
const masterBarNode = parent.addElement('MasterBar');
|
|
68577
68895
|
const key = masterBarNode.addElement('Key');
|
|
68578
|
-
|
|
68579
|
-
|
|
68896
|
+
let keySignature = masterBar.score.tracks[0].staves[0].bars[masterBar.index].keySignature;
|
|
68897
|
+
const keySignatureType = masterBar.score.tracks[0].staves[0].bars[masterBar.index].keySignatureType;
|
|
68898
|
+
// reverse transpose
|
|
68899
|
+
const transposeIndex = ModelUtils.flooredDivision(masterBar.score.tracks[0].staves[0].displayTranspositionPitch, 12);
|
|
68900
|
+
keySignature = ModelUtils.transposeKey(keySignature, -transposeIndex);
|
|
68901
|
+
key.addElement('AccidentalCount').innerText = keySignature.toString();
|
|
68902
|
+
key.addElement('Mode').innerText = KeySignatureType[keySignatureType];
|
|
68580
68903
|
key.addElement('Sharps').innerText = 'Sharps';
|
|
68581
68904
|
masterBarNode.addElement('Time').innerText =
|
|
68582
68905
|
`${masterBar.timeSignatureNumerator}/${masterBar.timeSignatureDenominator}`;
|
|
@@ -68886,6 +69209,7 @@ GpifWriter.MidiProgramInfoLookup = new Map([
|
|
|
68886
69209
|
[127, new GpifMidiProgramInfo(GpifIconIds.Fx, 'Timpani')]
|
|
68887
69210
|
]);
|
|
68888
69211
|
GpifWriter.DrumKitProgramInfo = new GpifMidiProgramInfo(GpifIconIds.PercussionKit, 'Drums', 'drumKit');
|
|
69212
|
+
GpifWriter.defaultSteps = ['C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B'];
|
|
68889
69213
|
|
|
68890
69214
|
/**
|
|
68891
69215
|
* CRC-32 with reversed data and unreversed output
|
|
@@ -70764,6 +71088,7 @@ const _barrel$2 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty(
|
|
|
70764
71088
|
SustainPedalMarker,
|
|
70765
71089
|
get SustainPedalMarkerType () { return SustainPedalMarkerType; },
|
|
70766
71090
|
SyncPointData,
|
|
71091
|
+
get TechniqueSymbolPlacement () { return TechniqueSymbolPlacement; },
|
|
70767
71092
|
Track,
|
|
70768
71093
|
get TrackNameMode () { return TrackNameMode; },
|
|
70769
71094
|
get TrackNameOrientation () { return TrackNameOrientation; },
|