@coderline/alphatab 1.7.0-alpha.1517 → 1.7.0-alpha.1522
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.core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.7.0-alpha.
|
|
2
|
+
* alphaTab v1.7.0-alpha.1522 (develop, build 1522)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -197,9 +197,9 @@ class VersionInfo {
|
|
|
197
197
|
print(`build date: ${VersionInfo.date}`);
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
|
-
VersionInfo.version = '1.7.0-alpha.
|
|
201
|
-
VersionInfo.date = '2025-08-
|
|
202
|
-
VersionInfo.commit = '
|
|
200
|
+
VersionInfo.version = '1.7.0-alpha.1522';
|
|
201
|
+
VersionInfo.date = '2025-08-24T02:21:16.522Z';
|
|
202
|
+
VersionInfo.commit = 'c80b4a66eae6b73cb2d7dacaaf74c8f9cce16318';
|
|
203
203
|
|
|
204
204
|
/**
|
|
205
205
|
* This public class provides names for all general midi instruments.
|
|
@@ -226,6 +226,14 @@ class GeneralMidi {
|
|
|
226
226
|
static isGuitar(program) {
|
|
227
227
|
return (program >= 24 && program <= 39) || program === 105 || program === 43;
|
|
228
228
|
}
|
|
229
|
+
static isBass(program) {
|
|
230
|
+
return program >= 32 && program <= 39;
|
|
231
|
+
}
|
|
232
|
+
static bankToLsbMsb(bank) {
|
|
233
|
+
const lsb = bank & 0x7f;
|
|
234
|
+
const msb = (bank >> 7) & 0x7f;
|
|
235
|
+
return [lsb, msb];
|
|
236
|
+
}
|
|
229
237
|
}
|
|
230
238
|
GeneralMidi._values = new Map([
|
|
231
239
|
['acousticgrandpiano', 0],
|
|
@@ -1420,6 +1428,10 @@ var AutomationType;
|
|
|
1420
1428
|
* A sync point for synchronizing the internal time axis with an external audio track.
|
|
1421
1429
|
*/
|
|
1422
1430
|
AutomationType[AutomationType["SyncPoint"] = 4] = "SyncPoint";
|
|
1431
|
+
/**
|
|
1432
|
+
* Midi Bank change.
|
|
1433
|
+
*/
|
|
1434
|
+
AutomationType[AutomationType["Bank"] = 4] = "Bank";
|
|
1423
1435
|
})(AutomationType || (AutomationType = {}));
|
|
1424
1436
|
/**
|
|
1425
1437
|
* Represents the data of a sync point for synchronizing the internal time axis with
|
|
@@ -8161,6 +8173,10 @@ class PlaybackInformation {
|
|
|
8161
8173
|
* Gets or sets the midi program to use.
|
|
8162
8174
|
*/
|
|
8163
8175
|
this.program = 0;
|
|
8176
|
+
/**
|
|
8177
|
+
* The midi bank to use.
|
|
8178
|
+
*/
|
|
8179
|
+
this.bank = 0;
|
|
8164
8180
|
/**
|
|
8165
8181
|
* Gets or sets the primary channel for all normal midi events.
|
|
8166
8182
|
*/
|
|
@@ -8555,6 +8571,12 @@ class Track {
|
|
|
8555
8571
|
*/
|
|
8556
8572
|
this.percussionArticulations = [];
|
|
8557
8573
|
}
|
|
8574
|
+
/**
|
|
8575
|
+
* Gets whether this track is a percussion track.
|
|
8576
|
+
*/
|
|
8577
|
+
get isPercussion() {
|
|
8578
|
+
return this.staves.some(s => s.isPercussion);
|
|
8579
|
+
}
|
|
8558
8580
|
/**
|
|
8559
8581
|
* Adds a new line break.
|
|
8560
8582
|
* @param index The index of the bar before which a line break should happen.
|
|
@@ -10219,33 +10241,15 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
10219
10241
|
}
|
|
10220
10242
|
return StaffMetaResult.KnownStaffMeta;
|
|
10221
10243
|
case 'instrument':
|
|
10222
|
-
this.sy = this.newSy();
|
|
10223
10244
|
this._staffTuningApplied = false;
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
10231
|
-
}
|
|
10232
|
-
}
|
|
10233
|
-
else if (this.sy === AlphaTexSymbols.String) {
|
|
10234
|
-
const instrumentName = this.syData.toLowerCase();
|
|
10235
|
-
if (instrumentName === 'percussion') {
|
|
10236
|
-
for (const staff of this._currentTrack.staves) {
|
|
10237
|
-
this.applyPercussionStaff(staff);
|
|
10238
|
-
}
|
|
10239
|
-
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
10240
|
-
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10241
|
-
}
|
|
10242
|
-
else {
|
|
10243
|
-
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10244
|
-
}
|
|
10245
|
-
}
|
|
10246
|
-
else {
|
|
10247
|
-
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10245
|
+
this.readTrackInstrument();
|
|
10246
|
+
return StaffMetaResult.KnownStaffMeta;
|
|
10247
|
+
case 'bank':
|
|
10248
|
+
this.sy = this.newSy();
|
|
10249
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10250
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10248
10251
|
}
|
|
10252
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10249
10253
|
this.sy = this.newSy();
|
|
10250
10254
|
return StaffMetaResult.KnownStaffMeta;
|
|
10251
10255
|
case 'lyrics':
|
|
@@ -10356,6 +10360,35 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
10356
10360
|
return StaffMetaResult.UnknownStaffMeta;
|
|
10357
10361
|
}
|
|
10358
10362
|
}
|
|
10363
|
+
readTrackInstrument() {
|
|
10364
|
+
this.sy = this.newSy();
|
|
10365
|
+
if (this.sy === AlphaTexSymbols.Number) {
|
|
10366
|
+
const instrument = this.syData;
|
|
10367
|
+
if (instrument >= 0 && instrument <= 127) {
|
|
10368
|
+
this._currentTrack.playbackInfo.program = this.syData;
|
|
10369
|
+
}
|
|
10370
|
+
else {
|
|
10371
|
+
this.error('instrument', AlphaTexSymbols.Number, false);
|
|
10372
|
+
}
|
|
10373
|
+
}
|
|
10374
|
+
else if (this.sy === AlphaTexSymbols.String) {
|
|
10375
|
+
const instrumentName = this.syData.toLowerCase();
|
|
10376
|
+
if (instrumentName === 'percussion') {
|
|
10377
|
+
for (const staff of this._currentTrack.staves) {
|
|
10378
|
+
this.applyPercussionStaff(staff);
|
|
10379
|
+
}
|
|
10380
|
+
this._currentTrack.playbackInfo.primaryChannel = SynthConstants.PercussionChannel;
|
|
10381
|
+
this._currentTrack.playbackInfo.secondaryChannel = SynthConstants.PercussionChannel;
|
|
10382
|
+
}
|
|
10383
|
+
else {
|
|
10384
|
+
this._currentTrack.playbackInfo.program = GeneralMidi.getValue(instrumentName);
|
|
10385
|
+
}
|
|
10386
|
+
}
|
|
10387
|
+
else {
|
|
10388
|
+
this.error('instrument', AlphaTexSymbols.Number, true);
|
|
10389
|
+
}
|
|
10390
|
+
this.sy = this.newSy();
|
|
10391
|
+
}
|
|
10359
10392
|
handleAccidentalMode() {
|
|
10360
10393
|
this.sy = this.newSy();
|
|
10361
10394
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -10628,6 +10661,17 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
10628
10661
|
}
|
|
10629
10662
|
this._score.stylesheet.perTrackMultiBarRest.add(this._currentTrack.index);
|
|
10630
10663
|
break;
|
|
10664
|
+
case 'instrument':
|
|
10665
|
+
this.readTrackInstrument();
|
|
10666
|
+
break;
|
|
10667
|
+
case 'bank':
|
|
10668
|
+
this.sy = this.newSy();
|
|
10669
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
10670
|
+
this.error('bank', AlphaTexSymbols.Number, true);
|
|
10671
|
+
}
|
|
10672
|
+
this._currentTrack.playbackInfo.bank = this.syData;
|
|
10673
|
+
this.sy = this.newSy();
|
|
10674
|
+
break;
|
|
10631
10675
|
default:
|
|
10632
10676
|
this.error('track-properties', AlphaTexSymbols.String, false);
|
|
10633
10677
|
break;
|
|
@@ -11428,6 +11472,17 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
11428
11472
|
automation.value = program;
|
|
11429
11473
|
beat.automations.push(automation);
|
|
11430
11474
|
}
|
|
11475
|
+
else if (syData === 'bank') {
|
|
11476
|
+
this.sy = this.newSy();
|
|
11477
|
+
if (this.sy !== AlphaTexSymbols.Number) {
|
|
11478
|
+
this.error('bank-change', AlphaTexSymbols.Number, true);
|
|
11479
|
+
}
|
|
11480
|
+
const automation = new Automation();
|
|
11481
|
+
automation.isLinear = false;
|
|
11482
|
+
automation.type = AutomationType.Bank;
|
|
11483
|
+
automation.value = this.syData;
|
|
11484
|
+
beat.automations.push(automation);
|
|
11485
|
+
}
|
|
11431
11486
|
else if (syData === 'fermata') {
|
|
11432
11487
|
this.sy = this.newSy();
|
|
11433
11488
|
if (this.sy !== AlphaTexSymbols.String) {
|
|
@@ -11438,7 +11493,7 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
11438
11493
|
this.sy = this.newSy(true);
|
|
11439
11494
|
if (this.sy === AlphaTexSymbols.Number) {
|
|
11440
11495
|
fermata.length = this.syData;
|
|
11441
|
-
this.sy = this.newSy(
|
|
11496
|
+
this.sy = this.newSy();
|
|
11442
11497
|
}
|
|
11443
11498
|
beat.fermata = fermata;
|
|
11444
11499
|
return true;
|
|
@@ -11471,13 +11526,9 @@ class AlphaTexImporter extends ScoreImporter {
|
|
|
11471
11526
|
beat.beamingMode = BeatBeamingMode.ForceSplitOnSecondaryToNext;
|
|
11472
11527
|
break;
|
|
11473
11528
|
}
|
|
11474
|
-
this.sy = this.newSy();
|
|
11475
|
-
return true;
|
|
11476
11529
|
}
|
|
11477
11530
|
else if (syData === 'timer') {
|
|
11478
11531
|
beat.showTimer = true;
|
|
11479
|
-
this.sy = this.newSy();
|
|
11480
|
-
return true;
|
|
11481
11532
|
}
|
|
11482
11533
|
else {
|
|
11483
11534
|
// string didn't match any beat effect syntax
|
|
@@ -15037,6 +15088,7 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15037
15088
|
this._trackCount = 0;
|
|
15038
15089
|
this._playbackInfos = [];
|
|
15039
15090
|
this._doubleBars = new Set();
|
|
15091
|
+
this._clefsPerTrack = new Map();
|
|
15040
15092
|
this._keySignatures = new Map();
|
|
15041
15093
|
this._beatTextChunksByTrack = new Map();
|
|
15042
15094
|
this._directionLookup = new Map();
|
|
@@ -15421,26 +15473,74 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15421
15473
|
mainStaff.capo = IOHelper.readInt32LE(this.data);
|
|
15422
15474
|
newTrack.color = GpBinaryHelpers.gpReadColor(this.data, false);
|
|
15423
15475
|
if (this._versionNumber >= 500) {
|
|
15424
|
-
const
|
|
15425
|
-
mainStaff.showTablature = (
|
|
15426
|
-
mainStaff.showStandardNotation = (
|
|
15427
|
-
const showChordDiagramListOnTopOfScore = (
|
|
15476
|
+
const staffFlags = this.data.readByte();
|
|
15477
|
+
mainStaff.showTablature = (staffFlags & 0x01) !== 0;
|
|
15478
|
+
mainStaff.showStandardNotation = (staffFlags & 0x02) !== 0;
|
|
15479
|
+
const showChordDiagramListOnTopOfScore = (staffFlags & 0x64) !== 0;
|
|
15428
15480
|
if (this._score.stylesheet.perTrackChordDiagramsOnTop === null) {
|
|
15429
15481
|
this._score.stylesheet.perTrackChordDiagramsOnTop = new Map();
|
|
15430
15482
|
}
|
|
15431
15483
|
this._score.stylesheet.perTrackChordDiagramsOnTop.set(newTrack.index, showChordDiagramListOnTopOfScore);
|
|
15432
|
-
//
|
|
15484
|
+
// MIDI: Automatic
|
|
15485
|
+
// 0x01 -> always set (unknown)
|
|
15433
15486
|
// 0x02 -> auto let ring
|
|
15434
15487
|
// 0x04 -> auto brush
|
|
15435
15488
|
this.data.readByte();
|
|
15436
|
-
//
|
|
15437
|
-
|
|
15489
|
+
// RSE: Auto-Accentuation on the Beat
|
|
15490
|
+
// 0 - None
|
|
15491
|
+
// 1 - Very Soft
|
|
15492
|
+
// 2 - Soft
|
|
15493
|
+
// 3 - Medium
|
|
15494
|
+
// 4 - Strong
|
|
15495
|
+
// 5 - Very Strong
|
|
15496
|
+
this.data.readByte();
|
|
15497
|
+
newTrack.playbackInfo.bank = this.data.readByte();
|
|
15498
|
+
// RSE: Human Playing (1 byte, 0-100%)
|
|
15499
|
+
this.data.readByte();
|
|
15500
|
+
// `12` for all tunings which have bass clefs
|
|
15501
|
+
const clefMode = IOHelper.readInt32LE(this.data);
|
|
15502
|
+
if (clefMode === 12) {
|
|
15503
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15504
|
+
}
|
|
15505
|
+
else {
|
|
15506
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15507
|
+
}
|
|
15508
|
+
// Unknown, no UI setting seem to affect this
|
|
15509
|
+
IOHelper.readInt32LE(this.data);
|
|
15510
|
+
// Unknown, no UI setting seem to affect this
|
|
15511
|
+
// typically: 100
|
|
15512
|
+
IOHelper.readInt32LE(this.data);
|
|
15513
|
+
// Unknown, no UI setting seem to affect this
|
|
15514
|
+
// typically: 1 2 3 4 5 6 7 8 9 10
|
|
15515
|
+
this.data.skip(10);
|
|
15516
|
+
// Unknown, no UI setting seem to affect this
|
|
15517
|
+
// typically: 255
|
|
15518
|
+
this.data.readByte();
|
|
15519
|
+
// Unknown, no UI setting seem to affect this
|
|
15520
|
+
// typically: 3
|
|
15521
|
+
this.data.readByte();
|
|
15522
|
+
this.readRseBank();
|
|
15523
|
+
// this.data.skip(42);
|
|
15524
|
+
if (this._versionNumber >= 510) {
|
|
15525
|
+
// RSE: 3-band EQ
|
|
15526
|
+
// 1 byte Low
|
|
15527
|
+
// 1 byte Mid
|
|
15528
|
+
// 1 byte High
|
|
15529
|
+
// 1 byte PRE
|
|
15530
|
+
this.data.skip(4);
|
|
15531
|
+
// RSE: effect name
|
|
15532
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15533
|
+
// RSE: effect category
|
|
15534
|
+
GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15535
|
+
}
|
|
15438
15536
|
}
|
|
15439
|
-
|
|
15440
|
-
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15537
|
+
else {
|
|
15538
|
+
if (GeneralMidi.isBass(newTrack.playbackInfo.program)) {
|
|
15539
|
+
this._clefsPerTrack.set(index, Clef.F4);
|
|
15540
|
+
}
|
|
15541
|
+
else {
|
|
15542
|
+
this._clefsPerTrack.set(index, Clef.G2);
|
|
15543
|
+
}
|
|
15444
15544
|
}
|
|
15445
15545
|
}
|
|
15446
15546
|
readBars() {
|
|
@@ -15456,6 +15556,9 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15456
15556
|
if (mainStaff.isPercussion) {
|
|
15457
15557
|
newBar.clef = Clef.Neutral;
|
|
15458
15558
|
}
|
|
15559
|
+
else if (this._clefsPerTrack.has(track.index)) {
|
|
15560
|
+
newBar.clef = this._clefsPerTrack.get(track.index);
|
|
15561
|
+
}
|
|
15459
15562
|
mainStaff.addBar(newBar);
|
|
15460
15563
|
if (this._keySignatures.has(newBar.index)) {
|
|
15461
15564
|
const newKeySignature = this._keySignatures.get(newBar.index);
|
|
@@ -15877,11 +15980,29 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15877
15980
|
return 0;
|
|
15878
15981
|
}
|
|
15879
15982
|
}
|
|
15983
|
+
readRseBank() {
|
|
15984
|
+
// RSE Banks on disk are having filenames like this: 033_2_002.ini
|
|
15985
|
+
// 033 is the RSE instrument (selected in the instrument list)
|
|
15986
|
+
// 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
|
|
15987
|
+
// likely for organizational purposes
|
|
15988
|
+
// 002 is the effective soundbank (selected in the soundbank dropdown)
|
|
15989
|
+
// RSE Instrument
|
|
15990
|
+
this.data.skip(4); // IOHelper.readInt32LE(this.data);
|
|
15991
|
+
// RSE Style/Variation
|
|
15992
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15993
|
+
// RSE Soundbank
|
|
15994
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15995
|
+
// Unknown, no UI setting seem to affect this
|
|
15996
|
+
// typically: -1
|
|
15997
|
+
this.data.skip(4); //IOHelper.readInt32LE(this.data);
|
|
15998
|
+
}
|
|
15880
15999
|
readMixTableChange(beat) {
|
|
15881
16000
|
const tableChange = new MixTableChange();
|
|
15882
16001
|
tableChange.instrument = IOHelper.readSInt8(this.data);
|
|
16002
|
+
// NOTE: The UI shows a Midi Bank selection, but this information is not stored in the file
|
|
16003
|
+
// when reopening the file the bank is always 0
|
|
15883
16004
|
if (this._versionNumber >= 500) {
|
|
15884
|
-
this.
|
|
16005
|
+
this.readRseBank();
|
|
15885
16006
|
}
|
|
15886
16007
|
tableChange.volume = IOHelper.readSInt8(this.data);
|
|
15887
16008
|
tableChange.balance = IOHelper.readSInt8(this.data);
|
|
@@ -15893,7 +16014,7 @@ class Gp3To5Importer extends ScoreImporter {
|
|
|
15893
16014
|
tableChange.tempoName = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding);
|
|
15894
16015
|
}
|
|
15895
16016
|
tableChange.tempo = IOHelper.readInt32LE(this.data);
|
|
15896
|
-
// durations
|
|
16017
|
+
// durations (in number of beats)
|
|
15897
16018
|
if (tableChange.volume >= 0) {
|
|
15898
16019
|
this.data.readByte();
|
|
15899
16020
|
}
|
|
@@ -16876,9 +16997,7 @@ class BinaryStylesheet {
|
|
|
16876
16997
|
return writer.toArray();
|
|
16877
16998
|
}
|
|
16878
16999
|
static addHeaderAndFooter(binaryStylesheet, style, prefix, name) {
|
|
16879
|
-
|
|
16880
|
-
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16881
|
-
}
|
|
17000
|
+
binaryStylesheet.addValue(`${prefix}${name}`, style.template, DataType.String);
|
|
16882
17001
|
binaryStylesheet.addValue(`${prefix}${name}Alignment`, style.textAlign, DataType.Integer);
|
|
16883
17002
|
if (style.isVisible !== undefined) {
|
|
16884
17003
|
binaryStylesheet.addValue(`${prefix}draw${name}`, style.isVisible, DataType.Boolean);
|
|
@@ -16912,6 +17031,7 @@ class GpifSound {
|
|
|
16912
17031
|
this.path = '';
|
|
16913
17032
|
this.role = '';
|
|
16914
17033
|
this.program = 0;
|
|
17034
|
+
this.bank = 0;
|
|
16915
17035
|
}
|
|
16916
17036
|
get uniqueId() {
|
|
16917
17037
|
return `${this.path};${this.name};${this.role}`;
|
|
@@ -17266,21 +17386,28 @@ class GpifParser {
|
|
|
17266
17386
|
if (!type) {
|
|
17267
17387
|
return;
|
|
17268
17388
|
}
|
|
17269
|
-
|
|
17389
|
+
const newAutomations = [];
|
|
17270
17390
|
switch (type) {
|
|
17271
17391
|
case 'Tempo':
|
|
17272
|
-
|
|
17392
|
+
newAutomations.push(Automation.buildTempoAutomation(isLinear, ratioPosition, numberValue, reference));
|
|
17273
17393
|
break;
|
|
17274
17394
|
case 'SyncPoint':
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
17395
|
+
const syncPoint = new Automation();
|
|
17396
|
+
syncPoint.type = AutomationType.SyncPoint;
|
|
17397
|
+
syncPoint.isLinear = isLinear;
|
|
17398
|
+
syncPoint.ratioPosition = ratioPosition;
|
|
17399
|
+
syncPoint.syncPointValue = syncPointValue;
|
|
17400
|
+
newAutomations.push(syncPoint);
|
|
17280
17401
|
break;
|
|
17281
17402
|
case 'Sound':
|
|
17282
17403
|
if (textValue && sounds && sounds.has(textValue)) {
|
|
17283
|
-
|
|
17404
|
+
const bankChange = new Automation();
|
|
17405
|
+
bankChange.type = AutomationType.Bank;
|
|
17406
|
+
bankChange.ratioPosition = ratioPosition;
|
|
17407
|
+
bankChange.value = sounds.get(textValue).bank;
|
|
17408
|
+
newAutomations.push(bankChange);
|
|
17409
|
+
const programChange = Automation.buildInstrumentAutomation(isLinear, ratioPosition, sounds.get(textValue).program);
|
|
17410
|
+
newAutomations.push(programChange);
|
|
17284
17411
|
}
|
|
17285
17412
|
break;
|
|
17286
17413
|
case 'SustainPedal':
|
|
@@ -17308,15 +17435,19 @@ class GpifParser {
|
|
|
17308
17435
|
}
|
|
17309
17436
|
break;
|
|
17310
17437
|
}
|
|
17311
|
-
if (
|
|
17438
|
+
if (newAutomations.length) {
|
|
17312
17439
|
if (text) {
|
|
17313
|
-
|
|
17440
|
+
for (const a of newAutomations) {
|
|
17441
|
+
a.text = text;
|
|
17442
|
+
}
|
|
17314
17443
|
}
|
|
17315
17444
|
if (barIndex >= 0) {
|
|
17316
17445
|
if (!automations.has(barIndex)) {
|
|
17317
17446
|
automations.set(barIndex, []);
|
|
17318
17447
|
}
|
|
17319
|
-
|
|
17448
|
+
for (const a of newAutomations) {
|
|
17449
|
+
automations.get(barIndex).push(a);
|
|
17450
|
+
}
|
|
17320
17451
|
}
|
|
17321
17452
|
}
|
|
17322
17453
|
}
|
|
@@ -17908,22 +18039,31 @@ class GpifParser {
|
|
|
17908
18039
|
break;
|
|
17909
18040
|
}
|
|
17910
18041
|
}
|
|
17911
|
-
if (sound.role === 'Factory' || track.playbackInfo.program === 0) {
|
|
17912
|
-
track.playbackInfo.program = sound.program;
|
|
17913
|
-
}
|
|
17914
18042
|
if (!this._soundsByTrack.has(trackId)) {
|
|
17915
18043
|
this._soundsByTrack.set(trackId, new Map());
|
|
18044
|
+
// apply first sound
|
|
18045
|
+
track.playbackInfo.program = sound.program;
|
|
18046
|
+
track.playbackInfo.bank = sound.bank;
|
|
17916
18047
|
}
|
|
17917
18048
|
this._soundsByTrack.get(trackId).set(sound.uniqueId, sound);
|
|
17918
18049
|
}
|
|
17919
18050
|
parseSoundMidi(sound, node) {
|
|
18051
|
+
let bankMsb = 0;
|
|
18052
|
+
let bankLsb = 0;
|
|
17920
18053
|
for (const c of node.childElements()) {
|
|
17921
18054
|
switch (c.localName) {
|
|
17922
18055
|
case 'Program':
|
|
17923
18056
|
sound.program = GpifParser.parseIntSafe(c.innerText, 0);
|
|
17924
18057
|
break;
|
|
18058
|
+
case 'MSB': // coarse
|
|
18059
|
+
bankMsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18060
|
+
break;
|
|
18061
|
+
case 'LSB': // Fine
|
|
18062
|
+
bankLsb = GpifParser.parseIntSafe(c.innerText, 0);
|
|
18063
|
+
break;
|
|
17925
18064
|
}
|
|
17926
18065
|
}
|
|
18066
|
+
sound.bank = ((bankMsb & 0x7f) << 7) | bankLsb;
|
|
17927
18067
|
}
|
|
17928
18068
|
parsePartSounding(trackId, track, node) {
|
|
17929
18069
|
for (const c of node.childElements()) {
|
|
@@ -19377,7 +19517,12 @@ class GpifParser {
|
|
|
19377
19517
|
for (const a of automations) {
|
|
19378
19518
|
// NOTE: currently the automations of a bar are applied to the
|
|
19379
19519
|
// first beat of a bar
|
|
19380
|
-
|
|
19520
|
+
const skip =
|
|
19521
|
+
// skip bank automations if they are 0 at start
|
|
19522
|
+
a.type === AutomationType.Bank && a.value === 0 && bar.index === 0;
|
|
19523
|
+
if (!skip) {
|
|
19524
|
+
beat.automations.push(a);
|
|
19525
|
+
}
|
|
19381
19526
|
}
|
|
19382
19527
|
}
|
|
19383
19528
|
}
|
|
@@ -20397,6 +20542,10 @@ class InstrumentArticulationWithPlaybackInfo extends InstrumentArticulation {
|
|
|
20397
20542
|
* The midi channel program to use when playing the note (-1 if using the default track program).
|
|
20398
20543
|
*/
|
|
20399
20544
|
this.outputMidiProgram = -1;
|
|
20545
|
+
/**
|
|
20546
|
+
* The midi bank to use when playing the note (-1 if using the default track bank).
|
|
20547
|
+
*/
|
|
20548
|
+
this.outputMidiBank = -1;
|
|
20400
20549
|
/**
|
|
20401
20550
|
* The volume to use when playing the note (-1 if using the default track volume).
|
|
20402
20551
|
*/
|
|
@@ -20895,6 +21044,9 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
20895
21044
|
if (trackInfo.firstArticulation.outputMidiProgram >= 0) {
|
|
20896
21045
|
track.playbackInfo.program = trackInfo.firstArticulation.outputMidiProgram;
|
|
20897
21046
|
}
|
|
21047
|
+
if (trackInfo.firstArticulation.outputMidiBank >= 0) {
|
|
21048
|
+
track.playbackInfo.bank = trackInfo.firstArticulation.outputMidiBank;
|
|
21049
|
+
}
|
|
20898
21050
|
if (trackInfo.firstArticulation.outputBalance >= 0) {
|
|
20899
21051
|
track.playbackInfo.balance = trackInfo.firstArticulation.outputBalance;
|
|
20900
21052
|
}
|
|
@@ -20926,7 +21078,9 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
20926
21078
|
articulation.outputMidiChannel = Number.parseInt(c.innerText) - 1;
|
|
20927
21079
|
break;
|
|
20928
21080
|
// case 'midi-name': Ignored
|
|
20929
|
-
|
|
21081
|
+
case 'midi-bank':
|
|
21082
|
+
articulation.outputMidiBank = Number.parseInt(c.innerText) - 1;
|
|
21083
|
+
break;
|
|
20930
21084
|
case 'midi-program':
|
|
20931
21085
|
articulation.outputMidiProgram = Number.parseInt(c.innerText) - 1;
|
|
20932
21086
|
break;
|
|
@@ -21456,7 +21610,15 @@ class MusicXmlImporter extends ScoreImporter {
|
|
|
21456
21610
|
switch (c.localName) {
|
|
21457
21611
|
// case 'midi-channel': Ignored
|
|
21458
21612
|
// case 'midi-name': Ignored
|
|
21459
|
-
|
|
21613
|
+
case 'midi-bank':
|
|
21614
|
+
if (!this._nextBeatAutomations) {
|
|
21615
|
+
this._nextBeatAutomations = [];
|
|
21616
|
+
}
|
|
21617
|
+
automation = new Automation();
|
|
21618
|
+
automation.type = AutomationType.Bank;
|
|
21619
|
+
automation.value = Number.parseInt(c.innerText) - 1;
|
|
21620
|
+
this._nextBeatAutomations.push(automation);
|
|
21621
|
+
break;
|
|
21460
21622
|
case 'midi-program':
|
|
21461
21623
|
if (!this._nextBeatAutomations) {
|
|
21462
21624
|
this._nextBeatAutomations = [];
|
|
@@ -23727,11 +23889,15 @@ class CircularSampleBuffer {
|
|
|
23727
23889
|
}
|
|
23728
23890
|
|
|
23729
23891
|
class EventEmitter {
|
|
23730
|
-
constructor() {
|
|
23892
|
+
constructor(fireOnRegister = undefined) {
|
|
23731
23893
|
this._listeners = [];
|
|
23894
|
+
this._fireOnRegister = fireOnRegister;
|
|
23732
23895
|
}
|
|
23733
23896
|
on(value) {
|
|
23734
23897
|
this._listeners.push(value);
|
|
23898
|
+
if (this._fireOnRegister?.()) {
|
|
23899
|
+
value();
|
|
23900
|
+
}
|
|
23735
23901
|
return () => {
|
|
23736
23902
|
this.off(value);
|
|
23737
23903
|
};
|
|
@@ -23749,11 +23915,18 @@ class EventEmitter {
|
|
|
23749
23915
|
* @partial
|
|
23750
23916
|
*/
|
|
23751
23917
|
class EventEmitterOfT {
|
|
23752
|
-
constructor() {
|
|
23918
|
+
constructor(fireOnRegister = undefined) {
|
|
23753
23919
|
this._listeners = [];
|
|
23920
|
+
this._fireOnRegister = fireOnRegister;
|
|
23754
23921
|
}
|
|
23755
23922
|
on(value) {
|
|
23756
23923
|
this._listeners.push(value);
|
|
23924
|
+
if (this._fireOnRegister) {
|
|
23925
|
+
const arg = this._fireOnRegister();
|
|
23926
|
+
if (arg !== null) {
|
|
23927
|
+
value(arg);
|
|
23928
|
+
}
|
|
23929
|
+
}
|
|
23757
23930
|
return () => {
|
|
23758
23931
|
this.off(value);
|
|
23759
23932
|
};
|
|
@@ -30794,6 +30967,12 @@ class AlphaSynthBase {
|
|
|
30794
30967
|
this.sequencer.playbackSpeed = value;
|
|
30795
30968
|
this.timePosition = this.timePosition * (oldSpeed / value);
|
|
30796
30969
|
}
|
|
30970
|
+
get loadedMidiInfo() {
|
|
30971
|
+
return this._loadedMidiInfo;
|
|
30972
|
+
}
|
|
30973
|
+
get currentPosition() {
|
|
30974
|
+
return this._currentPosition;
|
|
30975
|
+
}
|
|
30797
30976
|
get tickPosition() {
|
|
30798
30977
|
return this._tickPosition;
|
|
30799
30978
|
}
|
|
@@ -30851,22 +31030,38 @@ class AlphaSynthBase {
|
|
|
30851
31030
|
this._midiEventsPlayedFilter = new Set();
|
|
30852
31031
|
this._notPlayedSamples = 0;
|
|
30853
31032
|
this._synthStopping = false;
|
|
31033
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
30854
31034
|
this.isReady = false;
|
|
30855
31035
|
this.state = PlayerState.Paused;
|
|
30856
31036
|
this._loadedSoundFonts = [];
|
|
30857
|
-
this.ready = new EventEmitter();
|
|
30858
31037
|
this.readyForPlayback = new EventEmitter();
|
|
30859
31038
|
this.finished = new EventEmitter();
|
|
30860
31039
|
this.soundFontLoaded = new EventEmitter();
|
|
30861
31040
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
30862
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
30863
31041
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
30864
|
-
this.stateChanged = new EventEmitterOfT();
|
|
30865
|
-
this.positionChanged = new EventEmitterOfT();
|
|
30866
31042
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
30867
|
-
this.playbackRangeChanged = new EventEmitterOfT();
|
|
30868
31043
|
Logger.debug('AlphaSynth', 'Initializing player');
|
|
30869
31044
|
this.state = PlayerState.Paused;
|
|
31045
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
31046
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
31047
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
31048
|
+
if (this._loadedMidiInfo) {
|
|
31049
|
+
return this._loadedMidiInfo;
|
|
31050
|
+
}
|
|
31051
|
+
return null;
|
|
31052
|
+
});
|
|
31053
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
31054
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
31055
|
+
});
|
|
31056
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
31057
|
+
return this._currentPosition;
|
|
31058
|
+
});
|
|
31059
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
31060
|
+
if (this.playbackRange) {
|
|
31061
|
+
return new PlaybackRangeChangedEventArgs(this.playbackRange);
|
|
31062
|
+
}
|
|
31063
|
+
return null;
|
|
31064
|
+
});
|
|
30870
31065
|
Logger.debug('AlphaSynth', 'Creating output');
|
|
30871
31066
|
this._output = output;
|
|
30872
31067
|
Logger.debug('AlphaSynth', 'Creating synthesizer');
|
|
@@ -31044,7 +31239,8 @@ class AlphaSynthBase {
|
|
|
31044
31239
|
Logger.debug('AlphaSynth', 'Loading midi from model');
|
|
31045
31240
|
this.sequencer.loadMidi(midi);
|
|
31046
31241
|
this._isMidiLoaded = true;
|
|
31047
|
-
this.
|
|
31242
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(0, this.sequencer.currentEndTime, 0, this.sequencer.currentEndTick, false, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31243
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
31048
31244
|
Logger.debug('AlphaSynth', 'Midi successfully loaded');
|
|
31049
31245
|
this.checkReadyForPlayback();
|
|
31050
31246
|
this.tickPosition = 0;
|
|
@@ -31147,23 +31343,28 @@ class AlphaSynthBase {
|
|
|
31147
31343
|
this.sequencer.resetOneTimeMidi();
|
|
31148
31344
|
this.timePosition = this.sequencer.currentTime;
|
|
31149
31345
|
}
|
|
31150
|
-
|
|
31151
|
-
//
|
|
31152
|
-
let currentTime =
|
|
31153
|
-
this._timePosition = currentTime;
|
|
31346
|
+
createPositionChangedEventArgs(isSeek) {
|
|
31347
|
+
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31348
|
+
let currentTime = this._timePosition;
|
|
31154
31349
|
let currentTick = this.sequencer.currentTimePositionToTickPosition(currentTime);
|
|
31155
|
-
this._tickPosition = currentTick;
|
|
31156
31350
|
const endTime = this.sequencer.currentEndTime;
|
|
31157
31351
|
const endTick = this.sequencer.currentEndTick;
|
|
31158
|
-
// on fade outs we can have some milliseconds longer, ensure we don't report this
|
|
31159
31352
|
if (currentTime > endTime) {
|
|
31160
31353
|
currentTime = endTime;
|
|
31161
31354
|
currentTick = endTick;
|
|
31162
31355
|
}
|
|
31356
|
+
return new PositionChangedEventArgs(currentTime, endTime, currentTick, endTick, isSeek, this.sequencer.currentTempo, this.sequencer.modifiedTempo);
|
|
31357
|
+
}
|
|
31358
|
+
updateTimePosition(timePosition, isSeek) {
|
|
31359
|
+
// update the real positions
|
|
31360
|
+
this._timePosition = timePosition;
|
|
31361
|
+
const args = this.createPositionChangedEventArgs(isSeek);
|
|
31362
|
+
this._tickPosition = args.currentTick;
|
|
31163
31363
|
const mode = this.sequencer.isPlayingMain ? 'main' : this.sequencer.isPlayingCountIn ? 'count-in' : 'one-time';
|
|
31164
|
-
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})`);
|
|
31364
|
+
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})`);
|
|
31165
31365
|
if (this.sequencer.isPlayingMain) {
|
|
31166
|
-
this.
|
|
31366
|
+
this._currentPosition = args;
|
|
31367
|
+
this.positionChanged.trigger(args);
|
|
31167
31368
|
}
|
|
31168
31369
|
// build events which were actually played
|
|
31169
31370
|
if (isSeek) {
|
|
@@ -31171,7 +31372,7 @@ class AlphaSynthBase {
|
|
|
31171
31372
|
}
|
|
31172
31373
|
else {
|
|
31173
31374
|
const playedEvents = [];
|
|
31174
|
-
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < currentTime) {
|
|
31375
|
+
while (!this._playedEventsQueue.isEmpty && this._playedEventsQueue.peek().time < args.currentTime) {
|
|
31175
31376
|
const synthEvent = this._playedEventsQueue.dequeue();
|
|
31176
31377
|
playedEvents.push(synthEvent.event);
|
|
31177
31378
|
}
|
|
@@ -36622,6 +36823,15 @@ class Settings {
|
|
|
36622
36823
|
fillFromJson(json) {
|
|
36623
36824
|
SettingsSerializer.fromJson(this, json);
|
|
36624
36825
|
}
|
|
36826
|
+
/**
|
|
36827
|
+
* handles backwards compatibility aspects on the settings, removed in 2.0
|
|
36828
|
+
* @internal
|
|
36829
|
+
*/
|
|
36830
|
+
handleBackwardsCompatibility() {
|
|
36831
|
+
if (this.player.playerMode === PlayerMode.Disabled && this.player.enablePlayer) {
|
|
36832
|
+
this.player.playerMode = PlayerMode.EnabledAutomatic;
|
|
36833
|
+
}
|
|
36834
|
+
}
|
|
36625
36835
|
}
|
|
36626
36836
|
|
|
36627
36837
|
class SectionSerializer {
|
|
@@ -37839,6 +38049,7 @@ class PlaybackInformationSerializer {
|
|
|
37839
38049
|
o.set("balance", obj.balance);
|
|
37840
38050
|
o.set("port", obj.port);
|
|
37841
38051
|
o.set("program", obj.program);
|
|
38052
|
+
o.set("bank", obj.bank);
|
|
37842
38053
|
o.set("primarychannel", obj.primaryChannel);
|
|
37843
38054
|
o.set("secondarychannel", obj.secondaryChannel);
|
|
37844
38055
|
o.set("ismute", obj.isMute);
|
|
@@ -37859,6 +38070,9 @@ class PlaybackInformationSerializer {
|
|
|
37859
38070
|
case "program":
|
|
37860
38071
|
obj.program = v;
|
|
37861
38072
|
return true;
|
|
38073
|
+
case "bank":
|
|
38074
|
+
obj.bank = v;
|
|
38075
|
+
return true;
|
|
37862
38076
|
case "primarychannel":
|
|
37863
38077
|
obj.primaryChannel = v;
|
|
37864
38078
|
return true;
|
|
@@ -41517,6 +41731,11 @@ class MidiFileGenerator {
|
|
|
41517
41731
|
this._programsPerChannel.set(channel, program);
|
|
41518
41732
|
}
|
|
41519
41733
|
}
|
|
41734
|
+
addBankChange(track, tick, channel, bank) {
|
|
41735
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
41736
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectCoarse, lsbMsb[1]);
|
|
41737
|
+
this._handler.addControlChange(track.index, tick, channel, ControllerType.BankSelectFine, lsbMsb[0]);
|
|
41738
|
+
}
|
|
41520
41739
|
static buildTranspositionPitches(score, settings) {
|
|
41521
41740
|
const transpositionPitches = new Map();
|
|
41522
41741
|
for (const track of score.tracks) {
|
|
@@ -41544,6 +41763,7 @@ class MidiFileGenerator {
|
|
|
41544
41763
|
// Set PitchBendRangeCoarse to 12
|
|
41545
41764
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryFine, 0);
|
|
41546
41765
|
this._handler.addControlChange(track.index, 0, channel, ControllerType.DataEntryCoarse, MidiFileGenerator.PitchBendRangeInSemitones);
|
|
41766
|
+
this.addBankChange(track, 0, channel, playbackInfo.bank);
|
|
41547
41767
|
this.addProgramChange(track, 0, channel, playbackInfo.program);
|
|
41548
41768
|
}
|
|
41549
41769
|
/**
|
|
@@ -42839,6 +43059,10 @@ class MidiFileGenerator {
|
|
|
42839
43059
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, (automation.value | 0) & 0xff);
|
|
42840
43060
|
this.addProgramChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, (automation.value | 0) & 0xff);
|
|
42841
43061
|
break;
|
|
43062
|
+
case AutomationType.Bank:
|
|
43063
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, automation.value);
|
|
43064
|
+
this.addBankChange(beat.voice.bar.staff.track, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.secondaryChannel, automation.value);
|
|
43065
|
+
break;
|
|
42842
43066
|
case AutomationType.Balance:
|
|
42843
43067
|
const balance = MidiFileGenerator.toChannelShort(automation.value);
|
|
42844
43068
|
this._handler.addControlChange(beat.voice.bar.staff.track.index, beat.playbackStart + startMove, beat.voice.bar.staff.track.playbackInfo.primaryChannel, ControllerType.PanCoarse, balance);
|
|
@@ -43788,17 +44012,29 @@ class AlphaSynthWrapper {
|
|
|
43788
44012
|
this._playbackSpeed = 1;
|
|
43789
44013
|
this._isLooping = false;
|
|
43790
44014
|
this._midiEventsPlayedFilter = [];
|
|
43791
|
-
this.ready = new EventEmitter();
|
|
43792
|
-
this.readyForPlayback = new EventEmitter();
|
|
43793
44015
|
this.finished = new EventEmitter();
|
|
43794
44016
|
this.soundFontLoaded = new EventEmitter();
|
|
43795
44017
|
this.soundFontLoadFailed = new EventEmitterOfT();
|
|
43796
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
43797
44018
|
this.midiLoadFailed = new EventEmitterOfT();
|
|
43798
|
-
this.stateChanged = new EventEmitterOfT();
|
|
43799
|
-
this.positionChanged = new EventEmitterOfT();
|
|
43800
44019
|
this.midiEventsPlayed = new EventEmitterOfT();
|
|
43801
|
-
this.
|
|
44020
|
+
this.ready = new EventEmitter(() => this.isReady);
|
|
44021
|
+
this.readyForPlayback = new EventEmitter(() => this.isReadyForPlayback);
|
|
44022
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
44023
|
+
return this._instance?.loadedMidiInfo ?? null;
|
|
44024
|
+
});
|
|
44025
|
+
this.stateChanged = new EventEmitterOfT(() => {
|
|
44026
|
+
return new PlayerStateChangedEventArgs(this.state, false);
|
|
44027
|
+
});
|
|
44028
|
+
this.positionChanged = new EventEmitterOfT(() => {
|
|
44029
|
+
return this.currentPosition;
|
|
44030
|
+
});
|
|
44031
|
+
this.playbackRangeChanged = new EventEmitterOfT(() => {
|
|
44032
|
+
const range = this.playbackRange;
|
|
44033
|
+
if (range) {
|
|
44034
|
+
return new PlaybackRangeChangedEventArgs(range);
|
|
44035
|
+
}
|
|
44036
|
+
return null;
|
|
44037
|
+
});
|
|
43802
44038
|
}
|
|
43803
44039
|
get instance() {
|
|
43804
44040
|
return this._instance;
|
|
@@ -43820,10 +44056,14 @@ class AlphaSynthWrapper {
|
|
|
43820
44056
|
newUnregister.push(value.finished.on(() => this.finished.trigger()));
|
|
43821
44057
|
newUnregister.push(value.soundFontLoaded.on(() => this.soundFontLoaded.trigger()));
|
|
43822
44058
|
newUnregister.push(value.soundFontLoadFailed.on(e => this.soundFontLoadFailed.trigger(e)));
|
|
43823
|
-
newUnregister.push(value.midiLoaded.on(e =>
|
|
44059
|
+
newUnregister.push(value.midiLoaded.on(e => {
|
|
44060
|
+
this.midiLoaded.trigger(e);
|
|
44061
|
+
}));
|
|
43824
44062
|
newUnregister.push(value.midiLoadFailed.on(e => this.midiLoadFailed.trigger(e)));
|
|
43825
44063
|
newUnregister.push(value.stateChanged.on(e => this.stateChanged.trigger(e)));
|
|
43826
|
-
newUnregister.push(value.positionChanged.on(e =>
|
|
44064
|
+
newUnregister.push(value.positionChanged.on(e => {
|
|
44065
|
+
this.positionChanged.trigger(e);
|
|
44066
|
+
}));
|
|
43827
44067
|
newUnregister.push(value.midiEventsPlayed.on(e => this.midiEventsPlayed.trigger(e)));
|
|
43828
44068
|
newUnregister.push(value.playbackRangeChanged.on(e => this.playbackRangeChanged.trigger(e)));
|
|
43829
44069
|
this._instanceEventUnregister = newUnregister;
|
|
@@ -43902,6 +44142,14 @@ class AlphaSynthWrapper {
|
|
|
43902
44142
|
this._instance.playbackSpeed = value;
|
|
43903
44143
|
}
|
|
43904
44144
|
}
|
|
44145
|
+
get loadedMidiInfo() {
|
|
44146
|
+
return this._instance ? this._instance.loadedMidiInfo : undefined;
|
|
44147
|
+
}
|
|
44148
|
+
get currentPosition() {
|
|
44149
|
+
return this._instance
|
|
44150
|
+
? this._instance.currentPosition
|
|
44151
|
+
: new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
44152
|
+
}
|
|
43905
44153
|
get tickPosition() {
|
|
43906
44154
|
return this._instance ? this._instance.tickPosition : 0;
|
|
43907
44155
|
}
|
|
@@ -44243,83 +44491,6 @@ class AlphaTabApiBase {
|
|
|
44243
44491
|
this._previousStateForCursor = PlayerState.Paused;
|
|
44244
44492
|
this._previousCursorCache = null;
|
|
44245
44493
|
this._lastScroll = 0;
|
|
44246
|
-
/**
|
|
44247
|
-
* This event is fired when the played beat changed.
|
|
44248
|
-
*
|
|
44249
|
-
* @eventProperty
|
|
44250
|
-
* @category Events - Player
|
|
44251
|
-
* @since 0.9.4
|
|
44252
|
-
*
|
|
44253
|
-
* @example
|
|
44254
|
-
* JavaScript
|
|
44255
|
-
* ```js
|
|
44256
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44257
|
-
* api.playedBeatChanged.on((beat) => {
|
|
44258
|
-
* updateFretboard(beat);
|
|
44259
|
-
* });
|
|
44260
|
-
* ```
|
|
44261
|
-
*
|
|
44262
|
-
* @example
|
|
44263
|
-
* C#
|
|
44264
|
-
* ```cs
|
|
44265
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44266
|
-
* api.PlayedBeatChanged.On(beat =>
|
|
44267
|
-
* {
|
|
44268
|
-
* UpdateFretboard(beat);
|
|
44269
|
-
* });
|
|
44270
|
-
* ```
|
|
44271
|
-
*
|
|
44272
|
-
* @example
|
|
44273
|
-
* Android
|
|
44274
|
-
* ```kotlin
|
|
44275
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44276
|
-
* api.playedBeatChanged.on { beat ->
|
|
44277
|
-
* updateFretboard(beat)
|
|
44278
|
-
* }
|
|
44279
|
-
* ```
|
|
44280
|
-
*
|
|
44281
|
-
*/
|
|
44282
|
-
this.playedBeatChanged = new EventEmitterOfT();
|
|
44283
|
-
/**
|
|
44284
|
-
* This event is fired when the currently active beats across all tracks change.
|
|
44285
|
-
*
|
|
44286
|
-
* @remarks
|
|
44287
|
-
* Unlike the {@link playedBeatChanged} event this event contains the beats of all tracks and voices independent of them being rendered.
|
|
44288
|
-
*
|
|
44289
|
-
* @eventProperty
|
|
44290
|
-
* @category Events - Player
|
|
44291
|
-
* @since 1.2.3
|
|
44292
|
-
*
|
|
44293
|
-
* @example
|
|
44294
|
-
* JavaScript
|
|
44295
|
-
* ```js
|
|
44296
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44297
|
-
* api.activeBeatsChanged.on(args => {
|
|
44298
|
-
* updateHighlights(args.activeBeats);
|
|
44299
|
-
* });
|
|
44300
|
-
* ```
|
|
44301
|
-
*
|
|
44302
|
-
* @example
|
|
44303
|
-
* C#
|
|
44304
|
-
* ```cs
|
|
44305
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44306
|
-
* api.ActiveBeatsChanged.On(args =>
|
|
44307
|
-
* {
|
|
44308
|
-
* UpdateHighlights(args.ActiveBeats);
|
|
44309
|
-
* });
|
|
44310
|
-
* ```
|
|
44311
|
-
*
|
|
44312
|
-
* @example
|
|
44313
|
-
* Android
|
|
44314
|
-
* ```kotlin
|
|
44315
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44316
|
-
* api.activeBeatsChanged.on { args ->
|
|
44317
|
-
* updateHighlights(args.activeBeats)
|
|
44318
|
-
* }
|
|
44319
|
-
* ```
|
|
44320
|
-
*
|
|
44321
|
-
*/
|
|
44322
|
-
this.activeBeatsChanged = new EventEmitterOfT();
|
|
44323
44494
|
this._beatMouseDown = false;
|
|
44324
44495
|
this._noteMouseDown = false;
|
|
44325
44496
|
this._selectionStart = null;
|
|
@@ -44558,47 +44729,6 @@ class AlphaTabApiBase {
|
|
|
44558
44729
|
*
|
|
44559
44730
|
*/
|
|
44560
44731
|
this.noteMouseUp = new EventEmitterOfT();
|
|
44561
|
-
/**
|
|
44562
|
-
* This event is fired whenever a new song is loaded.
|
|
44563
|
-
* @remarks
|
|
44564
|
-
* This event is fired whenever a new song is loaded or changing due to {@link renderScore} or {@link renderTracks} calls.
|
|
44565
|
-
* It is fired after the transposition midi pitches from the settings were applied, but before any midi is generated or rendering is started.
|
|
44566
|
-
* This allows any modification of the score before further processing.
|
|
44567
|
-
*
|
|
44568
|
-
* @eventProperty
|
|
44569
|
-
* @category Events - Core
|
|
44570
|
-
* @since 0.9.4
|
|
44571
|
-
*
|
|
44572
|
-
* @example
|
|
44573
|
-
* JavaScript
|
|
44574
|
-
* ```js
|
|
44575
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44576
|
-
* api.scoreLoaded.on((score) => {
|
|
44577
|
-
* updateSongInformationInUi(score);
|
|
44578
|
-
* });
|
|
44579
|
-
* ```
|
|
44580
|
-
*
|
|
44581
|
-
* @example
|
|
44582
|
-
* C#
|
|
44583
|
-
* ```cs
|
|
44584
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44585
|
-
* api.ScoreLoaded.On(score =>
|
|
44586
|
-
* {
|
|
44587
|
-
* UpdateSongInformationInUi(score);
|
|
44588
|
-
* });
|
|
44589
|
-
* ```
|
|
44590
|
-
*
|
|
44591
|
-
* @example
|
|
44592
|
-
* Android
|
|
44593
|
-
* ```kotlin
|
|
44594
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44595
|
-
* api.scoreLoaded.on { score ->
|
|
44596
|
-
* updateSongInformationInUi(score)
|
|
44597
|
-
* }
|
|
44598
|
-
* ```
|
|
44599
|
-
*
|
|
44600
|
-
*/
|
|
44601
|
-
this.scoreLoaded = new EventEmitterOfT();
|
|
44602
44732
|
/**
|
|
44603
44733
|
* This event is fired when alphaTab was resized and is about to rerender the music notation.
|
|
44604
44734
|
* @remarks
|
|
@@ -44857,46 +44987,6 @@ class AlphaTabApiBase {
|
|
|
44857
44987
|
*
|
|
44858
44988
|
*/
|
|
44859
44989
|
this.midiLoad = new EventEmitterOfT();
|
|
44860
|
-
/**
|
|
44861
|
-
* This event is fired when the Midi file needed for playback was loaded.
|
|
44862
|
-
*
|
|
44863
|
-
* @eventProperty
|
|
44864
|
-
* @category Events - Player
|
|
44865
|
-
* @since 0.9.4
|
|
44866
|
-
*
|
|
44867
|
-
* @example
|
|
44868
|
-
* JavaScript
|
|
44869
|
-
* ```js
|
|
44870
|
-
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
44871
|
-
* api.midiLoaded.on(e => {
|
|
44872
|
-
* hideGeneratingAudioIndicator();
|
|
44873
|
-
* updateSongDuration(e.endTime);
|
|
44874
|
-
* });
|
|
44875
|
-
* ```
|
|
44876
|
-
*
|
|
44877
|
-
* @example
|
|
44878
|
-
* C#
|
|
44879
|
-
* ```cs
|
|
44880
|
-
* var api = new AlphaTabApi<MyControl>(...);
|
|
44881
|
-
* api.MidiLoaded.On(e =>
|
|
44882
|
-
* {
|
|
44883
|
-
* HideGeneratingAudioIndicator();
|
|
44884
|
-
* UpdateSongDuration(e.EndTime);
|
|
44885
|
-
* });
|
|
44886
|
-
* ```
|
|
44887
|
-
*
|
|
44888
|
-
* @example
|
|
44889
|
-
* Android
|
|
44890
|
-
* ```kotlin
|
|
44891
|
-
* val api = AlphaTabApi<MyControl>(...)
|
|
44892
|
-
* api.midiLoaded.on { e ->
|
|
44893
|
-
* hideGeneratingAudioIndicator()
|
|
44894
|
-
* updateSongDuration(e.endTime)
|
|
44895
|
-
* }
|
|
44896
|
-
* ```
|
|
44897
|
-
*
|
|
44898
|
-
*/
|
|
44899
|
-
this.midiLoaded = new EventEmitterOfT();
|
|
44900
44990
|
/**
|
|
44901
44991
|
* This event is fired when a settings update was requested.
|
|
44902
44992
|
*
|
|
@@ -44936,12 +45026,30 @@ class AlphaTabApiBase {
|
|
|
44936
45026
|
this.settingsUpdated = new EventEmitter();
|
|
44937
45027
|
this.uiFacade = uiFacade;
|
|
44938
45028
|
this.container = uiFacade.rootContainer;
|
|
45029
|
+
this.activeBeatsChanged = new EventEmitterOfT(() => {
|
|
45030
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45031
|
+
return new ActiveBeatsChangedEventArgs(this._currentBeat.beatLookup.highlightedBeats.map(h => h.beat));
|
|
45032
|
+
}
|
|
45033
|
+
return null;
|
|
45034
|
+
});
|
|
45035
|
+
this.playedBeatChanged = new EventEmitterOfT(() => {
|
|
45036
|
+
if (this._player.state === PlayerState.Playing && this._currentBeat) {
|
|
45037
|
+
return this._currentBeat.beat;
|
|
45038
|
+
}
|
|
45039
|
+
return null;
|
|
45040
|
+
});
|
|
45041
|
+
this.scoreLoaded = new EventEmitterOfT(() => {
|
|
45042
|
+
if (this._score) {
|
|
45043
|
+
return this._score;
|
|
45044
|
+
}
|
|
45045
|
+
return null;
|
|
45046
|
+
});
|
|
45047
|
+
this.midiLoaded = new EventEmitterOfT(() => {
|
|
45048
|
+
return this._player.loadedMidiInfo ?? null;
|
|
45049
|
+
});
|
|
44939
45050
|
uiFacade.initialize(this, settings);
|
|
44940
45051
|
Logger.logLevel = this.settings.core.logLevel;
|
|
44941
|
-
|
|
44942
|
-
if (this.settings.player.playerMode === PlayerMode.Disabled && this.settings.player.enablePlayer) {
|
|
44943
|
-
this.settings.player.playerMode = PlayerMode.EnabledAutomatic;
|
|
44944
|
-
}
|
|
45052
|
+
this.settings.handleBackwardsCompatibility();
|
|
44945
45053
|
Environment.printEnvironmentInfo(false);
|
|
44946
45054
|
this.canvasElement = uiFacade.createCanvasElement();
|
|
44947
45055
|
this.container.appendChild(this.canvasElement);
|
|
@@ -45100,6 +45208,7 @@ class AlphaTabApiBase {
|
|
|
45100
45208
|
* ```
|
|
45101
45209
|
*/
|
|
45102
45210
|
updateSettings() {
|
|
45211
|
+
this.settings.handleBackwardsCompatibility();
|
|
45103
45212
|
const score = this.score;
|
|
45104
45213
|
if (score) {
|
|
45105
45214
|
ModelUtils.applyPitchOffsets(this.settings, score);
|
|
@@ -45907,6 +46016,22 @@ class AlphaTabApiBase {
|
|
|
45907
46016
|
set timePosition(value) {
|
|
45908
46017
|
this._player.timePosition = value;
|
|
45909
46018
|
}
|
|
46019
|
+
/**
|
|
46020
|
+
* The total length of the song in midi ticks.
|
|
46021
|
+
* @category Properties - Player
|
|
46022
|
+
* @since 1.6.2
|
|
46023
|
+
*/
|
|
46024
|
+
get endTick() {
|
|
46025
|
+
return this._player.currentPosition.endTick;
|
|
46026
|
+
}
|
|
46027
|
+
/**
|
|
46028
|
+
* The total length of the song in milliseconds.
|
|
46029
|
+
* @category Properties - Player
|
|
46030
|
+
* @since 1.6.2
|
|
46031
|
+
*/
|
|
46032
|
+
get endTime() {
|
|
46033
|
+
return this._player.currentPosition.endTime;
|
|
46034
|
+
}
|
|
45910
46035
|
/**
|
|
45911
46036
|
* The range of the song that should be played.
|
|
45912
46037
|
* @remarks
|
|
@@ -48231,27 +48356,33 @@ class AlphaSynthWebWorkerApi {
|
|
|
48231
48356
|
value: value
|
|
48232
48357
|
});
|
|
48233
48358
|
}
|
|
48359
|
+
get loadedMidiInfo() {
|
|
48360
|
+
return this.loadedMidiInfo;
|
|
48361
|
+
}
|
|
48362
|
+
get currentPosition() {
|
|
48363
|
+
return this._currentPosition;
|
|
48364
|
+
}
|
|
48234
48365
|
get tickPosition() {
|
|
48235
|
-
return this.
|
|
48366
|
+
return this._currentPosition.currentTick;
|
|
48236
48367
|
}
|
|
48237
48368
|
set tickPosition(value) {
|
|
48238
48369
|
if (value < 0) {
|
|
48239
48370
|
value = 0;
|
|
48240
48371
|
}
|
|
48241
|
-
this.
|
|
48372
|
+
this._currentPosition = new PositionChangedEventArgs(this._currentPosition.currentTime, this._currentPosition.endTime, value, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48242
48373
|
this._synth.postMessage({
|
|
48243
48374
|
cmd: 'alphaSynth.setTickPosition',
|
|
48244
48375
|
value: value
|
|
48245
48376
|
});
|
|
48246
48377
|
}
|
|
48247
48378
|
get timePosition() {
|
|
48248
|
-
return this.
|
|
48379
|
+
return this._currentPosition.currentTime;
|
|
48249
48380
|
}
|
|
48250
48381
|
set timePosition(value) {
|
|
48251
48382
|
if (value < 0) {
|
|
48252
48383
|
value = 0;
|
|
48253
48384
|
}
|
|
48254
|
-
this.
|
|
48385
|
+
this._currentPosition = new PositionChangedEventArgs(value, this._currentPosition.endTime, this._currentPosition.currentTick, this._currentPosition.endTick, true, this._currentPosition.originalTempo, this._currentPosition.modifiedTempo);
|
|
48255
48386
|
this._synth.postMessage({
|
|
48256
48387
|
cmd: 'alphaSynth.setTimePosition',
|
|
48257
48388
|
value: value
|
|
@@ -48294,11 +48425,10 @@ class AlphaSynthWebWorkerApi {
|
|
|
48294
48425
|
this._metronomeVolume = 0;
|
|
48295
48426
|
this._countInVolume = 0;
|
|
48296
48427
|
this._playbackSpeed = 0;
|
|
48297
|
-
this._tickPosition = 0;
|
|
48298
|
-
this._timePosition = 0;
|
|
48299
48428
|
this._isLooping = false;
|
|
48300
48429
|
this._playbackRange = null;
|
|
48301
48430
|
this._midiEventsPlayedFilter = [];
|
|
48431
|
+
this._currentPosition = new PositionChangedEventArgs(0, 0, 0, 0, false, 120, 120);
|
|
48302
48432
|
this.ready = new EventEmitter();
|
|
48303
48433
|
this.readyForPlayback = new EventEmitter();
|
|
48304
48434
|
this.finished = new EventEmitter();
|
|
@@ -48317,8 +48447,6 @@ class AlphaSynthWebWorkerApi {
|
|
|
48317
48447
|
this._masterVolume = 0.0;
|
|
48318
48448
|
this._metronomeVolume = 0.0;
|
|
48319
48449
|
this._playbackSpeed = 0.0;
|
|
48320
|
-
this._tickPosition = 0;
|
|
48321
|
-
this._timePosition = 0.0;
|
|
48322
48450
|
this._isLooping = false;
|
|
48323
48451
|
this._playbackRange = null;
|
|
48324
48452
|
this._output = player;
|
|
@@ -48453,9 +48581,8 @@ class AlphaSynthWebWorkerApi {
|
|
|
48453
48581
|
this.checkReadyForPlayback();
|
|
48454
48582
|
break;
|
|
48455
48583
|
case 'alphaSynth.positionChanged':
|
|
48456
|
-
this.
|
|
48457
|
-
this.
|
|
48458
|
-
this.positionChanged.trigger(new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo));
|
|
48584
|
+
this._currentPosition = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48585
|
+
this.positionChanged.trigger(this._currentPosition);
|
|
48459
48586
|
break;
|
|
48460
48587
|
case 'alphaSynth.midiEventsPlayed':
|
|
48461
48588
|
this.midiEventsPlayed.trigger(new MidiEventsPlayedEventArgs(data.events.map(JsonConverter.jsObjectToMidiEvent)));
|
|
@@ -48479,7 +48606,8 @@ class AlphaSynthWebWorkerApi {
|
|
|
48479
48606
|
break;
|
|
48480
48607
|
case 'alphaSynth.midiLoaded':
|
|
48481
48608
|
this.checkReadyForPlayback();
|
|
48482
|
-
this.
|
|
48609
|
+
this._loadedMidiInfo = new PositionChangedEventArgs(data.currentTime, data.endTime, data.currentTick, data.endTick, data.isSeek, data.originalTempo, data.modifiedTempo);
|
|
48610
|
+
this.midiLoaded.trigger(this._loadedMidiInfo);
|
|
48483
48611
|
break;
|
|
48484
48612
|
case 'alphaSynth.midiLoadFailed':
|
|
48485
48613
|
this.checkReadyForPlayback();
|
|
@@ -66622,6 +66750,10 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66622
66750
|
track.score.stylesheet.perTrackMultiBarRest.has(track.index)) {
|
|
66623
66751
|
writer.writeLine(` multibarrest`);
|
|
66624
66752
|
}
|
|
66753
|
+
writer.writeLine(` instrument ${track.isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program)}`);
|
|
66754
|
+
if (track.playbackInfo.bank > 0) {
|
|
66755
|
+
writer.writeLine(` bank ${track.playbackInfo.bank}`);
|
|
66756
|
+
}
|
|
66625
66757
|
writer.outdent();
|
|
66626
66758
|
writer.writeLine('}');
|
|
66627
66759
|
writer.indent();
|
|
@@ -66680,13 +66812,7 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66680
66812
|
writer.writeLine('|');
|
|
66681
66813
|
}
|
|
66682
66814
|
if (voiceIndex === 0) {
|
|
66683
|
-
// Track meta on first bar
|
|
66684
66815
|
let anyWritten = false;
|
|
66685
|
-
if (bar.index === 0 && bar.staff.index === 0) {
|
|
66686
|
-
const l = writer.tex.length;
|
|
66687
|
-
this.writeTrackMetaTo(writer, bar.staff.track);
|
|
66688
|
-
anyWritten = writer.tex.length > l;
|
|
66689
|
-
}
|
|
66690
66816
|
// Staff meta on first bar
|
|
66691
66817
|
if (bar.index === 0) {
|
|
66692
66818
|
const l = writer.tex.length;
|
|
@@ -66716,14 +66842,6 @@ class AlphaTexExporter extends ScoreExporter {
|
|
|
66716
66842
|
}
|
|
66717
66843
|
writer.outdent();
|
|
66718
66844
|
}
|
|
66719
|
-
writeTrackMetaTo(writer, track) {
|
|
66720
|
-
writer.writeSingleLineComment(`Track ${track.index + 1} Metadata`);
|
|
66721
|
-
this.writePlaybackInfoTo(writer, track);
|
|
66722
|
-
}
|
|
66723
|
-
writePlaybackInfoTo(writer, track) {
|
|
66724
|
-
const isPercussion = track.staves.some(s => s.isPercussion);
|
|
66725
|
-
writer.writeMeta('instrument', isPercussion ? 'percussion' : GeneralMidi.getName(track.playbackInfo.program));
|
|
66726
|
-
}
|
|
66727
66845
|
writeStaffMetaTo(writer, staff) {
|
|
66728
66846
|
writer.writeSingleLineComment(`Staff ${staff.index + 1} Metadata`);
|
|
66729
66847
|
if (staff.capo !== 0) {
|
|
@@ -68346,15 +68464,16 @@ class GpifWriter {
|
|
|
68346
68464
|
}
|
|
68347
68465
|
return GpifIconIds.SteelGuitar;
|
|
68348
68466
|
}
|
|
68349
|
-
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, ratioPosition = 0) {
|
|
68467
|
+
writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, barIndex, program, bank, ratioPosition = 0) {
|
|
68350
68468
|
const soundNode = soundsNode.addElement('Sound');
|
|
68351
68469
|
soundNode.addElement('Name').setCData(name);
|
|
68352
68470
|
soundNode.addElement('Label').setCData(name);
|
|
68353
68471
|
soundNode.addElement('Path').setCData(path);
|
|
68354
68472
|
soundNode.addElement('Role').setCData(role);
|
|
68355
68473
|
const midi = soundNode.addElement('MIDI');
|
|
68356
|
-
|
|
68357
|
-
midi.addElement('
|
|
68474
|
+
const lsbMsb = GeneralMidi.bankToLsbMsb(bank);
|
|
68475
|
+
midi.addElement('LSB').innerText = lsbMsb[0].toString();
|
|
68476
|
+
midi.addElement('MSB').innerText = lsbMsb[1].toString();
|
|
68358
68477
|
midi.addElement('Program').innerText = program.toString();
|
|
68359
68478
|
const automationNode = automationsNode.addElement('Automation');
|
|
68360
68479
|
automationNode.addElement('Type').innerText = 'Sound';
|
|
@@ -68372,21 +68491,26 @@ class GpifWriter {
|
|
|
68372
68491
|
const trackSoundPath = `Midi/${track.playbackInfo.program}`;
|
|
68373
68492
|
const trackSoundRole = 'Factory';
|
|
68374
68493
|
let trackSoundWritten = false;
|
|
68494
|
+
let bank = track.playbackInfo.bank;
|
|
68375
68495
|
for (const staff of track.staves) {
|
|
68376
68496
|
for (const bar of staff.bars) {
|
|
68377
68497
|
for (const voice of bar.voices) {
|
|
68378
68498
|
for (const beat of voice.beats) {
|
|
68379
68499
|
const soundAutomation = beat.getAutomation(AutomationType.Instrument);
|
|
68380
68500
|
const isTrackSound = bar.index === 0 && beat.index === 0;
|
|
68501
|
+
const bankAutomation = beat.getAutomation(AutomationType.Bank);
|
|
68502
|
+
if (bankAutomation) {
|
|
68503
|
+
bank = bankAutomation.value;
|
|
68504
|
+
}
|
|
68381
68505
|
if (soundAutomation) {
|
|
68382
68506
|
const name = isTrackSound ? trackSoundName : `ProgramChange_${beat.id}`;
|
|
68383
68507
|
const path = isTrackSound ? trackSoundPath : `Midi/${soundAutomation.value}`;
|
|
68384
68508
|
const role = isTrackSound ? trackSoundRole : 'User';
|
|
68385
68509
|
if (!isTrackSound && !trackSoundWritten) {
|
|
68386
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program);
|
|
68510
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, trackSoundName, trackSoundPath, trackSoundRole, track.staves[0].bars[0].index, track.playbackInfo.program, track.playbackInfo.bank);
|
|
68387
68511
|
trackSoundWritten = true;
|
|
68388
68512
|
}
|
|
68389
|
-
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, soundAutomation.ratioPosition);
|
|
68513
|
+
this.writeSoundAndAutomation(soundsNode, automationsNode, name, path, role, bar.index, soundAutomation.value, bank, soundAutomation.ratioPosition);
|
|
68390
68514
|
if (isTrackSound) {
|
|
68391
68515
|
trackSoundWritten = true;
|
|
68392
68516
|
}
|