@coderline/alphatab 1.5.0-alpha.1394 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.header +4 -1
- package/dist/alphaTab.core.min.mjs +51 -1
- package/dist/alphaTab.core.mjs +578 -594
- package/dist/alphaTab.d.ts +2 -0
- package/dist/alphaTab.js +578 -594
- package/dist/alphaTab.min.js +51 -0
- package/dist/alphaTab.min.mjs +51 -1
- package/dist/alphaTab.mjs +7 -2
- package/dist/alphaTab.vite.js +7 -2
- package/dist/alphaTab.vite.mjs +7 -2
- package/dist/alphaTab.webpack.js +7 -2
- package/dist/alphaTab.webpack.mjs +7 -2
- package/dist/alphaTab.worker.min.mjs +51 -1
- package/dist/alphaTab.worker.mjs +7 -2
- package/dist/alphaTab.worklet.min.mjs +51 -1
- package/dist/alphaTab.worklet.mjs +7 -2
- package/package.json +2 -9
package/dist/alphaTab.core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
* alphaTab v1.5.0
|
|
1
|
+
/*!
|
|
2
|
+
* alphaTab v1.5.0 (, build 18)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -44,8 +44,13 @@
|
|
|
44
44
|
* Copyright: Copyright (c) 2002-2020 Xiph.org Foundation
|
|
45
45
|
* URL: https://github.com/xiph/vorbis
|
|
46
46
|
* Purpose: NVorbis adopted some code from libvorbis.
|
|
47
|
+
*
|
|
48
|
+
* @preserve
|
|
49
|
+
* @license
|
|
47
50
|
*/
|
|
48
51
|
|
|
52
|
+
if(typeof Symbol.dispose==='undefined'){Symbol.dispose = Symbol('Symbol.dispose')}
|
|
53
|
+
|
|
49
54
|
/**
|
|
50
55
|
* Lists all layout modes that are supported.
|
|
51
56
|
*/
|
|
@@ -2570,6 +2575,321 @@ class MasterBar {
|
|
|
2570
2575
|
}
|
|
2571
2576
|
MasterBar.MaxAlternateEndings = 8;
|
|
2572
2577
|
|
|
2578
|
+
// The SoundFont loading and Audio Synthesis is based on TinySoundFont, licensed under MIT,
|
|
2579
|
+
// developed by Bernhard Schelling (https://github.com/schellingb/TinySoundFont)
|
|
2580
|
+
// TypeScript port for alphaTab: (C) 2020 by Daniel Kuschny
|
|
2581
|
+
// Licensed under: MPL-2.0
|
|
2582
|
+
class SynthConstants {
|
|
2583
|
+
}
|
|
2584
|
+
SynthConstants.DefaultChannelCount = 16 + 1;
|
|
2585
|
+
SynthConstants.MetronomeChannel = SynthConstants.DefaultChannelCount - 1;
|
|
2586
|
+
SynthConstants.MetronomeKey = 33;
|
|
2587
|
+
SynthConstants.AudioChannels = 2;
|
|
2588
|
+
SynthConstants.MinVolume = 0;
|
|
2589
|
+
SynthConstants.MinProgram = 0;
|
|
2590
|
+
SynthConstants.MaxProgram = 127;
|
|
2591
|
+
SynthConstants.MinPlaybackSpeed = 0.125;
|
|
2592
|
+
SynthConstants.MaxPlaybackSpeed = 8;
|
|
2593
|
+
SynthConstants.PercussionChannel = 9;
|
|
2594
|
+
SynthConstants.PercussionBank = 128;
|
|
2595
|
+
/**
|
|
2596
|
+
* The Midi Pitch bend message is a 15-bit value
|
|
2597
|
+
*/
|
|
2598
|
+
SynthConstants.MaxPitchWheel = 0x4000;
|
|
2599
|
+
/**
|
|
2600
|
+
* The Midi 2.0 Pitch bend message is a 32-bit value
|
|
2601
|
+
*/
|
|
2602
|
+
SynthConstants.MaxPitchWheel20 = 0x100000000;
|
|
2603
|
+
/**
|
|
2604
|
+
* The pitch wheel value for no pitch change at all.
|
|
2605
|
+
*/
|
|
2606
|
+
SynthConstants.DefaultPitchWheel = SynthConstants.MaxPitchWheel / 2;
|
|
2607
|
+
SynthConstants.MicroBufferCount = 32;
|
|
2608
|
+
SynthConstants.MicroBufferSize = 64;
|
|
2609
|
+
|
|
2610
|
+
/**
|
|
2611
|
+
* Represents a group of grace beats that belong together
|
|
2612
|
+
*/
|
|
2613
|
+
class GraceGroup {
|
|
2614
|
+
constructor() {
|
|
2615
|
+
/**
|
|
2616
|
+
* All beats within this group.
|
|
2617
|
+
*/
|
|
2618
|
+
this.beats = [];
|
|
2619
|
+
/**
|
|
2620
|
+
* Gets a unique ID for this grace group.
|
|
2621
|
+
*/
|
|
2622
|
+
this.id = 'empty';
|
|
2623
|
+
/**
|
|
2624
|
+
* true if the grace beat are followed by a normal beat within the same
|
|
2625
|
+
* bar.
|
|
2626
|
+
*/
|
|
2627
|
+
this.isComplete = false;
|
|
2628
|
+
}
|
|
2629
|
+
/**
|
|
2630
|
+
* Adds a new beat to this group
|
|
2631
|
+
* @param beat The beat to add
|
|
2632
|
+
*/
|
|
2633
|
+
addBeat(beat) {
|
|
2634
|
+
beat.graceIndex = this.beats.length;
|
|
2635
|
+
beat.graceGroup = this;
|
|
2636
|
+
this.beats.push(beat);
|
|
2637
|
+
}
|
|
2638
|
+
finish() {
|
|
2639
|
+
if (this.beats.length > 0) {
|
|
2640
|
+
this.id = `${this.beats[0].absoluteDisplayStart}_${this.beats[0].voice.index}`;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
/**
|
|
2646
|
+
* Lists all graphical sub elements within a {@link Voice} which can be styled via {@link Voice.style}
|
|
2647
|
+
*/
|
|
2648
|
+
var VoiceSubElement;
|
|
2649
|
+
(function (VoiceSubElement) {
|
|
2650
|
+
/**
|
|
2651
|
+
* All general glyphs (like notes heads and rests).
|
|
2652
|
+
*/
|
|
2653
|
+
VoiceSubElement[VoiceSubElement["Glyphs"] = 0] = "Glyphs";
|
|
2654
|
+
})(VoiceSubElement || (VoiceSubElement = {}));
|
|
2655
|
+
/**
|
|
2656
|
+
* Defines the custom styles for voices.
|
|
2657
|
+
* @json
|
|
2658
|
+
* @json_strict
|
|
2659
|
+
*/
|
|
2660
|
+
class VoiceStyle extends ElementStyle {
|
|
2661
|
+
}
|
|
2662
|
+
/**
|
|
2663
|
+
* A voice represents a group of beats
|
|
2664
|
+
* that can be played during a bar.
|
|
2665
|
+
* @json
|
|
2666
|
+
* @json_strict
|
|
2667
|
+
*/
|
|
2668
|
+
let Voice$1 = class Voice {
|
|
2669
|
+
constructor() {
|
|
2670
|
+
this._isEmpty = true;
|
|
2671
|
+
this._isRestOnly = true;
|
|
2672
|
+
/**
|
|
2673
|
+
* Gets or sets the unique id of this bar.
|
|
2674
|
+
*/
|
|
2675
|
+
this.id = Voice._globalVoiceId++;
|
|
2676
|
+
/**
|
|
2677
|
+
* Gets or sets the zero-based index of this voice within the bar.
|
|
2678
|
+
* @json_ignore
|
|
2679
|
+
*/
|
|
2680
|
+
this.index = 0;
|
|
2681
|
+
/**
|
|
2682
|
+
* Gets or sets the list of beats contained in this voice.
|
|
2683
|
+
* @json_add addBeat
|
|
2684
|
+
*/
|
|
2685
|
+
this.beats = [];
|
|
2686
|
+
}
|
|
2687
|
+
/**
|
|
2688
|
+
* @internal
|
|
2689
|
+
*/
|
|
2690
|
+
static resetIds() {
|
|
2691
|
+
Voice._globalVoiceId = 0;
|
|
2692
|
+
}
|
|
2693
|
+
/**
|
|
2694
|
+
* Gets or sets a value indicating whether this voice is empty.
|
|
2695
|
+
*/
|
|
2696
|
+
get isEmpty() {
|
|
2697
|
+
return this._isEmpty;
|
|
2698
|
+
}
|
|
2699
|
+
/**
|
|
2700
|
+
* @internal
|
|
2701
|
+
*/
|
|
2702
|
+
forceNonEmpty() {
|
|
2703
|
+
this._isEmpty = false;
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Gets or sets a value indicating whether this voice is empty.
|
|
2707
|
+
*/
|
|
2708
|
+
get isRestOnly() {
|
|
2709
|
+
return this._isRestOnly;
|
|
2710
|
+
}
|
|
2711
|
+
insertBeat(after, newBeat) {
|
|
2712
|
+
newBeat.nextBeat = after.nextBeat;
|
|
2713
|
+
if (newBeat.nextBeat) {
|
|
2714
|
+
newBeat.nextBeat.previousBeat = newBeat;
|
|
2715
|
+
}
|
|
2716
|
+
newBeat.previousBeat = after;
|
|
2717
|
+
newBeat.voice = this;
|
|
2718
|
+
after.nextBeat = newBeat;
|
|
2719
|
+
this.beats.splice(after.index + 1, 0, newBeat);
|
|
2720
|
+
}
|
|
2721
|
+
addBeat(beat) {
|
|
2722
|
+
beat.voice = this;
|
|
2723
|
+
beat.index = this.beats.length;
|
|
2724
|
+
this.beats.push(beat);
|
|
2725
|
+
if (!beat.isEmpty) {
|
|
2726
|
+
this._isEmpty = false;
|
|
2727
|
+
}
|
|
2728
|
+
if (!beat.isRest) {
|
|
2729
|
+
this._isRestOnly = false;
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
chain(beat, sharedDataBag = null) {
|
|
2733
|
+
if (!this.bar) {
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
if (beat.index < this.beats.length - 1) {
|
|
2737
|
+
beat.nextBeat = this.beats[beat.index + 1];
|
|
2738
|
+
beat.nextBeat.previousBeat = beat;
|
|
2739
|
+
}
|
|
2740
|
+
else if (beat.isLastOfVoice && beat.voice.bar.nextBar) {
|
|
2741
|
+
const nextVoice = this.bar.nextBar.voices[this.index];
|
|
2742
|
+
if (nextVoice.beats.length > 0) {
|
|
2743
|
+
beat.nextBeat = nextVoice.beats[0];
|
|
2744
|
+
beat.nextBeat.previousBeat = beat;
|
|
2745
|
+
}
|
|
2746
|
+
else {
|
|
2747
|
+
beat.nextBeat.previousBeat = beat;
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
beat.chain(sharedDataBag);
|
|
2751
|
+
}
|
|
2752
|
+
addGraceBeat(beat) {
|
|
2753
|
+
if (this.beats.length === 0) {
|
|
2754
|
+
this.addBeat(beat);
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2757
|
+
// remove last beat
|
|
2758
|
+
const lastBeat = this.beats[this.beats.length - 1];
|
|
2759
|
+
this.beats.splice(this.beats.length - 1, 1);
|
|
2760
|
+
// insert grace beat
|
|
2761
|
+
this.addBeat(beat);
|
|
2762
|
+
// reinsert last beat
|
|
2763
|
+
this.addBeat(lastBeat);
|
|
2764
|
+
this._isEmpty = false;
|
|
2765
|
+
this._isRestOnly = false;
|
|
2766
|
+
}
|
|
2767
|
+
getBeatAtPlaybackStart(playbackStart) {
|
|
2768
|
+
if (this._beatLookup.has(playbackStart)) {
|
|
2769
|
+
return this._beatLookup.get(playbackStart);
|
|
2770
|
+
}
|
|
2771
|
+
return null;
|
|
2772
|
+
}
|
|
2773
|
+
finish(settings, sharedDataBag = null) {
|
|
2774
|
+
this._isEmpty = true;
|
|
2775
|
+
this._isRestOnly = true;
|
|
2776
|
+
this._beatLookup = new Map();
|
|
2777
|
+
let currentGraceGroup = null;
|
|
2778
|
+
for (let index = 0; index < this.beats.length; index++) {
|
|
2779
|
+
const beat = this.beats[index];
|
|
2780
|
+
beat.index = index;
|
|
2781
|
+
this.chain(beat, sharedDataBag);
|
|
2782
|
+
if (beat.graceType === GraceType.None) {
|
|
2783
|
+
beat.graceGroup = currentGraceGroup;
|
|
2784
|
+
if (currentGraceGroup) {
|
|
2785
|
+
currentGraceGroup.isComplete = true;
|
|
2786
|
+
}
|
|
2787
|
+
currentGraceGroup = null;
|
|
2788
|
+
}
|
|
2789
|
+
else {
|
|
2790
|
+
if (!currentGraceGroup) {
|
|
2791
|
+
currentGraceGroup = new GraceGroup();
|
|
2792
|
+
}
|
|
2793
|
+
currentGraceGroup.addBeat(beat);
|
|
2794
|
+
}
|
|
2795
|
+
if (!beat.isEmpty) {
|
|
2796
|
+
this._isEmpty = false;
|
|
2797
|
+
}
|
|
2798
|
+
if (!beat.isRest) {
|
|
2799
|
+
this._isRestOnly = false;
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
let currentDisplayTick = 0;
|
|
2803
|
+
let currentPlaybackTick = 0;
|
|
2804
|
+
for (let i = 0; i < this.beats.length; i++) {
|
|
2805
|
+
const beat = this.beats[i];
|
|
2806
|
+
beat.index = i;
|
|
2807
|
+
beat.finish(settings, sharedDataBag);
|
|
2808
|
+
// if this beat is a non-grace but has grace notes
|
|
2809
|
+
// we need to first steal the duration from the right beat
|
|
2810
|
+
// and place the grace beats correctly
|
|
2811
|
+
if (beat.graceType === GraceType.None) {
|
|
2812
|
+
if (beat.graceGroup) {
|
|
2813
|
+
const firstGraceBeat = beat.graceGroup.beats[0];
|
|
2814
|
+
const lastGraceBeat = beat.graceGroup.beats[beat.graceGroup.beats.length - 1];
|
|
2815
|
+
if (firstGraceBeat.graceType !== GraceType.BendGrace) {
|
|
2816
|
+
// find out the stolen duration first
|
|
2817
|
+
const stolenDuration = lastGraceBeat.playbackStart + lastGraceBeat.playbackDuration - firstGraceBeat.playbackStart;
|
|
2818
|
+
switch (firstGraceBeat.graceType) {
|
|
2819
|
+
case GraceType.BeforeBeat:
|
|
2820
|
+
// steal duration from previous beat and then place grace beats newly
|
|
2821
|
+
if (firstGraceBeat.previousBeat) {
|
|
2822
|
+
firstGraceBeat.previousBeat.playbackDuration -= stolenDuration;
|
|
2823
|
+
// place beats starting after new beat end
|
|
2824
|
+
if (firstGraceBeat.previousBeat.voice === this) {
|
|
2825
|
+
currentPlaybackTick =
|
|
2826
|
+
firstGraceBeat.previousBeat.playbackStart +
|
|
2827
|
+
firstGraceBeat.previousBeat.playbackDuration;
|
|
2828
|
+
}
|
|
2829
|
+
else {
|
|
2830
|
+
// stealing into the previous bar
|
|
2831
|
+
currentPlaybackTick = -stolenDuration;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
else {
|
|
2835
|
+
// before-beat on start is somehow not possible as it causes negative ticks
|
|
2836
|
+
currentPlaybackTick = -stolenDuration;
|
|
2837
|
+
}
|
|
2838
|
+
for (const graceBeat of beat.graceGroup.beats) {
|
|
2839
|
+
this._beatLookup.delete(graceBeat.playbackStart);
|
|
2840
|
+
graceBeat.playbackStart = currentPlaybackTick;
|
|
2841
|
+
this._beatLookup.set(graceBeat.playbackStart, beat);
|
|
2842
|
+
currentPlaybackTick += graceBeat.playbackDuration;
|
|
2843
|
+
}
|
|
2844
|
+
break;
|
|
2845
|
+
case GraceType.OnBeat:
|
|
2846
|
+
// steal duration from current beat
|
|
2847
|
+
beat.playbackDuration -= stolenDuration;
|
|
2848
|
+
if (lastGraceBeat.voice === this) {
|
|
2849
|
+
// with changed durations, update current position to be after the last grace beat
|
|
2850
|
+
currentPlaybackTick = lastGraceBeat.playbackStart + lastGraceBeat.playbackDuration;
|
|
2851
|
+
}
|
|
2852
|
+
else {
|
|
2853
|
+
// if last grace beat is on the previous bar, we shift the time back to have the note played earlier
|
|
2854
|
+
currentPlaybackTick = -stolenDuration;
|
|
2855
|
+
}
|
|
2856
|
+
break;
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
beat.displayStart = currentDisplayTick;
|
|
2861
|
+
beat.playbackStart = currentPlaybackTick;
|
|
2862
|
+
if (beat.fermata) {
|
|
2863
|
+
this.bar.masterBar.addFermata(beat.playbackStart, beat.fermata);
|
|
2864
|
+
}
|
|
2865
|
+
else {
|
|
2866
|
+
beat.fermata = this.bar.masterBar.getFermata(beat);
|
|
2867
|
+
}
|
|
2868
|
+
this._beatLookup.set(beat.playbackStart, beat);
|
|
2869
|
+
}
|
|
2870
|
+
else {
|
|
2871
|
+
beat.displayStart = currentDisplayTick;
|
|
2872
|
+
beat.playbackStart = currentPlaybackTick;
|
|
2873
|
+
}
|
|
2874
|
+
beat.finishTuplet();
|
|
2875
|
+
if (beat.graceGroup) {
|
|
2876
|
+
beat.graceGroup.finish();
|
|
2877
|
+
}
|
|
2878
|
+
currentDisplayTick += beat.displayDuration;
|
|
2879
|
+
currentPlaybackTick += beat.playbackDuration;
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
calculateDuration() {
|
|
2883
|
+
if (this.isEmpty || this.beats.length === 0) {
|
|
2884
|
+
return 0;
|
|
2885
|
+
}
|
|
2886
|
+
const lastBeat = this.beats[this.beats.length - 1];
|
|
2887
|
+
const firstBeat = this.beats[0];
|
|
2888
|
+
return lastBeat.playbackStart + lastBeat.playbackDuration - firstBeat.playbackStart;
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
Voice$1._globalVoiceId = 0;
|
|
2892
|
+
|
|
2573
2893
|
class TuningParseResult {
|
|
2574
2894
|
constructor() {
|
|
2575
2895
|
this.note = null;
|
|
@@ -2999,6 +3319,85 @@ class ModelUtils {
|
|
|
2999
3319
|
}
|
|
3000
3320
|
return headerFooterStyle;
|
|
3001
3321
|
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Performs some general consolidations of inconsistencies on the given score like
|
|
3324
|
+
* missing bars, beats, duplicated midi channels etc
|
|
3325
|
+
*/
|
|
3326
|
+
static consolidate(score) {
|
|
3327
|
+
// empty score?
|
|
3328
|
+
if (score.masterBars.length === 0) {
|
|
3329
|
+
const master = new MasterBar();
|
|
3330
|
+
score.addMasterBar(master);
|
|
3331
|
+
const tempoAutomation = new Automation();
|
|
3332
|
+
tempoAutomation.isLinear = false;
|
|
3333
|
+
tempoAutomation.type = AutomationType.Tempo;
|
|
3334
|
+
tempoAutomation.value = score.tempo;
|
|
3335
|
+
master.tempoAutomations.push(tempoAutomation);
|
|
3336
|
+
const bar = new Bar();
|
|
3337
|
+
score.tracks[0].staves[0].addBar(bar);
|
|
3338
|
+
const v = new Voice$1();
|
|
3339
|
+
bar.addVoice(v);
|
|
3340
|
+
const emptyBeat = new Beat();
|
|
3341
|
+
emptyBeat.isEmpty = true;
|
|
3342
|
+
v.addBeat(emptyBeat);
|
|
3343
|
+
return;
|
|
3344
|
+
}
|
|
3345
|
+
const usedChannels = new Set([SynthConstants.PercussionChannel]);
|
|
3346
|
+
for (const track of score.tracks) {
|
|
3347
|
+
// ensure percussion channel
|
|
3348
|
+
if (track.staves.length === 1 && track.staves[0].isPercussion) {
|
|
3349
|
+
track.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
3350
|
+
track.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
3351
|
+
}
|
|
3352
|
+
else {
|
|
3353
|
+
// unique midi channels and generate secondary channels
|
|
3354
|
+
if (track.playbackInfo.primaryChannel !== SynthConstants.PercussionChannel) {
|
|
3355
|
+
while (usedChannels.has(track.playbackInfo.primaryChannel)) {
|
|
3356
|
+
track.playbackInfo.primaryChannel++;
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
usedChannels.add(track.playbackInfo.primaryChannel);
|
|
3360
|
+
if (track.playbackInfo.secondaryChannel !== SynthConstants.PercussionChannel) {
|
|
3361
|
+
while (usedChannels.has(track.playbackInfo.secondaryChannel)) {
|
|
3362
|
+
track.playbackInfo.secondaryChannel++;
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
usedChannels.add(track.playbackInfo.secondaryChannel);
|
|
3366
|
+
}
|
|
3367
|
+
for (const staff of track.staves) {
|
|
3368
|
+
// fill empty beats
|
|
3369
|
+
for (const b of staff.bars) {
|
|
3370
|
+
for (const v of b.voices) {
|
|
3371
|
+
if (v.isEmpty && v.beats.length === 0) {
|
|
3372
|
+
const emptyBeat = new Beat();
|
|
3373
|
+
emptyBeat.isEmpty = true;
|
|
3374
|
+
v.addBeat(emptyBeat);
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
// fill missing bars
|
|
3379
|
+
const voiceCount = staff.bars.length === 0 ? 1 : staff.bars[0].voices.length;
|
|
3380
|
+
while (staff.bars.length < score.masterBars.length) {
|
|
3381
|
+
const bar = new Bar();
|
|
3382
|
+
staff.addBar(bar);
|
|
3383
|
+
const previousBar = bar.previousBar;
|
|
3384
|
+
if (previousBar) {
|
|
3385
|
+
bar.clef = previousBar.clef;
|
|
3386
|
+
bar.clefOttava = previousBar.clefOttava;
|
|
3387
|
+
bar.keySignature = bar.previousBar.keySignature;
|
|
3388
|
+
bar.keySignatureType = bar.previousBar.keySignatureType;
|
|
3389
|
+
}
|
|
3390
|
+
for (let i = 0; i < voiceCount; i++) {
|
|
3391
|
+
const v = new Voice$1();
|
|
3392
|
+
bar.addVoice(v);
|
|
3393
|
+
const emptyBeat = new Beat();
|
|
3394
|
+
emptyBeat.isEmpty = true;
|
|
3395
|
+
v.addBeat(emptyBeat);
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3002
3401
|
}
|
|
3003
3402
|
ModelUtils.TuningLetters = new Set([
|
|
3004
3403
|
0x43 /* C */, 0x44 /* D */, 0x45 /* E */, 0x46 /* F */, 0x47 /* G */, 0x41 /* A */, 0x42 /* B */, 0x63 /* c */,
|
|
@@ -5356,41 +5755,6 @@ class BeatCloner {
|
|
|
5356
5755
|
}
|
|
5357
5756
|
}
|
|
5358
5757
|
|
|
5359
|
-
/**
|
|
5360
|
-
* Represents a group of grace beats that belong together
|
|
5361
|
-
*/
|
|
5362
|
-
class GraceGroup {
|
|
5363
|
-
constructor() {
|
|
5364
|
-
/**
|
|
5365
|
-
* All beats within this group.
|
|
5366
|
-
*/
|
|
5367
|
-
this.beats = [];
|
|
5368
|
-
/**
|
|
5369
|
-
* Gets a unique ID for this grace group.
|
|
5370
|
-
*/
|
|
5371
|
-
this.id = 'empty';
|
|
5372
|
-
/**
|
|
5373
|
-
* true if the grace beat are followed by a normal beat within the same
|
|
5374
|
-
* bar.
|
|
5375
|
-
*/
|
|
5376
|
-
this.isComplete = false;
|
|
5377
|
-
}
|
|
5378
|
-
/**
|
|
5379
|
-
* Adds a new beat to this group
|
|
5380
|
-
* @param beat The beat to add
|
|
5381
|
-
*/
|
|
5382
|
-
addBeat(beat) {
|
|
5383
|
-
beat.graceIndex = this.beats.length;
|
|
5384
|
-
beat.graceGroup = this;
|
|
5385
|
-
this.beats.push(beat);
|
|
5386
|
-
}
|
|
5387
|
-
finish() {
|
|
5388
|
-
if (this.beats.length > 0) {
|
|
5389
|
-
this.id = `${this.beats[0].absoluteDisplayStart}_${this.beats[0].voice.index}`;
|
|
5390
|
-
}
|
|
5391
|
-
}
|
|
5392
|
-
}
|
|
5393
|
-
|
|
5394
5758
|
/**
|
|
5395
5759
|
* Lists all golpe types.
|
|
5396
5760
|
*/
|
|
@@ -6438,254 +6802,6 @@ class Beat {
|
|
|
6438
6802
|
}
|
|
6439
6803
|
Beat._globalBeatId = 0;
|
|
6440
6804
|
|
|
6441
|
-
/**
|
|
6442
|
-
* Lists all graphical sub elements within a {@link Voice} which can be styled via {@link Voice.style}
|
|
6443
|
-
*/
|
|
6444
|
-
var VoiceSubElement;
|
|
6445
|
-
(function (VoiceSubElement) {
|
|
6446
|
-
/**
|
|
6447
|
-
* All general glyphs (like notes heads and rests).
|
|
6448
|
-
*/
|
|
6449
|
-
VoiceSubElement[VoiceSubElement["Glyphs"] = 0] = "Glyphs";
|
|
6450
|
-
})(VoiceSubElement || (VoiceSubElement = {}));
|
|
6451
|
-
/**
|
|
6452
|
-
* Defines the custom styles for voices.
|
|
6453
|
-
* @json
|
|
6454
|
-
* @json_strict
|
|
6455
|
-
*/
|
|
6456
|
-
class VoiceStyle extends ElementStyle {
|
|
6457
|
-
}
|
|
6458
|
-
/**
|
|
6459
|
-
* A voice represents a group of beats
|
|
6460
|
-
* that can be played during a bar.
|
|
6461
|
-
* @json
|
|
6462
|
-
* @json_strict
|
|
6463
|
-
*/
|
|
6464
|
-
let Voice$1 = class Voice {
|
|
6465
|
-
constructor() {
|
|
6466
|
-
this._isEmpty = true;
|
|
6467
|
-
this._isRestOnly = true;
|
|
6468
|
-
/**
|
|
6469
|
-
* Gets or sets the unique id of this bar.
|
|
6470
|
-
*/
|
|
6471
|
-
this.id = Voice._globalVoiceId++;
|
|
6472
|
-
/**
|
|
6473
|
-
* Gets or sets the zero-based index of this voice within the bar.
|
|
6474
|
-
* @json_ignore
|
|
6475
|
-
*/
|
|
6476
|
-
this.index = 0;
|
|
6477
|
-
/**
|
|
6478
|
-
* Gets or sets the list of beats contained in this voice.
|
|
6479
|
-
* @json_add addBeat
|
|
6480
|
-
*/
|
|
6481
|
-
this.beats = [];
|
|
6482
|
-
}
|
|
6483
|
-
/**
|
|
6484
|
-
* @internal
|
|
6485
|
-
*/
|
|
6486
|
-
static resetIds() {
|
|
6487
|
-
Voice._globalVoiceId = 0;
|
|
6488
|
-
}
|
|
6489
|
-
/**
|
|
6490
|
-
* Gets or sets a value indicating whether this voice is empty.
|
|
6491
|
-
*/
|
|
6492
|
-
get isEmpty() {
|
|
6493
|
-
return this._isEmpty;
|
|
6494
|
-
}
|
|
6495
|
-
/**
|
|
6496
|
-
* @internal
|
|
6497
|
-
*/
|
|
6498
|
-
forceNonEmpty() {
|
|
6499
|
-
this._isEmpty = false;
|
|
6500
|
-
}
|
|
6501
|
-
/**
|
|
6502
|
-
* Gets or sets a value indicating whether this voice is empty.
|
|
6503
|
-
*/
|
|
6504
|
-
get isRestOnly() {
|
|
6505
|
-
return this._isRestOnly;
|
|
6506
|
-
}
|
|
6507
|
-
insertBeat(after, newBeat) {
|
|
6508
|
-
newBeat.nextBeat = after.nextBeat;
|
|
6509
|
-
if (newBeat.nextBeat) {
|
|
6510
|
-
newBeat.nextBeat.previousBeat = newBeat;
|
|
6511
|
-
}
|
|
6512
|
-
newBeat.previousBeat = after;
|
|
6513
|
-
newBeat.voice = this;
|
|
6514
|
-
after.nextBeat = newBeat;
|
|
6515
|
-
this.beats.splice(after.index + 1, 0, newBeat);
|
|
6516
|
-
}
|
|
6517
|
-
addBeat(beat) {
|
|
6518
|
-
beat.voice = this;
|
|
6519
|
-
beat.index = this.beats.length;
|
|
6520
|
-
this.beats.push(beat);
|
|
6521
|
-
if (!beat.isEmpty) {
|
|
6522
|
-
this._isEmpty = false;
|
|
6523
|
-
}
|
|
6524
|
-
if (!beat.isRest) {
|
|
6525
|
-
this._isRestOnly = false;
|
|
6526
|
-
}
|
|
6527
|
-
}
|
|
6528
|
-
chain(beat, sharedDataBag = null) {
|
|
6529
|
-
if (!this.bar) {
|
|
6530
|
-
return;
|
|
6531
|
-
}
|
|
6532
|
-
if (beat.index < this.beats.length - 1) {
|
|
6533
|
-
beat.nextBeat = this.beats[beat.index + 1];
|
|
6534
|
-
beat.nextBeat.previousBeat = beat;
|
|
6535
|
-
}
|
|
6536
|
-
else if (beat.isLastOfVoice && beat.voice.bar.nextBar) {
|
|
6537
|
-
const nextVoice = this.bar.nextBar.voices[this.index];
|
|
6538
|
-
if (nextVoice.beats.length > 0) {
|
|
6539
|
-
beat.nextBeat = nextVoice.beats[0];
|
|
6540
|
-
beat.nextBeat.previousBeat = beat;
|
|
6541
|
-
}
|
|
6542
|
-
else {
|
|
6543
|
-
beat.nextBeat.previousBeat = beat;
|
|
6544
|
-
}
|
|
6545
|
-
}
|
|
6546
|
-
beat.chain(sharedDataBag);
|
|
6547
|
-
}
|
|
6548
|
-
addGraceBeat(beat) {
|
|
6549
|
-
if (this.beats.length === 0) {
|
|
6550
|
-
this.addBeat(beat);
|
|
6551
|
-
return;
|
|
6552
|
-
}
|
|
6553
|
-
// remove last beat
|
|
6554
|
-
const lastBeat = this.beats[this.beats.length - 1];
|
|
6555
|
-
this.beats.splice(this.beats.length - 1, 1);
|
|
6556
|
-
// insert grace beat
|
|
6557
|
-
this.addBeat(beat);
|
|
6558
|
-
// reinsert last beat
|
|
6559
|
-
this.addBeat(lastBeat);
|
|
6560
|
-
this._isEmpty = false;
|
|
6561
|
-
this._isRestOnly = false;
|
|
6562
|
-
}
|
|
6563
|
-
getBeatAtPlaybackStart(playbackStart) {
|
|
6564
|
-
if (this._beatLookup.has(playbackStart)) {
|
|
6565
|
-
return this._beatLookup.get(playbackStart);
|
|
6566
|
-
}
|
|
6567
|
-
return null;
|
|
6568
|
-
}
|
|
6569
|
-
finish(settings, sharedDataBag = null) {
|
|
6570
|
-
this._isEmpty = true;
|
|
6571
|
-
this._isRestOnly = true;
|
|
6572
|
-
this._beatLookup = new Map();
|
|
6573
|
-
let currentGraceGroup = null;
|
|
6574
|
-
for (let index = 0; index < this.beats.length; index++) {
|
|
6575
|
-
const beat = this.beats[index];
|
|
6576
|
-
beat.index = index;
|
|
6577
|
-
this.chain(beat, sharedDataBag);
|
|
6578
|
-
if (beat.graceType === GraceType.None) {
|
|
6579
|
-
beat.graceGroup = currentGraceGroup;
|
|
6580
|
-
if (currentGraceGroup) {
|
|
6581
|
-
currentGraceGroup.isComplete = true;
|
|
6582
|
-
}
|
|
6583
|
-
currentGraceGroup = null;
|
|
6584
|
-
}
|
|
6585
|
-
else {
|
|
6586
|
-
if (!currentGraceGroup) {
|
|
6587
|
-
currentGraceGroup = new GraceGroup();
|
|
6588
|
-
}
|
|
6589
|
-
currentGraceGroup.addBeat(beat);
|
|
6590
|
-
}
|
|
6591
|
-
if (!beat.isEmpty) {
|
|
6592
|
-
this._isEmpty = false;
|
|
6593
|
-
}
|
|
6594
|
-
if (!beat.isRest) {
|
|
6595
|
-
this._isRestOnly = false;
|
|
6596
|
-
}
|
|
6597
|
-
}
|
|
6598
|
-
let currentDisplayTick = 0;
|
|
6599
|
-
let currentPlaybackTick = 0;
|
|
6600
|
-
for (let i = 0; i < this.beats.length; i++) {
|
|
6601
|
-
const beat = this.beats[i];
|
|
6602
|
-
beat.index = i;
|
|
6603
|
-
beat.finish(settings, sharedDataBag);
|
|
6604
|
-
// if this beat is a non-grace but has grace notes
|
|
6605
|
-
// we need to first steal the duration from the right beat
|
|
6606
|
-
// and place the grace beats correctly
|
|
6607
|
-
if (beat.graceType === GraceType.None) {
|
|
6608
|
-
if (beat.graceGroup) {
|
|
6609
|
-
const firstGraceBeat = beat.graceGroup.beats[0];
|
|
6610
|
-
const lastGraceBeat = beat.graceGroup.beats[beat.graceGroup.beats.length - 1];
|
|
6611
|
-
if (firstGraceBeat.graceType !== GraceType.BendGrace) {
|
|
6612
|
-
// find out the stolen duration first
|
|
6613
|
-
const stolenDuration = lastGraceBeat.playbackStart + lastGraceBeat.playbackDuration - firstGraceBeat.playbackStart;
|
|
6614
|
-
switch (firstGraceBeat.graceType) {
|
|
6615
|
-
case GraceType.BeforeBeat:
|
|
6616
|
-
// steal duration from previous beat and then place grace beats newly
|
|
6617
|
-
if (firstGraceBeat.previousBeat) {
|
|
6618
|
-
firstGraceBeat.previousBeat.playbackDuration -= stolenDuration;
|
|
6619
|
-
// place beats starting after new beat end
|
|
6620
|
-
if (firstGraceBeat.previousBeat.voice === this) {
|
|
6621
|
-
currentPlaybackTick =
|
|
6622
|
-
firstGraceBeat.previousBeat.playbackStart +
|
|
6623
|
-
firstGraceBeat.previousBeat.playbackDuration;
|
|
6624
|
-
}
|
|
6625
|
-
else {
|
|
6626
|
-
// stealing into the previous bar
|
|
6627
|
-
currentPlaybackTick = -stolenDuration;
|
|
6628
|
-
}
|
|
6629
|
-
}
|
|
6630
|
-
else {
|
|
6631
|
-
// before-beat on start is somehow not possible as it causes negative ticks
|
|
6632
|
-
currentPlaybackTick = -stolenDuration;
|
|
6633
|
-
}
|
|
6634
|
-
for (const graceBeat of beat.graceGroup.beats) {
|
|
6635
|
-
this._beatLookup.delete(graceBeat.playbackStart);
|
|
6636
|
-
graceBeat.playbackStart = currentPlaybackTick;
|
|
6637
|
-
this._beatLookup.set(graceBeat.playbackStart, beat);
|
|
6638
|
-
currentPlaybackTick += graceBeat.playbackDuration;
|
|
6639
|
-
}
|
|
6640
|
-
break;
|
|
6641
|
-
case GraceType.OnBeat:
|
|
6642
|
-
// steal duration from current beat
|
|
6643
|
-
beat.playbackDuration -= stolenDuration;
|
|
6644
|
-
if (lastGraceBeat.voice === this) {
|
|
6645
|
-
// with changed durations, update current position to be after the last grace beat
|
|
6646
|
-
currentPlaybackTick = lastGraceBeat.playbackStart + lastGraceBeat.playbackDuration;
|
|
6647
|
-
}
|
|
6648
|
-
else {
|
|
6649
|
-
// if last grace beat is on the previous bar, we shift the time back to have the note played earlier
|
|
6650
|
-
currentPlaybackTick = -stolenDuration;
|
|
6651
|
-
}
|
|
6652
|
-
break;
|
|
6653
|
-
}
|
|
6654
|
-
}
|
|
6655
|
-
}
|
|
6656
|
-
beat.displayStart = currentDisplayTick;
|
|
6657
|
-
beat.playbackStart = currentPlaybackTick;
|
|
6658
|
-
if (beat.fermata) {
|
|
6659
|
-
this.bar.masterBar.addFermata(beat.playbackStart, beat.fermata);
|
|
6660
|
-
}
|
|
6661
|
-
else {
|
|
6662
|
-
beat.fermata = this.bar.masterBar.getFermata(beat);
|
|
6663
|
-
}
|
|
6664
|
-
this._beatLookup.set(beat.playbackStart, beat);
|
|
6665
|
-
}
|
|
6666
|
-
else {
|
|
6667
|
-
beat.displayStart = currentDisplayTick;
|
|
6668
|
-
beat.playbackStart = currentPlaybackTick;
|
|
6669
|
-
}
|
|
6670
|
-
beat.finishTuplet();
|
|
6671
|
-
if (beat.graceGroup) {
|
|
6672
|
-
beat.graceGroup.finish();
|
|
6673
|
-
}
|
|
6674
|
-
currentDisplayTick += beat.displayDuration;
|
|
6675
|
-
currentPlaybackTick += beat.playbackDuration;
|
|
6676
|
-
}
|
|
6677
|
-
}
|
|
6678
|
-
calculateDuration() {
|
|
6679
|
-
if (this.isEmpty || this.beats.length === 0) {
|
|
6680
|
-
return 0;
|
|
6681
|
-
}
|
|
6682
|
-
const lastBeat = this.beats[this.beats.length - 1];
|
|
6683
|
-
const firstBeat = this.beats[0];
|
|
6684
|
-
return lastBeat.playbackStart + lastBeat.playbackDuration - firstBeat.playbackStart;
|
|
6685
|
-
}
|
|
6686
|
-
};
|
|
6687
|
-
Voice$1._globalVoiceId = 0;
|
|
6688
|
-
|
|
6689
6805
|
/**
|
|
6690
6806
|
* Lists all graphical sub elements within a {@link Score} which can be styled via {@link Score.style}
|
|
6691
6807
|
*/
|
|
@@ -8168,38 +8284,6 @@ class ByteBuffer {
|
|
|
8168
8284
|
}
|
|
8169
8285
|
}
|
|
8170
8286
|
|
|
8171
|
-
// The SoundFont loading and Audio Synthesis is based on TinySoundFont, licensed under MIT,
|
|
8172
|
-
// developed by Bernhard Schelling (https://github.com/schellingb/TinySoundFont)
|
|
8173
|
-
// TypeScript port for alphaTab: (C) 2020 by Daniel Kuschny
|
|
8174
|
-
// Licensed under: MPL-2.0
|
|
8175
|
-
class SynthConstants {
|
|
8176
|
-
}
|
|
8177
|
-
SynthConstants.DefaultChannelCount = 16 + 1;
|
|
8178
|
-
SynthConstants.MetronomeChannel = SynthConstants.DefaultChannelCount - 1;
|
|
8179
|
-
SynthConstants.MetronomeKey = 33;
|
|
8180
|
-
SynthConstants.AudioChannels = 2;
|
|
8181
|
-
SynthConstants.MinVolume = 0;
|
|
8182
|
-
SynthConstants.MinProgram = 0;
|
|
8183
|
-
SynthConstants.MaxProgram = 127;
|
|
8184
|
-
SynthConstants.MinPlaybackSpeed = 0.125;
|
|
8185
|
-
SynthConstants.MaxPlaybackSpeed = 8;
|
|
8186
|
-
SynthConstants.PercussionChannel = 9;
|
|
8187
|
-
SynthConstants.PercussionBank = 128;
|
|
8188
|
-
/**
|
|
8189
|
-
* The Midi Pitch bend message is a 15-bit value
|
|
8190
|
-
*/
|
|
8191
|
-
SynthConstants.MaxPitchWheel = 0x4000;
|
|
8192
|
-
/**
|
|
8193
|
-
* The Midi 2.0 Pitch bend message is a 32-bit value
|
|
8194
|
-
*/
|
|
8195
|
-
SynthConstants.MaxPitchWheel20 = 0x100000000;
|
|
8196
|
-
/**
|
|
8197
|
-
* The pitch wheel value for no pitch change at all.
|
|
8198
|
-
*/
|
|
8199
|
-
SynthConstants.DefaultPitchWheel = SynthConstants.MaxPitchWheel / 2;
|
|
8200
|
-
SynthConstants.MicroBufferCount = 32;
|
|
8201
|
-
SynthConstants.MicroBufferSize = 64;
|
|
8202
|
-
|
|
8203
8287
|
/**
|
|
8204
8288
|
* Lists all directions which can be applied to a masterbar.
|
|
8205
8289
|
*/
|
|
@@ -8404,7 +8488,7 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
8404
8488
|
throw new UnsupportedFormatError('No alphaTex data found');
|
|
8405
8489
|
}
|
|
8406
8490
|
}
|
|
8407
|
-
|
|
8491
|
+
ModelUtils.consolidate(this._score);
|
|
8408
8492
|
this._score.finish(this.settings);
|
|
8409
8493
|
this._score.rebuildRepeatGroups();
|
|
8410
8494
|
for (const [track, lyrics] of this._lyrics) {
|
|
@@ -8423,57 +8507,6 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
8423
8507
|
throw e;
|
|
8424
8508
|
}
|
|
8425
8509
|
}
|
|
8426
|
-
/**
|
|
8427
|
-
* Ensures all staffs of all tracks have the correct number of bars
|
|
8428
|
-
* (the number of bars per staff and track could be inconsistent)
|
|
8429
|
-
*/
|
|
8430
|
-
consolidate() {
|
|
8431
|
-
// empty score?
|
|
8432
|
-
if (this._score.masterBars.length === 0) {
|
|
8433
|
-
const master = new MasterBar();
|
|
8434
|
-
this._score.addMasterBar(master);
|
|
8435
|
-
const tempoAutomation = new Automation();
|
|
8436
|
-
tempoAutomation.isLinear = false;
|
|
8437
|
-
tempoAutomation.type = AutomationType.Tempo;
|
|
8438
|
-
tempoAutomation.value = this._score.tempo;
|
|
8439
|
-
master.tempoAutomations.push(tempoAutomation);
|
|
8440
|
-
const bar = new Bar();
|
|
8441
|
-
this._score.tracks[0].staves[0].addBar(bar);
|
|
8442
|
-
const v = new Voice$1();
|
|
8443
|
-
bar.addVoice(v);
|
|
8444
|
-
const emptyBeat = new Beat();
|
|
8445
|
-
emptyBeat.isEmpty = true;
|
|
8446
|
-
v.addBeat(emptyBeat);
|
|
8447
|
-
return;
|
|
8448
|
-
}
|
|
8449
|
-
for (const track of this._score.tracks) {
|
|
8450
|
-
for (const staff of track.staves) {
|
|
8451
|
-
// fill empty beats
|
|
8452
|
-
for (const b of staff.bars) {
|
|
8453
|
-
for (const v of b.voices) {
|
|
8454
|
-
if (v.isEmpty && v.beats.length === 0) {
|
|
8455
|
-
const emptyBeat = new Beat();
|
|
8456
|
-
emptyBeat.isEmpty = true;
|
|
8457
|
-
v.addBeat(emptyBeat);
|
|
8458
|
-
}
|
|
8459
|
-
}
|
|
8460
|
-
}
|
|
8461
|
-
// fill missing bars
|
|
8462
|
-
const voiceCount = staff.bars.length === 0 ? 1 : staff.bars[0].voices.length;
|
|
8463
|
-
while (staff.bars.length < this._score.masterBars.length) {
|
|
8464
|
-
const bar = new Bar();
|
|
8465
|
-
staff.addBar(bar);
|
|
8466
|
-
for (let i = 0; i < voiceCount; i++) {
|
|
8467
|
-
const v = new Voice$1();
|
|
8468
|
-
bar.addVoice(v);
|
|
8469
|
-
const emptyBeat = new Beat();
|
|
8470
|
-
emptyBeat.isEmpty = true;
|
|
8471
|
-
v.addBeat(emptyBeat);
|
|
8472
|
-
}
|
|
8473
|
-
}
|
|
8474
|
-
}
|
|
8475
|
-
}
|
|
8476
|
-
}
|
|
8477
8510
|
error(nonterm, expected, wrongSymbol = true) {
|
|
8478
8511
|
let receivedSymbol;
|
|
8479
8512
|
let showSyData = false;
|
|
@@ -11597,6 +11630,7 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
11597
11630
|
automation.text = this._score.tempoLabel;
|
|
11598
11631
|
this._score.masterBars[0].tempoAutomations.push(automation);
|
|
11599
11632
|
}
|
|
11633
|
+
ModelUtils.consolidate(this._score);
|
|
11600
11634
|
this._score.finish(this.settings);
|
|
11601
11635
|
if (this._lyrics && this._lyricsTrack >= 0) {
|
|
11602
11636
|
this._score.tracks[this._lyricsTrack].applyLyrics(this._lyrics);
|
|
@@ -11715,10 +11749,11 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
11715
11749
|
}
|
|
11716
11750
|
readPlaybackInfos() {
|
|
11717
11751
|
this._playbackInfos = [];
|
|
11752
|
+
let channel = 0;
|
|
11718
11753
|
for (let i = 0; i < 64; i++) {
|
|
11719
11754
|
const info = new PlaybackInformation();
|
|
11720
|
-
info.primaryChannel =
|
|
11721
|
-
info.secondaryChannel =
|
|
11755
|
+
info.primaryChannel = channel++;
|
|
11756
|
+
info.secondaryChannel = channel++;
|
|
11722
11757
|
info.program = IOHelper.readInt32LE(this.data);
|
|
11723
11758
|
info.volume = this.data.readByte();
|
|
11724
11759
|
info.balance = this.data.readByte();
|
|
@@ -14150,6 +14185,7 @@ class GpifParser {
|
|
|
14150
14185
|
}
|
|
14151
14186
|
this.parseDom(dom);
|
|
14152
14187
|
this.buildModel();
|
|
14188
|
+
ModelUtils.consolidate(this.score);
|
|
14153
14189
|
this.score.finish(settings);
|
|
14154
14190
|
if (!this._skipApplyLyrics && this._lyricsByTrack.size > 0) {
|
|
14155
14191
|
for (const [t, lyrics] of this._lyricsByTrack) {
|
|
@@ -14213,26 +14249,26 @@ class GpifParser {
|
|
|
14213
14249
|
for (const c of element.childElements()) {
|
|
14214
14250
|
switch (c.localName) {
|
|
14215
14251
|
case 'Title':
|
|
14216
|
-
this.score.title = c.
|
|
14252
|
+
this.score.title = c.innerText;
|
|
14217
14253
|
break;
|
|
14218
14254
|
case 'SubTitle':
|
|
14219
|
-
this.score.subTitle = c.
|
|
14255
|
+
this.score.subTitle = c.innerText;
|
|
14220
14256
|
break;
|
|
14221
14257
|
case 'Artist':
|
|
14222
|
-
this.score.artist = c.
|
|
14258
|
+
this.score.artist = c.innerText;
|
|
14223
14259
|
break;
|
|
14224
14260
|
case 'Album':
|
|
14225
|
-
this.score.album = c.
|
|
14261
|
+
this.score.album = c.innerText;
|
|
14226
14262
|
break;
|
|
14227
14263
|
case 'Words':
|
|
14228
|
-
this.score.words = c.
|
|
14264
|
+
this.score.words = c.innerText;
|
|
14229
14265
|
break;
|
|
14230
14266
|
case 'Music':
|
|
14231
|
-
this.score.music = c.
|
|
14267
|
+
this.score.music = c.innerText;
|
|
14232
14268
|
break;
|
|
14233
14269
|
case 'WordsAndMusic':
|
|
14234
|
-
|
|
14235
|
-
|
|
14270
|
+
const wordsAndMusic = c.innerText;
|
|
14271
|
+
if (wordsAndMusic !== '') {
|
|
14236
14272
|
if (wordsAndMusic && !this.score.words) {
|
|
14237
14273
|
this.score.words = wordsAndMusic;
|
|
14238
14274
|
}
|
|
@@ -14242,26 +14278,52 @@ class GpifParser {
|
|
|
14242
14278
|
}
|
|
14243
14279
|
break;
|
|
14244
14280
|
case 'Copyright':
|
|
14245
|
-
this.score.copyright = c.
|
|
14281
|
+
this.score.copyright = c.innerText;
|
|
14246
14282
|
break;
|
|
14247
14283
|
case 'Tabber':
|
|
14248
|
-
this.score.tab = c.
|
|
14284
|
+
this.score.tab = c.innerText;
|
|
14249
14285
|
break;
|
|
14250
14286
|
case 'Instructions':
|
|
14251
|
-
this.score.instructions = c.
|
|
14287
|
+
this.score.instructions = c.innerText;
|
|
14252
14288
|
break;
|
|
14253
14289
|
case 'Notices':
|
|
14254
|
-
this.score.notices = c.
|
|
14290
|
+
this.score.notices = c.innerText;
|
|
14255
14291
|
break;
|
|
14256
14292
|
case 'ScoreSystemsDefaultLayout':
|
|
14257
|
-
this.score.defaultSystemsLayout =
|
|
14293
|
+
this.score.defaultSystemsLayout = GpifParser.parseIntSafe(c.innerText, 4);
|
|
14258
14294
|
break;
|
|
14259
14295
|
case 'ScoreSystemsLayout':
|
|
14260
|
-
this.score.systemsLayout = c.innerText
|
|
14296
|
+
this.score.systemsLayout = GpifParser.splitSafe(c.innerText).map(i => GpifParser.parseIntSafe(i, 4));
|
|
14261
14297
|
break;
|
|
14262
14298
|
}
|
|
14263
14299
|
}
|
|
14264
14300
|
}
|
|
14301
|
+
static parseIntSafe(text, fallback) {
|
|
14302
|
+
if (!text) {
|
|
14303
|
+
return fallback;
|
|
14304
|
+
}
|
|
14305
|
+
const i = Number.parseInt(text);
|
|
14306
|
+
if (!Number.isNaN(i)) {
|
|
14307
|
+
return i;
|
|
14308
|
+
}
|
|
14309
|
+
return fallback;
|
|
14310
|
+
}
|
|
14311
|
+
static parseFloatSafe(text, fallback) {
|
|
14312
|
+
if (!text) {
|
|
14313
|
+
return fallback;
|
|
14314
|
+
}
|
|
14315
|
+
const i = Number.parseFloat(text);
|
|
14316
|
+
if (!Number.isNaN(i)) {
|
|
14317
|
+
return i;
|
|
14318
|
+
}
|
|
14319
|
+
return fallback;
|
|
14320
|
+
}
|
|
14321
|
+
static splitSafe(text, separator = ' ') {
|
|
14322
|
+
if (!text) {
|
|
14323
|
+
return [];
|
|
14324
|
+
}
|
|
14325
|
+
return text.split(separator).map(t => t.trim()).filter(t => t.length > 0);
|
|
14326
|
+
}
|
|
14265
14327
|
//
|
|
14266
14328
|
// <MasterTrack>...</MasterTrack>
|
|
14267
14329
|
//
|
|
@@ -14272,7 +14334,7 @@ class GpifParser {
|
|
|
14272
14334
|
this.parseAutomations(c, this._masterTrackAutomations, null, null);
|
|
14273
14335
|
break;
|
|
14274
14336
|
case 'Tracks':
|
|
14275
|
-
this._tracksMapping = c.innerText
|
|
14337
|
+
this._tracksMapping = GpifParser.splitSafe(c.innerText);
|
|
14276
14338
|
break;
|
|
14277
14339
|
case 'Anacrusis':
|
|
14278
14340
|
this._hasAnacrusis = true;
|
|
@@ -14307,26 +14369,26 @@ class GpifParser {
|
|
|
14307
14369
|
isLinear = c.innerText.toLowerCase() === 'true';
|
|
14308
14370
|
break;
|
|
14309
14371
|
case 'Bar':
|
|
14310
|
-
barIndex =
|
|
14372
|
+
barIndex = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14311
14373
|
break;
|
|
14312
14374
|
case 'Position':
|
|
14313
|
-
ratioPosition =
|
|
14375
|
+
ratioPosition = GpifParser.parseFloatSafe(c.innerText, 0);
|
|
14314
14376
|
break;
|
|
14315
14377
|
case 'Value':
|
|
14316
14378
|
if (c.firstElement && c.firstElement.nodeType === XmlNodeType.CDATA) {
|
|
14317
14379
|
textValue = c.innerText;
|
|
14318
14380
|
}
|
|
14319
14381
|
else {
|
|
14320
|
-
const parts = c.innerText
|
|
14382
|
+
const parts = GpifParser.splitSafe(c.innerText);
|
|
14321
14383
|
// Issue 391: Some GPX files might have
|
|
14322
14384
|
// single floating point value.
|
|
14323
14385
|
if (parts.length === 1) {
|
|
14324
|
-
numberValue =
|
|
14386
|
+
numberValue = GpifParser.parseFloatSafe(parts[0], 0);
|
|
14325
14387
|
reference = 1;
|
|
14326
14388
|
}
|
|
14327
14389
|
else {
|
|
14328
|
-
numberValue =
|
|
14329
|
-
reference =
|
|
14390
|
+
numberValue = GpifParser.parseFloatSafe(parts[0], 0);
|
|
14391
|
+
reference = GpifParser.parseIntSafe(parts[1], 0);
|
|
14330
14392
|
}
|
|
14331
14393
|
}
|
|
14332
14394
|
break;
|
|
@@ -14410,11 +14472,11 @@ class GpifParser {
|
|
|
14410
14472
|
track.name = c.innerText;
|
|
14411
14473
|
break;
|
|
14412
14474
|
case 'Color':
|
|
14413
|
-
const parts = c.innerText
|
|
14475
|
+
const parts = GpifParser.splitSafe(c.innerText);
|
|
14414
14476
|
if (parts.length >= 3) {
|
|
14415
|
-
const r =
|
|
14416
|
-
const g =
|
|
14417
|
-
const b =
|
|
14477
|
+
const r = GpifParser.parseIntSafe(parts[0], 0);
|
|
14478
|
+
const g = GpifParser.parseIntSafe(parts[1], 0);
|
|
14479
|
+
const b = GpifParser.parseIntSafe(parts[2], 0);
|
|
14418
14480
|
track.color = new Color(r, g, b, 0xff);
|
|
14419
14481
|
}
|
|
14420
14482
|
break;
|
|
@@ -14435,10 +14497,10 @@ class GpifParser {
|
|
|
14435
14497
|
track.shortName = c.innerText;
|
|
14436
14498
|
break;
|
|
14437
14499
|
case 'SystemsDefautLayout': // not a typo by alphaTab, this is a typo in the GPIF files.
|
|
14438
|
-
track.defaultSystemsLayout =
|
|
14500
|
+
track.defaultSystemsLayout = GpifParser.parseIntSafe(c.innerText, 4);
|
|
14439
14501
|
break;
|
|
14440
14502
|
case 'SystemsLayout':
|
|
14441
|
-
track.systemsLayout = c.innerText
|
|
14503
|
+
track.systemsLayout = GpifParser.splitSafe(c.innerText).map(i => GpifParser.parseIntSafe(i, 4));
|
|
14442
14504
|
break;
|
|
14443
14505
|
case 'Lyrics':
|
|
14444
14506
|
this.parseLyrics(trackId, c);
|
|
@@ -14489,7 +14551,7 @@ class GpifParser {
|
|
|
14489
14551
|
for (const c of node.childElements()) {
|
|
14490
14552
|
switch (c.localName) {
|
|
14491
14553
|
case 'LineCount':
|
|
14492
|
-
const lineCount =
|
|
14554
|
+
const lineCount = GpifParser.parseIntSafe(c.innerText, 5);
|
|
14493
14555
|
for (const staff of track.staves) {
|
|
14494
14556
|
staff.standardNotationLineCount = lineCount;
|
|
14495
14557
|
}
|
|
@@ -14504,13 +14566,6 @@ class GpifParser {
|
|
|
14504
14566
|
for (const c of node.childElements()) {
|
|
14505
14567
|
switch (c.localName) {
|
|
14506
14568
|
case 'Type':
|
|
14507
|
-
switch (c.innerText) {
|
|
14508
|
-
case 'drumKit':
|
|
14509
|
-
for (const staff of track.staves) {
|
|
14510
|
-
staff.isPercussion = true;
|
|
14511
|
-
}
|
|
14512
|
-
break;
|
|
14513
|
-
}
|
|
14514
14569
|
if (c.innerText === 'drumKit') {
|
|
14515
14570
|
for (const staff of track.staves) {
|
|
14516
14571
|
staff.isPercussion = true;
|
|
@@ -14521,7 +14576,7 @@ class GpifParser {
|
|
|
14521
14576
|
this.parseElements(track, c);
|
|
14522
14577
|
break;
|
|
14523
14578
|
case 'LineCount':
|
|
14524
|
-
const lineCount =
|
|
14579
|
+
const lineCount = GpifParser.parseIntSafe(c.innerText, 5);
|
|
14525
14580
|
for (const staff of track.staves) {
|
|
14526
14581
|
staff.standardNotationLineCount = lineCount;
|
|
14527
14582
|
}
|
|
@@ -14539,8 +14594,7 @@ class GpifParser {
|
|
|
14539
14594
|
}
|
|
14540
14595
|
}
|
|
14541
14596
|
parseElement(track, node) {
|
|
14542
|
-
const
|
|
14543
|
-
const type = typeElement ? typeElement.innerText : '';
|
|
14597
|
+
const type = node.findChildElement('Type')?.innerText ?? '';
|
|
14544
14598
|
for (const c of node.childElements()) {
|
|
14545
14599
|
switch (c.localName) {
|
|
14546
14600
|
case 'Name':
|
|
@@ -14571,9 +14625,7 @@ class GpifParser {
|
|
|
14571
14625
|
name = c.innerText;
|
|
14572
14626
|
break;
|
|
14573
14627
|
case 'OutputMidiNumber':
|
|
14574
|
-
|
|
14575
|
-
articulation.outputMidiNumber = Number.parseInt(txt);
|
|
14576
|
-
}
|
|
14628
|
+
articulation.outputMidiNumber = GpifParser.parseIntSafe(txt, 0);
|
|
14577
14629
|
break;
|
|
14578
14630
|
case 'TechniqueSymbol':
|
|
14579
14631
|
articulation.techniqueSymbol = this.parseTechniqueSymbol(txt);
|
|
@@ -14595,7 +14647,7 @@ class GpifParser {
|
|
|
14595
14647
|
}
|
|
14596
14648
|
break;
|
|
14597
14649
|
case 'Noteheads':
|
|
14598
|
-
const noteHeadsTxt =
|
|
14650
|
+
const noteHeadsTxt = GpifParser.splitSafe(txt);
|
|
14599
14651
|
if (noteHeadsTxt.length >= 1) {
|
|
14600
14652
|
articulation.noteHeadDefault = this.parseNoteHead(noteHeadsTxt[0]);
|
|
14601
14653
|
}
|
|
@@ -14613,9 +14665,7 @@ class GpifParser {
|
|
|
14613
14665
|
}
|
|
14614
14666
|
break;
|
|
14615
14667
|
case 'StaffLine':
|
|
14616
|
-
|
|
14617
|
-
articulation.staffLine = Number.parseInt(txt);
|
|
14618
|
-
}
|
|
14668
|
+
articulation.staffLine = GpifParser.parseIntSafe(txt, 0);
|
|
14619
14669
|
break;
|
|
14620
14670
|
}
|
|
14621
14671
|
}
|
|
@@ -14736,10 +14786,10 @@ class GpifParser {
|
|
|
14736
14786
|
for (const c of node.childElements()) {
|
|
14737
14787
|
switch (c.localName) {
|
|
14738
14788
|
case 'Pitches':
|
|
14739
|
-
const tuningParts = node.findChildElement('Pitches')
|
|
14789
|
+
const tuningParts = GpifParser.splitSafe(node.findChildElement('Pitches')?.innerText);
|
|
14740
14790
|
const tuning = new Array(tuningParts.length);
|
|
14741
14791
|
for (let i = 0; i < tuning.length; i++) {
|
|
14742
|
-
tuning[tuning.length - 1 - i] =
|
|
14792
|
+
tuning[tuning.length - 1 - i] = GpifParser.parseIntSafe(tuningParts[i], 0);
|
|
14743
14793
|
}
|
|
14744
14794
|
staff.stringTuning.tunings = tuning;
|
|
14745
14795
|
break;
|
|
@@ -14757,7 +14807,7 @@ class GpifParser {
|
|
|
14757
14807
|
this.parseDiagramCollectionForStaff(staff, node);
|
|
14758
14808
|
break;
|
|
14759
14809
|
case 'CapoFret':
|
|
14760
|
-
const capo =
|
|
14810
|
+
const capo = GpifParser.parseIntSafe(node.findChildElement('Fret')?.innerText, 0);
|
|
14761
14811
|
staff.capo = capo;
|
|
14762
14812
|
break;
|
|
14763
14813
|
}
|
|
@@ -14778,7 +14828,7 @@ class GpifParser {
|
|
|
14778
14828
|
for (const c of node.childElements()) {
|
|
14779
14829
|
switch (c.localName) {
|
|
14780
14830
|
case 'Offset':
|
|
14781
|
-
lyrics.startBar =
|
|
14831
|
+
lyrics.startBar = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14782
14832
|
break;
|
|
14783
14833
|
case 'Text':
|
|
14784
14834
|
lyrics.text = c.innerText;
|
|
@@ -14789,21 +14839,25 @@ class GpifParser {
|
|
|
14789
14839
|
}
|
|
14790
14840
|
parseDiagramCollectionForTrack(track, node) {
|
|
14791
14841
|
const items = node.findChildElement('Items');
|
|
14792
|
-
|
|
14793
|
-
|
|
14794
|
-
|
|
14795
|
-
|
|
14796
|
-
|
|
14842
|
+
if (items) {
|
|
14843
|
+
for (const c of items.childElements()) {
|
|
14844
|
+
switch (c.localName) {
|
|
14845
|
+
case 'Item':
|
|
14846
|
+
this.parseDiagramItemForTrack(track, c);
|
|
14847
|
+
break;
|
|
14848
|
+
}
|
|
14797
14849
|
}
|
|
14798
14850
|
}
|
|
14799
14851
|
}
|
|
14800
14852
|
parseDiagramCollectionForStaff(staff, node) {
|
|
14801
14853
|
const items = node.findChildElement('Items');
|
|
14802
|
-
|
|
14803
|
-
|
|
14804
|
-
|
|
14805
|
-
|
|
14806
|
-
|
|
14854
|
+
if (items) {
|
|
14855
|
+
for (const c of items.childElements()) {
|
|
14856
|
+
switch (c.localName) {
|
|
14857
|
+
case 'Item':
|
|
14858
|
+
this.parseDiagramItemForStaff(staff, c);
|
|
14859
|
+
break;
|
|
14860
|
+
}
|
|
14807
14861
|
}
|
|
14808
14862
|
}
|
|
14809
14863
|
}
|
|
@@ -14829,10 +14883,8 @@ class GpifParser {
|
|
|
14829
14883
|
chord.showFingering = false;
|
|
14830
14884
|
return;
|
|
14831
14885
|
}
|
|
14832
|
-
const stringCount =
|
|
14833
|
-
const baseFret = diagram.
|
|
14834
|
-
? Number.parseInt(diagram.getAttribute('baseFret'))
|
|
14835
|
-
: 0;
|
|
14886
|
+
const stringCount = GpifParser.parseIntSafe(diagram.getAttribute('stringCount'), 6);
|
|
14887
|
+
const baseFret = GpifParser.parseIntSafe(diagram.getAttribute('baseFret'), 0);
|
|
14836
14888
|
chord.firstFret = baseFret + 1;
|
|
14837
14889
|
for (let i = 0; i < stringCount; i++) {
|
|
14838
14890
|
chord.strings.push(-1);
|
|
@@ -14840,8 +14892,9 @@ class GpifParser {
|
|
|
14840
14892
|
for (const c of diagram.childElements()) {
|
|
14841
14893
|
switch (c.localName) {
|
|
14842
14894
|
case 'Fret':
|
|
14843
|
-
const guitarString =
|
|
14844
|
-
chord.strings[stringCount - guitarString - 1] =
|
|
14895
|
+
const guitarString = GpifParser.parseIntSafe(c.getAttribute('string'), 0);
|
|
14896
|
+
chord.strings[stringCount - guitarString - 1] =
|
|
14897
|
+
baseFret + GpifParser.parseIntSafe(c.getAttribute('fret'), 0);
|
|
14845
14898
|
break;
|
|
14846
14899
|
case 'Fingering':
|
|
14847
14900
|
const existingFingers = new Map();
|
|
@@ -14849,7 +14902,7 @@ class GpifParser {
|
|
|
14849
14902
|
switch (p.localName) {
|
|
14850
14903
|
case 'Position':
|
|
14851
14904
|
let finger = Fingers.Unknown;
|
|
14852
|
-
const fret = baseFret +
|
|
14905
|
+
const fret = baseFret + GpifParser.parseIntSafe(p.getAttribute('fret'), 0);
|
|
14853
14906
|
switch (p.getAttribute('finger')) {
|
|
14854
14907
|
case 'Index':
|
|
14855
14908
|
finger = Fingers.IndexFinger;
|
|
@@ -14908,10 +14961,10 @@ class GpifParser {
|
|
|
14908
14961
|
const propertyName = node.getAttribute('name');
|
|
14909
14962
|
switch (propertyName) {
|
|
14910
14963
|
case 'Tuning':
|
|
14911
|
-
const tuningParts = node.findChildElement('Pitches')
|
|
14964
|
+
const tuningParts = GpifParser.splitSafe(node.findChildElement('Pitches')?.innerText);
|
|
14912
14965
|
const tuning = new Array(tuningParts.length);
|
|
14913
14966
|
for (let i = 0; i < tuning.length; i++) {
|
|
14914
|
-
tuning[tuning.length - 1 - i] =
|
|
14967
|
+
tuning[tuning.length - 1 - i] = GpifParser.parseIntSafe(tuningParts[i], 0);
|
|
14915
14968
|
}
|
|
14916
14969
|
for (const staff of track.staves) {
|
|
14917
14970
|
staff.stringTuning.tunings = tuning;
|
|
@@ -14924,7 +14977,7 @@ class GpifParser {
|
|
|
14924
14977
|
this.parseDiagramCollectionForTrack(track, node);
|
|
14925
14978
|
break;
|
|
14926
14979
|
case 'CapoFret':
|
|
14927
|
-
const capo =
|
|
14980
|
+
const capo = GpifParser.parseIntSafe(node.findChildElement('Fret')?.innerText, 0);
|
|
14928
14981
|
for (const staff of track.staves) {
|
|
14929
14982
|
staff.capo = capo;
|
|
14930
14983
|
}
|
|
@@ -14935,16 +14988,16 @@ class GpifParser {
|
|
|
14935
14988
|
for (const c of node.childElements()) {
|
|
14936
14989
|
switch (c.localName) {
|
|
14937
14990
|
case 'Program':
|
|
14938
|
-
track.playbackInfo.program =
|
|
14991
|
+
track.playbackInfo.program = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14939
14992
|
break;
|
|
14940
14993
|
case 'Port':
|
|
14941
|
-
track.playbackInfo.port =
|
|
14994
|
+
track.playbackInfo.port = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14942
14995
|
break;
|
|
14943
14996
|
case 'PrimaryChannel':
|
|
14944
|
-
track.playbackInfo.primaryChannel =
|
|
14997
|
+
track.playbackInfo.primaryChannel = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14945
14998
|
break;
|
|
14946
14999
|
case 'SecondaryChannel':
|
|
14947
|
-
track.playbackInfo.secondaryChannel =
|
|
15000
|
+
track.playbackInfo.secondaryChannel = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14948
15001
|
break;
|
|
14949
15002
|
}
|
|
14950
15003
|
}
|
|
@@ -14994,7 +15047,7 @@ class GpifParser {
|
|
|
14994
15047
|
for (const c of node.childElements()) {
|
|
14995
15048
|
switch (c.localName) {
|
|
14996
15049
|
case 'Program':
|
|
14997
|
-
sound.program =
|
|
15050
|
+
sound.program = GpifParser.parseIntSafe(c.innerText, 0);
|
|
14998
15051
|
break;
|
|
14999
15052
|
}
|
|
15000
15053
|
}
|
|
@@ -15004,7 +15057,7 @@ class GpifParser {
|
|
|
15004
15057
|
switch (c.localName) {
|
|
15005
15058
|
case 'TranspositionPitch':
|
|
15006
15059
|
for (const staff of track.staves) {
|
|
15007
|
-
staff.displayTranspositionPitch =
|
|
15060
|
+
staff.displayTranspositionPitch = GpifParser.parseIntSafe(c.innerText, 0);
|
|
15008
15061
|
}
|
|
15009
15062
|
break;
|
|
15010
15063
|
}
|
|
@@ -15016,10 +15069,10 @@ class GpifParser {
|
|
|
15016
15069
|
for (const c of node.childElements()) {
|
|
15017
15070
|
switch (c.localName) {
|
|
15018
15071
|
case 'Chromatic':
|
|
15019
|
-
chromatic =
|
|
15072
|
+
chromatic = GpifParser.parseIntSafe(c.innerText, 0);
|
|
15020
15073
|
break;
|
|
15021
15074
|
case 'Octave':
|
|
15022
|
-
octave =
|
|
15075
|
+
octave = GpifParser.parseIntSafe(c.innerText, 0);
|
|
15023
15076
|
break;
|
|
15024
15077
|
}
|
|
15025
15078
|
}
|
|
@@ -15047,10 +15100,10 @@ class GpifParser {
|
|
|
15047
15100
|
}
|
|
15048
15101
|
parseChannelStripParameters(track, node) {
|
|
15049
15102
|
if (node.firstChild && node.firstChild.value) {
|
|
15050
|
-
const parameters = node.firstChild.value
|
|
15103
|
+
const parameters = GpifParser.splitSafe(node.firstChild.value);
|
|
15051
15104
|
if (parameters.length >= 12) {
|
|
15052
|
-
track.playbackInfo.balance = Math.floor(
|
|
15053
|
-
track.playbackInfo.volume = Math.floor(
|
|
15105
|
+
track.playbackInfo.balance = Math.floor(GpifParser.parseFloatSafe(parameters[11], 0.5) * 16);
|
|
15106
|
+
track.playbackInfo.volume = Math.floor(GpifParser.parseFloatSafe(parameters[12], 0.9) * 16);
|
|
15054
15107
|
}
|
|
15055
15108
|
}
|
|
15056
15109
|
}
|
|
@@ -15075,8 +15128,8 @@ class GpifParser {
|
|
|
15075
15128
|
switch (c.localName) {
|
|
15076
15129
|
case 'Time':
|
|
15077
15130
|
const timeParts = c.innerText.split('/');
|
|
15078
|
-
masterBar.timeSignatureNumerator =
|
|
15079
|
-
masterBar.timeSignatureDenominator =
|
|
15131
|
+
masterBar.timeSignatureNumerator = GpifParser.parseIntSafe(timeParts[0], 4);
|
|
15132
|
+
masterBar.timeSignatureDenominator = GpifParser.parseIntSafe(timeParts[1], 4);
|
|
15080
15133
|
break;
|
|
15081
15134
|
case 'FreeTime':
|
|
15082
15135
|
masterBar.isFreeTime = true;
|
|
@@ -15087,27 +15140,27 @@ class GpifParser {
|
|
|
15087
15140
|
break;
|
|
15088
15141
|
case 'Section':
|
|
15089
15142
|
masterBar.section = new Section();
|
|
15090
|
-
masterBar.section.marker = c.findChildElement('Letter')
|
|
15091
|
-
masterBar.section.text = c.findChildElement('Text')
|
|
15143
|
+
masterBar.section.marker = c.findChildElement('Letter')?.innerText ?? '';
|
|
15144
|
+
masterBar.section.text = c.findChildElement('Text')?.innerText ?? '';
|
|
15092
15145
|
break;
|
|
15093
15146
|
case 'Repeat':
|
|
15094
15147
|
if (c.getAttribute('start').toLowerCase() === 'true') {
|
|
15095
15148
|
masterBar.isRepeatStart = true;
|
|
15096
15149
|
}
|
|
15097
15150
|
if (c.getAttribute('end').toLowerCase() === 'true' && c.getAttribute('count')) {
|
|
15098
|
-
masterBar.repeatCount =
|
|
15151
|
+
masterBar.repeatCount = GpifParser.parseIntSafe(c.getAttribute('count'), 1);
|
|
15099
15152
|
}
|
|
15100
15153
|
break;
|
|
15101
15154
|
case 'AlternateEndings':
|
|
15102
|
-
const alternateEndings = c.innerText
|
|
15155
|
+
const alternateEndings = GpifParser.splitSafe(c.innerText);
|
|
15103
15156
|
let i = 0;
|
|
15104
15157
|
for (let k = 0; k < alternateEndings.length; k++) {
|
|
15105
|
-
i = i | (1 << (-1 +
|
|
15158
|
+
i = i | (1 << (-1 + GpifParser.parseIntSafe(alternateEndings[k], 0)));
|
|
15106
15159
|
}
|
|
15107
15160
|
masterBar.alternateEndings = i;
|
|
15108
15161
|
break;
|
|
15109
15162
|
case 'Bars':
|
|
15110
|
-
this._barsOfMasterBar.push(c.innerText
|
|
15163
|
+
this._barsOfMasterBar.push(GpifParser.splitSafe(c.innerText));
|
|
15111
15164
|
break;
|
|
15112
15165
|
case 'TripletFeel':
|
|
15113
15166
|
switch (c.innerText) {
|
|
@@ -15135,7 +15188,7 @@ class GpifParser {
|
|
|
15135
15188
|
}
|
|
15136
15189
|
break;
|
|
15137
15190
|
case 'Key':
|
|
15138
|
-
const keySignature =
|
|
15191
|
+
const keySignature = GpifParser.parseIntSafe(c.findChildElement('AccidentalCount')?.innerText, 0);
|
|
15139
15192
|
const mode = c.findChildElement('Mode');
|
|
15140
15193
|
let keySignatureType = KeySignatureType.Major;
|
|
15141
15194
|
if (mode) {
|
|
@@ -15263,13 +15316,13 @@ class GpifParser {
|
|
|
15263
15316
|
}
|
|
15264
15317
|
break;
|
|
15265
15318
|
case 'Length':
|
|
15266
|
-
fermata.length =
|
|
15319
|
+
fermata.length = GpifParser.parseFloatSafe(c.innerText, 0);
|
|
15267
15320
|
break;
|
|
15268
15321
|
case 'Offset':
|
|
15269
15322
|
const parts = c.innerText.split('/');
|
|
15270
15323
|
if (parts.length === 2) {
|
|
15271
|
-
const numerator =
|
|
15272
|
-
const denominator =
|
|
15324
|
+
const numerator = GpifParser.parseIntSafe(parts[0], 4);
|
|
15325
|
+
const denominator = GpifParser.parseIntSafe(parts[1], 4);
|
|
15273
15326
|
offset = ((numerator / denominator) * MidiUtils.QuarterTime) | 0;
|
|
15274
15327
|
}
|
|
15275
15328
|
break;
|
|
@@ -15295,7 +15348,7 @@ class GpifParser {
|
|
|
15295
15348
|
for (const c of node.childElements()) {
|
|
15296
15349
|
switch (c.localName) {
|
|
15297
15350
|
case 'Voices':
|
|
15298
|
-
this._voicesOfBar.set(barId, c.innerText
|
|
15351
|
+
this._voicesOfBar.set(barId, GpifParser.splitSafe(c.innerText));
|
|
15299
15352
|
break;
|
|
15300
15353
|
case 'Clef':
|
|
15301
15354
|
switch (c.innerText) {
|
|
@@ -15370,7 +15423,7 @@ class GpifParser {
|
|
|
15370
15423
|
for (const c of node.childElements()) {
|
|
15371
15424
|
switch (c.localName) {
|
|
15372
15425
|
case 'Beats':
|
|
15373
|
-
this._beatsOfVoice.set(voiceId, c.innerText
|
|
15426
|
+
this._beatsOfVoice.set(voiceId, GpifParser.splitSafe(c.innerText));
|
|
15374
15427
|
break;
|
|
15375
15428
|
}
|
|
15376
15429
|
}
|
|
@@ -15394,7 +15447,7 @@ class GpifParser {
|
|
|
15394
15447
|
for (const c of node.childElements()) {
|
|
15395
15448
|
switch (c.localName) {
|
|
15396
15449
|
case 'Notes':
|
|
15397
|
-
this._notesOfBeat.set(beatId, c.innerText
|
|
15450
|
+
this._notesOfBeat.set(beatId, GpifParser.splitSafe(c.innerText));
|
|
15398
15451
|
break;
|
|
15399
15452
|
case 'Rhythm':
|
|
15400
15453
|
this._rhythmOfBeat.set(beatId, c.getAttribute('ref'));
|
|
@@ -15510,20 +15563,20 @@ class GpifParser {
|
|
|
15510
15563
|
break;
|
|
15511
15564
|
case 'Whammy':
|
|
15512
15565
|
const whammyOrigin = new BendPoint(0, 0);
|
|
15513
|
-
whammyOrigin.value = this.toBendValue(
|
|
15514
|
-
whammyOrigin.offset = this.toBendOffset(
|
|
15566
|
+
whammyOrigin.value = this.toBendValue(GpifParser.parseFloatSafe(c.getAttribute('originValue'), 0));
|
|
15567
|
+
whammyOrigin.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.getAttribute('originOffset'), 0));
|
|
15515
15568
|
beat.addWhammyBarPoint(whammyOrigin);
|
|
15516
15569
|
const whammyMiddle1 = new BendPoint(0, 0);
|
|
15517
|
-
whammyMiddle1.value = this.toBendValue(
|
|
15518
|
-
whammyMiddle1.offset = this.toBendOffset(
|
|
15570
|
+
whammyMiddle1.value = this.toBendValue(GpifParser.parseFloatSafe(c.getAttribute('middleValue'), 0));
|
|
15571
|
+
whammyMiddle1.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.getAttribute('middleOffset1'), 0));
|
|
15519
15572
|
beat.addWhammyBarPoint(whammyMiddle1);
|
|
15520
15573
|
const whammyMiddle2 = new BendPoint(0, 0);
|
|
15521
|
-
whammyMiddle2.value = this.toBendValue(
|
|
15522
|
-
whammyMiddle2.offset = this.toBendOffset(
|
|
15574
|
+
whammyMiddle2.value = this.toBendValue(GpifParser.parseFloatSafe(c.getAttribute('middleValue'), 0));
|
|
15575
|
+
whammyMiddle2.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.getAttribute('middleOffset2'), 0));
|
|
15523
15576
|
beat.addWhammyBarPoint(whammyMiddle2);
|
|
15524
15577
|
const whammyDestination = new BendPoint(0, 0);
|
|
15525
|
-
whammyDestination.value = this.toBendValue(
|
|
15526
|
-
whammyDestination.offset = this.toBendOffset(
|
|
15578
|
+
whammyDestination.value = this.toBendValue(GpifParser.parseFloatSafe(c.getAttribute('destinationValue'), 0));
|
|
15579
|
+
whammyDestination.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.getAttribute('destinationOffset'), 0));
|
|
15527
15580
|
beat.addWhammyBarPoint(whammyDestination);
|
|
15528
15581
|
break;
|
|
15529
15582
|
case 'Ottavia':
|
|
@@ -15584,8 +15637,9 @@ class GpifParser {
|
|
|
15584
15637
|
break;
|
|
15585
15638
|
case 'Timer':
|
|
15586
15639
|
beat.showTimer = true;
|
|
15587
|
-
|
|
15588
|
-
|
|
15640
|
+
beat.timer = GpifParser.parseIntSafe(c.innerText, -1);
|
|
15641
|
+
if (beat.timer < 0) {
|
|
15642
|
+
beat.timer = null;
|
|
15589
15643
|
}
|
|
15590
15644
|
break;
|
|
15591
15645
|
}
|
|
@@ -15611,7 +15665,7 @@ class GpifParser {
|
|
|
15611
15665
|
let value = 0;
|
|
15612
15666
|
switch (id) {
|
|
15613
15667
|
case '1124204546':
|
|
15614
|
-
value =
|
|
15668
|
+
value = GpifParser.parseIntSafe(c.findChildElement('Int')?.innerText, 0);
|
|
15615
15669
|
switch (value) {
|
|
15616
15670
|
case 1:
|
|
15617
15671
|
beat.beamingMode = BeatBeamingMode.ForceMergeWithNext;
|
|
@@ -15622,7 +15676,7 @@ class GpifParser {
|
|
|
15622
15676
|
}
|
|
15623
15677
|
break;
|
|
15624
15678
|
case '1124204552':
|
|
15625
|
-
value =
|
|
15679
|
+
value = GpifParser.parseIntSafe(c.findChildElement('Int')?.innerText, 0);
|
|
15626
15680
|
switch (value) {
|
|
15627
15681
|
case 1:
|
|
15628
15682
|
if (beat.beamingMode !== BeatBeamingMode.ForceSplitToNext) {
|
|
@@ -15632,11 +15686,11 @@ class GpifParser {
|
|
|
15632
15686
|
}
|
|
15633
15687
|
break;
|
|
15634
15688
|
case '1124204545':
|
|
15635
|
-
value =
|
|
15689
|
+
value = GpifParser.parseIntSafe(c.findChildElement('Int')?.innerText, 0);
|
|
15636
15690
|
beat.invertBeamDirection = value === 1;
|
|
15637
15691
|
break;
|
|
15638
15692
|
case '687935489':
|
|
15639
|
-
value =
|
|
15693
|
+
value = GpifParser.parseIntSafe(c.findChildElement('Int')?.innerText, 0);
|
|
15640
15694
|
beat.brushDuration = value;
|
|
15641
15695
|
break;
|
|
15642
15696
|
}
|
|
@@ -15652,7 +15706,7 @@ class GpifParser {
|
|
|
15652
15706
|
switch (id) {
|
|
15653
15707
|
case '1124139520':
|
|
15654
15708
|
const childNode = c.findChildElement('Double') ?? c.findChildElement('Float');
|
|
15655
|
-
bar.displayScale =
|
|
15709
|
+
bar.displayScale = GpifParser.parseFloatSafe(childNode?.innerText, 1);
|
|
15656
15710
|
break;
|
|
15657
15711
|
}
|
|
15658
15712
|
break;
|
|
@@ -15666,7 +15720,7 @@ class GpifParser {
|
|
|
15666
15720
|
const id = c.getAttribute('id');
|
|
15667
15721
|
switch (id) {
|
|
15668
15722
|
case '1124073984':
|
|
15669
|
-
masterBar.displayScale =
|
|
15723
|
+
masterBar.displayScale = GpifParser.parseFloatSafe(c.findChildElement('Double')?.innerText, 1);
|
|
15670
15724
|
break;
|
|
15671
15725
|
}
|
|
15672
15726
|
break;
|
|
@@ -15686,7 +15740,7 @@ class GpifParser {
|
|
|
15686
15740
|
const name = c.getAttribute('name');
|
|
15687
15741
|
switch (name) {
|
|
15688
15742
|
case 'Brush':
|
|
15689
|
-
if (c.findChildElement('Direction')
|
|
15743
|
+
if (c.findChildElement('Direction')?.innerText === 'Up') {
|
|
15690
15744
|
beat.brushType = BrushType.BrushUp;
|
|
15691
15745
|
}
|
|
15692
15746
|
else {
|
|
@@ -15694,7 +15748,7 @@ class GpifParser {
|
|
|
15694
15748
|
}
|
|
15695
15749
|
break;
|
|
15696
15750
|
case 'PickStroke':
|
|
15697
|
-
if (c.findChildElement('Direction')
|
|
15751
|
+
if (c.findChildElement('Direction')?.innerText === 'Up') {
|
|
15698
15752
|
beat.pickStroke = PickStroke.Up;
|
|
15699
15753
|
}
|
|
15700
15754
|
else {
|
|
@@ -15712,7 +15766,7 @@ class GpifParser {
|
|
|
15712
15766
|
}
|
|
15713
15767
|
break;
|
|
15714
15768
|
case 'VibratoWTremBar':
|
|
15715
|
-
switch (c.findChildElement('Strength')
|
|
15769
|
+
switch (c.findChildElement('Strength')?.innerText) {
|
|
15716
15770
|
case 'Wide':
|
|
15717
15771
|
beat.vibrato = VibratoType.Wide;
|
|
15718
15772
|
break;
|
|
@@ -15731,40 +15785,40 @@ class GpifParser {
|
|
|
15731
15785
|
if (!whammyOrigin) {
|
|
15732
15786
|
whammyOrigin = new BendPoint(0, 0);
|
|
15733
15787
|
}
|
|
15734
|
-
whammyOrigin.value = this.toBendValue(
|
|
15788
|
+
whammyOrigin.value = this.toBendValue(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15735
15789
|
break;
|
|
15736
15790
|
case 'WhammyBarOriginOffset':
|
|
15737
15791
|
if (!whammyOrigin) {
|
|
15738
15792
|
whammyOrigin = new BendPoint(0, 0);
|
|
15739
15793
|
}
|
|
15740
|
-
whammyOrigin.offset = this.toBendOffset(
|
|
15794
|
+
whammyOrigin.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15741
15795
|
break;
|
|
15742
15796
|
case 'WhammyBarMiddleValue':
|
|
15743
|
-
whammyMiddleValue = this.toBendValue(
|
|
15797
|
+
whammyMiddleValue = this.toBendValue(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15744
15798
|
break;
|
|
15745
15799
|
case 'WhammyBarMiddleOffset1':
|
|
15746
|
-
whammyMiddleOffset1 = this.toBendOffset(
|
|
15800
|
+
whammyMiddleOffset1 = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15747
15801
|
break;
|
|
15748
15802
|
case 'WhammyBarMiddleOffset2':
|
|
15749
|
-
whammyMiddleOffset2 = this.toBendOffset(
|
|
15803
|
+
whammyMiddleOffset2 = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15750
15804
|
break;
|
|
15751
15805
|
case 'WhammyBarDestinationValue':
|
|
15752
15806
|
if (!whammyDestination) {
|
|
15753
15807
|
whammyDestination = new BendPoint(BendPoint.MaxPosition, 0);
|
|
15754
15808
|
}
|
|
15755
|
-
whammyDestination.value = this.toBendValue(
|
|
15809
|
+
whammyDestination.value = this.toBendValue(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15756
15810
|
break;
|
|
15757
15811
|
case 'WhammyBarDestinationOffset':
|
|
15758
15812
|
if (!whammyDestination) {
|
|
15759
15813
|
whammyDestination = new BendPoint(0, 0);
|
|
15760
15814
|
}
|
|
15761
|
-
whammyDestination.offset = this.toBendOffset(
|
|
15815
|
+
whammyDestination.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
15762
15816
|
break;
|
|
15763
15817
|
case 'BarreFret':
|
|
15764
|
-
beat.barreFret =
|
|
15818
|
+
beat.barreFret = GpifParser.parseIntSafe(c.findChildElement('Fret')?.innerText, 0);
|
|
15765
15819
|
break;
|
|
15766
15820
|
case 'BarreString':
|
|
15767
|
-
switch (c.findChildElement('String')
|
|
15821
|
+
switch (c.findChildElement('String')?.innerText) {
|
|
15768
15822
|
case '0':
|
|
15769
15823
|
beat.barreShape = BarreShape.Full;
|
|
15770
15824
|
break;
|
|
@@ -15774,7 +15828,7 @@ class GpifParser {
|
|
|
15774
15828
|
}
|
|
15775
15829
|
break;
|
|
15776
15830
|
case 'Rasgueado':
|
|
15777
|
-
switch (c.findChildElement('Rasgueado')
|
|
15831
|
+
switch (c.findChildElement('Rasgueado')?.innerText) {
|
|
15778
15832
|
case 'ii_1':
|
|
15779
15833
|
beat.rasgueado = Rasgueado.Ii;
|
|
15780
15834
|
break;
|
|
@@ -15884,11 +15938,11 @@ class GpifParser {
|
|
|
15884
15938
|
note.isLetRing = true;
|
|
15885
15939
|
break;
|
|
15886
15940
|
case 'Trill':
|
|
15887
|
-
note.trillValue =
|
|
15941
|
+
note.trillValue = GpifParser.parseIntSafe(c.innerText, -1);
|
|
15888
15942
|
note.trillSpeed = Duration.Sixteenth;
|
|
15889
15943
|
break;
|
|
15890
15944
|
case 'Accent':
|
|
15891
|
-
const accentFlags =
|
|
15945
|
+
const accentFlags = GpifParser.parseIntSafe(c.innerText, 0);
|
|
15892
15946
|
if ((accentFlags & 0x01) !== 0) {
|
|
15893
15947
|
note.isStaccato = true;
|
|
15894
15948
|
}
|
|
@@ -15956,7 +16010,7 @@ class GpifParser {
|
|
|
15956
16010
|
}
|
|
15957
16011
|
break;
|
|
15958
16012
|
case 'InstrumentArticulation':
|
|
15959
|
-
note.percussionArticulation =
|
|
16013
|
+
note.percussionArticulation = GpifParser.parseIntSafe(c.innerText, 0);
|
|
15960
16014
|
break;
|
|
15961
16015
|
case 'Ornament':
|
|
15962
16016
|
switch (c.innerText) {
|
|
@@ -15999,16 +16053,16 @@ class GpifParser {
|
|
|
15999
16053
|
}
|
|
16000
16054
|
break;
|
|
16001
16055
|
case 'String':
|
|
16002
|
-
note.string =
|
|
16056
|
+
note.string = GpifParser.parseIntSafe(c.findChildElement('String')?.innerText, 0) + 1;
|
|
16003
16057
|
break;
|
|
16004
16058
|
case 'Fret':
|
|
16005
|
-
note.fret =
|
|
16059
|
+
note.fret = GpifParser.parseIntSafe(c.findChildElement('Fret')?.innerText, 0);
|
|
16006
16060
|
break;
|
|
16007
16061
|
case 'Element':
|
|
16008
|
-
element =
|
|
16062
|
+
element = GpifParser.parseIntSafe(c.findChildElement('Element')?.innerText, 0);
|
|
16009
16063
|
break;
|
|
16010
16064
|
case 'Variation':
|
|
16011
|
-
variation =
|
|
16065
|
+
variation = GpifParser.parseIntSafe(c.findChildElement('Variation')?.innerText, 0);
|
|
16012
16066
|
break;
|
|
16013
16067
|
case 'Tapped':
|
|
16014
16068
|
this._tappedNotes.set(noteId, true);
|
|
@@ -16044,7 +16098,7 @@ class GpifParser {
|
|
|
16044
16098
|
case 'HarmonicFret':
|
|
16045
16099
|
const hfret = c.findChildElement('HFret');
|
|
16046
16100
|
if (hfret) {
|
|
16047
|
-
note.harmonicValue =
|
|
16101
|
+
note.harmonicValue = GpifParser.parseFloatSafe(hfret.innerText, 0);
|
|
16048
16102
|
}
|
|
16049
16103
|
break;
|
|
16050
16104
|
case 'Muted':
|
|
@@ -16058,14 +16112,14 @@ class GpifParser {
|
|
|
16058
16112
|
}
|
|
16059
16113
|
break;
|
|
16060
16114
|
case 'Octave':
|
|
16061
|
-
note.octave =
|
|
16115
|
+
note.octave = GpifParser.parseIntSafe(c.findChildElement('Number')?.innerText, 0);
|
|
16062
16116
|
// when exporting GP6 from GP7 the tone might be missing
|
|
16063
16117
|
if (note.tone === -1) {
|
|
16064
16118
|
note.tone = 0;
|
|
16065
16119
|
}
|
|
16066
16120
|
break;
|
|
16067
16121
|
case 'Tone':
|
|
16068
|
-
note.tone =
|
|
16122
|
+
note.tone = GpifParser.parseIntSafe(c.findChildElement('Step')?.innerText, 0);
|
|
16069
16123
|
break;
|
|
16070
16124
|
case 'ConcertPitch':
|
|
16071
16125
|
this.parseConcertPitch(c, note);
|
|
@@ -16077,34 +16131,34 @@ class GpifParser {
|
|
|
16077
16131
|
if (!bendOrigin) {
|
|
16078
16132
|
bendOrigin = new BendPoint(0, 0);
|
|
16079
16133
|
}
|
|
16080
|
-
bendOrigin.value = this.toBendValue(
|
|
16134
|
+
bendOrigin.value = this.toBendValue(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16081
16135
|
break;
|
|
16082
16136
|
case 'BendOriginOffset':
|
|
16083
16137
|
if (!bendOrigin) {
|
|
16084
16138
|
bendOrigin = new BendPoint(0, 0);
|
|
16085
16139
|
}
|
|
16086
|
-
bendOrigin.offset = this.toBendOffset(
|
|
16140
|
+
bendOrigin.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16087
16141
|
break;
|
|
16088
16142
|
case 'BendMiddleValue':
|
|
16089
|
-
bendMiddleValue = this.toBendValue(
|
|
16143
|
+
bendMiddleValue = this.toBendValue(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16090
16144
|
break;
|
|
16091
16145
|
case 'BendMiddleOffset1':
|
|
16092
|
-
bendMiddleOffset1 = this.toBendOffset(
|
|
16146
|
+
bendMiddleOffset1 = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16093
16147
|
break;
|
|
16094
16148
|
case 'BendMiddleOffset2':
|
|
16095
|
-
bendMiddleOffset2 = this.toBendOffset(
|
|
16149
|
+
bendMiddleOffset2 = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16096
16150
|
break;
|
|
16097
16151
|
case 'BendDestinationValue':
|
|
16098
16152
|
if (!bendDestination) {
|
|
16099
16153
|
bendDestination = new BendPoint(BendPoint.MaxPosition, 0);
|
|
16100
16154
|
}
|
|
16101
|
-
bendDestination.value = this.toBendValue(
|
|
16155
|
+
bendDestination.value = this.toBendValue(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16102
16156
|
break;
|
|
16103
16157
|
case 'BendDestinationOffset':
|
|
16104
16158
|
if (!bendDestination) {
|
|
16105
16159
|
bendDestination = new BendPoint(0, 0);
|
|
16106
16160
|
}
|
|
16107
|
-
bendDestination.offset = this.toBendOffset(
|
|
16161
|
+
bendDestination.offset = this.toBendOffset(GpifParser.parseFloatSafe(c.findChildElement('Float')?.innerText, 0));
|
|
16108
16162
|
break;
|
|
16109
16163
|
case 'HopoOrigin':
|
|
16110
16164
|
if (c.findChildElement('Enable')) {
|
|
@@ -16120,7 +16174,7 @@ class GpifParser {
|
|
|
16120
16174
|
note.isLeftHandTapped = true;
|
|
16121
16175
|
break;
|
|
16122
16176
|
case 'Slide':
|
|
16123
|
-
const slideFlags =
|
|
16177
|
+
const slideFlags = GpifParser.parseIntSafe(c.findChildElement('Flags')?.innerText, 0);
|
|
16124
16178
|
if ((slideFlags & 1) !== 0) {
|
|
16125
16179
|
note.slideOutType = SlideOutType.Shift;
|
|
16126
16180
|
}
|
|
@@ -16258,11 +16312,11 @@ class GpifParser {
|
|
|
16258
16312
|
}
|
|
16259
16313
|
break;
|
|
16260
16314
|
case 'PrimaryTuplet':
|
|
16261
|
-
rhythm.tupletNumerator =
|
|
16262
|
-
rhythm.tupletDenominator =
|
|
16315
|
+
rhythm.tupletNumerator = GpifParser.parseIntSafe(c.getAttribute('num'), -1);
|
|
16316
|
+
rhythm.tupletDenominator = GpifParser.parseIntSafe(c.getAttribute('den'), -1);
|
|
16263
16317
|
break;
|
|
16264
16318
|
case 'AugmentationDot':
|
|
16265
|
-
rhythm.dots =
|
|
16319
|
+
rhythm.dots = GpifParser.parseIntSafe(c.getAttribute('count'), 0);
|
|
16266
16320
|
break;
|
|
16267
16321
|
}
|
|
16268
16322
|
}
|
|
@@ -18277,61 +18331,11 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
18277
18331
|
this._score.tempo = 120;
|
|
18278
18332
|
this._score.stylesheet.hideDynamics = true;
|
|
18279
18333
|
this.parseDom(dom);
|
|
18280
|
-
|
|
18334
|
+
ModelUtils.consolidate(this._score);
|
|
18281
18335
|
this._score.finish(this.settings);
|
|
18282
18336
|
this._score.rebuildRepeatGroups();
|
|
18283
18337
|
return this._score;
|
|
18284
18338
|
}
|
|
18285
|
-
consolidate() {
|
|
18286
|
-
const usedChannels = new Set([SynthConstants.PercussionChannel]);
|
|
18287
|
-
for (const track of this._score.tracks) {
|
|
18288
|
-
// unique midi channels and generate secondary channels
|
|
18289
|
-
if (track.playbackInfo.primaryChannel !== SynthConstants.PercussionChannel) {
|
|
18290
|
-
while (usedChannels.has(track.playbackInfo.primaryChannel)) {
|
|
18291
|
-
track.playbackInfo.primaryChannel++;
|
|
18292
|
-
}
|
|
18293
|
-
}
|
|
18294
|
-
usedChannels.add(track.playbackInfo.primaryChannel);
|
|
18295
|
-
if (track.playbackInfo.secondaryChannel !== SynthConstants.PercussionChannel) {
|
|
18296
|
-
while (usedChannels.has(track.playbackInfo.secondaryChannel)) {
|
|
18297
|
-
track.playbackInfo.secondaryChannel++;
|
|
18298
|
-
}
|
|
18299
|
-
}
|
|
18300
|
-
usedChannels.add(track.playbackInfo.secondaryChannel);
|
|
18301
|
-
for (const staff of track.staves) {
|
|
18302
|
-
// fill empty beats
|
|
18303
|
-
for (const b of staff.bars) {
|
|
18304
|
-
for (const v of b.voices) {
|
|
18305
|
-
if (v.isEmpty && v.beats.length === 0) {
|
|
18306
|
-
const emptyBeat = new Beat();
|
|
18307
|
-
emptyBeat.isEmpty = true;
|
|
18308
|
-
v.addBeat(emptyBeat);
|
|
18309
|
-
}
|
|
18310
|
-
}
|
|
18311
|
-
}
|
|
18312
|
-
// fill missing bars
|
|
18313
|
-
const voiceCount = staff.bars.length === 0 ? 1 : staff.bars[0].voices.length;
|
|
18314
|
-
while (staff.bars.length < this._score.masterBars.length) {
|
|
18315
|
-
const bar = new Bar();
|
|
18316
|
-
staff.addBar(bar);
|
|
18317
|
-
const previousBar = bar.previousBar;
|
|
18318
|
-
if (previousBar) {
|
|
18319
|
-
bar.clef = previousBar.clef;
|
|
18320
|
-
bar.clefOttava = previousBar.clefOttava;
|
|
18321
|
-
bar.keySignature = bar.previousBar.keySignature;
|
|
18322
|
-
bar.keySignatureType = bar.previousBar.keySignatureType;
|
|
18323
|
-
}
|
|
18324
|
-
for (let i = 0; i < voiceCount; i++) {
|
|
18325
|
-
const v = new Voice$1();
|
|
18326
|
-
bar.addVoice(v);
|
|
18327
|
-
const emptyBeat = new Beat();
|
|
18328
|
-
emptyBeat.isEmpty = true;
|
|
18329
|
-
v.addBeat(emptyBeat);
|
|
18330
|
-
}
|
|
18331
|
-
}
|
|
18332
|
-
}
|
|
18333
|
-
}
|
|
18334
|
-
}
|
|
18335
18339
|
extractMusicXml() {
|
|
18336
18340
|
const zip = new ZipReader(this.data);
|
|
18337
18341
|
let entries;
|
|
@@ -48032,7 +48036,7 @@ class DynamicsGlyph extends MusicFontGlyph {
|
|
|
48032
48036
|
case DynamicValue.RFZ:
|
|
48033
48037
|
return MusicFontSymbol.DynamicRinforzando2;
|
|
48034
48038
|
case DynamicValue.SFZ:
|
|
48035
|
-
return MusicFontSymbol.
|
|
48039
|
+
return MusicFontSymbol.DynamicSforzato;
|
|
48036
48040
|
case DynamicValue.SFFZ:
|
|
48037
48041
|
return MusicFontSymbol.DynamicSforzatoFF;
|
|
48038
48042
|
case DynamicValue.FZ:
|
|
@@ -56037,29 +56041,7 @@ class CapellaParser {
|
|
|
56037
56041
|
this.score.finish(settings);
|
|
56038
56042
|
}
|
|
56039
56043
|
consolidate() {
|
|
56040
|
-
|
|
56041
|
-
// we need to ensure we have an equal amount of voices across all bars
|
|
56042
|
-
// and voices must contain an empty beat at minimum
|
|
56043
|
-
for (const track of this.score.tracks) {
|
|
56044
|
-
const trackVoiceCount = this._voiceCounts.get(track.index);
|
|
56045
|
-
for (const staff of track.staves) {
|
|
56046
|
-
while (staff.bars.length < this.score.masterBars.length) {
|
|
56047
|
-
this.addNewBar(staff);
|
|
56048
|
-
}
|
|
56049
|
-
for (const bar of staff.bars) {
|
|
56050
|
-
while (bar.voices.length < trackVoiceCount) {
|
|
56051
|
-
bar.addVoice(new Voice$1());
|
|
56052
|
-
}
|
|
56053
|
-
for (const voice of bar.voices) {
|
|
56054
|
-
if (voice.beats.length === 0) {
|
|
56055
|
-
const emptyBeat = new Beat();
|
|
56056
|
-
emptyBeat.isEmpty = true;
|
|
56057
|
-
voice.addBeat(emptyBeat);
|
|
56058
|
-
}
|
|
56059
|
-
}
|
|
56060
|
-
}
|
|
56061
|
-
}
|
|
56062
|
-
}
|
|
56044
|
+
ModelUtils.consolidate(this.score);
|
|
56063
56045
|
CapellaParser.applyEffectRange(this._slurs, (_, beat) => {
|
|
56064
56046
|
beat.isLegatoOrigin = true;
|
|
56065
56047
|
});
|
|
@@ -59311,9 +59293,9 @@ class VersionInfo {
|
|
|
59311
59293
|
print(`build date: ${VersionInfo.date}`);
|
|
59312
59294
|
}
|
|
59313
59295
|
}
|
|
59314
|
-
VersionInfo.version = '1.5.0
|
|
59315
|
-
VersionInfo.date = '2025-05-
|
|
59316
|
-
VersionInfo.commit = '
|
|
59296
|
+
VersionInfo.version = '1.5.0';
|
|
59297
|
+
VersionInfo.date = '2025-05-04T16:47:31.157Z';
|
|
59298
|
+
VersionInfo.commit = 'a7cda51f24b9e783ce3d3b719fa1e65198c24319';
|
|
59317
59299
|
|
|
59318
59300
|
/**
|
|
59319
59301
|
* A factory for custom layout engines.
|
|
@@ -63539,6 +63521,7 @@ const _barrel$3 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty(
|
|
|
63539
63521
|
Automation,
|
|
63540
63522
|
get AutomationType () { return AutomationType; },
|
|
63541
63523
|
Bar,
|
|
63524
|
+
get BarLineStyle () { return BarLineStyle; },
|
|
63542
63525
|
BarStyle,
|
|
63543
63526
|
get BarSubElement () { return BarSubElement; },
|
|
63544
63527
|
get BarreShape () { return BarreShape; },
|
|
@@ -63570,6 +63553,7 @@ const _barrel$3 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty(
|
|
|
63570
63553
|
GraceGroup,
|
|
63571
63554
|
get GraceType () { return GraceType; },
|
|
63572
63555
|
get HarmonicType () { return HarmonicType; },
|
|
63556
|
+
HeaderFooterStyle,
|
|
63573
63557
|
InstrumentArticulation,
|
|
63574
63558
|
JsonConverter,
|
|
63575
63559
|
get KeySignature () { return KeySignature; },
|