spessasynth_core 4.0.15 → 4.0.17
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/index.d.ts +30 -9
- package/dist/index.js +159 -151
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3743,6 +3743,7 @@ interface SequencerEventData {
|
|
|
3743
3743
|
};
|
|
3744
3744
|
/**
|
|
3745
3745
|
* Called when the playback stops.
|
|
3746
|
+
* @deprecated use songEnded instead.
|
|
3746
3747
|
*/
|
|
3747
3748
|
pause: {
|
|
3748
3749
|
/**
|
|
@@ -3750,6 +3751,10 @@ interface SequencerEventData {
|
|
|
3750
3751
|
*/
|
|
3751
3752
|
isFinished: boolean;
|
|
3752
3753
|
};
|
|
3754
|
+
/**
|
|
3755
|
+
* Called when the playback stops.
|
|
3756
|
+
*/
|
|
3757
|
+
songEnded: object;
|
|
3753
3758
|
/**
|
|
3754
3759
|
* Called when the song changes.
|
|
3755
3760
|
*/
|
|
@@ -3817,6 +3822,11 @@ declare class SpessaSynthSequencer {
|
|
|
3817
3822
|
* This is used by spessasynth_lib to pass them over to Web MIDI API.
|
|
3818
3823
|
*/
|
|
3819
3824
|
externalMIDIPlayback: boolean;
|
|
3825
|
+
/**
|
|
3826
|
+
* If the notes that were playing when the sequencer was paused should be re-triggered.
|
|
3827
|
+
* Defaults to true.
|
|
3828
|
+
*/
|
|
3829
|
+
retriggerPausedNotes: boolean;
|
|
3820
3830
|
/**
|
|
3821
3831
|
* The loop count of the sequencer.
|
|
3822
3832
|
* If infinite, it will loop forever.
|
|
@@ -3828,6 +3838,15 @@ declare class SpessaSynthSequencer {
|
|
|
3828
3838
|
* Defaults to true.
|
|
3829
3839
|
*/
|
|
3830
3840
|
skipToFirstNoteOn: boolean;
|
|
3841
|
+
/**
|
|
3842
|
+
* Indicates if the sequencer has finished playing.
|
|
3843
|
+
*/
|
|
3844
|
+
isFinished: boolean;
|
|
3845
|
+
/**
|
|
3846
|
+
* Indicates if the synthesizer should preload the voices for the newly loaded sequence.
|
|
3847
|
+
* Recommended.
|
|
3848
|
+
*/
|
|
3849
|
+
preload: boolean;
|
|
3831
3850
|
/**
|
|
3832
3851
|
* Called when the sequencer calls an event.
|
|
3833
3852
|
* @param event The event
|
|
@@ -3987,18 +4006,10 @@ declare class SpessaSynthSequencer {
|
|
|
3987
4006
|
*/
|
|
3988
4007
|
protected addNewMIDIPort(): void;
|
|
3989
4008
|
protected sendMIDIMessage(message: number[]): void;
|
|
4009
|
+
protected sendMIDIAllOff(): void;
|
|
3990
4010
|
protected sendMIDIReset(): void;
|
|
3991
4011
|
protected loadCurrentSong(): void;
|
|
3992
4012
|
protected shuffleSongIndexes(): void;
|
|
3993
|
-
protected sendMIDICC(channel: number, type: number, value: number): void;
|
|
3994
|
-
protected sendMIDIProgramChange(channel: number, program: number): void;
|
|
3995
|
-
/**
|
|
3996
|
-
* Sets the pitch of the given channel
|
|
3997
|
-
* @param channel usually 0-15: the channel to change pitch
|
|
3998
|
-
* @param MSB SECOND byte of the MIDI pitchWheel message
|
|
3999
|
-
* @param LSB FIRST byte of the MIDI pitchWheel message
|
|
4000
|
-
*/
|
|
4001
|
-
protected sendMIDIPitchWheel(channel: number, MSB: number, LSB: number): void;
|
|
4002
4013
|
/**
|
|
4003
4014
|
* Sets the time in MIDI ticks.
|
|
4004
4015
|
* @param ticks the MIDI ticks to set the time to.
|
|
@@ -4009,6 +4020,16 @@ declare class SpessaSynthSequencer {
|
|
|
4009
4020
|
* @param time the time in seconds to recalculate the start time for.
|
|
4010
4021
|
*/
|
|
4011
4022
|
protected recalculateStartTime(time: number): void;
|
|
4023
|
+
protected sendMIDINoteOn(channel: number, midiNote: number, velocity: number): void;
|
|
4024
|
+
protected sendMIDINoteOff(channel: number, midiNote: number): void;
|
|
4025
|
+
protected sendMIDICC(channel: number, type: MIDIController, value: number): void;
|
|
4026
|
+
protected sendMIDIProgramChange(channel: number, program: number): void;
|
|
4027
|
+
/**
|
|
4028
|
+
* Sets the pitch of the given channel
|
|
4029
|
+
* @param channel usually 0-15: the channel to change pitch
|
|
4030
|
+
* @param pitch the 14-bit pitch value
|
|
4031
|
+
*/
|
|
4032
|
+
protected sendMIDIPitchWheel(channel: number, pitch: number): void;
|
|
4012
4033
|
}
|
|
4013
4034
|
|
|
4014
4035
|
declare const DEFAULT_MASTER_PARAMETERS: MasterParameterType;
|
package/dist/index.js
CHANGED
|
@@ -3942,10 +3942,12 @@ function loadNewSequenceInternal(parsedMidi) {
|
|
|
3942
3942
|
if (parsedMidi.duration === 0) {
|
|
3943
3943
|
SpessaSynthWarn("This MIDI file has a duration of exactly 0 seconds.");
|
|
3944
3944
|
this.pausedTime = 0;
|
|
3945
|
+
this.isFinished = true;
|
|
3945
3946
|
return;
|
|
3946
3947
|
}
|
|
3947
3948
|
this.oneTickToSeconds = 60 / (120 * parsedMidi.timeDivision);
|
|
3948
3949
|
this._midiData = parsedMidi;
|
|
3950
|
+
this.isFinished = false;
|
|
3949
3951
|
this.synth.clearEmbeddedBank();
|
|
3950
3952
|
if (this._midiData.embeddedSoundBank !== void 0) {
|
|
3951
3953
|
SpessaSynthInfo(
|
|
@@ -3957,23 +3959,33 @@ function loadNewSequenceInternal(parsedMidi) {
|
|
|
3957
3959
|
this._midiData.bankOffset
|
|
3958
3960
|
);
|
|
3959
3961
|
}
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
);
|
|
3964
|
-
used.forEach((combos, preset) => {
|
|
3965
|
-
SpessaSynthInfo(
|
|
3966
|
-
`%cPreloading used samples on %c${preset.name}%c...`,
|
|
3967
|
-
consoleColors.info,
|
|
3968
|
-
consoleColors.recognized,
|
|
3962
|
+
if (this.preload) {
|
|
3963
|
+
SpessaSynthGroupCollapsed(
|
|
3964
|
+
"%cPreloading samples...",
|
|
3969
3965
|
consoleColors.info
|
|
3970
3966
|
);
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3967
|
+
const used = this._midiData.getUsedProgramsAndKeys(
|
|
3968
|
+
this.synth.soundBankManager
|
|
3969
|
+
);
|
|
3970
|
+
used.forEach((combos, preset) => {
|
|
3971
|
+
SpessaSynthInfo(
|
|
3972
|
+
`%cPreloading used samples on %c${preset.name}%c...`,
|
|
3973
|
+
consoleColors.info,
|
|
3974
|
+
consoleColors.recognized,
|
|
3975
|
+
consoleColors.info
|
|
3976
|
+
);
|
|
3977
|
+
for (const combo of combos) {
|
|
3978
|
+
const [midiNote, velocity] = combo.split("-").map(Number);
|
|
3979
|
+
this.synth.getVoicesForPreset(
|
|
3980
|
+
preset,
|
|
3981
|
+
midiNote,
|
|
3982
|
+
velocity,
|
|
3983
|
+
midiNote
|
|
3984
|
+
);
|
|
3985
|
+
}
|
|
3986
|
+
});
|
|
3987
|
+
SpessaSynthGroupEnd();
|
|
3988
|
+
}
|
|
3977
3989
|
this.currentMIDIPorts = this._midiData.tracks.map((t) => t.port);
|
|
3978
3990
|
this.midiPortChannelOffset = 0;
|
|
3979
3991
|
this.midiPortChannelOffsets = {};
|
|
@@ -4722,12 +4734,7 @@ function setTimeToInternal(time, ticks = void 0) {
|
|
|
4722
4734
|
return false;
|
|
4723
4735
|
}
|
|
4724
4736
|
this.oneTickToSeconds = 60 / (120 * this._midiData.timeDivision);
|
|
4725
|
-
|
|
4726
|
-
this.sendMIDIReset();
|
|
4727
|
-
} else {
|
|
4728
|
-
this.synth.resetAllControllers();
|
|
4729
|
-
this.synth.stopAllChannels(false);
|
|
4730
|
-
}
|
|
4737
|
+
this.sendMIDIReset();
|
|
4731
4738
|
this.playedTime = 0;
|
|
4732
4739
|
this.eventIndexes = Array(this._midiData.tracks.length).fill(0);
|
|
4733
4740
|
const channelsToSave = this.synth.midiChannels.length;
|
|
@@ -4811,15 +4818,7 @@ function setTimeToInternal(time, ticks = void 0) {
|
|
|
4811
4818
|
} else if (controllerNumber === midiControllers.resetAllControllers) {
|
|
4812
4819
|
resetAllControllers(channel);
|
|
4813
4820
|
}
|
|
4814
|
-
|
|
4815
|
-
this.sendMIDICC(channel, controllerNumber, ccV);
|
|
4816
|
-
} else {
|
|
4817
|
-
this.synth.controllerChange(
|
|
4818
|
-
channel,
|
|
4819
|
-
controllerNumber,
|
|
4820
|
-
ccV
|
|
4821
|
-
);
|
|
4822
|
-
}
|
|
4821
|
+
this.sendMIDICC(channel, controllerNumber, ccV);
|
|
4823
4822
|
} else {
|
|
4824
4823
|
savedControllers[channel] ??= Array.from(
|
|
4825
4824
|
defaultControllerArray
|
|
@@ -4847,70 +4846,28 @@ function setTimeToInternal(time, ticks = void 0) {
|
|
|
4847
4846
|
}
|
|
4848
4847
|
this.playedTime += this.oneTickToSeconds * (nextEvent.ticks - event.ticks);
|
|
4849
4848
|
}
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
});
|
|
4865
|
-
}
|
|
4866
|
-
if (programs[channelNumber].program >= 0 && programs[channelNumber].actualBank >= 0) {
|
|
4867
|
-
const bank = programs[channelNumber].actualBank;
|
|
4849
|
+
for (let channel = 0; channel < channelsToSave; channel++) {
|
|
4850
|
+
if (pitchWheels[channel] !== void 0) {
|
|
4851
|
+
this.sendMIDIPitchWheel(channel, pitchWheels[channel]);
|
|
4852
|
+
}
|
|
4853
|
+
if (savedControllers[channel] !== void 0) {
|
|
4854
|
+
savedControllers[channel].forEach((value, index) => {
|
|
4855
|
+
if (value !== defaultControllerArray[index] && !isCCNonSkippable(index)) {
|
|
4856
|
+
this.sendMIDICC(channel, index, value);
|
|
4857
|
+
}
|
|
4858
|
+
});
|
|
4859
|
+
}
|
|
4860
|
+
if (programs[channel].actualBank >= 0) {
|
|
4861
|
+
const p = programs[channel];
|
|
4862
|
+
if (p.program !== -1) {
|
|
4868
4863
|
this.sendMIDICC(
|
|
4869
|
-
|
|
4864
|
+
channel,
|
|
4870
4865
|
midiControllers.bankSelect,
|
|
4871
|
-
|
|
4872
|
-
);
|
|
4873
|
-
this.sendMIDIProgramChange(
|
|
4874
|
-
channelNumber,
|
|
4875
|
-
programs[channelNumber].program
|
|
4876
|
-
);
|
|
4877
|
-
}
|
|
4878
|
-
}
|
|
4879
|
-
} else {
|
|
4880
|
-
for (let channelNumber = 0; channelNumber < channelsToSave; channelNumber++) {
|
|
4881
|
-
if (pitchWheels[channelNumber] !== void 0) {
|
|
4882
|
-
this.synth.pitchWheel(
|
|
4883
|
-
channelNumber,
|
|
4884
|
-
pitchWheels[channelNumber]
|
|
4866
|
+
p.actualBank
|
|
4885
4867
|
);
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
if (value !== defaultControllerArray[index] && !isCCNonSkippable(index)) {
|
|
4890
|
-
this.synth.controllerChange(
|
|
4891
|
-
channelNumber,
|
|
4892
|
-
index,
|
|
4893
|
-
value
|
|
4894
|
-
);
|
|
4895
|
-
}
|
|
4896
|
-
});
|
|
4897
|
-
}
|
|
4898
|
-
if (programs[channelNumber].actualBank >= 0) {
|
|
4899
|
-
const p = programs[channelNumber];
|
|
4900
|
-
if (p.program !== -1) {
|
|
4901
|
-
this.synth.controllerChange(
|
|
4902
|
-
channelNumber,
|
|
4903
|
-
midiControllers.bankSelect,
|
|
4904
|
-
p.actualBank
|
|
4905
|
-
);
|
|
4906
|
-
this.synth.programChange(channelNumber, p.program);
|
|
4907
|
-
} else {
|
|
4908
|
-
this.synth.controllerChange(
|
|
4909
|
-
channelNumber,
|
|
4910
|
-
midiControllers.bankSelect,
|
|
4911
|
-
p.bank
|
|
4912
|
-
);
|
|
4913
|
-
}
|
|
4868
|
+
this.sendMIDIProgramChange(channel, p.program);
|
|
4869
|
+
} else {
|
|
4870
|
+
this.sendMIDICC(channel, midiControllers.bankSelect, p.bank);
|
|
4914
4871
|
}
|
|
4915
4872
|
}
|
|
4916
4873
|
}
|
|
@@ -4946,6 +4903,11 @@ var SpessaSynthSequencer = class {
|
|
|
4946
4903
|
* This is used by spessasynth_lib to pass them over to Web MIDI API.
|
|
4947
4904
|
*/
|
|
4948
4905
|
externalMIDIPlayback = false;
|
|
4906
|
+
/**
|
|
4907
|
+
* If the notes that were playing when the sequencer was paused should be re-triggered.
|
|
4908
|
+
* Defaults to true.
|
|
4909
|
+
*/
|
|
4910
|
+
retriggerPausedNotes = false;
|
|
4949
4911
|
/**
|
|
4950
4912
|
* The loop count of the sequencer.
|
|
4951
4913
|
* If infinite, it will loop forever.
|
|
@@ -4957,6 +4919,15 @@ var SpessaSynthSequencer = class {
|
|
|
4957
4919
|
* Defaults to true.
|
|
4958
4920
|
*/
|
|
4959
4921
|
skipToFirstNoteOn = true;
|
|
4922
|
+
/**
|
|
4923
|
+
* Indicates if the sequencer has finished playing.
|
|
4924
|
+
*/
|
|
4925
|
+
isFinished = false;
|
|
4926
|
+
/**
|
|
4927
|
+
* Indicates if the synthesizer should preload the voices for the newly loaded sequence.
|
|
4928
|
+
* Recommended.
|
|
4929
|
+
*/
|
|
4930
|
+
preload = false;
|
|
4960
4931
|
/**
|
|
4961
4932
|
* Called when the sequencer calls an event.
|
|
4962
4933
|
* @param event The event
|
|
@@ -5168,9 +5139,9 @@ var SpessaSynthSequencer = class {
|
|
|
5168
5139
|
if (this.paused) {
|
|
5169
5140
|
this.recalculateStartTime(this.pausedTime ?? 0);
|
|
5170
5141
|
}
|
|
5171
|
-
if (
|
|
5142
|
+
if (this.retriggerPausedNotes) {
|
|
5172
5143
|
this.playingNotes.forEach((n) => {
|
|
5173
|
-
this.
|
|
5144
|
+
this.sendMIDINoteOn(n.channel, n.midiNote, n.velocity);
|
|
5174
5145
|
});
|
|
5175
5146
|
}
|
|
5176
5147
|
this.pausedTime = void 0;
|
|
@@ -5208,8 +5179,12 @@ var SpessaSynthSequencer = class {
|
|
|
5208
5179
|
}
|
|
5209
5180
|
this.stop();
|
|
5210
5181
|
this.callEvent("pause", { isFinished });
|
|
5182
|
+
if (isFinished) {
|
|
5183
|
+
this.callEvent("songEnded", {});
|
|
5184
|
+
}
|
|
5211
5185
|
}
|
|
5212
5186
|
songIsFinished() {
|
|
5187
|
+
this.isFinished = true;
|
|
5213
5188
|
if (this.songs.length === 1) {
|
|
5214
5189
|
this.pauseInternal(true);
|
|
5215
5190
|
return;
|
|
@@ -5223,21 +5198,7 @@ var SpessaSynthSequencer = class {
|
|
|
5223
5198
|
*/
|
|
5224
5199
|
stop() {
|
|
5225
5200
|
this.pausedTime = this.currentTime;
|
|
5226
|
-
|
|
5227
|
-
this.synth.controllerChange(i, midiControllers.sustainPedal, 0);
|
|
5228
|
-
}
|
|
5229
|
-
this.synth.stopAllChannels();
|
|
5230
|
-
if (this.externalMIDIPlayback) {
|
|
5231
|
-
for (const note of this.playingNotes) {
|
|
5232
|
-
this.sendMIDIMessage([
|
|
5233
|
-
midiMessageTypes.noteOff | note.channel % 16,
|
|
5234
|
-
note.midiNote
|
|
5235
|
-
]);
|
|
5236
|
-
}
|
|
5237
|
-
for (let c = 0; c < MIDI_CHANNEL_COUNT; c++) {
|
|
5238
|
-
this.sendMIDICC(c, midiControllers.allNotesOff, 0);
|
|
5239
|
-
}
|
|
5240
|
-
}
|
|
5201
|
+
this.sendMIDIAllOff();
|
|
5241
5202
|
}
|
|
5242
5203
|
/**
|
|
5243
5204
|
* @returns the index of the first to the current played time
|
|
@@ -5267,24 +5228,36 @@ var SpessaSynthSequencer = class {
|
|
|
5267
5228
|
}
|
|
5268
5229
|
sendMIDIMessage(message) {
|
|
5269
5230
|
if (!this.externalMIDIPlayback) {
|
|
5231
|
+
SpessaSynthWarn(
|
|
5232
|
+
`Attempting to send ${arrayToHexString(message)} to the synthesizer via sendMIDIMessage. This shouldn't happen!`
|
|
5233
|
+
);
|
|
5270
5234
|
return;
|
|
5271
5235
|
}
|
|
5272
5236
|
this.callEvent("midiMessage", { message });
|
|
5273
5237
|
}
|
|
5238
|
+
sendMIDIAllOff() {
|
|
5239
|
+
for (let i = 0; i < 16; i++) {
|
|
5240
|
+
this.sendMIDICC(i, midiControllers.sustainPedal, 0);
|
|
5241
|
+
}
|
|
5242
|
+
if (!this.externalMIDIPlayback) {
|
|
5243
|
+
this.synth.stopAllChannels();
|
|
5244
|
+
return;
|
|
5245
|
+
}
|
|
5246
|
+
this.playingNotes.forEach((note) => {
|
|
5247
|
+
this.sendMIDINoteOff(note.channel, note.midiNote);
|
|
5248
|
+
});
|
|
5249
|
+
for (let c = 0; c < MIDI_CHANNEL_COUNT; c++) {
|
|
5250
|
+
this.sendMIDICC(c, midiControllers.allNotesOff, 0);
|
|
5251
|
+
this.sendMIDICC(c, midiControllers.allSoundOff, 0);
|
|
5252
|
+
}
|
|
5253
|
+
}
|
|
5274
5254
|
sendMIDIReset() {
|
|
5275
|
-
this.
|
|
5276
|
-
|
|
5277
|
-
this.
|
|
5278
|
-
|
|
5279
|
-
midiControllers.allSoundOff,
|
|
5280
|
-
0
|
|
5281
|
-
]);
|
|
5282
|
-
this.sendMIDIMessage([
|
|
5283
|
-
midiMessageTypes.controllerChange | ch,
|
|
5284
|
-
midiControllers.resetAllControllers,
|
|
5285
|
-
0
|
|
5286
|
-
]);
|
|
5255
|
+
this.sendMIDIAllOff();
|
|
5256
|
+
if (!this.externalMIDIPlayback) {
|
|
5257
|
+
this.synth.resetAllControllers();
|
|
5258
|
+
return;
|
|
5287
5259
|
}
|
|
5260
|
+
this.sendMIDIMessage([midiMessageTypes.reset]);
|
|
5288
5261
|
}
|
|
5289
5262
|
loadCurrentSong() {
|
|
5290
5263
|
let index = this._songIndex;
|
|
@@ -5302,11 +5275,65 @@ var SpessaSynthSequencer = class {
|
|
|
5302
5275
|
indexes.splice(indexes.indexOf(index), 1);
|
|
5303
5276
|
}
|
|
5304
5277
|
}
|
|
5305
|
-
|
|
5278
|
+
/**
|
|
5279
|
+
* Sets the time in MIDI ticks.
|
|
5280
|
+
* @param ticks the MIDI ticks to set the time to.
|
|
5281
|
+
*/
|
|
5282
|
+
setTimeTicks(ticks) {
|
|
5283
|
+
if (!this._midiData) {
|
|
5284
|
+
return;
|
|
5285
|
+
}
|
|
5286
|
+
this.playingNotes = [];
|
|
5287
|
+
const seconds = this._midiData.midiTicksToSeconds(ticks);
|
|
5288
|
+
this.callEvent("timeChange", { newTime: seconds });
|
|
5289
|
+
const isNotFinished = this.setTimeTo(0, ticks);
|
|
5290
|
+
this.recalculateStartTime(this.playedTime);
|
|
5291
|
+
if (!isNotFinished) {
|
|
5292
|
+
return;
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5295
|
+
/**
|
|
5296
|
+
* Recalculates the absolute start time of the sequencer.
|
|
5297
|
+
* @param time the time in seconds to recalculate the start time for.
|
|
5298
|
+
*/
|
|
5299
|
+
recalculateStartTime(time) {
|
|
5300
|
+
this.absoluteStartTime = this.synth.currentSynthTime - time / this._playbackRate;
|
|
5301
|
+
}
|
|
5302
|
+
/*
|
|
5303
|
+
SEND MIDI METHOD ABSTRACTIONS
|
|
5304
|
+
These abstract the difference between spessasynth and external MIDI
|
|
5305
|
+
*/
|
|
5306
|
+
sendMIDINoteOn(channel, midiNote, velocity) {
|
|
5307
|
+
if (!this.externalMIDIPlayback) {
|
|
5308
|
+
this.synth.noteOn(channel, midiNote, velocity);
|
|
5309
|
+
return;
|
|
5310
|
+
}
|
|
5311
|
+
channel %= 16;
|
|
5312
|
+
this.sendMIDIMessage([
|
|
5313
|
+
midiMessageTypes.noteOn | channel,
|
|
5314
|
+
midiNote,
|
|
5315
|
+
velocity
|
|
5316
|
+
]);
|
|
5317
|
+
}
|
|
5318
|
+
sendMIDINoteOff(channel, midiNote) {
|
|
5319
|
+
if (!this.externalMIDIPlayback) {
|
|
5320
|
+
this.synth.noteOff(channel, midiNote);
|
|
5321
|
+
return;
|
|
5322
|
+
}
|
|
5306
5323
|
channel %= 16;
|
|
5324
|
+
this.sendMIDIMessage([
|
|
5325
|
+
midiMessageTypes.noteOff | channel,
|
|
5326
|
+
midiNote,
|
|
5327
|
+
64
|
|
5328
|
+
// Make sure to send velocity as well
|
|
5329
|
+
]);
|
|
5330
|
+
}
|
|
5331
|
+
sendMIDICC(channel, type, value) {
|
|
5307
5332
|
if (!this.externalMIDIPlayback) {
|
|
5333
|
+
this.synth.controllerChange(channel, type, value);
|
|
5308
5334
|
return;
|
|
5309
5335
|
}
|
|
5336
|
+
channel %= 16;
|
|
5310
5337
|
this.sendMIDIMessage([
|
|
5311
5338
|
midiMessageTypes.controllerChange | channel,
|
|
5312
5339
|
type,
|
|
@@ -5314,10 +5341,11 @@ var SpessaSynthSequencer = class {
|
|
|
5314
5341
|
]);
|
|
5315
5342
|
}
|
|
5316
5343
|
sendMIDIProgramChange(channel, program) {
|
|
5317
|
-
channel %= 16;
|
|
5318
5344
|
if (!this.externalMIDIPlayback) {
|
|
5345
|
+
this.synth.programChange(channel, program);
|
|
5319
5346
|
return;
|
|
5320
5347
|
}
|
|
5348
|
+
channel %= 16;
|
|
5321
5349
|
this.sendMIDIMessage([
|
|
5322
5350
|
midiMessageTypes.programChange | channel,
|
|
5323
5351
|
program
|
|
@@ -5326,39 +5354,19 @@ var SpessaSynthSequencer = class {
|
|
|
5326
5354
|
/**
|
|
5327
5355
|
* Sets the pitch of the given channel
|
|
5328
5356
|
* @param channel usually 0-15: the channel to change pitch
|
|
5329
|
-
* @param
|
|
5330
|
-
* @param LSB FIRST byte of the MIDI pitchWheel message
|
|
5357
|
+
* @param pitch the 14-bit pitch value
|
|
5331
5358
|
*/
|
|
5332
|
-
sendMIDIPitchWheel(channel,
|
|
5333
|
-
channel %= 16;
|
|
5359
|
+
sendMIDIPitchWheel(channel, pitch) {
|
|
5334
5360
|
if (!this.externalMIDIPlayback) {
|
|
5361
|
+
this.synth.pitchWheel(channel, pitch);
|
|
5335
5362
|
return;
|
|
5336
5363
|
}
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
setTimeTicks(ticks) {
|
|
5344
|
-
if (!this._midiData) {
|
|
5345
|
-
return;
|
|
5346
|
-
}
|
|
5347
|
-
this.playingNotes = [];
|
|
5348
|
-
const seconds = this._midiData.midiTicksToSeconds(ticks);
|
|
5349
|
-
this.callEvent("timeChange", { newTime: seconds });
|
|
5350
|
-
const isNotFinished = this.setTimeTo(0, ticks);
|
|
5351
|
-
this.recalculateStartTime(this.playedTime);
|
|
5352
|
-
if (!isNotFinished) {
|
|
5353
|
-
return;
|
|
5354
|
-
}
|
|
5355
|
-
}
|
|
5356
|
-
/**
|
|
5357
|
-
* Recalculates the absolute start time of the sequencer.
|
|
5358
|
-
* @param time the time in seconds to recalculate the start time for.
|
|
5359
|
-
*/
|
|
5360
|
-
recalculateStartTime(time) {
|
|
5361
|
-
this.absoluteStartTime = this.synth.currentSynthTime - time / this._playbackRate;
|
|
5364
|
+
channel %= 16;
|
|
5365
|
+
this.sendMIDIMessage([
|
|
5366
|
+
midiMessageTypes.pitchWheel | channel,
|
|
5367
|
+
pitch & 127,
|
|
5368
|
+
pitch >> 7
|
|
5369
|
+
]);
|
|
5362
5370
|
}
|
|
5363
5371
|
};
|
|
5364
5372
|
|