spessasynth_lib 3.25.13 → 3.25.15

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.
@@ -310,31 +310,6 @@ class BasicMIDI extends MIDISequenceData
310
310
  copyrightComponents.push(name);
311
311
  }
312
312
  }
313
-
314
- // if the first event is not at 0 ticks, add a track name
315
- // https://github.com/spessasus/SpessaSynth/issues/145
316
- if (track[0].ticks > 0)
317
- {
318
- const name = this.trackNames[i];
319
- if (name.length > 0)
320
- {
321
- // can copy
322
- track.unshift(new MIDIMessage(
323
- 0,
324
- messageTypes.trackName,
325
- getStringBytes(name)
326
- ));
327
- }
328
- else
329
- {
330
- // sequence number
331
- track.unshift(new MIDIMessage(
332
- 0,
333
- messageTypes.sequenceNumber,
334
- new IndexedByteArray([0x0, 0x0]) // two bytes
335
- ));
336
- }
337
- }
338
313
  }
339
314
 
340
315
  // reverse the tempo changes
@@ -540,6 +515,19 @@ class BasicMIDI extends MIDISequenceData
540
515
  );
541
516
  }
542
517
 
518
+ // if the first event is not at 0 ticks, add a track name
519
+ // https://github.com/spessasus/SpessaSynth/issues/145
520
+ if (!this.tracks.some(t => t[0].ticks === 0))
521
+ {
522
+ const track = this.tracks[0];
523
+ // can copy
524
+ track.unshift(new MIDIMessage(
525
+ 0,
526
+ messageTypes.trackName,
527
+ new IndexedByteArray(this.rawMidiName.buffer)
528
+ ));
529
+ }
530
+
543
531
 
544
532
  /**
545
533
  * The total playback time, in seconds
@@ -121,7 +121,7 @@ class MIDISequenceData
121
121
  * Useful when the MIDI file uses a different code page.
122
122
  * @type {Uint8Array}
123
123
  */
124
- rawMidiName = undefined;
124
+ rawMidiName;
125
125
 
126
126
  /**
127
127
  * The format of the MIDI file, which can be 0, 1, or 2, indicating the type of the MIDI file.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_lib",
3
- "version": "3.25.13",
3
+ "version": "3.25.15",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "browser": "index.js",
6
6
  "type": "module",
@@ -10,7 +10,6 @@ import { SpessaSynthWarn } from "../utils/loggin.js";
10
10
  import { DUMMY_MIDI_DATA, MIDIData } from "../midi_parser/midi_data.js";
11
11
  import { BasicMIDI } from "../midi_parser/basic_midi.js";
12
12
  import { readBytesAsUintBigEndian } from "../utils/byte_functions/big_endian.js";
13
- import { IndexedByteArray } from "../utils/indexed_array.js";
14
13
  import { DEFAULT_SEQUENCER_OPTIONS } from "./default_sequencer_options.js";
15
14
 
16
15
  /**
@@ -31,6 +30,7 @@ import { DEFAULT_SEQUENCER_OPTIONS } from "./default_sequencer_options.js";
31
30
  * @typedef {BasicMIDI|MidFile} MIDIFile
32
31
  */
33
32
 
33
+ // noinspection JSUnusedGlobalSymbols
34
34
  /**
35
35
  * @typedef {Object} SequencerOptions
36
36
  * @property {boolean|undefined} skipToFirstNoteOn - if true, the sequencer will skip to the first note
@@ -50,7 +50,7 @@ export class Sequencer
50
50
 
51
51
  /**
52
52
  * Fires on text event
53
- * @type {function}
53
+ * @type {Function}
54
54
  * @param data {Uint8Array} the data text
55
55
  * @param type {number} the status byte of the message (the meta-status byte)
56
56
  * @param lyricsIndex {number} if the text is a lyric, the index of the lyric in midiData.lyrics, otherwise -1
@@ -96,7 +96,7 @@ export class Sequencer
96
96
 
97
97
  /**
98
98
  * Fires on meta-event
99
- * @type {Object<string, function([number, Uint8Array, number])>}
99
+ * @type {Object<string, function([number, Uint8Array, number, number])>}
100
100
  */
101
101
  onMetaEvent = {};
102
102
 
@@ -435,7 +435,8 @@ export class Sequencer
435
435
 
436
436
  /**
437
437
  * Adds a new event that gets called when a meta-event occurs
438
- * @param callback {function([number, Uint8Array, number])} the meta-event type, its data and the track number
438
+ * @param callback {function([number, Uint8Array, number, number])} the meta-event type,
439
+ * its data, the track number and MIDI ticks
439
440
  * @param id {string} must be unique
440
441
  */
441
442
  addOnMetaEvent(callback, id)
@@ -564,13 +565,6 @@ export class Sequencer
564
565
  }
565
566
  break;
566
567
 
567
- case WorkletSequencerReturnMessageType.textEvent:
568
- if (this.onTextEvent)
569
- {
570
- this.onTextEvent(...(messageData));
571
- }
572
- break;
573
-
574
568
  case WorkletSequencerReturnMessageType.timeChange:
575
569
  // message data is absolute time
576
570
  const time = this.synth.currentTime - messageData;
@@ -614,16 +608,63 @@ export class Sequencer
614
608
  break;
615
609
 
616
610
  case WorkletSequencerReturnMessageType.metaEvent:
617
- const type = messageData[0];
618
- if (type === messageTypes.setTempo)
611
+ /**
612
+ * @type {MIDIMessage}
613
+ */
614
+ const event = messageData[0];
615
+ switch (event.messageStatusByte)
619
616
  {
620
- const arr = new IndexedByteArray(messageData[1]);
621
- const bpm = 60000000 / readBytesAsUintBigEndian(arr, 3);
622
- this.currentTempo = Math.round(bpm * 100) / 100;
623
- if (this.onTempoChange)
624
- {
625
- this._callEvents(this.onTempoChange, this.currentTempo);
626
- }
617
+ case messageTypes.setTempo:
618
+ event.messageData.currentIndex = 0;
619
+ const bpm = 60000000 / readBytesAsUintBigEndian(event.messageData, 3);
620
+ event.messageData.currentIndex = 0;
621
+ this.currentTempo = Math.round(bpm * 100) / 100;
622
+ if (this.onTempoChange)
623
+ {
624
+ this._callEvents(this.onTempoChange, this.currentTempo);
625
+ }
626
+ break;
627
+
628
+ case messageTypes.text:
629
+ case messageTypes.lyric:
630
+ case messageTypes.copyright:
631
+ case messageTypes.trackName:
632
+ case messageTypes.marker:
633
+ case messageTypes.cuePoint:
634
+ case messageTypes.instrumentName:
635
+ case messageTypes.programName:
636
+ let lyricsIndex = -1;
637
+ if (event.messageStatusByte === messageTypes.lyric)
638
+ {
639
+ lyricsIndex = Math.min(
640
+ this.midiData.lyricsTicks.indexOf(event.ticks),
641
+ this.midiData.lyrics.length - 1
642
+ );
643
+ }
644
+ let sentStatus = event.messageStatusByte;
645
+ // if MIDI is a karaoke file, it uses the "text" event type or "lyrics" for lyrics (duh)
646
+ // why?
647
+ // because the MIDI standard is a messy pile of garbage,
648
+ // and it's not my fault that it's like this :(
649
+ // I'm just trying to make the best out of a bad situation.
650
+ // I'm sorry
651
+ // okay I should get back to work
652
+ // anyway,
653
+ // check for a karaoke file and change the status byte to "lyric"
654
+ // if it's a karaoke file
655
+ if (this.midiData.isKaraokeFile && (
656
+ event.messageStatusByte === messageTypes.text ||
657
+ event.messageStatusByte === messageTypes.lyric
658
+ ))
659
+ {
660
+ lyricsIndex = Math.min(
661
+ this.midiData.lyricsTicks.indexOf(event.ticks),
662
+ this.midiData.lyricsTicks.length
663
+ );
664
+ sentStatus = messageTypes.lyric;
665
+ }
666
+ this.onTextEvent(event.messageData, sentStatus, lyricsIndex, event.ticks);
667
+ break;
627
668
  }
628
669
  this._callEvents(this.onMetaEvent, messageData);
629
670
  break;
@@ -115,8 +115,6 @@ export function _processEvent(event, trackIndex)
115
115
  case messageTypes.keySignature:
116
116
  case messageTypes.sequenceNumber:
117
117
  case messageTypes.sequenceSpecific:
118
- break;
119
-
120
118
  case messageTypes.text:
121
119
  case messageTypes.lyric:
122
120
  case messageTypes.copyright:
@@ -125,40 +123,9 @@ export function _processEvent(event, trackIndex)
125
123
  case messageTypes.cuePoint:
126
124
  case messageTypes.instrumentName:
127
125
  case messageTypes.programName:
128
- let lyricsIndex = -1;
129
- if (statusByteData.status === messageTypes.lyric)
130
- {
131
- lyricsIndex = Math.min(
132
- this.midiData.lyricsTicks.indexOf(event.ticks),
133
- this.midiData.lyrics.length - 1
134
- );
135
- }
136
- let sentStatus = statusByteData.status;
137
- // if MIDI is a karaoke file, it uses the "text" event type or "lyrics" for lyrics (duh)
138
- // why?
139
- // because the MIDI standard is a messy pile of garbage, and it's not my fault that it's like this :(
140
- // I'm just trying to make the best out of a bad situation.
141
- // I'm sorry
142
- // okay I should get back to work
143
- // anyway,
144
- // check for a karaoke file and change the status byte to "lyric" if it's a karaoke file
145
- if (this.midiData.isKaraokeFile && (
146
- statusByteData.status === messageTypes.text ||
147
- statusByteData.status === messageTypes.lyric
148
- ))
149
- {
150
- lyricsIndex = Math.min(
151
- this.midiData.lyricsTicks.indexOf(event.ticks),
152
- this.midiData.lyricsTicks.length
153
- );
154
- sentStatus = messageTypes.lyric;
155
- }
156
- this.post(
157
- WorkletSequencerReturnMessageType.textEvent,
158
- [event.messageData, sentStatus, lyricsIndex]
159
- );
160
126
  break;
161
127
 
128
+
162
129
  case messageTypes.midiPort:
163
130
  this.assignMIDIPort(trackIndex, event.messageData[0]);
164
131
  break;
@@ -183,7 +150,7 @@ export function _processEvent(event, trackIndex)
183
150
  {
184
151
  this.post(
185
152
  WorkletSequencerReturnMessageType.metaEvent,
186
- [event.messageStatusByte, event.messageData, trackIndex]
153
+ [event, trackIndex]
187
154
  );
188
155
  }
189
156
  }
@@ -43,12 +43,11 @@ export const WorkletSequencerMessageType = {
43
43
  export const WorkletSequencerReturnMessageType = {
44
44
  midiEvent: 0, // [...midiEventBytes<number>]
45
45
  songChange: 1, // [songIndex<number>, isAutoPlayed<boolean>]
46
- textEvent: 2, // [messageData<number[]>, statusByte<number>, lyricsIndex<number>]
47
- timeChange: 3, // newAbsoluteTime<number>
48
- pause: 4, // no data
49
- getMIDI: 5, // midiData<MIDI>
50
- midiError: 6, // errorMSG<string>
51
- metaEvent: 7, // [messageType<number>, messageData<Uint8Array>, trackNum<number>]
52
- loopCountChange: 8, // newLoopCount<number>
53
- songListChange: 9 // songListData<MIDIData[]>
46
+ timeChange: 2, // newAbsoluteTime<number>
47
+ pause: 3, // no data
48
+ getMIDI: 4, // midiData<MIDI>
49
+ midiError: 5, // errorMSG<string>
50
+ metaEvent: 6, // [event<MIDIMessage>, trackNum<number>]
51
+ loopCountChange: 7, // newLoopCount<number>
52
+ songListChange: 8 // songListData<MIDIData[]>
54
53
  };
@@ -144,7 +144,7 @@ export function loadNewSequence(parsedMidi, autoPlay = true)
144
144
  else
145
145
  {
146
146
  // this shall not play: play to the first note and then wait
147
- const targetTime = this._skipToFirstNoteOn ? this.midiData.firstNoteOn - 1 : 0;
147
+ const targetTime = this.skipToFirstNoteOn ? this.midiData.firstNoteOn - 1 : 0;
148
148
  this.setTimeTicks(targetTime);
149
149
  this.pause();
150
150
  }
@@ -2,7 +2,7 @@ import { readBytesAsString } from "../../utils/byte_functions/string.js";
2
2
  import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
3
3
  import { DLSPreset } from "./dls_preset.js";
4
4
  import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
5
- import { SpessaSynthGroup, SpessaSynthGroupEnd } from "../../utils/loggin.js";
5
+ import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from "../../utils/loggin.js";
6
6
  import { BasicInstrumentZone } from "../basic_soundfont/basic_zones.js";
7
7
  import { consoleColors } from "../../utils/other.js";
8
8
  import { generatorLimits, generatorTypes } from "../basic_soundfont/generator.js";
@@ -54,7 +54,7 @@ export function readDLSInstrument(chunk)
54
54
  }
55
55
  preset.presetName = presetName;
56
56
  preset.DLSInstrument.instrumentName = presetName;
57
- SpessaSynthGroup(
57
+ SpessaSynthGroupCollapsed(
58
58
  `%cParsing %c"${presetName}"%c...`,
59
59
  consoleColors.info,
60
60
  consoleColors.recognized,