@coderline/alphatab 1.6.0-alpha.1405 → 1.6.0-alpha.1409
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 +952 -737
- package/dist/alphaTab.d.ts +41 -17
- package/dist/alphaTab.js +952 -737
- 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.1409 (develop, build 1409)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -22403,6 +22403,11 @@
|
|
|
22403
22403
|
this._mainState.eventIndex = 0;
|
|
22404
22404
|
this._mainState.syncPointIndex = 0;
|
|
22405
22405
|
this._mainState.tempoChangeIndex = 0;
|
|
22406
|
+
this._mainState.currentTempo = this._mainState.tempoChanges[0].bpm;
|
|
22407
|
+
this._mainState.modifiedTempo =
|
|
22408
|
+
this._mainState.syncPoints.length > 0
|
|
22409
|
+
? this._mainState.syncPoints[0].data.modifiedTempo
|
|
22410
|
+
: this._mainState.currentTempo;
|
|
22406
22411
|
if (this.isPlayingMain) {
|
|
22407
22412
|
const metronomeVolume = this._synthesizer.metronomeVolume;
|
|
22408
22413
|
this._synthesizer.noteOffAll(true);
|
|
@@ -22541,18 +22546,6 @@
|
|
|
22541
22546
|
this._currentState.synthData[this._currentState.eventIndex].time < this._currentState.currentTime) {
|
|
22542
22547
|
const synthEvent = this._currentState.synthData[this._currentState.eventIndex];
|
|
22543
22548
|
this._synthesizer.dispatchEvent(synthEvent);
|
|
22544
|
-
while (this._currentState.syncPointIndex < this._currentState.syncPoints.length &&
|
|
22545
|
-
this._currentState.syncPoints[this._currentState.syncPointIndex].tick < synthEvent.event.tick) {
|
|
22546
|
-
this._currentState.modifiedTempo =
|
|
22547
|
-
this._currentState.syncPoints[this._currentState.syncPointIndex].data.modifiedTempo;
|
|
22548
|
-
this._currentState.syncPointIndex++;
|
|
22549
|
-
}
|
|
22550
|
-
while (this._currentState.tempoChangeIndex < this._currentState.tempoChanges.length &&
|
|
22551
|
-
this._currentState.tempoChanges[this._currentState.tempoChangeIndex].time <= synthEvent.time) {
|
|
22552
|
-
this._currentState.currentTempo =
|
|
22553
|
-
this._currentState.tempoChanges[this._currentState.tempoChangeIndex].bpm;
|
|
22554
|
-
this._currentState.tempoChangeIndex++;
|
|
22555
|
-
}
|
|
22556
22549
|
this._currentState.eventIndex++;
|
|
22557
22550
|
anyEventsDispatched = true;
|
|
22558
22551
|
}
|
|
@@ -22582,9 +22575,6 @@
|
|
|
22582
22575
|
mainTickPositionToTimePosition(tickPosition) {
|
|
22583
22576
|
return this.tickPositionToTimePositionWithSpeed(this._mainState, tickPosition, this.playbackSpeed);
|
|
22584
22577
|
}
|
|
22585
|
-
mainTimePositionToTickPosition(timePosition) {
|
|
22586
|
-
return this.timePositionToTickPositionWithSpeed(this._mainState, timePosition, this.playbackSpeed);
|
|
22587
|
-
}
|
|
22588
22578
|
mainUpdateSyncPoints(syncPoints) {
|
|
22589
22579
|
const state = this._mainState;
|
|
22590
22580
|
syncPoints.sort((a, b) => a.tick - b.tick); // just in case
|
|
@@ -22612,7 +22602,49 @@
|
|
|
22612
22602
|
state.syncPointIndex = 0;
|
|
22613
22603
|
}
|
|
22614
22604
|
currentTimePositionToTickPosition(timePosition) {
|
|
22615
|
-
|
|
22605
|
+
const state = this._currentState;
|
|
22606
|
+
if (state.tempoChanges.length === 0) {
|
|
22607
|
+
return 0;
|
|
22608
|
+
}
|
|
22609
|
+
timePosition *= this.playbackSpeed;
|
|
22610
|
+
this.updateCurrentTempo(state, timePosition);
|
|
22611
|
+
const lastTempoChange = state.tempoChanges[state.tempoChangeIndex];
|
|
22612
|
+
const timeDiff = timePosition - lastTempoChange.time;
|
|
22613
|
+
const ticks = ((timeDiff / (60000.0 / (lastTempoChange.bpm * state.division))) | 0);
|
|
22614
|
+
// we add 1 for possible rounding errors.(floating point issuses)
|
|
22615
|
+
return lastTempoChange.ticks + ticks + 1;
|
|
22616
|
+
}
|
|
22617
|
+
updateCurrentTempo(state, timePosition) {
|
|
22618
|
+
let tempoChangeIndex = state.tempoChangeIndex;
|
|
22619
|
+
if (timePosition < state.tempoChanges[tempoChangeIndex].time) {
|
|
22620
|
+
tempoChangeIndex = 0;
|
|
22621
|
+
}
|
|
22622
|
+
while (tempoChangeIndex + 1 < state.tempoChanges.length &&
|
|
22623
|
+
state.tempoChanges[tempoChangeIndex + 1].time <= timePosition) {
|
|
22624
|
+
tempoChangeIndex++;
|
|
22625
|
+
}
|
|
22626
|
+
if (tempoChangeIndex !== state.tempoChangeIndex) {
|
|
22627
|
+
state.tempoChangeIndex = tempoChangeIndex;
|
|
22628
|
+
state.currentTempo = state.tempoChanges[state.tempoChangeIndex].bpm;
|
|
22629
|
+
}
|
|
22630
|
+
const syncPoints = state.syncPoints;
|
|
22631
|
+
if (syncPoints.length > 0) {
|
|
22632
|
+
let syncPointIndex = Math.min(state.syncPointIndex, syncPoints.length - 1);
|
|
22633
|
+
if (timePosition < syncPoints[syncPointIndex].data.millisecondOffset) {
|
|
22634
|
+
syncPointIndex = 0;
|
|
22635
|
+
}
|
|
22636
|
+
while (syncPointIndex + 1 < syncPoints.length &&
|
|
22637
|
+
syncPoints[syncPointIndex + 1].data.millisecondOffset <= timePosition) {
|
|
22638
|
+
syncPointIndex++;
|
|
22639
|
+
}
|
|
22640
|
+
if (syncPointIndex !== state.syncPointIndex) {
|
|
22641
|
+
state.syncPointIndex = syncPointIndex;
|
|
22642
|
+
state.modifiedTempo = syncPoints[syncPointIndex].data.modifiedTempo;
|
|
22643
|
+
}
|
|
22644
|
+
}
|
|
22645
|
+
else {
|
|
22646
|
+
state.modifiedTempo = state.currentTempo;
|
|
22647
|
+
}
|
|
22616
22648
|
}
|
|
22617
22649
|
mainTimePositionFromBackingTrack(timePosition, backingTrackLength) {
|
|
22618
22650
|
const mainState = this._mainState;
|
|
@@ -22620,11 +22652,8 @@
|
|
|
22620
22652
|
if (timePosition < 0 || syncPoints.length === 0) {
|
|
22621
22653
|
return timePosition;
|
|
22622
22654
|
}
|
|
22623
|
-
|
|
22624
|
-
|
|
22625
|
-
syncPoints[syncPointIndex + 1].data.millisecondOffset <= timePosition) {
|
|
22626
|
-
syncPointIndex++;
|
|
22627
|
-
}
|
|
22655
|
+
this.updateCurrentTempo(this._mainState, timePosition);
|
|
22656
|
+
const syncPointIndex = Math.min(mainState.syncPointIndex, syncPoints.length - 1);
|
|
22628
22657
|
const currentSyncPoint = syncPoints[syncPointIndex];
|
|
22629
22658
|
const timeDiff = timePosition - currentSyncPoint.data.millisecondOffset;
|
|
22630
22659
|
let alphaTabTimeDiff;
|
|
@@ -22646,7 +22675,10 @@
|
|
|
22646
22675
|
return timePosition;
|
|
22647
22676
|
}
|
|
22648
22677
|
timePosition *= this.playbackSpeed;
|
|
22649
|
-
let syncPointIndex =
|
|
22678
|
+
let syncPointIndex = Math.min(mainState.syncPointIndex, syncPoints.length - 1);
|
|
22679
|
+
if (timePosition < syncPoints[syncPointIndex].time) {
|
|
22680
|
+
syncPointIndex = 0;
|
|
22681
|
+
}
|
|
22650
22682
|
while (syncPointIndex + 1 < syncPoints.length && syncPoints[syncPointIndex + 1].time <= timePosition) {
|
|
22651
22683
|
syncPointIndex++;
|
|
22652
22684
|
}
|
|
@@ -22684,26 +22716,6 @@
|
|
|
22684
22716
|
timePosition += tickPosition * (60000.0 / (bpm * state.division));
|
|
22685
22717
|
return timePosition / playbackSpeed;
|
|
22686
22718
|
}
|
|
22687
|
-
timePositionToTickPositionWithSpeed(state, timePosition, playbackSpeed) {
|
|
22688
|
-
timePosition *= playbackSpeed;
|
|
22689
|
-
let ticks = 0;
|
|
22690
|
-
let bpm = 120.0;
|
|
22691
|
-
let lastChange = 0;
|
|
22692
|
-
// find start and bpm of last tempo change before time
|
|
22693
|
-
for (const c of state.tempoChanges) {
|
|
22694
|
-
if (timePosition < c.time) {
|
|
22695
|
-
break;
|
|
22696
|
-
}
|
|
22697
|
-
ticks = c.ticks;
|
|
22698
|
-
bpm = c.bpm;
|
|
22699
|
-
lastChange = c.time;
|
|
22700
|
-
}
|
|
22701
|
-
// add the missing ticks
|
|
22702
|
-
timePosition -= lastChange;
|
|
22703
|
-
ticks += (timePosition / (60000.0 / (bpm * state.division))) | 0;
|
|
22704
|
-
// we add 1 for possible rounding errors.(floating point issuses)
|
|
22705
|
-
return ticks + 1;
|
|
22706
|
-
}
|
|
22707
22719
|
get internalEndTime() {
|
|
22708
22720
|
if (this.isPlayingMain) {
|
|
22709
22721
|
return !this.mainPlaybackRange ? this._currentState.endTime : this._currentState.playbackRangeEndTime;
|
|
@@ -26922,7 +26934,7 @@
|
|
|
26922
26934
|
return processedEvents;
|
|
26923
26935
|
}
|
|
26924
26936
|
processMidiMessage(e) {
|
|
26925
|
-
Logger.debug('Midi', `Processing Midi message ${MidiEventType[e.type]}/${e.tick}`);
|
|
26937
|
+
//Logger.debug('Midi', `Processing Midi message ${MidiEventType[e.type]}/${e.tick}`);
|
|
26926
26938
|
const command = e.type;
|
|
26927
26939
|
switch (command) {
|
|
26928
26940
|
case MidiEventType.TimeSignature:
|
|
@@ -28043,6 +28055,9 @@
|
|
|
28043
28055
|
}
|
|
28044
28056
|
on(value) {
|
|
28045
28057
|
this._listeners.push(value);
|
|
28058
|
+
return () => {
|
|
28059
|
+
this.off(value);
|
|
28060
|
+
};
|
|
28046
28061
|
}
|
|
28047
28062
|
off(value) {
|
|
28048
28063
|
this._listeners = this._listeners.filter(l => l !== value);
|
|
@@ -28062,6 +28077,9 @@
|
|
|
28062
28077
|
}
|
|
28063
28078
|
on(value) {
|
|
28064
28079
|
this._listeners.push(value);
|
|
28080
|
+
return () => {
|
|
28081
|
+
this.off(value);
|
|
28082
|
+
};
|
|
28065
28083
|
}
|
|
28066
28084
|
off(value) {
|
|
28067
28085
|
this._listeners = this._listeners.filter(l => l !== value);
|
|
@@ -28458,7 +28476,7 @@
|
|
|
28458
28476
|
endTick = this.sequencer.currentEndTick;
|
|
28459
28477
|
}
|
|
28460
28478
|
if (this._tickPosition >= endTick) {
|
|
28461
|
-
// fully done with playback of remaining samples?
|
|
28479
|
+
// fully done with playback of remaining samples?
|
|
28462
28480
|
if (this._notPlayedSamples <= 0) {
|
|
28463
28481
|
this._notPlayedSamples = 0;
|
|
28464
28482
|
if (this.sequencer.isPlayingCountIn) {
|
|
@@ -35808,6 +35826,27 @@
|
|
|
35808
35826
|
controller.moveNext();
|
|
35809
35827
|
previousMasterBar = bar;
|
|
35810
35828
|
}
|
|
35829
|
+
// here we interpolate the sync point which marks the end of the sync.
|
|
35830
|
+
// Sync points define new tempos at certain positions.
|
|
35831
|
+
// looking from the last sync point to the end we do not assume the end where the audio ends,
|
|
35832
|
+
// but where it ends according to the BPM and the remaining ticks.
|
|
35833
|
+
if (this.syncPoints.length > 0) {
|
|
35834
|
+
const lastSyncPoint = this.syncPoints[this.syncPoints.length - 1];
|
|
35835
|
+
const endTick = controller.currentTick;
|
|
35836
|
+
const remainingTicks = endTick - lastSyncPoint.tick;
|
|
35837
|
+
if (remainingTicks > 0) {
|
|
35838
|
+
const syncPointData = new SyncPointData();
|
|
35839
|
+
// last occurence of the last bar
|
|
35840
|
+
syncPointData.barOccurence = barOccurence.get(this._score.masterBars.length - 1);
|
|
35841
|
+
// same tempo as last point
|
|
35842
|
+
syncPointData.modifiedTempo = lastSyncPoint.data.modifiedTempo;
|
|
35843
|
+
// interpolated end from last syncPoint
|
|
35844
|
+
syncPointData.millisecondOffset =
|
|
35845
|
+
lastSyncPoint.data.millisecondOffset +
|
|
35846
|
+
MidiUtils.ticksToMillis(remainingTicks, syncPointData.modifiedTempo);
|
|
35847
|
+
this.syncPoints.push(new BackingTrackSyncPoint(endTick, syncPointData));
|
|
35848
|
+
}
|
|
35849
|
+
}
|
|
35811
35850
|
for (const track of this._score.tracks) {
|
|
35812
35851
|
this._handler.finishTrack(track.index, controller.currentTick);
|
|
35813
35852
|
}
|
|
@@ -38299,6 +38338,270 @@
|
|
|
38299
38338
|
}
|
|
38300
38339
|
}
|
|
38301
38340
|
|
|
38341
|
+
/**
|
|
38342
|
+
* A {@link IAlphaSynth} implementation wrapping and underling other {@link IAlphaSynth}
|
|
38343
|
+
* allowing dynamic changing of the underlying instance without loosing aspects like the
|
|
38344
|
+
* main playback information and event listeners.
|
|
38345
|
+
*
|
|
38346
|
+
* @remarks
|
|
38347
|
+
* This wrapper is used when re-exposing the underlying player via {@link AlphaTabApiBase} to integrators.
|
|
38348
|
+
* Even with dynamic switching between synthesizer, backing tracks etc. aspects like volume, playbackspeed,
|
|
38349
|
+
* event listeners etc. should not be lost.
|
|
38350
|
+
*/
|
|
38351
|
+
class AlphaSynthWrapper {
|
|
38352
|
+
constructor() {
|
|
38353
|
+
// relevant state information we want to remember when switching between player instances
|
|
38354
|
+
this._masterVolume = 1;
|
|
38355
|
+
this._metronomeVolume = 0;
|
|
38356
|
+
this._countInVolume = 0;
|
|
38357
|
+
this._playbackSpeed = 1;
|
|
38358
|
+
this._isLooping = false;
|
|
38359
|
+
this._midiEventsPlayedFilter = [];
|
|
38360
|
+
this.ready = new EventEmitter();
|
|
38361
|
+
this.readyForPlayback = new EventEmitter();
|
|
38362
|
+
this.finished = new EventEmitter();
|
|
38363
|
+
this.soundFontLoaded = new EventEmitter();
|
|
38364
|
+
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
38365
|
+
this.midiLoaded = new EventEmitterOfT();
|
|
38366
|
+
this.midiLoadFailed = new EventEmitterOfT();
|
|
38367
|
+
this.stateChanged = new EventEmitterOfT();
|
|
38368
|
+
this.positionChanged = new EventEmitterOfT();
|
|
38369
|
+
this.midiEventsPlayed = new EventEmitterOfT();
|
|
38370
|
+
this.playbackRangeChanged = new EventEmitterOfT();
|
|
38371
|
+
}
|
|
38372
|
+
get instance() {
|
|
38373
|
+
return this._instance;
|
|
38374
|
+
}
|
|
38375
|
+
set instance(value) {
|
|
38376
|
+
this._instance = value;
|
|
38377
|
+
// unregister all events from previous instance
|
|
38378
|
+
const unregister = this._instanceEventUnregister;
|
|
38379
|
+
if (unregister) {
|
|
38380
|
+
for (const e of unregister) {
|
|
38381
|
+
e();
|
|
38382
|
+
}
|
|
38383
|
+
}
|
|
38384
|
+
if (value) {
|
|
38385
|
+
// regsiter to events of new player and forward them to existing listeners
|
|
38386
|
+
const newUnregister = [];
|
|
38387
|
+
newUnregister.push(value.ready.on(() => this.ready.trigger()));
|
|
38388
|
+
newUnregister.push(value.readyForPlayback.on(() => this.readyForPlayback.trigger()));
|
|
38389
|
+
newUnregister.push(value.finished.on(() => this.finished.trigger()));
|
|
38390
|
+
newUnregister.push(value.soundFontLoaded.on(() => this.soundFontLoaded.trigger()));
|
|
38391
|
+
newUnregister.push(value.soundFontLoadFailed.on(e => this.soundFontLoadFailed.trigger(e)));
|
|
38392
|
+
newUnregister.push(value.midiLoaded.on(e => this.midiLoaded.trigger(e)));
|
|
38393
|
+
newUnregister.push(value.midiLoadFailed.on(e => this.midiLoadFailed.trigger(e)));
|
|
38394
|
+
newUnregister.push(value.stateChanged.on(e => this.stateChanged.trigger(e)));
|
|
38395
|
+
newUnregister.push(value.positionChanged.on(e => this.positionChanged.trigger(e)));
|
|
38396
|
+
newUnregister.push(value.midiEventsPlayed.on(e => this.midiEventsPlayed.trigger(e)));
|
|
38397
|
+
newUnregister.push(value.playbackRangeChanged.on(e => this.playbackRangeChanged.trigger(e)));
|
|
38398
|
+
this._instanceEventUnregister = newUnregister;
|
|
38399
|
+
// restore state on new player
|
|
38400
|
+
if (this.isReady) {
|
|
38401
|
+
value.masterVolume = this._masterVolume;
|
|
38402
|
+
value.metronomeVolume = this._metronomeVolume;
|
|
38403
|
+
value.countInVolume = this._countInVolume;
|
|
38404
|
+
value.playbackSpeed = this._playbackSpeed;
|
|
38405
|
+
value.isLooping = this._isLooping;
|
|
38406
|
+
value.midiEventsPlayedFilter = this._midiEventsPlayedFilter;
|
|
38407
|
+
}
|
|
38408
|
+
else {
|
|
38409
|
+
newUnregister.push(value.ready.on(() => {
|
|
38410
|
+
value.masterVolume = this._masterVolume;
|
|
38411
|
+
value.metronomeVolume = this._metronomeVolume;
|
|
38412
|
+
value.countInVolume = this._countInVolume;
|
|
38413
|
+
value.playbackSpeed = this._playbackSpeed;
|
|
38414
|
+
value.isLooping = this._isLooping;
|
|
38415
|
+
value.midiEventsPlayedFilter = this._midiEventsPlayedFilter;
|
|
38416
|
+
}));
|
|
38417
|
+
}
|
|
38418
|
+
}
|
|
38419
|
+
else {
|
|
38420
|
+
this._instanceEventUnregister = undefined;
|
|
38421
|
+
}
|
|
38422
|
+
}
|
|
38423
|
+
get output() {
|
|
38424
|
+
return this._instance.output;
|
|
38425
|
+
}
|
|
38426
|
+
get isReady() {
|
|
38427
|
+
return this._instance ? this._instance.isReady : false;
|
|
38428
|
+
}
|
|
38429
|
+
get isReadyForPlayback() {
|
|
38430
|
+
return this._instance ? this._instance.isReadyForPlayback : false;
|
|
38431
|
+
}
|
|
38432
|
+
get state() {
|
|
38433
|
+
return this._instance ? this._instance.state : PlayerState.Paused;
|
|
38434
|
+
}
|
|
38435
|
+
get logLevel() {
|
|
38436
|
+
return Logger.logLevel;
|
|
38437
|
+
}
|
|
38438
|
+
set logLevel(value) {
|
|
38439
|
+
Logger.logLevel = value;
|
|
38440
|
+
if (this._instance) {
|
|
38441
|
+
this._instance.logLevel = value;
|
|
38442
|
+
}
|
|
38443
|
+
}
|
|
38444
|
+
get masterVolume() {
|
|
38445
|
+
return this._masterVolume;
|
|
38446
|
+
}
|
|
38447
|
+
set masterVolume(value) {
|
|
38448
|
+
value = Math.max(value, SynthConstants.MinVolume);
|
|
38449
|
+
this._masterVolume = value;
|
|
38450
|
+
if (this._instance) {
|
|
38451
|
+
this._instance.masterVolume = value;
|
|
38452
|
+
}
|
|
38453
|
+
}
|
|
38454
|
+
get metronomeVolume() {
|
|
38455
|
+
return this._metronomeVolume;
|
|
38456
|
+
}
|
|
38457
|
+
set metronomeVolume(value) {
|
|
38458
|
+
value = Math.max(value, SynthConstants.MinVolume);
|
|
38459
|
+
this._metronomeVolume = value;
|
|
38460
|
+
if (this._instance) {
|
|
38461
|
+
this._instance.metronomeVolume = value;
|
|
38462
|
+
}
|
|
38463
|
+
}
|
|
38464
|
+
get playbackSpeed() {
|
|
38465
|
+
return this._playbackSpeed;
|
|
38466
|
+
}
|
|
38467
|
+
set playbackSpeed(value) {
|
|
38468
|
+
this._playbackSpeed = value;
|
|
38469
|
+
if (this._instance) {
|
|
38470
|
+
this._instance.playbackSpeed = value;
|
|
38471
|
+
}
|
|
38472
|
+
}
|
|
38473
|
+
get tickPosition() {
|
|
38474
|
+
return this._instance ? this._instance.tickPosition : 0;
|
|
38475
|
+
}
|
|
38476
|
+
set tickPosition(value) {
|
|
38477
|
+
if (this._instance) {
|
|
38478
|
+
this._instance.tickPosition = value;
|
|
38479
|
+
}
|
|
38480
|
+
}
|
|
38481
|
+
get timePosition() {
|
|
38482
|
+
return this._instance ? this._instance.timePosition : 0;
|
|
38483
|
+
}
|
|
38484
|
+
set timePosition(value) {
|
|
38485
|
+
if (this._instance) {
|
|
38486
|
+
this._instance.timePosition = value;
|
|
38487
|
+
}
|
|
38488
|
+
}
|
|
38489
|
+
get playbackRange() {
|
|
38490
|
+
return this._instance ? this._instance.playbackRange : null;
|
|
38491
|
+
}
|
|
38492
|
+
set playbackRange(value) {
|
|
38493
|
+
if (this._instance) {
|
|
38494
|
+
this._instance.playbackRange = value;
|
|
38495
|
+
}
|
|
38496
|
+
}
|
|
38497
|
+
get isLooping() {
|
|
38498
|
+
return this._isLooping;
|
|
38499
|
+
}
|
|
38500
|
+
set isLooping(value) {
|
|
38501
|
+
this._isLooping = value;
|
|
38502
|
+
if (this._instance) {
|
|
38503
|
+
this._instance.isLooping = value;
|
|
38504
|
+
}
|
|
38505
|
+
}
|
|
38506
|
+
get countInVolume() {
|
|
38507
|
+
return this._countInVolume;
|
|
38508
|
+
}
|
|
38509
|
+
set countInVolume(value) {
|
|
38510
|
+
this._countInVolume = value;
|
|
38511
|
+
if (this._instance) {
|
|
38512
|
+
this._instance.countInVolume = value;
|
|
38513
|
+
}
|
|
38514
|
+
}
|
|
38515
|
+
get midiEventsPlayedFilter() {
|
|
38516
|
+
return this._midiEventsPlayedFilter;
|
|
38517
|
+
}
|
|
38518
|
+
set midiEventsPlayedFilter(value) {
|
|
38519
|
+
this._midiEventsPlayedFilter = value;
|
|
38520
|
+
if (this._instance) {
|
|
38521
|
+
this._instance.midiEventsPlayedFilter = value;
|
|
38522
|
+
}
|
|
38523
|
+
}
|
|
38524
|
+
destroy() {
|
|
38525
|
+
if (this._instance) {
|
|
38526
|
+
this._instance.destroy();
|
|
38527
|
+
this._instance = undefined;
|
|
38528
|
+
}
|
|
38529
|
+
}
|
|
38530
|
+
play() {
|
|
38531
|
+
return this._instance ? this._instance.play() : false;
|
|
38532
|
+
}
|
|
38533
|
+
pause() {
|
|
38534
|
+
if (this._instance) {
|
|
38535
|
+
this._instance.pause();
|
|
38536
|
+
}
|
|
38537
|
+
}
|
|
38538
|
+
playPause() {
|
|
38539
|
+
if (this._instance) {
|
|
38540
|
+
this._instance.playPause();
|
|
38541
|
+
}
|
|
38542
|
+
}
|
|
38543
|
+
stop() {
|
|
38544
|
+
if (this._instance) {
|
|
38545
|
+
this._instance.stop();
|
|
38546
|
+
}
|
|
38547
|
+
}
|
|
38548
|
+
playOneTimeMidiFile(midi) {
|
|
38549
|
+
if (this._instance) {
|
|
38550
|
+
this._instance.playOneTimeMidiFile(midi);
|
|
38551
|
+
}
|
|
38552
|
+
}
|
|
38553
|
+
loadSoundFont(data, append) {
|
|
38554
|
+
if (this._instance) {
|
|
38555
|
+
this._instance.loadSoundFont(data, append);
|
|
38556
|
+
}
|
|
38557
|
+
}
|
|
38558
|
+
resetSoundFonts() {
|
|
38559
|
+
if (this._instance) {
|
|
38560
|
+
this._instance.resetSoundFonts();
|
|
38561
|
+
}
|
|
38562
|
+
}
|
|
38563
|
+
loadMidiFile(midi) {
|
|
38564
|
+
if (this._instance) {
|
|
38565
|
+
this._instance.loadMidiFile(midi);
|
|
38566
|
+
}
|
|
38567
|
+
}
|
|
38568
|
+
loadBackingTrack(score, syncPoints) {
|
|
38569
|
+
if (this._instance) {
|
|
38570
|
+
this._instance.loadBackingTrack(score, syncPoints);
|
|
38571
|
+
}
|
|
38572
|
+
}
|
|
38573
|
+
applyTranspositionPitches(transpositionPitches) {
|
|
38574
|
+
if (this._instance) {
|
|
38575
|
+
this._instance.applyTranspositionPitches(transpositionPitches);
|
|
38576
|
+
}
|
|
38577
|
+
}
|
|
38578
|
+
setChannelTranspositionPitch(channel, semitones) {
|
|
38579
|
+
if (this._instance) {
|
|
38580
|
+
this._instance.setChannelTranspositionPitch(channel, semitones);
|
|
38581
|
+
}
|
|
38582
|
+
}
|
|
38583
|
+
setChannelMute(channel, mute) {
|
|
38584
|
+
if (this._instance) {
|
|
38585
|
+
this._instance.setChannelMute(channel, mute);
|
|
38586
|
+
}
|
|
38587
|
+
}
|
|
38588
|
+
resetChannelStates() {
|
|
38589
|
+
if (this._instance) {
|
|
38590
|
+
this._instance.resetChannelStates();
|
|
38591
|
+
}
|
|
38592
|
+
}
|
|
38593
|
+
setChannelSolo(channel, solo) {
|
|
38594
|
+
if (this._instance) {
|
|
38595
|
+
this._instance.setChannelSolo(channel, solo);
|
|
38596
|
+
}
|
|
38597
|
+
}
|
|
38598
|
+
setChannelVolume(channel, volume) {
|
|
38599
|
+
if (this._instance) {
|
|
38600
|
+
this._instance.setChannelVolume(channel, volume);
|
|
38601
|
+
}
|
|
38602
|
+
}
|
|
38603
|
+
}
|
|
38604
|
+
|
|
38302
38605
|
class SelectionInfo {
|
|
38303
38606
|
constructor(beat) {
|
|
38304
38607
|
this.bounds = null;
|
|
@@ -38389,43 +38692,13 @@
|
|
|
38389
38692
|
this._tracks = [];
|
|
38390
38693
|
this._actualPlayerMode = exports.PlayerMode.Disabled;
|
|
38391
38694
|
this._tickCache = null;
|
|
38392
|
-
/**
|
|
38393
|
-
* The alphaSynth player used for playback.
|
|
38394
|
-
* @remarks
|
|
38395
|
-
* This is the low-level API to the Midi synthesizer used for playback.
|
|
38396
|
-
* Gets access to the underling {@link IAlphaSynth} that is used for the audio playback.
|
|
38397
|
-
* @category Properties - Player
|
|
38398
|
-
* @since 0.9.4
|
|
38399
|
-
* @example
|
|
38400
|
-
* JavaScript
|
|
38401
|
-
* ```js
|
|
38402
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
38403
|
-
* setupPlayerEvents(api.settings);
|
|
38404
|
-
* ```
|
|
38405
|
-
*
|
|
38406
|
-
* @example
|
|
38407
|
-
* C#
|
|
38408
|
-
* ```cs
|
|
38409
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
38410
|
-
* SetupPlayerEvents(api.Player);
|
|
38411
|
-
* ```
|
|
38412
|
-
*
|
|
38413
|
-
* @example
|
|
38414
|
-
* Android
|
|
38415
|
-
* ```kotlin
|
|
38416
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
38417
|
-
* setupPlayerEvents(api.player)
|
|
38418
|
-
* ```
|
|
38419
|
-
*/
|
|
38420
|
-
this.player = null;
|
|
38421
38695
|
this._cursorWrapper = null;
|
|
38422
38696
|
this._barCursor = null;
|
|
38423
38697
|
this._beatCursor = null;
|
|
38424
38698
|
this._selectionWrapper = null;
|
|
38425
38699
|
this._previousTick = 0;
|
|
38426
|
-
this._playerState = PlayerState.Paused;
|
|
38427
38700
|
this._currentBeat = null;
|
|
38428
|
-
this.
|
|
38701
|
+
this._currentBeatBounds = null;
|
|
38429
38702
|
this._previousStateForCursor = PlayerState.Paused;
|
|
38430
38703
|
this._previousCursorCache = null;
|
|
38431
38704
|
this._lastScroll = 0;
|
|
@@ -38996,133 +39269,6 @@
|
|
|
38996
39269
|
*
|
|
38997
39270
|
*/
|
|
38998
39271
|
this.error = new EventEmitterOfT();
|
|
38999
|
-
/**
|
|
39000
|
-
* This event is fired when all required data for playback is loaded and ready.
|
|
39001
|
-
* @remarks
|
|
39002
|
-
* This event is fired when all required data for playback is loaded and ready. The player is ready for playback when
|
|
39003
|
-
* all background workers are started, the audio output is initialized, a soundfont is loaded, and a song was loaded into the player as midi file.
|
|
39004
|
-
*
|
|
39005
|
-
* @eventProperty
|
|
39006
|
-
* @category Events - Player
|
|
39007
|
-
* @since 0.9.4
|
|
39008
|
-
*
|
|
39009
|
-
* @example
|
|
39010
|
-
* JavaScript
|
|
39011
|
-
* ```js
|
|
39012
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39013
|
-
* api.playerReady.on(() => {
|
|
39014
|
-
* enablePlayerControls();
|
|
39015
|
-
* });
|
|
39016
|
-
* ```
|
|
39017
|
-
*
|
|
39018
|
-
* @example
|
|
39019
|
-
* C#
|
|
39020
|
-
* ```cs
|
|
39021
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39022
|
-
* api.PlayerReady.On(() =>
|
|
39023
|
-
* {
|
|
39024
|
-
* EnablePlayerControls()
|
|
39025
|
-
* });
|
|
39026
|
-
* ```
|
|
39027
|
-
*
|
|
39028
|
-
* @example
|
|
39029
|
-
* Android
|
|
39030
|
-
* ```kotlin
|
|
39031
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
39032
|
-
* api.playerReady.on {
|
|
39033
|
-
* enablePlayerControls()
|
|
39034
|
-
* }
|
|
39035
|
-
* ```
|
|
39036
|
-
*/
|
|
39037
|
-
this.playerReady = new EventEmitter();
|
|
39038
|
-
/**
|
|
39039
|
-
* This event is fired when the playback of the whole song finished.
|
|
39040
|
-
* @remarks
|
|
39041
|
-
* This event is finished regardless on whether looping is enabled or not.
|
|
39042
|
-
*
|
|
39043
|
-
* @eventProperty
|
|
39044
|
-
* @category Events - Player
|
|
39045
|
-
* @since 0.9.4
|
|
39046
|
-
*
|
|
39047
|
-
* @example
|
|
39048
|
-
* JavaScript
|
|
39049
|
-
* ```js
|
|
39050
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39051
|
-
* api.playerFinished.on((args) => {
|
|
39052
|
-
* // speed trainer
|
|
39053
|
-
* api.playbackSpeed = Math.min(1.0, api.playbackSpeed + 0.1);
|
|
39054
|
-
* });
|
|
39055
|
-
* api.isLooping = true;
|
|
39056
|
-
* api.playbackSpeed = 0.5;
|
|
39057
|
-
* api.play()
|
|
39058
|
-
* ```
|
|
39059
|
-
*
|
|
39060
|
-
* @example
|
|
39061
|
-
* C#
|
|
39062
|
-
* ```cs
|
|
39063
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39064
|
-
* api.PlayerFinished.On(() =>
|
|
39065
|
-
* {
|
|
39066
|
-
* // speed trainer
|
|
39067
|
-
* api.PlaybackSpeed = Math.Min(1.0, api.PlaybackSpeed + 0.1);
|
|
39068
|
-
* });
|
|
39069
|
-
* api.IsLooping = true;
|
|
39070
|
-
* api.PlaybackSpeed = 0.5;
|
|
39071
|
-
* api.Play();
|
|
39072
|
-
* ```
|
|
39073
|
-
*
|
|
39074
|
-
* @example
|
|
39075
|
-
* Android
|
|
39076
|
-
* ```kotlin
|
|
39077
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
39078
|
-
* api.playerFinished.on {
|
|
39079
|
-
* // speed trainer
|
|
39080
|
-
* api.playbackSpeed = min(1.0, api.playbackSpeed + 0.1);
|
|
39081
|
-
* }
|
|
39082
|
-
* api.isLooping = true
|
|
39083
|
-
* api.playbackSpeed = 0.5
|
|
39084
|
-
* api.play()
|
|
39085
|
-
* ```
|
|
39086
|
-
*
|
|
39087
|
-
*/
|
|
39088
|
-
this.playerFinished = new EventEmitter();
|
|
39089
|
-
/**
|
|
39090
|
-
* This event is fired when the SoundFont needed for playback was loaded.
|
|
39091
|
-
*
|
|
39092
|
-
* @eventProperty
|
|
39093
|
-
* @category Events - Player
|
|
39094
|
-
* @since 0.9.4
|
|
39095
|
-
*
|
|
39096
|
-
* @example
|
|
39097
|
-
* JavaScript
|
|
39098
|
-
* ```js
|
|
39099
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39100
|
-
* api.soundFontLoaded.on(() => {
|
|
39101
|
-
* hideSoundFontLoadingIndicator();
|
|
39102
|
-
* });
|
|
39103
|
-
* ```
|
|
39104
|
-
*
|
|
39105
|
-
* @example
|
|
39106
|
-
* C#
|
|
39107
|
-
* ```cs
|
|
39108
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39109
|
-
* api.SoundFontLoaded.On(() =>
|
|
39110
|
-
* {
|
|
39111
|
-
* HideSoundFontLoadingIndicator();
|
|
39112
|
-
* });
|
|
39113
|
-
* ```
|
|
39114
|
-
*
|
|
39115
|
-
* @example
|
|
39116
|
-
* Android
|
|
39117
|
-
* ```kotlin
|
|
39118
|
-
* val api = AlphaTabApi<MyControl>(...);
|
|
39119
|
-
* api.soundFontLoaded.on {
|
|
39120
|
-
* hideSoundFontLoadingIndicator();
|
|
39121
|
-
* }
|
|
39122
|
-
* ```
|
|
39123
|
-
*
|
|
39124
|
-
*/
|
|
39125
|
-
this.soundFontLoaded = new EventEmitter();
|
|
39126
39272
|
/**
|
|
39127
39273
|
* This event is fired when a Midi file is being loaded.
|
|
39128
39274
|
*
|
|
@@ -39210,213 +39356,6 @@
|
|
|
39210
39356
|
*
|
|
39211
39357
|
*/
|
|
39212
39358
|
this.midiLoaded = new EventEmitterOfT();
|
|
39213
|
-
/**
|
|
39214
|
-
* This event is fired when the playback state changed.
|
|
39215
|
-
*
|
|
39216
|
-
* @eventProperty
|
|
39217
|
-
* @category Events - Player
|
|
39218
|
-
* @since 0.9.4
|
|
39219
|
-
*
|
|
39220
|
-
* @example
|
|
39221
|
-
* JavaScript
|
|
39222
|
-
* ```js
|
|
39223
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39224
|
-
* api.playerStateChanged.on((args) => {
|
|
39225
|
-
* updatePlayerControls(args.state, args.stopped);
|
|
39226
|
-
* });
|
|
39227
|
-
* ```
|
|
39228
|
-
*
|
|
39229
|
-
* @example
|
|
39230
|
-
* C#
|
|
39231
|
-
* ```cs
|
|
39232
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39233
|
-
* api.PlayerStateChanged.On(args =>
|
|
39234
|
-
* {
|
|
39235
|
-
* UpdatePlayerControls(args);
|
|
39236
|
-
* });
|
|
39237
|
-
* ```
|
|
39238
|
-
*
|
|
39239
|
-
* @example
|
|
39240
|
-
* Android
|
|
39241
|
-
* ```kotlin
|
|
39242
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
39243
|
-
* api.playerStateChanged.on { args ->
|
|
39244
|
-
* updatePlayerControls(args)
|
|
39245
|
-
* }
|
|
39246
|
-
* ```
|
|
39247
|
-
*
|
|
39248
|
-
*/
|
|
39249
|
-
this.playerStateChanged = new EventEmitterOfT();
|
|
39250
|
-
/**
|
|
39251
|
-
* This event is fired when the current playback position of the song changed.
|
|
39252
|
-
*
|
|
39253
|
-
* @eventProperty
|
|
39254
|
-
* @category Events - Player
|
|
39255
|
-
* @since 0.9.4
|
|
39256
|
-
*
|
|
39257
|
-
* @example
|
|
39258
|
-
* JavaScript
|
|
39259
|
-
* ```js
|
|
39260
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39261
|
-
* api.playerPositionChanged.on((args) => {
|
|
39262
|
-
* updatePlayerPosition(args);
|
|
39263
|
-
* });
|
|
39264
|
-
* ```
|
|
39265
|
-
*
|
|
39266
|
-
* @example
|
|
39267
|
-
* C#
|
|
39268
|
-
* ```cs
|
|
39269
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39270
|
-
* api.PlayerPositionChanged.On(args =>
|
|
39271
|
-
* {
|
|
39272
|
-
* UpdatePlayerPosition(args);
|
|
39273
|
-
* });
|
|
39274
|
-
* ```
|
|
39275
|
-
*
|
|
39276
|
-
* @example
|
|
39277
|
-
* Android
|
|
39278
|
-
* ```kotlin
|
|
39279
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
39280
|
-
* api.playerPositionChanged.on { args ->
|
|
39281
|
-
* updatePlayerPosition(args)
|
|
39282
|
-
* }
|
|
39283
|
-
* ```
|
|
39284
|
-
*
|
|
39285
|
-
*/
|
|
39286
|
-
this.playerPositionChanged = new EventEmitterOfT();
|
|
39287
|
-
/**
|
|
39288
|
-
* This event is fired when the synthesizer played certain midi events.
|
|
39289
|
-
*
|
|
39290
|
-
* @remarks
|
|
39291
|
-
* This event is fired when the synthesizer played certain midi events. This allows reacing on various low level
|
|
39292
|
-
* audio playback elements like notes/rests played or metronome ticks.
|
|
39293
|
-
*
|
|
39294
|
-
* Refer to the [related guide](https://www.alphatab.net/docs/guides/handling-midi-events) to learn more about this feature.
|
|
39295
|
-
*
|
|
39296
|
-
* Also note that the provided data models changed significantly in {@version 1.3.0}. We try to provide backwards compatibility
|
|
39297
|
-
* until some extend but highly encourage changing to the new models in case of problems.
|
|
39298
|
-
*
|
|
39299
|
-
* @eventProperty
|
|
39300
|
-
* @category Events - Player
|
|
39301
|
-
* @since 1.2.0
|
|
39302
|
-
*
|
|
39303
|
-
* @example
|
|
39304
|
-
* JavaScript
|
|
39305
|
-
* ```js
|
|
39306
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39307
|
-
* api.midiEventsPlayedFilter = [alphaTab.midi.MidiEventType.AlphaTabMetronome];
|
|
39308
|
-
* api.midiEventsPlayed.on(function(e) {
|
|
39309
|
-
* for(const midi of e.events) {
|
|
39310
|
-
* if(midi.isMetronome) {
|
|
39311
|
-
* console.log('Metronome tick ' + midi.tick);
|
|
39312
|
-
* }
|
|
39313
|
-
* }
|
|
39314
|
-
* });
|
|
39315
|
-
* ```
|
|
39316
|
-
*
|
|
39317
|
-
* @example
|
|
39318
|
-
* C#
|
|
39319
|
-
* ```cs
|
|
39320
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39321
|
-
* api.MidiEventsPlayedFilter = new MidiEventType[] { AlphaTab.Midi.MidiEventType.AlphaTabMetronome };
|
|
39322
|
-
* api.MidiEventsPlayed.On(e =>
|
|
39323
|
-
* {
|
|
39324
|
-
* foreach(var midi of e.events)
|
|
39325
|
-
* {
|
|
39326
|
-
* if(midi is AlphaTab.Midi.AlphaTabMetronomeEvent sysex && sysex.IsMetronome)
|
|
39327
|
-
* {
|
|
39328
|
-
* Console.WriteLine("Metronome tick " + midi.Tick);
|
|
39329
|
-
* }
|
|
39330
|
-
* }
|
|
39331
|
-
* });
|
|
39332
|
-
* ```
|
|
39333
|
-
*
|
|
39334
|
-
* @example
|
|
39335
|
-
* Android
|
|
39336
|
-
* ```kotlin
|
|
39337
|
-
* val api = AlphaTabApi<MyControl>(...);
|
|
39338
|
-
* api.midiEventsPlayedFilter = alphaTab.collections.List<alphaTab.midi.MidiEventType>( alphaTab.midi.MidiEventType.AlphaTabMetronome )
|
|
39339
|
-
* api.midiEventsPlayed.on { e ->
|
|
39340
|
-
* for (midi in e.events) {
|
|
39341
|
-
* if(midi instanceof alphaTab.midi.AlphaTabMetronomeEvent && midi.isMetronome) {
|
|
39342
|
-
* println("Metronome tick " + midi.tick);
|
|
39343
|
-
* }
|
|
39344
|
-
* }
|
|
39345
|
-
* }
|
|
39346
|
-
* ```
|
|
39347
|
-
* @see {@link MidiEvent}
|
|
39348
|
-
* @see {@link TimeSignatureEvent}
|
|
39349
|
-
* @see {@link AlphaTabMetronomeEvent}
|
|
39350
|
-
* @see {@link AlphaTabRestEvent}
|
|
39351
|
-
* @see {@link NoteOnEvent}
|
|
39352
|
-
* @see {@link NoteOffEvent}
|
|
39353
|
-
* @see {@link ControlChangeEvent}
|
|
39354
|
-
* @see {@link ProgramChangeEvent}
|
|
39355
|
-
* @see {@link TempoChangeEvent}
|
|
39356
|
-
* @see {@link PitchBendEvent}
|
|
39357
|
-
* @see {@link NoteBendEvent}
|
|
39358
|
-
* @see {@link EndOfTrackEvent}
|
|
39359
|
-
* @see {@link MetaEvent}
|
|
39360
|
-
* @see {@link MetaDataEvent}
|
|
39361
|
-
* @see {@link MetaNumberEvent}
|
|
39362
|
-
* @see {@link Midi20PerNotePitchBendEvent}
|
|
39363
|
-
* @see {@link SystemCommonEvent}
|
|
39364
|
-
* @see {@link SystemExclusiveEvent}
|
|
39365
|
-
*/
|
|
39366
|
-
this.midiEventsPlayed = new EventEmitterOfT();
|
|
39367
|
-
/**
|
|
39368
|
-
* This event is fired when the playback range changed.
|
|
39369
|
-
*
|
|
39370
|
-
* @eventProperty
|
|
39371
|
-
* @category Events - Player
|
|
39372
|
-
* @since 1.2.3
|
|
39373
|
-
*
|
|
39374
|
-
* @example
|
|
39375
|
-
* JavaScript
|
|
39376
|
-
* ```js
|
|
39377
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
39378
|
-
* api.playbackRangeChanged.on((args) => {
|
|
39379
|
-
* if (args.playbackRange) {
|
|
39380
|
-
* highlightRangeInProgressBar(args.playbackRange.startTick, args.playbackRange.endTick);
|
|
39381
|
-
* } else {
|
|
39382
|
-
* clearHighlightInProgressBar();
|
|
39383
|
-
* }
|
|
39384
|
-
* });
|
|
39385
|
-
* ```
|
|
39386
|
-
*
|
|
39387
|
-
* @example
|
|
39388
|
-
* C#
|
|
39389
|
-
* ```cs
|
|
39390
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
39391
|
-
* api.PlaybackRangeChanged.On(args =>
|
|
39392
|
-
* {
|
|
39393
|
-
* if (args.PlaybackRange != null)
|
|
39394
|
-
* {
|
|
39395
|
-
* HighlightRangeInProgressBar(args.PlaybackRange.StartTick, args.PlaybackRange.EndTick);
|
|
39396
|
-
* }
|
|
39397
|
-
* else
|
|
39398
|
-
* {
|
|
39399
|
-
* ClearHighlightInProgressBar();
|
|
39400
|
-
* }
|
|
39401
|
-
* });
|
|
39402
|
-
* ```
|
|
39403
|
-
*
|
|
39404
|
-
* @example
|
|
39405
|
-
* Android
|
|
39406
|
-
* ```kotlin
|
|
39407
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
39408
|
-
* api.playbackRangeChanged.on { args ->
|
|
39409
|
-
* val playbackRange = args.playbackRange
|
|
39410
|
-
* if (playbackRange != null) {
|
|
39411
|
-
* highlightRangeInProgressBar(playbackRange.startTick, playbackRange.endTick)
|
|
39412
|
-
* } else {
|
|
39413
|
-
* clearHighlightInProgressBar()
|
|
39414
|
-
* }
|
|
39415
|
-
* }
|
|
39416
|
-
* ```
|
|
39417
|
-
*
|
|
39418
|
-
*/
|
|
39419
|
-
this.playbackRangeChanged = new EventEmitterOfT();
|
|
39420
39359
|
/**
|
|
39421
39360
|
* @internal
|
|
39422
39361
|
*/
|
|
@@ -39472,8 +39411,9 @@
|
|
|
39472
39411
|
this.appendRenderResult(null); // marks last element
|
|
39473
39412
|
});
|
|
39474
39413
|
this.renderer.error.on(this.onError.bind(this));
|
|
39414
|
+
this.setupPlayerWrapper();
|
|
39475
39415
|
if (this.settings.player.playerMode !== exports.PlayerMode.Disabled) {
|
|
39476
|
-
this.
|
|
39416
|
+
this.setupOrDestroyPlayer();
|
|
39477
39417
|
}
|
|
39478
39418
|
this.setupClickHandling();
|
|
39479
39419
|
// delay rendering to allow ui to hook up with events first.
|
|
@@ -39481,6 +39421,36 @@
|
|
|
39481
39421
|
this.uiFacade.initialRender();
|
|
39482
39422
|
});
|
|
39483
39423
|
}
|
|
39424
|
+
setupPlayerWrapper() {
|
|
39425
|
+
const player = new AlphaSynthWrapper();
|
|
39426
|
+
this._player = player;
|
|
39427
|
+
player.ready.on(() => {
|
|
39428
|
+
this.loadMidiForScore();
|
|
39429
|
+
});
|
|
39430
|
+
player.readyForPlayback.on(() => {
|
|
39431
|
+
this.onPlayerReady();
|
|
39432
|
+
if (this.tracks) {
|
|
39433
|
+
for (const track of this.tracks) {
|
|
39434
|
+
const volume = track.playbackInfo.volume / 16;
|
|
39435
|
+
player.setChannelVolume(track.playbackInfo.primaryChannel, volume);
|
|
39436
|
+
player.setChannelVolume(track.playbackInfo.secondaryChannel, volume);
|
|
39437
|
+
}
|
|
39438
|
+
}
|
|
39439
|
+
});
|
|
39440
|
+
player.soundFontLoaded.on(this.onSoundFontLoaded.bind(this));
|
|
39441
|
+
player.soundFontLoadFailed.on(e => {
|
|
39442
|
+
this.onError(e);
|
|
39443
|
+
});
|
|
39444
|
+
player.midiLoaded.on(this.onMidiLoaded.bind(this));
|
|
39445
|
+
player.midiLoadFailed.on(e => {
|
|
39446
|
+
this.onError(e);
|
|
39447
|
+
});
|
|
39448
|
+
player.stateChanged.on(this.onPlayerStateChanged.bind(this));
|
|
39449
|
+
player.positionChanged.on(this.onPlayerPositionChanged.bind(this));
|
|
39450
|
+
player.midiEventsPlayed.on(this.onMidiEventsPlayed.bind(this));
|
|
39451
|
+
player.playbackRangeChanged.on(this.onPlaybackRangeChanged.bind(this));
|
|
39452
|
+
player.finished.on(this.onPlayerFinished.bind(this));
|
|
39453
|
+
}
|
|
39484
39454
|
/**
|
|
39485
39455
|
* Destroys the alphaTab control and restores the initial state of the UI.
|
|
39486
39456
|
* @remarks
|
|
@@ -39513,9 +39483,7 @@
|
|
|
39513
39483
|
*/
|
|
39514
39484
|
destroy() {
|
|
39515
39485
|
this._isDestroyed = true;
|
|
39516
|
-
|
|
39517
|
-
this.player.destroy();
|
|
39518
|
-
}
|
|
39486
|
+
this._player.destroy();
|
|
39519
39487
|
this.uiFacade.destroy();
|
|
39520
39488
|
this.renderer.destroy();
|
|
39521
39489
|
}
|
|
@@ -39563,14 +39531,8 @@
|
|
|
39563
39531
|
ModelUtils.applyPitchOffsets(this.settings, score);
|
|
39564
39532
|
}
|
|
39565
39533
|
this.renderer.updateSettings(this.settings);
|
|
39566
|
-
|
|
39567
|
-
|
|
39568
|
-
if (this.setupPlayer() && score) {
|
|
39569
|
-
this.loadMidiForScore();
|
|
39570
|
-
}
|
|
39571
|
-
}
|
|
39572
|
-
else {
|
|
39573
|
-
this.destroyPlayer();
|
|
39534
|
+
if (this.setupOrDestroyPlayer()) {
|
|
39535
|
+
this.loadMidiForScore();
|
|
39574
39536
|
}
|
|
39575
39537
|
this.onSettingsUpdated();
|
|
39576
39538
|
}
|
|
@@ -39877,9 +39839,6 @@
|
|
|
39877
39839
|
* ```
|
|
39878
39840
|
*/
|
|
39879
39841
|
loadSoundFont(data, append = false) {
|
|
39880
|
-
if (!this.player) {
|
|
39881
|
-
return false;
|
|
39882
|
-
}
|
|
39883
39842
|
return this.uiFacade.loadSoundFont(data, append);
|
|
39884
39843
|
}
|
|
39885
39844
|
/**
|
|
@@ -39925,10 +39884,7 @@
|
|
|
39925
39884
|
* ```
|
|
39926
39885
|
*/
|
|
39927
39886
|
resetSoundFonts() {
|
|
39928
|
-
|
|
39929
|
-
return;
|
|
39930
|
-
}
|
|
39931
|
-
this.player.resetSoundFonts();
|
|
39887
|
+
this._player.resetSoundFonts();
|
|
39932
39888
|
}
|
|
39933
39889
|
/**
|
|
39934
39890
|
* Initiates a re-rendering of the current setup.
|
|
@@ -40042,6 +39998,37 @@
|
|
|
40042
39998
|
get boundsLookup() {
|
|
40043
39999
|
return this.renderer.boundsLookup;
|
|
40044
40000
|
}
|
|
40001
|
+
/**
|
|
40002
|
+
* The alphaSynth player used for playback.
|
|
40003
|
+
* @remarks
|
|
40004
|
+
* This is the low-level API to the Midi synthesizer used for playback.
|
|
40005
|
+
* Gets access to the underling {@link IAlphaSynth} that is used for the audio playback.
|
|
40006
|
+
* @category Properties - Player
|
|
40007
|
+
* @since 0.9.4
|
|
40008
|
+
* @example
|
|
40009
|
+
* JavaScript
|
|
40010
|
+
* ```js
|
|
40011
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
40012
|
+
* setupPlayerEvents(api.settings);
|
|
40013
|
+
* ```
|
|
40014
|
+
*
|
|
40015
|
+
* @example
|
|
40016
|
+
* C#
|
|
40017
|
+
* ```cs
|
|
40018
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
40019
|
+
* SetupPlayerEvents(api.Player);
|
|
40020
|
+
* ```
|
|
40021
|
+
*
|
|
40022
|
+
* @example
|
|
40023
|
+
* Android
|
|
40024
|
+
* ```kotlin
|
|
40025
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
40026
|
+
* setupPlayerEvents(api.player)
|
|
40027
|
+
* ```
|
|
40028
|
+
*/
|
|
40029
|
+
get player() {
|
|
40030
|
+
return this._player.instance ? this._player : null;
|
|
40031
|
+
}
|
|
40045
40032
|
/**
|
|
40046
40033
|
* Whether the player is ready for starting the playback.
|
|
40047
40034
|
* @remarks
|
|
@@ -40071,10 +40058,7 @@
|
|
|
40071
40058
|
* ```
|
|
40072
40059
|
*/
|
|
40073
40060
|
get isReadyForPlayback() {
|
|
40074
|
-
|
|
40075
|
-
return false;
|
|
40076
|
-
}
|
|
40077
|
-
return this.player.isReadyForPlayback;
|
|
40061
|
+
return this._player.isReadyForPlayback;
|
|
40078
40062
|
}
|
|
40079
40063
|
/**
|
|
40080
40064
|
* The current player state.
|
|
@@ -40104,10 +40088,7 @@
|
|
|
40104
40088
|
* ```
|
|
40105
40089
|
*/
|
|
40106
40090
|
get playerState() {
|
|
40107
|
-
|
|
40108
|
-
return PlayerState.Paused;
|
|
40109
|
-
}
|
|
40110
|
-
return this.player.state;
|
|
40091
|
+
return this._player.state;
|
|
40111
40092
|
}
|
|
40112
40093
|
/**
|
|
40113
40094
|
* The current master volume as percentage (0-1).
|
|
@@ -40137,15 +40118,10 @@
|
|
|
40137
40118
|
* ```
|
|
40138
40119
|
*/
|
|
40139
40120
|
get masterVolume() {
|
|
40140
|
-
|
|
40141
|
-
return 0;
|
|
40142
|
-
}
|
|
40143
|
-
return this.player.masterVolume;
|
|
40121
|
+
return this._player.masterVolume;
|
|
40144
40122
|
}
|
|
40145
40123
|
set masterVolume(value) {
|
|
40146
|
-
|
|
40147
|
-
this.player.masterVolume = value;
|
|
40148
|
-
}
|
|
40124
|
+
this._player.masterVolume = value;
|
|
40149
40125
|
}
|
|
40150
40126
|
/**
|
|
40151
40127
|
* The metronome volume as percentage (0-1).
|
|
@@ -40176,15 +40152,10 @@
|
|
|
40176
40152
|
* ```
|
|
40177
40153
|
*/
|
|
40178
40154
|
get metronomeVolume() {
|
|
40179
|
-
|
|
40180
|
-
return 0;
|
|
40181
|
-
}
|
|
40182
|
-
return this.player.metronomeVolume;
|
|
40155
|
+
return this._player.metronomeVolume;
|
|
40183
40156
|
}
|
|
40184
40157
|
set metronomeVolume(value) {
|
|
40185
|
-
|
|
40186
|
-
this.player.metronomeVolume = value;
|
|
40187
|
-
}
|
|
40158
|
+
this._player.metronomeVolume = value;
|
|
40188
40159
|
}
|
|
40189
40160
|
/**
|
|
40190
40161
|
* The volume of the count-in metronome ticks.
|
|
@@ -40215,15 +40186,10 @@
|
|
|
40215
40186
|
* ```
|
|
40216
40187
|
*/
|
|
40217
40188
|
get countInVolume() {
|
|
40218
|
-
|
|
40219
|
-
return 0;
|
|
40220
|
-
}
|
|
40221
|
-
return this.player.countInVolume;
|
|
40189
|
+
return this._player.countInVolume;
|
|
40222
40190
|
}
|
|
40223
40191
|
set countInVolume(value) {
|
|
40224
|
-
|
|
40225
|
-
this.player.countInVolume = value;
|
|
40226
|
-
}
|
|
40192
|
+
this._player.countInVolume = value;
|
|
40227
40193
|
}
|
|
40228
40194
|
/**
|
|
40229
40195
|
* The midi events which will trigger the `midiEventsPlayed` event
|
|
@@ -40282,15 +40248,10 @@
|
|
|
40282
40248
|
* ```
|
|
40283
40249
|
*/
|
|
40284
40250
|
get midiEventsPlayedFilter() {
|
|
40285
|
-
|
|
40286
|
-
return [];
|
|
40287
|
-
}
|
|
40288
|
-
return this.player.midiEventsPlayedFilter;
|
|
40251
|
+
return this._player.midiEventsPlayedFilter;
|
|
40289
40252
|
}
|
|
40290
40253
|
set midiEventsPlayedFilter(value) {
|
|
40291
|
-
|
|
40292
|
-
this.player.midiEventsPlayedFilter = value;
|
|
40293
|
-
}
|
|
40254
|
+
this._player.midiEventsPlayedFilter = value;
|
|
40294
40255
|
}
|
|
40295
40256
|
/**
|
|
40296
40257
|
* The position within the song in midi ticks.
|
|
@@ -40318,15 +40279,10 @@
|
|
|
40318
40279
|
* ```
|
|
40319
40280
|
*/
|
|
40320
40281
|
get tickPosition() {
|
|
40321
|
-
|
|
40322
|
-
return 0;
|
|
40323
|
-
}
|
|
40324
|
-
return this.player.tickPosition;
|
|
40282
|
+
return this._player.tickPosition;
|
|
40325
40283
|
}
|
|
40326
40284
|
set tickPosition(value) {
|
|
40327
|
-
|
|
40328
|
-
this.player.tickPosition = value;
|
|
40329
|
-
}
|
|
40285
|
+
this._player.tickPosition = value;
|
|
40330
40286
|
}
|
|
40331
40287
|
/**
|
|
40332
40288
|
* The position within the song in milliseconds
|
|
@@ -40354,15 +40310,10 @@
|
|
|
40354
40310
|
* ```
|
|
40355
40311
|
*/
|
|
40356
40312
|
get timePosition() {
|
|
40357
|
-
|
|
40358
|
-
return 0;
|
|
40359
|
-
}
|
|
40360
|
-
return this.player.timePosition;
|
|
40313
|
+
return this._player.timePosition;
|
|
40361
40314
|
}
|
|
40362
40315
|
set timePosition(value) {
|
|
40363
|
-
|
|
40364
|
-
this.player.timePosition = value;
|
|
40365
|
-
}
|
|
40316
|
+
this._player.timePosition = value;
|
|
40366
40317
|
}
|
|
40367
40318
|
/**
|
|
40368
40319
|
* The range of the song that should be played.
|
|
@@ -40396,17 +40347,12 @@
|
|
|
40396
40347
|
* ```
|
|
40397
40348
|
*/
|
|
40398
40349
|
get playbackRange() {
|
|
40399
|
-
|
|
40400
|
-
return null;
|
|
40401
|
-
}
|
|
40402
|
-
return this.player.playbackRange;
|
|
40350
|
+
return this._player.playbackRange;
|
|
40403
40351
|
}
|
|
40404
40352
|
set playbackRange(value) {
|
|
40405
|
-
|
|
40406
|
-
|
|
40407
|
-
|
|
40408
|
-
this.updateSelectionCursor(value);
|
|
40409
|
-
}
|
|
40353
|
+
this._player.playbackRange = value;
|
|
40354
|
+
if (this.settings.player.enableCursor) {
|
|
40355
|
+
this.updateSelectionCursor(value);
|
|
40410
40356
|
}
|
|
40411
40357
|
}
|
|
40412
40358
|
/**
|
|
@@ -40438,15 +40384,10 @@
|
|
|
40438
40384
|
* ```
|
|
40439
40385
|
*/
|
|
40440
40386
|
get playbackSpeed() {
|
|
40441
|
-
|
|
40442
|
-
return 0;
|
|
40443
|
-
}
|
|
40444
|
-
return this.player.playbackSpeed;
|
|
40387
|
+
return this._player.playbackSpeed;
|
|
40445
40388
|
}
|
|
40446
40389
|
set playbackSpeed(value) {
|
|
40447
|
-
|
|
40448
|
-
this.player.playbackSpeed = value;
|
|
40449
|
-
}
|
|
40390
|
+
this._player.playbackSpeed = value;
|
|
40450
40391
|
}
|
|
40451
40392
|
/**
|
|
40452
40393
|
* Whether the playback should automatically restart after it finished.
|
|
@@ -40477,27 +40418,17 @@
|
|
|
40477
40418
|
* ```
|
|
40478
40419
|
*/
|
|
40479
40420
|
get isLooping() {
|
|
40480
|
-
|
|
40481
|
-
return false;
|
|
40482
|
-
}
|
|
40483
|
-
return this.player.isLooping;
|
|
40421
|
+
return this._player.isLooping;
|
|
40484
40422
|
}
|
|
40485
40423
|
set isLooping(value) {
|
|
40486
|
-
|
|
40487
|
-
this.player.isLooping = value;
|
|
40488
|
-
}
|
|
40424
|
+
this._player.isLooping = value;
|
|
40489
40425
|
}
|
|
40490
40426
|
destroyPlayer() {
|
|
40491
|
-
|
|
40492
|
-
return;
|
|
40493
|
-
}
|
|
40494
|
-
this.player.destroy();
|
|
40495
|
-
this.player = null;
|
|
40427
|
+
this._player.destroy();
|
|
40496
40428
|
this._previousTick = 0;
|
|
40497
|
-
this._playerState = PlayerState.Paused;
|
|
40498
40429
|
this.destroyCursors();
|
|
40499
40430
|
}
|
|
40500
|
-
|
|
40431
|
+
setupOrDestroyPlayer() {
|
|
40501
40432
|
let mode = this.settings.player.playerMode;
|
|
40502
40433
|
if (mode === exports.PlayerMode.EnabledAutomatic) {
|
|
40503
40434
|
const score = this.score;
|
|
@@ -40511,66 +40442,34 @@
|
|
|
40511
40442
|
mode = exports.PlayerMode.EnabledSynthesizer;
|
|
40512
40443
|
}
|
|
40513
40444
|
}
|
|
40445
|
+
let newPlayer = null;
|
|
40514
40446
|
if (mode !== this._actualPlayerMode) {
|
|
40515
40447
|
this.destroyPlayer();
|
|
40448
|
+
switch (mode) {
|
|
40449
|
+
case exports.PlayerMode.Disabled:
|
|
40450
|
+
newPlayer = null;
|
|
40451
|
+
break;
|
|
40452
|
+
case exports.PlayerMode.EnabledSynthesizer:
|
|
40453
|
+
newPlayer = this.uiFacade.createWorkerPlayer();
|
|
40454
|
+
break;
|
|
40455
|
+
case exports.PlayerMode.EnabledBackingTrack:
|
|
40456
|
+
newPlayer = this.uiFacade.createBackingTrackPlayer();
|
|
40457
|
+
break;
|
|
40458
|
+
case exports.PlayerMode.EnabledExternalMedia:
|
|
40459
|
+
newPlayer = new ExternalMediaPlayer(this.settings.player.bufferTimeInMilliseconds);
|
|
40460
|
+
break;
|
|
40461
|
+
}
|
|
40462
|
+
}
|
|
40463
|
+
else {
|
|
40464
|
+
// no change in player mode, just update song info if needed
|
|
40465
|
+
return true;
|
|
40516
40466
|
}
|
|
40517
40467
|
this.updateCursors();
|
|
40518
40468
|
this._actualPlayerMode = mode;
|
|
40519
|
-
|
|
40520
|
-
case exports.PlayerMode.Disabled:
|
|
40521
|
-
this.destroyPlayer();
|
|
40522
|
-
return false;
|
|
40523
|
-
case exports.PlayerMode.EnabledSynthesizer:
|
|
40524
|
-
if (this.player) {
|
|
40525
|
-
return true;
|
|
40526
|
-
}
|
|
40527
|
-
// new player needed
|
|
40528
|
-
this.player = this.uiFacade.createWorkerPlayer();
|
|
40529
|
-
break;
|
|
40530
|
-
case exports.PlayerMode.EnabledBackingTrack:
|
|
40531
|
-
if (this.player) {
|
|
40532
|
-
return true;
|
|
40533
|
-
}
|
|
40534
|
-
// new player needed
|
|
40535
|
-
this.player = this.uiFacade.createBackingTrackPlayer();
|
|
40536
|
-
break;
|
|
40537
|
-
case exports.PlayerMode.EnabledExternalMedia:
|
|
40538
|
-
if (this.player) {
|
|
40539
|
-
return true;
|
|
40540
|
-
}
|
|
40541
|
-
this.player = new ExternalMediaPlayer(this.settings.player.bufferTimeInMilliseconds);
|
|
40542
|
-
break;
|
|
40543
|
-
}
|
|
40544
|
-
if (!this.player) {
|
|
40469
|
+
if (!newPlayer) {
|
|
40545
40470
|
return false;
|
|
40546
40471
|
}
|
|
40547
|
-
this.
|
|
40548
|
-
this.loadMidiForScore();
|
|
40549
|
-
});
|
|
40550
|
-
this.player.readyForPlayback.on(() => {
|
|
40551
|
-
this.onPlayerReady();
|
|
40552
|
-
if (this.tracks) {
|
|
40553
|
-
for (const track of this.tracks) {
|
|
40554
|
-
const volume = track.playbackInfo.volume / 16;
|
|
40555
|
-
this.player.setChannelVolume(track.playbackInfo.primaryChannel, volume);
|
|
40556
|
-
this.player.setChannelVolume(track.playbackInfo.secondaryChannel, volume);
|
|
40557
|
-
}
|
|
40558
|
-
}
|
|
40559
|
-
});
|
|
40560
|
-
this.player.soundFontLoaded.on(this.onSoundFontLoaded.bind(this));
|
|
40561
|
-
this.player.soundFontLoadFailed.on(e => {
|
|
40562
|
-
this.onError(e);
|
|
40563
|
-
});
|
|
40564
|
-
this.player.midiLoaded.on(this.onMidiLoaded.bind(this));
|
|
40565
|
-
this.player.midiLoadFailed.on(e => {
|
|
40566
|
-
this.onError(e);
|
|
40567
|
-
});
|
|
40568
|
-
this.player.stateChanged.on(this.onPlayerStateChanged.bind(this));
|
|
40569
|
-
this.player.positionChanged.on(this.onPlayerPositionChanged.bind(this));
|
|
40570
|
-
this.player.midiEventsPlayed.on(this.onMidiEventsPlayed.bind(this));
|
|
40571
|
-
this.player.playbackRangeChanged.on(this.onPlaybackRangeChanged.bind(this));
|
|
40572
|
-
this.player.finished.on(this.onPlayerFinished.bind(this));
|
|
40573
|
-
this.setupPlayerEvents();
|
|
40472
|
+
this._player.instance = newPlayer;
|
|
40574
40473
|
return false;
|
|
40575
40474
|
}
|
|
40576
40475
|
loadMidiForScore() {
|
|
@@ -40590,12 +40489,10 @@
|
|
|
40590
40489
|
generator.generate();
|
|
40591
40490
|
this._tickCache = generator.tickLookup;
|
|
40592
40491
|
this.onMidiLoad(midiFile);
|
|
40593
|
-
const player = this.
|
|
40594
|
-
|
|
40595
|
-
|
|
40596
|
-
|
|
40597
|
-
player.applyTranspositionPitches(generator.transpositionPitches);
|
|
40598
|
-
}
|
|
40492
|
+
const player = this._player;
|
|
40493
|
+
player.loadMidiFile(midiFile);
|
|
40494
|
+
player.loadBackingTrack(score, generator.syncPoints);
|
|
40495
|
+
player.applyTranspositionPitches(generator.transpositionPitches);
|
|
40599
40496
|
}
|
|
40600
40497
|
/**
|
|
40601
40498
|
* Changes the volume of the given tracks.
|
|
@@ -40633,12 +40530,9 @@
|
|
|
40633
40530
|
* ```
|
|
40634
40531
|
*/
|
|
40635
40532
|
changeTrackVolume(tracks, volume) {
|
|
40636
|
-
if (!this.player) {
|
|
40637
|
-
return;
|
|
40638
|
-
}
|
|
40639
40533
|
for (const track of tracks) {
|
|
40640
|
-
this.
|
|
40641
|
-
this.
|
|
40534
|
+
this._player.setChannelVolume(track.playbackInfo.primaryChannel, volume);
|
|
40535
|
+
this._player.setChannelVolume(track.playbackInfo.secondaryChannel, volume);
|
|
40642
40536
|
}
|
|
40643
40537
|
}
|
|
40644
40538
|
/**
|
|
@@ -40675,12 +40569,9 @@
|
|
|
40675
40569
|
* ```
|
|
40676
40570
|
*/
|
|
40677
40571
|
changeTrackSolo(tracks, solo) {
|
|
40678
|
-
if (!this.player) {
|
|
40679
|
-
return;
|
|
40680
|
-
}
|
|
40681
40572
|
for (const track of tracks) {
|
|
40682
|
-
this.
|
|
40683
|
-
this.
|
|
40573
|
+
this._player.setChannelSolo(track.playbackInfo.primaryChannel, solo);
|
|
40574
|
+
this._player.setChannelSolo(track.playbackInfo.secondaryChannel, solo);
|
|
40684
40575
|
}
|
|
40685
40576
|
}
|
|
40686
40577
|
/**
|
|
@@ -40716,12 +40607,9 @@
|
|
|
40716
40607
|
* ```
|
|
40717
40608
|
*/
|
|
40718
40609
|
changeTrackMute(tracks, mute) {
|
|
40719
|
-
if (!this.player) {
|
|
40720
|
-
return;
|
|
40721
|
-
}
|
|
40722
40610
|
for (const track of tracks) {
|
|
40723
|
-
this.
|
|
40724
|
-
this.
|
|
40611
|
+
this._player.setChannelMute(track.playbackInfo.primaryChannel, mute);
|
|
40612
|
+
this._player.setChannelMute(track.playbackInfo.secondaryChannel, mute);
|
|
40725
40613
|
}
|
|
40726
40614
|
}
|
|
40727
40615
|
/**
|
|
@@ -40759,12 +40647,9 @@
|
|
|
40759
40647
|
* ```
|
|
40760
40648
|
*/
|
|
40761
40649
|
changeTrackTranspositionPitch(tracks, semitones) {
|
|
40762
|
-
if (!this.player) {
|
|
40763
|
-
return;
|
|
40764
|
-
}
|
|
40765
40650
|
for (const track of tracks) {
|
|
40766
|
-
this.
|
|
40767
|
-
this.
|
|
40651
|
+
this._player.setChannelTranspositionPitch(track.playbackInfo.primaryChannel, semitones);
|
|
40652
|
+
this._player.setChannelTranspositionPitch(track.playbackInfo.secondaryChannel, semitones);
|
|
40768
40653
|
}
|
|
40769
40654
|
}
|
|
40770
40655
|
/**
|
|
@@ -40795,10 +40680,7 @@
|
|
|
40795
40680
|
* ```
|
|
40796
40681
|
*/
|
|
40797
40682
|
play() {
|
|
40798
|
-
|
|
40799
|
-
return false;
|
|
40800
|
-
}
|
|
40801
|
-
return this.player.play();
|
|
40683
|
+
return this._player.play();
|
|
40802
40684
|
}
|
|
40803
40685
|
/**
|
|
40804
40686
|
* Pauses the playback of the current song.
|
|
@@ -40827,10 +40709,7 @@
|
|
|
40827
40709
|
* ```
|
|
40828
40710
|
*/
|
|
40829
40711
|
pause() {
|
|
40830
|
-
|
|
40831
|
-
return;
|
|
40832
|
-
}
|
|
40833
|
-
this.player.pause();
|
|
40712
|
+
this._player.pause();
|
|
40834
40713
|
}
|
|
40835
40714
|
/**
|
|
40836
40715
|
* Toggles between play/pause depending on the current player state.
|
|
@@ -40861,10 +40740,7 @@
|
|
|
40861
40740
|
* ```
|
|
40862
40741
|
*/
|
|
40863
40742
|
playPause() {
|
|
40864
|
-
|
|
40865
|
-
return;
|
|
40866
|
-
}
|
|
40867
|
-
this.player.playPause();
|
|
40743
|
+
this._player.playPause();
|
|
40868
40744
|
}
|
|
40869
40745
|
/**
|
|
40870
40746
|
* Stops the playback of the current song, and moves the playback position back to the start.
|
|
@@ -40895,10 +40771,7 @@
|
|
|
40895
40771
|
* ```
|
|
40896
40772
|
*/
|
|
40897
40773
|
stop() {
|
|
40898
|
-
|
|
40899
|
-
return;
|
|
40900
|
-
}
|
|
40901
|
-
this.player.stop();
|
|
40774
|
+
this._player.stop();
|
|
40902
40775
|
}
|
|
40903
40776
|
/**
|
|
40904
40777
|
* Triggers the play of the given beat.
|
|
@@ -40934,15 +40807,12 @@
|
|
|
40934
40807
|
* ```
|
|
40935
40808
|
*/
|
|
40936
40809
|
playBeat(beat) {
|
|
40937
|
-
if (!this.player) {
|
|
40938
|
-
return;
|
|
40939
|
-
}
|
|
40940
40810
|
// we generate a new midi file containing only the beat
|
|
40941
40811
|
const midiFile = new MidiFile();
|
|
40942
40812
|
const handler = new AlphaSynthMidiFileHandler(midiFile);
|
|
40943
40813
|
const generator = new MidiFileGenerator(beat.voice.bar.staff.track.score, this.settings, handler);
|
|
40944
40814
|
generator.generateSingleBeat(beat);
|
|
40945
|
-
this.
|
|
40815
|
+
this._player.playOneTimeMidiFile(midiFile);
|
|
40946
40816
|
}
|
|
40947
40817
|
/**
|
|
40948
40818
|
* Triggers the play of the given note.
|
|
@@ -40977,15 +40847,12 @@
|
|
|
40977
40847
|
* ```
|
|
40978
40848
|
*/
|
|
40979
40849
|
playNote(note) {
|
|
40980
|
-
if (!this.player) {
|
|
40981
|
-
return;
|
|
40982
|
-
}
|
|
40983
40850
|
// we generate a new midi file containing only the beat
|
|
40984
40851
|
const midiFile = new MidiFile();
|
|
40985
40852
|
const handler = new AlphaSynthMidiFileHandler(midiFile);
|
|
40986
40853
|
const generator = new MidiFileGenerator(note.beat.voice.bar.staff.track.score, this.settings, handler);
|
|
40987
40854
|
generator.generateSingleNote(note);
|
|
40988
|
-
this.
|
|
40855
|
+
this._player.playOneTimeMidiFile(midiFile);
|
|
40989
40856
|
}
|
|
40990
40857
|
destroyCursors() {
|
|
40991
40858
|
if (!this._cursorWrapper) {
|
|
@@ -41017,36 +40884,6 @@
|
|
|
41017
40884
|
this.destroyCursors();
|
|
41018
40885
|
}
|
|
41019
40886
|
}
|
|
41020
|
-
setupPlayerEvents() {
|
|
41021
|
-
//
|
|
41022
|
-
// Hook into events
|
|
41023
|
-
this._previousTick = 0;
|
|
41024
|
-
this._playerState = PlayerState.Paused;
|
|
41025
|
-
// we need to update our position caches if we render a tablature
|
|
41026
|
-
this.renderer.postRenderFinished.on(() => {
|
|
41027
|
-
this._currentBeat = null;
|
|
41028
|
-
this.cursorUpdateTick(this._previousTick, false, 1, this._previousTick > 10);
|
|
41029
|
-
});
|
|
41030
|
-
if (this.player) {
|
|
41031
|
-
this.player.positionChanged.on(e => {
|
|
41032
|
-
this._previousTick = e.currentTick;
|
|
41033
|
-
this.uiFacade.beginInvoke(() => {
|
|
41034
|
-
const cursorSpeed = e.modifiedTempo / e.originalTempo;
|
|
41035
|
-
this.cursorUpdateTick(e.currentTick, false, cursorSpeed, false, e.isSeek);
|
|
41036
|
-
});
|
|
41037
|
-
});
|
|
41038
|
-
this.player.stateChanged.on(e => {
|
|
41039
|
-
this._playerState = e.state;
|
|
41040
|
-
if (!e.stopped && e.state === PlayerState.Paused) {
|
|
41041
|
-
const currentBeat = this._currentBeat;
|
|
41042
|
-
const tickCache = this._tickCache;
|
|
41043
|
-
if (currentBeat && tickCache) {
|
|
41044
|
-
this.player.tickPosition = tickCache.getBeatStart(currentBeat.beat);
|
|
41045
|
-
}
|
|
41046
|
-
}
|
|
41047
|
-
});
|
|
41048
|
-
}
|
|
41049
|
-
}
|
|
41050
40887
|
/**
|
|
41051
40888
|
* updates the cursors to highlight the beat at the specified tick position
|
|
41052
40889
|
* @param tick
|
|
@@ -41087,7 +40924,7 @@
|
|
|
41087
40924
|
if (!forceUpdate &&
|
|
41088
40925
|
beat === previousBeat?.beat &&
|
|
41089
40926
|
cache === previousCache &&
|
|
41090
|
-
previousState === this.
|
|
40927
|
+
previousState === this._player.state &&
|
|
41091
40928
|
previousBeat?.start === lookupResult.start) {
|
|
41092
40929
|
return;
|
|
41093
40930
|
}
|
|
@@ -41099,7 +40936,7 @@
|
|
|
41099
40936
|
// actually show the cursor
|
|
41100
40937
|
this._currentBeat = lookupResult;
|
|
41101
40938
|
this._previousCursorCache = cache;
|
|
41102
|
-
this._previousStateForCursor = this.
|
|
40939
|
+
this._previousStateForCursor = this._player.state;
|
|
41103
40940
|
this.uiFacade.beginInvoke(() => {
|
|
41104
40941
|
this.internalCursorUpdateBeat(beat, nextBeat, duration, stop, beatsToHighlight, cache, beatBoundings, shouldScroll, lookupResult.cursorMode, cursorSpeed);
|
|
41105
40942
|
});
|
|
@@ -41110,9 +40947,9 @@
|
|
|
41110
40947
|
* @category Methods - Player
|
|
41111
40948
|
*/
|
|
41112
40949
|
scrollToCursor() {
|
|
41113
|
-
const
|
|
41114
|
-
if (
|
|
41115
|
-
this.internalScrollToCursor(barBounds);
|
|
40950
|
+
const beatBounds = this._currentBeatBounds;
|
|
40951
|
+
if (beatBounds) {
|
|
40952
|
+
this.internalScrollToCursor(beatBounds.barBounds.masterBarBounds);
|
|
41116
40953
|
}
|
|
41117
40954
|
}
|
|
41118
40955
|
internalScrollToCursor(barBoundings) {
|
|
@@ -41171,10 +41008,12 @@
|
|
|
41171
41008
|
const beatCursor = this._beatCursor;
|
|
41172
41009
|
const barBoundings = beatBoundings.barBounds.masterBarBounds;
|
|
41173
41010
|
const barBounds = barBoundings.visualBounds;
|
|
41174
|
-
|
|
41011
|
+
const previousBeatBounds = this._currentBeatBounds;
|
|
41012
|
+
this._currentBeatBounds = beatBoundings;
|
|
41175
41013
|
if (barCursor) {
|
|
41176
41014
|
barCursor.setBounds(barBounds.x, barBounds.y, barBounds.w, barBounds.h);
|
|
41177
41015
|
}
|
|
41016
|
+
const isPlayingUpdate = this._player.state === PlayerState.Playing && !stop;
|
|
41178
41017
|
let nextBeatX = barBoundings.visualBounds.x + barBoundings.visualBounds.w;
|
|
41179
41018
|
// get position of next beat on same system
|
|
41180
41019
|
if (nextBeat && cursorMode === MidiTickLookupFindBeatResultCursorMode.ToNextBext) {
|
|
@@ -41192,12 +41031,38 @@
|
|
|
41192
41031
|
if (this.settings.player.enableAnimatedBeatCursor) {
|
|
41193
41032
|
const animationWidth = nextBeatX - beatBoundings.onNotesX;
|
|
41194
41033
|
const relativePosition = this._previousTick - this._currentBeat.start;
|
|
41195
|
-
const ratioPosition = relativePosition / this._currentBeat.tickDuration;
|
|
41034
|
+
const ratioPosition = this._currentBeat.tickDuration > 0 ? relativePosition / this._currentBeat.tickDuration : 0;
|
|
41196
41035
|
startBeatX = beatBoundings.onNotesX + animationWidth * ratioPosition;
|
|
41197
41036
|
duration -= duration * ratioPosition;
|
|
41198
|
-
|
|
41037
|
+
if (isPlayingUpdate) {
|
|
41038
|
+
// we do not "reset" the cursor if we are smoothly moving from left to right.
|
|
41039
|
+
const jumpCursor = !previousBeatBounds ||
|
|
41040
|
+
barBounds.y !== previousBeatBounds.barBounds.masterBarBounds.visualBounds.y ||
|
|
41041
|
+
startBeatX < previousBeatBounds.onNotesX ||
|
|
41042
|
+
barBoundings.index > previousBeatBounds.barBounds.masterBarBounds.index + 1;
|
|
41043
|
+
if (jumpCursor) {
|
|
41044
|
+
beatCursor.transitionToX(0, startBeatX);
|
|
41045
|
+
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
41046
|
+
}
|
|
41047
|
+
// we need to put the transition to an own animation frame
|
|
41048
|
+
// otherwise the stop animation above is not applied.
|
|
41049
|
+
this.uiFacade.beginInvoke(() => {
|
|
41050
|
+
// it can happen that the cursor reaches the target position slightly too early (especially on backing tracks)
|
|
41051
|
+
// to avoid the cursor stopping, causing a wierd look, we animate the cursor to the double position in double time.
|
|
41052
|
+
// beatCursor!.transitionToX((duration / cursorSpeed), nextBeatX);
|
|
41053
|
+
const doubleEndBeatX = startBeatX + (nextBeatX - startBeatX) * 2;
|
|
41054
|
+
beatCursor.transitionToX((duration / cursorSpeed) * 2, doubleEndBeatX);
|
|
41055
|
+
});
|
|
41056
|
+
}
|
|
41057
|
+
else {
|
|
41058
|
+
beatCursor.transitionToX(0, startBeatX);
|
|
41059
|
+
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
41060
|
+
}
|
|
41061
|
+
}
|
|
41062
|
+
else {
|
|
41063
|
+
// ticking cursor
|
|
41064
|
+
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
41199
41065
|
}
|
|
41200
|
-
beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
|
|
41201
41066
|
}
|
|
41202
41067
|
// if playing, animate the cursor to the next beat
|
|
41203
41068
|
if (this.settings.player.enableElementHighlighting) {
|
|
@@ -41205,7 +41070,6 @@
|
|
|
41205
41070
|
}
|
|
41206
41071
|
// actively playing? -> animate cursor and highlight items
|
|
41207
41072
|
let shouldNotifyBeatChange = false;
|
|
41208
|
-
const isPlayingUpdate = this._playerState === PlayerState.Playing && !stop;
|
|
41209
41073
|
if (isPlayingUpdate) {
|
|
41210
41074
|
if (this.settings.player.enableElementHighlighting) {
|
|
41211
41075
|
for (const highlight of beatsToHighlight) {
|
|
@@ -41216,15 +41080,6 @@
|
|
|
41216
41080
|
shouldScroll = !stop;
|
|
41217
41081
|
shouldNotifyBeatChange = true;
|
|
41218
41082
|
}
|
|
41219
|
-
if (this.settings.player.enableAnimatedBeatCursor && beatCursor) {
|
|
41220
|
-
if (isPlayingUpdate) {
|
|
41221
|
-
// we need to put the transition to an own animation frame
|
|
41222
|
-
// otherwise the stop animation above is not applied.
|
|
41223
|
-
this.uiFacade.beginInvoke(() => {
|
|
41224
|
-
beatCursor.transitionToX(duration / cursorSpeed, nextBeatX);
|
|
41225
|
-
});
|
|
41226
|
-
}
|
|
41227
|
-
}
|
|
41228
41083
|
if (shouldScroll && !this._beatMouseDown && this.settings.player.scrollMode !== exports.ScrollMode.Off) {
|
|
41229
41084
|
this.internalScrollToCursor(barBoundings);
|
|
41230
41085
|
}
|
|
@@ -41314,7 +41169,7 @@
|
|
|
41314
41169
|
const realMasterBarStart = tickCache.getMasterBarStart(this._selectionStart.beat.voice.bar.masterBar);
|
|
41315
41170
|
// move to selection start
|
|
41316
41171
|
this._currentBeat = null; // reset current beat so it is updating the cursor
|
|
41317
|
-
if (this.
|
|
41172
|
+
if (this._player.state === PlayerState.Paused) {
|
|
41318
41173
|
this.cursorUpdateTick(this._tickCache.getBeatStart(this._selectionStart.beat), false, 1);
|
|
41319
41174
|
}
|
|
41320
41175
|
this.tickPosition = realMasterBarStart + this._selectionStart.beat.playbackStart;
|
|
@@ -41505,7 +41360,7 @@
|
|
|
41505
41360
|
}
|
|
41506
41361
|
this.scoreLoaded.trigger(score);
|
|
41507
41362
|
this.uiFacade.triggerEvent(this.container, 'scoreLoaded', score);
|
|
41508
|
-
if (this.
|
|
41363
|
+
if (this.setupOrDestroyPlayer()) {
|
|
41509
41364
|
this.loadMidiForScore();
|
|
41510
41365
|
}
|
|
41511
41366
|
}
|
|
@@ -41534,6 +41389,8 @@
|
|
|
41534
41389
|
if (this._isDestroyed) {
|
|
41535
41390
|
return;
|
|
41536
41391
|
}
|
|
41392
|
+
this._currentBeat = null;
|
|
41393
|
+
this.cursorUpdateTick(this._previousTick, false, 1, this._previousTick > 10);
|
|
41537
41394
|
this.postRenderFinished.trigger();
|
|
41538
41395
|
this.uiFacade.triggerEvent(this.container, 'postRenderFinished', null);
|
|
41539
41396
|
}
|
|
@@ -41548,25 +41405,155 @@
|
|
|
41548
41405
|
this.error.trigger(error);
|
|
41549
41406
|
this.uiFacade.triggerEvent(this.container, 'error', error);
|
|
41550
41407
|
}
|
|
41408
|
+
/**
|
|
41409
|
+
* This event is fired when all required data for playback is loaded and ready.
|
|
41410
|
+
* @remarks
|
|
41411
|
+
* This event is fired when all required data for playback is loaded and ready. The player is ready for playback when
|
|
41412
|
+
* all background workers are started, the audio output is initialized, a soundfont is loaded, and a song was loaded into the player as midi file.
|
|
41413
|
+
*
|
|
41414
|
+
* @eventProperty
|
|
41415
|
+
* @category Events - Player
|
|
41416
|
+
* @since 0.9.4
|
|
41417
|
+
*
|
|
41418
|
+
* @example
|
|
41419
|
+
* JavaScript
|
|
41420
|
+
* ```js
|
|
41421
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41422
|
+
* api.playerReady.on(() => {
|
|
41423
|
+
* enablePlayerControls();
|
|
41424
|
+
* });
|
|
41425
|
+
* ```
|
|
41426
|
+
*
|
|
41427
|
+
* @example
|
|
41428
|
+
* C#
|
|
41429
|
+
* ```cs
|
|
41430
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41431
|
+
* api.PlayerReady.On(() =>
|
|
41432
|
+
* {
|
|
41433
|
+
* EnablePlayerControls()
|
|
41434
|
+
* });
|
|
41435
|
+
* ```
|
|
41436
|
+
*
|
|
41437
|
+
* @example
|
|
41438
|
+
* Android
|
|
41439
|
+
* ```kotlin
|
|
41440
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
41441
|
+
* api.playerReady.on {
|
|
41442
|
+
* enablePlayerControls()
|
|
41443
|
+
* }
|
|
41444
|
+
* ```
|
|
41445
|
+
*/
|
|
41446
|
+
get playerReady() {
|
|
41447
|
+
return this._player.readyForPlayback;
|
|
41448
|
+
}
|
|
41551
41449
|
onPlayerReady() {
|
|
41552
41450
|
if (this._isDestroyed) {
|
|
41553
41451
|
return;
|
|
41554
41452
|
}
|
|
41555
|
-
this.playerReady.trigger();
|
|
41556
41453
|
this.uiFacade.triggerEvent(this.container, 'playerReady', null);
|
|
41557
41454
|
}
|
|
41455
|
+
/**
|
|
41456
|
+
* This event is fired when the playback of the whole song finished.
|
|
41457
|
+
* @remarks
|
|
41458
|
+
* This event is finished regardless on whether looping is enabled or not.
|
|
41459
|
+
*
|
|
41460
|
+
* @eventProperty
|
|
41461
|
+
* @category Events - Player
|
|
41462
|
+
* @since 0.9.4
|
|
41463
|
+
*
|
|
41464
|
+
* @example
|
|
41465
|
+
* JavaScript
|
|
41466
|
+
* ```js
|
|
41467
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41468
|
+
* api.playerFinished.on((args) => {
|
|
41469
|
+
* // speed trainer
|
|
41470
|
+
* api.playbackSpeed = Math.min(1.0, api.playbackSpeed + 0.1);
|
|
41471
|
+
* });
|
|
41472
|
+
* api.isLooping = true;
|
|
41473
|
+
* api.playbackSpeed = 0.5;
|
|
41474
|
+
* api.play()
|
|
41475
|
+
* ```
|
|
41476
|
+
*
|
|
41477
|
+
* @example
|
|
41478
|
+
* C#
|
|
41479
|
+
* ```cs
|
|
41480
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41481
|
+
* api.PlayerFinished.On(() =>
|
|
41482
|
+
* {
|
|
41483
|
+
* // speed trainer
|
|
41484
|
+
* api.PlaybackSpeed = Math.Min(1.0, api.PlaybackSpeed + 0.1);
|
|
41485
|
+
* });
|
|
41486
|
+
* api.IsLooping = true;
|
|
41487
|
+
* api.PlaybackSpeed = 0.5;
|
|
41488
|
+
* api.Play();
|
|
41489
|
+
* ```
|
|
41490
|
+
*
|
|
41491
|
+
* @example
|
|
41492
|
+
* Android
|
|
41493
|
+
* ```kotlin
|
|
41494
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
41495
|
+
* api.playerFinished.on {
|
|
41496
|
+
* // speed trainer
|
|
41497
|
+
* api.playbackSpeed = min(1.0, api.playbackSpeed + 0.1);
|
|
41498
|
+
* }
|
|
41499
|
+
* api.isLooping = true
|
|
41500
|
+
* api.playbackSpeed = 0.5
|
|
41501
|
+
* api.play()
|
|
41502
|
+
* ```
|
|
41503
|
+
*
|
|
41504
|
+
*/
|
|
41505
|
+
get playerFinished() {
|
|
41506
|
+
return this._player.finished;
|
|
41507
|
+
}
|
|
41558
41508
|
onPlayerFinished() {
|
|
41559
41509
|
if (this._isDestroyed) {
|
|
41560
41510
|
return;
|
|
41561
41511
|
}
|
|
41562
|
-
this.playerFinished.trigger();
|
|
41563
41512
|
this.uiFacade.triggerEvent(this.container, 'playerFinished', null);
|
|
41564
41513
|
}
|
|
41514
|
+
/**
|
|
41515
|
+
* This event is fired when the SoundFont needed for playback was loaded.
|
|
41516
|
+
*
|
|
41517
|
+
* @eventProperty
|
|
41518
|
+
* @category Events - Player
|
|
41519
|
+
* @since 0.9.4
|
|
41520
|
+
*
|
|
41521
|
+
* @example
|
|
41522
|
+
* JavaScript
|
|
41523
|
+
* ```js
|
|
41524
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41525
|
+
* api.soundFontLoaded.on(() => {
|
|
41526
|
+
* hideSoundFontLoadingIndicator();
|
|
41527
|
+
* });
|
|
41528
|
+
* ```
|
|
41529
|
+
*
|
|
41530
|
+
* @example
|
|
41531
|
+
* C#
|
|
41532
|
+
* ```cs
|
|
41533
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41534
|
+
* api.SoundFontLoaded.On(() =>
|
|
41535
|
+
* {
|
|
41536
|
+
* HideSoundFontLoadingIndicator();
|
|
41537
|
+
* });
|
|
41538
|
+
* ```
|
|
41539
|
+
*
|
|
41540
|
+
* @example
|
|
41541
|
+
* Android
|
|
41542
|
+
* ```kotlin
|
|
41543
|
+
* val api = AlphaTabApi<MyControl>(...);
|
|
41544
|
+
* api.soundFontLoaded.on {
|
|
41545
|
+
* hideSoundFontLoadingIndicator();
|
|
41546
|
+
* }
|
|
41547
|
+
* ```
|
|
41548
|
+
*
|
|
41549
|
+
*/
|
|
41550
|
+
get soundFontLoaded() {
|
|
41551
|
+
return this._player.soundFontLoaded;
|
|
41552
|
+
}
|
|
41565
41553
|
onSoundFontLoaded() {
|
|
41566
41554
|
if (this._isDestroyed) {
|
|
41567
41555
|
return;
|
|
41568
41556
|
}
|
|
41569
|
-
this.soundFontLoaded.trigger();
|
|
41570
41557
|
this.uiFacade.triggerEvent(this.container, 'soundFontLoaded', null);
|
|
41571
41558
|
}
|
|
41572
41559
|
onMidiLoad(e) {
|
|
@@ -41583,34 +41570,255 @@
|
|
|
41583
41570
|
this.midiLoaded.trigger(e);
|
|
41584
41571
|
this.uiFacade.triggerEvent(this.container, 'midiFileLoaded', e);
|
|
41585
41572
|
}
|
|
41573
|
+
/**
|
|
41574
|
+
* This event is fired when the playback state changed.
|
|
41575
|
+
*
|
|
41576
|
+
* @eventProperty
|
|
41577
|
+
* @category Events - Player
|
|
41578
|
+
* @since 0.9.4
|
|
41579
|
+
*
|
|
41580
|
+
* @example
|
|
41581
|
+
* JavaScript
|
|
41582
|
+
* ```js
|
|
41583
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41584
|
+
* api.playerStateChanged.on((args) => {
|
|
41585
|
+
* updatePlayerControls(args.state, args.stopped);
|
|
41586
|
+
* });
|
|
41587
|
+
* ```
|
|
41588
|
+
*
|
|
41589
|
+
* @example
|
|
41590
|
+
* C#
|
|
41591
|
+
* ```cs
|
|
41592
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41593
|
+
* api.PlayerStateChanged.On(args =>
|
|
41594
|
+
* {
|
|
41595
|
+
* UpdatePlayerControls(args);
|
|
41596
|
+
* });
|
|
41597
|
+
* ```
|
|
41598
|
+
*
|
|
41599
|
+
* @example
|
|
41600
|
+
* Android
|
|
41601
|
+
* ```kotlin
|
|
41602
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
41603
|
+
* api.playerStateChanged.on { args ->
|
|
41604
|
+
* updatePlayerControls(args)
|
|
41605
|
+
* }
|
|
41606
|
+
* ```
|
|
41607
|
+
*
|
|
41608
|
+
*/
|
|
41609
|
+
get playerStateChanged() {
|
|
41610
|
+
return this._player.stateChanged;
|
|
41611
|
+
}
|
|
41586
41612
|
onPlayerStateChanged(e) {
|
|
41587
41613
|
if (this._isDestroyed) {
|
|
41588
41614
|
return;
|
|
41589
41615
|
}
|
|
41590
|
-
|
|
41616
|
+
if (!e.stopped && e.state === PlayerState.Paused) {
|
|
41617
|
+
const currentBeat = this._currentBeat;
|
|
41618
|
+
const tickCache = this._tickCache;
|
|
41619
|
+
if (currentBeat && tickCache) {
|
|
41620
|
+
this._player.tickPosition = tickCache.getBeatStart(currentBeat.beat);
|
|
41621
|
+
}
|
|
41622
|
+
}
|
|
41591
41623
|
this.uiFacade.triggerEvent(this.container, 'playerStateChanged', e);
|
|
41592
41624
|
}
|
|
41625
|
+
/**
|
|
41626
|
+
* This event is fired when the current playback position of the song changed.
|
|
41627
|
+
*
|
|
41628
|
+
* @eventProperty
|
|
41629
|
+
* @category Events - Player
|
|
41630
|
+
* @since 0.9.4
|
|
41631
|
+
*
|
|
41632
|
+
* @example
|
|
41633
|
+
* JavaScript
|
|
41634
|
+
* ```js
|
|
41635
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41636
|
+
* api.playerPositionChanged.on((args) => {
|
|
41637
|
+
* updatePlayerPosition(args);
|
|
41638
|
+
* });
|
|
41639
|
+
* ```
|
|
41640
|
+
*
|
|
41641
|
+
* @example
|
|
41642
|
+
* C#
|
|
41643
|
+
* ```cs
|
|
41644
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41645
|
+
* api.PlayerPositionChanged.On(args =>
|
|
41646
|
+
* {
|
|
41647
|
+
* UpdatePlayerPosition(args);
|
|
41648
|
+
* });
|
|
41649
|
+
* ```
|
|
41650
|
+
*
|
|
41651
|
+
* @example
|
|
41652
|
+
* Android
|
|
41653
|
+
* ```kotlin
|
|
41654
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
41655
|
+
* api.playerPositionChanged.on { args ->
|
|
41656
|
+
* updatePlayerPosition(args)
|
|
41657
|
+
* }
|
|
41658
|
+
* ```
|
|
41659
|
+
*
|
|
41660
|
+
*/
|
|
41661
|
+
get playerPositionChanged() {
|
|
41662
|
+
return this._player.positionChanged;
|
|
41663
|
+
}
|
|
41593
41664
|
onPlayerPositionChanged(e) {
|
|
41594
41665
|
if (this._isDestroyed) {
|
|
41595
41666
|
return;
|
|
41596
41667
|
}
|
|
41597
|
-
|
|
41598
|
-
|
|
41599
|
-
|
|
41600
|
-
|
|
41668
|
+
this._previousTick = e.currentTick;
|
|
41669
|
+
this.uiFacade.beginInvoke(() => {
|
|
41670
|
+
const cursorSpeed = e.modifiedTempo / e.originalTempo;
|
|
41671
|
+
this.cursorUpdateTick(e.currentTick, false, cursorSpeed, false, e.isSeek);
|
|
41672
|
+
});
|
|
41673
|
+
this.uiFacade.triggerEvent(this.container, 'playerPositionChanged', e);
|
|
41674
|
+
}
|
|
41675
|
+
/**
|
|
41676
|
+
* This event is fired when the synthesizer played certain midi events.
|
|
41677
|
+
*
|
|
41678
|
+
* @remarks
|
|
41679
|
+
* This event is fired when the synthesizer played certain midi events. This allows reacing on various low level
|
|
41680
|
+
* audio playback elements like notes/rests played or metronome ticks.
|
|
41681
|
+
*
|
|
41682
|
+
* Refer to the [related guide](https://www.alphatab.net/docs/guides/handling-midi-events) to learn more about this feature.
|
|
41683
|
+
*
|
|
41684
|
+
* Also note that the provided data models changed significantly in {@version 1.3.0}. We try to provide backwards compatibility
|
|
41685
|
+
* until some extend but highly encourage changing to the new models in case of problems.
|
|
41686
|
+
*
|
|
41687
|
+
* @eventProperty
|
|
41688
|
+
* @category Events - Player
|
|
41689
|
+
* @since 1.2.0
|
|
41690
|
+
*
|
|
41691
|
+
* @example
|
|
41692
|
+
* JavaScript
|
|
41693
|
+
* ```js
|
|
41694
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41695
|
+
* api.midiEventsPlayedFilter = [alphaTab.midi.MidiEventType.AlphaTabMetronome];
|
|
41696
|
+
* api.midiEventsPlayed.on(function(e) {
|
|
41697
|
+
* for(const midi of e.events) {
|
|
41698
|
+
* if(midi.isMetronome) {
|
|
41699
|
+
* console.log('Metronome tick ' + midi.tick);
|
|
41700
|
+
* }
|
|
41701
|
+
* }
|
|
41702
|
+
* });
|
|
41703
|
+
* ```
|
|
41704
|
+
*
|
|
41705
|
+
* @example
|
|
41706
|
+
* C#
|
|
41707
|
+
* ```cs
|
|
41708
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41709
|
+
* api.MidiEventsPlayedFilter = new MidiEventType[] { AlphaTab.Midi.MidiEventType.AlphaTabMetronome };
|
|
41710
|
+
* api.MidiEventsPlayed.On(e =>
|
|
41711
|
+
* {
|
|
41712
|
+
* foreach(var midi of e.events)
|
|
41713
|
+
* {
|
|
41714
|
+
* if(midi is AlphaTab.Midi.AlphaTabMetronomeEvent sysex && sysex.IsMetronome)
|
|
41715
|
+
* {
|
|
41716
|
+
* Console.WriteLine("Metronome tick " + midi.Tick);
|
|
41717
|
+
* }
|
|
41718
|
+
* }
|
|
41719
|
+
* });
|
|
41720
|
+
* ```
|
|
41721
|
+
*
|
|
41722
|
+
* @example
|
|
41723
|
+
* Android
|
|
41724
|
+
* ```kotlin
|
|
41725
|
+
* val api = AlphaTabApi<MyControl>(...);
|
|
41726
|
+
* api.midiEventsPlayedFilter = alphaTab.collections.List<alphaTab.midi.MidiEventType>( alphaTab.midi.MidiEventType.AlphaTabMetronome )
|
|
41727
|
+
* api.midiEventsPlayed.on { e ->
|
|
41728
|
+
* for (midi in e.events) {
|
|
41729
|
+
* if(midi instanceof alphaTab.midi.AlphaTabMetronomeEvent && midi.isMetronome) {
|
|
41730
|
+
* println("Metronome tick " + midi.tick);
|
|
41731
|
+
* }
|
|
41732
|
+
* }
|
|
41733
|
+
* }
|
|
41734
|
+
* ```
|
|
41735
|
+
* @see {@link MidiEvent}
|
|
41736
|
+
* @see {@link TimeSignatureEvent}
|
|
41737
|
+
* @see {@link AlphaTabMetronomeEvent}
|
|
41738
|
+
* @see {@link AlphaTabRestEvent}
|
|
41739
|
+
* @see {@link NoteOnEvent}
|
|
41740
|
+
* @see {@link NoteOffEvent}
|
|
41741
|
+
* @see {@link ControlChangeEvent}
|
|
41742
|
+
* @see {@link ProgramChangeEvent}
|
|
41743
|
+
* @see {@link TempoChangeEvent}
|
|
41744
|
+
* @see {@link PitchBendEvent}
|
|
41745
|
+
* @see {@link NoteBendEvent}
|
|
41746
|
+
* @see {@link EndOfTrackEvent}
|
|
41747
|
+
* @see {@link MetaEvent}
|
|
41748
|
+
* @see {@link MetaDataEvent}
|
|
41749
|
+
* @see {@link MetaNumberEvent}
|
|
41750
|
+
* @see {@link Midi20PerNotePitchBendEvent}
|
|
41751
|
+
* @see {@link SystemCommonEvent}
|
|
41752
|
+
* @see {@link SystemExclusiveEvent}
|
|
41753
|
+
*/
|
|
41754
|
+
get midiEventsPlayed() {
|
|
41755
|
+
return this._player.midiEventsPlayed;
|
|
41601
41756
|
}
|
|
41602
41757
|
onMidiEventsPlayed(e) {
|
|
41603
41758
|
if (this._isDestroyed) {
|
|
41604
41759
|
return;
|
|
41605
41760
|
}
|
|
41606
|
-
this.midiEventsPlayed.trigger(e);
|
|
41607
41761
|
this.uiFacade.triggerEvent(this.container, 'midiEventsPlayed', e);
|
|
41608
41762
|
}
|
|
41763
|
+
/**
|
|
41764
|
+
* This event is fired when the playback range changed.
|
|
41765
|
+
*
|
|
41766
|
+
* @eventProperty
|
|
41767
|
+
* @category Events - Player
|
|
41768
|
+
* @since 1.2.3
|
|
41769
|
+
*
|
|
41770
|
+
* @example
|
|
41771
|
+
* JavaScript
|
|
41772
|
+
* ```js
|
|
41773
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
41774
|
+
* api.playbackRangeChanged.on((args) => {
|
|
41775
|
+
* if (args.playbackRange) {
|
|
41776
|
+
* highlightRangeInProgressBar(args.playbackRange.startTick, args.playbackRange.endTick);
|
|
41777
|
+
* } else {
|
|
41778
|
+
* clearHighlightInProgressBar();
|
|
41779
|
+
* }
|
|
41780
|
+
* });
|
|
41781
|
+
* ```
|
|
41782
|
+
*
|
|
41783
|
+
* @example
|
|
41784
|
+
* C#
|
|
41785
|
+
* ```cs
|
|
41786
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
41787
|
+
* api.PlaybackRangeChanged.On(args =>
|
|
41788
|
+
* {
|
|
41789
|
+
* if (args.PlaybackRange != null)
|
|
41790
|
+
* {
|
|
41791
|
+
* HighlightRangeInProgressBar(args.PlaybackRange.StartTick, args.PlaybackRange.EndTick);
|
|
41792
|
+
* }
|
|
41793
|
+
* else
|
|
41794
|
+
* {
|
|
41795
|
+
* ClearHighlightInProgressBar();
|
|
41796
|
+
* }
|
|
41797
|
+
* });
|
|
41798
|
+
* ```
|
|
41799
|
+
*
|
|
41800
|
+
* @example
|
|
41801
|
+
* Android
|
|
41802
|
+
* ```kotlin
|
|
41803
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
41804
|
+
* api.playbackRangeChanged.on { args ->
|
|
41805
|
+
* val playbackRange = args.playbackRange
|
|
41806
|
+
* if (playbackRange != null) {
|
|
41807
|
+
* highlightRangeInProgressBar(playbackRange.startTick, playbackRange.endTick)
|
|
41808
|
+
* } else {
|
|
41809
|
+
* clearHighlightInProgressBar()
|
|
41810
|
+
* }
|
|
41811
|
+
* }
|
|
41812
|
+
* ```
|
|
41813
|
+
*
|
|
41814
|
+
*/
|
|
41815
|
+
get playbackRangeChanged() {
|
|
41816
|
+
return this._player.playbackRangeChanged;
|
|
41817
|
+
}
|
|
41609
41818
|
onPlaybackRangeChanged(e) {
|
|
41610
41819
|
if (this._isDestroyed) {
|
|
41611
41820
|
return;
|
|
41612
41821
|
}
|
|
41613
|
-
this.playbackRangeChanged.trigger(e);
|
|
41614
41822
|
this.uiFacade.triggerEvent(this.container, 'playbackRangeChanged', e);
|
|
41615
41823
|
}
|
|
41616
41824
|
onSettingsUpdated() {
|
|
@@ -41672,10 +41880,7 @@
|
|
|
41672
41880
|
* ```
|
|
41673
41881
|
*/
|
|
41674
41882
|
async enumerateOutputDevices() {
|
|
41675
|
-
|
|
41676
|
-
return await this.player.output.enumerateOutputDevices();
|
|
41677
|
-
}
|
|
41678
|
-
return [];
|
|
41883
|
+
return await this._player.output.enumerateOutputDevices();
|
|
41679
41884
|
}
|
|
41680
41885
|
/**
|
|
41681
41886
|
* Changes the output device which should be used for playing the audio (player must be enabled).
|
|
@@ -41726,9 +41931,7 @@
|
|
|
41726
41931
|
* ```
|
|
41727
41932
|
*/
|
|
41728
41933
|
async setOutputDevice(device) {
|
|
41729
|
-
|
|
41730
|
-
await this.player.output.setOutputDevice(device);
|
|
41731
|
-
}
|
|
41934
|
+
await this._player.output.setOutputDevice(device);
|
|
41732
41935
|
}
|
|
41733
41936
|
/**
|
|
41734
41937
|
* The currently configured output device if changed via {@link setOutputDevice}.
|
|
@@ -41768,10 +41971,7 @@
|
|
|
41768
41971
|
*
|
|
41769
41972
|
*/
|
|
41770
41973
|
async getOutputDevice() {
|
|
41771
|
-
|
|
41772
|
-
return await this.player.output.getOutputDevice();
|
|
41773
|
-
}
|
|
41774
|
-
return null;
|
|
41974
|
+
return await this._player.output.getOutputDevice();
|
|
41775
41975
|
}
|
|
41776
41976
|
}
|
|
41777
41977
|
|
|
@@ -41948,38 +42148,52 @@
|
|
|
41948
42148
|
this.element = element;
|
|
41949
42149
|
this.mouseDown = {
|
|
41950
42150
|
on: (value) => {
|
|
41951
|
-
|
|
42151
|
+
const nativeListener = e => {
|
|
41952
42152
|
value(new BrowserMouseEventArgs(e));
|
|
41953
|
-
}
|
|
42153
|
+
};
|
|
42154
|
+
this.element.addEventListener('mousedown', nativeListener, true);
|
|
42155
|
+
return () => {
|
|
42156
|
+
this.element.removeEventListener('mousedown', nativeListener, true);
|
|
42157
|
+
};
|
|
41954
42158
|
},
|
|
41955
42159
|
off: (value) => {
|
|
41956
42160
|
}
|
|
41957
42161
|
};
|
|
41958
42162
|
this.mouseUp = {
|
|
41959
42163
|
on: (value) => {
|
|
41960
|
-
|
|
42164
|
+
const nativeListener = e => {
|
|
41961
42165
|
value(new BrowserMouseEventArgs(e));
|
|
41962
|
-
}
|
|
42166
|
+
};
|
|
42167
|
+
this.element.addEventListener('mouseup', nativeListener, true);
|
|
42168
|
+
return () => {
|
|
42169
|
+
this.element.removeEventListener('mouseup', nativeListener, true);
|
|
42170
|
+
};
|
|
41963
42171
|
},
|
|
41964
42172
|
off: (value) => {
|
|
41965
42173
|
}
|
|
41966
42174
|
};
|
|
41967
42175
|
this.mouseMove = {
|
|
41968
42176
|
on: (value) => {
|
|
41969
|
-
|
|
42177
|
+
const nativeListener = e => {
|
|
41970
42178
|
value(new BrowserMouseEventArgs(e));
|
|
41971
|
-
}
|
|
42179
|
+
};
|
|
42180
|
+
this.element.addEventListener('mousemove', nativeListener, true);
|
|
42181
|
+
return () => {
|
|
42182
|
+
this.element.removeEventListener('mousemove', nativeListener, true);
|
|
42183
|
+
};
|
|
41972
42184
|
},
|
|
41973
42185
|
off: (_) => {
|
|
41974
42186
|
}
|
|
41975
42187
|
};
|
|
42188
|
+
const container = this;
|
|
41976
42189
|
this.resize = {
|
|
41977
|
-
on: (value)
|
|
41978
|
-
if (
|
|
41979
|
-
HtmlElementContainer.resizeObserver.value.observe(
|
|
42190
|
+
on: function (value) {
|
|
42191
|
+
if (container._resizeListeners === 0) {
|
|
42192
|
+
HtmlElementContainer.resizeObserver.value.observe(container.element);
|
|
41980
42193
|
}
|
|
41981
|
-
|
|
41982
|
-
|
|
42194
|
+
container.element.addEventListener('resize', value, true);
|
|
42195
|
+
container._resizeListeners++;
|
|
42196
|
+
return () => this.off(value);
|
|
41983
42197
|
},
|
|
41984
42198
|
off: (value) => {
|
|
41985
42199
|
this.element.removeEventListener('resize', value, true);
|
|
@@ -42560,21 +42774,6 @@
|
|
|
42560
42774
|
}
|
|
42561
42775
|
}
|
|
42562
42776
|
|
|
42563
|
-
/**
|
|
42564
|
-
* Represents the progress of any data being loaded.
|
|
42565
|
-
*/
|
|
42566
|
-
class ProgressEventArgs {
|
|
42567
|
-
/**
|
|
42568
|
-
* Initializes a new instance of the {@link ProgressEventArgs} class.
|
|
42569
|
-
* @param loaded
|
|
42570
|
-
* @param total
|
|
42571
|
-
*/
|
|
42572
|
-
constructor(loaded, total) {
|
|
42573
|
-
this.loaded = loaded;
|
|
42574
|
-
this.total = total;
|
|
42575
|
-
}
|
|
42576
|
-
}
|
|
42577
|
-
|
|
42578
42777
|
/**
|
|
42579
42778
|
* a WebWorker based alphaSynth which uses the given player as output.
|
|
42580
42779
|
* @target web
|
|
@@ -42811,25 +43010,6 @@
|
|
|
42811
43010
|
append: append
|
|
42812
43011
|
});
|
|
42813
43012
|
}
|
|
42814
|
-
loadSoundFontFromUrl(url, append, progress) {
|
|
42815
|
-
Logger.debug('AlphaSynth', `Start loading Soundfont from url ${url}`);
|
|
42816
|
-
const request = new XMLHttpRequest();
|
|
42817
|
-
request.open('GET', url, true, null, null);
|
|
42818
|
-
request.responseType = 'arraybuffer';
|
|
42819
|
-
request.onload = _ => {
|
|
42820
|
-
const buffer = new Uint8Array(request.response);
|
|
42821
|
-
this.loadSoundFont(buffer, append);
|
|
42822
|
-
};
|
|
42823
|
-
request.onerror = e => {
|
|
42824
|
-
Logger.error('AlphaSynth', `Loading failed: ${e.message}`);
|
|
42825
|
-
this.soundFontLoadFailed.trigger(new FileLoadError(e.message, request));
|
|
42826
|
-
};
|
|
42827
|
-
request.onprogress = e => {
|
|
42828
|
-
Logger.debug('AlphaSynth', `Soundfont downloading: ${e.loaded}/${e.total} bytes`);
|
|
42829
|
-
progress(new ProgressEventArgs(e.loaded, e.total));
|
|
42830
|
-
};
|
|
42831
|
-
request.send();
|
|
42832
|
-
}
|
|
42833
43013
|
resetSoundFonts() {
|
|
42834
43014
|
this._synth.postMessage({
|
|
42835
43015
|
cmd: 'alphaSynth.resetSoundFonts'
|
|
@@ -43381,7 +43561,11 @@
|
|
|
43381
43561
|
}
|
|
43382
43562
|
this._padding = backingTrack.padding / 1000;
|
|
43383
43563
|
const blob = new Blob([backingTrack.rawAudioFile]);
|
|
43564
|
+
// https://html.spec.whatwg.org/multipage/media.html#loading-the-media-resource
|
|
43565
|
+
// Step 8. resets the playbackRate, we need to remember and restore it.
|
|
43566
|
+
const playbackRate = this.audioElement.playbackRate;
|
|
43384
43567
|
this.audioElement.src = URL.createObjectURL(blob);
|
|
43568
|
+
this.audioElement.playbackRate = playbackRate;
|
|
43385
43569
|
}
|
|
43386
43570
|
open(_bufferTimeInMilliseconds) {
|
|
43387
43571
|
const audioElement = document.createElement('audio');
|
|
@@ -44100,6 +44284,21 @@
|
|
|
44100
44284
|
}
|
|
44101
44285
|
}
|
|
44102
44286
|
|
|
44287
|
+
/**
|
|
44288
|
+
* Represents the progress of any data being loaded.
|
|
44289
|
+
*/
|
|
44290
|
+
class ProgressEventArgs {
|
|
44291
|
+
/**
|
|
44292
|
+
* Initializes a new instance of the {@link ProgressEventArgs} class.
|
|
44293
|
+
* @param loaded
|
|
44294
|
+
* @param total
|
|
44295
|
+
*/
|
|
44296
|
+
constructor(loaded, total) {
|
|
44297
|
+
this.loaded = loaded;
|
|
44298
|
+
this.total = total;
|
|
44299
|
+
}
|
|
44300
|
+
}
|
|
44301
|
+
|
|
44103
44302
|
/**
|
|
44104
44303
|
* @target web
|
|
44105
44304
|
*/
|
|
@@ -44343,13 +44542,29 @@
|
|
|
44343
44542
|
* @since 0.9.4
|
|
44344
44543
|
*/
|
|
44345
44544
|
loadSoundFontFromUrl(url, append) {
|
|
44346
|
-
|
|
44545
|
+
const player = this.player;
|
|
44546
|
+
if (!player) {
|
|
44347
44547
|
return;
|
|
44348
44548
|
}
|
|
44349
|
-
|
|
44350
|
-
|
|
44351
|
-
|
|
44352
|
-
|
|
44549
|
+
Logger.debug('AlphaSynth', `Start loading Soundfont from url ${url}`);
|
|
44550
|
+
const request = new XMLHttpRequest();
|
|
44551
|
+
request.open('GET', url, true, null, null);
|
|
44552
|
+
request.responseType = 'arraybuffer';
|
|
44553
|
+
request.onload = _ => {
|
|
44554
|
+
const buffer = new Uint8Array(request.response);
|
|
44555
|
+
this.loadSoundFont(buffer, append);
|
|
44556
|
+
};
|
|
44557
|
+
request.onerror = e => {
|
|
44558
|
+
Logger.error('AlphaSynth', `Loading failed: ${e.message}`);
|
|
44559
|
+
player.soundFontLoadFailed.trigger(new FileLoadError(e.message, request));
|
|
44560
|
+
};
|
|
44561
|
+
request.onprogress = e => {
|
|
44562
|
+
Logger.debug('AlphaSynth', `Soundfont downloading: ${e.loaded}/${e.total} bytes`);
|
|
44563
|
+
const args = new ProgressEventArgs(e.loaded, e.total);
|
|
44564
|
+
this.soundFontLoad.trigger(args);
|
|
44565
|
+
this.uiFacade.triggerEvent(this.container, 'soundFontLoad', args);
|
|
44566
|
+
};
|
|
44567
|
+
request.send();
|
|
44353
44568
|
}
|
|
44354
44569
|
}
|
|
44355
44570
|
|
|
@@ -60316,9 +60531,9 @@
|
|
|
60316
60531
|
print(`build date: ${VersionInfo.date}`);
|
|
60317
60532
|
}
|
|
60318
60533
|
}
|
|
60319
|
-
VersionInfo.version = '1.6.0-alpha.
|
|
60320
|
-
VersionInfo.date = '2025-05-
|
|
60321
|
-
VersionInfo.commit = '
|
|
60534
|
+
VersionInfo.version = '1.6.0-alpha.1409';
|
|
60535
|
+
VersionInfo.date = '2025-05-14T02:06:32.990Z';
|
|
60536
|
+
VersionInfo.commit = 'f91fed13b0a0946b3fa9306b480ddf8044b948e2';
|
|
60322
60537
|
|
|
60323
60538
|
/**
|
|
60324
60539
|
* A factory for custom layout engines.
|