@coderline/alphatab 1.7.0-alpha.1517 → 1.7.0-alpha.1524
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alphaTab.core.min.mjs +2 -2
- package/dist/alphaTab.core.mjs +410 -286
- package/dist/alphaTab.d.ts +78 -23
- package/dist/alphaTab.js +410 -286
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.vite.js +1 -1
- package/dist/alphaTab.vite.mjs +1 -1
- package/dist/alphaTab.webpack.js +1 -1
- package/dist/alphaTab.webpack.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +1 -1
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.7.0-alpha.
|
|
2
|
+
* alphaTab v1.7.0-alpha.1524 (develop, build 1524)
|
|
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.
|
|
207
|
-
VersionInfo.date = '2025-08-
|
|
208
|
-
VersionInfo.commit = '
|
|
206
|
+
VersionInfo.version = '1.7.0-alpha.1524';
|
|
207
|
+
VersionInfo.date = '2025-08-26T02:05:48.392Z';
|
|
208
|
+
VersionInfo.commit = 'df53c7a4e3df1b16f58e3cd395021e50a6fa0048';
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* This public class provides names for all general midi instruments.
|
|
@@ -232,6 +232,14 @@
|
|
|
232
232
|
static isGuitar(program) {
|
|
233
233
|
return (program >= 24 && program <= 39) || program === 105 || program === 43;
|
|
234
234
|
}
|
|
235
|
+
static isBass(program) {
|
|
236
|
+
return program >= 32 && program <= 39;
|
|
237
|
+
}
|
|
238
|
+
static bankToLsbMsb(bank) {
|
|
239
|
+
const lsb = bank & 0x7f;
|
|
240
|
+
const msb = (bank >> 7) & 0x7f;
|
|
241
|
+
return [lsb, msb];
|
|
242
|
+
}
|
|
235
243
|
}
|
|
236
244
|
GeneralMidi._values = new Map([
|
|
237
245
|
['acousticgrandpiano', 0],
|
|
@@ -1426,6 +1434,10 @@
|
|
|
1426
1434
|
* A sync point for synchronizing the internal time axis with an external audio track.
|
|
1427
1435
|
*/
|
|
1428
1436
|
AutomationType[AutomationType["SyncPoint"] = 4] = "SyncPoint";
|
|
1437
|
+
/**
|
|
1438
|
+
* Midi Bank change.
|
|
1439
|
+
*/
|
|
1440
|
+
AutomationType[AutomationType["Bank"] = 4] = "Bank";
|
|
1429
1441
|
})(AutomationType || (AutomationType = {}));
|
|
1430
1442
|
/**
|
|
1431
1443
|
* Represents the data of a sync point for synchronizing the internal time axis with
|
|
@@ -8167,6 +8179,10 @@
|
|
|
8167
8179
|
* Gets or sets the midi program to use.
|
|
8168
8180
|
*/
|
|
8169
8181
|
this.program = 0;
|
|
8182
|
+
/**
|
|
8183
|
+
* The midi bank to use.
|
|
8184
|
+
*/
|
|
8185
|
+
this.bank = 0;
|
|
8170
8186
|
/**
|
|
8171
8187
|
* Gets or sets the primary channel for all normal midi events.
|
|
8172
8188
|
*/
|
|
@@ -8561,6 +8577,12 @@
|
|
|
8561
8577
|
*/
|
|
8562
8578
|
this.percussionArticulations = [];
|
|
8563
8579
|
}
|
|
8580
|
+
/**
|
|
8581
|
+
* Gets whether this track is a percussion track.
|
|
8582
|
+
*/
|
|
8583
|
+
get isPercussion() {
|
|
8584
|
+
return this.staves.some(s => s.isPercussion);
|
|
8585
|
+
}
|
|
8564
8586
|
/**
|
|
8565
8587
|
* Adds a new line break.
|
|
8566
8588
|
* @param index The index of the bar before which a line break should happen.
|
|
@@ -10225,33 +10247,15 @@
|
|
|
10225
10247
|
}
|
|
10226
10248
|
return StaffMetaResult.KnownStaffMeta;
|
|
10227
10249
|
case 'instrument':
|
|
10228
|
-
this.sy = this.newSy();
|
|
10229
10250
|
this._staffTuningApplied = false;
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
10237
|
-
}
|
|
10238
|
-
}
|
|
10239
|
-
else if (this.sy === AlphaTexSymbols.String) {
|
|
10240
|
-
const instrumentName = this.syData.toLowerCase();
|
|
10241
|
-
if (instrumentName === 'percussion') {
|
|
10242
|
-
for (const staff of this._currentTrack.staves) {
|
|
10243
|
-
this.applyPercussionStaff(staff);
|
|
10244
|
-
}
|
|
10245
|
-
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
10246
|
-
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10247
|
-
}
|
|
10248
|
-
else {
|
|
10249
|
-
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10250
|
-
}
|
|
10251
|
-
}
|
|
10252
|
-
else {
|
|
10253
|
-
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10251
|
+
this.readTrackInstrument();
|
|
10252
|
+
return StaffMetaResult.KnownStaffMeta;
|
|
10253
|
+
case 'bank':
|
|
10254
|
+
this.sy = this.newSy();
|
|
10255
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10256
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10254
10257
|
}
|
|
10258
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10255
10259
|
this.sy = this.newSy();
|
|
10256
10260
|
return StaffMetaResult.KnownStaffMeta;
|
|
10257
10261
|
case 'lyrics':
|
|
@@ -10362,6 +10366,35 @@
|
|
|
10362
10366
|
return StaffMetaResult.UnknownStaffMeta;
|
|
10363
10367
|
}
|
|
10364
10368
|
}
|
|
10369
|
+
readTrackInstrument() {
|
|
10370
|
+
this.sy = this.newSy();
|
|
10371
|
+
if (this.sy === AlphaTexSymbols.Number) {
|
|
10372
|
+
const instrument = this.syData;
|
|
10373
|
+
if (instrument >= 0 && instrument <= 127) {
|
|
10374
|
+
this._currentTrack.playbackInfo.program = this.syData;
|
|
10375
|
+
}
|
|
10376
|
+
else {
|
|
10377
|
+
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
10378
|
+
}
|
|
10379
|
+
}
|
|
10380
|
+
else if (this.sy === AlphaTexSymbols.String) {
|
|
10381
|
+
const instrumentName = this.syData.toLowerCase();
|
|
10382
|
+
if (instrumentName === 'percussion') {
|
|
10383
|
+
for (const staff of this._currentTrack.staves) {
|
|
10384
|
+
this.applyPercussionStaff(staff);
|
|
10385
|
+
}
|
|
10386
|
+
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
10387
|
+
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10388
|
+
}
|
|
10389
|
+
else {
|
|
10390
|
+
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10391
|
+
}
|
|
10392
|
+
}
|
|
10393
|
+
else {
|
|
10394
|
+
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10395
|
+
}
|
|
10396
|
+
this.sy = this.newSy();
|
|
10397
|
+
}
|
|
10365
10398
|
handleAccidentalMode() {
|
|
10366
10399
|
this.sy = this.newSy();
|
|
10367
10400
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -10634,6 +10667,17 @@
|
|
|
10634
10667
|
}
|
|
10635
10668
|
this._score.stylesheet.perTrackMultiBarRest.add(this._currentTrack.index);
|
|
10636
10669
|
break;
|
|
10670
|
+
case 'instrument':
|
|
10671
|
+
this.readTrackInstrument();
|
|
10672
|
+
break;
|
|
10673
|
+
case 'bank':
|
|
10674
|
+
this.sy = this.newSy();
|
|
10675
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10676
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10677
|
+
}
|
|
10678
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10679
|
+
this.sy = this.newSy();
|
|
10680
|
+
break;
|
|
10637
10681
|
default:
|
|
10638
10682
|
this.error('track-properties', AlphaTexSymbols.String, false);
|
|
10639
10683
|
break;
|
|
@@ -11434,6 +11478,17 @@
|
|
|
11434
11478
|
automation.value = program;
|
|
11435
11479
|
beat.automations.push(automation);
|
|
11436
11480
|
}
|
|
11481
|
+
else if (syData === 'bank') {
|
|
11482
|
+
this.sy = this.newSy();
|
|
11483
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
11484
|
+
this.error('bank-change', AlphaTexSymbols.Number, true);
|
|
11485
|
+
}
|
|
11486
|
+
const automation = new Automation();
|
|
11487
|
+
automation.isLinear = false;
|
|
11488
|
+
automation.type = AutomationType.Bank;
|
|
11489
|
+
automation.value = this.syData;
|
|
11490
|
+
beat.automations.push(automation);
|
|
11491
|
+
}
|
|
11437
11492
|
else if (syData === 'fermata') {
|
|
11438
11493
|
this.sy = this.newSy();
|
|
11439
11494
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -11444,7 +11499,7 @@
|
|
|
11444
11499
|
this.sy = this.newSy(true);
|
|
11445
11500
|
if (this.sy === AlphaTexSymbols.Number) {
|
|
11446
11501
|
fermata.length = this.syData;
|
|
11447
|
-
this.sy = this.newSy(
|
|
11502
|
+
this.sy = this.newSy();
|
|
11448
11503
|
}
|
|
11449
11504
|
beat.fermata = fermata;
|
|
11450
11505
|
return true;
|
|
@@ -11477,13 +11532,9 @@
|
|
|
11477
11532
|
beat.beamingMode = BeatBeamingMode.ForceSplitOnSecondaryToNext;
|
|
11478
11533
|
break;
|
|
11479
11534
|
}
|
|
11480
|
-
this.sy = this.newSy();
|
|
11481
|
-
return true;
|
|
11482
11535
|
}
|
|
11483
11536
|
else if (syData === 'timer') {
|
|
11484
11537
|
beat.showTimer = true;
|
|
11485
|
-
this.sy = this.newSy();
|
|
11486
|
-
return true;
|
|
11487
11538
|
}
|
|
11488
11539
|
else {
|
|
11489
11540
|
// string didn't match any beat effect syntax
|
|
@@ -15043,6 +15094,7 @@
|
|
|
15043
15094
|
this._trackCount = 0;
|
|
15044
15095
|
this._playbackInfos = [];
|
|
15045
15096
|
this._doubleBars = new Set();
|
|
15097
|
+
this._clefsPerTrack = new Map();
|
|
15046
15098
|
this._keySignatures = new Map();
|
|
15047
15099
|
this._beatTextChunksByTrack = new Map();
|
|
15048
15100
|
this._directionLookup = new Map();
|
|
@@ -15427,26 +15479,74 @@
|
|
|
15427
15479
|
mainStaff.capo = IOHelper.readInt32LE(this.data);
|
|
15428
15480
|
newTrack.color = GpBinaryHelpers.gpReadColor(this.data, false);
|
|
15429
15481
|
if (this._versionNumber >= 500) {
|
|
15430
|
-
const
|
|
15431
|
-
mainStaff.showTablature = (
|
|
15432
|
-
mainStaff.showStandardNotation = (
|
|
15433
|
-
const showChordDiagramListOnTopOfScore = (
|
|
15482
|
+
const staffFlags = this.data.readByte();
|
|
15483
|
+
mainStaff.showTablature = (staffFlags & 0x01) !== 0;
|
|
15484
|
+
mainStaff.showStandardNotation = (staffFlags & 0x02) !== 0;
|
|
15485
|
+
const showChordDiagramListOnTopOfScore = (staffFlags & 0x64) !== 0;
|
|
15434
15486
|
if (this._score.stylesheet.perTrackChordDiagramsOnTop === null) {
|
|
15435
15487
|
this._score.stylesheet.perTrackChordDiagramsOnTop = new Map();
|
|
15436
15488
|
}
|
|
15437
15489
|
this._score.stylesheet.perTrackChordDiagramsOnTop.set(newTrack.index, showChordDiagramListOnTopOfScore);
|
|
15438
|
-
//
|
|
15490
|
+
// MIDI: Automatic
|
|
15491
|
+
// 0x01 -> always set (unknown)
|
|
15439
15492
|
// 0x02 -> auto let ring
|
|
15440
15493
|
// 0x04 -> auto brush
|
|
15441
15494
|
this.data.readByte();
|
|
15442
|
-
//
|
|
15443
|
-
|
|
15495
|
+
// RSE: Auto-Accentuation on the Beat
|
|
15496
|
+
// 0 - None
|
|
15497
|
+
// 1 - Very Soft
|
|
15498
|
+
// 2 - Soft
|
|
15499
|
+
// 3 - Medium
|
|
15500
|
+
// 4 - Strong
|
|
15501
|
+
// 5 - Very Strong
|
|
15502
|
+
this.data.readByte();
|
|
15503
|
+
newTrack.playbackInfo.bank = this.data.readByte();
|
|
15504
|
+
// RSE: Human Playing (1 byte, 0-100%)
|
|
15505
|
+
this.data.readByte();
|
|
15506
|
+
// `12` for all tunings which have bass clefs
|
|
15507
|
+
const clefMode = IOHelper.readInt32LE(this.data);
|
|
15508
|
+
if (clefMode === 12) {
|
|
15509
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15510
|
+
}
|
|
15511
|
+
else {
|
|
15512
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15513
|
+
}
|
|
15514
|
+
// Unknown, no UI setting seem to affect this
|
|
15515
|
+
IOHelper.readInt32LE(this.data);
|
|
15516
|
+
// Unknown, no UI setting seem to affect this
|
|
15517
|
+
// typically: 100
|
|
15518
|
+
IOHelper.readInt32LE(this.data);
|
|
15519
|
+
// Unknown, no UI setting seem to affect this
|
|
15520
|
+
// typically: 1 2 3 4 5 6 7 8 9 10
|
|
15521
|
+
this.data.skip(10);
|
|
15522
|
+
// Unknown, no UI setting seem to affect this
|
|
15523
|
+
// typically: 255
|
|
15524
|
+
this.data.readByte();
|
|
15525
|
+
// Unknown, no UI setting seem to affect this
|
|
15526
|
+
// typically: 3
|
|
15527
|
+
this.data.readByte();
|
|
15528
|
+
this.readRseBank();
|
|
15529
|
+
// this.data.skip(42);
|
|
15530
|
+
if (this._versionNumber >= 510) {
|
|
15531
|
+
// RSE: 3-band EQ
|
|
15532
|
+
// 1 byte Low
|
|
15533
|
+
// 1 byte Mid
|
|
15534
|
+
// 1 byte High
|
|
15535
|
+
// 1 byte PRE
|
|
15536
|
+
this.data.skip(4);
|
|
15537
|
+
// RSE: effect name
|
|
15538
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15539
|
+
// RSE: effect category
|
|
15540
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15541
|
+
}
|
|
15444
15542
|
}
|
|
15445
|
-
|
|
15446
|
-
|
|
15447
|
-
|
|
15448
|
-
|
|
15449
|
-
|
|
15543
|
+
else {
|
|
15544
|
+
if (GeneralMidi.isBass(newTrack.playbackInfo.program)) {
|
|
15545
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15546
|
+
}
|
|
15547
|
+
else {
|
|
15548
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15549
|
+
}
|
|
15450
15550
|
}
|
|
15451
15551
|
}
|
|
15452
15552
|
readBars() {
|
|
@@ -15462,6 +15562,9 @@
|
|
|
15462
15562
|
if (mainStaff.isPercussion) {
|
|
15463
15563
|
newBar.clef = Clef.Neutral;
|
|
15464
15564
|
}
|
|
15565
|
+
else if (this._clefsPerTrack.has(track.index)) {
|
|
15566
|
+
newBar.clef = this._clefsPerTrack.get(track.index);
|
|
15567
|
+
}
|
|
15465
15568
|
mainStaff.addBar(newBar);
|
|
15466
15569
|
if (this._keySignatures.has(newBar.index)) {
|
|
15467
15570
|
const newKeySignature = this._keySignatures.get(newBar.index);
|
|
@@ -15883,11 +15986,29 @@
|
|
|
15883
15986
|
return 0;
|
|
15884
15987
|
}
|
|
15885
15988
|
}
|
|
15989
|
+
readRseBank() {
|
|
15990
|
+
// RSE Banks on disk are having filenames like this: 033_2_002.ini
|
|
15991
|
+
// 033 is the RSE instrument (selected in the instrument list)
|
|
15992
|
+
// 2 seem to be some sort of style variation. e.g. bass has multiple variations (1,2), guitars have only 1, percussion has only 0
|
|
15993
|
+
// likely for organizational purposes
|
|
15994
|
+
// 002 is the effective soundbank (selected in the soundbank dropdown)
|
|
15995
|
+
// RSE Instrument
|
|
15996
|
+
this.data.skip(4); // IOHelper.readInt32LE(this.data);
|
|
15997
|
+
// RSE Style/Variation
|
|
15998
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15999
|
+
// RSE Soundbank
|
|
16000
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
16001
|
+
// Unknown, no UI setting seem to affect this
|
|
16002
|
+
// typically: -1
|
|
16003
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
16004
|
+
}
|
|
15886
16005
|
readMixTableChange(beat) {
|
|
15887
16006
|
const tableChange = new MixTableChange();
|
|
15888
16007
|
tableChange.instrument = IOHelper.readSInt8(this.data);
|
|
16008
|
+
// NOTE: The UI shows a Midi Bank selection, but this information is not stored in the file
|
|
16009
|
+
// when reopening the file the bank is always 0
|
|
15889
16010
|
if (this._versionNumber >= 500) {
|
|
15890
|
-
this.
|
|
16011
|
+
this.readRseBank();
|
|
15891
16012
|
}
|
|
15892
16013
|
tableChange.volume = IOHelper.readSInt8(this.data);
|
|
15893
16014
|
tableChange.balance = IOHelper.readSInt8(this.data);
|
|
@@ -15899,7 +16020,7 @@
|
|
|
15899
16020
|
tableChange.tempoName = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15900
16021
|
}
|
|
15901
16022
|
tableChange.tempo = IOHelper.readInt32LE(this.data);
|
|
15902
|
-
// durations
|
|
16023
|
+
// durations (in number of beats)
|
|
15903
16024
|
if (tableChange.volume >= 0) {
|
|
15904
16025
|
this.data.readByte();
|
|
15905
16026
|
}
|
|
@@ -16882,9 +17003,7 @@
|
|
|
16882
17003
|
return writer.toArray();
|
|
16883
17004
|
}
|
|
16884
17005
|
static addHeaderAndFooter(binaryStylesheet, style, prefix, name) {
|
|
16885
|
-
|
|
16886
|
-
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16887
|
-
}
|
|
17006
|
+
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16888
17007
|
binaryStylesheet.addValue(`${prefix}${name}Alignment`, style.textAlign, DataType.Integer);
|
|
16889
17008
|
if (style.isVisible !== undefined) {
|
|
16890
17009
|
binaryStylesheet.addValue(`${prefix}draw${name}`, style.isVisible, DataType.Boolean);
|
|
@@ -16918,6 +17037,7 @@
|
|
|
16918
17037
|
this.path = '';
|
|
16919
17038
|
this.role = '';
|
|
16920
17039
|
this.program = 0;
|
|
17040
|
+
this.bank = 0;
|
|
16921
17041
|
}
|
|
16922
17042
|
get uniqueId() {
|
|
16923
17043
|
return `${this.path};${this.name};${this.role}`;
|
|
@@ -17272,21 +17392,28 @@
|
|
|
17272
17392
|
if (!type) {
|
|
17273
17393
|
return;
|
|
17274
17394
|
}
|
|
17275
|
-
|
|
17395
|
+
const newAutomations = [];
|
|
17276
17396
|
switch (type) {
|
|
17277
17397
|
case 'Tempo':
|
|
17278
|
-
|
|
17398
|
+
newAutomations.push(Automation.buildTempoAutomation(isLinear, ratioPosition, numberValue, reference));
|
|
17279
17399
|
break;
|
|
17280
17400
|
case 'SyncPoint':
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
|
|
17284
|
-
|
|
17285
|
-
|
|
17401
|
+
const syncPoint = new Automation();
|
|
17402
|
+
syncPoint.type = AutomationType.SyncPoint;
|
|
17403
|
+
syncPoint.isLinear = isLinear;
|
|
17404
|
+
syncPoint.ratioPosition = ratioPosition;
|
|
17405
|
+
syncPoint.syncPointValue = syncPointValue;
|
|
17406
|
+
newAutomations.push(syncPoint);
|
|
17286
17407
|
break;
|
|
17287
17408
|
case 'Sound':
|
|
17288
17409
|
if (textValue && sounds && sounds.has(textValue)) {
|
|
17289
|
-
|
|
17410
|
+
const bankChange = new Automation();
|
|
17411
|
+
bankChange.type = AutomationType.Bank;
|
|
17412
|
+
bankChange.ratioPosition = ratioPosition;
|
|
17413
|
+
bankChange.value = sounds.get(textValue).bank;
|
|
17414
|
+
newAutomations.push(bankChange);
|
|
17415
|
+
const programChange = Automation.buildInstrumentAutomation(isLinear, ratioPosition, sounds.get(textValue).program);
|
|
17416
|
+
newAutomations.push(programChange);
|
|
17290
17417
|
}
|
|
17291
17418
|
break;
|
|
17292
17419
|
case 'SustainPedal':
|
|
@@ -17314,15 +17441,19 @@
|
|
|
17314
17441
|
}
|
|
17315
17442
|
break;
|
|
17316
17443
|
}
|
|
17317
|
-
if (
|
|
17444
|
+
if (newAutomations.length) {
|
|
17318
17445
|
if (text) {
|
|
17319
|
-
|
|
17446
|
+
for (const a of newAutomations) {
|
|
17447
|
+
a.text = text;
|
|
17448
|
+
}
|
|
17320
17449
|
}
|
|
17321
17450
|
if (barIndex >= 0) {
|
|
17322
17451
|
if (!automations.has(barIndex)) {
|
|
17323
17452
|
automations.set(barIndex, []);
|
|
17324
17453
|
}
|
|
17325
|
-
|
|
17454
|
+
for (const a of newAutomations) {
|
|
17455
|
+
automations.get(barIndex).push(a);
|
|
17456
|
+
}
|
|
17326
17457
|
}
|
|
17327
17458
|
}
|
|
17328
17459
|
}
|
|
@@ -17914,22 +18045,31 @@
|
|
|
17914
18045
|
break;
|
|
17915
18046
|
}
|
|
17916
18047
|
}
|
|
17917
|
-
if (sound.role === 'Factory' || track.playbackInfo.program === 0) {
|
|
17918
|
-
track.playbackInfo.program = sound.program;
|
|
17919
|
-
}
|
|
17920
18048
|
if (!this._soundsByTrack.has(trackId)) {
|
|
17921
18049
|
this._soundsByTrack.set(trackId, new Map());
|
|
18050
|
+
// apply first sound
|
|
18051
|
+
track.playbackInfo.program = sound.program;
|
|
18052
|
+
track.playbackInfo.bank = sound.bank;
|
|
17922
18053
|
}
|
|
17923
18054
|
this._soundsByTrack.get(trackId).set(sound.uniqueId, sound);
|
|
17924
18055
|
}
|
|
17925
18056
|
parseSoundMidi(sound, node) {
|
|
18057
|
+
let bankMsb = 0;
|
|
18058
|
+
let bankLsb = 0;
|
|
17926
18059
|
for (const c of node.childElements()) {
|
|
17927
18060
|
switch (c.localName) {
|
|
17928
18061
|
case 'Program':
|
|
17929
18062
|
sound.program = GpifParser.parseIntSafe(c.innerText, 0);
|
|
17930
18063
|
break;
|
|
18064
|
+
case 'MSB': // coarse
|
|
18065
|
+
bankMsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18066
|
+
break;
|
|
18067
|
+
case 'LSB': // Fine
|
|
18068
|
+
bankLsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18069
|
+
break;
|
|
17931
18070
|
}
|
|
17932
18071
|
}
|
|
18072
|
+
sound.bank = ((bankMsb & 0x7f) << 7) | bankLsb;
|
|
17933
18073
|
}
|
|
17934
18074
|
parsePartSounding(trackId, track, node) {
|
|
17935
18075
|
for (const c of node.childElements()) {
|
|
@@ -19383,7 +19523,12 @@
|
|
|
19383
19523
|
for (const a of automations) {
|
|
19384
19524
|
// NOTE: currently the automations of a bar are applied to the
|
|
19385
19525
|
// first beat of a bar
|
|
19386
|
-
|
|
19526
|
+
const skip =
|
|
19527
|
+
// skip bank automations if they are 0 at start
|
|
19528
|
+
a.type === AutomationType.Bank && a.value === 0 && bar.index === 0;
|
|
19529
|
+
if (!skip) {
|
|
19530
|
+
beat.automations.push(a);
|
|
19531
|
+
}
|
|
19387
19532
|
}
|
|
19388
19533
|
}
|
|
19389
19534
|
}
|
|
@@ -20403,6 +20548,10 @@
|
|
|
20403
20548
|
* The midi channel program to use when playing the note (-1 if using the default track program).
|
|
20404
20549
|
*/
|
|
20405
20550
|
this.outputMidiProgram = -1;
|
|
20551
|
+
/**
|
|
20552
|
+
* The midi bank to use when playing the note (-1 if using the default track bank).
|
|
20553
|
+
*/
|
|
20554
|
+
this.outputMidiBank = -1;
|
|
20406
20555
|
/**
|
|
20407
20556
|
* The volume to use when playing the note (-1 if using the default track volume).
|
|
20408
20557
|
*/
|
|
@@ -20901,6 +21050,9 @@
|
|
|
20901
21050
|
if (trackInfo.firstArticulation.outputMidiProgram >= 0) {
|
|
20902
21051
|
track.playbackInfo.program = trackInfo.firstArticulation.outputMidiProgram;
|
|
20903
21052
|
}
|
|
21053
|
+
if (trackInfo.firstArticulation.outputMidiBank >= 0) {
|
|
21054
|
+
track.playbackInfo.bank = trackInfo.firstArticulation.outputMidiBank;
|
|
21055
|
+
}
|
|
20904
21056
|
if (trackInfo.firstArticulation.outputBalance >= 0) {
|
|
20905
21057
|
track.playbackInfo.balance = trackInfo.firstArticulation.outputBalance;
|
|
20906
21058
|
}
|
|
@@ -20932,7 +21084,9 @@
|
|
|
20932
21084
|
articulation.outputMidiChannel = Number.parseInt(c.innerText) - 1;
|
|
20933
21085
|
break;
|
|
20934
21086
|
// case 'midi-name': Ignored
|
|
20935
|
-
|
|
21087
|
+
case 'midi-bank':
|
|
21088
|
+
articulation.outputMidiBank = Number.parseInt(c.innerText) - 1;
|
|
21089
|
+
break;
|
|
20936
21090
|
case 'midi-program':
|
|
20937
21091
|
articulation.outputMidiProgram = Number.parseInt(c.innerText) - 1;
|
|
20938
21092
|
break;
|
|
@@ -21462,7 +21616,15 @@
|
|
|
21462
21616
|
switch (c.localName) {
|
|
21463
21617
|
// case 'midi-channel': Ignored
|
|
21464
21618
|
// case 'midi-name': Ignored
|
|
21465
|
-
|
|
21619
|
+
case 'midi-bank':
|
|
21620
|
+
if (!this._nextBeatAutomations) {
|
|
21621
|
+
this._nextBeatAutomations = [];
|
|
21622
|
+
}
|
|
21623
|
+
automation = new Automation();
|
|
21624
|
+
automation.type = AutomationType.Bank;
|
|
21625
|
+
automation.value = Number.parseInt(c.innerText) - 1;
|
|
21626
|
+
this._nextBeatAutomations.push(automation);
|
|
21627
|
+
break;
|
|
21466
21628
|
case 'midi-program':
|
|
21467
21629
|
if (!this._nextBeatAutomations) {
|
|
21468
21630
|
this._nextBeatAutomations = [];
|
|
@@ -23733,11 +23895,15 @@
|
|
|
23733
23895
|
}
|
|
23734
23896
|
|
|
23735
23897
|
class EventEmitter {
|
|
23736
|
-
constructor() {
|
|
23898
|
+
constructor(fireOnRegister = undefined) {
|
|
23737
23899
|
this._listeners = [];
|
|
23900
|
+
this._fireOnRegister = fireOnRegister;
|
|
23738
23901
|
}
|
|
23739
23902
|
on(value) {
|
|
23740
23903
|
this._listeners.push(value);
|
|
23904
|
+
if (this._fireOnRegister?.()) {
|
|
23905
|
+
value();
|
|
23906
|
+
}
|
|
23741
23907
|
return () => {
|
|
23742
23908
|
this.off(value);
|
|
23743
23909
|
};
|
|
@@ -23755,11 +23921,18 @@
|
|
|
23755
23921
|
* @partial
|
|
23756
23922
|
*/
|
|
23757
23923
|
class EventEmitterOfT {
|
|
23758
|
-
constructor() {
|
|
23924
|
+
constructor(fireOnRegister = undefined) {
|
|
23759
23925
|
this._listeners = [];
|
|
23926
|
+
this._fireOnRegister = fireOnRegister;
|
|
23760
23927
|
}
|
|
23761
23928
|
on(value) {
|
|
23762
23929
|
this._listeners.push(value);
|
|
23930
|
+
if (this._fireOnRegister) {
|
|
23931
|
+
const arg = this._fireOnRegister();
|
|
23932
|
+
if (arg !== null) {
|
|
23933
|
+
value(arg);
|
|
23934
|
+
}
|
|
23935
|
+
}
|
|
23763
23936
|
return () => {
|
|
23764
23937
|
this.off(value);
|
|
23765
23938
|
};
|
|
@@ -30800,6 +30973,12 @@
|
|
|
30800
30973
|
this.sequencer.playbackSpeed = value;
|
|
30801
30974
|
this.timePosition = this.timePosition * (oldSpeed / value);
|
|
30802
30975
|
}
|
|
30976
|
+
get loadedMidiInfo() {
|
|
30977
|
+
return this._loadedMidiInfo;
|
|
30978
|
+
}
|
|
30979
|
+
get currentPosition() {
|
|
30980
|
+
return this._currentPosition;
|
|
30981
|
+
}
|
|
30803
30982
|
get tickPosition() {
|
|
30804
30983
|
return this._tickPosition;
|
|
30805
30984
|
}
|
|
@@ -30857,22 +31036,38 @@
|
|
|
30857
31036
|
this._midiEventsPlayedFilter = new Set();
|
|
30858
31037
|
this._notPlayedSamples = 0;
|
|
30859
31038
|
this._synthStopping = false;
|
|
31039
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
30860
31040
|
this.isReady = false;
|
|
30861
31041
|
this.state = PlayerState.Paused;
|
|
30862
31042
|
this._loadedSoundFonts = [];
|
|
30863
|
-
this.ready = new EventEmitter();
|
|
30864
31043
|
this.readyForPlayback = new EventEmitter();
|
|
30865
31044
|
this.finished = new EventEmitter();
|
|
30866
31045
|
this.soundFontLoaded = new EventEmitter();
|
|
30867
31046
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
30868
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
30869
31047
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
30870
|
-
this.stateChanged = new EventEmitterOfT();
|
|
30871
|
-
this.positionChanged = new EventEmitterOfT();
|
|
30872
31048
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
30873
|
-
this.playbackRangeChanged = new EventEmitterOfT();
|
|
30874
31049
|
Logger.debug('AlphaSynth', 'Initializing player');
|
|
30875
31050
|
this.state = PlayerState.Paused;
|
|
31051
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
31052
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
31053
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
31054
|
+
if (this._loadedMidiInfo) {
|
|
31055
|
+
return this._loadedMidiInfo;
|
|
31056
|
+
}
|
|
31057
|
+
return null;
|
|
31058
|
+
});
|
|
31059
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
31060
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
31061
|
+
});
|
|
31062
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
31063
|
+
return this._currentPosition;
|
|
31064
|
+
});
|
|
31065
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
31066
|
+
if (this.playbackRange) {
|
|
31067
|
+
return new PlaybackRangeChangedEventArgs(this.playbackRange);
|
|
31068
|
+
}
|
|
31069
|
+
return null;
|
|
31070
|
+
});
|
|
30876
31071
|
Logger.debug('AlphaSynth', 'Creating output');
|
|
30877
31072
|
this._output = output;
|
|
30878
31073
|
Logger.debug('AlphaSynth', 'Creating synthesizer');
|
|
@@ -31050,7 +31245,8 @@
|
|
|
31050
31245
|
Logger.debug('AlphaSynth', 'Loading midi from model');
|
|
31051
31246
|
this.sequencer.loadMidi(midi);
|
|
31052
31247
|
this._isMidiLoaded = true;
|
|
31053
|
-
this.
|
|
31248
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(0, this.sequencer.currentEndTime, 0, this.sequencer.currentEndTick, false, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31249
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
31054
31250
|
Logger.debug('AlphaSynth', 'Midi successfully loaded');
|
|
31055
31251
|
this.checkReadyForPlayback();
|
|
31056
31252
|
this.tickPosition = 0;
|
|
@@ -31153,23 +31349,28 @@
|
|
|
31153
31349
|
this.sequencer.resetOneTimeMidi();
|
|
31154
31350
|
this.timePosition = this.sequencer.currentTime;
|
|
31155
31351
|
}
|
|
31156
|
-
|
|
31157
|
-
//
|
|
31158
|
-
let currentTime =
|
|
31159
|
-
this._timePosition = currentTime;
|
|
31352
|
+
createPositionChangedEventArgs(isSeek) {
|
|
31353
|
+
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31354
|
+
let currentTime = this._timePosition;
|
|
31160
31355
|
let currentTick = this.sequencer.currentTimePositionToTickPosition(currentTime);
|
|
31161
|
-
this._tickPosition = currentTick;
|
|
31162
31356
|
const endTime = this.sequencer.currentEndTime;
|
|
31163
31357
|
const endTick = this.sequencer.currentEndTick;
|
|
31164
|
-
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31165
31358
|
if (currentTime > endTime) {
|
|
31166
31359
|
currentTime = endTime;
|
|
31167
31360
|
currentTick = endTick;
|
|
31168
31361
|
}
|
|
31362
|
+
return new PositionChangedEventArgs(currentTime, endTime, currentTick, endTick, isSeek, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31363
|
+
}
|
|
31364
|
+
updateTimePosition(timePosition, isSeek) {
|
|
31365
|
+
// update the real positions
|
|
31366
|
+
this._timePosition = timePosition;
|
|
31367
|
+
const args = this.createPositionChangedEventArgs(isSeek);
|
|
31368
|
+
this._tickPosition = args.currentTick;
|
|
31169
31369
|
const mode = this.sequencer.isPlayingMain ? 'main' : this.sequencer.isPlayingCountIn ? 'count-in' : 'one-time';
|
|
31170
|
-
Logger.debug('AlphaSynth', `Position changed: (time: ${currentTime}/${endTime}, tick: ${currentTick}/${endTick}, Active Voices: ${this.synthesizer.activeVoiceCount} (${mode}), Tempo original: ${this.sequencer.currentTempo}, Tempo modified: ${this.sequencer.modifiedTempo})`);
|
|
31370
|
+
Logger.debug('AlphaSynth', `Position changed: (time: ${args.currentTime}/${args.endTime}, tick: ${args.currentTick}/${args.endTick}, Active Voices: ${this.synthesizer.activeVoiceCount} (${mode}), Tempo original: ${this.sequencer.currentTempo}, Tempo modified: ${this.sequencer.modifiedTempo})`);
|
|
31171
31371
|
if (this.sequencer.isPlayingMain) {
|
|
31172
|
-
this.
|
|
31372
|
+
this._currentPosition = args;
|
|
31373
|
+
this.positionChanged.trigger(args);
|
|
31173
31374
|
}
|
|
31174
31375
|
// build events which were actually played
|
|
31175
31376
|
if (isSeek) {
|
|
@@ -31177,7 +31378,7 @@
|
|
|
31177
31378
|
}
|
|
31178
31379
|
else {
|
|
31179
31380
|
const playedEvents = [];
|
|
31180
|
-
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < currentTime) {
|
|
31381
|
+
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < args.currentTime) {
|
|
31181
31382
|
const synthEvent = this._playedEventsQueue.dequeue();
|
|
31182
31383
|
playedEvents.push(synthEvent.event);
|
|
31183
31384
|
}
|
|
@@ -36628,6 +36829,15 @@
|
|
|
36628
36829
|
fillFromJson(json) {
|
|
36629
36830
|
SettingsSerializer.fromJson(this, json);
|
|
36630
36831
|
}
|
|
36832
|
+
/**
|
|
36833
|
+
* handles backwards compatibility aspects on the settings, removed in 2.0
|
|
36834
|
+
* @internal
|
|
36835
|
+
*/
|
|
36836
|
+
handleBackwardsCompatibility() {
|
|
36837
|
+
if (this.player.playerMode === exports.PlayerMode.Disabled && this.player.enablePlayer) {
|
|
36838
|
+
this.player.playerMode = exports.PlayerMode.EnabledAutomatic;
|
|
36839
|
+
}
|
|
36840
|
+
}
|
|
36631
36841
|
}
|
|
36632
36842
|
|
|
36633
36843
|
class SectionSerializer {
|
|
@@ -37845,6 +38055,7 @@
|
|
|
37845
38055
|
o.set("balance", obj.balance);
|
|
37846
38056
|
o.set("port", obj.port);
|
|
37847
38057
|
o.set("program", obj.program);
|
|
38058
|
+
o.set("bank", obj.bank);
|
|
37848
38059
|
o.set("primarychannel", obj.primaryChannel);
|
|
37849
38060
|
o.set("secondarychannel", obj.secondaryChannel);
|
|
37850
38061
|
o.set("ismute", obj.isMute);
|
|
@@ -37865,6 +38076,9 @@
|
|
|
37865
38076
|
case "program":
|
|
37866
38077
|
obj.program = v;
|
|
37867
38078
|
return true;
|
|
38079
|
+
case "bank":
|
|
38080
|
+
obj.bank = v;
|
|
38081
|
+
return true;
|
|
37868
38082
|
case "primarychannel":
|
|
37869
38083
|
obj.primaryChannel = v;
|
|
37870
38084
|
return true;
|
|
@@ -41523,6 +41737,11 @@
|
|
|
41523
41737
|
this._programsPerChannel.set(channel, program);
|
|
41524
41738
|
}
|
|
41525
41739
|
}
|
|
41740
|
+
addBankChange(track, tick, channel, bank) {
|
|
41741
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
41742
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectCoarse, lsbMsb[1]);
|
|
41743
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectFine, lsbMsb[0]);
|
|
41744
|
+
}
|
|
41526
41745
|
static buildTranspositionPitches(score, settings) {
|
|
41527
41746
|
const transpositionPitches = new Map();
|
|
41528
41747
|
for (const track of score.tracks) {
|
|
@@ -41550,6 +41769,7 @@
|
|
|
41550
41769
|
// Set PitchBendRangeCoarse to 12
|
|
41551
41770
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryFine, 0);
|
|
41552
41771
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryCoarse, MidiFileGenerator.PitchBendRangeInSemitones);
|
|
41772
|
+
this.addBankChange(track, 0, channel, playbackInfo.bank);
|
|
41553
41773
|
this.addProgramChange(track, 0, channel, playbackInfo.program);
|
|
41554
41774
|
}
|
|
41555
41775
|
/**
|
|
@@ -42845,6 +43065,10 @@
|
|
|
42845
43065
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, (automation.value | 0) & 0xff);
|
|
42846
43066
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, (automation.value | 0) & 0xff);
|
|
42847
43067
|
break;
|
|
43068
|
+
case AutomationType.Bank:
|
|
43069
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, automation.value);
|
|
43070
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, automation.value);
|
|
43071
|
+
break;
|
|
42848
43072
|
case AutomationType.Balance:
|
|
42849
43073
|
const balance = MidiFileGenerator.toChannelShort(automation.value);
|
|
42850
43074
|
this._handler.addControlChange(beat.voice.bar.staff.track.index, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, ControllerType.PanCoarse, balance);
|
|
@@ -43794,17 +44018,29 @@
|
|
|
43794
44018
|
this._playbackSpeed = 1;
|
|
43795
44019
|
this._isLooping = false;
|
|
43796
44020
|
this._midiEventsPlayedFilter = [];
|
|
43797
|
-
this.ready = new EventEmitter();
|
|
43798
|
-
this.readyForPlayback = new EventEmitter();
|
|
43799
44021
|
this.finished = new EventEmitter();
|
|
43800
44022
|
this.soundFontLoaded = new EventEmitter();
|
|
43801
44023
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
43802
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
43803
44024
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
43804
|
-
this.stateChanged = new EventEmitterOfT();
|
|
43805
|
-
this.positionChanged = new EventEmitterOfT();
|
|
43806
44025
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
43807
|
-
this.
|
|
44026
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
44027
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
44028
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
44029
|
+
return this._instance?.loadedMidiInfo ?? null;
|
|
44030
|
+
});
|
|
44031
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
44032
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
44033
|
+
});
|
|
44034
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
44035
|
+
return this.currentPosition;
|
|
44036
|
+
});
|
|
44037
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
44038
|
+
const range = this.playbackRange;
|
|
44039
|
+
if (range) {
|
|
44040
|
+
return new PlaybackRangeChangedEventArgs(range);
|
|
44041
|
+
}
|
|
44042
|
+
return null;
|
|
44043
|
+
});
|
|
43808
44044
|
}
|
|
43809
44045
|
get instance() {
|
|
43810
44046
|
return this._instance;
|
|
@@ -43826,10 +44062,14 @@
|
|
|
43826
44062
|
newUnregister.push(value.finished.on(() => this.finished.trigger()));
|
|
43827
44063
|
newUnregister.push(value.soundFontLoaded.on(() => this.soundFontLoaded.trigger()));
|
|
43828
44064
|
newUnregister.push(value.soundFontLoadFailed.on(e => this.soundFontLoadFailed.trigger(e)));
|
|
43829
|
-
newUnregister.push(value.midiLoaded.on(e =>
|
|
44065
|
+
newUnregister.push(value.midiLoaded.on(e => {
|
|
44066
|
+
this.midiLoaded.trigger(e);
|
|
44067
|
+
}));
|
|
43830
44068
|
newUnregister.push(value.midiLoadFailed.on(e => this.midiLoadFailed.trigger(e)));
|
|
43831
44069
|
newUnregister.push(value.stateChanged.on(e => this.stateChanged.trigger(e)));
|
|
43832
|
-
newUnregister.push(value.positionChanged.on(e =>
|
|
44070
|
+
newUnregister.push(value.positionChanged.on(e => {
|
|
44071
|
+
this.positionChanged.trigger(e);
|
|
44072
|
+
}));
|
|
43833
44073
|
newUnregister.push(value.midiEventsPlayed.on(e => this.midiEventsPlayed.trigger(e)));
|
|
43834
44074
|
newUnregister.push(value.playbackRangeChanged.on(e => this.playbackRangeChanged.trigger(e)));
|
|
43835
44075
|
this._instanceEventUnregister = newUnregister;
|
|
@@ -43908,6 +44148,14 @@
|
|
|
43908
44148
|
this._instance.playbackSpeed = value;
|
|
43909
44149
|
}
|
|
43910
44150
|
}
|
|
44151
|
+
get loadedMidiInfo() {
|
|
44152
|
+
return this._instance ? this._instance.loadedMidiInfo : undefined;
|
|
44153
|
+
}
|
|
44154
|
+
get currentPosition() {
|
|
44155
|
+
return this._instance
|
|
44156
|
+
? this._instance.currentPosition
|
|
44157
|
+
: new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
44158
|
+
}
|
|
43911
44159
|
get tickPosition() {
|
|
43912
44160
|
return this._instance ? this._instance.tickPosition : 0;
|
|
43913
44161
|
}
|
|
@@ -44249,83 +44497,6 @@
|
|
|
44249
44497
|
this._previousStateForCursor = PlayerState.Paused;
|
|
44250
44498
|
this._previousCursorCache = null;
|
|
44251
44499
|
this._lastScroll = 0;
|
|
44252
|
-
/**
|
|
44253
|
-
* This event is fired when the played beat changed.
|
|
44254
|
-
*
|
|
44255
|
-
* @eventProperty
|
|
44256
|
-
* @category Events - Player
|
|
44257
|
-
* @since 0.9.4
|
|
44258
|
-
*
|
|
44259
|
-
* @example
|
|
44260
|
-
* JavaScript
|
|
44261
|
-
* ```js
|
|
44262
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44263
|
-
* api.playedBeatChanged.on((beat) => {
|
|
44264
|
-
* updateFretboard(beat);
|
|
44265
|
-
* });
|
|
44266
|
-
* ```
|
|
44267
|
-
*
|
|
44268
|
-
* @example
|
|
44269
|
-
* C#
|
|
44270
|
-
* ```cs
|
|
44271
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44272
|
-
* api.PlayedBeatChanged.On(beat =>
|
|
44273
|
-
* {
|
|
44274
|
-
* UpdateFretboard(beat);
|
|
44275
|
-
* });
|
|
44276
|
-
* ```
|
|
44277
|
-
*
|
|
44278
|
-
* @example
|
|
44279
|
-
* Android
|
|
44280
|
-
* ```kotlin
|
|
44281
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44282
|
-
* api.playedBeatChanged.on { beat ->
|
|
44283
|
-
* updateFretboard(beat)
|
|
44284
|
-
* }
|
|
44285
|
-
* ```
|
|
44286
|
-
*
|
|
44287
|
-
*/
|
|
44288
|
-
this.playedBeatChanged = new EventEmitterOfT();
|
|
44289
|
-
/**
|
|
44290
|
-
* This event is fired when the currently active beats across all tracks change.
|
|
44291
|
-
*
|
|
44292
|
-
* @remarks
|
|
44293
|
-
* Unlike the {@link playedBeatChanged} event this event contains the beats of all tracks and voices independent of them being rendered.
|
|
44294
|
-
*
|
|
44295
|
-
* @eventProperty
|
|
44296
|
-
* @category Events - Player
|
|
44297
|
-
* @since 1.2.3
|
|
44298
|
-
*
|
|
44299
|
-
* @example
|
|
44300
|
-
* JavaScript
|
|
44301
|
-
* ```js
|
|
44302
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44303
|
-
* api.activeBeatsChanged.on(args => {
|
|
44304
|
-
* updateHighlights(args.activeBeats);
|
|
44305
|
-
* });
|
|
44306
|
-
* ```
|
|
44307
|
-
*
|
|
44308
|
-
* @example
|
|
44309
|
-
* C#
|
|
44310
|
-
* ```cs
|
|
44311
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44312
|
-
* api.ActiveBeatsChanged.On(args =>
|
|
44313
|
-
* {
|
|
44314
|
-
* UpdateHighlights(args.ActiveBeats);
|
|
44315
|
-
* });
|
|
44316
|
-
* ```
|
|
44317
|
-
*
|
|
44318
|
-
* @example
|
|
44319
|
-
* Android
|
|
44320
|
-
* ```kotlin
|
|
44321
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44322
|
-
* api.activeBeatsChanged.on { args ->
|
|
44323
|
-
* updateHighlights(args.activeBeats)
|
|
44324
|
-
* }
|
|
44325
|
-
* ```
|
|
44326
|
-
*
|
|
44327
|
-
*/
|
|
44328
|
-
this.activeBeatsChanged = new EventEmitterOfT();
|
|
44329
44500
|
this._beatMouseDown = false;
|
|
44330
44501
|
this._noteMouseDown = false;
|
|
44331
44502
|
this._selectionStart = null;
|
|
@@ -44564,47 +44735,6 @@
|
|
|
44564
44735
|
*
|
|
44565
44736
|
*/
|
|
44566
44737
|
this.noteMouseUp = new EventEmitterOfT();
|
|
44567
|
-
/**
|
|
44568
|
-
* This event is fired whenever a new song is loaded.
|
|
44569
|
-
* @remarks
|
|
44570
|
-
* This event is fired whenever a new song is loaded or changing due to {@link renderScore} or {@link renderTracks} calls.
|
|
44571
|
-
* It is fired after the transposition midi pitches from the settings were applied, but before any midi is generated or rendering is started.
|
|
44572
|
-
* This allows any modification of the score before further processing.
|
|
44573
|
-
*
|
|
44574
|
-
* @eventProperty
|
|
44575
|
-
* @category Events - Core
|
|
44576
|
-
* @since 0.9.4
|
|
44577
|
-
*
|
|
44578
|
-
* @example
|
|
44579
|
-
* JavaScript
|
|
44580
|
-
* ```js
|
|
44581
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44582
|
-
* api.scoreLoaded.on((score) => {
|
|
44583
|
-
* updateSongInformationInUi(score);
|
|
44584
|
-
* });
|
|
44585
|
-
* ```
|
|
44586
|
-
*
|
|
44587
|
-
* @example
|
|
44588
|
-
* C#
|
|
44589
|
-
* ```cs
|
|
44590
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44591
|
-
* api.ScoreLoaded.On(score =>
|
|
44592
|
-
* {
|
|
44593
|
-
* UpdateSongInformationInUi(score);
|
|
44594
|
-
* });
|
|
44595
|
-
* ```
|
|
44596
|
-
*
|
|
44597
|
-
* @example
|
|
44598
|
-
* Android
|
|
44599
|
-
* ```kotlin
|
|
44600
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44601
|
-
* api.scoreLoaded.on { score ->
|
|
44602
|
-
* updateSongInformationInUi(score)
|
|
44603
|
-
* }
|
|
44604
|
-
* ```
|
|
44605
|
-
*
|
|
44606
|
-
*/
|
|
44607
|
-
this.scoreLoaded = new EventEmitterOfT();
|
|
44608
44738
|
/**
|
|
44609
44739
|
* This event is fired when alphaTab was resized and is about to rerender the music notation.
|
|
44610
44740
|
* @remarks
|
|
@@ -44863,46 +44993,6 @@
|
|
|
44863
44993
|
*
|
|
44864
44994
|
*/
|
|
44865
44995
|
this.midiLoad = new EventEmitterOfT();
|
|
44866
|
-
/**
|
|
44867
|
-
* This event is fired when the Midi file needed for playback was loaded.
|
|
44868
|
-
*
|
|
44869
|
-
* @eventProperty
|
|
44870
|
-
* @category Events - Player
|
|
44871
|
-
* @since 0.9.4
|
|
44872
|
-
*
|
|
44873
|
-
* @example
|
|
44874
|
-
* JavaScript
|
|
44875
|
-
* ```js
|
|
44876
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44877
|
-
* api.midiLoaded.on(e => {
|
|
44878
|
-
* hideGeneratingAudioIndicator();
|
|
44879
|
-
* updateSongDuration(e.endTime);
|
|
44880
|
-
* });
|
|
44881
|
-
* ```
|
|
44882
|
-
*
|
|
44883
|
-
* @example
|
|
44884
|
-
* C#
|
|
44885
|
-
* ```cs
|
|
44886
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44887
|
-
* api.MidiLoaded.On(e =>
|
|
44888
|
-
* {
|
|
44889
|
-
* HideGeneratingAudioIndicator();
|
|
44890
|
-
* UpdateSongDuration(e.EndTime);
|
|
44891
|
-
* });
|
|
44892
|
-
* ```
|
|
44893
|
-
*
|
|
44894
|
-
* @example
|
|
44895
|
-
* Android
|
|
44896
|
-
* ```kotlin
|
|
44897
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44898
|
-
* api.midiLoaded.on { e ->
|
|
44899
|
-
* hideGeneratingAudioIndicator()
|
|
44900
|
-
* updateSongDuration(e.endTime)
|
|
44901
|
-
* }
|
|
44902
|
-
* ```
|
|
44903
|
-
*
|
|
44904
|
-
*/
|
|
44905
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
44906
44996
|
/**
|
|
44907
44997
|
* This event is fired when a settings update was requested.
|
|
44908
44998
|
*
|
|
@@ -44942,12 +45032,30 @@
|
|
|
44942
45032
|
this.settingsUpdated = new EventEmitter();
|
|
44943
45033
|
this.uiFacade = uiFacade;
|
|
44944
45034
|
this.container = uiFacade.rootContainer;
|
|
45035
|
+
this.activeBeatsChanged = new EventEmitterOfT(() => {
|
|
45036
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45037
|
+
return new ActiveBeatsChangedEventArgs(this._currentBeat.beatLookup.highlightedBeats.map(h => h.beat));
|
|
45038
|
+
}
|
|
45039
|
+
return null;
|
|
45040
|
+
});
|
|
45041
|
+
this.playedBeatChanged = new EventEmitterOfT(() => {
|
|
45042
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45043
|
+
return this._currentBeat.beat;
|
|
45044
|
+
}
|
|
45045
|
+
return null;
|
|
45046
|
+
});
|
|
45047
|
+
this.scoreLoaded = new EventEmitterOfT(() => {
|
|
45048
|
+
if (this._score) {
|
|
45049
|
+
return this._score;
|
|
45050
|
+
}
|
|
45051
|
+
return null;
|
|
45052
|
+
});
|
|
45053
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
45054
|
+
return this._player.loadedMidiInfo ?? null;
|
|
45055
|
+
});
|
|
44945
45056
|
uiFacade.initialize(this, settings);
|
|
44946
45057
|
Logger.logLevel = this.settings.core.logLevel;
|
|
44947
|
-
|
|
44948
|
-
if (this.settings.player.playerMode === exports.PlayerMode.Disabled && this.settings.player.enablePlayer) {
|
|
44949
|
-
this.settings.player.playerMode = exports.PlayerMode.EnabledAutomatic;
|
|
44950
|
-
}
|
|
45058
|
+
this.settings.handleBackwardsCompatibility();
|
|
44951
45059
|
Environment.printEnvironmentInfo(false);
|
|
44952
45060
|
this.canvasElement = uiFacade.createCanvasElement();
|
|
44953
45061
|
this.container.appendChild(this.canvasElement);
|
|
@@ -45106,6 +45214,7 @@
|
|
|
45106
45214
|
* ```
|
|
45107
45215
|
*/
|
|
45108
45216
|
updateSettings() {
|
|
45217
|
+
this.settings.handleBackwardsCompatibility();
|
|
45109
45218
|
const score = this.score;
|
|
45110
45219
|
if (score) {
|
|
45111
45220
|
ModelUtils.applyPitchOffsets(this.settings, score);
|
|
@@ -45913,6 +46022,22 @@
|
|
|
45913
46022
|
set timePosition(value) {
|
|
45914
46023
|
this._player.timePosition = value;
|
|
45915
46024
|
}
|
|
46025
|
+
/**
|
|
46026
|
+
* The total length of the song in midi ticks.
|
|
46027
|
+
* @category Properties - Player
|
|
46028
|
+
* @since 1.6.2
|
|
46029
|
+
*/
|
|
46030
|
+
get endTick() {
|
|
46031
|
+
return this._player.currentPosition.endTick;
|
|
46032
|
+
}
|
|
46033
|
+
/**
|
|
46034
|
+
* The total length of the song in milliseconds.
|
|
46035
|
+
* @category Properties - Player
|
|
46036
|
+
* @since 1.6.2
|
|
46037
|
+
*/
|
|
46038
|
+
get endTime() {
|
|
46039
|
+
return this._player.currentPosition.endTime;
|
|
46040
|
+
}
|
|
45916
46041
|
/**
|
|
45917
46042
|
* The range of the song that should be played.
|
|
45918
46043
|
* @remarks
|
|
@@ -48237,27 +48362,33 @@
|
|
|
48237
48362
|
value: value
|
|
48238
48363
|
});
|
|
48239
48364
|
}
|
|
48365
|
+
get loadedMidiInfo() {
|
|
48366
|
+
return this.loadedMidiInfo;
|
|
48367
|
+
}
|
|
48368
|
+
get currentPosition() {
|
|
48369
|
+
return this._currentPosition;
|
|
48370
|
+
}
|
|
48240
48371
|
get tickPosition() {
|
|
48241
|
-
return this.
|
|
48372
|
+
return this._currentPosition.currentTick;
|
|
48242
48373
|
}
|
|
48243
48374
|
set tickPosition(value) {
|
|
48244
48375
|
if (value < 0) {
|
|
48245
48376
|
value = 0;
|
|
48246
48377
|
}
|
|
48247
|
-
this.
|
|
48378
|
+
this._currentPosition = new PositionChangedEventArgs(this._currentPosition.currentTime, this._currentPosition.endTime, value, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48248
48379
|
this._synth.postMessage({
|
|
48249
48380
|
cmd: 'alphaSynth.setTickPosition',
|
|
48250
48381
|
value: value
|
|
48251
48382
|
});
|
|
48252
48383
|
}
|
|
48253
48384
|
get timePosition() {
|
|
48254
|
-
return this.
|
|
48385
|
+
return this._currentPosition.currentTime;
|
|
48255
48386
|
}
|
|
48256
48387
|
set timePosition(value) {
|
|
48257
48388
|
if (value < 0) {
|
|
48258
48389
|
value = 0;
|
|
48259
48390
|
}
|
|
48260
|
-
this.
|
|
48391
|
+
this._currentPosition = new PositionChangedEventArgs(value, this._currentPosition.endTime, this._currentPosition.currentTick, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48261
48392
|
this._synth.postMessage({
|
|
48262
48393
|
cmd: 'alphaSynth.setTimePosition',
|
|
48263
48394
|
value: value
|
|
@@ -48300,11 +48431,10 @@
|
|
|
48300
48431
|
this._metronomeVolume = 0;
|
|
48301
48432
|
this._countInVolume = 0;
|
|
48302
48433
|
this._playbackSpeed = 0;
|
|
48303
|
-
this._tickPosition = 0;
|
|
48304
|
-
this._timePosition = 0;
|
|
48305
48434
|
this._isLooping = false;
|
|
48306
48435
|
this._playbackRange = null;
|
|
48307
48436
|
this._midiEventsPlayedFilter = [];
|
|
48437
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
48308
48438
|
this.ready = new EventEmitter();
|
|
48309
48439
|
this.readyForPlayback = new EventEmitter();
|
|
48310
48440
|
this.finished = new EventEmitter();
|
|
@@ -48323,8 +48453,6 @@
|
|
|
48323
48453
|
this._masterVolume = 0.0;
|
|
48324
48454
|
this._metronomeVolume = 0.0;
|
|
48325
48455
|
this._playbackSpeed = 0.0;
|
|
48326
|
-
this._tickPosition = 0;
|
|
48327
|
-
this._timePosition = 0.0;
|
|
48328
48456
|
this._isLooping = false;
|
|
48329
48457
|
this._playbackRange = null;
|
|
48330
48458
|
this._output = player;
|
|
@@ -48459,9 +48587,8 @@
|
|
|
48459
48587
|
this.checkReadyForPlayback();
|
|
48460
48588
|
break;
|
|
48461
48589
|
case 'alphaSynth.positionChanged':
|
|
48462
|
-
this.
|
|
48463
|
-
this.
|
|
48464
|
-
this.positionChanged.trigger(new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo));
|
|
48590
|
+
this._currentPosition = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48591
|
+
this.positionChanged.trigger(this._currentPosition);
|
|
48465
48592
|
break;
|
|
48466
48593
|
case 'alphaSynth.midiEventsPlayed':
|
|
48467
48594
|
this.midiEventsPlayed.trigger(new MidiEventsPlayedEventArgs(data.events.map(JsonConverter.jsObjectToMidiEvent)));
|
|
@@ -48485,7 +48612,8 @@
|
|
|
48485
48612
|
break;
|
|
48486
48613
|
case 'alphaSynth.midiLoaded':
|
|
48487
48614
|
this.checkReadyForPlayback();
|
|
48488
|
-
this.
|
|
48615
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48616
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
48489
48617
|
break;
|
|
48490
48618
|
case 'alphaSynth.midiLoadFailed':
|
|
48491
48619
|
this.checkReadyForPlayback();
|
|
@@ -66628,6 +66756,10 @@
|
|
|
66628
66756
|
track.score.stylesheet.perTrackMultiBarRest.has(track.index)) {
|
|
66629
66757
|
writer.writeLine(` multibarrest`);
|
|
66630
66758
|
}
|
|
66759
|
+
writer.writeLine(` instrument ${track.isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program)}`);
|
|
66760
|
+
if (track.playbackInfo.bank > 0) {
|
|
66761
|
+
writer.writeLine(` bank ${track.playbackInfo.bank}`);
|
|
66762
|
+
}
|
|
66631
66763
|
writer.outdent();
|
|
66632
66764
|
writer.writeLine('}');
|
|
66633
66765
|
writer.indent();
|
|
@@ -66686,13 +66818,7 @@
|
|
|
66686
66818
|
writer.writeLine('|');
|
|
66687
66819
|
}
|
|
66688
66820
|
if (voiceIndex === 0) {
|
|
66689
|
-
// Track meta on first bar
|
|
66690
66821
|
let anyWritten = false;
|
|
66691
|
-
if (bar.index === 0 && bar.staff.index === 0) {
|
|
66692
|
-
const l = writer.tex.length;
|
|
66693
|
-
this.writeTrackMetaTo(writer, bar.staff.track);
|
|
66694
|
-
anyWritten = writer.tex.length > l;
|
|
66695
|
-
}
|
|
66696
66822
|
// Staff meta on first bar
|
|
66697
66823
|
if (bar.index === 0) {
|
|
66698
66824
|
const l = writer.tex.length;
|
|
@@ -66722,14 +66848,6 @@
|
|
|
66722
66848
|
}
|
|
66723
66849
|
writer.outdent();
|
|
66724
66850
|
}
|
|
66725
|
-
writeTrackMetaTo(writer, track) {
|
|
66726
|
-
writer.writeSingleLineComment(`Track ${track.index + 1} Metadata`);
|
|
66727
|
-
this.writePlaybackInfoTo(writer, track);
|
|
66728
|
-
}
|
|
66729
|
-
writePlaybackInfoTo(writer, track) {
|
|
66730
|
-
const isPercussion = track.staves.some(s => s.isPercussion);
|
|
66731
|
-
writer.writeMeta('instrument', isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program));
|
|
66732
|
-
}
|
|
66733
66851
|
writeStaffMetaTo(writer, staff) {
|
|
66734
66852
|
writer.writeSingleLineComment(`Staff ${staff.index + 1} Metadata`);
|
|
66735
66853
|
if (staff.capo !== 0) {
|
|
@@ -68352,15 +68470,16 @@
|
|
|
68352
68470
|
}
|
|
68353
68471
|
return GpifIconIds.SteelGuitar;
|
|
68354
68472
|
}
|
|
68355
|
-
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, ratioPosition = 0) {
|
|
68473
|
+
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, bank, ratioPosition = 0) {
|
|
68356
68474
|
const soundNode = soundsNode.addElement('Sound');
|
|
68357
68475
|
soundNode.addElement('Name').setCData(name);
|
|
68358
68476
|
soundNode.addElement('Label').setCData(name);
|
|
68359
68477
|
soundNode.addElement('Path').setCData(path);
|
|
68360
68478
|
soundNode.addElement('Role').setCData(role);
|
|
68361
68479
|
const midi = soundNode.addElement('MIDI');
|
|
68362
|
-
|
|
68363
|
-
midi.addElement('
|
|
68480
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
68481
|
+
midi.addElement('LSB').innerText = lsbMsb[0].toString();
|
|
68482
|
+
midi.addElement('MSB').innerText = lsbMsb[1].toString();
|
|
68364
68483
|
midi.addElement('Program').innerText = program.toString();
|
|
68365
68484
|
const automationNode = automationsNode.addElement('Automation');
|
|
68366
68485
|
automationNode.addElement('Type').innerText = 'Sound';
|
|
@@ -68378,21 +68497,26 @@
|
|
|
68378
68497
|
const trackSoundPath = `Midi/${track.playbackInfo.program}`;
|
|
68379
68498
|
const trackSoundRole = 'Factory';
|
|
68380
68499
|
let trackSoundWritten = false;
|
|
68500
|
+
let bank = track.playbackInfo.bank;
|
|
68381
68501
|
for (const staff of track.staves) {
|
|
68382
68502
|
for (const bar of staff.bars) {
|
|
68383
68503
|
for (const voice of bar.voices) {
|
|
68384
68504
|
for (const beat of voice.beats) {
|
|
68385
68505
|
const soundAutomation = beat.getAutomation(AutomationType.Instrument);
|
|
68386
68506
|
const isTrackSound = bar.index === 0 && beat.index === 0;
|
|
68507
|
+
const bankAutomation = beat.getAutomation(AutomationType.Bank);
|
|
68508
|
+
if (bankAutomation) {
|
|
68509
|
+
bank = bankAutomation.value;
|
|
68510
|
+
}
|
|
68387
68511
|
if (soundAutomation) {
|
|
68388
68512
|
const name = isTrackSound ? trackSoundName : `ProgramChange_${beat.id}`;
|
|
68389
68513
|
const path = isTrackSound ? trackSoundPath : `Midi/${soundAutomation.value}`;
|
|
68390
68514
|
const role = isTrackSound ? trackSoundRole : 'User';
|
|
68391
68515
|
if (!isTrackSound && !trackSoundWritten) {
|
|
68392
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program);
|
|
68516
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program, track.playbackInfo.bank);
|
|
68393
68517
|
trackSoundWritten = true;
|
|
68394
68518
|
}
|
|
68395
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, soundAutomation.ratioPosition);
|
|
68519
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, bank, soundAutomation.ratioPosition);
|
|
68396
68520
|
if (isTrackSound) {
|
|
68397
68521
|
trackSoundWritten = true;
|
|
68398
68522
|
}
|