@coderline/alphatab 1.3.0-alpha.849 → 1.3.0-alpha.856

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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * alphaTab v1.3.0-alpha.849 (develop, build 849)
2
+ * alphaTab v1.3.0-alpha.856 (develop, build 856)
3
3
  *
4
4
  * Copyright © 2023, Daniel Kuschny and Contributors, All rights reserved.
5
5
  *
@@ -2023,6 +2023,7 @@ class Note {
2023
2023
  this.maxBendPoint = null;
2024
2024
  /**
2025
2025
  * Gets or sets the fret on which this note is played on the instrument.
2026
+ * 0 is the nut.
2026
2027
  */
2027
2028
  this.fret = -1;
2028
2029
  /**
@@ -2370,28 +2371,43 @@ class Note {
2370
2371
  return 0;
2371
2372
  }
2372
2373
  get realValue() {
2373
- let realValue = this.realValueWithoutHarmonic;
2374
- if (this.isStringed) {
2375
- if (this.harmonicType === HarmonicType.Natural) {
2376
- realValue = this.harmonicPitch + this.stringTuning - this.beat.voice.bar.staff.transpositionPitch;
2377
- }
2378
- else {
2379
- realValue += this.harmonicPitch;
2380
- }
2381
- }
2382
- return realValue;
2374
+ return this.calculateRealValue(true, true);
2383
2375
  }
2384
2376
  get realValueWithoutHarmonic() {
2385
- if (this.isPercussion) {
2386
- return this.percussionArticulation;
2387
- }
2388
- if (this.isStringed) {
2389
- return this.fret + this.stringTuning - this.beat.voice.bar.staff.transpositionPitch;
2377
+ return this.calculateRealValue(true, false);
2378
+ }
2379
+ /**
2380
+ * Calculates the real note value of this note as midi key respecting the given options.
2381
+ * @param applyTranspositionPitch Whether or not to apply the transposition pitch of the current staff.
2382
+ * @param applyHarmonic Whether or not to apply harmonic pitches to the note.
2383
+ * @returns The calculated note value as midi key.
2384
+ */
2385
+ calculateRealValue(applyTranspositionPitch, applyHarmonic) {
2386
+ const transpositionPitch = applyTranspositionPitch ? this.beat.voice.bar.staff.transpositionPitch : 0;
2387
+ if (applyHarmonic) {
2388
+ let realValue = this.calculateRealValue(applyTranspositionPitch, false);
2389
+ if (this.isStringed) {
2390
+ if (this.harmonicType === HarmonicType.Natural) {
2391
+ realValue = this.harmonicPitch + this.stringTuning - transpositionPitch;
2392
+ }
2393
+ else {
2394
+ realValue += this.harmonicPitch;
2395
+ }
2396
+ }
2397
+ return realValue;
2390
2398
  }
2391
- if (this.isPiano) {
2392
- return this.octave * 12 + this.tone - this.beat.voice.bar.staff.transpositionPitch;
2399
+ else {
2400
+ if (this.isPercussion) {
2401
+ return this.percussionArticulation;
2402
+ }
2403
+ if (this.isStringed) {
2404
+ return this.fret + this.stringTuning - transpositionPitch;
2405
+ }
2406
+ if (this.isPiano) {
2407
+ return this.octave * 12 + this.tone - transpositionPitch;
2408
+ }
2409
+ return 0;
2393
2410
  }
2394
- return 0;
2395
2411
  }
2396
2412
  get harmonicPitch() {
2397
2413
  if (this.harmonicType === HarmonicType.None || !this.isStringed) {
@@ -13317,6 +13333,7 @@ class MusicXmlImporter extends ScoreImporter {
13317
13333
  this.ensureVoices(bar);
13318
13334
  }
13319
13335
  }
13336
+ let chordsByIdForTrack = new Map();
13320
13337
  if (masterBar) {
13321
13338
  let attributesParsed = false;
13322
13339
  for (let c of element.childNodes) {
@@ -13338,7 +13355,7 @@ class MusicXmlImporter extends ScoreImporter {
13338
13355
  }
13339
13356
  break;
13340
13357
  case 'harmony':
13341
- this.parseHarmony(c, track);
13358
+ this.parseHarmony(c, track, chordsByIdForTrack);
13342
13359
  break;
13343
13360
  case 'sound':
13344
13361
  // TODO
@@ -13478,127 +13495,23 @@ class MusicXmlImporter extends ScoreImporter {
13478
13495
  staff.tuning[staff.tuning.length - line] = tuning;
13479
13496
  }
13480
13497
  }
13481
- parseHarmony(element, track) {
13482
- let rootStep = null;
13483
- let rootAlter = '';
13484
- // let kind: string | null = null;
13485
- // let kindText: string | null = null;
13486
- for (let c of element.childNodes) {
13487
- if (c.nodeType === XmlNodeType.Element) {
13488
- switch (c.localName) {
13498
+ parseHarmony(element, track, chordsByIdForTrack) {
13499
+ let chord = new Chord();
13500
+ for (let childNode of element.childNodes) {
13501
+ if (childNode.nodeType === XmlNodeType.Element) {
13502
+ switch (childNode.localName) {
13489
13503
  case 'root':
13490
- for (let rootChild of c.childNodes) {
13491
- if (rootChild.nodeType === XmlNodeType.Element) {
13492
- switch (rootChild.localName) {
13493
- case 'root-step':
13494
- rootStep = rootChild.innerText;
13495
- break;
13496
- case 'root-alter':
13497
- switch (parseInt(c.innerText)) {
13498
- case -2:
13499
- rootAlter = ' bb';
13500
- break;
13501
- case -1:
13502
- rootAlter = ' b';
13503
- break;
13504
- case 0:
13505
- rootAlter = '';
13506
- break;
13507
- case 1:
13508
- rootAlter = ' #';
13509
- break;
13510
- case 2:
13511
- rootAlter = ' ##';
13512
- break;
13513
- }
13514
- break;
13515
- }
13516
- }
13517
- }
13504
+ chord.name = this.parseHarmonyRoot(childNode);
13505
+ break;
13506
+ case 'kind':
13507
+ chord.name = chord.name + this.parseHarmonyKind(childNode);
13508
+ break;
13509
+ case 'frame':
13510
+ this.parseHarmonyFrame(childNode, chord);
13518
13511
  break;
13519
13512
  }
13520
13513
  }
13521
13514
  }
13522
- let chord = new Chord();
13523
- chord.name = rootStep + rootAlter;
13524
- // TODO: find proper names for the rest
13525
- // switch (kind)
13526
- // {
13527
- // // triads
13528
- // case "major":
13529
- // break;
13530
- // case "minor":
13531
- // chord.Name += "m";
13532
- // break;
13533
- // // Sevenths
13534
- // case "augmented":
13535
- // break;
13536
- // case "diminished":
13537
- // break;
13538
- // case "dominant":
13539
- // break;
13540
- // case "major-seventh":
13541
- // chord.Name += "7M";
13542
- // break;
13543
- // case "minor-seventh":
13544
- // chord.Name += "m7";
13545
- // break;
13546
- // case "diminished-seventh":
13547
- // break;
13548
- // case "augmented-seventh":
13549
- // break;
13550
- // case "half-diminished":
13551
- // break;
13552
- // case "major-minor":
13553
- // break;
13554
- // // Sixths
13555
- // case "major-sixth":
13556
- // break;
13557
- // case "minor-sixth":
13558
- // break;
13559
- // // Ninths
13560
- // case "dominant-ninth":
13561
- // break;
13562
- // case "major-ninth":
13563
- // break;
13564
- // case "minor-ninth":
13565
- // break;
13566
- // // 11ths
13567
- // case "dominant-11th":
13568
- // break;
13569
- // case "major-11th":
13570
- // break;
13571
- // case "minor-11th":
13572
- // break;
13573
- // // 13ths
13574
- // case "dominant-13th":
13575
- // break;
13576
- // case "major-13th":
13577
- // break;
13578
- // case "minor-13th":
13579
- // break;
13580
- // // Suspended
13581
- // case "suspended-second":
13582
- // break;
13583
- // case "suspended-fourth":
13584
- // break;
13585
- // // Functional sixths
13586
- // case "Neapolitan":
13587
- // break;
13588
- // case "Italian":
13589
- // break;
13590
- // case "French":
13591
- // break;
13592
- // case "German":
13593
- // break;
13594
- // // Other
13595
- // case "pedal":
13596
- // break;
13597
- // case "power":
13598
- // break;
13599
- // case "Tristan":
13600
- // break;
13601
- // }
13602
13515
  // var degree = element.GetElementsByTagName("degree");
13603
13516
  // if (degree.Length > 0)
13604
13517
  // {
@@ -13615,9 +13528,199 @@ class MusicXmlImporter extends ScoreImporter {
13615
13528
  // }
13616
13529
  // }
13617
13530
  this._currentChord = ModelUtils.newGuid();
13531
+ const chordKey = chord.uniqueId;
13532
+ if (chordsByIdForTrack.has(chordKey)) {
13533
+ // check if the chord is already present
13534
+ chord.showDiagram = false;
13535
+ }
13618
13536
  for (let staff of track.staves) {
13619
13537
  staff.addChord(this._currentChord, chord);
13620
13538
  }
13539
+ chordsByIdForTrack.set(chordKey, chord);
13540
+ }
13541
+ parseHarmonyRoot(xmlNode) {
13542
+ let rootStep = '';
13543
+ let rootAlter = '';
13544
+ for (let rootChild of xmlNode.childNodes) {
13545
+ if (rootChild.nodeType === XmlNodeType.Element) {
13546
+ switch (rootChild.localName) {
13547
+ case 'root-step':
13548
+ rootStep = rootChild.innerText;
13549
+ break;
13550
+ case 'root-alter':
13551
+ switch (parseInt(xmlNode.innerText)) {
13552
+ case -2:
13553
+ rootAlter = 'bb';
13554
+ break;
13555
+ case -1:
13556
+ rootAlter = 'b';
13557
+ break;
13558
+ case 0:
13559
+ rootAlter = '';
13560
+ break;
13561
+ case 1:
13562
+ rootAlter = '#';
13563
+ break;
13564
+ case 2:
13565
+ rootAlter = '##';
13566
+ break;
13567
+ }
13568
+ break;
13569
+ }
13570
+ }
13571
+ }
13572
+ return rootStep + rootAlter;
13573
+ }
13574
+ parseHarmonyKind(xmlNode) {
13575
+ const kindText = xmlNode.getAttribute('text');
13576
+ let resultKind = '';
13577
+ if (kindText) {
13578
+ // the abbreviation is already provided
13579
+ resultKind = kindText;
13580
+ }
13581
+ else {
13582
+ const kindContent = xmlNode.innerText;
13583
+ switch (kindContent) {
13584
+ // triads
13585
+ case 'major':
13586
+ resultKind = '';
13587
+ break;
13588
+ case 'minor':
13589
+ resultKind = 'm';
13590
+ break;
13591
+ // Sevenths
13592
+ case 'augmented':
13593
+ resultKind = '+';
13594
+ break;
13595
+ case 'diminished':
13596
+ resultKind = '\u25CB';
13597
+ break;
13598
+ case 'dominant':
13599
+ resultKind = '7';
13600
+ break;
13601
+ case 'major-seventh':
13602
+ resultKind = '7M';
13603
+ break;
13604
+ case 'minor-seventh':
13605
+ resultKind = 'm7';
13606
+ break;
13607
+ case 'diminished-seventh':
13608
+ resultKind = '\u25CB7';
13609
+ break;
13610
+ case 'augmented-seventh':
13611
+ resultKind = '+7';
13612
+ break;
13613
+ case 'half-diminished':
13614
+ resultKind = '\u2349';
13615
+ break;
13616
+ case 'major-minor':
13617
+ resultKind = 'mMaj';
13618
+ break;
13619
+ // Sixths
13620
+ case 'major-sixth':
13621
+ resultKind = 'maj6';
13622
+ break;
13623
+ case 'minor-sixth':
13624
+ resultKind = 'm6';
13625
+ break;
13626
+ // Ninths
13627
+ case 'dominant-ninth':
13628
+ resultKind = '9';
13629
+ break;
13630
+ case 'major-ninth':
13631
+ resultKind = 'maj9';
13632
+ break;
13633
+ case 'minor-ninth':
13634
+ resultKind = 'm9';
13635
+ break;
13636
+ // 11ths
13637
+ case 'dominant-11th':
13638
+ resultKind = '11';
13639
+ break;
13640
+ case 'major-11th':
13641
+ resultKind = 'maj11';
13642
+ break;
13643
+ case 'minor-11th':
13644
+ resultKind = 'm11';
13645
+ break;
13646
+ // 13ths
13647
+ case 'dominant-13th':
13648
+ resultKind = '13';
13649
+ break;
13650
+ case 'major-13th':
13651
+ resultKind = 'maj13';
13652
+ break;
13653
+ case 'minor-13th':
13654
+ resultKind = 'm13';
13655
+ break;
13656
+ // Suspended
13657
+ case 'suspended-second':
13658
+ resultKind = 'sus2';
13659
+ break;
13660
+ case 'suspended-fourth':
13661
+ resultKind = 'sus4';
13662
+ break;
13663
+ // TODO: find proper names for the rest
13664
+ // Functional sixths
13665
+ // case "Neapolitan":
13666
+ // break;
13667
+ // case "Italian":
13668
+ // break;
13669
+ // case "French":
13670
+ // break;
13671
+ // case "German":
13672
+ // break;
13673
+ // // Other
13674
+ // case "pedal":
13675
+ // break;
13676
+ // case "power":
13677
+ // break;
13678
+ // case "Tristan":
13679
+ // break;
13680
+ }
13681
+ }
13682
+ return resultKind;
13683
+ }
13684
+ parseHarmonyFrame(xmlNode, chord) {
13685
+ for (let frameChild of xmlNode.childNodes) {
13686
+ if (frameChild.nodeType === XmlNodeType.Element) {
13687
+ switch (frameChild.localName) {
13688
+ case 'frame-strings':
13689
+ const stringsCount = parseInt(frameChild.innerText);
13690
+ chord.strings = new Array(stringsCount);
13691
+ for (let i = 0; i < stringsCount; i++) {
13692
+ // set strings unplayed as default
13693
+ chord.strings[i] = -1;
13694
+ }
13695
+ break;
13696
+ case 'first-fret':
13697
+ chord.firstFret = parseInt(frameChild.innerText);
13698
+ break;
13699
+ case 'frame-note':
13700
+ let stringNo = null;
13701
+ let fretNo = null;
13702
+ for (let noteChild of frameChild.childNodes) {
13703
+ switch (noteChild.localName) {
13704
+ case 'string':
13705
+ stringNo = parseInt(noteChild.innerText);
13706
+ break;
13707
+ case 'fret':
13708
+ fretNo = parseInt(noteChild.innerText);
13709
+ if (stringNo && fretNo >= 0) {
13710
+ chord.strings[stringNo - 1] = fretNo;
13711
+ }
13712
+ break;
13713
+ case 'barre':
13714
+ if (stringNo && fretNo && noteChild.getAttribute('type') === 'start') {
13715
+ chord.barreFrets.push(fretNo);
13716
+ }
13717
+ break;
13718
+ }
13719
+ }
13720
+ break;
13721
+ }
13722
+ }
13723
+ }
13621
13724
  }
13622
13725
  parseBarline(element, masterBar) {
13623
13726
  for (let c of element.childNodes) {
@@ -13884,9 +13987,9 @@ class MusicXmlImporter extends ScoreImporter {
13884
13987
  if (!slurNumber) {
13885
13988
  slurNumber = '1';
13886
13989
  }
13887
- // slur numbers are unique in the way that they have the same ID across
13888
- // staffs/tracks etc. as long they represent the logically same slur.
13889
- // but in our case it must be globally unique to link the correct notes.
13990
+ // slur numbers are unique in the way that they have the same ID across
13991
+ // staffs/tracks etc. as long they represent the logically same slur.
13992
+ // but in our case it must be globally unique to link the correct notes.
13890
13993
  // adding the staff ID should be enough to achieve this
13891
13994
  slurNumber = beat.voice.bar.staff.index + '_' + slurNumber;
13892
13995
  switch (c.getAttribute('type')) {
@@ -18922,6 +19025,14 @@ class MidiFileGenerator {
18922
19025
  * at a given midi tick position.
18923
19026
  */
18924
19027
  this.tickLookup = new MidiTickLookup();
19028
+ /**
19029
+ * Gets or sets whether transposition pitches should be applied to the individual midi events or not.
19030
+ */
19031
+ this.applyTranspositionPitches = true;
19032
+ /**
19033
+ * Gets the transposition pitches for the individual midi channels.
19034
+ */
19035
+ this.transpositionPitches = new Map();
18925
19036
  this._currentTripletFeel = null;
18926
19037
  this.vibratoResolution = 16;
18927
19038
  this._score = score;
@@ -18933,6 +19044,7 @@ class MidiFileGenerator {
18933
19044
  * Starts the generation of the midi file.
18934
19045
  */
18935
19046
  generate() {
19047
+ this.transpositionPitches.clear();
18936
19048
  // initialize tracks
18937
19049
  for (const track of this._score.tracks) {
18938
19050
  this.generateTrack(track);
@@ -18978,7 +19090,22 @@ class MidiFileGenerator {
18978
19090
  this._programsPerChannel.set(channel, program);
18979
19091
  }
18980
19092
  }
19093
+ static buildTranspositionPitches(score, settings) {
19094
+ const transpositionPitches = new Map();
19095
+ for (const track of score.tracks) {
19096
+ const transpositionPitch = track.index < settings.notation.transpositionPitches.length
19097
+ ? settings.notation.transpositionPitches[track.index]
19098
+ : 0;
19099
+ transpositionPitches.set(track.playbackInfo.primaryChannel, transpositionPitch);
19100
+ transpositionPitches.set(track.playbackInfo.secondaryChannel, transpositionPitch);
19101
+ }
19102
+ return transpositionPitches;
19103
+ }
18981
19104
  generateChannel(track, channel, playbackInfo) {
19105
+ const transpositionPitch = track.index < this._settings.notation.transpositionPitches.length
19106
+ ? this._settings.notation.transpositionPitches[track.index]
19107
+ : 0;
19108
+ this.transpositionPitches.set(channel, transpositionPitch);
18982
19109
  let volume = MidiFileGenerator.toChannelShort(playbackInfo.volume);
18983
19110
  let balance = MidiFileGenerator.toChannelShort(playbackInfo.balance);
18984
19111
  this._handler.addControlChange(track.index, 0, channel, ControllerType.VolumeCoarse, volume);
@@ -19198,7 +19325,7 @@ class MidiFileGenerator {
19198
19325
  generateNote(note, beatStart, beatDuration, brushInfo) {
19199
19326
  const track = note.beat.voice.bar.staff.track;
19200
19327
  const staff = note.beat.voice.bar.staff;
19201
- let noteKey = note.realValue;
19328
+ let noteKey = note.calculateRealValue(this.applyTranspositionPitches, true);
19202
19329
  if (note.isPercussion) {
19203
19330
  const articulation = PercussionMapper.getArticulation(note);
19204
19331
  if (articulation) {
@@ -19476,7 +19603,7 @@ class MidiFileGenerator {
19476
19603
  case SlideOutType.Shift:
19477
19604
  playedBendPoints.push(new BendPoint(shiftSlideDurationOffset, 0));
19478
19605
  // normal note values are in 1/2 tones, bends are in 1/4 tones
19479
- const dy = (note.slideTarget.realValue - note.realValue) * 2;
19606
+ const dy = (note.slideTarget.calculateRealValue(this.applyTranspositionPitches, true) - note.calculateRealValue(this.applyTranspositionPitches, true)) * 2;
19480
19607
  playedBendPoints.push(new BendPoint(BendPoint.MaxPosition, dy));
19481
19608
  break;
19482
19609
  case SlideOutType.OutDown:
@@ -20015,6 +20142,7 @@ class TinySoundFont {
20015
20142
  this._mutedChannels = new Map();
20016
20143
  this._soloChannels = new Map();
20017
20144
  this._isAnySolo = false;
20145
+ this._transpositionPitches = new Map();
20018
20146
  this.currentTempo = 0;
20019
20147
  this.timeSignatureNumerator = 0;
20020
20148
  this.timeSignatureDenominator = 0;
@@ -20076,8 +20204,30 @@ class TinySoundFont {
20076
20204
  resetChannelStates() {
20077
20205
  this._mutedChannels = new Map();
20078
20206
  this._soloChannels = new Map();
20207
+ this.applyTranspositionPitches(new Map());
20079
20208
  this._isAnySolo = false;
20080
20209
  }
20210
+ applyTranspositionPitches(transpositionPitches) {
20211
+ // dynamically adjust actively playing voices to the new pitch they have.
20212
+ // we are not updating the used preset and regions though.
20213
+ const previousTransposePitches = this._transpositionPitches;
20214
+ for (const voice of this._voices) {
20215
+ if (voice.playingChannel >= 0 && voice.playingChannel !== 9 /*percussion*/) {
20216
+ let pitchDifference = 0;
20217
+ if (previousTransposePitches.has(voice.playingChannel)) {
20218
+ pitchDifference -= previousTransposePitches.get(voice.playingChannel);
20219
+ }
20220
+ if (transpositionPitches.has(voice.playingChannel)) {
20221
+ pitchDifference += transpositionPitches.get(voice.playingChannel);
20222
+ }
20223
+ voice.playingKey += pitchDifference;
20224
+ if (this._channels) {
20225
+ voice.updatePitchRatio(this._channels.channelList[voice.playingChannel], this.outSampleRate);
20226
+ }
20227
+ }
20228
+ }
20229
+ this._transpositionPitches = transpositionPitches;
20230
+ }
20081
20231
  dispatchEvent(synthEvent) {
20082
20232
  this._midiEventQueue.enqueue(synthEvent);
20083
20233
  }
@@ -20492,6 +20642,9 @@ class TinySoundFont {
20492
20642
  if (!this._channels || channel > this._channels.channelList.length) {
20493
20643
  return;
20494
20644
  }
20645
+ if (this._transpositionPitches.has(channel)) {
20646
+ key += this._transpositionPitches.get(channel);
20647
+ }
20495
20648
  this._channels.activeChannel = channel;
20496
20649
  this.noteOn(this._channels.channelList[channel].presetIndex, key, vel);
20497
20650
  }
@@ -20501,6 +20654,9 @@ class TinySoundFont {
20501
20654
  * @param key note value between 0 and 127 (60 being middle C)
20502
20655
  */
20503
20656
  channelNoteOff(channel, key) {
20657
+ if (this._transpositionPitches.has(channel)) {
20658
+ key += this._transpositionPitches.get(channel);
20659
+ }
20504
20660
  const matches = [];
20505
20661
  let matchFirst = null;
20506
20662
  let matchLast = null;
@@ -20689,6 +20845,9 @@ class TinySoundFont {
20689
20845
  * @param pitchWheel pitch wheel position 0 to 16383 (default 8192 unpitched)
20690
20846
  */
20691
20847
  channelSetPerNotePitchWheel(channel, key, pitchWheel) {
20848
+ if (this._transpositionPitches.has(channel)) {
20849
+ key += this._transpositionPitches.get(channel);
20850
+ }
20692
20851
  const c = this.channelInit(channel);
20693
20852
  if (c.perNotePitchWheel.has(key) && c.perNotePitchWheel.get(key) === pitchWheel) {
20694
20853
  return;
@@ -21486,6 +21645,9 @@ class AlphaSynth {
21486
21645
  this.midiLoadFailed.trigger(e);
21487
21646
  }
21488
21647
  }
21648
+ applyTranspositionPitches(transpositionPitches) {
21649
+ this._synthesizer.applyTranspositionPitches(transpositionPitches);
21650
+ }
21489
21651
  setChannelMute(channel, mute) {
21490
21652
  this._synthesizer.channelSetMute(channel, mute);
21491
21653
  }
@@ -23174,6 +23336,9 @@ class AlphaSynthWebWorker {
23174
23336
  cmd: 'alphaSynth.destroyed'
23175
23337
  });
23176
23338
  break;
23339
+ case 'alphaSynth.applyTranspositionPitches':
23340
+ this._player.applyTranspositionPitches(new Map(JSON.parse(data.transpositionPitches)));
23341
+ break;
23177
23342
  }
23178
23343
  }
23179
23344
  onPositionChanged(e) {
@@ -24963,6 +25128,7 @@ class AlphaTabApiBase {
24963
25128
  * Applies any changes that were done to the settings object and informs the {@link renderer} about any new values to consider.
24964
25129
  */
24965
25130
  updateSettings() {
25131
+ var _a;
24966
25132
  const score = this.score;
24967
25133
  if (score) {
24968
25134
  ModelUtils.applyPitchOffsets(this.settings, score);
@@ -24971,6 +25137,9 @@ class AlphaTabApiBase {
24971
25137
  // enable/disable player if needed
24972
25138
  if (this.settings.player.enablePlayer) {
24973
25139
  this.setupPlayer();
25140
+ if (score) {
25141
+ (_a = this.player) === null || _a === void 0 ? void 0 : _a.applyTranspositionPitches(MidiFileGenerator.buildTranspositionPitches(score, this.settings));
25142
+ }
24974
25143
  }
24975
25144
  else {
24976
25145
  this.destroyPlayer();
@@ -25341,10 +25510,13 @@ class AlphaTabApiBase {
25341
25510
  let midiFile = new MidiFile();
25342
25511
  let handler = new AlphaSynthMidiFileHandler(midiFile);
25343
25512
  let generator = new MidiFileGenerator(this.score, this.settings, handler);
25513
+ // we pass the transposition pitches separately to alphaSynth.
25514
+ generator.applyTranspositionPitches = false;
25344
25515
  generator.generate();
25345
25516
  this._tickCache = generator.tickLookup;
25346
25517
  this.onMidiLoad(midiFile);
25347
25518
  this.player.loadMidiFile(midiFile);
25519
+ this.player.applyTranspositionPitches(generator.transpositionPitches);
25348
25520
  }
25349
25521
  /**
25350
25522
  * Changes the volume of the given tracks.
@@ -27018,6 +27190,12 @@ class AlphaSynthWebWorkerApi {
27018
27190
  midi: JsonConverter.midiFileToJsObject(midi)
27019
27191
  });
27020
27192
  }
27193
+ applyTranspositionPitches(transpositionPitches) {
27194
+ this._synth.postMessage({
27195
+ cmd: 'alphaSynth.applyTranspositionPitches',
27196
+ transpositionPitches: JSON.stringify(Array.from(transpositionPitches.entries()))
27197
+ });
27198
+ }
27021
27199
  setChannelMute(channel, mute) {
27022
27200
  this._synth.postMessage({
27023
27201
  cmd: 'alphaSynth.setChannelMute',
@@ -42315,8 +42493,8 @@ class CoreSettings {
42315
42493
  // </auto-generated>
42316
42494
  class VersionInfo {
42317
42495
  }
42318
- VersionInfo.version = '1.3.0-alpha.849';
42319
- VersionInfo.date = '2023-12-05T01:25:45.378Z';
42496
+ VersionInfo.version = '1.3.0-alpha.856';
42497
+ VersionInfo.date = '2023-12-12T01:25:35.593Z';
42320
42498
 
42321
42499
  var index$5 = /*#__PURE__*/Object.freeze({
42322
42500
  __proto__: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coderline/alphatab",
3
- "version": "1.3.0-alpha.849",
3
+ "version": "1.3.0-alpha.856",
4
4
  "description": "alphaTab is a music notation and guitar tablature rendering library",
5
5
  "keywords": [
6
6
  "guitar",
@@ -80,7 +80,7 @@
80
80
  "rollup-plugin-dts": "^6.1.0",
81
81
  "rollup-plugin-license": "^3.2.0",
82
82
  "terser": "^5.24.0",
83
- "tsx": "^3.14.0",
83
+ "tsx": "^4.6.2",
84
84
  "typescript": "^5.2.2"
85
85
  },
86
86
  "files": [