spessasynth_lib 3.25.12 → 3.25.14

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.
@@ -1,6 +1,6 @@
1
1
  import { MIDISequenceData } from "./midi_sequence.js";
2
2
  import { getStringBytes, readBytesAsString } from "../utils/byte_functions/string.js";
3
- import { messageTypes } from "./midi_message.js";
3
+ import { messageTypes, MIDIMessage } from "./midi_message.js";
4
4
  import { readBytesAsUintBigEndian } from "../utils/byte_functions/big_endian.js";
5
5
  import { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from "../utils/loggin.js";
6
6
  import { consoleColors, formatTitle, sanitizeKarLyrics } from "../utils/other.js";
@@ -8,6 +8,7 @@ import { writeMIDI } from "./midi_writer.js";
8
8
  import { applySnapshotToMIDI, modifyMIDI } from "./midi_editor.js";
9
9
  import { writeRMIDI } from "./rmidi_writer.js";
10
10
  import { getUsedProgramsAndKeys } from "./used_keys_loaded.js";
11
+ import { IndexedByteArray } from "../utils/indexed_array.js";
11
12
 
12
13
  /**
13
14
  * BasicMIDI is the base of a complete MIDI file, used by the sequencer internally.
@@ -98,6 +99,9 @@ class BasicMIDI extends MIDISequenceData
98
99
 
99
100
  for (let i = 0; i < this.tracks.length; i++)
100
101
  {
102
+ /**
103
+ * @type {MIDIMessage[]}
104
+ */
101
105
  const track = this.tracks[i];
102
106
  const usedChannels = new Set();
103
107
  let trackHasVoiceMessages = false;
@@ -306,6 +310,31 @@ class BasicMIDI extends MIDISequenceData
306
310
  copyrightComponents.push(name);
307
311
  }
308
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
+ }
309
338
  }
310
339
 
311
340
  // reverse the tempo changes
@@ -40,7 +40,7 @@ class MIDISequenceData
40
40
 
41
41
  /**
42
42
  * The track names in the MIDI file, an empty string if not set.
43
- * @type {[]}
43
+ * @type {string[]}
44
44
  */
45
45
  trackNames = [];
46
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_lib",
3
- "version": "3.25.12",
3
+ "version": "3.25.14",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "browser": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @type {SequencerOptions}
3
+ */
4
+ export const DEFAULT_SEQUENCER_OPTIONS = {
5
+ skipToFirstNoteOn: true,
6
+ autoPlay: true,
7
+ preservePlaybackState: false
8
+ };
@@ -11,6 +11,7 @@ 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
13
  import { IndexedByteArray } from "../utils/indexed_array.js";
14
+ import { DEFAULT_SEQUENCER_OPTIONS } from "./default_sequencer_options.js";
14
15
 
15
16
  /**
16
17
  * sequencer.js
@@ -38,15 +39,6 @@ import { IndexedByteArray } from "../utils/indexed_array.js";
38
39
  * the sequencer will stay paused when seeking or changing the playback rate
39
40
  */
40
41
 
41
- /**
42
- * @type {SequencerOptions}
43
- */
44
- const DEFAULT_OPTIONS = {
45
- skipToFirstNoteOn: true,
46
- autoPlay: true,
47
- preservePlaybackState: false
48
- };
49
-
50
42
  // noinspection JSUnusedGlobalSymbols
51
43
  export class Sequencer
52
44
  {
@@ -153,7 +145,7 @@ export class Sequencer
153
145
  * @param synth {Synthetizer} synth to send events to
154
146
  * @param options {SequencerOptions} the sequencer's options
155
147
  */
156
- constructor(midiBinaries, synth, options = DEFAULT_OPTIONS)
148
+ constructor(midiBinaries, synth, options = DEFAULT_SEQUENCER_OPTIONS)
157
149
  {
158
150
  this.ignoreEvents = false;
159
151
  this.synth = synth;
@@ -95,7 +95,7 @@ export function processMessage(messageType, messageData)
95
95
  break;
96
96
 
97
97
  case WorkletSequencerMessageType.setSkipToFirstNote:
98
- this._skipToFirstNoteOn = messageData;
98
+ this.skipToFirstNoteOn = messageData;
99
99
  break;
100
100
 
101
101
  case WorkletSequencerMessageType.setPreservePlaybackState:
@@ -127,9 +127,8 @@ class WorkletSequencer
127
127
 
128
128
  /**
129
129
  * @type {boolean}
130
- * @private
131
130
  */
132
- _skipToFirstNoteOn = true;
131
+ skipToFirstNoteOn = true;
133
132
 
134
133
  /**
135
134
  * If true, seq will stay paused when seeking or changing the playback rate
@@ -178,7 +177,7 @@ class WorkletSequencer
178
177
  if (time > this.duration || time < 0)
179
178
  {
180
179
  // time is 0
181
- if (this._skipToFirstNoteOn)
180
+ if (this.skipToFirstNoteOn)
182
181
  {
183
182
  this.setTimeTicks(this.midiData.firstNoteOn - 1);
184
183
  }
@@ -188,7 +187,7 @@ class WorkletSequencer
188
187
  }
189
188
  return;
190
189
  }
191
- if (this._skipToFirstNoteOn)
190
+ if (this.skipToFirstNoteOn)
192
191
  {
193
192
  if (time < this.firstNoteTime)
194
193
  {
@@ -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,
@@ -5,6 +5,7 @@
5
5
  * @property {boolean|undefined} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel).
6
6
  * this disabled chorus and reverb.
7
7
  * @property {number|undefined} loopCount - the times to loop the song
8
+ * @property {SequencerOptions} sequencerOptions - the options to pass to the sequencer
8
9
  */
9
10
 
10
11
  export const WORKLET_PROCESSOR_NAME = "spessasynth-worklet-system";
@@ -1,5 +1,5 @@
1
1
  import { IndexedByteArray } from "../utils/indexed_array.js";
2
- import { consoleColors, fillWithDefaults } from "../utils/other.js";
2
+ import { consoleColors } from "../utils/other.js";
3
3
  import { getEvent, messageTypes, midiControllers } from "../midi_parser/midi_message.js";
4
4
  import { EventHandler } from "./synth_event_handler.js";
5
5
  import { FancyChorus } from "./audio_effects/fancy_chorus.js";
@@ -23,6 +23,8 @@ import {
23
23
  WORKLET_PROCESSOR_NAME
24
24
  } from "./synth_constants.js";
25
25
  import { BasicMIDI } from "../midi_parser/basic_midi.js";
26
+ import { fillWithDefaults } from "../utils/fill_with_defaults.js";
27
+ import { DEFAULT_SEQUENCER_OPTIONS } from "../sequencer/default_sequencer_options.js";
26
28
 
27
29
 
28
30
  /**
@@ -150,6 +152,15 @@ export class Synthetizer
150
152
  }
151
153
  sequencerRenderingData.snapshot = snapshot;
152
154
  }
155
+ if (startRenderingData?.sequencerOptions)
156
+ {
157
+ // sequencer options
158
+ sequencerRenderingData.sequencerOptions = fillWithDefaults(
159
+ startRenderingData.sequencerOptions,
160
+ DEFAULT_SEQUENCER_OPTIONS
161
+ );
162
+ }
163
+
153
164
  sequencerRenderingData.loopCount = startRenderingData?.loopCount ?? 0;
154
165
  }
155
166