spessasynth_core 1.0.5 → 1.0.7

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 (56) hide show
  1. package/.idea/inspectionProfiles/Project_Default.xml +0 -0
  2. package/.idea/jsLibraryMappings.xml +0 -0
  3. package/.idea/modules.xml +0 -0
  4. package/.idea/spessasynth_core.iml +0 -0
  5. package/.idea/vcs.xml +0 -0
  6. package/LICENSE +0 -0
  7. package/README.md +0 -0
  8. package/index.js +0 -0
  9. package/package.json +1 -1
  10. package/spessasynth_core/midi_parser/README.md +0 -0
  11. package/spessasynth_core/midi_parser/midi_loader.js +0 -0
  12. package/spessasynth_core/midi_parser/midi_message.js +0 -0
  13. package/spessasynth_core/sequencer/sequencer.js +0 -0
  14. package/spessasynth_core/sequencer/worklet_sequencer/play.js +0 -0
  15. package/spessasynth_core/sequencer/worklet_sequencer/process_event.js +1 -20
  16. package/spessasynth_core/sequencer/worklet_sequencer/process_tick.js +0 -0
  17. package/spessasynth_core/sequencer/worklet_sequencer/song_control.js +25 -3
  18. package/spessasynth_core/soundfont/README.md +0 -0
  19. package/spessasynth_core/soundfont/chunk/generators.js +0 -0
  20. package/spessasynth_core/soundfont/chunk/instruments.js +0 -0
  21. package/spessasynth_core/soundfont/chunk/modulators.js +0 -0
  22. package/spessasynth_core/soundfont/chunk/presets.js +0 -0
  23. package/spessasynth_core/soundfont/chunk/riff_chunk.js +0 -0
  24. package/spessasynth_core/soundfont/chunk/samples.js +0 -0
  25. package/spessasynth_core/soundfont/chunk/zones.js +0 -0
  26. package/spessasynth_core/soundfont/soundfont_parser.js +0 -0
  27. package/spessasynth_core/synthetizer/README.md +0 -0
  28. package/spessasynth_core/synthetizer/synthesizer.js +0 -0
  29. package/spessasynth_core/synthetizer/worklet_system/README.md +0 -0
  30. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -0
  31. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -0
  32. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_off.js +0 -0
  33. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_on.js +2 -2
  34. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/program_control.js +0 -0
  35. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -0
  36. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -0
  37. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -0
  38. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/voice_control.js +51 -15
  39. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lfo.js +0 -0
  40. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -0
  41. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +0 -0
  42. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +0 -0
  43. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +0 -0
  44. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/unit_converter.js +0 -0
  45. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -0
  46. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -0
  47. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +0 -0
  48. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +0 -0
  49. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +0 -0
  50. package/spessasynth_core/utils/README.md +0 -0
  51. package/spessasynth_core/utils/buffer_to_wav.js +0 -0
  52. package/spessasynth_core/utils/byte_functions.js +0 -0
  53. package/spessasynth_core/utils/loggin.js +0 -0
  54. package/spessasynth_core/utils/other.js +0 -0
  55. package/spessasynth_core/utils/shiftable_array.js +0 -0
  56. package/spessasynth_core/utils/stbvorbis_sync.js +0 -0
File without changes
File without changes
package/.idea/modules.xml CHANGED
File without changes
File without changes
package/.idea/vcs.xml CHANGED
File without changes
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
File without changes
package/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_core",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "SoundFont2 synthesizer library for node.js",
5
5
  "main": "index.js",
6
6
  "type": "module",
File without changes
File without changes
File without changes
File without changes
@@ -50,27 +50,8 @@ export function _processEvent(event, trackIndex)
50
50
  }
51
51
  break;
52
52
 
53
+ // recognized but ignored
53
54
  case messageTypes.midiPort:
54
- const port = event.messageData[0];
55
- // assign new 16 channels if the port is not occupied yet
56
- if(this.midiPortChannelOffset === 0)
57
- {
58
- this.midiPortChannelOffset += 16;
59
- this.midiPortChannelOffsets[port] = 0;
60
- }
61
-
62
- if(this.midiPortChannelOffsets[port] === undefined)
63
- {
64
- if(this.synth.workletProcessorChannels.length < this.midiPortChannelOffset + 16) {
65
- this._addNewMidiPort();
66
- }
67
- this.midiPortChannelOffsets[port] = this.midiPortChannelOffset;
68
- this.midiPortChannelOffset += 16;
69
- }
70
-
71
- this.midiPorts[trackIndex] = port;
72
- break;
73
-
74
55
  case messageTypes.endOfTrack:
75
56
  case messageTypes.midiChannelPrefix:
76
57
  case messageTypes.timeSignature:
@@ -33,17 +33,39 @@ export function loadNewSequence(parsedMidi)
33
33
  */
34
34
  this.tracks = this.midiData.tracks;
35
35
 
36
- // copy over the port data (can be overwritten in real time if needed)
36
+ // clear last port data
37
+ this.midiPortChannelOffset = 0;
38
+ this.midiPortChannelOffsets = {};
39
+ // copy over the port data
37
40
  this.midiPorts = this.midiData.midiPorts;
38
41
 
42
+ // assign port offsets
43
+ this.midiData.midiPorts.forEach((port, trackIndex) => {
44
+ // assign new 16 channels if the port is not occupied yet
45
+ if(this.midiPortChannelOffset === 0)
46
+ {
47
+ this.midiPortChannelOffset += 16;
48
+ this.midiPortChannelOffsets[port] = 0;
49
+ }
50
+
51
+ if(this.midiPortChannelOffsets[port] === undefined)
52
+ {
53
+ if(this.synth.workletProcessorChannels.length < this.midiPortChannelOffset + 16) {
54
+ this._addNewMidiPort();
55
+ }
56
+ this.midiPortChannelOffsets[port] = this.midiPortChannelOffset;
57
+ this.midiPortChannelOffset += 16;
58
+ }
59
+
60
+ this.midiPorts[trackIndex] = port;
61
+ });
62
+
39
63
  /**
40
64
  * Same as Audio.duration (seconds)
41
65
  * @type {number}
42
66
  */
43
67
  this.duration = this.midiData.duration;
44
68
  SpessaSynthInfo(`%cTotal song time: ${formatTime(Math.ceil(this.duration)).time}`, consoleColors.recognized);
45
- this.midiPortChannelOffset = 0;
46
- this.midiPortChannelOffsets = {};
47
69
 
48
70
  this.synth.resetAllControllers();
49
71
  if(this.duration <= 1)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -64,12 +64,12 @@ export function noteOn(channel, midiNote, velocity, enableDebugging = false)
64
64
  computeModulators(voice, this.workletProcessorChannels[channel].midiControllers);
65
65
  voice.currentAttenuationDb = 100;
66
66
  })
67
- channelVoices.push(...voices);
68
67
 
69
68
  this.totalVoicesAmount += voices.length;
70
69
  // cap the voices
71
70
  if(this.totalVoicesAmount > VOICE_CAP)
72
71
  {
73
- this.voiceKilling(this.totalVoicesAmount - VOICE_CAP);
72
+ this.voiceKilling(voices.length);
74
73
  }
74
+ channelVoices.push(...voices);
75
75
  }
@@ -143,6 +143,35 @@ export function renderVoice(channel, voice, output, reverbOutput, chorusOutput)
143
143
  chorusOutput, voice.modulatedGenerators[generatorTypes.chorusEffectsSend]);
144
144
  }
145
145
 
146
+ /**
147
+ * @param channel {WorkletProcessorChannel}
148
+ * @param voice {WorkletVoice}
149
+ * @return {number}
150
+ */
151
+ function getPriority(channel, voice)
152
+ {
153
+ let priority = 0;
154
+ if(channel.drumChannel)
155
+ {
156
+ // important
157
+ priority += 5;
158
+ }
159
+ if(voice.isInRelease)
160
+ {
161
+ // not important
162
+ priority -= 5;
163
+ }
164
+ // less velocity = less important
165
+ priority += voice.velocity / 25; // map to 0-5
166
+ // the newer, more important
167
+ priority -= voice.volumeEnvelopeState;
168
+ if(voice.isInRelease)
169
+ {
170
+ priority -= 5;
171
+ }
172
+ priority -= voice.currentAttenuationDb / 50;
173
+ return priority;
174
+ }
146
175
 
147
176
  /**
148
177
  * @this {Synthesizer}
@@ -150,23 +179,30 @@ export function renderVoice(channel, voice, output, reverbOutput, chorusOutput)
150
179
  */
151
180
  export function voiceKilling(amount)
152
181
  {
153
- // kill the smallest velocity voices
154
- let voicesOrderedByVelocity = this.workletProcessorChannels.map(channel => channel.voices);
155
-
156
- /**
157
- * @type {WorkletVoice[]}
158
- */
159
- voicesOrderedByVelocity = voicesOrderedByVelocity.flat();
160
- voicesOrderedByVelocity.sort((v1, v2) => v1.velocity - v2.velocity);
161
- if(voicesOrderedByVelocity.length < amount)
182
+ let allVoices = [];
183
+ for (const channel of this.workletProcessorChannels)
162
184
  {
163
- amount = voicesOrderedByVelocity.length;
185
+ for (const voice of channel.voices)
186
+ {
187
+ if (!voice.finished)
188
+ {
189
+ const priority = getPriority(channel, voice);
190
+ allVoices.push({ channel, voice, priority });
191
+ }
192
+ }
164
193
  }
165
- for (let i = 0; i < amount; i++) {
166
- const voice = voicesOrderedByVelocity[i];
167
- this.workletProcessorChannels[voice.channelNumber].voices
168
- .splice(this.workletProcessorChannels[voice.channelNumber].voices.indexOf(voice), 1);
169
- this.totalVoicesAmount--;
194
+
195
+ // Step 2: Sort voices by priority (ascending order)
196
+ allVoices.sort((a, b) => a.priority - b.priority);
197
+ const voicesToRemove = allVoices.slice(0, amount);
198
+
199
+ for (const { channel, voice } of voicesToRemove)
200
+ {
201
+ const index = channel.voices.indexOf(voice);
202
+ if (index > -1)
203
+ {
204
+ channel.voices.splice(index, 1);
205
+ }
170
206
  }
171
207
  }
172
208
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes