@coderline/alphatab 1.3.0-alpha.200 → 1.3.0-alpha.205
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.d.ts +24 -9
- package/dist/alphaTab.js +270 -166
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +2 -2
- package/dist/alphaTab.mjs +270 -166
- package/package.json +1 -1
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* alphaTab v1.3.0-alpha.
|
|
2
|
+
* alphaTab v1.3.0-alpha.205 (develop, build 205)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2022, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -14443,20 +14443,23 @@
|
|
|
14443
14443
|
this._mainState = new MidiSequencerState();
|
|
14444
14444
|
this._currentState = this._mainState;
|
|
14445
14445
|
}
|
|
14446
|
+
get isPlayingMain() {
|
|
14447
|
+
return this._currentState == this._mainState;
|
|
14448
|
+
}
|
|
14446
14449
|
get isPlayingOneTimeMidi() {
|
|
14447
14450
|
return this._currentState == this._oneTimeState;
|
|
14448
14451
|
}
|
|
14449
14452
|
get isPlayingCountIn() {
|
|
14450
14453
|
return this._currentState == this._countInState;
|
|
14451
14454
|
}
|
|
14452
|
-
get
|
|
14453
|
-
return this.
|
|
14455
|
+
get mainPlaybackRange() {
|
|
14456
|
+
return this._mainState.playbackRange;
|
|
14454
14457
|
}
|
|
14455
|
-
set
|
|
14456
|
-
this.
|
|
14458
|
+
set mainPlaybackRange(value) {
|
|
14459
|
+
this._mainState.playbackRange = value;
|
|
14457
14460
|
if (value) {
|
|
14458
|
-
this.
|
|
14459
|
-
this.
|
|
14461
|
+
this._mainState.playbackRangeStartTime = this.tickPositionToTimePositionWithSpeed(this._mainState, value.startTick, 1);
|
|
14462
|
+
this._mainState.playbackRangeEndTime = this.tickPositionToTimePositionWithSpeed(this._mainState, value.endTick, 1);
|
|
14460
14463
|
}
|
|
14461
14464
|
}
|
|
14462
14465
|
get currentTime() {
|
|
@@ -14465,52 +14468,56 @@
|
|
|
14465
14468
|
/**
|
|
14466
14469
|
* Gets the duration of the song in ticks.
|
|
14467
14470
|
*/
|
|
14468
|
-
get
|
|
14471
|
+
get currentEndTick() {
|
|
14469
14472
|
return this._currentState.endTick;
|
|
14470
14473
|
}
|
|
14471
|
-
get
|
|
14474
|
+
get currentEndTime() {
|
|
14472
14475
|
return this._currentState.endTime / this.playbackSpeed;
|
|
14473
14476
|
}
|
|
14474
|
-
|
|
14477
|
+
mainSeek(timePosition) {
|
|
14475
14478
|
// map to speed=1
|
|
14476
14479
|
timePosition *= this.playbackSpeed;
|
|
14477
14480
|
// ensure playback range
|
|
14478
|
-
if (this.
|
|
14479
|
-
if (timePosition < this.
|
|
14480
|
-
timePosition = this.
|
|
14481
|
+
if (this.mainPlaybackRange) {
|
|
14482
|
+
if (timePosition < this._mainState.playbackRangeStartTime) {
|
|
14483
|
+
timePosition = this._mainState.playbackRangeStartTime;
|
|
14481
14484
|
}
|
|
14482
|
-
else if (timePosition > this.
|
|
14483
|
-
timePosition = this.
|
|
14485
|
+
else if (timePosition > this._mainState.playbackRangeEndTime) {
|
|
14486
|
+
timePosition = this._mainState.playbackRangeEndTime;
|
|
14484
14487
|
}
|
|
14485
14488
|
}
|
|
14486
|
-
if (timePosition > this.
|
|
14487
|
-
this.
|
|
14489
|
+
if (timePosition > this._mainState.currentTime) {
|
|
14490
|
+
this.mainSilentProcess(timePosition - this._mainState.currentTime);
|
|
14488
14491
|
}
|
|
14489
|
-
else if (timePosition < this.
|
|
14492
|
+
else if (timePosition < this._mainState.currentTime) {
|
|
14490
14493
|
// we have to restart the midi to make sure we get the right state: instruments, volume, pan, etc
|
|
14491
|
-
this.
|
|
14492
|
-
this.
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
|
|
14496
|
-
|
|
14497
|
-
|
|
14494
|
+
this._mainState.currentTime = 0;
|
|
14495
|
+
this._mainState.eventIndex = 0;
|
|
14496
|
+
if (this.isPlayingMain) {
|
|
14497
|
+
let metronomeVolume = this._synthesizer.metronomeVolume;
|
|
14498
|
+
this._synthesizer.noteOffAll(true);
|
|
14499
|
+
this._synthesizer.resetSoft();
|
|
14500
|
+
this._synthesizer.setupMetronomeChannel(metronomeVolume);
|
|
14501
|
+
}
|
|
14502
|
+
this.mainSilentProcess(timePosition);
|
|
14498
14503
|
}
|
|
14499
14504
|
}
|
|
14500
|
-
|
|
14505
|
+
mainSilentProcess(milliseconds) {
|
|
14501
14506
|
if (milliseconds <= 0) {
|
|
14502
14507
|
return;
|
|
14503
14508
|
}
|
|
14504
14509
|
let start = Date.now();
|
|
14505
|
-
let finalTime = this.
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
this.
|
|
14510
|
+
let finalTime = this._mainState.currentTime + milliseconds;
|
|
14511
|
+
if (this.isPlayingMain) {
|
|
14512
|
+
while (this._mainState.currentTime < finalTime) {
|
|
14513
|
+
if (this.fillMidiEventQueueLimited(finalTime - this._mainState.currentTime)) {
|
|
14514
|
+
this._synthesizer.synthesizeSilent(SynthConstants.MicroBufferSize);
|
|
14515
|
+
}
|
|
14509
14516
|
}
|
|
14510
14517
|
}
|
|
14511
|
-
this.
|
|
14518
|
+
this._mainState.currentTime = finalTime;
|
|
14512
14519
|
let duration = Date.now() - start;
|
|
14513
|
-
Logger.debug('Sequencer', 'Silent seek finished in ' + duration + 'ms');
|
|
14520
|
+
Logger.debug('Sequencer', 'Silent seek finished in ' + duration + 'ms (main)');
|
|
14514
14521
|
}
|
|
14515
14522
|
loadOneTimeMidi(midiFile) {
|
|
14516
14523
|
this._oneTimeState = this.createStateFromFile(midiFile);
|
|
@@ -14616,18 +14623,21 @@
|
|
|
14616
14623
|
}
|
|
14617
14624
|
return anyEventsDispatched;
|
|
14618
14625
|
}
|
|
14619
|
-
|
|
14620
|
-
return this.tickPositionToTimePositionWithSpeed(tickPosition, this.playbackSpeed);
|
|
14626
|
+
mainTickPositionToTimePosition(tickPosition) {
|
|
14627
|
+
return this.tickPositionToTimePositionWithSpeed(this._mainState, tickPosition, this.playbackSpeed);
|
|
14628
|
+
}
|
|
14629
|
+
mainTimePositionToTickPosition(timePosition) {
|
|
14630
|
+
return this.timePositionToTickPositionWithSpeed(this._mainState, timePosition, this.playbackSpeed);
|
|
14621
14631
|
}
|
|
14622
|
-
|
|
14623
|
-
return this.timePositionToTickPositionWithSpeed(timePosition, this.playbackSpeed);
|
|
14632
|
+
currentTimePositionToTickPosition(timePosition) {
|
|
14633
|
+
return this.timePositionToTickPositionWithSpeed(this._currentState, timePosition, this.playbackSpeed);
|
|
14624
14634
|
}
|
|
14625
|
-
tickPositionToTimePositionWithSpeed(tickPosition, playbackSpeed) {
|
|
14635
|
+
tickPositionToTimePositionWithSpeed(state, tickPosition, playbackSpeed) {
|
|
14626
14636
|
let timePosition = 0.0;
|
|
14627
14637
|
let bpm = 120.0;
|
|
14628
14638
|
let lastChange = 0;
|
|
14629
14639
|
// find start and bpm of last tempo change before time
|
|
14630
|
-
for (const c of
|
|
14640
|
+
for (const c of state.tempoChanges) {
|
|
14631
14641
|
if (tickPosition < c.ticks) {
|
|
14632
14642
|
break;
|
|
14633
14643
|
}
|
|
@@ -14637,16 +14647,16 @@
|
|
|
14637
14647
|
}
|
|
14638
14648
|
// add the missing millis
|
|
14639
14649
|
tickPosition -= lastChange;
|
|
14640
|
-
timePosition += tickPosition * (60000.0 / (bpm *
|
|
14650
|
+
timePosition += tickPosition * (60000.0 / (bpm * state.division));
|
|
14641
14651
|
return timePosition / playbackSpeed;
|
|
14642
14652
|
}
|
|
14643
|
-
timePositionToTickPositionWithSpeed(timePosition, playbackSpeed) {
|
|
14653
|
+
timePositionToTickPositionWithSpeed(state, timePosition, playbackSpeed) {
|
|
14644
14654
|
timePosition *= playbackSpeed;
|
|
14645
14655
|
let ticks = 0;
|
|
14646
14656
|
let bpm = 120.0;
|
|
14647
14657
|
let lastChange = 0;
|
|
14648
14658
|
// find start and bpm of last tempo change before time
|
|
14649
|
-
for (const c of
|
|
14659
|
+
for (const c of state.tempoChanges) {
|
|
14650
14660
|
if (timePosition < c.time) {
|
|
14651
14661
|
break;
|
|
14652
14662
|
}
|
|
@@ -14656,25 +14666,29 @@
|
|
|
14656
14666
|
}
|
|
14657
14667
|
// add the missing ticks
|
|
14658
14668
|
timePosition -= lastChange;
|
|
14659
|
-
ticks += (timePosition / (60000.0 / (bpm *
|
|
14669
|
+
ticks += (timePosition / (60000.0 / (bpm * state.division))) | 0;
|
|
14660
14670
|
// we add 1 for possible rounding errors.(floating point issuses)
|
|
14661
14671
|
return ticks + 1;
|
|
14662
14672
|
}
|
|
14663
14673
|
get internalEndTime() {
|
|
14664
|
-
|
|
14674
|
+
if (this.isPlayingMain) {
|
|
14675
|
+
return !this.mainPlaybackRange ? this._currentState.endTime : this._currentState.playbackRangeEndTime;
|
|
14676
|
+
}
|
|
14677
|
+
else {
|
|
14678
|
+
return this._currentState.endTime;
|
|
14679
|
+
}
|
|
14665
14680
|
}
|
|
14666
14681
|
get isFinished() {
|
|
14667
14682
|
return this._currentState.currentTime >= this.internalEndTime;
|
|
14668
14683
|
}
|
|
14669
14684
|
stop() {
|
|
14670
|
-
if (
|
|
14671
|
-
this._currentState.currentTime =
|
|
14672
|
-
this._currentState.eventIndex = 0;
|
|
14685
|
+
if (this.isPlayingMain && this.mainPlaybackRange) {
|
|
14686
|
+
this._currentState.currentTime = this.mainPlaybackRange.startTick;
|
|
14673
14687
|
}
|
|
14674
|
-
else
|
|
14675
|
-
this._currentState.currentTime =
|
|
14676
|
-
this._currentState.eventIndex = 0;
|
|
14688
|
+
else {
|
|
14689
|
+
this._currentState.currentTime = 0;
|
|
14677
14690
|
}
|
|
14691
|
+
this._currentState.eventIndex = 0;
|
|
14678
14692
|
}
|
|
14679
14693
|
resetOneTimeMidi() {
|
|
14680
14694
|
this._oneTimeState = null;
|
|
@@ -17312,7 +17326,7 @@
|
|
|
17312
17326
|
* Initializes a new instance of the {@link AlphaSynth} class.
|
|
17313
17327
|
* @param output The output to use for playing the generated samples.
|
|
17314
17328
|
*/
|
|
17315
|
-
constructor(output) {
|
|
17329
|
+
constructor(output, bufferTimeInMilliseconds) {
|
|
17316
17330
|
this._isSoundFontLoaded = false;
|
|
17317
17331
|
this._isMidiLoaded = false;
|
|
17318
17332
|
this._tickPosition = 0;
|
|
@@ -17321,6 +17335,7 @@
|
|
|
17321
17335
|
this._countInVolume = 0;
|
|
17322
17336
|
this._playedEventsQueue = new Queue();
|
|
17323
17337
|
this._midiEventsPlayedFilter = new Set();
|
|
17338
|
+
this._notPlayedSamples = 0;
|
|
17324
17339
|
this.isReady = false;
|
|
17325
17340
|
this.state = PlayerState.Paused;
|
|
17326
17341
|
this.ready = new EventEmitter();
|
|
@@ -17348,33 +17363,36 @@
|
|
|
17348
17363
|
this.checkReadyForPlayback();
|
|
17349
17364
|
});
|
|
17350
17365
|
this.output.sampleRequest.on(() => {
|
|
17351
|
-
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
|
|
17355
|
-
|
|
17356
|
-
|
|
17357
|
-
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
|
|
17361
|
-
|
|
17362
|
-
this.
|
|
17363
|
-
|
|
17364
|
-
|
|
17365
|
-
|
|
17366
|
-
|
|
17367
|
-
|
|
17366
|
+
if (!this._sequencer.isFinished) {
|
|
17367
|
+
let samples = new Float32Array(SynthConstants.MicroBufferSize * SynthConstants.MicroBufferCount * SynthConstants.AudioChannels);
|
|
17368
|
+
let bufferPos = 0;
|
|
17369
|
+
for (let i = 0; i < SynthConstants.MicroBufferCount; i++) {
|
|
17370
|
+
// synthesize buffer
|
|
17371
|
+
this._sequencer.fillMidiEventQueue();
|
|
17372
|
+
const synthesizedEvents = this._synthesizer.synthesize(samples, bufferPos, SynthConstants.MicroBufferSize);
|
|
17373
|
+
bufferPos += SynthConstants.MicroBufferSize * SynthConstants.AudioChannels;
|
|
17374
|
+
// push all processed events into the queue
|
|
17375
|
+
// for informing users about played events
|
|
17376
|
+
for (const e of synthesizedEvents) {
|
|
17377
|
+
if (this._midiEventsPlayedFilter.has(e.event.command)) {
|
|
17378
|
+
this._playedEventsQueue.enqueue(e);
|
|
17379
|
+
}
|
|
17380
|
+
}
|
|
17381
|
+
// tell sequencer to check whether its work is done
|
|
17382
|
+
if (this._sequencer.isFinished) {
|
|
17383
|
+
break;
|
|
17384
|
+
}
|
|
17368
17385
|
}
|
|
17386
|
+
// send it to output
|
|
17387
|
+
if (bufferPos < samples.length) {
|
|
17388
|
+
samples = samples.subarray(0, bufferPos);
|
|
17389
|
+
}
|
|
17390
|
+
this._notPlayedSamples += samples.length;
|
|
17391
|
+
this.output.addSamples(samples);
|
|
17369
17392
|
}
|
|
17370
|
-
// send it to output
|
|
17371
|
-
if (bufferPos < samples.length) {
|
|
17372
|
-
samples = samples.subarray(0, bufferPos);
|
|
17373
|
-
}
|
|
17374
|
-
this.output.addSamples(samples);
|
|
17375
17393
|
});
|
|
17376
17394
|
this.output.samplesPlayed.on(this.onSamplesPlayed.bind(this));
|
|
17377
|
-
this.output.open();
|
|
17395
|
+
this.output.open(bufferTimeInMilliseconds);
|
|
17378
17396
|
}
|
|
17379
17397
|
get isReadyForPlayback() {
|
|
17380
17398
|
return this.isReady && this._isSoundFontLoaded && this._isMidiLoaded;
|
|
@@ -17391,7 +17409,6 @@
|
|
|
17391
17409
|
set masterVolume(value) {
|
|
17392
17410
|
value = Math.max(value, SynthConstants.MinVolume);
|
|
17393
17411
|
this._synthesizer.masterVolume = value;
|
|
17394
|
-
this.onAudioSettingsUpdate();
|
|
17395
17412
|
}
|
|
17396
17413
|
get metronomeVolume() {
|
|
17397
17414
|
return this._metronomeVolume;
|
|
@@ -17400,7 +17417,6 @@
|
|
|
17400
17417
|
value = Math.max(value, SynthConstants.MinVolume);
|
|
17401
17418
|
this._metronomeVolume = value;
|
|
17402
17419
|
this._synthesizer.metronomeVolume = value;
|
|
17403
|
-
this.onAudioSettingsUpdate();
|
|
17404
17420
|
}
|
|
17405
17421
|
get countInVolume() {
|
|
17406
17422
|
return this._countInVolume;
|
|
@@ -17428,25 +17444,28 @@
|
|
|
17428
17444
|
return this._tickPosition;
|
|
17429
17445
|
}
|
|
17430
17446
|
set tickPosition(value) {
|
|
17431
|
-
this.timePosition = this._sequencer.
|
|
17447
|
+
this.timePosition = this._sequencer.mainTickPositionToTimePosition(value);
|
|
17432
17448
|
}
|
|
17433
17449
|
get timePosition() {
|
|
17434
17450
|
return this._timePosition;
|
|
17435
17451
|
}
|
|
17436
17452
|
set timePosition(value) {
|
|
17437
|
-
Logger.debug('AlphaSynth', `Seeking to position ${value}ms`);
|
|
17453
|
+
Logger.debug('AlphaSynth', `Seeking to position ${value}ms (main)`);
|
|
17438
17454
|
// tell the sequencer to jump to the given position
|
|
17439
|
-
this._sequencer.
|
|
17455
|
+
this._sequencer.mainSeek(value);
|
|
17440
17456
|
// update the internal position
|
|
17441
17457
|
this.updateTimePosition(value, true);
|
|
17442
17458
|
// tell the output to reset the already synthesized buffers and request data again
|
|
17443
|
-
this.
|
|
17459
|
+
if (this._sequencer.isPlayingMain) {
|
|
17460
|
+
this._notPlayedSamples = 0;
|
|
17461
|
+
this.output.resetSamples();
|
|
17462
|
+
}
|
|
17444
17463
|
}
|
|
17445
17464
|
get playbackRange() {
|
|
17446
|
-
return this._sequencer.
|
|
17465
|
+
return this._sequencer.mainPlaybackRange;
|
|
17447
17466
|
}
|
|
17448
17467
|
set playbackRange(value) {
|
|
17449
|
-
this._sequencer.
|
|
17468
|
+
this._sequencer.mainPlaybackRange = value;
|
|
17450
17469
|
if (value) {
|
|
17451
17470
|
this.tickPosition = value.startTick;
|
|
17452
17471
|
}
|
|
@@ -17479,6 +17498,10 @@
|
|
|
17479
17498
|
return true;
|
|
17480
17499
|
}
|
|
17481
17500
|
playInternal() {
|
|
17501
|
+
if (this._sequencer.isPlayingOneTimeMidi) {
|
|
17502
|
+
Logger.debug('AlphaSynth', 'Cancelling one time midi');
|
|
17503
|
+
this.stopOneTimeMidi();
|
|
17504
|
+
}
|
|
17482
17505
|
Logger.debug('AlphaSynth', 'Starting playback');
|
|
17483
17506
|
this._synthesizer.setupMetronomeChannel(this.metronomeVolume);
|
|
17484
17507
|
this.state = PlayerState.Playing;
|
|
@@ -17509,18 +17532,27 @@
|
|
|
17509
17532
|
Logger.debug('AlphaSynth', 'Stopping playback');
|
|
17510
17533
|
this.state = PlayerState.Paused;
|
|
17511
17534
|
this.output.pause();
|
|
17535
|
+
this._notPlayedSamples = 0;
|
|
17512
17536
|
this._sequencer.stop();
|
|
17513
17537
|
this._synthesizer.noteOffAll(true);
|
|
17514
|
-
this.tickPosition = this._sequencer.
|
|
17538
|
+
this.tickPosition = this._sequencer.mainPlaybackRange ? this._sequencer.mainPlaybackRange.startTick : 0;
|
|
17515
17539
|
this.stateChanged.trigger(new PlayerStateChangedEventArgs(this.state, true));
|
|
17516
17540
|
}
|
|
17517
17541
|
playOneTimeMidiFile(midi) {
|
|
17518
|
-
|
|
17519
|
-
|
|
17542
|
+
if (this._sequencer.isPlayingOneTimeMidi) {
|
|
17543
|
+
this.stopOneTimeMidi();
|
|
17544
|
+
}
|
|
17545
|
+
else {
|
|
17546
|
+
// pause current playback.
|
|
17547
|
+
this.pause();
|
|
17548
|
+
}
|
|
17520
17549
|
this._sequencer.loadOneTimeMidi(midi);
|
|
17521
|
-
this._sequencer.stop();
|
|
17522
17550
|
this._synthesizer.noteOffAll(true);
|
|
17523
|
-
|
|
17551
|
+
// update the internal position
|
|
17552
|
+
this.updateTimePosition(0, true);
|
|
17553
|
+
// tell the output to reset the already synthesized buffers and request data again
|
|
17554
|
+
this._notPlayedSamples = 0;
|
|
17555
|
+
this.output.resetSamples();
|
|
17524
17556
|
this.output.play();
|
|
17525
17557
|
}
|
|
17526
17558
|
resetSoundFonts() {
|
|
@@ -17563,7 +17595,7 @@
|
|
|
17563
17595
|
Logger.debug('AlphaSynth', 'Loading midi from model');
|
|
17564
17596
|
this._sequencer.loadMidi(midi);
|
|
17565
17597
|
this._isMidiLoaded = true;
|
|
17566
|
-
this.midiLoaded.trigger(new PositionChangedEventArgs(0, this._sequencer.
|
|
17598
|
+
this.midiLoaded.trigger(new PositionChangedEventArgs(0, this._sequencer.currentEndTime, 0, this._sequencer.currentEndTick, false));
|
|
17567
17599
|
Logger.debug('AlphaSynth', 'Midi successfully loaded');
|
|
17568
17600
|
this.checkReadyForPlayback();
|
|
17569
17601
|
this.tickPosition = 0;
|
|
@@ -17575,28 +17607,23 @@
|
|
|
17575
17607
|
}
|
|
17576
17608
|
setChannelMute(channel, mute) {
|
|
17577
17609
|
this._synthesizer.channelSetMute(channel, mute);
|
|
17578
|
-
this.onAudioSettingsUpdate();
|
|
17579
17610
|
}
|
|
17580
17611
|
resetChannelStates() {
|
|
17581
17612
|
this._synthesizer.resetChannelStates();
|
|
17582
17613
|
}
|
|
17583
17614
|
setChannelSolo(channel, solo) {
|
|
17584
17615
|
this._synthesizer.channelSetSolo(channel, solo);
|
|
17585
|
-
this.onAudioSettingsUpdate();
|
|
17586
17616
|
}
|
|
17587
17617
|
setChannelVolume(channel, volume) {
|
|
17588
17618
|
volume = Math.max(volume, SynthConstants.MinVolume);
|
|
17589
17619
|
this._synthesizer.channelSetMixVolume(channel, volume);
|
|
17590
|
-
this.onAudioSettingsUpdate();
|
|
17591
|
-
}
|
|
17592
|
-
onAudioSettingsUpdate() {
|
|
17593
|
-
// seeking to the currently known position, will ensure we
|
|
17594
|
-
// clear all audio buffers and re-generate the audio
|
|
17595
|
-
// which was not actually played yet.
|
|
17596
|
-
this.timePosition = this.timePosition;
|
|
17597
17620
|
}
|
|
17598
17621
|
onSamplesPlayed(sampleCount) {
|
|
17622
|
+
if (sampleCount === 0) {
|
|
17623
|
+
return;
|
|
17624
|
+
}
|
|
17599
17625
|
let playedMillis = (sampleCount / this._synthesizer.outSampleRate) * 1000;
|
|
17626
|
+
this._notPlayedSamples -= sampleCount * SynthConstants.AudioChannels;
|
|
17600
17627
|
this.updateTimePosition(this._timePosition + playedMillis, false);
|
|
17601
17628
|
this.checkForFinish();
|
|
17602
17629
|
}
|
|
@@ -17608,22 +17635,24 @@
|
|
|
17608
17635
|
endTick = this.playbackRange.endTick;
|
|
17609
17636
|
}
|
|
17610
17637
|
else {
|
|
17611
|
-
endTick = this._sequencer.
|
|
17638
|
+
endTick = this._sequencer.currentEndTick;
|
|
17612
17639
|
}
|
|
17613
|
-
if (this._tickPosition >= endTick) {
|
|
17614
|
-
|
|
17640
|
+
if (this._tickPosition >= endTick && this._notPlayedSamples <= 0) {
|
|
17641
|
+
this._notPlayedSamples = 0;
|
|
17615
17642
|
if (this._sequencer.isPlayingCountIn) {
|
|
17643
|
+
Logger.debug('AlphaSynth', 'Finished playback (count-in)');
|
|
17616
17644
|
this._sequencer.resetCountIn();
|
|
17617
17645
|
this.timePosition = this._sequencer.currentTime;
|
|
17618
17646
|
this.playInternal();
|
|
17619
17647
|
}
|
|
17620
17648
|
else if (this._sequencer.isPlayingOneTimeMidi) {
|
|
17621
|
-
|
|
17649
|
+
Logger.debug('AlphaSynth', 'Finished playback (one time)');
|
|
17650
|
+
this.output.resetSamples();
|
|
17622
17651
|
this.state = PlayerState.Paused;
|
|
17623
|
-
this.
|
|
17624
|
-
this._synthesizer.noteOffAll(false);
|
|
17652
|
+
this.stopOneTimeMidi();
|
|
17625
17653
|
}
|
|
17626
17654
|
else {
|
|
17655
|
+
Logger.debug('AlphaSynth', 'Finished playback (main)');
|
|
17627
17656
|
this.finished.trigger();
|
|
17628
17657
|
if (this.isLooping) {
|
|
17629
17658
|
this.tickPosition = startTick;
|
|
@@ -17634,16 +17663,27 @@
|
|
|
17634
17663
|
}
|
|
17635
17664
|
}
|
|
17636
17665
|
}
|
|
17666
|
+
stopOneTimeMidi() {
|
|
17667
|
+
this.output.pause();
|
|
17668
|
+
this._synthesizer.noteOffAll(true);
|
|
17669
|
+
this._sequencer.resetOneTimeMidi();
|
|
17670
|
+
this.timePosition = this._sequencer.currentTime;
|
|
17671
|
+
}
|
|
17637
17672
|
updateTimePosition(timePosition, isSeek) {
|
|
17638
17673
|
// update the real positions
|
|
17639
17674
|
const currentTime = timePosition;
|
|
17640
17675
|
this._timePosition = currentTime;
|
|
17641
|
-
const currentTick = this._sequencer.
|
|
17676
|
+
const currentTick = this._sequencer.currentTimePositionToTickPosition(currentTime);
|
|
17642
17677
|
this._tickPosition = currentTick;
|
|
17643
|
-
const endTime = this._sequencer.
|
|
17644
|
-
const endTick = this._sequencer.
|
|
17645
|
-
|
|
17646
|
-
|
|
17678
|
+
const endTime = this._sequencer.currentEndTime;
|
|
17679
|
+
const endTick = this._sequencer.currentEndTick;
|
|
17680
|
+
const mode = this._sequencer.isPlayingMain
|
|
17681
|
+
? 'main'
|
|
17682
|
+
: this._sequencer.isPlayingCountIn
|
|
17683
|
+
? 'count-in'
|
|
17684
|
+
: 'one-time';
|
|
17685
|
+
Logger.debug('AlphaSynth', `Position changed: (time: ${currentTime}/${endTime}, tick: ${currentTick}/${endTick}, Active Voices: ${this._synthesizer.activeVoiceCount} (${mode})`);
|
|
17686
|
+
if (this._sequencer.isPlayingMain) {
|
|
17647
17687
|
this.positionChanged.trigger(new PositionChangedEventArgs(currentTime, endTime, currentTick, endTick, isSeek));
|
|
17648
17688
|
}
|
|
17649
17689
|
// build events which were actually played
|
|
@@ -18620,6 +18660,12 @@
|
|
|
18620
18660
|
* Gets or sets whether the triplet feel should be applied/played during audio playback.
|
|
18621
18661
|
*/
|
|
18622
18662
|
this.playTripletFeel = true;
|
|
18663
|
+
/**
|
|
18664
|
+
* Gets or sets how many milliseconds of audio samples should be buffered in total.
|
|
18665
|
+
* Larger buffers cause a delay from when audio settings like volumes will be applied.
|
|
18666
|
+
* Smaller buffers can cause audio crackling due to constant buffering that is happening.
|
|
18667
|
+
*/
|
|
18668
|
+
this.bufferTimeInMilliseconds = 500;
|
|
18623
18669
|
}
|
|
18624
18670
|
}
|
|
18625
18671
|
|
|
@@ -19076,6 +19122,7 @@
|
|
|
19076
19122
|
o.set("vibrato", VibratoPlaybackSettingsSerializer.toJson(obj.vibrato));
|
|
19077
19123
|
o.set("slide", SlidePlaybackSettingsSerializer.toJson(obj.slide));
|
|
19078
19124
|
o.set("playtripletfeel", obj.playTripletFeel);
|
|
19125
|
+
o.set("buffertimeinmilliseconds", obj.bufferTimeInMilliseconds);
|
|
19079
19126
|
return o;
|
|
19080
19127
|
}
|
|
19081
19128
|
static setProperty(obj, property, v) {
|
|
@@ -19127,6 +19174,9 @@
|
|
|
19127
19174
|
case "playtripletfeel":
|
|
19128
19175
|
obj.playTripletFeel = v;
|
|
19129
19176
|
return true;
|
|
19177
|
+
case "buffertimeinmilliseconds":
|
|
19178
|
+
obj.bufferTimeInMilliseconds = v;
|
|
19179
|
+
return true;
|
|
19130
19180
|
}
|
|
19131
19181
|
if (["vibrato"].indexOf(property) >= 0) {
|
|
19132
19182
|
VibratoPlaybackSettingsSerializer.fromJson(obj.vibrato, v);
|
|
@@ -20714,10 +20764,10 @@
|
|
|
20714
20764
|
* @target web
|
|
20715
20765
|
*/
|
|
20716
20766
|
class AlphaSynthWebWorker {
|
|
20717
|
-
constructor(main) {
|
|
20767
|
+
constructor(main, bufferTimeInMilliseconds) {
|
|
20718
20768
|
this._main = main;
|
|
20719
20769
|
this._main.addEventListener('message', this.handleMessage.bind(this));
|
|
20720
|
-
this._player = new AlphaSynth(new AlphaSynthWorkerSynthOutput());
|
|
20770
|
+
this._player = new AlphaSynth(new AlphaSynthWorkerSynthOutput(), bufferTimeInMilliseconds);
|
|
20721
20771
|
this._player.positionChanged.on(this.onPositionChanged.bind(this));
|
|
20722
20772
|
this._player.stateChanged.on(this.onPlayerStateChanged.bind(this));
|
|
20723
20773
|
this._player.finished.on(this.onFinished.bind(this));
|
|
@@ -20742,7 +20792,7 @@
|
|
|
20742
20792
|
case 'alphaSynth.initialize':
|
|
20743
20793
|
AlphaSynthWorkerSynthOutput.preferredSampleRate = data.sampleRate;
|
|
20744
20794
|
Logger.logLevel = data.logLevel;
|
|
20745
|
-
Environment.globalThis.alphaSynthWebWorker = new AlphaSynthWebWorker(main);
|
|
20795
|
+
Environment.globalThis.alphaSynthWebWorker = new AlphaSynthWebWorker(main, data.bufferTimeInMilliseconds);
|
|
20746
20796
|
break;
|
|
20747
20797
|
}
|
|
20748
20798
|
});
|
|
@@ -21028,11 +21078,11 @@
|
|
|
21028
21078
|
/**
|
|
21029
21079
|
* Gets or sets the index of the first masterbar that was rendered in this result.
|
|
21030
21080
|
*/
|
|
21031
|
-
this.firstMasterBarIndex =
|
|
21081
|
+
this.firstMasterBarIndex = -1;
|
|
21032
21082
|
/**
|
|
21033
21083
|
* Gets or sets the index of the last masterbar that was rendered in this result.
|
|
21034
21084
|
*/
|
|
21035
|
-
this.lastMasterBarIndex =
|
|
21085
|
+
this.lastMasterBarIndex = -1;
|
|
21036
21086
|
/**
|
|
21037
21087
|
* Gets or sets the render engine specific result object which contains the rendered music sheet.
|
|
21038
21088
|
*/
|
|
@@ -21393,14 +21443,6 @@
|
|
|
21393
21443
|
}
|
|
21394
21444
|
this.isFinished = true;
|
|
21395
21445
|
}
|
|
21396
|
-
/**
|
|
21397
|
-
* Adds a new note to the lookup.
|
|
21398
|
-
* @param bounds The note bounds to add.
|
|
21399
|
-
*/
|
|
21400
|
-
addNote(bounds) {
|
|
21401
|
-
let beat = this.findBeat(bounds.note.beat);
|
|
21402
|
-
beat.addNote(bounds);
|
|
21403
|
-
}
|
|
21404
21446
|
/**
|
|
21405
21447
|
* Adds a new stave group to the lookup.
|
|
21406
21448
|
* @param bounds The stave group bounds to add.
|
|
@@ -21430,7 +21472,11 @@
|
|
|
21430
21472
|
* @param bounds The beat bounds to add.
|
|
21431
21473
|
*/
|
|
21432
21474
|
addBeat(bounds) {
|
|
21433
|
-
|
|
21475
|
+
var _a;
|
|
21476
|
+
if (!this._beatLookup.has(bounds.beat.id)) {
|
|
21477
|
+
this._beatLookup.set(bounds.beat.id, []);
|
|
21478
|
+
}
|
|
21479
|
+
(_a = this._beatLookup.get(bounds.beat.id)) === null || _a === void 0 ? void 0 : _a.push(bounds);
|
|
21434
21480
|
}
|
|
21435
21481
|
/**
|
|
21436
21482
|
* Tries to find the master bar bounds by a given index.
|
|
@@ -21461,6 +21507,15 @@
|
|
|
21461
21507
|
* @returns The beat bounds if it was rendered, or null if no boundary information is available.
|
|
21462
21508
|
*/
|
|
21463
21509
|
findBeat(beat) {
|
|
21510
|
+
const all = this.findBeats(beat);
|
|
21511
|
+
return all ? all[0] : null;
|
|
21512
|
+
}
|
|
21513
|
+
/**
|
|
21514
|
+
* Tries to find the bounds of a given beat.
|
|
21515
|
+
* @param beat The beat to find.
|
|
21516
|
+
* @returns The beat bounds if it was rendered, or null if no boundary information is available.
|
|
21517
|
+
*/
|
|
21518
|
+
findBeats(beat) {
|
|
21464
21519
|
let id = beat.id;
|
|
21465
21520
|
if (this._beatLookup.has(id)) {
|
|
21466
21521
|
return this._beatLookup.get(id);
|
|
@@ -21517,11 +21572,16 @@
|
|
|
21517
21572
|
* @returns The note at the given position within the beat.
|
|
21518
21573
|
*/
|
|
21519
21574
|
getNoteAtPos(beat, x, y) {
|
|
21520
|
-
|
|
21521
|
-
if (
|
|
21522
|
-
|
|
21575
|
+
const beatBounds = this.findBeats(beat);
|
|
21576
|
+
if (beatBounds) {
|
|
21577
|
+
for (const b of beatBounds) {
|
|
21578
|
+
const note = b.findNoteAtPos(x, y);
|
|
21579
|
+
if (note) {
|
|
21580
|
+
return note;
|
|
21581
|
+
}
|
|
21582
|
+
}
|
|
21523
21583
|
}
|
|
21524
|
-
return
|
|
21584
|
+
return null;
|
|
21525
21585
|
}
|
|
21526
21586
|
}
|
|
21527
21587
|
|
|
@@ -23627,7 +23687,7 @@
|
|
|
23627
23687
|
}
|
|
23628
23688
|
generateSingleNote(note) {
|
|
23629
23689
|
this.prepareSingleBeat(note.beat);
|
|
23630
|
-
this.generateNote(note,
|
|
23690
|
+
this.generateNote(note, 0, note.beat.playbackDuration, new Int32Array(note.beat.voice.bar.staff.tuning.length));
|
|
23631
23691
|
}
|
|
23632
23692
|
}
|
|
23633
23693
|
MidiFileGenerator.DefaultDurationDead = 30;
|
|
@@ -24079,11 +24139,15 @@
|
|
|
24079
24139
|
this._lastScroll = 0;
|
|
24080
24140
|
this.playedBeatChanged = new EventEmitterOfT();
|
|
24081
24141
|
this._beatMouseDown = false;
|
|
24142
|
+
this._noteMouseDown = false;
|
|
24082
24143
|
this._selectionStart = null;
|
|
24083
24144
|
this._selectionEnd = null;
|
|
24084
24145
|
this.beatMouseDown = new EventEmitterOfT();
|
|
24085
24146
|
this.beatMouseMove = new EventEmitterOfT();
|
|
24086
24147
|
this.beatMouseUp = new EventEmitterOfT();
|
|
24148
|
+
this.noteMouseDown = new EventEmitterOfT();
|
|
24149
|
+
this.noteMouseMove = new EventEmitterOfT();
|
|
24150
|
+
this.noteMouseUp = new EventEmitterOfT();
|
|
24087
24151
|
this.scoreLoaded = new EventEmitterOfT();
|
|
24088
24152
|
this.resize = new EventEmitterOfT();
|
|
24089
24153
|
this.renderStarted = new EventEmitterOfT();
|
|
@@ -24684,7 +24748,6 @@
|
|
|
24684
24748
|
this._playerState = PlayerState.Paused;
|
|
24685
24749
|
// we need to update our position caches if we render a tablature
|
|
24686
24750
|
this.renderer.postRenderFinished.on(() => {
|
|
24687
|
-
debugger;
|
|
24688
24751
|
this.cursorUpdateTick(this._previousTick, false, this._previousTick > 10);
|
|
24689
24752
|
});
|
|
24690
24753
|
if (this.player) {
|
|
@@ -24899,6 +24962,14 @@
|
|
|
24899
24962
|
this.beatMouseDown.trigger(beat);
|
|
24900
24963
|
this.uiFacade.triggerEvent(this.container, 'beatMouseDown', beat, originalEvent);
|
|
24901
24964
|
}
|
|
24965
|
+
onNoteMouseDown(originalEvent, note) {
|
|
24966
|
+
if (this._isDestroyed) {
|
|
24967
|
+
return;
|
|
24968
|
+
}
|
|
24969
|
+
this._noteMouseDown = true;
|
|
24970
|
+
this.noteMouseDown.trigger(note);
|
|
24971
|
+
this.uiFacade.triggerEvent(this.container, 'noteMouseDown', note, originalEvent);
|
|
24972
|
+
}
|
|
24902
24973
|
onBeatMouseMove(originalEvent, beat) {
|
|
24903
24974
|
if (this._isDestroyed) {
|
|
24904
24975
|
return;
|
|
@@ -24912,6 +24983,13 @@
|
|
|
24912
24983
|
this.beatMouseMove.trigger(beat);
|
|
24913
24984
|
this.uiFacade.triggerEvent(this.container, 'beatMouseMove', beat, originalEvent);
|
|
24914
24985
|
}
|
|
24986
|
+
onNoteMouseMove(originalEvent, note) {
|
|
24987
|
+
if (this._isDestroyed) {
|
|
24988
|
+
return;
|
|
24989
|
+
}
|
|
24990
|
+
this.noteMouseMove.trigger(note);
|
|
24991
|
+
this.uiFacade.triggerEvent(this.container, 'noteMouseMove', note, originalEvent);
|
|
24992
|
+
}
|
|
24915
24993
|
onBeatMouseUp(originalEvent, beat) {
|
|
24916
24994
|
if (this._isDestroyed) {
|
|
24917
24995
|
return;
|
|
@@ -24960,6 +25038,14 @@
|
|
|
24960
25038
|
this.uiFacade.triggerEvent(this.container, 'beatMouseUp', beat, originalEvent);
|
|
24961
25039
|
this._beatMouseDown = false;
|
|
24962
25040
|
}
|
|
25041
|
+
onNoteMouseUp(originalEvent, note) {
|
|
25042
|
+
if (this._isDestroyed) {
|
|
25043
|
+
return;
|
|
25044
|
+
}
|
|
25045
|
+
this.noteMouseUp.trigger(note);
|
|
25046
|
+
this.uiFacade.triggerEvent(this.container, 'noteMouseUp', note, originalEvent);
|
|
25047
|
+
this._noteMouseDown = false;
|
|
25048
|
+
}
|
|
24963
25049
|
updateSelectionCursor(range) {
|
|
24964
25050
|
if (!this._tickCache) {
|
|
24965
25051
|
return;
|
|
@@ -24979,7 +25065,7 @@
|
|
|
24979
25065
|
}
|
|
24980
25066
|
setupClickHandling() {
|
|
24981
25067
|
this.canvasElement.mouseDown.on(e => {
|
|
24982
|
-
var _a, _b;
|
|
25068
|
+
var _a, _b, _c;
|
|
24983
25069
|
if (!e.isLeftMouseButton) {
|
|
24984
25070
|
return;
|
|
24985
25071
|
}
|
|
@@ -24991,10 +25077,16 @@
|
|
|
24991
25077
|
let beat = (_b = (_a = this.renderer.boundsLookup) === null || _a === void 0 ? void 0 : _a.getBeatAtPos(relX, relY)) !== null && _b !== void 0 ? _b : null;
|
|
24992
25078
|
if (beat) {
|
|
24993
25079
|
this.onBeatMouseDown(e, beat);
|
|
25080
|
+
if (this.settings.core.includeNoteBounds) {
|
|
25081
|
+
const note = (_c = this.renderer.boundsLookup) === null || _c === void 0 ? void 0 : _c.getNoteAtPos(beat, relX, relY);
|
|
25082
|
+
if (note) {
|
|
25083
|
+
this.onNoteMouseDown(e, note);
|
|
25084
|
+
}
|
|
25085
|
+
}
|
|
24994
25086
|
}
|
|
24995
25087
|
});
|
|
24996
25088
|
this.canvasElement.mouseMove.on(e => {
|
|
24997
|
-
var _a, _b;
|
|
25089
|
+
var _a, _b, _c;
|
|
24998
25090
|
if (!this._beatMouseDown) {
|
|
24999
25091
|
return;
|
|
25000
25092
|
}
|
|
@@ -25003,10 +25095,16 @@
|
|
|
25003
25095
|
let beat = (_b = (_a = this.renderer.boundsLookup) === null || _a === void 0 ? void 0 : _a.getBeatAtPos(relX, relY)) !== null && _b !== void 0 ? _b : null;
|
|
25004
25096
|
if (beat) {
|
|
25005
25097
|
this.onBeatMouseMove(e, beat);
|
|
25098
|
+
if (this._noteMouseDown) {
|
|
25099
|
+
const note = (_c = this.renderer.boundsLookup) === null || _c === void 0 ? void 0 : _c.getNoteAtPos(beat, relX, relY);
|
|
25100
|
+
if (note) {
|
|
25101
|
+
this.onNoteMouseMove(e, note);
|
|
25102
|
+
}
|
|
25103
|
+
}
|
|
25006
25104
|
}
|
|
25007
25105
|
});
|
|
25008
25106
|
this.canvasElement.mouseUp.on(e => {
|
|
25009
|
-
var _a, _b;
|
|
25107
|
+
var _a, _b, _c, _d;
|
|
25010
25108
|
if (!this._beatMouseDown) {
|
|
25011
25109
|
return;
|
|
25012
25110
|
}
|
|
@@ -25017,6 +25115,15 @@
|
|
|
25017
25115
|
let relY = e.getY(this.canvasElement);
|
|
25018
25116
|
let beat = (_b = (_a = this.renderer.boundsLookup) === null || _a === void 0 ? void 0 : _a.getBeatAtPos(relX, relY)) !== null && _b !== void 0 ? _b : null;
|
|
25019
25117
|
this.onBeatMouseUp(e, beat);
|
|
25118
|
+
if (this._noteMouseDown) {
|
|
25119
|
+
if (beat) {
|
|
25120
|
+
const note = (_d = (_c = this.renderer.boundsLookup) === null || _c === void 0 ? void 0 : _c.getNoteAtPos(beat, relX, relY)) !== null && _d !== void 0 ? _d : null;
|
|
25121
|
+
this.onNoteMouseUp(e, note);
|
|
25122
|
+
}
|
|
25123
|
+
else {
|
|
25124
|
+
this.onNoteMouseUp(e, null);
|
|
25125
|
+
}
|
|
25126
|
+
}
|
|
25020
25127
|
});
|
|
25021
25128
|
this.renderer.postRenderFinished.on(() => {
|
|
25022
25129
|
if (!this._selectionStart ||
|
|
@@ -25650,7 +25757,7 @@
|
|
|
25650
25757
|
}
|
|
25651
25758
|
throw new AlphaTabError(exports.AlphaTabErrorType.General, 'AudioContext not found');
|
|
25652
25759
|
}
|
|
25653
|
-
open() {
|
|
25760
|
+
open(bufferTimeInMilliseconds) {
|
|
25654
25761
|
this.patchIosSampleRate();
|
|
25655
25762
|
this._context = this.createAudioContext();
|
|
25656
25763
|
let ctx = this._context;
|
|
@@ -25708,8 +25815,7 @@
|
|
|
25708
25815
|
}
|
|
25709
25816
|
}
|
|
25710
25817
|
AlphaSynthWebAudioOutputBase.BufferSize = 4096;
|
|
25711
|
-
AlphaSynthWebAudioOutputBase.PreferredSampleRate = 44100;
|
|
25712
|
-
AlphaSynthWebAudioOutputBase.TotalBufferTimeInMilliseconds = 5000;
|
|
25818
|
+
AlphaSynthWebAudioOutputBase.PreferredSampleRate = 44100;
|
|
25713
25819
|
|
|
25714
25820
|
// tslint:disable: deprecation
|
|
25715
25821
|
/**
|
|
@@ -25725,11 +25831,9 @@
|
|
|
25725
25831
|
this._requestedBufferCount = 0;
|
|
25726
25832
|
this._outputBuffer = new Float32Array(0);
|
|
25727
25833
|
}
|
|
25728
|
-
open() {
|
|
25729
|
-
super.open();
|
|
25730
|
-
this._bufferCount = Math.floor((
|
|
25731
|
-
1000 /
|
|
25732
|
-
AlphaSynthWebAudioOutputBase.BufferSize);
|
|
25834
|
+
open(bufferTimeInMilliseconds) {
|
|
25835
|
+
super.open(bufferTimeInMilliseconds);
|
|
25836
|
+
this._bufferCount = Math.floor((bufferTimeInMilliseconds * this.sampleRate) / 1000 / AlphaSynthWebAudioOutputBase.BufferSize);
|
|
25733
25837
|
this._circularBuffer = new CircularSampleBuffer(AlphaSynthWebAudioOutputBase.BufferSize * this._bufferCount);
|
|
25734
25838
|
this.onReady();
|
|
25735
25839
|
}
|
|
@@ -25787,13 +25891,13 @@
|
|
|
25787
25891
|
buffer = new Float32Array(samples);
|
|
25788
25892
|
this._outputBuffer = buffer;
|
|
25789
25893
|
}
|
|
25790
|
-
this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
|
|
25894
|
+
const samplesFromBuffer = this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
|
|
25791
25895
|
let s = 0;
|
|
25792
25896
|
for (let i = 0; i < left.length; i++) {
|
|
25793
25897
|
left[i] = buffer[s++];
|
|
25794
25898
|
right[i] = buffer[s++];
|
|
25795
25899
|
}
|
|
25796
|
-
this.onSamplesPlayed(
|
|
25900
|
+
this.onSamplesPlayed(samplesFromBuffer / SynthConstants.AudioChannels);
|
|
25797
25901
|
this.requestBuffers();
|
|
25798
25902
|
}
|
|
25799
25903
|
}
|
|
@@ -25818,7 +25922,7 @@
|
|
|
25818
25922
|
* @target web
|
|
25819
25923
|
*/
|
|
25820
25924
|
class AlphaSynthWebWorkerApi {
|
|
25821
|
-
constructor(player, alphaSynthScriptFile, logLevel) {
|
|
25925
|
+
constructor(player, alphaSynthScriptFile, logLevel, bufferTimeInMilliseconds) {
|
|
25822
25926
|
this._workerIsReadyForPlayback = false;
|
|
25823
25927
|
this._workerIsReady = false;
|
|
25824
25928
|
this._outputIsReady = false;
|
|
@@ -25858,7 +25962,7 @@
|
|
|
25858
25962
|
this._output.ready.on(this.onOutputReady.bind(this));
|
|
25859
25963
|
this._output.samplesPlayed.on(this.onOutputSamplesPlayed.bind(this));
|
|
25860
25964
|
this._output.sampleRequest.on(this.onOutputSampleRequest.bind(this));
|
|
25861
|
-
this._output.open();
|
|
25965
|
+
this._output.open(bufferTimeInMilliseconds);
|
|
25862
25966
|
try {
|
|
25863
25967
|
this._synth = Environment.createAlphaTabWorker(alphaSynthScriptFile);
|
|
25864
25968
|
}
|
|
@@ -25876,7 +25980,8 @@
|
|
|
25876
25980
|
this._synth.postMessage({
|
|
25877
25981
|
cmd: 'alphaSynth.initialize',
|
|
25878
25982
|
sampleRate: this._output.sampleRate,
|
|
25879
|
-
logLevel: logLevel
|
|
25983
|
+
logLevel: logLevel,
|
|
25984
|
+
bufferTimeInMilliseconds: bufferTimeInMilliseconds
|
|
25880
25985
|
});
|
|
25881
25986
|
this.masterVolume = 1;
|
|
25882
25987
|
this.playbackSpeed = 1;
|
|
@@ -26360,14 +26465,13 @@
|
|
|
26360
26465
|
}
|
|
26361
26466
|
AlphaSynthWebWorklet._isRegistered = true;
|
|
26362
26467
|
registerProcessor('alphatab', (_a = class AlphaSynthWebWorkletProcessor extends AudioWorkletProcessor {
|
|
26363
|
-
constructor(
|
|
26364
|
-
super(
|
|
26468
|
+
constructor(options) {
|
|
26469
|
+
super(options);
|
|
26365
26470
|
this._outputBuffer = new Float32Array(0);
|
|
26366
26471
|
this._bufferCount = 0;
|
|
26367
26472
|
this._requestedBufferCount = 0;
|
|
26368
|
-
Logger.
|
|
26369
|
-
this._bufferCount = Math.floor((
|
|
26370
|
-
sampleRate) /
|
|
26473
|
+
Logger.debug('WebAudio', 'creating processor');
|
|
26474
|
+
this._bufferCount = Math.floor((options.processorOptions.bufferTimeInMilliseconds * sampleRate) /
|
|
26371
26475
|
1000 /
|
|
26372
26476
|
AlphaSynthWebWorkletProcessor.BufferSize);
|
|
26373
26477
|
this._circularBuffer = new CircularSampleBuffer(AlphaSynthWebWorkletProcessor.BufferSize * this._bufferCount);
|
|
@@ -26402,7 +26506,7 @@
|
|
|
26402
26506
|
buffer = new Float32Array(samples);
|
|
26403
26507
|
this._outputBuffer = buffer;
|
|
26404
26508
|
}
|
|
26405
|
-
this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
|
|
26509
|
+
const samplesFromBuffer = this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
|
|
26406
26510
|
let s = 0;
|
|
26407
26511
|
for (let i = 0; i < left.length; i++) {
|
|
26408
26512
|
left[i] = buffer[s++];
|
|
@@ -26410,7 +26514,7 @@
|
|
|
26410
26514
|
}
|
|
26411
26515
|
this.port.postMessage({
|
|
26412
26516
|
cmd: AlphaSynthWorkerSynthOutput.CmdOutputSamplesPlayed,
|
|
26413
|
-
samples:
|
|
26517
|
+
samples: samplesFromBuffer / SynthConstants.AudioChannels
|
|
26414
26518
|
});
|
|
26415
26519
|
this.requestBuffers();
|
|
26416
26520
|
return true;
|
|
@@ -26436,7 +26540,6 @@
|
|
|
26436
26540
|
}
|
|
26437
26541
|
},
|
|
26438
26542
|
_a.BufferSize = 4096,
|
|
26439
|
-
_a.TotalBufferTimeInMilliseconds = 5000,
|
|
26440
26543
|
_a));
|
|
26441
26544
|
}
|
|
26442
26545
|
}
|
|
@@ -26450,9 +26553,11 @@
|
|
|
26450
26553
|
constructor() {
|
|
26451
26554
|
super(...arguments);
|
|
26452
26555
|
this._worklet = null;
|
|
26556
|
+
this._bufferTimeInMilliseconds = 0;
|
|
26453
26557
|
}
|
|
26454
|
-
open() {
|
|
26455
|
-
super.open();
|
|
26558
|
+
open(bufferTimeInMilliseconds) {
|
|
26559
|
+
super.open(bufferTimeInMilliseconds);
|
|
26560
|
+
this._bufferTimeInMilliseconds = bufferTimeInMilliseconds;
|
|
26456
26561
|
this.onReady();
|
|
26457
26562
|
}
|
|
26458
26563
|
play() {
|
|
@@ -26462,7 +26567,10 @@
|
|
|
26462
26567
|
ctx.audioWorklet.addModule(Environment.scriptFile).then(() => {
|
|
26463
26568
|
this._worklet = new AudioWorkletNode(ctx, 'alphatab', {
|
|
26464
26569
|
numberOfOutputs: 1,
|
|
26465
|
-
outputChannelCount: [2]
|
|
26570
|
+
outputChannelCount: [2],
|
|
26571
|
+
processorOptions: {
|
|
26572
|
+
bufferTimeInMilliseconds: this._bufferTimeInMilliseconds
|
|
26573
|
+
}
|
|
26466
26574
|
});
|
|
26467
26575
|
this._worklet.port.onmessage = this.handleMessage.bind(this);
|
|
26468
26576
|
this._source.connect(this._worklet);
|
|
@@ -26908,7 +27016,9 @@
|
|
|
26908
27016
|
// remember which bar is contained in which node for faster lookup
|
|
26909
27017
|
// on highlight/unhighlight
|
|
26910
27018
|
for (let i = renderResult.firstMasterBarIndex; i <= renderResult.lastMasterBarIndex; i++) {
|
|
26911
|
-
|
|
27019
|
+
if (i >= 0) {
|
|
27020
|
+
this._barToElementLookup.set(i, placeholder);
|
|
27021
|
+
}
|
|
26912
27022
|
}
|
|
26913
27023
|
if (this._api.settings.core.enableLazyLoading) {
|
|
26914
27024
|
// re-observe to fire event
|
|
@@ -26935,11 +27045,11 @@
|
|
|
26935
27045
|
let supportsAudioWorklets = window.isSecureContext && 'AudioWorkletNode' in window && !Environment.isWebPackBundled;
|
|
26936
27046
|
if (supportsAudioWorklets) {
|
|
26937
27047
|
Logger.debug('Player', 'Will use webworkers for synthesizing and web audio api with worklets for playback');
|
|
26938
|
-
player = new AlphaSynthWebWorkerApi(new AlphaSynthAudioWorkletOutput(), alphaSynthScriptFile, this._api.settings.core.logLevel);
|
|
27048
|
+
player = new AlphaSynthWebWorkerApi(new AlphaSynthAudioWorkletOutput(), alphaSynthScriptFile, this._api.settings.core.logLevel, this._api.settings.player.bufferTimeInMilliseconds);
|
|
26939
27049
|
}
|
|
26940
27050
|
else if (supportsScriptProcessor) {
|
|
26941
27051
|
Logger.debug('Player', 'Will use webworkers for synthesizing and web audio api for playback');
|
|
26942
|
-
player = new AlphaSynthWebWorkerApi(new AlphaSynthScriptProcessorOutput(), alphaSynthScriptFile, this._api.settings.core.logLevel);
|
|
27052
|
+
player = new AlphaSynthWebWorkerApi(new AlphaSynthScriptProcessorOutput(), alphaSynthScriptFile, this._api.settings.core.logLevel, this._api.settings.player.bufferTimeInMilliseconds);
|
|
26943
27053
|
}
|
|
26944
27054
|
if (!player) {
|
|
26945
27055
|
Logger.error('Player', 'Player requires webworkers and web audio api, browser unsupported', null);
|
|
@@ -32872,8 +32982,6 @@
|
|
|
32872
32982
|
e.height = tuningHeight;
|
|
32873
32983
|
e.totalWidth = this.width;
|
|
32874
32984
|
e.totalHeight = totalHeight < 0 ? y + e.height : totalHeight;
|
|
32875
|
-
e.firstMasterBarIndex = -1;
|
|
32876
|
-
e.lastMasterBarIndex = -1;
|
|
32877
32985
|
this.registerPartial(e, (canvas) => {
|
|
32878
32986
|
canvas.color = res.scoreInfoColor;
|
|
32879
32987
|
canvas.textAlign = TextAlign.Center;
|
|
@@ -32896,8 +33004,6 @@
|
|
|
32896
33004
|
e.height = diagramHeight;
|
|
32897
33005
|
e.totalWidth = this.width;
|
|
32898
33006
|
e.totalHeight = totalHeight < 0 ? y + diagramHeight : totalHeight;
|
|
32899
|
-
e.firstMasterBarIndex = -1;
|
|
32900
|
-
e.lastMasterBarIndex = -1;
|
|
32901
33007
|
this.registerPartial(e, (canvas) => {
|
|
32902
33008
|
canvas.color = res.scoreInfoColor;
|
|
32903
33009
|
canvas.textAlign = TextAlign.Center;
|
|
@@ -32955,8 +33061,6 @@
|
|
|
32955
33061
|
e.height = infoHeight;
|
|
32956
33062
|
e.totalWidth = this.width;
|
|
32957
33063
|
e.totalHeight = totalHeight < 0 ? y + e.height : totalHeight;
|
|
32958
|
-
e.firstMasterBarIndex = -1;
|
|
32959
|
-
e.lastMasterBarIndex = -1;
|
|
32960
33064
|
this.registerPartial(e, (canvas) => {
|
|
32961
33065
|
canvas.color = res.scoreInfoColor;
|
|
32962
33066
|
canvas.textAlign = TextAlign.Center;
|
|
@@ -37821,7 +37925,7 @@
|
|
|
37821
37925
|
noteBounds.noteHeadBounds.y = cy + this.y - this.height / 2;
|
|
37822
37926
|
noteBounds.noteHeadBounds.w = this.width;
|
|
37823
37927
|
noteBounds.noteHeadBounds.h = this.height;
|
|
37824
|
-
|
|
37928
|
+
beatBounds.addNote(noteBounds);
|
|
37825
37929
|
}
|
|
37826
37930
|
}
|
|
37827
37931
|
|
|
@@ -40684,8 +40788,8 @@
|
|
|
40684
40788
|
// </auto-generated>
|
|
40685
40789
|
class VersionInfo {
|
|
40686
40790
|
}
|
|
40687
|
-
VersionInfo.version = '1.3.0-alpha.
|
|
40688
|
-
VersionInfo.date = '2022-03-
|
|
40791
|
+
VersionInfo.version = '1.3.0-alpha.205';
|
|
40792
|
+
VersionInfo.date = '2022-03-13T00:34:39.940Z';
|
|
40689
40793
|
|
|
40690
40794
|
var index$5 = /*#__PURE__*/Object.freeze({
|
|
40691
40795
|
__proto__: null,
|