@coderline/alphatab 1.8.0 → 1.8.1
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 +618 -355
- package/dist/alphaTab.d.ts +131 -4
- package/dist/alphaTab.js +618 -355
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +1 -1
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.8.
|
|
2
|
+
* alphaTab v1.8.1 (, build 30)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2026, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -209,9 +209,9 @@
|
|
|
209
209
|
* @internal
|
|
210
210
|
*/
|
|
211
211
|
class VersionInfo {
|
|
212
|
-
static version = '1.8.
|
|
213
|
-
static date = '2026-
|
|
214
|
-
static commit = '
|
|
212
|
+
static version = '1.8.1';
|
|
213
|
+
static date = '2026-02-01T19:53:46.853Z';
|
|
214
|
+
static commit = '8a2102fe7ee7dcf4b50c3a4198fbb8c0d5c0fda3';
|
|
215
215
|
static print(print) {
|
|
216
216
|
print(`alphaTab ${VersionInfo.version}`);
|
|
217
217
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -4525,135 +4525,6 @@
|
|
|
4525
4525
|
return ModelUtils._keyTransposeTable[transpose][keySignature + 7];
|
|
4526
4526
|
}
|
|
4527
4527
|
}
|
|
4528
|
-
/**
|
|
4529
|
-
* a lookup list containing an info whether the notes within an octave
|
|
4530
|
-
* need an accidental rendered. the accidental symbol is determined based on the type of key signature.
|
|
4531
|
-
*/
|
|
4532
|
-
static _keySignatureLookup = [
|
|
4533
|
-
// Flats (where the value is true, a flat accidental is required for the notes)
|
|
4534
|
-
[true, true, true, true, true, true, true, true, true, true, true, true],
|
|
4535
|
-
[true, true, true, true, true, false, true, true, true, true, true, true],
|
|
4536
|
-
[false, true, true, true, true, false, true, true, true, true, true, true],
|
|
4537
|
-
[false, true, true, true, true, false, false, false, true, true, true, true],
|
|
4538
|
-
[false, false, false, true, true, false, false, false, true, true, true, true],
|
|
4539
|
-
[false, false, false, true, true, false, false, false, false, false, true, true],
|
|
4540
|
-
[false, false, false, false, false, false, false, false, false, false, true, true],
|
|
4541
|
-
// natural
|
|
4542
|
-
[false, false, false, false, false, false, false, false, false, false, false, false],
|
|
4543
|
-
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
4544
|
-
[false, false, false, false, false, true, true, false, false, false, false, false],
|
|
4545
|
-
[true, true, false, false, false, true, true, false, false, false, false, false],
|
|
4546
|
-
[true, true, false, false, false, true, true, true, true, false, false, false],
|
|
4547
|
-
[true, true, true, true, false, true, true, true, true, false, false, false],
|
|
4548
|
-
[true, true, true, true, false, true, true, true, true, true, true, false],
|
|
4549
|
-
[true, true, true, true, true, true, true, true, true, true, true, false],
|
|
4550
|
-
[true, true, true, true, true, true, true, true, true, true, true, true]
|
|
4551
|
-
];
|
|
4552
|
-
/**
|
|
4553
|
-
* Contains the list of notes within an octave have accidentals set.
|
|
4554
|
-
* @internal
|
|
4555
|
-
*/
|
|
4556
|
-
static accidentalNotes = [
|
|
4557
|
-
false,
|
|
4558
|
-
true,
|
|
4559
|
-
false,
|
|
4560
|
-
true,
|
|
4561
|
-
false,
|
|
4562
|
-
false,
|
|
4563
|
-
true,
|
|
4564
|
-
false,
|
|
4565
|
-
true,
|
|
4566
|
-
false,
|
|
4567
|
-
true,
|
|
4568
|
-
false
|
|
4569
|
-
];
|
|
4570
|
-
/**
|
|
4571
|
-
* @internal
|
|
4572
|
-
*/
|
|
4573
|
-
static computeAccidental(keySignature, accidentalMode, noteValue, quarterBend, currentAccidental = null) {
|
|
4574
|
-
const ks = keySignature;
|
|
4575
|
-
const ksi = ks + 7;
|
|
4576
|
-
const index = noteValue % 12;
|
|
4577
|
-
const accidentalForKeySignature = ksi < 7 ? AccidentalType.Flat : AccidentalType.Sharp;
|
|
4578
|
-
const hasKeySignatureAccidentalSetForNote = ModelUtils._keySignatureLookup[ksi][index];
|
|
4579
|
-
const hasNoteAccidentalWithinOctave = ModelUtils.accidentalNotes[index];
|
|
4580
|
-
// the general logic is like this:
|
|
4581
|
-
// - we check if the key signature has an accidental defined
|
|
4582
|
-
// - we calculate which accidental a note needs according to its index in the octave
|
|
4583
|
-
// - if the accidental is already placed at this line, nothing needs to be done, otherwise we place it
|
|
4584
|
-
// - if there should not be an accidental, but there is one in the key signature, we clear it.
|
|
4585
|
-
// the exceptions are:
|
|
4586
|
-
// - for quarter bends we just place the corresponding accidental
|
|
4587
|
-
// - the accidental mode can enforce the accidentals for the note
|
|
4588
|
-
let accidentalToSet = AccidentalType.None;
|
|
4589
|
-
if (quarterBend) {
|
|
4590
|
-
accidentalToSet = hasNoteAccidentalWithinOctave ? accidentalForKeySignature : AccidentalType.Natural;
|
|
4591
|
-
switch (accidentalToSet) {
|
|
4592
|
-
case AccidentalType.Natural:
|
|
4593
|
-
accidentalToSet = AccidentalType.NaturalQuarterNoteUp;
|
|
4594
|
-
break;
|
|
4595
|
-
case AccidentalType.Sharp:
|
|
4596
|
-
accidentalToSet = AccidentalType.SharpQuarterNoteUp;
|
|
4597
|
-
break;
|
|
4598
|
-
case AccidentalType.Flat:
|
|
4599
|
-
accidentalToSet = AccidentalType.FlatQuarterNoteUp;
|
|
4600
|
-
break;
|
|
4601
|
-
}
|
|
4602
|
-
}
|
|
4603
|
-
else {
|
|
4604
|
-
// define which accidental should be shown ignoring what might be set on the KS already
|
|
4605
|
-
switch (accidentalMode) {
|
|
4606
|
-
case NoteAccidentalMode.ForceSharp:
|
|
4607
|
-
accidentalToSet = AccidentalType.Sharp;
|
|
4608
|
-
break;
|
|
4609
|
-
case NoteAccidentalMode.ForceDoubleSharp:
|
|
4610
|
-
accidentalToSet = AccidentalType.DoubleSharp;
|
|
4611
|
-
break;
|
|
4612
|
-
case NoteAccidentalMode.ForceFlat:
|
|
4613
|
-
accidentalToSet = AccidentalType.Flat;
|
|
4614
|
-
break;
|
|
4615
|
-
case NoteAccidentalMode.ForceDoubleFlat:
|
|
4616
|
-
accidentalToSet = AccidentalType.DoubleFlat;
|
|
4617
|
-
break;
|
|
4618
|
-
default:
|
|
4619
|
-
// if note has an accidental in the octave, we place a symbol
|
|
4620
|
-
// according to the Key Signature
|
|
4621
|
-
if (hasNoteAccidentalWithinOctave) {
|
|
4622
|
-
accidentalToSet = accidentalForKeySignature;
|
|
4623
|
-
}
|
|
4624
|
-
else if (hasKeySignatureAccidentalSetForNote) {
|
|
4625
|
-
// note does not get an accidental, but KS defines one -> Naturalize
|
|
4626
|
-
accidentalToSet = AccidentalType.Natural;
|
|
4627
|
-
}
|
|
4628
|
-
break;
|
|
4629
|
-
}
|
|
4630
|
-
// do we need an accidental on the note?
|
|
4631
|
-
if (accidentalToSet !== AccidentalType.None) {
|
|
4632
|
-
// if there is no accidental on the line, and the key signature has it set already, we clear it on the note
|
|
4633
|
-
if (currentAccidental != null) {
|
|
4634
|
-
if (currentAccidental === accidentalToSet) {
|
|
4635
|
-
accidentalToSet = AccidentalType.None;
|
|
4636
|
-
}
|
|
4637
|
-
}
|
|
4638
|
-
else if (hasKeySignatureAccidentalSetForNote && accidentalToSet === accidentalForKeySignature) {
|
|
4639
|
-
accidentalToSet = AccidentalType.None;
|
|
4640
|
-
}
|
|
4641
|
-
}
|
|
4642
|
-
else {
|
|
4643
|
-
// if we don't want an accidental, but there is already one applied, we place a naturalize accidental
|
|
4644
|
-
// and clear the registration
|
|
4645
|
-
if (currentAccidental !== null) {
|
|
4646
|
-
if (currentAccidental === AccidentalType.Natural) {
|
|
4647
|
-
accidentalToSet = AccidentalType.None;
|
|
4648
|
-
}
|
|
4649
|
-
else {
|
|
4650
|
-
accidentalToSet = AccidentalType.Natural;
|
|
4651
|
-
}
|
|
4652
|
-
}
|
|
4653
|
-
}
|
|
4654
|
-
}
|
|
4655
|
-
return accidentalToSet;
|
|
4656
|
-
}
|
|
4657
4528
|
/**
|
|
4658
4529
|
* @internal
|
|
4659
4530
|
*/
|
|
@@ -4692,6 +4563,239 @@
|
|
|
4692
4563
|
}
|
|
4693
4564
|
return systemIndex < systemsLayout.length ? systemsLayout[systemIndex] : defaultSystemsLayout;
|
|
4694
4565
|
}
|
|
4566
|
+
// diatonic accidentals
|
|
4567
|
+
static _degreeSemitones = [0, 2, 4, 5, 7, 9, 11];
|
|
4568
|
+
static _sharpPreferredSpellings = [
|
|
4569
|
+
{ degree: 0, accidentalOffset: 0 }, // C
|
|
4570
|
+
{ degree: 0, accidentalOffset: 1 }, // C#
|
|
4571
|
+
{ degree: 1, accidentalOffset: 0 }, // D
|
|
4572
|
+
{ degree: 1, accidentalOffset: 1 }, // D#
|
|
4573
|
+
{ degree: 2, accidentalOffset: 0 }, // E
|
|
4574
|
+
{ degree: 3, accidentalOffset: 0 }, // F
|
|
4575
|
+
{ degree: 3, accidentalOffset: 1 }, // F#
|
|
4576
|
+
{ degree: 4, accidentalOffset: 0 }, // G
|
|
4577
|
+
{ degree: 4, accidentalOffset: 1 }, // G#
|
|
4578
|
+
{ degree: 5, accidentalOffset: 0 }, // A
|
|
4579
|
+
{ degree: 5, accidentalOffset: 1 }, // A#
|
|
4580
|
+
{ degree: 6, accidentalOffset: 0 } // B
|
|
4581
|
+
];
|
|
4582
|
+
static _flatPreferredSpellings = [
|
|
4583
|
+
{ degree: 0, accidentalOffset: 0 }, // C
|
|
4584
|
+
{ degree: 1, accidentalOffset: -1 }, // Db
|
|
4585
|
+
{ degree: 1, accidentalOffset: 0 }, // D
|
|
4586
|
+
{ degree: 2, accidentalOffset: -1 }, // Eb
|
|
4587
|
+
{ degree: 2, accidentalOffset: 0 }, // E
|
|
4588
|
+
{ degree: 3, accidentalOffset: 0 }, // F
|
|
4589
|
+
{ degree: 4, accidentalOffset: -1 }, // Gb
|
|
4590
|
+
{ degree: 4, accidentalOffset: 0 }, // G
|
|
4591
|
+
{ degree: 5, accidentalOffset: -1 }, // Ab
|
|
4592
|
+
{ degree: 5, accidentalOffset: 0 }, // A
|
|
4593
|
+
{ degree: 6, accidentalOffset: -1 }, // Bb
|
|
4594
|
+
{ degree: 6, accidentalOffset: 0 } // B
|
|
4595
|
+
];
|
|
4596
|
+
// 12 chromatic pitch classes with always 3 possible spellings in the
|
|
4597
|
+
// accidental range of bb..##
|
|
4598
|
+
static _spellingCandidates = [
|
|
4599
|
+
// 0: C
|
|
4600
|
+
[
|
|
4601
|
+
{ degree: 0, accidentalOffset: 0 }, // C
|
|
4602
|
+
{ degree: 1, accidentalOffset: -2 }, // Dbb
|
|
4603
|
+
{ degree: 6, accidentalOffset: 1 } // B#
|
|
4604
|
+
],
|
|
4605
|
+
// 1: C#/Db
|
|
4606
|
+
[
|
|
4607
|
+
{ degree: 0, accidentalOffset: 1 }, // C#
|
|
4608
|
+
{ degree: 1, accidentalOffset: -1 }, // Db
|
|
4609
|
+
{ degree: 6, accidentalOffset: 2 } // B##
|
|
4610
|
+
],
|
|
4611
|
+
// 2: D
|
|
4612
|
+
[
|
|
4613
|
+
{ degree: 1, accidentalOffset: 0 }, // D
|
|
4614
|
+
{ degree: 0, accidentalOffset: 2 }, // C##
|
|
4615
|
+
{ degree: 2, accidentalOffset: -2 } // Ebb
|
|
4616
|
+
],
|
|
4617
|
+
// 3: D#/Eb
|
|
4618
|
+
[
|
|
4619
|
+
{ degree: 1, accidentalOffset: 1 }, // D#
|
|
4620
|
+
{ degree: 2, accidentalOffset: -1 }, // Eb
|
|
4621
|
+
{ degree: 3, accidentalOffset: -2 } // Fbb
|
|
4622
|
+
],
|
|
4623
|
+
// 4: E
|
|
4624
|
+
[
|
|
4625
|
+
{ degree: 2, accidentalOffset: 0 }, // E
|
|
4626
|
+
{ degree: 1, accidentalOffset: 2 }, // D##
|
|
4627
|
+
{ degree: 3, accidentalOffset: -1 } // Fb
|
|
4628
|
+
],
|
|
4629
|
+
// 5: F
|
|
4630
|
+
[
|
|
4631
|
+
{ degree: 3, accidentalOffset: 0 }, // F
|
|
4632
|
+
{ degree: 2, accidentalOffset: 1 }, // E#
|
|
4633
|
+
{ degree: 4, accidentalOffset: -2 } // Gbb
|
|
4634
|
+
],
|
|
4635
|
+
// 6: F#/Gb
|
|
4636
|
+
[
|
|
4637
|
+
{ degree: 3, accidentalOffset: 1 }, // F#
|
|
4638
|
+
{ degree: 4, accidentalOffset: -1 }, // Gb
|
|
4639
|
+
{ degree: 2, accidentalOffset: 2 } // E##
|
|
4640
|
+
],
|
|
4641
|
+
// 7: G
|
|
4642
|
+
[
|
|
4643
|
+
{ degree: 4, accidentalOffset: 0 }, // G
|
|
4644
|
+
{ degree: 3, accidentalOffset: 2 }, // F##
|
|
4645
|
+
{ degree: 5, accidentalOffset: -2 } // Abb
|
|
4646
|
+
],
|
|
4647
|
+
// 8: G#/Ab
|
|
4648
|
+
[
|
|
4649
|
+
{ degree: 4, accidentalOffset: 1 }, // G#
|
|
4650
|
+
{ degree: 5, accidentalOffset: -1 } // Ab
|
|
4651
|
+
],
|
|
4652
|
+
// 9: A
|
|
4653
|
+
[
|
|
4654
|
+
{ degree: 5, accidentalOffset: 0 }, // A
|
|
4655
|
+
{ degree: 4, accidentalOffset: 2 }, // G##
|
|
4656
|
+
{ degree: 6, accidentalOffset: -2 } // Bbb
|
|
4657
|
+
],
|
|
4658
|
+
// 10: A#/Bb
|
|
4659
|
+
[
|
|
4660
|
+
{ degree: 5, accidentalOffset: 1 }, // A#
|
|
4661
|
+
{ degree: 6, accidentalOffset: -1 }, // Bb
|
|
4662
|
+
{ degree: 0, accidentalOffset: -2 } // Cbb
|
|
4663
|
+
],
|
|
4664
|
+
// 11: B
|
|
4665
|
+
[
|
|
4666
|
+
{ degree: 6, accidentalOffset: 0 }, // B
|
|
4667
|
+
{ degree: 5, accidentalOffset: 2 }, // A##
|
|
4668
|
+
{ degree: 0, accidentalOffset: -1 } // Cb
|
|
4669
|
+
]
|
|
4670
|
+
];
|
|
4671
|
+
static _sharpKeySignatureOrder = [3, 0, 4, 1, 5, 2, 6]; // F C G D A E B
|
|
4672
|
+
static _flatKeySignatureOrder = [6, 2, 5, 1, 4, 0, 3]; // B E A D G C F
|
|
4673
|
+
static _keySignatureAccidentalByDegree = ModelUtils._buildKeySignatureAccidentalByDegree();
|
|
4674
|
+
static _accidentalOffsetToType = new Map([
|
|
4675
|
+
[-2, AccidentalType.DoubleFlat],
|
|
4676
|
+
[-1, AccidentalType.Flat],
|
|
4677
|
+
[0, AccidentalType.Natural],
|
|
4678
|
+
[1, AccidentalType.Sharp],
|
|
4679
|
+
[2, AccidentalType.DoubleSharp]
|
|
4680
|
+
]);
|
|
4681
|
+
static _forcedAccidentalOffsetByMode = new Map([
|
|
4682
|
+
[NoteAccidentalMode.ForceSharp, 1],
|
|
4683
|
+
[NoteAccidentalMode.ForceDoubleSharp, 2],
|
|
4684
|
+
[NoteAccidentalMode.ForceFlat, -1],
|
|
4685
|
+
[NoteAccidentalMode.ForceDoubleFlat, -2],
|
|
4686
|
+
[NoteAccidentalMode.ForceNatural, 0],
|
|
4687
|
+
[NoteAccidentalMode.ForceNone, 0],
|
|
4688
|
+
[NoteAccidentalMode.Default, Number.NaN]
|
|
4689
|
+
]);
|
|
4690
|
+
static _buildKeySignatureAccidentalByDegree() {
|
|
4691
|
+
const lookup = [];
|
|
4692
|
+
for (let ks = -7; ks <= 7; ks++) {
|
|
4693
|
+
const row = [0, 0, 0, 0, 0, 0, 0];
|
|
4694
|
+
if (ks > 0) {
|
|
4695
|
+
for (let i = 0; i < ks; i++) {
|
|
4696
|
+
row[ModelUtils._sharpKeySignatureOrder[i]] = 1;
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4699
|
+
else if (ks < 0) {
|
|
4700
|
+
for (let i = 0; i < -ks; i++) {
|
|
4701
|
+
row[ModelUtils._flatKeySignatureOrder[i]] = -1;
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
lookup.push(row);
|
|
4705
|
+
}
|
|
4706
|
+
return lookup;
|
|
4707
|
+
}
|
|
4708
|
+
static getKeySignatureAccidentalOffset(keySignature, degree) {
|
|
4709
|
+
return ModelUtils._keySignatureAccidentalByDegree[keySignature + 7][degree];
|
|
4710
|
+
}
|
|
4711
|
+
static resolveSpelling(keySignature, noteValue, accidentalMode) {
|
|
4712
|
+
const chroma = ModelUtils.flooredDivision(noteValue, 12);
|
|
4713
|
+
const preferred = ModelUtils._getPreferredSpellingForKeySignature(keySignature, chroma);
|
|
4714
|
+
const desiredOffset = ModelUtils._forcedAccidentalOffsetByMode.has(accidentalMode)
|
|
4715
|
+
? ModelUtils._forcedAccidentalOffsetByMode.get(accidentalMode)
|
|
4716
|
+
: Number.NaN;
|
|
4717
|
+
let spelling = preferred;
|
|
4718
|
+
if (!Number.isNaN(desiredOffset)) {
|
|
4719
|
+
const candidates = ModelUtils._spellingCandidates[chroma];
|
|
4720
|
+
const exact = candidates.find(c => c.accidentalOffset === desiredOffset);
|
|
4721
|
+
if (exact) {
|
|
4722
|
+
spelling = exact;
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
const baseSemitone = ModelUtils._degreeSemitones[spelling.degree] + spelling.accidentalOffset;
|
|
4726
|
+
const octave = Math.floor((noteValue - baseSemitone) / 12) - 1;
|
|
4727
|
+
return {
|
|
4728
|
+
degree: spelling.degree,
|
|
4729
|
+
accidentalOffset: spelling.accidentalOffset,
|
|
4730
|
+
chroma,
|
|
4731
|
+
octave
|
|
4732
|
+
};
|
|
4733
|
+
}
|
|
4734
|
+
static computeAccidental(keySignature, accidentalMode, noteValue, quarterBend, currentAccidentalOffset = null) {
|
|
4735
|
+
const spelling = ModelUtils.resolveSpelling(keySignature, noteValue, accidentalMode);
|
|
4736
|
+
return ModelUtils.computeAccidentalForSpelling(keySignature, accidentalMode, spelling, quarterBend, currentAccidentalOffset);
|
|
4737
|
+
}
|
|
4738
|
+
static computeAccidentalForSpelling(keySignature, accidentalMode, spelling, quarterBend, currentAccidentalOffset = null) {
|
|
4739
|
+
if (accidentalMode === NoteAccidentalMode.ForceNone) {
|
|
4740
|
+
return AccidentalType.None;
|
|
4741
|
+
}
|
|
4742
|
+
if (quarterBend) {
|
|
4743
|
+
if (spelling.accidentalOffset > 0) {
|
|
4744
|
+
return AccidentalType.SharpQuarterNoteUp;
|
|
4745
|
+
}
|
|
4746
|
+
if (spelling.accidentalOffset < 0) {
|
|
4747
|
+
return AccidentalType.FlatQuarterNoteUp;
|
|
4748
|
+
}
|
|
4749
|
+
return AccidentalType.NaturalQuarterNoteUp;
|
|
4750
|
+
}
|
|
4751
|
+
const desiredOffset = spelling.accidentalOffset;
|
|
4752
|
+
const ksOffset = ModelUtils.getKeySignatureAccidentalOffset(keySignature, spelling.degree);
|
|
4753
|
+
// already active in bar -> no accidental needed
|
|
4754
|
+
if (currentAccidentalOffset === desiredOffset) {
|
|
4755
|
+
return AccidentalType.None;
|
|
4756
|
+
}
|
|
4757
|
+
// key signature already defines the accidental and no explicit accidental is active
|
|
4758
|
+
if (currentAccidentalOffset == null && desiredOffset === ksOffset) {
|
|
4759
|
+
return AccidentalType.None;
|
|
4760
|
+
}
|
|
4761
|
+
return ModelUtils.accidentalOffsetToType(desiredOffset);
|
|
4762
|
+
}
|
|
4763
|
+
static accidentalOffsetToType(offset) {
|
|
4764
|
+
return ModelUtils._accidentalOffsetToType.has(offset)
|
|
4765
|
+
? ModelUtils._accidentalOffsetToType.get(offset)
|
|
4766
|
+
: AccidentalType.None;
|
|
4767
|
+
}
|
|
4768
|
+
static _getPreferredSpellingForKeySignature(keySignature, chroma) {
|
|
4769
|
+
const candidates = ModelUtils._spellingCandidates[chroma];
|
|
4770
|
+
const ksMatch = candidates.find(c => ModelUtils.getKeySignatureAccidentalOffset(keySignature, c.degree) === c.accidentalOffset);
|
|
4771
|
+
if (ksMatch) {
|
|
4772
|
+
return ksMatch;
|
|
4773
|
+
}
|
|
4774
|
+
const preferFlat = ModelUtils.keySignatureIsFlat(keySignature);
|
|
4775
|
+
return preferFlat ? ModelUtils._flatPreferredSpellings[chroma] : ModelUtils._sharpPreferredSpellings[chroma];
|
|
4776
|
+
}
|
|
4777
|
+
static _majorKeySignatureTonicDegrees = [
|
|
4778
|
+
// Flats: Cb, Gb, Db, Ab, Eb, Bb, F
|
|
4779
|
+
0, 4, 1, 5, 2, 6, 3,
|
|
4780
|
+
// Natural: C
|
|
4781
|
+
0,
|
|
4782
|
+
// Sharps: G, D, A, E, B, F#, C#
|
|
4783
|
+
4, 1, 5, 2, 6, 3, 0
|
|
4784
|
+
];
|
|
4785
|
+
static _minorKeySignatureTonicDegrees = [
|
|
4786
|
+
// Flats: Ab, Eb, Bb, F, C, G, D
|
|
4787
|
+
5, 2, 6, 3, 0, 4, 1,
|
|
4788
|
+
// Natural: A
|
|
4789
|
+
5,
|
|
4790
|
+
// Sharps: E, B, F#, C#, G#, D#, A#
|
|
4791
|
+
2, 6, 3, 0, 4, 1, 5
|
|
4792
|
+
];
|
|
4793
|
+
static getKeySignatureTonicDegree(keySignature, keySignatureType) {
|
|
4794
|
+
const ksi = keySignature + 7;
|
|
4795
|
+
return keySignatureType === KeySignatureType.Minor
|
|
4796
|
+
? ModelUtils._minorKeySignatureTonicDegrees[ksi]
|
|
4797
|
+
: ModelUtils._majorKeySignatureTonicDegrees[ksi];
|
|
4798
|
+
}
|
|
4695
4799
|
}
|
|
4696
4800
|
|
|
4697
4801
|
/**
|
|
@@ -5402,7 +5506,8 @@
|
|
|
5402
5506
|
}
|
|
5403
5507
|
}
|
|
5404
5508
|
}
|
|
5405
|
-
|
|
5509
|
+
// unknown combination, should not happen, fallback to some default value (Snare hit)
|
|
5510
|
+
return 'Snare (hit)';
|
|
5406
5511
|
}
|
|
5407
5512
|
static getArticulation(n) {
|
|
5408
5513
|
const articulationIndex = n.percussionArticulation;
|
|
@@ -15578,7 +15683,11 @@
|
|
|
15578
15683
|
const slurId = `s${note.slurOrigin.id}`;
|
|
15579
15684
|
Atnf.prop(properties, 'slur', Atnf.identValue(slurId));
|
|
15580
15685
|
}
|
|
15581
|
-
|
|
15686
|
+
// NOTE: it would be better to check via accidentalhelper what accidentals we really need to force
|
|
15687
|
+
const skipAccidental = note.accidentalMode === NoteAccidentalMode.Default ||
|
|
15688
|
+
(note.beat.voice.bar.keySignature === KeySignature.C &&
|
|
15689
|
+
note.accidentalMode === NoteAccidentalMode.ForceNatural);
|
|
15690
|
+
if (!skipAccidental) {
|
|
15582
15691
|
Atnf.prop(properties, 'acc', Atnf.identValue(ModelUtils.reverseAccidentalModeMapping.get(note.accidentalMode)));
|
|
15583
15692
|
}
|
|
15584
15693
|
switch (note.ornament) {
|
|
@@ -19543,6 +19652,24 @@
|
|
|
19543
19652
|
*/
|
|
19544
19653
|
class Gp3To5Importer extends ScoreImporter {
|
|
19545
19654
|
static _versionString = 'FICHIER GUITAR PRO ';
|
|
19655
|
+
// NOTE: General Midi only defines percussion instruments from 35-81
|
|
19656
|
+
// Guitar Pro 5 allowed GS extensions (27-34 and 82-87)
|
|
19657
|
+
// GP7-8 do not have all these definitions anymore, this lookup ensures some fallback
|
|
19658
|
+
// (even if they are not correct)
|
|
19659
|
+
// we can support this properly in future when we allow custom alphaTex articulation definitions
|
|
19660
|
+
// then we don't need to rely on GP specifics anymore but handle things on export/import
|
|
19661
|
+
static _gp5PercussionInstrumentMap = new Map([
|
|
19662
|
+
// High Q -> GS "High Q / Filter Snap"
|
|
19663
|
+
[27, 42],
|
|
19664
|
+
// Slap
|
|
19665
|
+
[28, 60],
|
|
19666
|
+
// Scratch Push
|
|
19667
|
+
[29, 29],
|
|
19668
|
+
// Scratch Pull
|
|
19669
|
+
[30, 30],
|
|
19670
|
+
// Square Click
|
|
19671
|
+
[32, 31]
|
|
19672
|
+
]);
|
|
19546
19673
|
_versionNumber = 0;
|
|
19547
19674
|
_score;
|
|
19548
19675
|
_globalTripletFeel = TripletFeel.NoTripletFeel;
|
|
@@ -19889,9 +20016,9 @@
|
|
|
19889
20016
|
}
|
|
19890
20017
|
}
|
|
19891
20018
|
/**
|
|
19892
|
-
* Guitar Pro 3-6 changes to a bass clef if any string tuning is below
|
|
20019
|
+
* Guitar Pro 3-6 changes to a bass clef if any string tuning is below B1
|
|
19893
20020
|
*/
|
|
19894
|
-
static _bassClefTuningThreshold = ModelUtils.parseTuning('
|
|
20021
|
+
static _bassClefTuningThreshold = ModelUtils.parseTuning('B1').realValue;
|
|
19895
20022
|
readTrack() {
|
|
19896
20023
|
const newTrack = new Track();
|
|
19897
20024
|
newTrack.ensureStaveCount(1);
|
|
@@ -20612,7 +20739,9 @@
|
|
|
20612
20739
|
this.readNoteEffects(track, voice, beat, newNote);
|
|
20613
20740
|
}
|
|
20614
20741
|
if (bar.staff.isPercussion) {
|
|
20615
|
-
newNote.percussionArticulation = newNote.fret
|
|
20742
|
+
newNote.percussionArticulation = Gp3To5Importer._gp5PercussionInstrumentMap.has(newNote.fret)
|
|
20743
|
+
? Gp3To5Importer._gp5PercussionInstrumentMap.get(newNote.fret)
|
|
20744
|
+
: newNote.fret;
|
|
20616
20745
|
newNote.string = -1;
|
|
20617
20746
|
newNote.fret = -1;
|
|
20618
20747
|
}
|
|
@@ -23864,6 +23993,9 @@
|
|
|
23864
23993
|
switch (c.localName) {
|
|
23865
23994
|
case 'Accidental':
|
|
23866
23995
|
switch (c.innerText) {
|
|
23996
|
+
case '':
|
|
23997
|
+
note.accidentalMode = NoteAccidentalMode.ForceNatural;
|
|
23998
|
+
break;
|
|
23867
23999
|
case 'x':
|
|
23868
24000
|
note.accidentalMode = NoteAccidentalMode.ForceDoubleSharp;
|
|
23869
24001
|
break;
|
|
@@ -24902,13 +25034,9 @@
|
|
|
24902
25034
|
*/
|
|
24903
25035
|
static _octaveSteps = [38, 32, 30, 26, 38];
|
|
24904
25036
|
/**
|
|
24905
|
-
*
|
|
24906
|
-
*/
|
|
24907
|
-
static sharpNoteSteps = [0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6];
|
|
24908
|
-
/**
|
|
24909
|
-
* The step offsets of the notes within an octave in case of for flat keysignatures
|
|
25037
|
+
* Diatonic step offsets within an octave.
|
|
24910
25038
|
*/
|
|
24911
|
-
static
|
|
25039
|
+
static _diatonicSteps = [0, 1, 2, 3, 4, 5, 6];
|
|
24912
25040
|
_registeredAccidentals = new Map();
|
|
24913
25041
|
_appliedScoreSteps = new Map();
|
|
24914
25042
|
_appliedScoreStepsByValue = new Map();
|
|
@@ -24940,23 +25068,7 @@
|
|
|
24940
25068
|
return PercussionMapper.getArticulation(note)?.staffLine ?? 0;
|
|
24941
25069
|
}
|
|
24942
25070
|
static getNoteValue(note) {
|
|
24943
|
-
|
|
24944
|
-
// adjust note height according to accidentals enforced
|
|
24945
|
-
switch (note.accidentalMode) {
|
|
24946
|
-
case NoteAccidentalMode.ForceDoubleFlat:
|
|
24947
|
-
noteValue += 2;
|
|
24948
|
-
break;
|
|
24949
|
-
case NoteAccidentalMode.ForceDoubleSharp:
|
|
24950
|
-
noteValue -= 2;
|
|
24951
|
-
break;
|
|
24952
|
-
case NoteAccidentalMode.ForceFlat:
|
|
24953
|
-
noteValue += 1;
|
|
24954
|
-
break;
|
|
24955
|
-
case NoteAccidentalMode.ForceSharp:
|
|
24956
|
-
noteValue -= 1;
|
|
24957
|
-
break;
|
|
24958
|
-
}
|
|
24959
|
-
return noteValue;
|
|
25071
|
+
return note.displayValue;
|
|
24960
25072
|
}
|
|
24961
25073
|
/**
|
|
24962
25074
|
* Calculates the accidental for the given note and assignes the value to it.
|
|
@@ -24988,7 +25100,8 @@
|
|
|
24988
25100
|
steps = AccidentalHelper.getPercussionSteps(note);
|
|
24989
25101
|
}
|
|
24990
25102
|
else {
|
|
24991
|
-
|
|
25103
|
+
const spelling = ModelUtils.resolveSpelling(bar.keySignature, noteValue, note.accidentalMode);
|
|
25104
|
+
steps = AccidentalHelper.calculateNoteSteps(bar.clef, spelling);
|
|
24992
25105
|
}
|
|
24993
25106
|
return steps;
|
|
24994
25107
|
}
|
|
@@ -25001,11 +25114,12 @@
|
|
|
25001
25114
|
}
|
|
25002
25115
|
else {
|
|
25003
25116
|
const accidentalMode = note ? note.accidentalMode : NoteAccidentalMode.Default;
|
|
25004
|
-
|
|
25005
|
-
|
|
25117
|
+
const spelling = ModelUtils.resolveSpelling(this._bar.keySignature, noteValue, accidentalMode);
|
|
25118
|
+
steps = AccidentalHelper.calculateNoteSteps(this._bar.clef, spelling);
|
|
25119
|
+
const currentAccidentalOffset = this._registeredAccidentals.has(steps)
|
|
25006
25120
|
? this._registeredAccidentals.get(steps)
|
|
25007
25121
|
: null;
|
|
25008
|
-
accidentalToSet = ModelUtils.
|
|
25122
|
+
accidentalToSet = ModelUtils.computeAccidentalForSpelling(this._bar.keySignature, accidentalMode, spelling, quarterBend, currentAccidentalOffset);
|
|
25009
25123
|
let skipAccidental = false;
|
|
25010
25124
|
switch (accidentalToSet) {
|
|
25011
25125
|
case AccidentalType.NaturalQuarterNoteUp:
|
|
@@ -25030,14 +25144,12 @@
|
|
|
25030
25144
|
if (skipAccidental) {
|
|
25031
25145
|
accidentalToSet = AccidentalType.None;
|
|
25032
25146
|
}
|
|
25033
|
-
else {
|
|
25034
|
-
// do we need an accidental on the note?
|
|
25035
|
-
if (accidentalToSet !== AccidentalType.None) {
|
|
25036
|
-
this._registeredAccidentals.set(steps, accidentalToSet);
|
|
25037
|
-
}
|
|
25038
|
-
}
|
|
25039
25147
|
break;
|
|
25040
25148
|
}
|
|
25149
|
+
const shouldRegister = !quarterBend && accidentalToSet !== AccidentalType.None;
|
|
25150
|
+
if (shouldRegister) {
|
|
25151
|
+
this._registeredAccidentals.set(steps, spelling.accidentalOffset);
|
|
25152
|
+
}
|
|
25041
25153
|
}
|
|
25042
25154
|
if (note) {
|
|
25043
25155
|
this._appliedScoreSteps.set(note.id, steps);
|
|
@@ -25089,21 +25201,14 @@
|
|
|
25089
25201
|
getMinStepsNote(b) {
|
|
25090
25202
|
return this._beatSteps.has(b.id) ? this._beatSteps.get(b.id).minStepsNote : null;
|
|
25091
25203
|
}
|
|
25092
|
-
static calculateNoteSteps(
|
|
25093
|
-
const value = noteValue;
|
|
25094
|
-
const ks = keySignature;
|
|
25204
|
+
static calculateNoteSteps(clef, spelling) {
|
|
25095
25205
|
const clefValue = clef;
|
|
25096
|
-
const index = value % 12;
|
|
25097
|
-
const octave = ((value / 12) | 0) - 1;
|
|
25098
25206
|
// Initial Position
|
|
25099
25207
|
let steps = AccidentalHelper._octaveSteps[clefValue];
|
|
25100
25208
|
// Move to Octave
|
|
25101
|
-
steps -= octave * AccidentalHelper._stepsPerOctave;
|
|
25102
|
-
//
|
|
25103
|
-
|
|
25104
|
-
? AccidentalHelper.sharpNoteSteps
|
|
25105
|
-
: AccidentalHelper.flatNoteSteps;
|
|
25106
|
-
steps -= stepList[index];
|
|
25209
|
+
steps -= spelling.octave * AccidentalHelper._stepsPerOctave;
|
|
25210
|
+
// Move within octave
|
|
25211
|
+
steps -= AccidentalHelper._diatonicSteps[spelling.degree];
|
|
25107
25212
|
return steps;
|
|
25108
25213
|
}
|
|
25109
25214
|
getNoteSteps(n) {
|
|
@@ -25208,7 +25313,8 @@
|
|
|
25208
25313
|
musicXmlStaffSteps = 4; // middle of bar
|
|
25209
25314
|
}
|
|
25210
25315
|
else {
|
|
25211
|
-
|
|
25316
|
+
const spelling = ModelUtils.resolveSpelling(bar.keySignature, noteValue, NoteAccidentalMode.Default);
|
|
25317
|
+
musicXmlStaffSteps = AccidentalHelper.calculateNoteSteps(bar.clef, spelling);
|
|
25212
25318
|
}
|
|
25213
25319
|
// to translate this into the "staffLine" semantics we need to subtract additionally the steps "missing" from the absent lines
|
|
25214
25320
|
const actualSteps = note.beat.voice.bar.staff.standardNotationLineCount * 2 - 1;
|
|
@@ -47062,9 +47168,14 @@
|
|
|
47062
47168
|
*/
|
|
47063
47169
|
MidiTickLookupFindBeatResultCursorMode[MidiTickLookupFindBeatResultCursorMode["ToNextBext"] = 1] = "ToNextBext";
|
|
47064
47170
|
/**
|
|
47065
|
-
*
|
|
47171
|
+
* @deprecated replaced by {@link ToEndOfBeat}
|
|
47066
47172
|
*/
|
|
47067
47173
|
MidiTickLookupFindBeatResultCursorMode[MidiTickLookupFindBeatResultCursorMode["ToEndOfBar"] = 2] = "ToEndOfBar";
|
|
47174
|
+
/**
|
|
47175
|
+
* The cursor should animate to the end of the **beat** (typically on repeats and jumps)
|
|
47176
|
+
* (this is named end of bar historically)
|
|
47177
|
+
*/
|
|
47178
|
+
MidiTickLookupFindBeatResultCursorMode[MidiTickLookupFindBeatResultCursorMode["ToEndOfBeat"] = 3] = "ToEndOfBeat";
|
|
47068
47179
|
})(MidiTickLookupFindBeatResultCursorMode || (MidiTickLookupFindBeatResultCursorMode = {}));
|
|
47069
47180
|
/**
|
|
47070
47181
|
* Represents the results of searching the currently played beat.
|
|
@@ -47212,6 +47323,11 @@
|
|
|
47212
47323
|
* This info allows building the correct "next" beat and duration.
|
|
47213
47324
|
*/
|
|
47214
47325
|
multiBarRestInfo = null;
|
|
47326
|
+
/**
|
|
47327
|
+
* An optional playback range to consider when performing lookups.
|
|
47328
|
+
* This will mainly influence the used {@link MidiTickLookupFindBeatResultCursorMode}
|
|
47329
|
+
*/
|
|
47330
|
+
playbackRange = null;
|
|
47215
47331
|
/**
|
|
47216
47332
|
* Finds the currently played beat given a list of tracks and the current time.
|
|
47217
47333
|
* @param trackLookup The tracks indices in which to search the played beat for.
|
|
@@ -47237,6 +47353,13 @@
|
|
|
47237
47353
|
if (!result) {
|
|
47238
47354
|
result = this._findBeatSlow(checker, currentBeatHint, tick, false);
|
|
47239
47355
|
}
|
|
47356
|
+
if (result) {
|
|
47357
|
+
const playbackRange = this.playbackRange;
|
|
47358
|
+
const isBeyondRangeEnd = playbackRange !== null && result.start >= playbackRange.endTick;
|
|
47359
|
+
if (isBeyondRangeEnd) {
|
|
47360
|
+
return null;
|
|
47361
|
+
}
|
|
47362
|
+
}
|
|
47240
47363
|
return result;
|
|
47241
47364
|
}
|
|
47242
47365
|
_findBeatFast(checker, currentBeatHint, tick) {
|
|
@@ -47276,20 +47399,24 @@
|
|
|
47276
47399
|
if (current.nextBeat) {
|
|
47277
47400
|
current.tickDuration = current.nextBeat.start - current.start;
|
|
47278
47401
|
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToNextBext;
|
|
47402
|
+
// jump back
|
|
47279
47403
|
if (current.nextBeat.masterBar.masterBar.index !== endMasterBar.masterBar.index + 1 &&
|
|
47280
47404
|
(current.nextBeat.masterBar.masterBar.index !== endMasterBar.masterBar.index ||
|
|
47281
47405
|
current.nextBeat.beat.playbackStart <= current.beat.playbackStart)) {
|
|
47282
|
-
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.
|
|
47406
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47407
|
+
}
|
|
47408
|
+
else if (this.playbackRange !== null && this.playbackRange.endTick <= current.nextBeat.start) {
|
|
47409
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47283
47410
|
}
|
|
47284
47411
|
}
|
|
47285
47412
|
else {
|
|
47286
47413
|
current.tickDuration = endMasterBar.nextMasterBar.end - current.start;
|
|
47287
|
-
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.
|
|
47414
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47288
47415
|
}
|
|
47289
47416
|
}
|
|
47290
47417
|
else {
|
|
47291
47418
|
current.tickDuration = endMasterBar.end - current.start;
|
|
47292
|
-
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.
|
|
47419
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47293
47420
|
}
|
|
47294
47421
|
}
|
|
47295
47422
|
else {
|
|
@@ -47297,7 +47424,7 @@
|
|
|
47297
47424
|
// this is wierd, we have a masterbar without known tick?
|
|
47298
47425
|
// make a best guess with the number of bars
|
|
47299
47426
|
current.tickDuration = (current.masterBar.end - current.masterBar.start) * (group.length + 1);
|
|
47300
|
-
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.
|
|
47427
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47301
47428
|
}
|
|
47302
47429
|
current.calculateDuration();
|
|
47303
47430
|
}
|
|
@@ -47323,16 +47450,20 @@
|
|
|
47323
47450
|
}
|
|
47324
47451
|
else {
|
|
47325
47452
|
current.tickDuration = current.masterBar.end - current.start;
|
|
47326
|
-
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.
|
|
47453
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47327
47454
|
current.calculateDuration();
|
|
47328
47455
|
}
|
|
47329
|
-
|
|
47330
|
-
|
|
47331
|
-
|
|
47332
|
-
current.nextBeat.masterBar.masterBar.index !== current.masterBar.masterBar.index + 1 &&
|
|
47333
|
-
|
|
47334
|
-
|
|
47335
|
-
|
|
47456
|
+
if (current.nextBeat) {
|
|
47457
|
+
// if the next beat is not directly the next master bar (e.g. jumping back or forth)
|
|
47458
|
+
// we report no next beat and animate to the end
|
|
47459
|
+
if (current.nextBeat.masterBar.masterBar.index !== current.masterBar.masterBar.index + 1 &&
|
|
47460
|
+
(current.nextBeat.masterBar.masterBar.index !== current.masterBar.masterBar.index ||
|
|
47461
|
+
current.nextBeat.beat.playbackStart <= current.beat.playbackStart)) {
|
|
47462
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47463
|
+
}
|
|
47464
|
+
else if (this.playbackRange !== null && this.playbackRange.endTick <= current.nextBeat.start) {
|
|
47465
|
+
current.cursorMode = MidiTickLookupFindBeatResultCursorMode.ToEndOfBeat;
|
|
47466
|
+
}
|
|
47336
47467
|
}
|
|
47337
47468
|
}
|
|
47338
47469
|
_isMultiBarRestResult(current) {
|
|
@@ -49358,22 +49489,61 @@
|
|
|
49358
49489
|
}
|
|
49359
49490
|
|
|
49360
49491
|
/**
|
|
49361
|
-
*
|
|
49362
|
-
*
|
|
49492
|
+
* A cursor handler which animates the beat cursor to the next beat or end of the beat bounds
|
|
49493
|
+
* depending on the cursor mode.
|
|
49494
|
+
* @internal
|
|
49363
49495
|
*/
|
|
49364
|
-
class
|
|
49365
|
-
|
|
49366
|
-
|
|
49367
|
-
|
|
49368
|
-
|
|
49369
|
-
|
|
49370
|
-
|
|
49371
|
-
|
|
49372
|
-
|
|
49373
|
-
|
|
49374
|
-
|
|
49375
|
-
|
|
49376
|
-
|
|
49496
|
+
class ToNextBeatAnimatingCursorHandler {
|
|
49497
|
+
onAttach(_cursors) {
|
|
49498
|
+
}
|
|
49499
|
+
onDetach(_cursors) {
|
|
49500
|
+
}
|
|
49501
|
+
placeBeatCursor(beatCursor, beatBounds, startBeatX) {
|
|
49502
|
+
const barBoundings = beatBounds.barBounds.masterBarBounds;
|
|
49503
|
+
const barBounds = barBoundings.visualBounds;
|
|
49504
|
+
beatCursor.transitionToX(0, startBeatX);
|
|
49505
|
+
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
49506
|
+
}
|
|
49507
|
+
placeBarCursor(barCursor, beatBounds) {
|
|
49508
|
+
const barBoundings = beatBounds.barBounds.masterBarBounds;
|
|
49509
|
+
const barBounds = barBoundings.visualBounds;
|
|
49510
|
+
barCursor.setBounds(barBounds.x, barBounds.y, barBounds.w, barBounds.h);
|
|
49511
|
+
}
|
|
49512
|
+
transitionBeatCursor(beatCursor, _beatBounds, startBeatX, nextBeatX, duration, cursorMode) {
|
|
49513
|
+
// it can happen that the cursor reaches the target position slightly too early (especially on backing tracks)
|
|
49514
|
+
// to avoid the cursor stopping, causing a wierd look, we animate the cursor to the double position in double time.
|
|
49515
|
+
// beatCursor!.transitionToX((duration / cursorSpeed), nextBeatX);
|
|
49516
|
+
const factor = cursorMode === MidiTickLookupFindBeatResultCursorMode.ToNextBext ? 2 : 1;
|
|
49517
|
+
nextBeatX = startBeatX + (nextBeatX - startBeatX) * factor;
|
|
49518
|
+
duration = duration * factor;
|
|
49519
|
+
// we need to put the transition to an own animation frame
|
|
49520
|
+
// otherwise the stop animation above is not applied.
|
|
49521
|
+
beatCursor.transitionToX(duration, nextBeatX);
|
|
49522
|
+
}
|
|
49523
|
+
}
|
|
49524
|
+
/**
|
|
49525
|
+
* A cursor handler which just places the bar and beat cursor without any animations applied.
|
|
49526
|
+
* @internal
|
|
49527
|
+
*/
|
|
49528
|
+
class NonAnimatingCursorHandler {
|
|
49529
|
+
onAttach(_cursors) {
|
|
49530
|
+
}
|
|
49531
|
+
onDetach(_cursors) {
|
|
49532
|
+
}
|
|
49533
|
+
placeBeatCursor(beatCursor, beatBounds, startBeatX) {
|
|
49534
|
+
const barBoundings = beatBounds.barBounds.masterBarBounds;
|
|
49535
|
+
const barBounds = barBoundings.visualBounds;
|
|
49536
|
+
beatCursor.transitionToX(0, startBeatX);
|
|
49537
|
+
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
49538
|
+
}
|
|
49539
|
+
placeBarCursor(barCursor, beatBounds) {
|
|
49540
|
+
const barBoundings = beatBounds.barBounds.masterBarBounds;
|
|
49541
|
+
const barBounds = barBoundings.visualBounds;
|
|
49542
|
+
barCursor.setBounds(barBounds.x, barBounds.y, barBounds.w, barBounds.h);
|
|
49543
|
+
}
|
|
49544
|
+
transitionBeatCursor(beatCursor, beatBounds, startBeatX, _nextBeatX, _duration, _cursorMode) {
|
|
49545
|
+
this.placeBeatCursor(beatCursor, beatBounds, startBeatX);
|
|
49546
|
+
}
|
|
49377
49547
|
}
|
|
49378
49548
|
|
|
49379
49549
|
/**
|
|
@@ -49815,6 +49985,25 @@
|
|
|
49815
49985
|
error = new EventEmitterOfT();
|
|
49816
49986
|
}
|
|
49817
49987
|
|
|
49988
|
+
/**
|
|
49989
|
+
* Represents the information related to a resize event.
|
|
49990
|
+
* @public
|
|
49991
|
+
*/
|
|
49992
|
+
class ResizeEventArgs {
|
|
49993
|
+
/**
|
|
49994
|
+
* Gets the size before the resizing happened.
|
|
49995
|
+
*/
|
|
49996
|
+
oldWidth = 0;
|
|
49997
|
+
/**
|
|
49998
|
+
* Gets the size after the resize was complete.
|
|
49999
|
+
*/
|
|
50000
|
+
newWidth = 0;
|
|
50001
|
+
/**
|
|
50002
|
+
* Gets the settings currently used for rendering.
|
|
50003
|
+
*/
|
|
50004
|
+
settings = null;
|
|
50005
|
+
}
|
|
50006
|
+
|
|
49818
50007
|
/**
|
|
49819
50008
|
* Some basic scroll handler checking for changed offsets and scroll if changed.
|
|
49820
50009
|
* @internal
|
|
@@ -50684,6 +50873,42 @@
|
|
|
50684
50873
|
}
|
|
50685
50874
|
}
|
|
50686
50875
|
|
|
50876
|
+
/**
|
|
50877
|
+
* This wrapper holds all cursor related elements.
|
|
50878
|
+
* @public
|
|
50879
|
+
*/
|
|
50880
|
+
class Cursors {
|
|
50881
|
+
/**
|
|
50882
|
+
* Gets the element that spans across the whole music sheet and holds the other cursor elements.
|
|
50883
|
+
*/
|
|
50884
|
+
cursorWrapper;
|
|
50885
|
+
/**
|
|
50886
|
+
* Gets the element that is positioned above the bar that is currently played.
|
|
50887
|
+
*/
|
|
50888
|
+
barCursor;
|
|
50889
|
+
/**
|
|
50890
|
+
* Gets the element that is positioned above the beat that is currently played.
|
|
50891
|
+
*/
|
|
50892
|
+
beatCursor;
|
|
50893
|
+
/**
|
|
50894
|
+
* Gets the element that spans across the whole music sheet and will hold any selection related elements.
|
|
50895
|
+
*/
|
|
50896
|
+
selectionWrapper;
|
|
50897
|
+
/**
|
|
50898
|
+
* Initializes a new instance of the {@link Cursors} class.
|
|
50899
|
+
* @param cursorWrapper
|
|
50900
|
+
* @param barCursor
|
|
50901
|
+
* @param beatCursor
|
|
50902
|
+
* @param selectionWrapper
|
|
50903
|
+
*/
|
|
50904
|
+
constructor(cursorWrapper, barCursor, beatCursor, selectionWrapper) {
|
|
50905
|
+
this.cursorWrapper = cursorWrapper;
|
|
50906
|
+
this.barCursor = barCursor;
|
|
50907
|
+
this.beatCursor = beatCursor;
|
|
50908
|
+
this.selectionWrapper = selectionWrapper;
|
|
50909
|
+
}
|
|
50910
|
+
}
|
|
50911
|
+
|
|
50687
50912
|
/**
|
|
50688
50913
|
* @internal
|
|
50689
50914
|
*/
|
|
@@ -50715,6 +50940,8 @@
|
|
|
50715
50940
|
_player;
|
|
50716
50941
|
_renderer;
|
|
50717
50942
|
_defaultScrollHandler;
|
|
50943
|
+
_defaultCursorHandler;
|
|
50944
|
+
_customCursorHandler;
|
|
50718
50945
|
/**
|
|
50719
50946
|
* An indicator by how many midi-ticks the song contents are shifted.
|
|
50720
50947
|
* Grace beats at start might require a shift for the first beat to start at 0.
|
|
@@ -51486,6 +51713,80 @@
|
|
|
51486
51713
|
this.uiFacade.canRenderChanged.on(() => this.render(renderHints));
|
|
51487
51714
|
}
|
|
51488
51715
|
}
|
|
51716
|
+
/**
|
|
51717
|
+
* A custom cursor handler which will be used to update the cursor positions during playback.
|
|
51718
|
+
*
|
|
51719
|
+
* @category Properties - Player
|
|
51720
|
+
* @since 1.8.1
|
|
51721
|
+
* @example
|
|
51722
|
+
* JavaScript
|
|
51723
|
+
* ```js
|
|
51724
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
51725
|
+
* api.customCursorHandler = {
|
|
51726
|
+
* _customAdorner: undefined,
|
|
51727
|
+
* onAttach(cursors) {
|
|
51728
|
+
* this._customAdorner = document.createElement('div');
|
|
51729
|
+
* this._customAdorner.classList.add('cursor-adorner');
|
|
51730
|
+
* cursors.cursorWrapper.element.appendChild(this._customAdorner);
|
|
51731
|
+
* },
|
|
51732
|
+
* onDetach(cursors) { this._customAdorner.remove(); },
|
|
51733
|
+
* placeBarCursor(barCursor, beatBounds) {
|
|
51734
|
+
* const barBoundings = beatBounds.barBounds.masterBarBounds;
|
|
51735
|
+
* const barBounds = barBoundings.visualBounds;
|
|
51736
|
+
* barCursor.setBounds(barBounds.x, barBounds.y, barBounds.w, barBounds.h);
|
|
51737
|
+
* },
|
|
51738
|
+
* placeBeatCursor(beatCursor, beatBounds, startBeatX) {
|
|
51739
|
+
* const barBoundings = beatBounds.barBounds.masterBarBounds;
|
|
51740
|
+
* const barBounds = barBoundings.visualBounds;
|
|
51741
|
+
* beatCursor.transitionToX(0, startBeatX);
|
|
51742
|
+
* beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
51743
|
+
* this._customAdorner.style.left = startBeatX + 'px';
|
|
51744
|
+
* this._customAdorner.style.top = (barBounds.y - 10) + 'px';
|
|
51745
|
+
* this._customAdorner.style.width = '1px';
|
|
51746
|
+
* this._customAdorner.style.height = '10px';
|
|
51747
|
+
* this._customAdorner.style.transition = 'left 0ms linear'; // stop animation
|
|
51748
|
+
* },
|
|
51749
|
+
* transitionBeatCursor(beatCursor, beatBounds, startBeatX, endBeatX, duration, cursorMode) {
|
|
51750
|
+
* this._customAdorner.style.transition = `left ${duration}ms linear`; // start animation
|
|
51751
|
+
* this._customAdorner.style.left = endBeatX + 'px';
|
|
51752
|
+
* }
|
|
51753
|
+
* }
|
|
51754
|
+
* ```
|
|
51755
|
+
*
|
|
51756
|
+
* @example
|
|
51757
|
+
* C#
|
|
51758
|
+
* ```cs
|
|
51759
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
51760
|
+
* api.CustomCursorHandler = new CustomCursorHandler();
|
|
51761
|
+
* ```
|
|
51762
|
+
*
|
|
51763
|
+
* @example
|
|
51764
|
+
* Android
|
|
51765
|
+
* ```kotlin
|
|
51766
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
51767
|
+
* api.customCursorHandler = CustomCursorHandler();
|
|
51768
|
+
* ```
|
|
51769
|
+
*/
|
|
51770
|
+
get customCursorHandler() {
|
|
51771
|
+
return this._customCursorHandler;
|
|
51772
|
+
}
|
|
51773
|
+
set customCursorHandler(value) {
|
|
51774
|
+
if (this._customCursorHandler === value) {
|
|
51775
|
+
return;
|
|
51776
|
+
}
|
|
51777
|
+
const currentHandler = this._customCursorHandler ?? this._defaultCursorHandler;
|
|
51778
|
+
this._customCursorHandler = value;
|
|
51779
|
+
if (this._cursorWrapper) {
|
|
51780
|
+
const cursors = new Cursors(this._cursorWrapper, this._barCursor, this._beatCursor, this._selectionWrapper);
|
|
51781
|
+
currentHandler?.onDetach(cursors);
|
|
51782
|
+
if (value) {
|
|
51783
|
+
value?.onDetach(cursors);
|
|
51784
|
+
}
|
|
51785
|
+
else if (this._defaultCursorHandler) {
|
|
51786
|
+
this._defaultCursorHandler.onAttach(cursors);
|
|
51787
|
+
}
|
|
51788
|
+
}
|
|
51789
|
+
}
|
|
51489
51790
|
_tickCache = null;
|
|
51490
51791
|
/**
|
|
51491
51792
|
* A custom scroll handler which will be used to handle scrolling operations during playback.
|
|
@@ -51963,6 +52264,9 @@
|
|
|
51963
52264
|
}
|
|
51964
52265
|
set playbackRange(value) {
|
|
51965
52266
|
this._player.playbackRange = value;
|
|
52267
|
+
if (this._tickCache) {
|
|
52268
|
+
this._tickCache.playbackRange = value;
|
|
52269
|
+
}
|
|
51966
52270
|
this._updateSelectionCursor(value);
|
|
51967
52271
|
}
|
|
51968
52272
|
/**
|
|
@@ -52110,6 +52414,7 @@
|
|
|
52110
52414
|
generator.applyTranspositionPitches = false;
|
|
52111
52415
|
generator.generate();
|
|
52112
52416
|
this._tickCache = generator.tickLookup;
|
|
52417
|
+
this._tickCache.playbackRange = this.playbackRange;
|
|
52113
52418
|
this._onMidiLoad(midiFile);
|
|
52114
52419
|
const player = this._player;
|
|
52115
52420
|
player.midiTickShift = handler.tickShift;
|
|
@@ -52505,6 +52810,8 @@
|
|
|
52505
52810
|
if (!this._cursorWrapper) {
|
|
52506
52811
|
return;
|
|
52507
52812
|
}
|
|
52813
|
+
const cursorHandler = this.customCursorHandler ?? this._defaultCursorHandler;
|
|
52814
|
+
cursorHandler?.onDetach(new Cursors(this._cursorWrapper, this._barCursor, this._beatCursor, this._selectionWrapper));
|
|
52508
52815
|
this.uiFacade.destroyCursors();
|
|
52509
52816
|
this._cursorWrapper = null;
|
|
52510
52817
|
this._barCursor = null;
|
|
@@ -52522,6 +52829,8 @@
|
|
|
52522
52829
|
this._barCursor = cursors.barCursor;
|
|
52523
52830
|
this._beatCursor = cursors.beatCursor;
|
|
52524
52831
|
this._selectionWrapper = cursors.selectionWrapper;
|
|
52832
|
+
const cursorHandler = this.customCursorHandler ?? this._defaultCursorHandler;
|
|
52833
|
+
cursorHandler?.onAttach(cursors);
|
|
52525
52834
|
this._isInitialBeatCursorUpdate = true;
|
|
52526
52835
|
}
|
|
52527
52836
|
if (this._currentBeat !== null) {
|
|
@@ -52529,6 +52838,7 @@
|
|
|
52529
52838
|
}
|
|
52530
52839
|
}
|
|
52531
52840
|
_updateCursors() {
|
|
52841
|
+
this._updateCursorHandler();
|
|
52532
52842
|
this._updateScrollHandler();
|
|
52533
52843
|
const enable = this._hasCursor;
|
|
52534
52844
|
if (enable) {
|
|
@@ -52538,6 +52848,21 @@
|
|
|
52538
52848
|
this._destroyCursors();
|
|
52539
52849
|
}
|
|
52540
52850
|
}
|
|
52851
|
+
_cursorHandlerMode = false;
|
|
52852
|
+
_updateCursorHandler() {
|
|
52853
|
+
const currentHandler = this._defaultCursorHandler;
|
|
52854
|
+
const cursorHandlerMode = this.settings.player.enableAnimatedBeatCursor;
|
|
52855
|
+
// no change
|
|
52856
|
+
if (currentHandler !== undefined && this._cursorHandlerMode === cursorHandlerMode) {
|
|
52857
|
+
return;
|
|
52858
|
+
}
|
|
52859
|
+
if (cursorHandlerMode) {
|
|
52860
|
+
this._defaultCursorHandler = new ToNextBeatAnimatingCursorHandler();
|
|
52861
|
+
}
|
|
52862
|
+
else {
|
|
52863
|
+
this._defaultCursorHandler = new NonAnimatingCursorHandler();
|
|
52864
|
+
}
|
|
52865
|
+
}
|
|
52541
52866
|
_scrollHandlerMode = exports.ScrollMode.Off;
|
|
52542
52867
|
_scrollHandlerVertical = true;
|
|
52543
52868
|
_updateScrollHandler() {
|
|
@@ -52605,9 +52930,6 @@
|
|
|
52605
52930
|
*/
|
|
52606
52931
|
_cursorUpdateBeat(lookupResult, stop, shouldScroll, cursorSpeed, forceUpdate = false) {
|
|
52607
52932
|
const beat = lookupResult.beat;
|
|
52608
|
-
const nextBeat = lookupResult.nextBeat?.beat ?? null;
|
|
52609
|
-
const duration = lookupResult.duration;
|
|
52610
|
-
const beatsToHighlight = lookupResult.beatLookup.highlightedBeats;
|
|
52611
52933
|
if (!beat) {
|
|
52612
52934
|
return;
|
|
52613
52935
|
}
|
|
@@ -52635,7 +52957,7 @@
|
|
|
52635
52957
|
this._previousCursorCache = cache;
|
|
52636
52958
|
this._previousStateForCursor = this._player.state;
|
|
52637
52959
|
this.uiFacade.beginInvoke(() => {
|
|
52638
|
-
this._internalCursorUpdateBeat(
|
|
52960
|
+
this._internalCursorUpdateBeat(lookupResult, stop, cache, beatBoundings, shouldScroll, cursorSpeed);
|
|
52639
52961
|
});
|
|
52640
52962
|
}
|
|
52641
52963
|
/**
|
|
@@ -52652,24 +52974,30 @@
|
|
|
52652
52974
|
}
|
|
52653
52975
|
}
|
|
52654
52976
|
}
|
|
52655
|
-
_internalCursorUpdateBeat(
|
|
52656
|
-
const
|
|
52977
|
+
_internalCursorUpdateBeat(lookupResult, stop, boundsLookup, beatBoundings, shouldScroll, cursorSpeed) {
|
|
52978
|
+
const beat = lookupResult.beat;
|
|
52979
|
+
const nextBeat = lookupResult.nextBeat?.beat;
|
|
52980
|
+
let duration = lookupResult.duration;
|
|
52981
|
+
const beatsToHighlight = lookupResult.beatLookup.highlightedBeats;
|
|
52982
|
+
const cursorMode = lookupResult.cursorMode;
|
|
52983
|
+
const cursorHandler = this.customCursorHandler ?? this._defaultCursorHandler;
|
|
52657
52984
|
const beatCursor = this._beatCursor;
|
|
52985
|
+
const barCursor = this._barCursor;
|
|
52658
52986
|
const barBoundings = beatBoundings.barBounds.masterBarBounds;
|
|
52659
52987
|
const barBounds = barBoundings.visualBounds;
|
|
52660
52988
|
const previousBeatBounds = this._currentBeatBounds;
|
|
52661
52989
|
this._currentBeatBounds = beatBoundings;
|
|
52662
52990
|
if (barCursor) {
|
|
52663
|
-
|
|
52991
|
+
cursorHandler.placeBarCursor(barCursor, beatBoundings);
|
|
52664
52992
|
}
|
|
52665
52993
|
const isPlayingUpdate = this._player.state === PlayerState.Playing && !stop;
|
|
52666
|
-
let nextBeatX =
|
|
52994
|
+
let nextBeatX = beatBoundings.realBounds.x + beatBoundings.realBounds.w;
|
|
52667
52995
|
let nextBeatBoundings = null;
|
|
52668
52996
|
// get position of next beat on same system
|
|
52669
52997
|
if (nextBeat && cursorMode === MidiTickLookupFindBeatResultCursorMode.ToNextBext) {
|
|
52670
52998
|
// if we are moving within the same bar or to the next bar
|
|
52671
52999
|
// transition to the next beat, otherwise transition to the end of the bar.
|
|
52672
|
-
nextBeatBoundings =
|
|
53000
|
+
nextBeatBoundings = boundsLookup.findBeat(nextBeat);
|
|
52673
53001
|
if (nextBeatBoundings &&
|
|
52674
53002
|
nextBeatBoundings.barBounds.masterBarBounds.staffSystemBounds === barBoundings.staffSystemBounds) {
|
|
52675
53003
|
nextBeatX = nextBeatBoundings.onNotesX;
|
|
@@ -52677,48 +53005,30 @@
|
|
|
52677
53005
|
}
|
|
52678
53006
|
let startBeatX = beatBoundings.onNotesX;
|
|
52679
53007
|
if (beatCursor) {
|
|
52680
|
-
|
|
52681
|
-
|
|
52682
|
-
|
|
52683
|
-
|
|
52684
|
-
|
|
52685
|
-
|
|
52686
|
-
|
|
52687
|
-
|
|
52688
|
-
|
|
52689
|
-
|
|
52690
|
-
|
|
52691
|
-
|
|
52692
|
-
|
|
52693
|
-
|
|
52694
|
-
|
|
52695
|
-
|
|
52696
|
-
|
|
52697
|
-
|
|
52698
|
-
|
|
52699
|
-
|
|
52700
|
-
// beatCursor!.transitionToX((duration / cursorSpeed), nextBeatX);
|
|
52701
|
-
const factor = cursorMode === MidiTickLookupFindBeatResultCursorMode.ToNextBext ? 2 : 1;
|
|
52702
|
-
nextBeatX = startBeatX + (nextBeatX - startBeatX) * factor;
|
|
52703
|
-
duration = (duration / cursorSpeed) * factor;
|
|
52704
|
-
// we need to put the transition to an own animation frame
|
|
52705
|
-
// otherwise the stop animation above is not applied.
|
|
52706
|
-
this.uiFacade.beginInvoke(() => {
|
|
52707
|
-
beatCursor.transitionToX(duration, nextBeatX);
|
|
52708
|
-
});
|
|
52709
|
-
}
|
|
52710
|
-
else {
|
|
52711
|
-
duration = 0;
|
|
52712
|
-
beatCursor.transitionToX(duration, nextBeatX);
|
|
52713
|
-
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
52714
|
-
}
|
|
53008
|
+
const animationWidth = nextBeatX - beatBoundings.onNotesX;
|
|
53009
|
+
const relativePosition = this._previousTick - this._currentBeat.start;
|
|
53010
|
+
const ratioPosition = this._currentBeat.tickDuration > 0 ? relativePosition / this._currentBeat.tickDuration : 0;
|
|
53011
|
+
startBeatX = beatBoundings.onNotesX + animationWidth * ratioPosition;
|
|
53012
|
+
duration -= duration * ratioPosition;
|
|
53013
|
+
// respect speed
|
|
53014
|
+
duration = duration / cursorSpeed;
|
|
53015
|
+
if (isPlayingUpdate) {
|
|
53016
|
+
// we do not "reset" the cursor if we are smoothly moving from left to right.
|
|
53017
|
+
const jumpCursor = !previousBeatBounds ||
|
|
53018
|
+
this._isInitialBeatCursorUpdate ||
|
|
53019
|
+
barBounds.y !== previousBeatBounds.barBounds.masterBarBounds.visualBounds.y ||
|
|
53020
|
+
startBeatX < previousBeatBounds.onNotesX ||
|
|
53021
|
+
barBoundings.index > previousBeatBounds.barBounds.masterBarBounds.index + 1;
|
|
53022
|
+
if (jumpCursor) {
|
|
53023
|
+
cursorHandler.placeBeatCursor(beatCursor, beatBoundings, startBeatX);
|
|
53024
|
+
}
|
|
53025
|
+
this.uiFacade.beginInvoke(() => {
|
|
53026
|
+
cursorHandler.transitionBeatCursor(beatCursor, beatBoundings, startBeatX, nextBeatX, duration, cursorMode);
|
|
53027
|
+
});
|
|
52715
53028
|
}
|
|
52716
53029
|
else {
|
|
52717
|
-
// ticking cursor
|
|
52718
53030
|
duration = 0;
|
|
52719
|
-
|
|
52720
|
-
beatCursor.transitionToX(duration, nextBeatX);
|
|
52721
|
-
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
53031
|
+
cursorHandler.placeBeatCursor(beatCursor, beatBoundings, startBeatX);
|
|
52722
53032
|
}
|
|
52723
53033
|
this._isInitialBeatCursorUpdate = false;
|
|
52724
53034
|
}
|
|
@@ -55595,42 +55905,6 @@
|
|
|
55595
55905
|
error = new EventEmitterOfT();
|
|
55596
55906
|
}
|
|
55597
55907
|
|
|
55598
|
-
/**
|
|
55599
|
-
* This wrapper holds all cursor related elements.
|
|
55600
|
-
* @public
|
|
55601
|
-
*/
|
|
55602
|
-
class Cursors {
|
|
55603
|
-
/**
|
|
55604
|
-
* Gets the element that spans across the whole music sheet and holds the other cursor elements.
|
|
55605
|
-
*/
|
|
55606
|
-
cursorWrapper;
|
|
55607
|
-
/**
|
|
55608
|
-
* Gets the element that is positioned above the bar that is currently played.
|
|
55609
|
-
*/
|
|
55610
|
-
barCursor;
|
|
55611
|
-
/**
|
|
55612
|
-
* Gets the element that is positioned above the beat that is currently played.
|
|
55613
|
-
*/
|
|
55614
|
-
beatCursor;
|
|
55615
|
-
/**
|
|
55616
|
-
* Gets the element that spans across the whole music sheet and will hold any selection related elements.
|
|
55617
|
-
*/
|
|
55618
|
-
selectionWrapper;
|
|
55619
|
-
/**
|
|
55620
|
-
* Initializes a new instance of the {@link Cursors} class.
|
|
55621
|
-
* @param cursorWrapper
|
|
55622
|
-
* @param barCursor
|
|
55623
|
-
* @param beatCursor
|
|
55624
|
-
* @param selectionWrapper
|
|
55625
|
-
*/
|
|
55626
|
-
constructor(cursorWrapper, barCursor, beatCursor, selectionWrapper) {
|
|
55627
|
-
this.cursorWrapper = cursorWrapper;
|
|
55628
|
-
this.barCursor = barCursor;
|
|
55629
|
-
this.beatCursor = beatCursor;
|
|
55630
|
-
this.selectionWrapper = selectionWrapper;
|
|
55631
|
-
}
|
|
55632
|
-
}
|
|
55633
|
-
|
|
55634
55908
|
/**
|
|
55635
55909
|
* An IContainer implementation which can be used for cursors and select ranges
|
|
55636
55910
|
* where browser scaling is relevant.
|
|
@@ -59934,11 +60208,12 @@
|
|
|
59934
60208
|
}
|
|
59935
60209
|
doLayout() {
|
|
59936
60210
|
super.doLayout();
|
|
59937
|
-
|
|
60211
|
+
let text = '';
|
|
59938
60212
|
let text2 = '';
|
|
59939
60213
|
let accidental = AccidentalType.None;
|
|
59940
60214
|
switch (this._keySignatureType) {
|
|
59941
60215
|
case KeySignatureType.Major:
|
|
60216
|
+
text = '1 = ';
|
|
59942
60217
|
switch (this._keySignature) {
|
|
59943
60218
|
case KeySignature.Cb:
|
|
59944
60219
|
text2 = ' C';
|
|
@@ -60002,6 +60277,7 @@
|
|
|
60002
60277
|
}
|
|
60003
60278
|
break;
|
|
60004
60279
|
case KeySignatureType.Minor:
|
|
60280
|
+
text = '6 = ';
|
|
60005
60281
|
switch (this._keySignature) {
|
|
60006
60282
|
case KeySignature.Cb:
|
|
60007
60283
|
text2 = ' a';
|
|
@@ -67981,7 +68257,6 @@
|
|
|
67981
68257
|
* @internal
|
|
67982
68258
|
*/
|
|
67983
68259
|
class NumberedBeatPreNotesGlyph extends BeatGlyphBase {
|
|
67984
|
-
isNaturalizeAccidental = false;
|
|
67985
68260
|
accidental = AccidentalType.None;
|
|
67986
68261
|
skipLayout = false;
|
|
67987
68262
|
get effectElement() {
|
|
@@ -67996,25 +68271,25 @@
|
|
|
67996
68271
|
accidentals.renderer = this.renderer;
|
|
67997
68272
|
if (this.container.beat.notes.length > 0) {
|
|
67998
68273
|
const note = this.container.beat.notes[0];
|
|
67999
|
-
|
|
68000
|
-
|
|
68001
|
-
|
|
68002
|
-
|
|
68003
|
-
|
|
68004
|
-
|
|
68005
|
-
|
|
68006
|
-
|
|
68007
|
-
|
|
68008
|
-
|
|
68009
|
-
|
|
68010
|
-
|
|
68011
|
-
|
|
68012
|
-
|
|
68013
|
-
|
|
68014
|
-
|
|
68015
|
-
|
|
68016
|
-
|
|
68017
|
-
|
|
68274
|
+
const spelling = ModelUtils.resolveSpelling(this.renderer.bar.keySignature, note.displayValue, note.accidentalMode);
|
|
68275
|
+
const ksOffset = ModelUtils.getKeySignatureAccidentalOffset(this.renderer.bar.keySignature, spelling.degree);
|
|
68276
|
+
const requiredOffset = spelling.accidentalOffset - ksOffset;
|
|
68277
|
+
let accidentalToSet = AccidentalType.None;
|
|
68278
|
+
if (note.accidentalMode !== NoteAccidentalMode.ForceNone) {
|
|
68279
|
+
if (note.hasQuarterToneOffset) {
|
|
68280
|
+
if (requiredOffset > 0) {
|
|
68281
|
+
accidentalToSet = AccidentalType.SharpQuarterNoteUp;
|
|
68282
|
+
}
|
|
68283
|
+
else if (requiredOffset < 0) {
|
|
68284
|
+
accidentalToSet = AccidentalType.FlatQuarterNoteUp;
|
|
68285
|
+
}
|
|
68286
|
+
else {
|
|
68287
|
+
accidentalToSet = AccidentalType.NaturalQuarterNoteUp;
|
|
68288
|
+
}
|
|
68289
|
+
}
|
|
68290
|
+
else if (requiredOffset !== 0) {
|
|
68291
|
+
accidentalToSet = ModelUtils.accidentalOffsetToType(requiredOffset);
|
|
68292
|
+
}
|
|
68018
68293
|
}
|
|
68019
68294
|
// do we need an accidental on the note?
|
|
68020
68295
|
if (accidentalToSet !== AccidentalType.None) {
|
|
@@ -68121,21 +68396,21 @@
|
|
|
68121
68396
|
}
|
|
68122
68397
|
return 0;
|
|
68123
68398
|
}
|
|
68124
|
-
static
|
|
68125
|
-
// Flats
|
|
68126
|
-
59, 66, 61, 68, 63,
|
|
68127
|
-
// natural
|
|
68399
|
+
static _majorKeySignatureOneValues = [
|
|
68400
|
+
// Flats: Cb, Gb, Db, Ab, Eb, Bb, F
|
|
68401
|
+
59, 66, 61, 68, 63, 70, 65,
|
|
68402
|
+
// natural: C
|
|
68128
68403
|
60,
|
|
68129
|
-
// sharps
|
|
68404
|
+
// sharps: G, D, A, E, B, F#, C#
|
|
68130
68405
|
67, 62, 69, 64, 71, 66, 61
|
|
68131
68406
|
];
|
|
68132
|
-
static
|
|
68133
|
-
// Flats
|
|
68134
|
-
|
|
68135
|
-
// natural
|
|
68136
|
-
|
|
68137
|
-
// sharps
|
|
68138
|
-
|
|
68407
|
+
static _minorKeySignatureOneValues = [
|
|
68408
|
+
// Flats: Ab, Eb, Bb, F, C, G, D
|
|
68409
|
+
68, 63, 70, 65, 60, 67, 62,
|
|
68410
|
+
// natural: A
|
|
68411
|
+
69,
|
|
68412
|
+
// sharps: E, B, F#, C#, G#, D#, A#
|
|
68413
|
+
64, 71, 66, 61, 68, 63, 70
|
|
68139
68414
|
];
|
|
68140
68415
|
doLayout() {
|
|
68141
68416
|
// create glyphs
|
|
@@ -68149,38 +68424,26 @@
|
|
|
68149
68424
|
let numberWithinOctave = '0';
|
|
68150
68425
|
if (this.container.beat.notes.length > 0) {
|
|
68151
68426
|
const note = this.container.beat.notes[0];
|
|
68152
|
-
const kst = this.renderer.bar.keySignatureType;
|
|
68153
|
-
const ks = this.renderer.bar.keySignature;
|
|
68154
|
-
const ksi = ks + 7;
|
|
68155
|
-
const oneNoteValues = kst === KeySignatureType.Minor
|
|
68156
|
-
? NumberedBeatGlyph.minorKeySignatureOneValues
|
|
68157
|
-
: NumberedBeatGlyph.majorKeySignatureOneValues;
|
|
68158
|
-
const oneNoteValue = oneNoteValues[ksi];
|
|
68159
68427
|
if (note.isDead) {
|
|
68160
68428
|
numberWithinOctave = 'X';
|
|
68161
68429
|
}
|
|
68162
68430
|
else {
|
|
68431
|
+
const ks = this.renderer.bar.keySignature;
|
|
68432
|
+
const kst = this.renderer.bar.keySignatureType;
|
|
68433
|
+
const ksi = ks + 7;
|
|
68434
|
+
const oneNoteValues = kst === KeySignatureType.Minor
|
|
68435
|
+
? NumberedBeatGlyph._minorKeySignatureOneValues
|
|
68436
|
+
: NumberedBeatGlyph._majorKeySignatureOneValues;
|
|
68437
|
+
const oneNoteValue = oneNoteValues[ksi];
|
|
68438
|
+
const spelling = ModelUtils.resolveSpelling(ks, note.displayValue, note.accidentalMode);
|
|
68439
|
+
const tonicDegree = ModelUtils.getKeySignatureTonicDegree(ks, kst);
|
|
68440
|
+
const effectiveTonic = kst === KeySignatureType.Minor
|
|
68441
|
+
? (tonicDegree + 2) % 7 // relative major
|
|
68442
|
+
: tonicDegree;
|
|
68443
|
+
const degreeDistance = (spelling.degree - effectiveTonic + 7) % 7;
|
|
68444
|
+
numberWithinOctave = (degreeDistance + 1).toString();
|
|
68163
68445
|
const noteValue = note.displayValue - oneNoteValue;
|
|
68164
|
-
|
|
68165
|
-
octaveDots = noteValue < 0 ? ((Math.abs(noteValue) + 12) / 12) | 0 : (noteValue / 12) | 0;
|
|
68166
|
-
if (noteValue < 0) {
|
|
68167
|
-
octaveDots *= -1;
|
|
68168
|
-
}
|
|
68169
|
-
const stepList = ModelUtils.keySignatureIsSharp(ks) || ModelUtils.keySignatureIsNatural(ks)
|
|
68170
|
-
? AccidentalHelper.flatNoteSteps
|
|
68171
|
-
: AccidentalHelper.sharpNoteSteps;
|
|
68172
|
-
let steps = stepList[index] + 1;
|
|
68173
|
-
const hasAccidental = ModelUtils.accidentalNotes[index];
|
|
68174
|
-
if (hasAccidental &&
|
|
68175
|
-
!this.container.preNotes.isNaturalizeAccidental) {
|
|
68176
|
-
if (ksi < 7) {
|
|
68177
|
-
steps++;
|
|
68178
|
-
}
|
|
68179
|
-
else {
|
|
68180
|
-
steps--;
|
|
68181
|
-
}
|
|
68182
|
-
}
|
|
68183
|
-
numberWithinOctave = steps.toString();
|
|
68446
|
+
octaveDots = Math.floor(noteValue / 12);
|
|
68184
68447
|
}
|
|
68185
68448
|
}
|
|
68186
68449
|
if (this.container.beat.deadSlapped) {
|