spessasynth_lib 3.16.5 → 3.20.0

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.
Files changed (87) hide show
  1. package/@types/index.d.ts +5 -4
  2. package/@types/midi_parser/basic_midi.d.ts +125 -0
  3. package/@types/midi_parser/midi_builder.d.ts +69 -0
  4. package/@types/midi_parser/midi_data.d.ts +2 -2
  5. package/@types/midi_parser/midi_editor.d.ts +4 -4
  6. package/@types/midi_parser/midi_loader.d.ts +3 -100
  7. package/@types/midi_parser/midi_writer.d.ts +2 -2
  8. package/@types/midi_parser/rmidi_writer.d.ts +3 -3
  9. package/@types/midi_parser/used_keys_loaded.d.ts +2 -2
  10. package/@types/sequencer/sequencer.d.ts +1 -1
  11. package/@types/soundfont/basic_soundfont/basic_sample.d.ts +2 -2
  12. package/@types/soundfont/basic_soundfont/basic_zone.d.ts +12 -12
  13. package/@types/soundfont/basic_soundfont/basic_zones.d.ts +4 -0
  14. package/@types/soundfont/basic_soundfont/riff_chunk.d.ts +6 -0
  15. package/@types/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.d.ts +2 -2
  16. package/@types/soundfont/dls/articulator_converter.d.ts +10 -0
  17. package/@types/soundfont/dls/dls_destinations.d.ts +29 -0
  18. package/@types/soundfont/dls/dls_preset.d.ts +13 -0
  19. package/@types/soundfont/dls/dls_sample.d.ts +18 -0
  20. package/@types/soundfont/dls/dls_soundfont.d.ts +31 -0
  21. package/@types/soundfont/dls/dls_sources.d.ts +22 -0
  22. package/@types/soundfont/dls/dls_zone.d.ts +22 -0
  23. package/@types/soundfont/dls/read_articulation.d.ts +12 -0
  24. package/@types/soundfont/dls/read_instrument.d.ts +5 -0
  25. package/@types/soundfont/dls/read_instrument_list.d.ts +5 -0
  26. package/@types/soundfont/dls/read_lart.d.ts +7 -0
  27. package/@types/soundfont/dls/read_region.d.ts +7 -0
  28. package/@types/soundfont/dls/read_samples.d.ts +5 -0
  29. package/@types/soundfont/load_soundfont.d.ts +6 -0
  30. package/@types/soundfont/read_sf2/generators.d.ts +18 -5
  31. package/@types/soundfont/read_sf2/modulators.d.ts +1 -0
  32. package/@types/soundfont/soundfont.d.ts +2 -1
  33. package/@types/synthetizer/synthetizer.d.ts +2 -2
  34. package/@types/utils/byte_functions/little_endian.d.ts +1 -1
  35. package/README.md +27 -15
  36. package/index.js +6 -4
  37. package/midi_parser/basic_midi.js +146 -0
  38. package/midi_parser/midi_builder.js +281 -0
  39. package/midi_parser/midi_data.js +1 -1
  40. package/midi_parser/midi_editor.js +2 -2
  41. package/midi_parser/midi_loader.js +38 -56
  42. package/midi_parser/midi_writer.js +1 -1
  43. package/midi_parser/rmidi_writer.js +2 -2
  44. package/midi_parser/used_keys_loaded.js +1 -1
  45. package/package.json +1 -1
  46. package/sequencer/sequencer.js +1 -1
  47. package/sequencer/worklet_sequencer/song_control.js +3 -3
  48. package/sequencer/worklet_sequencer/worklet_sequencer.js +1 -1
  49. package/soundfont/README.md +6 -2
  50. package/soundfont/basic_soundfont/basic_sample.js +3 -3
  51. package/soundfont/basic_soundfont/basic_zone.js +28 -28
  52. package/soundfont/basic_soundfont/basic_zones.js +15 -19
  53. package/soundfont/basic_soundfont/riff_chunk.js +20 -4
  54. package/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.js +1 -1
  55. package/soundfont/dls/articulator_converter.js +311 -0
  56. package/soundfont/dls/dls_destinations.js +38 -0
  57. package/soundfont/dls/dls_preset.js +32 -0
  58. package/soundfont/dls/dls_sample.js +58 -0
  59. package/soundfont/dls/dls_soundfont.js +150 -0
  60. package/soundfont/dls/dls_sources.js +26 -0
  61. package/soundfont/dls/dls_zone.js +75 -0
  62. package/soundfont/dls/read_articulation.js +327 -0
  63. package/soundfont/dls/read_instrument.js +100 -0
  64. package/soundfont/dls/read_instrument_list.js +17 -0
  65. package/soundfont/dls/read_lart.js +35 -0
  66. package/soundfont/dls/read_region.js +129 -0
  67. package/soundfont/dls/read_samples.js +174 -0
  68. package/soundfont/load_soundfont.js +21 -0
  69. package/soundfont/read_sf2/generators.js +41 -6
  70. package/soundfont/read_sf2/instruments.js +2 -2
  71. package/soundfont/read_sf2/modulators.js +8 -8
  72. package/soundfont/read_sf2/presets.js +7 -7
  73. package/soundfont/read_sf2/samples.js +8 -8
  74. package/soundfont/read_sf2/zones.js +5 -5
  75. package/soundfont/soundfont.js +8 -3
  76. package/synthetizer/synthetizer.js +1 -1
  77. package/synthetizer/worklet_processor.min.js +10 -7
  78. package/synthetizer/worklet_system/main_processor.js +1 -2
  79. package/synthetizer/worklet_system/worklet_methods/program_control.js +6 -3
  80. package/synthetizer/worklet_system/worklet_methods/worklet_soundfont_manager/worklet_soundfont_manager.js +5 -5
  81. package/utils/buffer_to_wav.js +5 -26
  82. package/utils/byte_functions/little_endian.js +1 -1
  83. /package/@types/{midi_handler → external_midi}/midi_handler.d.ts +0 -0
  84. /package/@types/{midi_handler → external_midi}/web_midi_link.d.ts +0 -0
  85. /package/{midi_handler → external_midi}/README.md +0 -0
  86. /package/{midi_handler → external_midi}/midi_handler.js +0 -0
  87. /package/{midi_handler → external_midi}/web_midi_link.js +0 -0
@@ -0,0 +1,281 @@
1
+ import { BasicMIDI } from './basic_midi.js'
2
+ import { messageTypes, MidiMessage } from './midi_message.js'
3
+ import { IndexedByteArray } from '../utils/indexed_array.js'
4
+ import { readBytesAsUintBigEndian } from '../utils/byte_functions/big_endian.js'
5
+ import { SpessaSynthWarn } from '../utils/loggin.js'
6
+
7
+ export class MIDIBuilder extends BasicMIDI
8
+ {
9
+ /**
10
+ * @param name {string} The MIDI's name
11
+ * @param timeDivision {number} the file's time division
12
+ * @param initialTempo {number} the file's initial tempo
13
+ */
14
+ constructor(name, timeDivision = 480, initialTempo = 120)
15
+ {
16
+ super();
17
+ this.timeDivision = timeDivision;
18
+ this.midiName = name;
19
+ this.encoder = new TextEncoder();
20
+ this.rawMidiName = this.encoder.encode(name);
21
+
22
+ // create the first track with the file name
23
+ this.addNewTrack(name);
24
+ this.addSetTempo(0, initialTempo);
25
+ }
26
+
27
+ /**
28
+ * Updates all internal values
29
+ */
30
+ flush()
31
+ {
32
+
33
+ // find first note on
34
+ const firstNoteOns = [];
35
+ for(const t of this.tracks)
36
+ {
37
+ // sost the track by ticks
38
+ t.sort((e1, e2) => e1.ticks - e2.ticks);
39
+ const firstNoteOn = t.find(e => (e.messageStatusByte & 0xF0) === messageTypes.noteOn);
40
+ if(firstNoteOn)
41
+ {
42
+ firstNoteOns.push(firstNoteOn.ticks);
43
+ }
44
+ }
45
+ this.firstNoteOn = Math.min(...firstNoteOns);
46
+
47
+ // find tempo changes
48
+ // and used channels on tracks
49
+ // and midi ports
50
+ // and last voice event tick
51
+ // and loop
52
+ this.lastVoiceEventTick = 0
53
+ this.tempoChanges = [{ticks: 0, tempo: 120}];
54
+ this.midiPorts = [];
55
+ this.midiPortChannelOffsets = [];
56
+ let portOffset = 0;
57
+ /**
58
+ * @type {Set<number>[]}
59
+ */
60
+ this.usedChannelsOnTrack = this.tracks.map(() => new Set());
61
+ this.tracks.forEach((t, trackNum) => {
62
+ this.midiPorts.push(-1);
63
+ t.forEach(e => {
64
+ // last voice event tick
65
+ if(e.messageStatusByte >= 0x80 && e.messageStatusByte < 0xF0)
66
+ {
67
+ if(e.ticks > this.lastVoiceEventTick)
68
+ {
69
+ this.lastVoiceEventTick = e.ticks;
70
+ }
71
+ }
72
+
73
+ // tempo, used channels, port
74
+ if(e.messageStatusByte === messageTypes.setTempo)
75
+ {
76
+ this.tempoChanges.push({
77
+ ticks: e.ticks,
78
+ tempo: 60000000 / readBytesAsUintBigEndian(e.messageData, 3)
79
+ });
80
+ }
81
+ else
82
+ if((e.messageStatusByte & 0xF0) === messageTypes.noteOn)
83
+ {
84
+ this.usedChannelsOnTrack[trackNum].add(e.messageData[0]);
85
+ }
86
+ else
87
+ if(e.messageStatusByte === messageTypes.midiPort)
88
+ {
89
+ const port = e.messageData[0];
90
+ this.midiPorts[trackNum] = port;
91
+ if(this.midiPortChannelOffsets[port] === undefined)
92
+ {
93
+ this.midiPortChannelOffsets[port] = portOffset;
94
+ portOffset += 16;
95
+ }
96
+ }
97
+ })
98
+ });
99
+
100
+ this.loop = {start: this.firstNoteOn, end: this.lastVoiceEventTick};
101
+
102
+ // reverse tempo and compute duration
103
+ this.tempoChanges.reverse();
104
+ this.duration = this._ticksToSeconds(this.lastVoiceEventTick);
105
+
106
+ // fix midi ports:
107
+ // midi tracks without ports will have a value of -1
108
+ // if all ports have a value of -1, set it to 0, otherwise take the first midi port and replace all -1 with it
109
+ // why do this? some midis (for some reason) specify all channels to port 1 or else, but leave the conductor track with no port pref.
110
+ // this spessasynth to reserve the first 16 channels for the conductor track (which doesn't play anything) and use additional 16 for the actual ports.
111
+ let defaultP = 0;
112
+ for(let port of this.midiPorts)
113
+ {
114
+ if(port !== -1)
115
+ {
116
+ defaultP = port;
117
+ break;
118
+ }
119
+ }
120
+ this.midiPorts = this.midiPorts.map(port => port === -1 ? defaultP : port);
121
+ // add dummy port if empty
122
+ if(this.midiPortChannelOffsets.length === 0)
123
+ {
124
+ this.midiPortChannelOffsets = [0];
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Adds a new "set tempo" message
130
+ * @param ticks {number} the tick number of the event
131
+ * @param tempo {number} the tempo in beats per minute (BPM)
132
+ */
133
+ addSetTempo(ticks, tempo)
134
+ {
135
+ const array = new IndexedByteArray(3);
136
+
137
+ tempo = 60000000 / tempo;
138
+
139
+ // Extract each byte in big-endian order
140
+ array[0] = (tempo >> 16) & 0xFF;
141
+ array[1] = (tempo >> 8) & 0xFF;
142
+ array[2] = tempo & 0xFF;
143
+
144
+ this.addEvent(ticks, 0, messageTypes.setTempo, array);
145
+ }
146
+
147
+ /**
148
+ * Adds a new MIDI track
149
+ * @param name {string} the new track's name
150
+ * @param port {number} the new track's port
151
+ */
152
+ addNewTrack(name, port = 0)
153
+ {
154
+ this.tracksAmount++;
155
+ if(this.tracksAmount > 1)
156
+ {
157
+ this.format = 1;
158
+ }
159
+ this.tracks.push([]);
160
+ this.tracks[this.tracksAmount - 1].push(
161
+ new MidiMessage(0, messageTypes.endOfTrack, new IndexedByteArray(0))
162
+ );
163
+ this.addEvent(0, this.tracksAmount - 1, messageTypes.trackName, this.encoder.encode(name));
164
+ this.addEvent(0, this.tracksAmount - 1, messageTypes.midiPort, [port]);
165
+ }
166
+
167
+ /**
168
+ * Adds a new MIDI Event
169
+ * @param ticks {number} the tick time of the event
170
+ * @param track {number} the track number to use
171
+ * @param event {number} the MIDI event number
172
+ * @param eventData {Uint8Array|Iterable<number>} the raw event data
173
+ */
174
+ addEvent(ticks, track, event, eventData)
175
+ {
176
+ if(!this.tracks[track])
177
+ {
178
+ throw new Error(`Track ${track} does not exist. Add it via addTrack method.`);
179
+ }
180
+ if(event === messageTypes.endOfTrack)
181
+ {
182
+ SpessaSynthWarn("The EndOfTrack is added automatically. Ignoring!");
183
+ return;
184
+ }
185
+ // remove end of track
186
+ this.tracks[track].pop();
187
+ this.tracks[track].push(new MidiMessage(
188
+ ticks,
189
+ event,
190
+ new IndexedByteArray(eventData)
191
+ ));
192
+ // add end of track
193
+ this.tracks[track].push(new MidiMessage(
194
+ ticks,
195
+ messageTypes.endOfTrack,
196
+ new IndexedByteArray(0)
197
+ ));
198
+ }
199
+
200
+ /**
201
+ * Adds a new Note On event
202
+ * @param ticks {number} the tick time of the event
203
+ * @param track {number} the track number to use
204
+ * @param channel {number} the channel to use
205
+ * @param midiNote {number} the midi note of the keypress
206
+ * @param velocity {number} the velocity of the keypress
207
+ */
208
+ addNoteOn(ticks, track, channel, midiNote, velocity)
209
+ {
210
+ channel %= 16;
211
+ midiNote %= 128;
212
+ velocity %= 128;
213
+ this.addEvent(
214
+ ticks,
215
+ track,
216
+ messageTypes.noteOn | channel,
217
+ [midiNote, velocity]
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Adds a new Note Off event
223
+ * @param ticks {number} the tick time of the event
224
+ * @param track {number} the track number to use
225
+ * @param channel {number} the channel to use
226
+ * @param midiNote {number} the midi note of the key release
227
+ */
228
+ addNoteOff(ticks, track, channel, midiNote)
229
+ {
230
+ channel %= 16;
231
+ midiNote %= 128;
232
+ this.addEvent(
233
+ ticks,
234
+ track,
235
+ messageTypes.noteOff | channel,
236
+ [midiNote, 64]
237
+ );
238
+ }
239
+
240
+ /**
241
+ * Adds a new Controller Change event
242
+ * @param ticks {number} the tick time of the event
243
+ * @param track {number} the track number to use
244
+ * @param channel {number} the channel to use
245
+ * @param controllerNumber {number} the MIDI CC to use
246
+ * @param controllerValue {number} the new CC value
247
+ */
248
+ addControllerChange(ticks, track, channel, controllerNumber, controllerValue)
249
+ {
250
+ channel %= 16;
251
+ controllerNumber %= 128;
252
+ controllerValue %= 128;
253
+ this.addEvent(
254
+ ticks,
255
+ track,
256
+ messageTypes.controllerChange | channel,
257
+ [controllerNumber, controllerValue]
258
+ );
259
+ }
260
+
261
+ /**
262
+ * Adds a new Pitch Wheel event
263
+ * @param ticks {number} the tick time of the event
264
+ * @param track {number} the track to use
265
+ * @param channel {number} the channel to use
266
+ * @param MSB {number} SECOND byte of the MIDI pitchWheel message
267
+ * @param LSB {number} FIRST byte of the MIDI pitchWheel message
268
+ */
269
+ addPitchWheel(ticks, track, channel, MSB, LSB)
270
+ {
271
+ channel %= 16;
272
+ MSB %= 128;
273
+ LSB %= 128;
274
+ this.addEvent(
275
+ ticks,
276
+ track,
277
+ messageTypes.pitchBend | channel,
278
+ [LSB, MSB]
279
+ );
280
+ }
281
+ }
@@ -5,7 +5,7 @@
5
5
  export class MidiData
6
6
  {
7
7
  /**
8
- * @param midi {MIDI}
8
+ * @param midi {BasicMIDI}
9
9
  */
10
10
  constructor(midi)
11
11
  {
@@ -75,7 +75,7 @@ function getDrumChange(channel, ticks)
75
75
 
76
76
  /**
77
77
  * Allows easy editing of the file
78
- * @param midi {MIDI}
78
+ * @param midi {BasicMIDI}
79
79
  * @param desiredProgramChanges {{
80
80
  * channel: number,
81
81
  * program: number,
@@ -520,7 +520,7 @@ export function modifyMIDI(
520
520
 
521
521
  /**
522
522
  * Modifies the sequence according to the locked presets and controllers in the given snapshot
523
- * @param midi {MIDI}
523
+ * @param midi {BasicMIDI}
524
524
  * @param snapshot {SynthesizerSnapshot}
525
525
  */
526
526
  export function applySnapshotToMIDI(midi, snapshot)
@@ -1,63 +1,40 @@
1
1
  import { dataBytesAmount, getChannel, messageTypes, MidiMessage } from './midi_message.js'
2
2
  import { IndexedByteArray } from '../utils/indexed_array.js'
3
3
  import { arrayToHexString, consoleColors, formatTitle } from '../utils/other.js'
4
- import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from '../utils/loggin.js'
4
+ import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from '../utils/loggin.js'
5
5
  import { readRIFFChunk } from '../soundfont/basic_soundfont/riff_chunk.js'
6
6
  import { readVariableLengthQuantity } from '../utils/byte_functions/variable_length_quantity.js'
7
7
  import { readBytesAsUintBigEndian } from '../utils/byte_functions/big_endian.js'
8
8
  import { readBytesAsString } from '../utils/byte_functions/string.js'
9
- import { readBytesAsUintLittleEndian } from '../utils/byte_functions/little_endian.js'
9
+ import { readLittleEndian } from '../utils/byte_functions/little_endian.js'
10
10
  import { RMIDINFOChunks } from './rmidi_writer.js'
11
+ import { BasicMIDI } from './basic_midi.js'
11
12
 
12
13
  /**
13
14
  * midi_loader.js
14
15
  * purpose: parses a midi file for the seqyencer, including things like marker or CC 2/4 loop detection, copyright detection etc.
15
16
  */
16
- class MIDI{
17
+ class MIDI extends BasicMIDI
18
+ {
17
19
  /**
18
20
  * Parses a given midi file
19
21
  * @param arrayBuffer {ArrayBuffer}
20
22
  * @param fileName {string} optional, replaces the decoded title if empty
21
23
  */
22
- constructor(arrayBuffer, fileName="") {
24
+ constructor(arrayBuffer, fileName="")
25
+ {
26
+ super();
23
27
  SpessaSynthGroupCollapsed(`%cParsing MIDI File...`, consoleColors.info);
24
28
  const binaryData = new IndexedByteArray(arrayBuffer);
25
29
  let fileByteArray;
26
30
 
27
31
  // check for rmid
28
- /**
29
- * If the RMI file has an embedded sf2 in it, it will appeear here, otherwise undefined
30
- * @type {ArrayBuffer}
31
- */
32
- this.embeddedSoundFont = undefined;
33
-
34
- /**
35
- * The RMID Info data if RMID, otherwise undefined
36
- * @type {Object<string, IndexedByteArray>}
37
- */
38
- this.RMIDInfo = undefined;
39
- /**
40
- * The bank offset for RMIDI
41
- * @type {number}
42
- */
43
- this.bankOffset = 0;
44
-
45
- /**
46
- * Contains the copyright strings
47
- * @type {string}
48
- */
49
- this.copyright = "";
50
32
  let copyrightDetected = false;
51
33
 
52
- /**
53
- * The MIDI name
54
- * @type {string}
55
- */
56
- this.midiName = "";
57
-
58
- this.rawMidiName = new Uint8Array(0);
59
34
  let nameDetected = false;
60
35
 
36
+ let DLSRMID = false;
37
+
61
38
  const initialString = readBytesAsString(binaryData, 4);
62
39
  binaryData.currentIndex -= 4;
63
40
  if(initialString === "RIFF")
@@ -87,12 +64,21 @@ class MIDI{
87
64
  const currentChunk = readRIFFChunk(binaryData, true);
88
65
  if(currentChunk.header === "RIFF")
89
66
  {
90
- const type = readBytesAsString(currentChunk.chunkData, 4);
91
- if(type === "sfbk" || type === "sfpk")
67
+ const type = readBytesAsString(currentChunk.chunkData, 4).toLowerCase();
68
+ if(type === "sfbk" || type === "sfpk" || type === "dls ")
92
69
  {
93
70
  SpessaSynthInfo("%cFound embedded soundfont!", consoleColors.recognized);
94
71
  this.embeddedSoundFont = binaryData.slice(startIndex, startIndex + currentChunk.size).buffer;
95
72
  }
73
+ else
74
+ {
75
+ SpessaSynthWarn(`Unknown RIFF chunk: "${type}"`);
76
+ }
77
+ if(type === "dls ")
78
+ {
79
+ // assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.
80
+ DLSRMID = true;
81
+ }
96
82
  }
97
83
  else if(currentChunk.header === "LIST")
98
84
  {
@@ -129,11 +115,18 @@ class MIDI{
129
115
  this.bankOffset = 1; // defaults to 1
130
116
  if(this.RMIDInfo[RMIDINFOChunks.bankOffset])
131
117
  {
132
- this.bankOffset = readBytesAsUintLittleEndian(this.RMIDInfo[RMIDINFOChunks.bankOffset], 2);
118
+ this.bankOffset = readLittleEndian(this.RMIDInfo[RMIDINFOChunks.bankOffset], 2);
133
119
  }
134
120
  }
135
121
  }
136
122
  }
123
+
124
+ if(DLSRMID)
125
+ {
126
+ console.log(DLSRMID)
127
+ // assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.
128
+ this.bankOffset = 0;
129
+ }
137
130
  }
138
131
  else
139
132
  {
@@ -413,6 +406,15 @@ class MIDI{
413
406
  loopEnd = 0;
414
407
  }
415
408
  break;
409
+
410
+ case 0:
411
+ // check RMID
412
+ if(DLSRMID && eventData[1] !== 0 && eventData[1] !== 127)
413
+ {
414
+ SpessaSynthInfo("%cDLS RMIDI with offset 1 detected!",
415
+ consoleColors.recognized);
416
+ this.bankOffset = 1;
417
+ }
416
418
  }
417
419
  }
418
420
  }
@@ -564,25 +566,5 @@ class MIDI{
564
566
  fileByteArray.currentIndex += chunk.size;
565
567
  return chunk;
566
568
  }
567
-
568
-
569
- /**
570
- * Coverts ticks to time in seconds
571
- * @param ticks {number}
572
- * @returns {number}
573
- * @private
574
- */
575
- _ticksToSeconds(ticks)
576
- {
577
- if (ticks <= 0) {
578
- return 0;
579
- }
580
-
581
- // find the last tempo change that has occured
582
- let tempo = this.tempoChanges.find(v => v.ticks < ticks);
583
-
584
- let timeSinceLastTempo = ticks - tempo.ticks;
585
- return this._ticksToSeconds(ticks - timeSinceLastTempo) + (timeSinceLastTempo * 60) / (tempo.tempo * this.timeDivision);
586
- }
587
569
  }
588
570
  export { MIDI }
@@ -4,7 +4,7 @@ import { writeBytesAsUintBigEndian } from '../utils/byte_functions/big_endian.js
4
4
 
5
5
  /**
6
6
  * Exports the midi as a .mid file
7
- * @param midi {MIDI}
7
+ * @param midi {BasicMIDI}
8
8
  * @returns {Uint8Array} the binary .mid file data
9
9
  */
10
10
  export function writeMIDIFile(midi)
@@ -47,8 +47,8 @@ const DEFAULT_COPYRIGHT = "Created using SpessaSynth";
47
47
  /**
48
48
  * Writes an RMIDI file
49
49
  * @param soundfontBinary {Uint8Array}
50
- * @param mid {MIDI}
51
- * @param soundfont {SoundFont2}
50
+ * @param mid {BasicMIDI}
51
+ * @param soundfont {BasicSoundFont}
52
52
  * @param bankOffset {number} the bank offset for RMIDI
53
53
  * @param encoding {string} the encoding of the RMIDI info chunk
54
54
  * @param metadata {RMIDMetadata} the metadata of the file. Optional. If provided, the encoding is forced to utf-8/
@@ -4,7 +4,7 @@ import { DEFAULT_PERCUSSION } from '../synthetizer/synthetizer.js'
4
4
  import { messageTypes, midiControllers } from './midi_message.js'
5
5
 
6
6
  /**
7
- * @param mid {MIDI}
7
+ * @param mid {BasicMIDI}
8
8
  * @param soundfont {{getPreset: function(number, number): BasicPreset}}
9
9
  * @returns {Object<string, Set<string>>}
10
10
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_lib",
3
- "version": "3.16.5",
3
+ "version": "3.20.0",
4
4
  "description": "No compromise MIDI and SoundFont2 Synthesizer library",
5
5
  "browser": "index.js",
6
6
  "types": "@types/index.d.ts",
@@ -21,7 +21,7 @@ import { DUMMY_MIDI_DATA, MidiData } from '../midi_parser/midi_data.js'
21
21
  */
22
22
 
23
23
  /**
24
- * @typedef {MIDI|MidFile} MIDIFile
24
+ * @typedef {BasicMIDI|MidFile} MIDIFile
25
25
  */
26
26
 
27
27
  /**
@@ -35,7 +35,7 @@ export function assignMIDIPort(trackNum, port)
35
35
 
36
36
  /**
37
37
  * Loads a new sequence
38
- * @param parsedMidi {MIDI}
38
+ * @param parsedMidi {BasicMIDI}
39
39
  * @this {WorkletSequencer}
40
40
  */
41
41
  export function loadNewSequence(parsedMidi)
@@ -49,7 +49,7 @@ export function loadNewSequence(parsedMidi)
49
49
  this.oneTickToSeconds = 60 / (120 * parsedMidi.timeDivision)
50
50
 
51
51
  /**
52
- * @type {MIDI}
52
+ * @type {BasicMIDI}
53
53
  */
54
54
  this.midiData = parsedMidi;
55
55
 
@@ -135,7 +135,7 @@ export function loadNewSongList(midiBuffers)
135
135
  {
136
136
  /**
137
137
  * parse the MIDIs (only the array buffers, MIDI is unchanged)
138
- * @type {MIDI[]}
138
+ * @type {BasicMIDI[]}
139
139
  */
140
140
  this.songs = midiBuffers.reduce((mids, b) => {
141
141
  if(b.duration)
@@ -71,7 +71,7 @@ class WorkletSequencer
71
71
 
72
72
  /**
73
73
  * the current track data
74
- * @type {MIDI}
74
+ * @type {BasicMIDI}
75
75
  */
76
76
  this.midiData = undefined;
77
77
 
@@ -3,6 +3,10 @@ The code here is responsible for parsing the SoundFont2 file and
3
3
  providing an easy way to get the data out.
4
4
  Default modulators are also stored here (in `modulators.js`)
5
5
 
6
- `read` folder contains the classes that represent the soundfont file
6
+ `basic_soundfont` folder contains the classes that represent the soundfont file.
7
7
 
8
- `write` folder contains the code for writing out an `.sf2` file.
8
+ `read_sf2` folder contains the code for reading an `.sf2` file.
9
+
10
+ `write` folder contains the code for writing out an `.sf2` file.
11
+
12
+ `dls` folder contains the code for reading a `.dls` file (and converting in into a soundfont representation).
@@ -58,15 +58,15 @@ export class BasicSample {
58
58
  */
59
59
  this.sampleType = sampleType
60
60
  /**
61
- * Relative to start of the sample, bytes
61
+ * Relative to start of the sample, bytes assuming 16 bit
62
62
  * @type {number}
63
63
  */
64
64
  this.sampleLoopStartIndex = loopStart
65
65
  /**
66
- * Relative to start of the sample, in bytes
66
+ * Relative to start of the sample, in bytes assuming 16 bit
67
67
  * @type {number}
68
68
  */
69
- this.sampleLoopEndIndex = loopEnd
69
+ this.sampleLoopEndIndex = loopEnd;
70
70
 
71
71
  /**
72
72
  * Indicates if the sample is compressed
@@ -6,34 +6,34 @@
6
6
 
7
7
  export class BasicZone
8
8
  {
9
- constructor()
10
- {
11
- /**
12
- * The zone's generators
13
- * @type {Generator[]}
14
- */
15
- this.generators = [];
16
- /**
17
- * The zone's modulators
18
- * @type {Modulator[]}
19
- */
20
- this.modulators = [];
21
- /**
22
- * Indicates if the zone is global
23
- * @type {boolean}
24
- */
25
- this.isGlobal = false;
26
- /**
27
- * The zone's key range
28
- * @type {SoundFontRange}
29
- */
30
- this.keyRange = { min: 0, max: 127 };
9
+ /**
10
+ * The zone's velocity range
11
+ * @type {SoundFontRange}
12
+ */
13
+ velRange = { min: 0, max: 127 };
31
14
 
32
- /**
33
- * The zone's velocity range
34
- * @type {SoundFontRange}
35
- */
36
- this.velRange = { min: 0, max: 127 };
37
- }
15
+ /**
16
+ * The zone's key range
17
+ * @type {SoundFontRange}
18
+ */
19
+ keyRange = { min: 0, max: 127 };
20
+
21
+ /**
22
+ * Indicates if the zone is global
23
+ * @type {boolean}
24
+ */
25
+ isGlobal = false;
26
+
27
+ /**
28
+ * The zone's generators
29
+ * @type {Generator[]}
30
+ */
31
+ generators = [];
32
+
33
+ /**
34
+ * The zone's modulators
35
+ * @type {Modulator[]}
36
+ */
37
+ modulators = [];
38
38
  }
39
39