@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * alphaTab v1.3.0-alpha.200 (develop, build 200)
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 playbackRange() {
14453
- return this._currentState.playbackRange;
14455
+ get mainPlaybackRange() {
14456
+ return this._mainState.playbackRange;
14454
14457
  }
14455
- set playbackRange(value) {
14456
- this._currentState.playbackRange = value;
14458
+ set mainPlaybackRange(value) {
14459
+ this._mainState.playbackRange = value;
14457
14460
  if (value) {
14458
- this._currentState.playbackRangeStartTime = this.tickPositionToTimePositionWithSpeed(value.startTick, 1);
14459
- this._currentState.playbackRangeEndTime = this.tickPositionToTimePositionWithSpeed(value.endTick, 1);
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 endTick() {
14471
+ get currentEndTick() {
14469
14472
  return this._currentState.endTick;
14470
14473
  }
14471
- get endTime() {
14474
+ get currentEndTime() {
14472
14475
  return this._currentState.endTime / this.playbackSpeed;
14473
14476
  }
14474
- seek(timePosition) {
14477
+ mainSeek(timePosition) {
14475
14478
  // map to speed=1
14476
14479
  timePosition *= this.playbackSpeed;
14477
14480
  // ensure playback range
14478
- if (this.playbackRange) {
14479
- if (timePosition < this._currentState.playbackRangeStartTime) {
14480
- timePosition = this._currentState.playbackRangeStartTime;
14481
+ if (this.mainPlaybackRange) {
14482
+ if (timePosition < this._mainState.playbackRangeStartTime) {
14483
+ timePosition = this._mainState.playbackRangeStartTime;
14481
14484
  }
14482
- else if (timePosition > this._currentState.playbackRangeEndTime) {
14483
- timePosition = this._currentState.playbackRangeEndTime;
14485
+ else if (timePosition > this._mainState.playbackRangeEndTime) {
14486
+ timePosition = this._mainState.playbackRangeEndTime;
14484
14487
  }
14485
14488
  }
14486
- if (timePosition > this._currentState.currentTime) {
14487
- this.silentProcess(timePosition - this._currentState.currentTime);
14489
+ if (timePosition > this._mainState.currentTime) {
14490
+ this.mainSilentProcess(timePosition - this._mainState.currentTime);
14488
14491
  }
14489
- else if (timePosition < this._currentState.currentTime) {
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._currentState.currentTime = 0;
14492
- this._currentState.eventIndex = 0;
14493
- let metronomeVolume = this._synthesizer.metronomeVolume;
14494
- this._synthesizer.noteOffAll(true);
14495
- this._synthesizer.resetSoft();
14496
- this._synthesizer.setupMetronomeChannel(metronomeVolume);
14497
- this.silentProcess(timePosition);
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
- silentProcess(milliseconds) {
14505
+ mainSilentProcess(milliseconds) {
14501
14506
  if (milliseconds <= 0) {
14502
14507
  return;
14503
14508
  }
14504
14509
  let start = Date.now();
14505
- let finalTime = this._currentState.currentTime + milliseconds;
14506
- while (this._currentState.currentTime < finalTime) {
14507
- if (this.fillMidiEventQueueLimited(finalTime - this._currentState.currentTime)) {
14508
- this._synthesizer.synthesizeSilent(SynthConstants.MicroBufferSize);
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._currentState.currentTime = finalTime;
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
- tickPositionToTimePosition(tickPosition) {
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
- timePositionToTickPosition(timePosition) {
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 this._currentState.tempoChanges) {
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 * this._currentState.division));
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 this._currentState.tempoChanges) {
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 * this._currentState.division))) | 0;
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
- return !this.playbackRange ? this._currentState.endTime : this._currentState.playbackRangeEndTime;
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 (!this.playbackRange) {
14671
- this._currentState.currentTime = 0;
14672
- this._currentState.eventIndex = 0;
14685
+ if (this.isPlayingMain && this.mainPlaybackRange) {
14686
+ this._currentState.currentTime = this.mainPlaybackRange.startTick;
14673
14687
  }
14674
- else if (this.playbackRange) {
14675
- this._currentState.currentTime = this.playbackRange.startTick;
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
- let samples = new Float32Array(SynthConstants.MicroBufferSize * SynthConstants.MicroBufferCount * SynthConstants.AudioChannels);
17352
- let bufferPos = 0;
17353
- for (let i = 0; i < SynthConstants.MicroBufferCount; i++) {
17354
- // synthesize buffer
17355
- this._sequencer.fillMidiEventQueue();
17356
- const synthesizedEvents = this._synthesizer.synthesize(samples, bufferPos, SynthConstants.MicroBufferSize);
17357
- bufferPos += SynthConstants.MicroBufferSize * SynthConstants.AudioChannels;
17358
- // push all processed events into the queue
17359
- // for informing users about played events
17360
- for (const e of synthesizedEvents) {
17361
- if (this._midiEventsPlayedFilter.has(e.event.command)) {
17362
- this._playedEventsQueue.enqueue(e);
17363
- }
17364
- }
17365
- // tell sequencer to check whether its work is done
17366
- if (this._sequencer.isFinished) {
17367
- break;
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.tickPositionToTimePosition(value);
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.seek(value);
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.output.resetSamples();
17459
+ if (this._sequencer.isPlayingMain) {
17460
+ this._notPlayedSamples = 0;
17461
+ this.output.resetSamples();
17462
+ }
17444
17463
  }
17445
17464
  get playbackRange() {
17446
- return this._sequencer.playbackRange;
17465
+ return this._sequencer.mainPlaybackRange;
17447
17466
  }
17448
17467
  set playbackRange(value) {
17449
- this._sequencer.playbackRange = value;
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.playbackRange ? this._sequencer.playbackRange.startTick : 0;
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
- // pause current playback.
17519
- this.pause();
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
- this.tickPosition = 0;
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.endTime, 0, this._sequencer.endTick, false));
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.endTick;
17638
+ endTick = this._sequencer.currentEndTick;
17612
17639
  }
17613
- if (this._tickPosition >= endTick) {
17614
- Logger.debug('AlphaSynth', 'Finished playback');
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
- this._sequencer.resetOneTimeMidi();
17649
+ Logger.debug('AlphaSynth', 'Finished playback (one time)');
17650
+ this.output.resetSamples();
17622
17651
  this.state = PlayerState.Paused;
17623
- this.output.pause();
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.timePositionToTickPosition(currentTime);
17676
+ const currentTick = this._sequencer.currentTimePositionToTickPosition(currentTime);
17642
17677
  this._tickPosition = currentTick;
17643
- const endTime = this._sequencer.endTime;
17644
- const endTick = this._sequencer.endTick;
17645
- if (!this._sequencer.isPlayingOneTimeMidi && !this._sequencer.isPlayingCountIn) {
17646
- Logger.debug('AlphaSynth', `Position changed: (time: ${currentTime}/${endTime}, tick: ${currentTick}/${endTick}, Active Voices: ${this._synthesizer.activeVoiceCount}`);
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 = 0;
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 = 0;
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
- this._beatLookup.set(bounds.beat.id, bounds);
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
- let beatBounds = this.findBeat(beat);
21521
- if (!beatBounds) {
21522
- return null;
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 beatBounds.findNoteAtPos(x, y);
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, -note.beat.playbackStart, note.beat.playbackDuration, new Int32Array(note.beat.voice.bar.staff.tuning.length));
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((AlphaSynthWebAudioOutputBase.TotalBufferTimeInMilliseconds * this.sampleRate) /
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(left.length);
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(...args) {
26364
- super(...args);
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.info('WebAudio', 'creating processor');
26369
- this._bufferCount = Math.floor((AlphaSynthWebWorkletProcessor.TotalBufferTimeInMilliseconds *
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: left.length
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
- this._barToElementLookup.set(i, placeholder);
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
- this.renderer.scoreRenderer.boundsLookup.addNote(noteBounds);
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.200';
40688
- VersionInfo.date = '2022-03-08T00:34:45.791Z';
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,