spessasynth_lib 3.25.22 → 3.26.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 (168) hide show
  1. package/README.md +29 -114
  2. package/index.js +33 -33
  3. package/package.json +16 -6
  4. package/external_midi/README.md +0 -4
  5. package/external_midi/midi_handler.js +0 -130
  6. package/external_midi/web_midi_link.js +0 -43
  7. package/externals/fflate/LICENSE +0 -21
  8. package/externals/fflate/fflate.min.js +0 -1
  9. package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
  10. package/externals/stbvorbis_sync/LICENSE +0 -202
  11. package/externals/stbvorbis_sync/NOTICE +0 -6
  12. package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
  13. package/midi/README.md +0 -32
  14. package/midi/basic_midi.js +0 -565
  15. package/midi/midi_builder.js +0 -202
  16. package/midi/midi_data.js +0 -63
  17. package/midi/midi_loader.js +0 -324
  18. package/midi/midi_message.js +0 -254
  19. package/midi/midi_sequence.js +0 -225
  20. package/midi/midi_tools/get_note_times.js +0 -154
  21. package/midi/midi_tools/midi_editor.js +0 -611
  22. package/midi/midi_tools/midi_writer.js +0 -99
  23. package/midi/midi_tools/rmidi_writer.js +0 -567
  24. package/midi/midi_tools/used_keys_loaded.js +0 -238
  25. package/midi/xmf_loader.js +0 -454
  26. package/sequencer/README.md +0 -32
  27. package/sequencer/sequencer_engine/events.js +0 -207
  28. package/sequencer/sequencer_engine/play.js +0 -353
  29. package/sequencer/sequencer_engine/process_event.js +0 -169
  30. package/sequencer/sequencer_engine/process_tick.js +0 -106
  31. package/sequencer/sequencer_engine/sequencer_engine.js +0 -337
  32. package/sequencer/sequencer_engine/song_control.js +0 -229
  33. package/sequencer/worklet_wrapper/default_sequencer_options.js +0 -8
  34. package/sequencer/worklet_wrapper/sequencer.js +0 -807
  35. package/sequencer/worklet_wrapper/sequencer_message.js +0 -53
  36. package/soundfont/README.md +0 -13
  37. package/soundfont/basic_soundfont/basic_instrument.js +0 -77
  38. package/soundfont/basic_soundfont/basic_preset.js +0 -336
  39. package/soundfont/basic_soundfont/basic_sample.js +0 -197
  40. package/soundfont/basic_soundfont/basic_soundfont.js +0 -565
  41. package/soundfont/basic_soundfont/basic_zone.js +0 -64
  42. package/soundfont/basic_soundfont/basic_zones.js +0 -43
  43. package/soundfont/basic_soundfont/generator.js +0 -220
  44. package/soundfont/basic_soundfont/modulator.js +0 -378
  45. package/soundfont/basic_soundfont/riff_chunk.js +0 -149
  46. package/soundfont/basic_soundfont/write_dls/art2.js +0 -173
  47. package/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
  48. package/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -400
  49. package/soundfont/basic_soundfont/write_dls/ins.js +0 -103
  50. package/soundfont/basic_soundfont/write_dls/lins.js +0 -18
  51. package/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
  52. package/soundfont/basic_soundfont/write_dls/rgn2.js +0 -121
  53. package/soundfont/basic_soundfont/write_dls/wave.js +0 -94
  54. package/soundfont/basic_soundfont/write_dls/write_dls.js +0 -119
  55. package/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
  56. package/soundfont/basic_soundfont/write_dls/wvpl.js +0 -32
  57. package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -39
  58. package/soundfont/basic_soundfont/write_sf2/igen.js +0 -80
  59. package/soundfont/basic_soundfont/write_sf2/imod.js +0 -46
  60. package/soundfont/basic_soundfont/write_sf2/inst.js +0 -34
  61. package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -39
  62. package/soundfont/basic_soundfont/write_sf2/pgen.js +0 -82
  63. package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -42
  64. package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -46
  65. package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -80
  66. package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -55
  67. package/soundfont/basic_soundfont/write_sf2/write.js +0 -222
  68. package/soundfont/dls/articulator_converter.js +0 -396
  69. package/soundfont/dls/dls_destinations.js +0 -38
  70. package/soundfont/dls/dls_preset.js +0 -44
  71. package/soundfont/dls/dls_sample.js +0 -75
  72. package/soundfont/dls/dls_soundfont.js +0 -186
  73. package/soundfont/dls/dls_sources.js +0 -62
  74. package/soundfont/dls/dls_zone.js +0 -95
  75. package/soundfont/dls/read_articulation.js +0 -299
  76. package/soundfont/dls/read_instrument.js +0 -121
  77. package/soundfont/dls/read_instrument_list.js +0 -17
  78. package/soundfont/dls/read_lart.js +0 -35
  79. package/soundfont/dls/read_region.js +0 -152
  80. package/soundfont/dls/read_samples.js +0 -270
  81. package/soundfont/load_soundfont.js +0 -21
  82. package/soundfont/read_sf2/generators.js +0 -46
  83. package/soundfont/read_sf2/instruments.js +0 -66
  84. package/soundfont/read_sf2/modulators.js +0 -36
  85. package/soundfont/read_sf2/presets.js +0 -80
  86. package/soundfont/read_sf2/samples.js +0 -304
  87. package/soundfont/read_sf2/soundfont.js +0 -305
  88. package/soundfont/read_sf2/zones.js +0 -263
  89. package/synthetizer/README.md +0 -10
  90. package/synthetizer/audio_effects/effects_config.js +0 -25
  91. package/synthetizer/audio_effects/fancy_chorus.js +0 -162
  92. package/synthetizer/audio_effects/rb_compressed.min.js +0 -1
  93. package/synthetizer/audio_effects/reverb.js +0 -35
  94. package/synthetizer/audio_effects/reverb_as_binary.js +0 -18
  95. package/synthetizer/audio_engine/README.md +0 -25
  96. package/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -266
  97. package/synthetizer/audio_engine/engine_components/controller_tables.js +0 -88
  98. package/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -149
  99. package/synthetizer/audio_engine/engine_components/lfo.js +0 -26
  100. package/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
  101. package/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -471
  102. package/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
  103. package/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
  104. package/synthetizer/audio_engine/engine_components/soundfont_manager/sfman_message.js +0 -9
  105. package/synthetizer/audio_engine/engine_components/soundfont_manager/soundfont_manager.js +0 -254
  106. package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
  107. package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  108. package/synthetizer/audio_engine/engine_components/voice.js +0 -519
  109. package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
  110. package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
  111. package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
  112. package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
  113. package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
  114. package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
  115. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
  116. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
  117. package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  118. package/synthetizer/audio_engine/engine_methods/note_on.js +0 -174
  119. package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  120. package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
  121. package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
  122. package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
  123. package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
  124. package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
  125. package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
  126. package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
  127. package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
  128. package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
  129. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  130. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  131. package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  132. package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -744
  133. package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
  134. package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
  135. package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
  136. package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  137. package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
  138. package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  139. package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  140. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  141. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  142. package/synthetizer/audio_engine/main_processor.js +0 -765
  143. package/synthetizer/audio_engine/message_protocol/README.md +0 -13
  144. package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
  145. package/synthetizer/audio_engine/message_protocol/worklet_message.js +0 -107
  146. package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
  147. package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  148. package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
  149. package/synthetizer/synth_constants.js +0 -20
  150. package/synthetizer/worklet_processor.min.js +0 -21
  151. package/synthetizer/worklet_wrapper/key_modifier_manager.js +0 -104
  152. package/synthetizer/worklet_wrapper/synth_event_handler.js +0 -214
  153. package/synthetizer/worklet_wrapper/synth_soundfont_manager.js +0 -111
  154. package/synthetizer/worklet_wrapper/synthetizer.js +0 -1027
  155. package/synthetizer/worklet_wrapper/worklet_processor.js +0 -340
  156. package/synthetizer/worklet_wrapper/worklet_url.js +0 -16
  157. package/utils/README.md +0 -5
  158. package/utils/buffer_to_wav.js +0 -186
  159. package/utils/byte_functions/big_endian.js +0 -32
  160. package/utils/byte_functions/little_endian.js +0 -77
  161. package/utils/byte_functions/string.js +0 -107
  162. package/utils/byte_functions/variable_length_quantity.js +0 -42
  163. package/utils/fill_with_defaults.js +0 -21
  164. package/utils/indexed_array.js +0 -52
  165. package/utils/loggin.js +0 -79
  166. package/utils/other.js +0 -92
  167. package/utils/sysex_detector.js +0 -58
  168. package/utils/xg_hacks.js +0 -193
@@ -1,66 +0,0 @@
1
- import { consoleColors } from "../../../../utils/other.js";
2
- import { SpessaSynthInfo } from "../../../../utils/loggin.js";
3
- import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
4
- import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
5
- import { midiControllers } from "../../../../midi/midi_message.js";
6
-
7
- /**
8
- * Executes a data entry for an RPN tuning
9
- * @param dataValue {number} dataEntry LSB
10
- * @this {MidiAudioChannel}
11
- * @private
12
- */
13
- export function dataEntryFine(dataValue)
14
- {
15
- switch (this.dataEntryState)
16
- {
17
- default:
18
- break;
19
-
20
- case dataEntryStates.RPCoarse:
21
- case dataEntryStates.RPFine:
22
- const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
23
- switch (rpnValue)
24
- {
25
- default:
26
- break;
27
-
28
- // pitch bend range fine tune
29
- case 0x0000:
30
- if (dataValue === 0)
31
- {
32
- break;
33
- }
34
- // 14-bit value, so upper 7 are coarse and lower 7 are fine!
35
- this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] |= dataValue;
36
- const actualTune = (this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] >> 7) + dataValue / 128;
37
- SpessaSynthInfo(
38
- `%cChannel ${this.channelNumber} bend range. Semitones: %c${actualTune}`,
39
- consoleColors.info,
40
- consoleColors.value
41
- );
42
- break;
43
-
44
- // fine-tuning
45
- case 0x0001:
46
- // grab the data and shift
47
- const coarse = this.customControllers[customControllers.channelTuning];
48
- const finalTuning = (coarse << 7) | dataValue;
49
- this.setTuning(finalTuning * 0.01220703125); // multiply by 8192 / 100 (cent increments)
50
- break;
51
-
52
- // modulation depth
53
- case 0x0005:
54
- const currentModulationDepthCents = this.customControllers[customControllers.modulationMultiplier] * 50;
55
- let cents = currentModulationDepthCents + (dataValue / 128) * 100;
56
- this.setModulationDepth(cents);
57
- break;
58
-
59
- case 0x3FFF:
60
- this.resetParameters();
61
- break;
62
-
63
- }
64
-
65
- }
66
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * @param isMuted {boolean}
3
- * @this {MidiAudioChannel}
4
- */
5
- export function muteChannel(isMuted)
6
- {
7
- if (isMuted)
8
- {
9
- this.stopAllNotes(true);
10
- }
11
- this.isMuted = isMuted;
12
- this.sendChannelProperty();
13
- this.synth.callEvent("mutechannel", {
14
- channel: this.channelNumber,
15
- isMuted: isMuted
16
- });
17
- }
@@ -1,174 +0,0 @@
1
- import { computeModulators } from "../engine_components/compute_modulator.js";
2
- import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
3
- import { midiControllers } from "../../../midi/midi_message.js";
4
- import { portamentoTimeToSeconds } from "./portamento_time.js";
5
-
6
- /**
7
- * sends a "MIDI Note on message"
8
- * @param midiNote {number}
9
- * @param velocity {number}
10
- * @this {MidiAudioChannel}
11
- */
12
- export function noteOn(midiNote, velocity)
13
- {
14
- if (velocity < 1)
15
- {
16
- this.noteOff(midiNote);
17
- return;
18
- }
19
- velocity = Math.min(127, velocity);
20
-
21
- if (
22
- (this.synth.highPerformanceMode && this.synth.totalVoicesAmount > 200 && velocity < 40) ||
23
- (this.synth.highPerformanceMode && velocity < 10) ||
24
- (this.isMuted)
25
- )
26
- {
27
- return;
28
- }
29
-
30
- const realKey = midiNote + this.channelTransposeKeyShift;
31
- let sentMidiNote = realKey;
32
-
33
- if (realKey > 127 || realKey < 0)
34
- {
35
- return;
36
- }
37
- const program = this.preset.program;
38
- if (this.synth.tunings[program]?.[realKey]?.midiNote >= 0)
39
- {
40
- sentMidiNote = this.synth.tunings[program]?.[realKey].midiNote;
41
- }
42
-
43
- // velocity override
44
- if (this.velocityOverride > 0)
45
- {
46
- velocity = this.velocityOverride;
47
- }
48
-
49
- // key velocity override
50
- const keyVel = this.synth.keyModifierManager.getVelocity(this.channelNumber, realKey);
51
- if (keyVel > -1)
52
- {
53
- velocity = keyVel;
54
- }
55
-
56
- // gain
57
- const voiceGain = this.synth.keyModifierManager.getGain(this.channelNumber, realKey);
58
-
59
- // portamento
60
- let portamentoFromKey = -1;
61
- let portamentoDuration = 0;
62
- // note: the 14-bit value needs to go down to 7-bit
63
- const portamentoTime = this.midiControllers[midiControllers.portamentoTime] >> 7;
64
- const control = this.midiControllers[midiControllers.portamentoControl];
65
- const currentFromKey = control >> 7;
66
- if (
67
- !this.drumChannel && // no portamento on drum channel
68
- currentFromKey !== sentMidiNote && // if the same note, there's no portamento
69
- this.midiControllers[midiControllers.portamentoOnOff] >= 8192 && // (64 << 7)
70
- portamentoTime > 0 // 0 duration is no portamento
71
- )
72
- {
73
- // a value of one means the initial portamento
74
- if (control !== 1)
75
- {
76
- const diff = Math.abs(sentMidiNote - currentFromKey);
77
- portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);
78
- portamentoFromKey = currentFromKey;
79
- }
80
- // set portamento control to previous value
81
- this.controllerChange(midiControllers.portamentoControl, sentMidiNote);
82
- }
83
-
84
- // get voices
85
- const voices = this.synth.getVoices(
86
- this.channelNumber,
87
- sentMidiNote,
88
- velocity,
89
- realKey
90
- );
91
-
92
- // zero means disabled
93
- let panOverride = 0;
94
- if (this.randomPan)
95
- {
96
- // the range is -500 to 500
97
- panOverride = Math.round(Math.random() * 1000 - 500);
98
- }
99
-
100
- // add voices
101
- const channelVoices = this.voices;
102
- voices.forEach(voice =>
103
- {
104
- // apply portamento
105
- voice.portamentoFromKey = portamentoFromKey;
106
- voice.portamentoDuration = portamentoDuration;
107
-
108
- // apply pan override
109
- voice.overridePan = panOverride;
110
-
111
- // apply gain override
112
- voice.gain = voiceGain;
113
-
114
- // apply exclusive class
115
- const exclusive = voice.exclusiveClass;
116
- if (exclusive !== 0)
117
- {
118
- // kill all voices with the same exclusive class
119
- channelVoices.forEach(v =>
120
- {
121
- if (v.exclusiveClass === exclusive)
122
- {
123
- v.exclusiveRelease(this.synth.currentSynthTime);
124
- }
125
- });
126
- }
127
- // compute all modulators
128
- computeModulators(voice, this.midiControllers);
129
- // modulate sample offsets (these are not real time)
130
- const cursorStartOffset = voice.modulatedGenerators[generatorTypes.startAddrsOffset] + voice.modulatedGenerators[generatorTypes.startAddrsCoarseOffset] * 32768;
131
- const endOffset = voice.modulatedGenerators[generatorTypes.endAddrOffset] + voice.modulatedGenerators[generatorTypes.endAddrsCoarseOffset] * 32768;
132
- const loopStartOffset = voice.modulatedGenerators[generatorTypes.startloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.startloopAddrsCoarseOffset] * 32768;
133
- const loopEndOffset = voice.modulatedGenerators[generatorTypes.endloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.endloopAddrsCoarseOffset] * 32768;
134
- const sm = voice.sample;
135
- // apply them
136
- const clamp = num => Math.max(0, Math.min(sm.sampleData.length - 1, num));
137
- sm.cursor = clamp(sm.cursor + cursorStartOffset);
138
- sm.end = clamp(sm.end + endOffset);
139
- sm.loopStart = clamp(sm.loopStart + loopStartOffset);
140
- sm.loopEnd = clamp(sm.loopEnd + loopEndOffset);
141
- // swap loops if needed
142
- if (sm.loopEnd < sm.loopStart)
143
- {
144
- const temp = sm.loopStart;
145
- sm.loopStart = sm.loopEnd;
146
- sm.loopEnd = temp;
147
- }
148
- if (sm.loopEnd - sm.loopStart < 1)
149
- {
150
- sm.loopingMode = 0;
151
- sm.isLooping = false;
152
- }
153
- // set the current attenuation to target,
154
- // as it's interpolated (we don't want 0 attenuation for even a split second)
155
- voice.volumeEnvelope.attenuation = voice.volumeEnvelope.attenuationTargetGain;
156
- // set initial pan to avoid split second changing from middle to the correct value
157
- voice.currentPan = Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan])); // -500 to 500
158
- });
159
-
160
- this.synth.totalVoicesAmount += voices.length;
161
- // cap the voices
162
- if (this.synth.totalVoicesAmount > this.synth.voiceCap)
163
- {
164
- this.synth.voiceKilling(voices.length);
165
- }
166
- channelVoices.push(...voices);
167
- this.sendChannelProperty();
168
- this.synth.callEvent("noteon", {
169
- midiNote: midiNote,
170
- channel: this.channelNumber,
171
- velocity: velocity
172
- });
173
-
174
- }
@@ -1,92 +0,0 @@
1
- // Tests were performed by John Novak
2
- // https://github.com/dosbox-staging/dosbox-staging/pull/2705
3
-
4
- /*
5
- CC 5 value Portamento time
6
- ---------- ---------------
7
- 0 0.000 s
8
- 1 0.006 s
9
- 2 0.023 s
10
- 4 0.050 s
11
- 8 0.110 s
12
- 16 0.250 s
13
- 32 0.500 s
14
- 64 2.060 s
15
- 80 4.200 s
16
- 96 8.400 s
17
- 112 19.500 s
18
- 116 26.700 s
19
- 120 40.000 s
20
- 124 80.000 s
21
- 127 480.000 s
22
- */
23
-
24
- const portamentoLookup = {
25
- 0: 0.000,
26
- 1: 0.006,
27
- 2: 0.023,
28
- 4: 0.050,
29
- 8: 0.110,
30
- 16: 0.250,
31
- 32: 0.500,
32
- 64: 2.060,
33
- 80: 4.200,
34
- 96: 8.400,
35
- 112: 19.500,
36
- 116: 26.700,
37
- 120: 40.000,
38
- 124: 80.000,
39
- 127: 480.000
40
- };
41
-
42
- /**
43
- * @param value {number}
44
- * @returns {number}
45
- */
46
- function getLookup(value)
47
- {
48
- if (portamentoLookup[value] !== undefined)
49
- {
50
- return portamentoLookup[value];
51
- }
52
- // get the nearest lower and upper points from the lookup table
53
- let lower = null;
54
- let upper = null;
55
-
56
- for (let key of Object.keys(portamentoLookup))
57
- {
58
- key = parseInt(key);
59
- if (key < value && (lower === null || key > lower))
60
- {
61
- lower = key;
62
- }
63
- if (key > value && (upper === null || key < upper))
64
- {
65
- upper = key;
66
- }
67
- }
68
-
69
- // if we have found both lower and upper points, perform linear interpolation
70
- if (lower !== null && upper !== null)
71
- {
72
- let lowerTime = portamentoLookup[lower];
73
- let upperTime = portamentoLookup[upper];
74
-
75
- // linear interpolation
76
- return lowerTime + ((value - lower) * (upperTime - lowerTime)) / (upper - lower);
77
- }
78
- return 0;
79
- }
80
-
81
-
82
- /**
83
- * Converts portamento time to seconds
84
- * @param time {number} 0 - 127
85
- * @param distance {number} distance in keys
86
- * @returns {number} seconds
87
- */
88
- export function portamentoTimeToSeconds(time, distance)
89
- {
90
- // this seems to work fine for the MIDIs I have
91
- return getLookup(time) * (distance / 30);
92
- }
@@ -1,61 +0,0 @@
1
- /**
2
- * executes a program change
3
- * @param programNumber {number}
4
- * @this {MidiAudioChannel}
5
- */
6
- export function programChange(programNumber)
7
- {
8
- if (this.lockPreset)
9
- {
10
- return;
11
- }
12
- // always 128 for percussion
13
- let bank = this.getBankSelect();
14
- let sentBank;
15
- /**
16
- * @type {BasicPreset}
17
- */
18
- let preset;
19
-
20
- const isXG = this.isXGChannel;
21
- // check if override
22
- if (this.synth.overrideSoundfont)
23
- {
24
- const bankWithOffset = bank === 128 ? 128 : bank - this.synth.soundfontBankOffset;
25
- const p = this.synth.overrideSoundfont.getPresetNoFallback(
26
- bankWithOffset,
27
- programNumber,
28
- isXG
29
- );
30
- if (p)
31
- {
32
- sentBank = p.bank === 128 ? 128 : p.bank + this.synth.soundfontBankOffset;
33
- preset = p;
34
- this.presetUsesOverride = true;
35
- }
36
- else
37
- {
38
- preset = this.synth.soundfontManager.getPreset(bank, programNumber, isXG);
39
- const offset = this.synth.soundfontManager.soundfontList
40
- .find(s => s.soundfont === preset.parentSoundBank).bankOffset;
41
- sentBank = preset.bank - offset;
42
- this.presetUsesOverride = false;
43
- }
44
- }
45
- else
46
- {
47
- preset = this.synth.soundfontManager.getPreset(bank, programNumber, isXG);
48
- const offset = this.synth.soundfontManager.soundfontList
49
- .find(s => s.soundfont === preset.parentSoundBank).bankOffset;
50
- sentBank = preset.bank - offset;
51
- this.presetUsesOverride = false;
52
- }
53
- this.setPreset(preset);
54
- this.sentBank = sentBank;
55
- this.synth.callEvent("programchange", {
56
- channel: this.channelNumber,
57
- program: preset.program,
58
- bank: sentBank
59
- });
60
- this.sendChannelProperty();
61
- }
@@ -1,196 +0,0 @@
1
- import { VolumeEnvelope } from "../engine_components/volume_envelope.js";
2
- import { ModulationEnvelope } from "../engine_components/modulation_envelope.js";
3
- import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
4
- import { customControllers } from "../engine_components/controller_tables.js";
5
- import { absCentsToHz, timecentsToSeconds } from "../engine_components/unit_converter.js";
6
- import { getLFOValue } from "../engine_components/lfo.js";
7
- import { interpolationTypes, WavetableOscillator } from "../engine_components/wavetable_oscillator.js";
8
- import { WorkletLowpassFilter } from "../engine_components/lowpass_filter.js";
9
-
10
- /**
11
- * Renders a voice to the stereo output buffer
12
- * @param voice {Voice} the voice to render
13
- * @param timeNow {number} current time in seconds
14
- * @param outputLeft {Float32Array} the left output buffer
15
- * @param outputRight {Float32Array} the right output buffer
16
- * @param reverbOutputLeft {Float32Array} left output for reverb
17
- * @param reverbOutputRight {Float32Array} right output for reverb
18
- * @param chorusOutputLeft {Float32Array} left output for chorus
19
- * @param chorusOutputRight {Float32Array} right output for chorus
20
- * @this {MidiAudioChannel}
21
- * @returns {boolean} true if the voice is finished
22
- */
23
- export function renderVoice(
24
- voice, timeNow,
25
- outputLeft, outputRight,
26
- reverbOutputLeft, reverbOutputRight,
27
- chorusOutputLeft, chorusOutputRight
28
- )
29
- {
30
- // check if release
31
- if (!voice.isInRelease)
32
- {
33
- // if not in release, check if the release time is
34
- if (timeNow >= voice.releaseStartTime)
35
- {
36
- // release the voice here
37
- voice.isInRelease = true;
38
- VolumeEnvelope.startRelease(voice);
39
- ModulationEnvelope.startRelease(voice);
40
- if (voice.sample.loopingMode === 3)
41
- {
42
- voice.sample.isLooping = false;
43
- }
44
- }
45
- }
46
-
47
-
48
- // if the initial attenuation is more than 100dB, skip the voice (it's silent anyway)
49
- if (voice.modulatedGenerators[generatorTypes.initialAttenuation] > 2500)
50
- {
51
- if (voice.isInRelease)
52
- {
53
- voice.finished = true;
54
- }
55
- return voice.finished;
56
- }
57
-
58
- // TUNING
59
- let targetKey = voice.targetKey;
60
-
61
- // calculate tuning
62
- let cents = voice.modulatedGenerators[generatorTypes.fineTune] // soundfont fine tune
63
- + this.channelOctaveTuning[voice.midiNote] // MTS octave tuning
64
- + this.channelTuningCents; // channel tuning
65
- let semitones = voice.modulatedGenerators[generatorTypes.coarseTune]; // soundfont coarse tuning
66
-
67
- // midi tuning standard
68
- const tuning = this.synth.tunings[this.preset.program]?.[voice.realKey];
69
- if (tuning !== undefined && tuning?.midiNote >= 0)
70
- {
71
- // override key
72
- targetKey = tuning.midiNote;
73
- // add micro-tonal tuning
74
- cents += tuning.centTuning;
75
- }
76
-
77
- // portamento
78
- if (voice.portamentoFromKey > -1)
79
- {
80
- // 0 to 1
81
- const elapsed = Math.min((timeNow - voice.startTime) / voice.portamentoDuration, 1);
82
- const diff = targetKey - voice.portamentoFromKey;
83
- // zero progress means the pitch being in fromKey, full progress means the normal pitch
84
- semitones -= diff * (1 - elapsed);
85
- }
86
-
87
- // calculate tuning by key using soundfont's scale tuning
88
- cents += (targetKey - voice.sample.rootKey) * voice.modulatedGenerators[generatorTypes.scaleTuning];
89
-
90
- // vibrato LFO
91
- const vibratoDepth = voice.modulatedGenerators[generatorTypes.vibLfoToPitch];
92
- if (vibratoDepth !== 0)
93
- {
94
- // calculate start time and lfo value
95
- const vibStart = voice.startTime + timecentsToSeconds(voice.modulatedGenerators[generatorTypes.delayVibLFO]);
96
- const vibFreqHz = absCentsToHz(voice.modulatedGenerators[generatorTypes.freqVibLFO]);
97
- const lfoVal = getLFOValue(vibStart, vibFreqHz, timeNow);
98
- // use modulation multiplier (RPN modulation depth)
99
- cents += lfoVal * (vibratoDepth * this.customControllers[customControllers.modulationMultiplier]);
100
- }
101
-
102
- // low pass excursion with LFO and mod envelope
103
- let lowpassExcursion = 0;
104
-
105
- // mod LFO
106
- const modPitchDepth = voice.modulatedGenerators[generatorTypes.modLfoToPitch];
107
- const modVolDepth = voice.modulatedGenerators[generatorTypes.modLfoToVolume];
108
- const modFilterDepth = voice.modulatedGenerators[generatorTypes.modLfoToFilterFc];
109
- let modLfoCentibels = 0;
110
- // don't compute mod lfo unless necessary
111
- if (modPitchDepth !== 0 || modFilterDepth !== 0 || modVolDepth !== 0)
112
- {
113
- // calculate start time and lfo value
114
- const modStart = voice.startTime + timecentsToSeconds(voice.modulatedGenerators[generatorTypes.delayModLFO]);
115
- const modFreqHz = absCentsToHz(voice.modulatedGenerators[generatorTypes.freqModLFO]);
116
- const modLfoValue = getLFOValue(modStart, modFreqHz, timeNow);
117
- // use modulation multiplier (RPN modulation depth)
118
- cents += modLfoValue * (modPitchDepth * this.customControllers[customControllers.modulationMultiplier]);
119
- // vole nv volume offset
120
- // negate the lfo value because audigy starts with increase rather than decrease
121
- modLfoCentibels = -modLfoValue * modVolDepth;
122
- // low pass frequency
123
- lowpassExcursion += modLfoValue * modFilterDepth;
124
- }
125
-
126
- // channel vibrato (GS NRPN)
127
- if (this.channelVibrato.depth > 0)
128
- {
129
- // same as others
130
- const channelVibrato = getLFOValue(
131
- voice.startTime + this.channelVibrato.delay,
132
- this.channelVibrato.rate,
133
- timeNow
134
- );
135
- if (channelVibrato)
136
- {
137
- cents += channelVibrato * this.channelVibrato.depth;
138
- }
139
- }
140
-
141
- // mod env
142
- const modEnvPitchDepth = voice.modulatedGenerators[generatorTypes.modEnvToPitch];
143
- const modEnvFilterDepth = voice.modulatedGenerators[generatorTypes.modEnvToFilterFc];
144
- // don't compute mod env unless necessary
145
- if (modEnvFilterDepth !== 0 || modEnvPitchDepth !== 0)
146
- {
147
- const modEnv = ModulationEnvelope.getValue(voice, timeNow);
148
- // apply values
149
- lowpassExcursion += modEnv * modEnvFilterDepth;
150
- cents += modEnv * modEnvPitchDepth;
151
- }
152
-
153
- // finally, calculate the playback rate
154
- const centsTotal = ~~(cents + semitones * 100);
155
- if (centsTotal !== voice.currentTuningCents)
156
- {
157
- voice.currentTuningCents = centsTotal;
158
- voice.currentTuningCalculated = Math.pow(2, centsTotal / 1200);
159
- }
160
-
161
-
162
- // SYNTHESIS
163
- const bufferOut = new Float32Array(outputLeft.length);
164
-
165
- // wave table oscillator
166
- switch (this.synth.interpolationType)
167
- {
168
- case interpolationTypes.fourthOrder:
169
- WavetableOscillator.getSampleCubic(voice, bufferOut);
170
- break;
171
-
172
- case interpolationTypes.linear:
173
- default:
174
- WavetableOscillator.getSampleLinear(voice, bufferOut);
175
- break;
176
-
177
- case interpolationTypes.nearestNeighbor:
178
- WavetableOscillator.getSampleNearest(voice, bufferOut);
179
- break;
180
- }
181
-
182
- // low pass filter
183
- WorkletLowpassFilter.apply(voice, bufferOut, lowpassExcursion, this.synth.filterSmoothingFactor);
184
-
185
- // vol env
186
- VolumeEnvelope.apply(voice, bufferOut, modLfoCentibels, this.synth.volumeEnvelopeSmoothingFactor);
187
-
188
- this.panVoice(
189
- voice,
190
- bufferOut,
191
- outputLeft, outputRight,
192
- reverbOutputLeft, reverbOutputRight,
193
- chorusOutputLeft, chorusOutputRight
194
- );
195
- return voice.finished;
196
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * @this {SpessaSynthProcessor}
3
- * @param sendPresets {boolean}
4
- * @param clearOverride {boolean}
5
- */
6
- export function clearSoundFont(sendPresets = true, clearOverride = true)
7
- {
8
- this.stopAllChannels(true);
9
- if (clearOverride)
10
- {
11
- delete this.overrideSoundfont;
12
- this.overrideSoundfont = undefined;
13
- }
14
- this.getDefaultPresets();
15
- this.cachedVoices = [];
16
-
17
- for (let i = 0; i < this.midiAudioChannels.length; i++)
18
- {
19
- const channelObject = this.midiAudioChannels[i];
20
- if (!clearOverride || (clearOverride && channelObject.presetUsesOverride))
21
- {
22
- channelObject.setPresetLock(false);
23
- }
24
- channelObject.programChange(channelObject.preset.program);
25
- }
26
- if (sendPresets)
27
- {
28
- this.sendPresetList();
29
- }
30
- }
@@ -1,22 +0,0 @@
1
- import { isSystemXG } from "../../../../utils/xg_hacks.js";
2
-
3
- /**
4
- * @this {SpessaSynthProcessor}
5
- * @param program {number}
6
- * @param bank {number}
7
- * @returns {BasicPreset}
8
- */
9
- export function getPreset(bank, program)
10
- {
11
- if (this.overrideSoundfont)
12
- {
13
- // if override soundfont
14
- const bankWithOffset = bank === 128 ? 128 : bank - this.soundfontBankOffset;
15
- const preset = this.overrideSoundfont.getPresetNoFallback(bankWithOffset, program, isSystemXG(this.system));
16
- if (preset)
17
- {
18
- return preset;
19
- }
20
- }
21
- return this.soundfontManager.getPreset(bank, program, isSystemXG(this.system));
22
- }