@coderline/alphatab 1.6.0-alpha.1428 → 1.6.0-alpha.1432
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 +415 -114
- package/dist/alphaTab.d.ts +218 -26
- package/dist/alphaTab.js +415 -114
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.vite.js +1 -1
- package/dist/alphaTab.vite.mjs +1 -1
- package/dist/alphaTab.webpack.js +1 -1
- package/dist/alphaTab.webpack.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +1 -1
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.6.0-alpha.
|
|
2
|
+
* alphaTab v1.6.0-alpha.1432 (develop, build 1432)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -1012,6 +1012,26 @@
|
|
|
1012
1012
|
get isEmpty() {
|
|
1013
1013
|
return this._isEmpty;
|
|
1014
1014
|
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Whether this bar has any changes applied which are not related to the voices in it.
|
|
1017
|
+
* (e.g. new key signatures)
|
|
1018
|
+
*/
|
|
1019
|
+
get hasChanges() {
|
|
1020
|
+
if (this.index === 0) {
|
|
1021
|
+
return true;
|
|
1022
|
+
}
|
|
1023
|
+
const hasChangesToPrevious = this.keySignature !== this.previousBar.keySignature ||
|
|
1024
|
+
this.keySignatureType !== this.previousBar.keySignatureType ||
|
|
1025
|
+
this.clef !== this.previousBar.clef ||
|
|
1026
|
+
this.clefOttava !== this.previousBar.clefOttava;
|
|
1027
|
+
if (hasChangesToPrevious) {
|
|
1028
|
+
return true;
|
|
1029
|
+
}
|
|
1030
|
+
return (this.simileMark !== SimileMark.None ||
|
|
1031
|
+
this.sustainPedals.length > 0 ||
|
|
1032
|
+
this.barLineLeft !== BarLineStyle.Automatic ||
|
|
1033
|
+
this.barLineRight !== BarLineStyle.Automatic);
|
|
1034
|
+
}
|
|
1015
1035
|
/**
|
|
1016
1036
|
* Whether this bar is empty or has only rests.
|
|
1017
1037
|
*/
|
|
@@ -1417,12 +1437,6 @@
|
|
|
1417
1437
|
* Indicates for which repeat occurence this sync point is valid (e.g. 0 on the first time played, 1 on the second time played)
|
|
1418
1438
|
*/
|
|
1419
1439
|
this.barOccurence = 0;
|
|
1420
|
-
/**
|
|
1421
|
-
* The modified tempo at which the cursor should move (aka. the tempo played within the external audio track).
|
|
1422
|
-
* This information is used together with normal tempo changes to calculate how much faster/slower the
|
|
1423
|
-
* cursor playback is performed to align with the audio track.
|
|
1424
|
-
*/
|
|
1425
|
-
this.modifiedTempo = 0;
|
|
1426
1440
|
/**
|
|
1427
1441
|
* The audio offset marking the position within the audio track in milliseconds.
|
|
1428
1442
|
* This information is used to regularly sync (or on seeking) to match a given external audio time axis with the internal time axis.
|
|
@@ -2631,6 +2645,33 @@
|
|
|
2631
2645
|
*/
|
|
2632
2646
|
this.directions = null;
|
|
2633
2647
|
}
|
|
2648
|
+
/**
|
|
2649
|
+
* Whether the masterbar is has any changes applied to it (e.g. tempo changes, time signature changes etc)
|
|
2650
|
+
* The first bar is always considered changed due to initial setup of values. It does not consider
|
|
2651
|
+
* elements like whether the tempo really changes to the previous bar.
|
|
2652
|
+
*/
|
|
2653
|
+
get hasChanges() {
|
|
2654
|
+
if (this.index === 0) {
|
|
2655
|
+
return false;
|
|
2656
|
+
}
|
|
2657
|
+
const hasChangesToPrevious = this.timeSignatureCommon !== this.previousMasterBar.timeSignatureCommon ||
|
|
2658
|
+
this.timeSignatureNumerator !== this.previousMasterBar.timeSignatureNumerator ||
|
|
2659
|
+
this.timeSignatureDenominator !== this.previousMasterBar.timeSignatureDenominator ||
|
|
2660
|
+
this.tripletFeel !== this.previousMasterBar.tripletFeel;
|
|
2661
|
+
if (hasChangesToPrevious) {
|
|
2662
|
+
return true;
|
|
2663
|
+
}
|
|
2664
|
+
return (this.alternateEndings !== 0 ||
|
|
2665
|
+
this.isRepeatStart ||
|
|
2666
|
+
this.isRepeatEnd ||
|
|
2667
|
+
this.isFreeTime ||
|
|
2668
|
+
this.isSectionStart ||
|
|
2669
|
+
this.tempoAutomations.length > 0 ||
|
|
2670
|
+
this.syncPoints && this.syncPoints.length > 0 ||
|
|
2671
|
+
(this.fermata !== null && this.fermata.size > 0) ||
|
|
2672
|
+
(this.directions !== null && this.directions.size > 0) ||
|
|
2673
|
+
this.isAnacrusis);
|
|
2674
|
+
}
|
|
2634
2675
|
/**
|
|
2635
2676
|
* The key signature used on all bars.
|
|
2636
2677
|
* @deprecated Use key signatures on bar level
|
|
@@ -3572,6 +3613,43 @@
|
|
|
3572
3613
|
}
|
|
3573
3614
|
}
|
|
3574
3615
|
}
|
|
3616
|
+
/**
|
|
3617
|
+
* Trims any empty bars at the end of the song.
|
|
3618
|
+
* @param score
|
|
3619
|
+
*/
|
|
3620
|
+
static trimEmptyBarsAtEnd(score) {
|
|
3621
|
+
while (score.masterBars.length > 1) {
|
|
3622
|
+
const barIndex = score.masterBars.length - 1;
|
|
3623
|
+
const masterBar = score.masterBars[barIndex];
|
|
3624
|
+
if (masterBar.hasChanges) {
|
|
3625
|
+
return;
|
|
3626
|
+
}
|
|
3627
|
+
for (const track of score.tracks) {
|
|
3628
|
+
for (const staff of track.staves) {
|
|
3629
|
+
if (barIndex < staff.bars.length) {
|
|
3630
|
+
const bar = staff.bars[barIndex];
|
|
3631
|
+
if (!bar.isEmpty || bar.hasChanges) {
|
|
3632
|
+
// found a non-empty bar, stop whole cleanup
|
|
3633
|
+
return;
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
// if we reach here, all found bars are empty, remove the bar
|
|
3639
|
+
for (const track of score.tracks) {
|
|
3640
|
+
for (const staff of track.staves) {
|
|
3641
|
+
if (barIndex < staff.bars.length) {
|
|
3642
|
+
const bar = staff.bars[barIndex];
|
|
3643
|
+
staff.bars.pop();
|
|
3644
|
+
// unlink
|
|
3645
|
+
bar.previousBar.nextBar = null;
|
|
3646
|
+
}
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3649
|
+
score.masterBars.pop();
|
|
3650
|
+
masterBar.previousMasterBar.nextMasterBar = null;
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3575
3653
|
}
|
|
3576
3654
|
ModelUtils.TuningLetters = new Set([
|
|
3577
3655
|
0x43 /* C */, 0x44 /* D */, 0x45 /* E */, 0x46 /* F */, 0x47 /* G */, 0x41 /* A */, 0x42 /* B */, 0x63 /* c */,
|
|
@@ -5849,7 +5927,6 @@
|
|
|
5849
5927
|
static clone(original) {
|
|
5850
5928
|
const clone = new SyncPointData();
|
|
5851
5929
|
clone.barOccurence = original.barOccurence;
|
|
5852
|
-
clone.modifiedTempo = original.modifiedTempo;
|
|
5853
5930
|
clone.millisecondOffset = original.millisecondOffset;
|
|
5854
5931
|
return clone;
|
|
5855
5932
|
}
|
|
@@ -7319,7 +7396,6 @@
|
|
|
7319
7396
|
automation.ratioPosition = Math.min(1, Math.max(0, syncPoint.barPosition));
|
|
7320
7397
|
automation.type = AutomationType.SyncPoint;
|
|
7321
7398
|
automation.syncPointValue = new SyncPointData();
|
|
7322
|
-
automation.syncPointValue.modifiedTempo = syncPoint.modifiedTempo;
|
|
7323
7399
|
automation.syncPointValue.millisecondOffset = syncPoint.millisecondOffset;
|
|
7324
7400
|
automation.syncPointValue.barOccurence = syncPoint.barOccurence;
|
|
7325
7401
|
if (syncPoint.barIndex < this.masterBars.length) {
|
|
@@ -7352,8 +7428,7 @@
|
|
|
7352
7428
|
barIndex: masterBar.index,
|
|
7353
7429
|
barOccurence: syncPoint.syncPointValue.barOccurence,
|
|
7354
7430
|
barPosition: syncPoint.ratioPosition,
|
|
7355
|
-
millisecondOffset: syncPoint.syncPointValue.millisecondOffset
|
|
7356
|
-
modifiedTempo: syncPoint.syncPointValue.modifiedTempo
|
|
7431
|
+
millisecondOffset: syncPoint.syncPointValue.millisecondOffset
|
|
7357
7432
|
});
|
|
7358
7433
|
}
|
|
7359
7434
|
}
|
|
@@ -8692,6 +8767,7 @@
|
|
|
8692
8767
|
this._slurs = new Map();
|
|
8693
8768
|
this._articulationValueToIndex = new Map();
|
|
8694
8769
|
this._accidentalMode = AlphaTexAccidentalMode.Explicit;
|
|
8770
|
+
this._syncPoints = [];
|
|
8695
8771
|
this.logErrors = false;
|
|
8696
8772
|
}
|
|
8697
8773
|
get name() {
|
|
@@ -8732,10 +8808,16 @@
|
|
|
8732
8808
|
if (!anyMetaRead && !anyBarsRead) {
|
|
8733
8809
|
throw new UnsupportedFormatError('No alphaTex data found');
|
|
8734
8810
|
}
|
|
8811
|
+
if (this._sy === AlphaTexSymbols.Dot) {
|
|
8812
|
+
this._sy = this.newSy();
|
|
8813
|
+
this.syncPoints();
|
|
8814
|
+
}
|
|
8735
8815
|
}
|
|
8736
8816
|
ModelUtils.consolidate(this._score);
|
|
8737
8817
|
this._score.finish(this.settings);
|
|
8818
|
+
ModelUtils.trimEmptyBarsAtEnd(this._score);
|
|
8738
8819
|
this._score.rebuildRepeatGroups();
|
|
8820
|
+
this._score.applyFlatSyncPoints(this._syncPoints);
|
|
8739
8821
|
for (const [track, lyrics] of this._lyrics) {
|
|
8740
8822
|
this._score.tracks[track].applyLyrics(lyrics);
|
|
8741
8823
|
}
|
|
@@ -8752,6 +8834,47 @@
|
|
|
8752
8834
|
throw e;
|
|
8753
8835
|
}
|
|
8754
8836
|
}
|
|
8837
|
+
syncPoints() {
|
|
8838
|
+
while (this._sy !== AlphaTexSymbols.Eof) {
|
|
8839
|
+
this.syncPoint();
|
|
8840
|
+
}
|
|
8841
|
+
}
|
|
8842
|
+
syncPoint() {
|
|
8843
|
+
// \sync BarIndex Occurence MillisecondOffset
|
|
8844
|
+
// \sync BarIndex Occurence MillisecondOffset RatioPosition
|
|
8845
|
+
if (this._sy !== AlphaTexSymbols.MetaCommand || this._syData !== 'sync') {
|
|
8846
|
+
this.error('syncPoint', AlphaTexSymbols.MetaCommand, true);
|
|
8847
|
+
}
|
|
8848
|
+
this._sy = this.newSy();
|
|
8849
|
+
if (this._sy !== AlphaTexSymbols.Number) {
|
|
8850
|
+
this.error('syncPointBarIndex', AlphaTexSymbols.Number, true);
|
|
8851
|
+
}
|
|
8852
|
+
const barIndex = this._syData;
|
|
8853
|
+
this._sy = this.newSy();
|
|
8854
|
+
if (this._sy !== AlphaTexSymbols.Number) {
|
|
8855
|
+
this.error('syncPointBarOccurence', AlphaTexSymbols.Number, true);
|
|
8856
|
+
}
|
|
8857
|
+
const barOccurence = this._syData;
|
|
8858
|
+
this._sy = this.newSy();
|
|
8859
|
+
if (this._sy !== AlphaTexSymbols.Number) {
|
|
8860
|
+
this.error('syncPointBarMillis', AlphaTexSymbols.Number, true);
|
|
8861
|
+
}
|
|
8862
|
+
const millisecondOffset = this._syData;
|
|
8863
|
+
this._allowFloat = true;
|
|
8864
|
+
this._sy = this.newSy();
|
|
8865
|
+
this._allowFloat = false;
|
|
8866
|
+
let barPosition = 0;
|
|
8867
|
+
if (this._sy === AlphaTexSymbols.Number) {
|
|
8868
|
+
barPosition = this._syData;
|
|
8869
|
+
this._sy = this.newSy();
|
|
8870
|
+
}
|
|
8871
|
+
this._syncPoints.push({
|
|
8872
|
+
barIndex,
|
|
8873
|
+
barOccurence,
|
|
8874
|
+
barPosition,
|
|
8875
|
+
millisecondOffset
|
|
8876
|
+
});
|
|
8877
|
+
}
|
|
8755
8878
|
error(nonterm, expected, wrongSymbol = true) {
|
|
8756
8879
|
let receivedSymbol;
|
|
8757
8880
|
let showSyData = false;
|
|
@@ -14720,9 +14843,6 @@
|
|
|
14720
14843
|
case 'BarOccurrence':
|
|
14721
14844
|
syncPointValue.barOccurence = GpifParser.parseIntSafe(vc.innerText, 0);
|
|
14722
14845
|
break;
|
|
14723
|
-
case 'ModifiedTempo':
|
|
14724
|
-
syncPointValue.modifiedTempo = GpifParser.parseFloatSafe(vc.innerText, 0);
|
|
14725
|
-
break;
|
|
14726
14846
|
case 'FrameOffset':
|
|
14727
14847
|
const frameOffset = GpifParser.parseFloatSafe(vc.innerText, 0);
|
|
14728
14848
|
syncPointValue.millisecondOffset = (frameOffset / GpifParser.SampleRate) * 1000;
|
|
@@ -22345,6 +22465,61 @@
|
|
|
22345
22465
|
}
|
|
22346
22466
|
}
|
|
22347
22467
|
|
|
22468
|
+
/**
|
|
22469
|
+
* Rerpresents a point to sync the alphaTab time axis with an external backing track.
|
|
22470
|
+
*/
|
|
22471
|
+
class BackingTrackSyncPoint {
|
|
22472
|
+
constructor() {
|
|
22473
|
+
/**
|
|
22474
|
+
* The index of the masterbar to which this sync point belongs to.
|
|
22475
|
+
* @remarks
|
|
22476
|
+
* This property is purely informative for external use like in editors.
|
|
22477
|
+
* It has no impact to the synchronization itself.
|
|
22478
|
+
*/
|
|
22479
|
+
this.masterBarIndex = 0;
|
|
22480
|
+
/**
|
|
22481
|
+
* The occurence of the masterbar to which this sync point belongs to. The occurence
|
|
22482
|
+
* is 0-based and increases with every repeated play of a masterbar (e.g. on repeats or jumps).
|
|
22483
|
+
* @remarks
|
|
22484
|
+
* This property is purely informative for external use like in editors.
|
|
22485
|
+
* It has no impact to the synchronization itself.
|
|
22486
|
+
*/
|
|
22487
|
+
this.masterBarOccurence = 0;
|
|
22488
|
+
/**
|
|
22489
|
+
* The BPM the synthesizer has at the exact tick position of this sync point.
|
|
22490
|
+
*/
|
|
22491
|
+
this.synthBpm = 0;
|
|
22492
|
+
/**
|
|
22493
|
+
* The millisecond time position of the synthesizer when this sync point is reached.
|
|
22494
|
+
*/
|
|
22495
|
+
this.synthTime = 0;
|
|
22496
|
+
/**
|
|
22497
|
+
* The midi tick position of the synthesizer when this sync point is reached.
|
|
22498
|
+
*/
|
|
22499
|
+
this.synthTick = 0;
|
|
22500
|
+
/**
|
|
22501
|
+
* The millisecond time in the external media marking the synchronization point.
|
|
22502
|
+
*/
|
|
22503
|
+
this.syncTime = 0;
|
|
22504
|
+
/**
|
|
22505
|
+
* The BPM the song will have virtually after this sync point to align the external media time axis
|
|
22506
|
+
* with the one from the synthesizer.
|
|
22507
|
+
*/
|
|
22508
|
+
this.syncBpm = 0;
|
|
22509
|
+
}
|
|
22510
|
+
/**
|
|
22511
|
+
* Updates the synchronization BPM that will apply after this sync point.
|
|
22512
|
+
* @param nextSyncPointSynthTime The synthesizer time of the next sync point after this one.
|
|
22513
|
+
* @param nextSyncPointSyncTime The synchronization time of the next sync point after this one.
|
|
22514
|
+
*/
|
|
22515
|
+
updateSyncBpm(nextSyncPointSynthTime, nextSyncPointSyncTime) {
|
|
22516
|
+
const synthDuration = nextSyncPointSynthTime - this.synthTime;
|
|
22517
|
+
const syncedDuration = nextSyncPointSyncTime - this.syncTime;
|
|
22518
|
+
const modifiedTempo = (synthDuration / syncedDuration) * this.synthBpm;
|
|
22519
|
+
this.syncBpm = modifiedTempo;
|
|
22520
|
+
}
|
|
22521
|
+
}
|
|
22522
|
+
|
|
22348
22523
|
class MidiFileSequencerTempoChange {
|
|
22349
22524
|
constructor(bpm, ticks, time) {
|
|
22350
22525
|
this.bpm = bpm;
|
|
@@ -22352,14 +22527,6 @@
|
|
|
22352
22527
|
this.time = time;
|
|
22353
22528
|
}
|
|
22354
22529
|
}
|
|
22355
|
-
class BackingTrackSyncPointWithTime {
|
|
22356
|
-
constructor(tick, time, modifiedTempo, millisecondOffset) {
|
|
22357
|
-
this.alphaTabTick = tick;
|
|
22358
|
-
this.alphaTabTime = time;
|
|
22359
|
-
this.modifiedTempo = modifiedTempo;
|
|
22360
|
-
this.millisecondOffset = millisecondOffset;
|
|
22361
|
-
}
|
|
22362
|
-
}
|
|
22363
22530
|
class MidiSequencerState {
|
|
22364
22531
|
constructor() {
|
|
22365
22532
|
this.tempoChanges = [];
|
|
@@ -22463,7 +22630,7 @@
|
|
|
22463
22630
|
this._mainState.currentTempo = this._mainState.tempoChanges[0].bpm;
|
|
22464
22631
|
this._mainState.modifiedTempo =
|
|
22465
22632
|
this._mainState.syncPoints.length > 0
|
|
22466
|
-
? this._mainState.syncPoints[0].
|
|
22633
|
+
? this._mainState.syncPoints[0].syncBpm
|
|
22467
22634
|
: this._mainState.currentTempo;
|
|
22468
22635
|
if (this.isPlayingMain) {
|
|
22469
22636
|
const metronomeVolume = this._synthesizer.metronomeVolume;
|
|
@@ -22634,7 +22801,7 @@
|
|
|
22634
22801
|
}
|
|
22635
22802
|
mainUpdateSyncPoints(syncPoints) {
|
|
22636
22803
|
const state = this._mainState;
|
|
22637
|
-
syncPoints.sort((a, b) => a.
|
|
22804
|
+
syncPoints.sort((a, b) => a.synthTick - b.synthTick); // just in case
|
|
22638
22805
|
state.syncPoints = [];
|
|
22639
22806
|
if (syncPoints.length >= 0) {
|
|
22640
22807
|
let bpm = 120;
|
|
@@ -22644,6 +22811,8 @@
|
|
|
22644
22811
|
for (let i = 0; i < syncPoints.length; i++) {
|
|
22645
22812
|
const p = syncPoints[i];
|
|
22646
22813
|
let deltaTick = 0;
|
|
22814
|
+
// TODO: merge interpolation into MidiFileGenerator where we already play through
|
|
22815
|
+
// the time axis.
|
|
22647
22816
|
// remember state from previous sync point (or start). to handle linear interpolation
|
|
22648
22817
|
let previousModifiedTempo;
|
|
22649
22818
|
let previousMillisecondOffset;
|
|
@@ -22655,9 +22824,9 @@
|
|
|
22655
22824
|
}
|
|
22656
22825
|
else {
|
|
22657
22826
|
const previousSyncPoint = syncPoints[i - 1];
|
|
22658
|
-
previousModifiedTempo = previousSyncPoint.
|
|
22659
|
-
previousMillisecondOffset = previousSyncPoint.
|
|
22660
|
-
previousTick = previousSyncPoint.
|
|
22827
|
+
previousModifiedTempo = previousSyncPoint.syncBpm;
|
|
22828
|
+
previousMillisecondOffset = previousSyncPoint.syncTime;
|
|
22829
|
+
previousTick = previousSyncPoint.synthTick;
|
|
22661
22830
|
}
|
|
22662
22831
|
// process time until sync point
|
|
22663
22832
|
// here it gets a bit tricky. if we have tempo changes on the synthesizer time axis (inbetween two sync points)
|
|
@@ -22665,27 +22834,31 @@
|
|
|
22665
22834
|
// otherwise the linear interpolation later in the lookup will fail.
|
|
22666
22835
|
// goal is to have always a linear increase between two points, no matter if the time axis is sliced by tempo changes or sync points
|
|
22667
22836
|
while (tempoChangeIndex < state.tempoChanges.length &&
|
|
22668
|
-
state.tempoChanges[tempoChangeIndex].ticks <= p.
|
|
22837
|
+
state.tempoChanges[tempoChangeIndex].ticks <= p.synthTick) {
|
|
22669
22838
|
deltaTick = state.tempoChanges[tempoChangeIndex].ticks - absTick;
|
|
22670
22839
|
if (deltaTick > 0) {
|
|
22671
22840
|
absTick += deltaTick;
|
|
22672
22841
|
absTime += deltaTick * (60000.0 / (bpm * state.division));
|
|
22673
|
-
const millisPerTick = (p.
|
|
22842
|
+
const millisPerTick = (p.syncTime - previousMillisecondOffset) / (p.synthTick - previousTick);
|
|
22674
22843
|
const interpolatedMillisecondOffset = (absTick - previousTick) * millisPerTick + previousMillisecondOffset;
|
|
22675
|
-
|
|
22844
|
+
const syncPoint = new BackingTrackSyncPoint();
|
|
22845
|
+
syncPoint.synthTick = absTick;
|
|
22846
|
+
syncPoint.synthBpm = bpm;
|
|
22847
|
+
syncPoint.synthTime = absTime;
|
|
22848
|
+
syncPoint.syncTime = interpolatedMillisecondOffset;
|
|
22849
|
+
syncPoint.syncBpm = previousModifiedTempo;
|
|
22676
22850
|
}
|
|
22677
22851
|
bpm = state.tempoChanges[tempoChangeIndex].bpm;
|
|
22678
22852
|
tempoChangeIndex++;
|
|
22679
22853
|
}
|
|
22680
|
-
deltaTick = p.
|
|
22854
|
+
deltaTick = p.synthTick - absTick;
|
|
22681
22855
|
absTick += deltaTick;
|
|
22682
22856
|
absTime += deltaTick * (60000.0 / (bpm * state.division));
|
|
22683
|
-
state.syncPoints.push(
|
|
22857
|
+
state.syncPoints.push(p);
|
|
22684
22858
|
}
|
|
22685
22859
|
}
|
|
22686
22860
|
state.syncPointIndex = 0;
|
|
22687
|
-
state.modifiedTempo =
|
|
22688
|
-
state.syncPoints.length > 0 ? state.syncPoints[0].modifiedTempo : state.currentTempo;
|
|
22861
|
+
state.modifiedTempo = state.syncPoints.length > 0 ? state.syncPoints[0].syncBpm : state.currentTempo;
|
|
22689
22862
|
}
|
|
22690
22863
|
currentTimePositionToTickPosition(timePosition) {
|
|
22691
22864
|
const state = this._currentState;
|
|
@@ -22718,16 +22891,15 @@
|
|
|
22718
22891
|
const syncPoints = state.syncPoints;
|
|
22719
22892
|
if (syncPoints.length > 0) {
|
|
22720
22893
|
let syncPointIndex = Math.min(state.syncPointIndex, syncPoints.length - 1);
|
|
22721
|
-
if (timePosition < syncPoints[syncPointIndex].
|
|
22894
|
+
if (timePosition < syncPoints[syncPointIndex].syncTime) {
|
|
22722
22895
|
syncPointIndex = 0;
|
|
22723
22896
|
}
|
|
22724
|
-
while (syncPointIndex + 1 < syncPoints.length &&
|
|
22725
|
-
syncPoints[syncPointIndex + 1].millisecondOffset <= timePosition) {
|
|
22897
|
+
while (syncPointIndex + 1 < syncPoints.length && syncPoints[syncPointIndex + 1].syncTime <= timePosition) {
|
|
22726
22898
|
syncPointIndex++;
|
|
22727
22899
|
}
|
|
22728
22900
|
if (syncPointIndex !== state.syncPointIndex) {
|
|
22729
22901
|
state.syncPointIndex = syncPointIndex;
|
|
22730
|
-
state.modifiedTempo = syncPoints[syncPointIndex].
|
|
22902
|
+
state.modifiedTempo = syncPoints[syncPointIndex].syncBpm;
|
|
22731
22903
|
}
|
|
22732
22904
|
}
|
|
22733
22905
|
else {
|
|
@@ -22743,18 +22915,18 @@
|
|
|
22743
22915
|
this.updateSyncPoints(this._mainState, timePosition);
|
|
22744
22916
|
const syncPointIndex = Math.min(mainState.syncPointIndex, syncPoints.length - 1);
|
|
22745
22917
|
const currentSyncPoint = syncPoints[syncPointIndex];
|
|
22746
|
-
const timeDiff = timePosition - currentSyncPoint.
|
|
22918
|
+
const timeDiff = timePosition - currentSyncPoint.syncTime;
|
|
22747
22919
|
let alphaTabTimeDiff;
|
|
22748
22920
|
if (syncPointIndex + 1 < syncPoints.length) {
|
|
22749
22921
|
const nextSyncPoint = syncPoints[syncPointIndex + 1];
|
|
22750
|
-
const relativeTimeDiff = timeDiff / (nextSyncPoint.
|
|
22751
|
-
alphaTabTimeDiff = (nextSyncPoint.
|
|
22922
|
+
const relativeTimeDiff = timeDiff / (nextSyncPoint.syncTime - currentSyncPoint.syncTime);
|
|
22923
|
+
alphaTabTimeDiff = (nextSyncPoint.synthTime - currentSyncPoint.synthTime) * relativeTimeDiff;
|
|
22752
22924
|
}
|
|
22753
22925
|
else {
|
|
22754
|
-
const relativeTimeDiff = timeDiff / (backingTrackLength - currentSyncPoint.
|
|
22755
|
-
alphaTabTimeDiff = (mainState.endTime - currentSyncPoint.
|
|
22926
|
+
const relativeTimeDiff = timeDiff / (backingTrackLength - currentSyncPoint.syncTime);
|
|
22927
|
+
alphaTabTimeDiff = (mainState.endTime - currentSyncPoint.synthTime) * relativeTimeDiff;
|
|
22756
22928
|
}
|
|
22757
|
-
return (currentSyncPoint.
|
|
22929
|
+
return (currentSyncPoint.synthTime + alphaTabTimeDiff) / this.playbackSpeed;
|
|
22758
22930
|
}
|
|
22759
22931
|
mainTimePositionToBackingTrack(timePosition, backingTrackLength) {
|
|
22760
22932
|
const mainState = this._mainState;
|
|
@@ -22764,27 +22936,27 @@
|
|
|
22764
22936
|
}
|
|
22765
22937
|
timePosition *= this.playbackSpeed;
|
|
22766
22938
|
let syncPointIndex = Math.min(mainState.syncPointIndex, syncPoints.length - 1);
|
|
22767
|
-
if (timePosition < syncPoints[syncPointIndex].
|
|
22939
|
+
if (timePosition < syncPoints[syncPointIndex].synthTime) {
|
|
22768
22940
|
syncPointIndex = 0;
|
|
22769
22941
|
}
|
|
22770
|
-
while (syncPointIndex + 1 < syncPoints.length && syncPoints[syncPointIndex + 1].
|
|
22942
|
+
while (syncPointIndex + 1 < syncPoints.length && syncPoints[syncPointIndex + 1].synthTime <= timePosition) {
|
|
22771
22943
|
syncPointIndex++;
|
|
22772
22944
|
}
|
|
22773
22945
|
// NOTE: this logic heavily relies on the interpolation done in mainUpdateSyncPoints
|
|
22774
22946
|
// we ensure that we have a linear increase between two points
|
|
22775
22947
|
const currentSyncPoint = syncPoints[syncPointIndex];
|
|
22776
|
-
const alphaTabTimeDiff = timePosition - currentSyncPoint.
|
|
22948
|
+
const alphaTabTimeDiff = timePosition - currentSyncPoint.synthTime;
|
|
22777
22949
|
let backingTrackPos;
|
|
22778
22950
|
if (syncPointIndex + 1 < syncPoints.length) {
|
|
22779
22951
|
const nextSyncPoint = syncPoints[syncPointIndex + 1];
|
|
22780
|
-
const relativeAlphaTabTimeDiff = alphaTabTimeDiff / (nextSyncPoint.
|
|
22781
|
-
const backingTrackDiff = nextSyncPoint.
|
|
22782
|
-
backingTrackPos = currentSyncPoint.
|
|
22952
|
+
const relativeAlphaTabTimeDiff = alphaTabTimeDiff / (nextSyncPoint.synthTime - currentSyncPoint.synthTime);
|
|
22953
|
+
const backingTrackDiff = nextSyncPoint.syncTime - currentSyncPoint.syncTime;
|
|
22954
|
+
backingTrackPos = currentSyncPoint.syncTime + backingTrackDiff * relativeAlphaTabTimeDiff;
|
|
22783
22955
|
}
|
|
22784
22956
|
else {
|
|
22785
|
-
const relativeAlphaTabTimeDiff = alphaTabTimeDiff / (mainState.endTime - currentSyncPoint.
|
|
22786
|
-
const frameDiff = backingTrackLength - currentSyncPoint.
|
|
22787
|
-
backingTrackPos = currentSyncPoint.
|
|
22957
|
+
const relativeAlphaTabTimeDiff = alphaTabTimeDiff / (mainState.endTime - currentSyncPoint.synthTime);
|
|
22958
|
+
const frameDiff = backingTrackLength - currentSyncPoint.syncTime;
|
|
22959
|
+
backingTrackPos = currentSyncPoint.syncTime + frameDiff * relativeAlphaTabTimeDiff;
|
|
22788
22960
|
}
|
|
22789
22961
|
return backingTrackPos;
|
|
22790
22962
|
}
|
|
@@ -31056,7 +31228,6 @@
|
|
|
31056
31228
|
}
|
|
31057
31229
|
const o = new Map();
|
|
31058
31230
|
o.set("baroccurence", obj.barOccurence);
|
|
31059
|
-
o.set("modifiedtempo", obj.modifiedTempo);
|
|
31060
31231
|
o.set("millisecondoffset", obj.millisecondOffset);
|
|
31061
31232
|
return o;
|
|
31062
31233
|
}
|
|
@@ -31065,9 +31236,6 @@
|
|
|
31065
31236
|
case "baroccurence":
|
|
31066
31237
|
obj.barOccurence = v;
|
|
31067
31238
|
return true;
|
|
31068
|
-
case "modifiedtempo":
|
|
31069
|
-
obj.modifiedTempo = v;
|
|
31070
|
-
return true;
|
|
31071
31239
|
case "millisecondoffset":
|
|
31072
31240
|
obj.millisecondOffset = v;
|
|
31073
31241
|
return true;
|
|
@@ -33072,7 +33240,7 @@
|
|
|
33072
33240
|
addSamples(samples) {
|
|
33073
33241
|
this._worker.postMessage({
|
|
33074
33242
|
cmd: 'alphaSynth.output.addSamples',
|
|
33075
|
-
samples: samples
|
|
33243
|
+
samples: Environment.prepareForPostMessage(samples)
|
|
33076
33244
|
});
|
|
33077
33245
|
}
|
|
33078
33246
|
play() {
|
|
@@ -33268,7 +33436,7 @@
|
|
|
33268
33436
|
onSoundFontLoadFailed(e) {
|
|
33269
33437
|
this._main.postMessage({
|
|
33270
33438
|
cmd: 'alphaSynth.soundFontLoadFailed',
|
|
33271
|
-
error: this.serializeException(e)
|
|
33439
|
+
error: this.serializeException(Environment.prepareForPostMessage(e))
|
|
33272
33440
|
});
|
|
33273
33441
|
}
|
|
33274
33442
|
serializeException(e) {
|
|
@@ -33299,7 +33467,7 @@
|
|
|
33299
33467
|
onMidiLoadFailed(e) {
|
|
33300
33468
|
this._main.postMessage({
|
|
33301
33469
|
cmd: 'alphaSynth.midiLoaded',
|
|
33302
|
-
error: this.serializeException(e)
|
|
33470
|
+
error: this.serializeException(Environment.prepareForPostMessage(e))
|
|
33303
33471
|
});
|
|
33304
33472
|
}
|
|
33305
33473
|
onReadyForPlayback() {
|
|
@@ -35830,17 +35998,6 @@
|
|
|
35830
35998
|
}
|
|
35831
35999
|
}
|
|
35832
36000
|
|
|
35833
|
-
/**
|
|
35834
|
-
* Rerpresents a point to sync the alphaTab time axis with an external backing track.
|
|
35835
|
-
*/
|
|
35836
|
-
class BackingTrackSyncPoint {
|
|
35837
|
-
constructor(tick, data) {
|
|
35838
|
-
this.tick = 0;
|
|
35839
|
-
this.tick = tick;
|
|
35840
|
-
this.data = data;
|
|
35841
|
-
}
|
|
35842
|
-
}
|
|
35843
|
-
|
|
35844
36001
|
class MidiNoteDuration {
|
|
35845
36002
|
constructor() {
|
|
35846
36003
|
this.noteOnly = 0;
|
|
@@ -35861,6 +36018,14 @@
|
|
|
35861
36018
|
this.brushInfos = [];
|
|
35862
36019
|
}
|
|
35863
36020
|
}
|
|
36021
|
+
class PlayThroughContext {
|
|
36022
|
+
constructor() {
|
|
36023
|
+
this.synthTick = 0;
|
|
36024
|
+
this.synthTime = 0;
|
|
36025
|
+
this.currentTempo = 0;
|
|
36026
|
+
this.automationToSyncPoint = new Map();
|
|
36027
|
+
}
|
|
36028
|
+
}
|
|
35864
36029
|
/**
|
|
35865
36030
|
* This generator creates a midi file using a score.
|
|
35866
36031
|
*/
|
|
@@ -35987,9 +36152,22 @@
|
|
|
35987
36152
|
});
|
|
35988
36153
|
return syncPoints;
|
|
35989
36154
|
}
|
|
36155
|
+
/**
|
|
36156
|
+
* @internal
|
|
36157
|
+
*/
|
|
36158
|
+
static buildModifiedTempoLookup(score) {
|
|
36159
|
+
const syncPoints = [];
|
|
36160
|
+
const context = MidiFileGenerator.playThroughSong(score, syncPoints, (_masterBar, _previousMasterBar, _currentTick, _currentTempo, _barOccurence) => {
|
|
36161
|
+
}, (_barIndex, _currentTick, _currentTempo) => {
|
|
36162
|
+
}, _endTick => {
|
|
36163
|
+
});
|
|
36164
|
+
return context.automationToSyncPoint;
|
|
36165
|
+
}
|
|
35990
36166
|
static playThroughSong(score, syncPoints, generateMasterBar, generateTracks, finish) {
|
|
35991
36167
|
const controller = new MidiPlaybackController(score);
|
|
35992
|
-
|
|
36168
|
+
const playContext = new PlayThroughContext();
|
|
36169
|
+
playContext.currentTempo = score.tempo;
|
|
36170
|
+
playContext.syncPoints = syncPoints;
|
|
35993
36171
|
let previousMasterBar = null;
|
|
35994
36172
|
// store the previous played bar for repeats
|
|
35995
36173
|
const barOccurence = new Map();
|
|
@@ -36002,23 +36180,11 @@
|
|
|
36002
36180
|
let occurence = barOccurence.has(index) ? barOccurence.get(index) : -1;
|
|
36003
36181
|
occurence++;
|
|
36004
36182
|
barOccurence.set(index, occurence);
|
|
36005
|
-
generateMasterBar(bar, previousMasterBar, currentTick, currentTempo, occurence);
|
|
36006
|
-
const
|
|
36007
|
-
|
|
36008
|
-
|
|
36009
|
-
|
|
36010
|
-
const tick = currentTick + bar.calculateDuration() * syncPoint.ratioPosition;
|
|
36011
|
-
syncPoints.push(new BackingTrackSyncPoint(tick, syncPoint.syncPointValue));
|
|
36012
|
-
}
|
|
36013
|
-
}
|
|
36014
|
-
}
|
|
36015
|
-
if (bar.tempoAutomations.length > 0) {
|
|
36016
|
-
currentTempo = bar.tempoAutomations[0].value;
|
|
36017
|
-
}
|
|
36018
|
-
generateTracks(index, currentTick, currentTempo);
|
|
36019
|
-
if (bar.tempoAutomations.length > 0) {
|
|
36020
|
-
currentTempo = bar.tempoAutomations[bar.tempoAutomations.length - 1].value;
|
|
36021
|
-
}
|
|
36183
|
+
generateMasterBar(bar, previousMasterBar, currentTick, playContext.currentTempo, occurence);
|
|
36184
|
+
const trackTempo = bar.tempoAutomations.length > 0 ? bar.tempoAutomations[0].value : playContext.currentTempo;
|
|
36185
|
+
generateTracks(index, currentTick, trackTempo);
|
|
36186
|
+
playContext.synthTick = currentTick;
|
|
36187
|
+
MidiFileGenerator.processBarTime(bar, occurence, playContext);
|
|
36022
36188
|
}
|
|
36023
36189
|
controller.moveNext();
|
|
36024
36190
|
previousMasterBar = bar;
|
|
@@ -36029,21 +36195,119 @@
|
|
|
36029
36195
|
// but where it ends according to the BPM and the remaining ticks.
|
|
36030
36196
|
if (syncPoints.length > 0) {
|
|
36031
36197
|
const lastSyncPoint = syncPoints[syncPoints.length - 1];
|
|
36032
|
-
const remainingTicks = controller.currentTick - lastSyncPoint.
|
|
36198
|
+
const remainingTicks = controller.currentTick - lastSyncPoint.synthTick;
|
|
36033
36199
|
if (remainingTicks > 0) {
|
|
36034
|
-
const
|
|
36035
|
-
|
|
36036
|
-
|
|
36037
|
-
|
|
36038
|
-
|
|
36039
|
-
//
|
|
36040
|
-
|
|
36041
|
-
|
|
36042
|
-
|
|
36043
|
-
|
|
36200
|
+
const backingTrackSyncPoint = new BackingTrackSyncPoint();
|
|
36201
|
+
backingTrackSyncPoint.masterBarIndex = previousMasterBar.index;
|
|
36202
|
+
backingTrackSyncPoint.masterBarOccurence = barOccurence.get(previousMasterBar.index) - 1;
|
|
36203
|
+
backingTrackSyncPoint.synthTick = controller.currentTick;
|
|
36204
|
+
backingTrackSyncPoint.synthBpm = playContext.currentTempo;
|
|
36205
|
+
// we need to assume some BPM for the last interpolated point.
|
|
36206
|
+
// if we have more than just a start point, we keep the BPM before the last manual sync point
|
|
36207
|
+
// otherwise we have no customized sync BPM known and keep the synthesizer one.
|
|
36208
|
+
backingTrackSyncPoint.syncBpm =
|
|
36209
|
+
syncPoints.length > 1 ? syncPoints[syncPoints.length - 2].syncBpm : lastSyncPoint.synthBpm;
|
|
36210
|
+
backingTrackSyncPoint.synthTime =
|
|
36211
|
+
lastSyncPoint.synthTime + MidiUtils.ticksToMillis(remainingTicks, lastSyncPoint.synthBpm);
|
|
36212
|
+
backingTrackSyncPoint.syncTime =
|
|
36213
|
+
lastSyncPoint.syncTime + MidiUtils.ticksToMillis(remainingTicks, backingTrackSyncPoint.syncBpm);
|
|
36214
|
+
// update the previous sync point according to the new time
|
|
36215
|
+
lastSyncPoint.updateSyncBpm(backingTrackSyncPoint.synthTime, backingTrackSyncPoint.syncTime);
|
|
36216
|
+
syncPoints.push(backingTrackSyncPoint);
|
|
36044
36217
|
}
|
|
36045
36218
|
}
|
|
36046
36219
|
finish(controller.currentTick);
|
|
36220
|
+
return playContext;
|
|
36221
|
+
}
|
|
36222
|
+
static processBarTime(bar, occurence, context) {
|
|
36223
|
+
const duration = bar.calculateDuration();
|
|
36224
|
+
const barSyncPoints = bar.syncPoints;
|
|
36225
|
+
const barStartTick = context.synthTick;
|
|
36226
|
+
if (barSyncPoints) {
|
|
36227
|
+
MidiFileGenerator.processBarTimeWithSyncPoints(bar, occurence, context);
|
|
36228
|
+
}
|
|
36229
|
+
else {
|
|
36230
|
+
MidiFileGenerator.processBarTimeNoSyncPoints(bar, context);
|
|
36231
|
+
}
|
|
36232
|
+
// don't forget the part after the last tempo change
|
|
36233
|
+
const endTick = barStartTick + duration;
|
|
36234
|
+
const tickOffset = endTick - context.synthTick;
|
|
36235
|
+
if (tickOffset > 0) {
|
|
36236
|
+
context.synthTime += MidiUtils.ticksToMillis(tickOffset, context.currentTempo);
|
|
36237
|
+
context.synthTick = endTick;
|
|
36238
|
+
}
|
|
36239
|
+
}
|
|
36240
|
+
static processBarTimeWithSyncPoints(bar, occurence, context) {
|
|
36241
|
+
const barStartTick = context.synthTick;
|
|
36242
|
+
const duration = bar.calculateDuration();
|
|
36243
|
+
let tempoChangeIndex = 0;
|
|
36244
|
+
let tickOffset;
|
|
36245
|
+
for (const syncPoint of bar.syncPoints) {
|
|
36246
|
+
if (syncPoint.syncPointValue.barOccurence !== occurence) {
|
|
36247
|
+
continue;
|
|
36248
|
+
}
|
|
36249
|
+
const syncPointTick = barStartTick + syncPoint.ratioPosition * duration;
|
|
36250
|
+
// first process all tempo changes until this sync point
|
|
36251
|
+
while (tempoChangeIndex < bar.tempoAutomations.length &&
|
|
36252
|
+
bar.tempoAutomations[tempoChangeIndex].ratioPosition <= syncPoint.ratioPosition) {
|
|
36253
|
+
const tempoChange = bar.tempoAutomations[tempoChangeIndex];
|
|
36254
|
+
const absoluteTick = barStartTick + tempoChange.ratioPosition * duration;
|
|
36255
|
+
tickOffset = absoluteTick - context.synthTick;
|
|
36256
|
+
if (tickOffset > 0) {
|
|
36257
|
+
context.synthTick = absoluteTick;
|
|
36258
|
+
context.synthTime += MidiUtils.ticksToMillis(tickOffset, context.currentTempo);
|
|
36259
|
+
}
|
|
36260
|
+
context.currentTempo = tempoChange.value;
|
|
36261
|
+
tempoChangeIndex++;
|
|
36262
|
+
}
|
|
36263
|
+
// process time until sync point
|
|
36264
|
+
tickOffset = syncPointTick - context.synthTick;
|
|
36265
|
+
if (tickOffset > 0) {
|
|
36266
|
+
context.synthTick = syncPointTick;
|
|
36267
|
+
context.synthTime += MidiUtils.ticksToMillis(tickOffset, context.currentTempo);
|
|
36268
|
+
}
|
|
36269
|
+
// update the previous sync point according to the new time
|
|
36270
|
+
if (context.syncPoints.length > 0) {
|
|
36271
|
+
context.syncPoints[context.syncPoints.length - 1].updateSyncBpm(context.synthTime, syncPoint.syncPointValue.millisecondOffset);
|
|
36272
|
+
}
|
|
36273
|
+
// create the new sync point
|
|
36274
|
+
const backingTrackSyncPoint = new BackingTrackSyncPoint();
|
|
36275
|
+
backingTrackSyncPoint.masterBarIndex = bar.index;
|
|
36276
|
+
backingTrackSyncPoint.masterBarOccurence = occurence;
|
|
36277
|
+
backingTrackSyncPoint.synthTick = syncPointTick;
|
|
36278
|
+
backingTrackSyncPoint.synthBpm = context.currentTempo;
|
|
36279
|
+
backingTrackSyncPoint.synthTime = context.synthTime;
|
|
36280
|
+
backingTrackSyncPoint.syncTime = syncPoint.syncPointValue.millisecondOffset;
|
|
36281
|
+
backingTrackSyncPoint.syncBpm = 0 /* calculated by next sync point */;
|
|
36282
|
+
context.syncPoints.push(backingTrackSyncPoint);
|
|
36283
|
+
context.automationToSyncPoint.set(syncPoint, backingTrackSyncPoint);
|
|
36284
|
+
}
|
|
36285
|
+
// process remaining tempo changes after all sync points
|
|
36286
|
+
while (tempoChangeIndex < bar.tempoAutomations.length) {
|
|
36287
|
+
const tempoChange = bar.tempoAutomations[tempoChangeIndex];
|
|
36288
|
+
const absoluteTick = barStartTick + tempoChange.ratioPosition * duration;
|
|
36289
|
+
tickOffset = absoluteTick - context.synthTick;
|
|
36290
|
+
if (tickOffset > 0) {
|
|
36291
|
+
context.synthTick = absoluteTick;
|
|
36292
|
+
context.synthTime += MidiUtils.ticksToMillis(tickOffset, context.currentTempo);
|
|
36293
|
+
}
|
|
36294
|
+
context.currentTempo = tempoChange.value;
|
|
36295
|
+
tempoChangeIndex++;
|
|
36296
|
+
}
|
|
36297
|
+
}
|
|
36298
|
+
static processBarTimeNoSyncPoints(bar, context) {
|
|
36299
|
+
// walk through the tempo changes
|
|
36300
|
+
const barStartTick = context.synthTick;
|
|
36301
|
+
const duration = bar.calculateDuration();
|
|
36302
|
+
for (const changes of bar.tempoAutomations) {
|
|
36303
|
+
const absoluteTick = barStartTick + changes.ratioPosition * duration;
|
|
36304
|
+
const tickOffset = absoluteTick - context.synthTick;
|
|
36305
|
+
if (tickOffset > 0) {
|
|
36306
|
+
context.synthTick = absoluteTick;
|
|
36307
|
+
context.synthTime += MidiUtils.ticksToMillis(tickOffset, context.currentTempo);
|
|
36308
|
+
}
|
|
36309
|
+
context.currentTempo = changes.value;
|
|
36310
|
+
}
|
|
36047
36311
|
}
|
|
36048
36312
|
static toChannelShort(data) {
|
|
36049
36313
|
const value = Math.max(-32768, Math.min(32767, data * 8 - 1));
|
|
@@ -42328,6 +42592,18 @@
|
|
|
42328
42592
|
* available importers
|
|
42329
42593
|
*/
|
|
42330
42594
|
class ScoreLoader {
|
|
42595
|
+
/**
|
|
42596
|
+
* Loads the given alphaTex string.
|
|
42597
|
+
* @param tex The alphaTex string.
|
|
42598
|
+
* @param settings The settings to use for parsing.
|
|
42599
|
+
* @returns The parsed {@see Score}.
|
|
42600
|
+
*/
|
|
42601
|
+
static loadAlphaTex(tex, settings) {
|
|
42602
|
+
const parser = new AlphaTexImporter();
|
|
42603
|
+
parser.logErrors = true;
|
|
42604
|
+
parser.initFromString(tex, settings ?? new Settings());
|
|
42605
|
+
return parser.readScore();
|
|
42606
|
+
}
|
|
42331
42607
|
/**
|
|
42332
42608
|
* Loads a score asynchronously from the given datasource
|
|
42333
42609
|
* @param path the source path to load the binary file from
|
|
@@ -43178,7 +43454,7 @@
|
|
|
43178
43454
|
this._midiEventsPlayedFilter = value;
|
|
43179
43455
|
this._synth.postMessage({
|
|
43180
43456
|
cmd: 'alphaSynth.setMidiEventsPlayedFilter',
|
|
43181
|
-
value: value
|
|
43457
|
+
value: Environment.prepareForPostMessage(value)
|
|
43182
43458
|
});
|
|
43183
43459
|
}
|
|
43184
43460
|
get playbackSpeed() {
|
|
@@ -43243,7 +43519,7 @@
|
|
|
43243
43519
|
this._playbackRange = value;
|
|
43244
43520
|
this._synth.postMessage({
|
|
43245
43521
|
cmd: 'alphaSynth.setPlaybackRange',
|
|
43246
|
-
value: value
|
|
43522
|
+
value: Environment.prepareForPostMessage(value)
|
|
43247
43523
|
});
|
|
43248
43524
|
}
|
|
43249
43525
|
constructor(player, settings) {
|
|
@@ -43337,13 +43613,13 @@
|
|
|
43337
43613
|
playOneTimeMidiFile(midi) {
|
|
43338
43614
|
this._synth.postMessage({
|
|
43339
43615
|
cmd: 'alphaSynth.playOneTimeMidiFile',
|
|
43340
|
-
midi: JsonConverter.midiFileToJsObject(midi)
|
|
43616
|
+
midi: JsonConverter.midiFileToJsObject(Environment.prepareForPostMessage(midi))
|
|
43341
43617
|
});
|
|
43342
43618
|
}
|
|
43343
43619
|
loadSoundFont(data, append) {
|
|
43344
43620
|
this._synth.postMessage({
|
|
43345
43621
|
cmd: 'alphaSynth.loadSoundFontBytes',
|
|
43346
|
-
data: data,
|
|
43622
|
+
data: Environment.prepareForPostMessage(data),
|
|
43347
43623
|
append: append
|
|
43348
43624
|
});
|
|
43349
43625
|
}
|
|
@@ -43355,13 +43631,13 @@
|
|
|
43355
43631
|
loadMidiFile(midi) {
|
|
43356
43632
|
this._synth.postMessage({
|
|
43357
43633
|
cmd: 'alphaSynth.loadMidi',
|
|
43358
|
-
midi: JsonConverter.midiFileToJsObject(midi)
|
|
43634
|
+
midi: JsonConverter.midiFileToJsObject(Environment.prepareForPostMessage(midi))
|
|
43359
43635
|
});
|
|
43360
43636
|
}
|
|
43361
43637
|
applyTranspositionPitches(transpositionPitches) {
|
|
43362
43638
|
this._synth.postMessage({
|
|
43363
43639
|
cmd: 'alphaSynth.applyTranspositionPitches',
|
|
43364
|
-
transpositionPitches: JSON.stringify(Array.from(transpositionPitches.entries()))
|
|
43640
|
+
transpositionPitches: JSON.stringify(Array.from(Environment.prepareForPostMessage(transpositionPitches).entries()))
|
|
43365
43641
|
});
|
|
43366
43642
|
}
|
|
43367
43643
|
setChannelTranspositionPitch(channel, semitones) {
|
|
@@ -43533,7 +43809,7 @@
|
|
|
43533
43809
|
});
|
|
43534
43810
|
}
|
|
43535
43811
|
serializeSettingsForWorker(settings) {
|
|
43536
|
-
const jsObject = JsonConverter.settingsToJsObject(settings);
|
|
43812
|
+
const jsObject = JsonConverter.settingsToJsObject(Environment.prepareForPostMessage(settings));
|
|
43537
43813
|
// cut out player settings, they are only needed on UI thread side
|
|
43538
43814
|
jsObject.delete('player');
|
|
43539
43815
|
return jsObject;
|
|
@@ -43591,11 +43867,11 @@
|
|
|
43591
43867
|
}
|
|
43592
43868
|
}
|
|
43593
43869
|
renderScore(score, trackIndexes) {
|
|
43594
|
-
const jsObject = score == null ? null : JsonConverter.scoreToJsObject(score);
|
|
43870
|
+
const jsObject = score == null ? null : JsonConverter.scoreToJsObject(Environment.prepareForPostMessage(score));
|
|
43595
43871
|
this._worker.postMessage({
|
|
43596
43872
|
cmd: 'alphaTab.renderScore',
|
|
43597
43873
|
score: jsObject,
|
|
43598
|
-
trackIndexes: trackIndexes,
|
|
43874
|
+
trackIndexes: Environment.prepareForPostMessage(trackIndexes),
|
|
43599
43875
|
fontSizes: FontSizes.FontSizeLookupTables
|
|
43600
43876
|
});
|
|
43601
43877
|
}
|
|
@@ -43786,7 +44062,7 @@
|
|
|
43786
44062
|
addSamples(f) {
|
|
43787
44063
|
this._worklet?.port.postMessage({
|
|
43788
44064
|
cmd: AlphaSynthWorkerSynthOutput.CmdOutputAddSamples,
|
|
43789
|
-
samples: f
|
|
44065
|
+
samples: Environment.prepareForPostMessage(f)
|
|
43790
44066
|
});
|
|
43791
44067
|
}
|
|
43792
44068
|
resetSamples() {
|
|
@@ -61006,9 +61282,9 @@
|
|
|
61006
61282
|
print(`build date: ${VersionInfo.date}`);
|
|
61007
61283
|
}
|
|
61008
61284
|
}
|
|
61009
|
-
VersionInfo.version = '1.6.0-alpha.
|
|
61010
|
-
VersionInfo.date = '2025-05-
|
|
61011
|
-
VersionInfo.commit = '
|
|
61285
|
+
VersionInfo.version = '1.6.0-alpha.1432';
|
|
61286
|
+
VersionInfo.date = '2025-05-31T02:06:00.256Z';
|
|
61287
|
+
VersionInfo.commit = '91e41f1b2cf0b786a1ca2053f51cf3f370da4bc6';
|
|
61012
61288
|
|
|
61013
61289
|
/**
|
|
61014
61290
|
* A factory for custom layout engines.
|
|
@@ -61553,6 +61829,29 @@
|
|
|
61553
61829
|
print(`Screen Size: ${window.screen.width}x${window.screen.height}`);
|
|
61554
61830
|
}
|
|
61555
61831
|
}
|
|
61832
|
+
/**
|
|
61833
|
+
* Prepares the given object to be sent to workers. Web Frameworks like Vue might
|
|
61834
|
+
* create proxy objects for all objects used. This code handles the necessary unwrapping.
|
|
61835
|
+
* @internal
|
|
61836
|
+
* @target web
|
|
61837
|
+
*/
|
|
61838
|
+
static prepareForPostMessage(object) {
|
|
61839
|
+
if (!object) {
|
|
61840
|
+
return object;
|
|
61841
|
+
}
|
|
61842
|
+
// Vue toRaw:
|
|
61843
|
+
// https://github.com/vuejs/core/blob/e7381761cc7971c0d40ae0a0a72687a500fd8db3/packages/reactivity/src/reactive.ts#L378-L381
|
|
61844
|
+
if (typeof object === 'object') {
|
|
61845
|
+
const unwrapped = object.__v_raw;
|
|
61846
|
+
if (unwrapped) {
|
|
61847
|
+
return Environment.prepareForPostMessage(unwrapped);
|
|
61848
|
+
}
|
|
61849
|
+
}
|
|
61850
|
+
// Solidjs unwrap: the symbol required to access the raw object is unfortunately hidden and we cannot unwrap it without importing
|
|
61851
|
+
// import { unwrap } from "solid-js/store"
|
|
61852
|
+
// alternative for users is to replace this method during runtime.
|
|
61853
|
+
return object;
|
|
61854
|
+
}
|
|
61556
61855
|
}
|
|
61557
61856
|
Environment.StaffIdBeforeSlashAlways = 'before-slash-always';
|
|
61558
61857
|
Environment.StaffIdBeforeScoreAlways = 'before-score-always';
|
|
@@ -61824,6 +62123,7 @@
|
|
|
61824
62123
|
|
|
61825
62124
|
const _barrel$7 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
61826
62125
|
__proto__: null,
|
|
62126
|
+
AlphaTexImporter,
|
|
61827
62127
|
ScoreImporter,
|
|
61828
62128
|
ScoreLoader,
|
|
61829
62129
|
UnsupportedFormatError
|
|
@@ -62658,6 +62958,7 @@
|
|
|
62658
62958
|
: undefined;
|
|
62659
62959
|
const millisecondPadding = initialSyncPoint ? initialSyncPoint.syncPointValue.millisecondOffset : 0;
|
|
62660
62960
|
this.backingTrackFramePadding = (-1 * ((millisecondPadding / 1000) * GpifWriter.SampleRate)) | 0;
|
|
62961
|
+
const modifiedTempoLookup = new Lazy(() => MidiFileGenerator.buildModifiedTempoLookup(score));
|
|
62661
62962
|
for (const mb of score.masterBars) {
|
|
62662
62963
|
for (const automation of mb.tempoAutomations) {
|
|
62663
62964
|
const tempoAutomation = automations.addElement('Automation');
|
|
@@ -62682,7 +62983,7 @@
|
|
|
62682
62983
|
const value = syncPointAutomation.addElement('Value');
|
|
62683
62984
|
value.addElement('BarIndex').innerText = mb.index.toString();
|
|
62684
62985
|
value.addElement('BarOccurrence').innerText = syncPoint.syncPointValue.barOccurence.toString();
|
|
62685
|
-
value.addElement('ModifiedTempo').innerText = syncPoint.
|
|
62986
|
+
value.addElement('ModifiedTempo').innerText = modifiedTempoLookup.value.get(syncPoint).syncBpm.toString();
|
|
62686
62987
|
value.addElement('OriginalTempo').innerText = score.tempo.toString();
|
|
62687
62988
|
const frameOffset = (((syncPoint.syncPointValue.millisecondOffset - millisecondPadding) / 1000) *
|
|
62688
62989
|
GpifWriter.SampleRate) |
|