@coderline/alphatab 1.7.0-alpha.1568 → 1.7.0-alpha.1575

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.7.0-alpha.1568 (develop, build 1568)
2
+ * alphaTab v1.7.0-alpha.1575 (develop, build 1575)
3
3
  *
4
4
  * Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
5
5
  *
@@ -203,9 +203,9 @@
203
203
  print(`build date: ${VersionInfo.date}`);
204
204
  }
205
205
  }
206
- VersionInfo.version = '1.7.0-alpha.1568';
207
- VersionInfo.date = '2025-10-07T01:57:28.773Z';
208
- VersionInfo.commit = '74a7b1503601f5a61437e95ba242fc411e55052a';
206
+ VersionInfo.version = '1.7.0-alpha.1575';
207
+ VersionInfo.date = '2025-10-14T01:59:22.619Z';
208
+ VersionInfo.commit = 'a3c1535029d34be6f5b12229cd84222f2f4d37ce';
209
209
 
210
210
  /**
211
211
  * This public class provides names for all general midi instruments.
@@ -1487,8 +1487,13 @@
1487
1487
  * Gets or sets the additional text of the automation.
1488
1488
  */
1489
1489
  this.text = '';
1490
+ /**
1491
+ * Whether this automation should be visible. (not all automation types are shown,
1492
+ * e.g. tempo changes shown in the score while volume changes are not).
1493
+ */
1494
+ this.isVisible = true;
1490
1495
  }
1491
- static buildTempoAutomation(isLinear, ratioPosition, value, reference) {
1496
+ static buildTempoAutomation(isLinear, ratioPosition, value, reference, isVisible = true) {
1492
1497
  if (reference < 1 || reference > 5) {
1493
1498
  reference = 2;
1494
1499
  }
@@ -1498,6 +1503,7 @@
1498
1503
  automation.isLinear = isLinear;
1499
1504
  automation.ratioPosition = ratioPosition;
1500
1505
  automation.value = value * references[reference];
1506
+ automation.isVisible = isVisible;
1501
1507
  return automation;
1502
1508
  }
1503
1509
  static buildInstrumentAutomation(isLinear, ratioPosition, value) {
@@ -3904,6 +3910,19 @@
3904
3910
  }
3905
3911
  }
3906
3912
  }
3913
+ // ensure first masterbar has a tempo automation for score tempo
3914
+ if (score.masterBars.length > 0) {
3915
+ const firstTempoAutomation = score.masterBars[0].tempoAutomations.find(a => a.type === AutomationType.Tempo && a.ratioPosition === 0);
3916
+ if (!firstTempoAutomation) {
3917
+ const tempoAutomation = new Automation();
3918
+ tempoAutomation.isLinear = false;
3919
+ tempoAutomation.type = AutomationType.Tempo;
3920
+ tempoAutomation.value = score.tempo;
3921
+ tempoAutomation.text = score.tempoLabel;
3922
+ tempoAutomation.isVisible = false;
3923
+ score.masterBars[0].tempoAutomations.push(tempoAutomation);
3924
+ }
3925
+ }
3907
3926
  }
3908
3927
  /**
3909
3928
  * Trims any empty bars at the end of the song.
@@ -6234,6 +6253,7 @@
6234
6253
  clone.syncPointValue = original.syncPointValue ? SyncPointDataCloner.clone(original.syncPointValue) : undefined;
6235
6254
  clone.ratioPosition = original.ratioPosition;
6236
6255
  clone.text = original.text;
6256
+ clone.isVisible = original.isVisible;
6237
6257
  return clone;
6238
6258
  }
6239
6259
  }
@@ -7634,14 +7654,6 @@
7634
7654
  * The author of this tablature.
7635
7655
  */
7636
7656
  this.tab = '';
7637
- /**
7638
- * Gets or sets the global tempo of the song in BPM. The tempo might change via {@link MasterBar.tempoAutomations}.
7639
- */
7640
- this.tempo = 120;
7641
- /**
7642
- * Gets or sets the name/label of the tempo.
7643
- */
7644
- this.tempoLabel = '';
7645
7657
  /**
7646
7658
  * Gets or sets a list of all masterbars contained in this song.
7647
7659
  * @json_add addMasterBar
@@ -7676,6 +7688,22 @@
7676
7688
  Voice$1.resetIds();
7677
7689
  Note.resetIds();
7678
7690
  }
7691
+ /**
7692
+ * The initial tempo of the song in BPM. The tempo might change via {@link MasterBar.tempoAutomations}.
7693
+ */
7694
+ get tempo() {
7695
+ return this.masterBars.length && this.masterBars[0].tempoAutomations.length > 0
7696
+ ? this.masterBars[0].tempoAutomations[0].value
7697
+ : 120;
7698
+ }
7699
+ /**
7700
+ * The name/label of the initial tempo.
7701
+ */
7702
+ get tempoLabel() {
7703
+ return this.masterBars.length && this.masterBars[0].tempoAutomations.length > 0
7704
+ ? this.masterBars[0].tempoAutomations[0].text
7705
+ : '';
7706
+ }
7679
7707
  rebuildRepeatGroups() {
7680
7708
  this._currentRepeatGroup = null;
7681
7709
  this._openedRepeatGroups = [];
@@ -9521,6 +9549,7 @@
9521
9549
  this._trackChannel = 0;
9522
9550
  this._barIndex = 0;
9523
9551
  this._voiceIndex = 0;
9552
+ this._initialTempo = Automation.buildTempoAutomation(false, 0, 120, 0);
9524
9553
  // Last known position that had valid syntax/symbols
9525
9554
  this._currentDuration = Duration.QuadrupleWhole;
9526
9555
  this._currentDynamics = DynamicValue.PPP;
@@ -9688,8 +9717,6 @@
9688
9717
  */
9689
9718
  createDefaultScore() {
9690
9719
  this._score = new Score();
9691
- this._score.tempo = 120;
9692
- this._score.tempoLabel = '';
9693
9720
  this.newTrack();
9694
9721
  }
9695
9722
  newTrack() {
@@ -9977,14 +10004,14 @@
9977
10004
  case 'tempo':
9978
10005
  this.sy = this.newSy(true);
9979
10006
  if (this.sy === AlphaTexSymbols.Number) {
9980
- this._score.tempo = this.syData;
10007
+ this._initialTempo.value = this.syData;
9981
10008
  }
9982
10009
  else {
9983
10010
  this.error('tempo', AlphaTexSymbols.Number, true);
9984
10011
  }
9985
10012
  this.sy = this.newSy();
9986
10013
  if (this.sy === AlphaTexSymbols.String) {
9987
- this._score.tempoLabel = this.syData;
10014
+ this._initialTempo.text = this.syData;
9988
10015
  this.sy = this.newSy();
9989
10016
  }
9990
10017
  anyTopLevelMeta = true;
@@ -10746,6 +10773,9 @@
10746
10773
  master.timeSignatureNumerator = master.previousMasterBar.timeSignatureNumerator;
10747
10774
  master.tripletFeel = master.previousMasterBar.tripletFeel;
10748
10775
  }
10776
+ else {
10777
+ master.tempoAutomations.push(this._initialTempo);
10778
+ }
10749
10779
  }
10750
10780
  const anyBarMeta = this.barMeta(bar);
10751
10781
  // detect tuning for staff
@@ -11239,6 +11269,15 @@
11239
11269
  else if (syData === 'tempo') {
11240
11270
  // NOTE: playbackRatio is calculated on score finish when playback positions are known
11241
11271
  const tempoAutomation = this.readTempoAutomation(false);
11272
+ if (beat.index === 0) {
11273
+ const existing = beat.voice.bar.masterBar.tempoAutomations.find(a => a.ratioPosition === 0);
11274
+ if (existing) {
11275
+ existing.value = tempoAutomation.value;
11276
+ existing.text = tempoAutomation.text;
11277
+ beat.automations.push(existing);
11278
+ return true;
11279
+ }
11280
+ }
11242
11281
  beat.automations.push(tempoAutomation);
11243
11282
  beat.voice.bar.masterBar.tempoAutomations.push(tempoAutomation);
11244
11283
  return true;
@@ -12229,7 +12268,15 @@
12229
12268
  }
12230
12269
  else if (syData === 'tempo') {
12231
12270
  const tempoAutomation = this.readTempoAutomation(true);
12232
- master.tempoAutomations.push(tempoAutomation);
12271
+ const existing = master.tempoAutomations.find(a => a.ratioPosition === tempoAutomation.ratioPosition);
12272
+ if (existing) {
12273
+ existing.value = tempoAutomation.value;
12274
+ existing.text = tempoAutomation.text;
12275
+ existing.isVisible = tempoAutomation.isVisible;
12276
+ }
12277
+ else {
12278
+ master.tempoAutomations.push(tempoAutomation);
12279
+ }
12233
12280
  }
12234
12281
  else if (syData === 'section') {
12235
12282
  this.sy = this.newSy();
@@ -12517,7 +12564,7 @@
12517
12564
  const tempoAutomation = new Automation();
12518
12565
  tempoAutomation.isLinear = false;
12519
12566
  tempoAutomation.type = AutomationType.Tempo;
12520
- if (this.sy === AlphaTexSymbols.LBrace && withPosition) {
12567
+ if (this.sy === AlphaTexSymbols.LParensis && withPosition) {
12521
12568
  this.sy = this.newSy(true);
12522
12569
  if (this.sy !== AlphaTexSymbols.Number) {
12523
12570
  this.error('tempo', AlphaTexSymbols.Number, true);
@@ -12533,8 +12580,12 @@
12533
12580
  }
12534
12581
  tempoAutomation.ratioPosition = this.syData;
12535
12582
  this.sy = this.newSy();
12536
- if (this.sy !== AlphaTexSymbols.RBrace) {
12537
- this.error('tempo', AlphaTexSymbols.RBrace, true);
12583
+ if (this.sy === AlphaTexSymbols.String && this.syData === 'hide') {
12584
+ tempoAutomation.isVisible = false;
12585
+ this.sy = this.newSy();
12586
+ }
12587
+ if (this.sy !== AlphaTexSymbols.RParensis) {
12588
+ this.error('tempo', AlphaTexSymbols.RParensis, true);
12538
12589
  }
12539
12590
  this.sy = this.newSy();
12540
12591
  }
@@ -14009,6 +14060,7 @@
14009
14060
  this._trackChannel = 0;
14010
14061
  this._beamingMode = BeatBeamingMode.Auto;
14011
14062
  this._isFirstSystem = true;
14063
+ this._initialTempo = -1;
14012
14064
  this._staffLookup = new Map();
14013
14065
  this._brackets = [];
14014
14066
  this._staffLayoutLookup = new Map();
@@ -14071,7 +14123,6 @@
14071
14123
  }
14072
14124
  if (root.localName === 'score') {
14073
14125
  this.score = new Score();
14074
- this.score.tempo = 120;
14075
14126
  // parse all children
14076
14127
  for (const n of root.childElements()) {
14077
14128
  switch (n.localName) {
@@ -14245,7 +14296,7 @@
14245
14296
  parseSystem(element) {
14246
14297
  if (element.attributes.has('tempo')) {
14247
14298
  if (this.score.masterBars.length === 0) {
14248
- this.score.tempo = Number.parseInt(element.attributes.get('tempo'), 10);
14299
+ this._initialTempo = Number.parseInt(element.attributes.get('tempo'), 10);
14249
14300
  }
14250
14301
  }
14251
14302
  if (element.getAttribute('beamGrouping') === '0') {
@@ -14352,6 +14403,9 @@
14352
14403
  if (master.index > 0) {
14353
14404
  master.tripletFeel = master.previousMasterBar.tripletFeel;
14354
14405
  }
14406
+ else if (this._initialTempo > 0) {
14407
+ master.tempoAutomations.push(Automation.buildTempoAutomation(false, 0, this._initialTempo, 0));
14408
+ }
14355
14409
  master.timeSignatureDenominator = this._timeSignature.timeSignatureDenominator;
14356
14410
  master.timeSignatureNumerator = this._timeSignature.timeSignatureNumerator;
14357
14411
  master.timeSignatureCommon = this._timeSignature.timeSignatureCommon;
@@ -15127,12 +15181,13 @@
15127
15181
  this.data.skip(19);
15128
15182
  }
15129
15183
  // page setup since GP5
15184
+ this._initialTempo = Automation.buildTempoAutomation(false, 0, 0, 0);
15130
15185
  if (this._versionNumber >= 500) {
15131
15186
  this.readPageSetup();
15132
- this._score.tempoLabel = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
15187
+ this._initialTempo.text = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
15133
15188
  }
15134
15189
  // tempo stuff
15135
- this._score.tempo = IOHelper.readInt32LE(this.data);
15190
+ this._initialTempo.value = IOHelper.readInt32LE(this.data);
15136
15191
  if (this._versionNumber >= 510) {
15137
15192
  GpBinaryHelpers.gpReadBool(this.data); // hide tempo?
15138
15193
  }
@@ -15211,7 +15266,8 @@
15211
15266
  }
15212
15267
  version = version.substr(Gp3To5Importer.VersionString.length + 1);
15213
15268
  const dot = version.indexOf(String.fromCharCode(46));
15214
- this._versionNumber = 100 * Number.parseInt(version.substr(0, dot), 10) + Number.parseInt(version.substr(dot + 1), 10);
15269
+ this._versionNumber =
15270
+ 100 * Number.parseInt(version.substr(0, dot), 10) + Number.parseInt(version.substr(dot + 1), 10);
15215
15271
  Logger.debug(this.name, `Guitar Pro version ${version} detected`);
15216
15272
  }
15217
15273
  readScoreInformation() {
@@ -15321,6 +15377,9 @@
15321
15377
  previousMasterBar = this._score.masterBars[this._score.masterBars.length - 1];
15322
15378
  }
15323
15379
  const newMasterBar = new MasterBar();
15380
+ if (!previousMasterBar && this._initialTempo.value > 0) {
15381
+ newMasterBar.tempoAutomations.push(this._initialTempo);
15382
+ }
15324
15383
  const flags = this.data.readByte();
15325
15384
  // time signature
15326
15385
  if ((flags & 0x01) !== 0) {
@@ -17333,6 +17392,7 @@
17333
17392
  let reference = 0;
17334
17393
  let text = null;
17335
17394
  let syncPointValue = undefined;
17395
+ let isVisible = true;
17336
17396
  for (const c of node.childElements()) {
17337
17397
  switch (c.localName) {
17338
17398
  case 'Type':
@@ -17387,6 +17447,9 @@
17387
17447
  case 'Text':
17388
17448
  text = c.innerText;
17389
17449
  break;
17450
+ case 'Visible':
17451
+ isVisible = c.innerText.toLowerCase() === 'true';
17452
+ break;
17390
17453
  }
17391
17454
  }
17392
17455
  if (!type) {
@@ -17395,7 +17458,7 @@
17395
17458
  const newAutomations = [];
17396
17459
  switch (type) {
17397
17460
  case 'Tempo':
17398
- newAutomations.push(Automation.buildTempoAutomation(isLinear, ratioPosition, numberValue, reference));
17461
+ newAutomations.push(Automation.buildTempoAutomation(isLinear, ratioPosition, numberValue, reference, isVisible));
17399
17462
  break;
17400
17463
  case 'SyncPoint':
17401
17464
  const syncPoint = new Automation();
@@ -17403,6 +17466,7 @@
17403
17466
  syncPoint.isLinear = isLinear;
17404
17467
  syncPoint.ratioPosition = ratioPosition;
17405
17468
  syncPoint.syncPointValue = syncPointValue;
17469
+ syncPoint.isVisible = isVisible;
17406
17470
  newAutomations.push(syncPoint);
17407
17471
  break;
17408
17472
  case 'Sound':
@@ -17411,6 +17475,7 @@
17411
17475
  bankChange.type = AutomationType.Bank;
17412
17476
  bankChange.ratioPosition = ratioPosition;
17413
17477
  bankChange.value = sounds.get(textValue).bank;
17478
+ bankChange.isVisible = isVisible;
17414
17479
  newAutomations.push(bankChange);
17415
17480
  const programChange = Automation.buildInstrumentAutomation(isLinear, ratioPosition, sounds.get(textValue).program);
17416
17481
  newAutomations.push(programChange);
@@ -19551,12 +19616,6 @@
19551
19616
  const automation = automations[i];
19552
19617
  switch (automation.type) {
19553
19618
  case AutomationType.Tempo:
19554
- if (barNumber === 0) {
19555
- this.score.tempo = automation.value | 0;
19556
- if (automation.text) {
19557
- this.score.tempoLabel = automation.text;
19558
- }
19559
- }
19560
19619
  masterBar.tempoAutomations.push(automation);
19561
19620
  break;
19562
19621
  case AutomationType.SyncPoint:
@@ -20660,7 +20719,6 @@
20660
20719
  throw new UnsupportedFormatError('Unsupported format', e);
20661
20720
  }
20662
20721
  this._score = new Score();
20663
- this._score.tempo = 120;
20664
20722
  this._score.stylesheet.hideDynamics = true;
20665
20723
  this.parseDom(dom);
20666
20724
  ModelUtils.consolidate(this._score);
@@ -22302,9 +22360,6 @@
22302
22360
  tempoAutomation.ratioPosition = getRatioPosition();
22303
22361
  if (!this.hasSameTempo(masterBar, tempoAutomation)) {
22304
22362
  masterBar.tempoAutomations.push(tempoAutomation);
22305
- if (masterBar.index === 0) {
22306
- masterBar.score.tempo = tempoAutomation.value;
22307
- }
22308
22363
  }
22309
22364
  }
22310
22365
  let previousWords = '';
@@ -22450,9 +22505,6 @@
22450
22505
  tempoAutomation.ratioPosition = ratioPosition;
22451
22506
  if (!this.hasSameTempo(masterBar, tempoAutomation)) {
22452
22507
  masterBar.tempoAutomations.push(tempoAutomation);
22453
- if (masterBar.index === 0) {
22454
- masterBar.score.tempo = tempoAutomation.value;
22455
- }
22456
22508
  }
22457
22509
  }
22458
22510
  }
@@ -36918,6 +36970,7 @@
36918
36970
  }
36919
36971
  o.set("ratioposition", obj.ratioPosition);
36920
36972
  o.set("text", obj.text);
36973
+ o.set("isvisible", obj.isVisible);
36921
36974
  return o;
36922
36975
  }
36923
36976
  static setProperty(obj, property, v) {
@@ -36946,6 +36999,9 @@
36946
36999
  case "text":
36947
37000
  obj.text = v;
36948
37001
  return true;
37002
+ case "isvisible":
37003
+ obj.isVisible = v;
37004
+ return true;
36949
37005
  }
36950
37006
  return false;
36951
37007
  }
@@ -38502,8 +38558,6 @@
38502
38558
  o.set("title", obj.title);
38503
38559
  o.set("words", obj.words);
38504
38560
  o.set("tab", obj.tab);
38505
- o.set("tempo", obj.tempo);
38506
- o.set("tempolabel", obj.tempoLabel);
38507
38561
  o.set("masterbars", obj.masterBars.map(i => MasterBarSerializer.toJson(i)));
38508
38562
  o.set("tracks", obj.tracks.map(i => TrackSerializer.toJson(i)));
38509
38563
  o.set("defaultsystemslayout", obj.defaultSystemsLayout);
@@ -38549,12 +38603,6 @@
38549
38603
  case "tab":
38550
38604
  obj.tab = v;
38551
38605
  return true;
38552
- case "tempo":
38553
- obj.tempo = v;
38554
- return true;
38555
- case "tempolabel":
38556
- obj.tempoLabel = v;
38557
- return true;
38558
38606
  case "masterbars":
38559
38607
  obj.masterBars = [];
38560
38608
  for (const o of v) {
@@ -56845,10 +56893,10 @@
56845
56893
  return (beat.voice.bar.staff.index === 0 &&
56846
56894
  beat.voice.index === 0 &&
56847
56895
  beat.index === 0 &&
56848
- beat.voice.bar.masterBar.tempoAutomations.length > 0);
56896
+ beat.voice.bar.masterBar.tempoAutomations.some(t => t.isVisible));
56849
56897
  }
56850
56898
  createNewGlyph(_renderer, beat) {
56851
- return new BarTempoGlyph(beat.voice.bar.masterBar.tempoAutomations);
56899
+ return new BarTempoGlyph(beat.voice.bar.masterBar.tempoAutomations.filter(a => a.isVisible));
56852
56900
  }
56853
56901
  canExpand(_from, _to) {
56854
56902
  return true;
@@ -66966,11 +67014,15 @@
66966
67014
  }
66967
67015
  }
66968
67016
  for (const a of masterBar.tempoAutomations) {
66969
- writer.write(`\\tempo { ${a.value} `);
67017
+ writer.write(`\\tempo ( ${a.value} `);
66970
67018
  if (a.text) {
66971
67019
  writer.writeString(a.text);
66972
67020
  }
66973
- writer.writeLine(`${a.ratioPosition} }`);
67021
+ writer.write(`${a.ratioPosition} `);
67022
+ if (!a.isVisible) {
67023
+ writer.writeLine('hide ');
67024
+ }
67025
+ writer.writeLine(`)`);
66974
67026
  }
66975
67027
  writer.dropSingleLineComment();
66976
67028
  }
@@ -68387,7 +68439,7 @@
68387
68439
  tempoAutomation.addElement('Linear').innerText = automation.isLinear ? 'true' : 'false';
68388
68440
  tempoAutomation.addElement('Bar').innerText = mb.index.toString();
68389
68441
  tempoAutomation.addElement('Position').innerText = automation.ratioPosition.toString();
68390
- tempoAutomation.addElement('Visible').innerText = 'true';
68442
+ tempoAutomation.addElement('Visible').innerText = automation.isVisible ? 'true' : 'false';
68391
68443
  tempoAutomation.addElement('Value').innerText = `${automation.value} 2`;
68392
68444
  if (automation.text) {
68393
68445
  tempoAutomation.addElement('Text').innerText = automation.text;