spessasynth_lib 3.21.4 → 3.21.6

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.
@@ -68,6 +68,12 @@ export class Sequencer {
68
68
  * @type {boolean}
69
69
  */
70
70
  isFinished: boolean;
71
+ /**
72
+ * Indicates if the sequencer is paused.
73
+ * Paused if a number, undefined if playing
74
+ * @type {undefined|number}
75
+ */
76
+ pausedTime: undefined | number;
71
77
  /**
72
78
  * The current sequence's length, in seconds
73
79
  * @type {number}
@@ -146,7 +152,6 @@ export class Sequencer {
146
152
  * @private
147
153
  */
148
154
  private _handleMessage;
149
- pausedTime: number;
150
155
  /**
151
156
  * @param time
152
157
  * @private
@@ -157,9 +162,11 @@ export class Sequencer {
157
162
  */
158
163
  getMIDI(): Promise<MIDI>;
159
164
  /**
160
- * @param midiBuffers {MIDIFile[]}
165
+ * Loads a new song list
166
+ * @param midiBuffers {MIDIFile[]} - the MIDI files to play
167
+ * @param autoPlay {boolean} - if true, the first sequence will automatically start playing
161
168
  */
162
- loadNewSongList(midiBuffers: MIDIFile[]): void;
169
+ loadNewSongList(midiBuffers: MIDIFile[], autoPlay?: boolean): void;
163
170
  songsAmount: number;
164
171
  /**
165
172
  * @param output {MIDIOutput}
@@ -199,7 +206,11 @@ export type SequencerOptions = {
199
206
  /**
200
207
  * - if true, the sequencer will skip to the first note
201
208
  */
202
- skipToFirstNoteOn: boolean;
209
+ skipToFirstNoteOn: boolean | undefined;
210
+ /**
211
+ * - if true, the sequencer will automatically start playing the MIDI
212
+ */
213
+ autoPlay: boolean | undefined;
203
214
  };
204
215
  import { MidiData } from "../midi_parser/midi_data.js";
205
216
  import { Synthetizer } from "../synthetizer/synthetizer.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_lib",
3
- "version": "3.21.4",
3
+ "version": "3.21.6",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "browser": "index.js",
6
6
  "types": "@types/index.d.ts",
@@ -26,14 +26,16 @@ import { DUMMY_MIDI_DATA, MidiData } from "../midi_parser/midi_data.js";
26
26
 
27
27
  /**
28
28
  * @typedef {Object} SequencerOptions
29
- * @property {boolean} skipToFirstNoteOn - if true, the sequencer will skip to the first note
29
+ * @property {boolean|undefined} skipToFirstNoteOn - if true, the sequencer will skip to the first note
30
+ * @property {boolean|undefined} autoPlay - if true, the sequencer will automatically start playing the MIDI
30
31
  */
31
32
 
32
33
  /**
33
34
  * @type {SequencerOptions}
34
35
  */
35
36
  const DEFAULT_OPTIONS = {
36
- skipToFirstNoteOn: true
37
+ skipToFirstNoteOn: true,
38
+ autoPlay: true
37
39
  };
38
40
 
39
41
  export class Sequencer
@@ -117,6 +119,13 @@ export class Sequencer
117
119
  */
118
120
  this.isFinished = false;
119
121
 
122
+ /**
123
+ * Indicates if the sequencer is paused.
124
+ * Paused if a number, undefined if playing
125
+ * @type {undefined|number}
126
+ */
127
+ this.pausedTime = undefined;
128
+
120
129
  /**
121
130
  * The current sequence's length, in seconds
122
131
  * @type {number}
@@ -137,7 +146,7 @@ export class Sequencer
137
146
  this._sendMessage(WorkletSequencerMessageType.setSkipToFirstNote, false);
138
147
  }
139
148
 
140
- this.loadNewSongList(midiBinaries);
149
+ this.loadNewSongList(midiBinaries, options?.autoPlay ?? false);
141
150
 
142
151
  window.addEventListener("beforeunload", this.resetMIDIOut.bind(this));
143
152
  }
@@ -167,7 +176,7 @@ export class Sequencer
167
176
  get currentTime()
168
177
  {
169
178
  // return the paused time if it's set to something other than undefined
170
- if (this.pausedTime)
179
+ if (this.pausedTime !== undefined)
171
180
  {
172
181
  return this.pausedTime;
173
182
  }
@@ -198,7 +207,7 @@ export class Sequencer
198
207
  */
199
208
  get currentHighResolutionTime()
200
209
  {
201
- if (this.pausedTime)
210
+ if (this.pausedTime !== undefined)
202
211
  {
203
212
  return this.pausedTime;
204
213
  }
@@ -364,7 +373,11 @@ export class Sequencer
364
373
  this.absoluteStartTime = 0;
365
374
  this.duration = this.midiData.duration;
366
375
  Object.entries(this.onSongChange).forEach((callback) => callback[1](songChangeData));
367
- this.unpause();
376
+ // if is auto played, unpause
377
+ if (messageData[2] === true)
378
+ {
379
+ this.unpause();
380
+ }
368
381
  break;
369
382
 
370
383
  case WorkletSequencerReturnMessageType.textEvent:
@@ -437,22 +450,28 @@ export class Sequencer
437
450
  }
438
451
 
439
452
  /**
440
- * @param midiBuffers {MIDIFile[]}
453
+ * Loads a new song list
454
+ * @param midiBuffers {MIDIFile[]} - the MIDI files to play
455
+ * @param autoPlay {boolean} - if true, the first sequence will automatically start playing
441
456
  */
442
- loadNewSongList(midiBuffers)
457
+ loadNewSongList(midiBuffers, autoPlay = true)
443
458
  {
444
459
  this.pause();
445
460
  // add some dummy data
446
461
  this.midiData = DUMMY_MIDI_DATA;
447
462
  this.hasDummyData = true;
448
463
  this.duration = 99999;
449
- this._sendMessage(WorkletSequencerMessageType.loadNewSongList, midiBuffers);
464
+ this._sendMessage(WorkletSequencerMessageType.loadNewSongList, [midiBuffers, autoPlay]);
450
465
  this.songIndex = 0;
451
466
  this.songsAmount = midiBuffers.length;
452
467
  if (this.songsAmount > 1)
453
468
  {
454
469
  this.loop = false;
455
470
  }
471
+ if (autoPlay === false)
472
+ {
473
+ this.pausedTime = this.currentTime;
474
+ }
456
475
  }
457
476
 
458
477
  /**
@@ -16,7 +16,7 @@ export function processMessage(messageType, messageData)
16
16
  break;
17
17
 
18
18
  case WorkletSequencerMessageType.loadNewSongList:
19
- this.loadNewSongList(messageData);
19
+ this.loadNewSongList(messageData[0], messageData[1]);
20
20
  break;
21
21
 
22
22
  case WorkletSequencerMessageType.pause:
@@ -32,10 +32,10 @@ export const WorkletSequencerMessageType = {
32
32
  */
33
33
  export const WorkletSequencerReturnMessageType = {
34
34
  midiEvent: 0, // [...midiEventBytes<number>]
35
- songChange: 1, // [midiData<MidiData>, songIndex<number>]
35
+ songChange: 1, // [midiData<MidiData>, songIndex<number>, isAutoPlayed<boolean>]
36
36
  textEvent: 2, // [messageData<number[]>, statusByte<number]
37
37
  timeChange: 3, // newAbsoluteTime<number>
38
38
  pause: 4, // no data
39
39
  getMIDI: 5, // midiData<MIDI>
40
- midiError: 6 // errorMSG<string>
40
+ midiError: 6 // errorMSG<string>
41
41
  };
@@ -41,9 +41,10 @@ export function assignMIDIPort(trackNum, port)
41
41
  /**
42
42
  * Loads a new sequence
43
43
  * @param parsedMidi {BasicMIDI}
44
+ * @param autoPlay {boolean}
44
45
  * @this {WorkletSequencer}
45
46
  */
46
- export function loadNewSequence(parsedMidi)
47
+ export function loadNewSequence(parsedMidi, autoPlay = true)
47
48
  {
48
49
  this.stop();
49
50
  if (!parsedMidi.tracks)
@@ -122,9 +123,8 @@ export function loadNewSequence(parsedMidi)
122
123
  this.firstNoteTime = MIDIticksToSeconds(this.midiData.firstNoteOn, this.midiData);
123
124
  SpessaSynthInfo(`%cTotal song time: ${formatTime(Math.ceil(this.duration)).time}`, consoleColors.recognized);
124
125
 
125
- this.post(WorkletSequencerReturnMessageType.songChange, [new MidiData(this.midiData), this.songIndex]);
126
+ this.post(WorkletSequencerReturnMessageType.songChange, [new MidiData(this.midiData), this.songIndex, autoPlay]);
126
127
 
127
- this.synth.resetAllControllers();
128
128
  if (this.duration <= 1)
129
129
  {
130
130
  SpessaSynthWarn(
@@ -133,14 +133,25 @@ export function loadNewSequence(parsedMidi)
133
133
  );
134
134
  this.loop = false;
135
135
  }
136
- this.play(true);
136
+ if (autoPlay)
137
+ {
138
+ this.play(true);
139
+ }
140
+ else
141
+ {
142
+ // this shall not play: play to the first note and then wait
143
+ const targetTime = this._skipToFirstNoteOn ? this.midiData.firstNoteOn - 1 : 0;
144
+ this.setTimeTicks(targetTime);
145
+ this.pause();
146
+ }
137
147
  }
138
148
 
139
149
  /**
140
150
  * @param midiBuffers {MIDIFile[]}
151
+ * @param autoPlay {boolean}
141
152
  * @this {WorkletSequencer}
142
153
  */
143
- export function loadNewSongList(midiBuffers)
154
+ export function loadNewSongList(midiBuffers, autoPlay = true)
144
155
  {
145
156
  /**
146
157
  * parse the MIDIs (only the array buffers, MIDI is unchanged)
@@ -173,7 +184,7 @@ export function loadNewSongList(midiBuffers)
173
184
  {
174
185
  this.loop = false;
175
186
  }
176
- this.loadNewSequence(this.songs[this.songIndex]);
187
+ this.loadNewSequence(this.songs[this.songIndex], autoPlay);
177
188
  }
178
189
 
179
190
  /**
@@ -119,7 +119,7 @@ class WorkletSequencer
119
119
  get currentTime()
120
120
  {
121
121
  // return the paused time if it's set to something other than undefined
122
- if (this.pausedTime)
122
+ if (this.pausedTime !== undefined)
123
123
  {
124
124
  return this.pausedTime;
125
125
  }