spessasynth_lib 0.0.1

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 (154) hide show
  1. package/.idea/modules.xml +8 -0
  2. package/.idea/spessasynth_lib.iml +12 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/copy_version.sh +38 -0
  5. package/index.js +73 -0
  6. package/package/@types/externals/stbvorbis_sync/stbvorbis_sync.min.d.ts +1 -0
  7. package/package/@types/index.d.ts +34 -0
  8. package/package/@types/midi_handler/midi_handler.d.ts +39 -0
  9. package/package/@types/midi_handler/web_midi_link.d.ts +12 -0
  10. package/package/@types/midi_parser/midi_data.d.ts +95 -0
  11. package/package/@types/midi_parser/midi_editor.d.ts +45 -0
  12. package/package/@types/midi_parser/midi_loader.d.ts +100 -0
  13. package/package/@types/midi_parser/midi_message.d.ts +154 -0
  14. package/package/@types/midi_parser/midi_writer.d.ts +6 -0
  15. package/package/@types/midi_parser/rmidi_writer.d.ts +9 -0
  16. package/package/@types/midi_parser/used_keys_loaded.d.ts +7 -0
  17. package/package/@types/sequencer/sequencer.d.ts +180 -0
  18. package/package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +28 -0
  19. package/package/@types/soundfont/read/generators.d.ts +98 -0
  20. package/package/@types/soundfont/read/instruments.d.ts +50 -0
  21. package/package/@types/soundfont/read/modulators.d.ts +73 -0
  22. package/package/@types/soundfont/read/presets.d.ts +87 -0
  23. package/package/@types/soundfont/read/riff_chunk.d.ts +31 -0
  24. package/package/@types/soundfont/read/samples.d.ts +134 -0
  25. package/package/@types/soundfont/read/zones.d.ts +141 -0
  26. package/package/@types/soundfont/soundfont.d.ts +76 -0
  27. package/package/@types/soundfont/write/ibag.d.ts +6 -0
  28. package/package/@types/soundfont/write/igen.d.ts +6 -0
  29. package/package/@types/soundfont/write/imod.d.ts +6 -0
  30. package/package/@types/soundfont/write/inst.d.ts +6 -0
  31. package/package/@types/soundfont/write/pbag.d.ts +6 -0
  32. package/package/@types/soundfont/write/pgen.d.ts +6 -0
  33. package/package/@types/soundfont/write/phdr.d.ts +6 -0
  34. package/package/@types/soundfont/write/pmod.d.ts +6 -0
  35. package/package/@types/soundfont/write/sdta.d.ts +11 -0
  36. package/package/@types/soundfont/write/shdr.d.ts +8 -0
  37. package/package/@types/soundfont/write/soundfont_trimmer.d.ts +6 -0
  38. package/package/@types/soundfont/write/write.d.ts +21 -0
  39. package/package/@types/synthetizer/audio_effects/effects_config.d.ts +29 -0
  40. package/package/@types/synthetizer/audio_effects/fancy_chorus.d.ts +93 -0
  41. package/package/@types/synthetizer/audio_effects/reverb.d.ts +7 -0
  42. package/package/@types/synthetizer/synth_event_handler.d.ts +161 -0
  43. package/package/@types/synthetizer/synthetizer.d.ts +294 -0
  44. package/package/@types/synthetizer/worklet_system/message_protocol/worklet_message.d.ts +89 -0
  45. package/package/@types/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.d.ts +134 -0
  46. package/package/@types/synthetizer/worklet_url.d.ts +5 -0
  47. package/package/@types/utils/buffer_to_wav.d.ts +8 -0
  48. package/package/@types/utils/byte_functions/big_endian.d.ts +13 -0
  49. package/package/@types/utils/byte_functions/little_endian.d.ts +35 -0
  50. package/package/@types/utils/byte_functions/string.d.ts +22 -0
  51. package/package/@types/utils/byte_functions/variable_length_quantity.d.ts +12 -0
  52. package/package/@types/utils/indexed_array.d.ts +21 -0
  53. package/package/@types/utils/loggin.d.ts +26 -0
  54. package/package/@types/utils/other.d.ts +32 -0
  55. package/package/LICENSE +26 -0
  56. package/package/README.md +84 -0
  57. package/package/externals/NOTICE +9 -0
  58. package/package/externals/libvorbis/@types/OggVorbisEncoder.d.ts +34 -0
  59. package/package/externals/libvorbis/OggVorbisEncoder.min.js +1 -0
  60. package/package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
  61. package/package/externals/stbvorbis_sync/LICENSE +202 -0
  62. package/package/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
  63. package/package/index.js +73 -0
  64. package/package/midi_handler/README.md +3 -0
  65. package/package/midi_handler/midi_handler.js +118 -0
  66. package/package/midi_handler/web_midi_link.js +41 -0
  67. package/package/midi_parser/README.md +3 -0
  68. package/package/midi_parser/midi_data.js +121 -0
  69. package/package/midi_parser/midi_editor.js +557 -0
  70. package/package/midi_parser/midi_loader.js +502 -0
  71. package/package/midi_parser/midi_message.js +234 -0
  72. package/package/midi_parser/midi_writer.js +95 -0
  73. package/package/midi_parser/rmidi_writer.js +271 -0
  74. package/package/midi_parser/used_keys_loaded.js +172 -0
  75. package/package/package.json +43 -0
  76. package/package/sequencer/README.md +23 -0
  77. package/package/sequencer/sequencer.js +439 -0
  78. package/package/sequencer/worklet_sequencer/events.js +92 -0
  79. package/package/sequencer/worklet_sequencer/play.js +309 -0
  80. package/package/sequencer/worklet_sequencer/process_event.js +167 -0
  81. package/package/sequencer/worklet_sequencer/process_tick.js +85 -0
  82. package/package/sequencer/worklet_sequencer/sequencer_message.js +39 -0
  83. package/package/sequencer/worklet_sequencer/song_control.js +193 -0
  84. package/package/sequencer/worklet_sequencer/worklet_sequencer.js +218 -0
  85. package/package/soundfont/README.md +8 -0
  86. package/package/soundfont/read/generators.js +212 -0
  87. package/package/soundfont/read/instruments.js +125 -0
  88. package/package/soundfont/read/modulators.js +249 -0
  89. package/package/soundfont/read/presets.js +300 -0
  90. package/package/soundfont/read/riff_chunk.js +81 -0
  91. package/package/soundfont/read/samples.js +398 -0
  92. package/package/soundfont/read/zones.js +310 -0
  93. package/package/soundfont/soundfont.js +357 -0
  94. package/package/soundfont/write/ibag.js +39 -0
  95. package/package/soundfont/write/igen.js +75 -0
  96. package/package/soundfont/write/imod.js +46 -0
  97. package/package/soundfont/write/inst.js +34 -0
  98. package/package/soundfont/write/pbag.js +39 -0
  99. package/package/soundfont/write/pgen.js +77 -0
  100. package/package/soundfont/write/phdr.js +42 -0
  101. package/package/soundfont/write/pmod.js +46 -0
  102. package/package/soundfont/write/sdta.js +72 -0
  103. package/package/soundfont/write/shdr.js +54 -0
  104. package/package/soundfont/write/soundfont_trimmer.js +169 -0
  105. package/package/soundfont/write/write.js +180 -0
  106. package/package/synthetizer/README.md +6 -0
  107. package/package/synthetizer/audio_effects/effects_config.js +21 -0
  108. package/package/synthetizer/audio_effects/fancy_chorus.js +120 -0
  109. package/package/synthetizer/audio_effects/impulse_response_2.flac +0 -0
  110. package/package/synthetizer/audio_effects/reverb.js +24 -0
  111. package/package/synthetizer/synth_event_handler.js +156 -0
  112. package/package/synthetizer/synthetizer.js +766 -0
  113. package/package/synthetizer/worklet_processor.min.js +13 -0
  114. package/package/synthetizer/worklet_system/README.md +6 -0
  115. package/package/synthetizer/worklet_system/main_processor.js +363 -0
  116. package/package/synthetizer/worklet_system/message_protocol/handle_message.js +197 -0
  117. package/package/synthetizer/worklet_system/message_protocol/message_sending.js +74 -0
  118. package/package/synthetizer/worklet_system/message_protocol/worklet_message.js +121 -0
  119. package/package/synthetizer/worklet_system/minify_processor.sh +4 -0
  120. package/package/synthetizer/worklet_system/worklet_methods/controller_control.js +230 -0
  121. package/package/synthetizer/worklet_system/worklet_methods/data_entry.js +277 -0
  122. package/package/synthetizer/worklet_system/worklet_methods/note_off.js +109 -0
  123. package/package/synthetizer/worklet_system/worklet_methods/note_on.js +91 -0
  124. package/package/synthetizer/worklet_system/worklet_methods/program_control.js +183 -0
  125. package/package/synthetizer/worklet_system/worklet_methods/reset_controllers.js +177 -0
  126. package/package/synthetizer/worklet_system/worklet_methods/snapshot.js +129 -0
  127. package/package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +272 -0
  128. package/package/synthetizer/worklet_system/worklet_methods/tuning_control.js +195 -0
  129. package/package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +29 -0
  130. package/package/synthetizer/worklet_system/worklet_methods/voice_control.js +233 -0
  131. package/package/synthetizer/worklet_system/worklet_processor.js +9 -0
  132. package/package/synthetizer/worklet_system/worklet_utilities/lfo.js +23 -0
  133. package/package/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +130 -0
  134. package/package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +73 -0
  135. package/package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +86 -0
  136. package/package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +81 -0
  137. package/package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +66 -0
  138. package/package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +265 -0
  139. package/package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +83 -0
  140. package/package/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +234 -0
  141. package/package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +116 -0
  142. package/package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +272 -0
  143. package/package/synthetizer/worklet_url.js +5 -0
  144. package/package/utils/README.md +4 -0
  145. package/package/utils/buffer_to_wav.js +101 -0
  146. package/package/utils/byte_functions/big_endian.js +28 -0
  147. package/package/utils/byte_functions/little_endian.js +74 -0
  148. package/package/utils/byte_functions/string.js +97 -0
  149. package/package/utils/byte_functions/variable_length_quantity.js +37 -0
  150. package/package/utils/encode_vorbis.js +30 -0
  151. package/package/utils/indexed_array.js +41 -0
  152. package/package/utils/loggin.js +79 -0
  153. package/package/utils/other.js +54 -0
  154. package/package.json +43 -0
@@ -0,0 +1,180 @@
1
+ import { combineArrays, IndexedByteArray } from '../../utils/indexed_array.js'
2
+ import { RiffChunk, writeRIFFChunk } from '../read/riff_chunk.js'
3
+ import { writeStringAsBytes } from '../../utils/byte_functions/string.js'
4
+ import { consoleColors } from '../../utils/other.js'
5
+ import { getIGEN } from './igen.js'
6
+ import { getSDTA } from './sdta.js'
7
+ import { getSHDR } from './shdr.js'
8
+ import { getIMOD } from './imod.js'
9
+ import { getIBAG } from './ibag.js'
10
+ import { getINST } from './inst.js'
11
+ import { getPGEN } from './pgen.js'
12
+ import { getPMOD } from './pmod.js'
13
+ import { getPBAG } from './pbag.js'
14
+ import { getPHDR } from './phdr.js'
15
+ import { writeWord } from '../../utils/byte_functions/little_endian.js'
16
+ import {
17
+ SpessaSynthGroupCollapsed,
18
+ SpessaSynthGroupEnd,
19
+ SpessaSynthInfo,
20
+ } from '../../utils/loggin.js'
21
+
22
+ /**
23
+ * @typedef {Object} SoundFont2WriteOptions
24
+ * @property {boolean} compress - if the soundfont should be compressed with the ogg vorbis codec
25
+ * @property {number} compressionQuality - the vorbis compression quality, from -0.1 to 1
26
+ * @property {EncodeVorbisFunction|undefined} compressionFunction - the encode vorbis function. Can be undefined if not compressing.
27
+ */
28
+
29
+ /**
30
+ * @type {SoundFont2WriteOptions}
31
+ */
32
+ const DEFAULT_WRITE_OPTIONS = {
33
+ compress: false,
34
+ compressionQuality: 0.5,
35
+ compressionFunction: undefined
36
+ }
37
+
38
+ /**
39
+ * Write the soundfont as an .sf2 file. This method is DESTRUCTIVE
40
+ * @this {SoundFont2}
41
+ * @param {SoundFont2WriteOptions} options
42
+ * @returns {Uint8Array}
43
+ */
44
+ export function write(options = DEFAULT_WRITE_OPTIONS)
45
+ {
46
+ if(options.compress)
47
+ {
48
+ if(typeof options.compressionFunction !== "function")
49
+ {
50
+ throw new TypeError("No compression function supplied but compression enabled.");
51
+ }
52
+ }
53
+ SpessaSynthGroupCollapsed("%cSaving soundfont...",
54
+ consoleColors.info);
55
+ SpessaSynthInfo(`%cCompression: %c${options?.compress || "false"}%c quality: %c${options?.compressionQuality || "none"}`,
56
+ consoleColors.info,
57
+ consoleColors.recognized,
58
+ consoleColors.info,
59
+ consoleColors.recognized)
60
+ SpessaSynthInfo("%cWriting INFO...",
61
+ consoleColors.info);
62
+ /**
63
+ * Write INFO
64
+ * @type {IndexedByteArray[]}
65
+ */
66
+ const infoArrays = [];
67
+ this.soundFontInfo["ISFT"] = "SpessaSynth"; // ( ͡° ͜ʖ ͡°)
68
+ if(options?.compress)
69
+ {
70
+ this.soundFontInfo["ifil"] = "3.0"; // set version to 3
71
+ }
72
+ for (const [type, data] of Object.entries(this.soundFontInfo))
73
+ {
74
+ if(type === "ifil" || type === "iver")
75
+ {
76
+ const major= parseInt(data.split(".")[0]);
77
+ const minor= parseInt(data.split(".")[1]);
78
+ const ckdata = new IndexedByteArray(4);
79
+ writeWord(ckdata, major);
80
+ writeWord(ckdata, minor);
81
+ infoArrays.push(writeRIFFChunk(new RiffChunk(
82
+ type,
83
+ 4,
84
+ ckdata
85
+ )));
86
+ }
87
+ else
88
+ {
89
+ const arr = new IndexedByteArray(data.length);
90
+ writeStringAsBytes(arr, data);
91
+ infoArrays.push(writeRIFFChunk(new RiffChunk(
92
+ type,
93
+ data.length,
94
+ arr
95
+ )));
96
+ }
97
+ }
98
+ const combined = combineArrays([
99
+ new IndexedByteArray([73, 78, 70, 79]), // INFO
100
+ ...infoArrays
101
+ ]);
102
+ const infoChunk = writeRIFFChunk(new RiffChunk("LIST", combined.length, combined));
103
+
104
+ SpessaSynthInfo("%cWriting SDTA...",
105
+ consoleColors.info);
106
+ // write sdata
107
+ const smplStartOffsets = [];
108
+ const smplEndOffsets = [];
109
+ const sdtaChunk = getSDTA.call(this, smplStartOffsets, smplEndOffsets, options?.compress, options?.compressionQuality || 0.5, options.compressionFunction);
110
+
111
+ SpessaSynthInfo("%cWriting PDTA...",
112
+ consoleColors.info);
113
+ // write pdata
114
+ // go in reverse so the indexes are correct
115
+ // instruments
116
+ SpessaSynthInfo("%cWriting SHDR...",
117
+ consoleColors.info);
118
+ const shdrChunk = getSHDR.call(this, smplStartOffsets, smplEndOffsets);
119
+ SpessaSynthInfo("%cWriting IGEN...",
120
+ consoleColors.info);
121
+ const igenChunk = getIGEN.call(this);
122
+ SpessaSynthInfo("%cWriting IMOD...",
123
+ consoleColors.info);
124
+ const imodChunk = getIMOD.call(this);
125
+ SpessaSynthInfo("%cWriting IBAG...",
126
+ consoleColors.info);
127
+ const ibagChunk = getIBAG.call(this);
128
+ SpessaSynthInfo("%cWriting INST...",
129
+ consoleColors.info);
130
+ const instChunk = getINST.call(this);
131
+ // presets
132
+ const pgenChunk = getPGEN.call(this);
133
+ SpessaSynthInfo("%cWriting PMOD...",
134
+ consoleColors.info);
135
+ const pmodChunk = getPMOD.call(this);
136
+ SpessaSynthInfo("%cWriting PBAG...",
137
+ consoleColors.info);
138
+ const pbagChunk = getPBAG.call(this);
139
+ SpessaSynthInfo("%cWriting PHDR...",
140
+ consoleColors.info);
141
+ const phdrChunk = getPHDR.call(this);
142
+ // combine in the sfspec order
143
+ const pdtadata = combineArrays([
144
+ new IndexedByteArray([112, 100, 116, 97]), // "ptda"
145
+ phdrChunk,
146
+ pbagChunk,
147
+ pmodChunk,
148
+ pgenChunk,
149
+ instChunk,
150
+ ibagChunk,
151
+ imodChunk,
152
+ igenChunk,
153
+ shdrChunk
154
+ ]);
155
+ const pdtaChunk = writeRIFFChunk(new RiffChunk(
156
+ "LIST",
157
+ pdtadata.length,
158
+ pdtadata
159
+ ));
160
+ SpessaSynthInfo("%cWriting the output file...",
161
+ consoleColors.info);
162
+ // finally, combine everything
163
+ const riffdata = combineArrays([
164
+ new IndexedByteArray([115, 102, 98, 107]), // "sfbk"
165
+ infoChunk,
166
+ sdtaChunk,
167
+ pdtaChunk
168
+ ]);
169
+
170
+ const main = writeRIFFChunk(new RiffChunk(
171
+ "RIFF",
172
+ riffdata.length,
173
+ riffdata
174
+ ));
175
+ SpessaSynthInfo(`%cSaved succesfully! Final file size: %c${main.length}`,
176
+ consoleColors.info,
177
+ consoleColors.recognized)
178
+ SpessaSynthGroupEnd();
179
+ return main;
180
+ }
@@ -0,0 +1,6 @@
1
+ ## This is the main synthesizer folder.
2
+ The code here is responsible for making the actual sound.
3
+ This is the heart of the SpessaSynth library.
4
+ - `worklet_system` - the current synthesis system with AudioWorklets.
5
+
6
+ `worklet_processor.min.js` - the minified worklet processor code to import.
@@ -0,0 +1,21 @@
1
+ import { DEFAULT_CHORUS_CONFIG } from './fancy_chorus.js'
2
+
3
+ /**
4
+ * @typedef {Object} EffectsConfig
5
+ * @property {boolean} chorusEnabled - indicates if the chorus effect is enabled.
6
+ * @property {ChorusConfig} chorusConfig - the configuration for chorus. Pass undefined to use defaults
7
+ * @property {boolean} reverbEnabled - indicates if the reverb effect is enabled.
8
+ * @property {AudioBuffer} reverbImpulseResponse - the impulse response for the reverb. Pass undefined to use defaults
9
+ */
10
+
11
+
12
+ /**
13
+ * @type {EffectsConfig}
14
+ */
15
+ export const DEFAULT_EFFECTS_CONFIG = {
16
+ chorusEnabled: true,
17
+ chorusConfig: DEFAULT_CHORUS_CONFIG,
18
+
19
+ reverbEnabled: true,
20
+ reverbImpulseResponse: undefined // will load the integrated one
21
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * fancy_chorus.js
3
+ * purpose: creates a simple chorus effect node
4
+ */
5
+
6
+ /**
7
+ * @typedef {{
8
+ * oscillator: OscillatorNode,
9
+ * oscillatorGain: GainNode,
10
+ * delay: DelayNode
11
+ * }} ChorusNode
12
+ */
13
+
14
+ /**
15
+ * @typedef {Object} ChorusConfig
16
+ * @property {number} nodesAmount - the amount of delay nodes (for each channel) and the corresponding oscillators
17
+ * @property {number} defaultDelay - the initial delay, in seconds
18
+ * @property {number} delayVariation - the difference between delays in the delay nodes
19
+ * @property {number} stereoDifference - the difference of delays between two channels (added to the left channel and subtracted from the right)
20
+ * @property {number} oscillatorFrequency - the initial delay oscillator frequency, in Hz.
21
+ * @property {number} oscillatorFrequencyVariation - the difference between frequencies of oscillators, in Hz
22
+ * @property {number} oscillatorGain - how much will oscillator alter the delay in delay nodes, in seconds
23
+ */
24
+
25
+ const NODES_AMOUNT = 4;
26
+ const DEFAULT_DELAY = 0.03;
27
+ const DELAY_VARIATION = 0.01;
28
+ const STEREO_DIFF = 0.02;
29
+
30
+ const OSC_FREQ = 0.3;
31
+ const OSC_FREQ_VARIATION = 0.05;
32
+ const OSC_GAIN = 0.003;
33
+
34
+ export const DEFAULT_CHORUS_CONFIG = {
35
+ nodesAmount: NODES_AMOUNT,
36
+ defaultDelay: DEFAULT_DELAY,
37
+ delayVariation: DELAY_VARIATION,
38
+ stereoDifference: STEREO_DIFF,
39
+ oscillatorFrequency: OSC_FREQ,
40
+ oscillatorFrequencyVariation: OSC_FREQ_VARIATION,
41
+ oscillatorGain: OSC_GAIN
42
+ };
43
+
44
+ export class FancyChorus
45
+ {
46
+ /**
47
+ * Creates a fancy chorus effect
48
+ * @param output {AudioNode}
49
+ * @param config {ChorusConfig}
50
+ */
51
+ constructor(output, config = DEFAULT_CHORUS_CONFIG) {
52
+ const context = output.context;
53
+
54
+ this.input = new ChannelSplitterNode(context, {
55
+ numberOfOutputs: 2
56
+ });
57
+
58
+ const merger = new ChannelMergerNode(context, {
59
+ numberOfInputs: 2
60
+ });
61
+
62
+ /**
63
+ * @type {ChorusNode[]}
64
+ */
65
+ const chorusNodesLeft = [];
66
+ /**
67
+ * @type {ChorusNode[]}
68
+ */
69
+ const chorusNodesRight = [];
70
+ let freq = config.oscillatorFrequency;
71
+ let delay = config.defaultDelay;
72
+ for (let i = 0; i < config.nodesAmount; i++) {
73
+ // left node
74
+ this.createChorusNode(freq, delay - config.stereoDifference, chorusNodesLeft, 0, merger, 0, context, config);
75
+ // right node
76
+ this.createChorusNode(freq, delay + config.stereoDifference, chorusNodesRight, 1, merger, 1, context, config);
77
+ freq += config.oscillatorFrequencyVariation;
78
+ delay += config.delayVariation;
79
+ }
80
+
81
+ merger.connect(output);
82
+ }
83
+
84
+ /**
85
+ * @param freq {number}
86
+ * @param delay {number}
87
+ * @param list {ChorusNode[]}
88
+ * @param input {number}
89
+ * @param output {AudioNode}
90
+ * @param outputNum {number}
91
+ * @param context {BaseAudioContext}
92
+ * @param config {ChorusConfig}
93
+ */
94
+ createChorusNode(freq, delay, list, input, output, outputNum, context, config)
95
+ {
96
+ const oscillator = new OscillatorNode(context, {
97
+ type: 'sine',
98
+ frequency: freq
99
+ });
100
+ const gainNode = new GainNode(context, {
101
+ gain: config.oscillatorGain
102
+ });
103
+ const delayNode = new DelayNode(context, {
104
+ delayTime: delay
105
+ });
106
+
107
+ oscillator.connect(gainNode);
108
+ gainNode.connect(delayNode.delayTime);
109
+ oscillator.start(context.currentTime + delay);
110
+
111
+ this.input.connect(delayNode, input);
112
+ delayNode.connect(output, 0, outputNum);
113
+
114
+ list.push({
115
+ oscillator: oscillator,
116
+ oscillatorGain: gainNode,
117
+ delay: delayNode
118
+ });
119
+ }
120
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Creates a reverb processor
3
+ * @param context {BaseAudioContext}
4
+ * @param reverbBuffer {AudioBuffer}
5
+ * @returns {ConvolverNode}
6
+ */
7
+ export function getReverbProcessor(context, reverbBuffer = undefined)
8
+ {
9
+ const convolver = new ConvolverNode(context);
10
+ if(reverbBuffer)
11
+ {
12
+ convolver.buffer = reverbBuffer;
13
+ }
14
+ else
15
+ {
16
+ // resolve relative url
17
+ const impulseURL = new URL("impulse_response_2.flac", import.meta.url);
18
+ fetch(impulseURL).then(async response => {
19
+ const data = await response.arrayBuffer();
20
+ convolver.buffer = await context.decodeAudioData(data);
21
+ });
22
+ }
23
+ return convolver;
24
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * synth_event_handler.js
3
+ * purpose: manages the synthesizer's event system, calling assinged functions when synthesizer requests dispatching the event
4
+ */
5
+
6
+ /**
7
+ *
8
+ * @typedef {{
9
+ * midiNote: number,
10
+ * channel: number,
11
+ * velocity: number
12
+ * }} NoteOnCallback
13
+ *
14
+ * @typedef {{
15
+ * midiNote: number,
16
+ * channel: number
17
+ * }} NoteOffCallback
18
+ *
19
+ * @typedef {{
20
+ * channel: number,
21
+ * isDrumChannel: boolean
22
+ * }} DrumChangeCallback
23
+ *
24
+ * @typedef {{
25
+ * channel: number,
26
+ * program: number,
27
+ * bank: number,
28
+ * userCalled: boolean
29
+ * }} ProgramChangeCallback
30
+ *
31
+ * @typedef {{
32
+ * channel: number,
33
+ * controllerNumber: number,
34
+ * controllerValue: number
35
+ * }} ControllerChangeCallback
36
+ *
37
+ * @typedef {{
38
+ * channel:number,
39
+ * isMuted: boolean
40
+ * }} MuteChannelCallback
41
+ *
42
+ * @typedef {{
43
+ * presetName: string,
44
+ * bank: number,
45
+ * program: number
46
+ * }[]} PresetListChangeCallback
47
+ *
48
+ *
49
+ * @typedef {{
50
+ * channel: number,
51
+ * MSB: number,
52
+ * LSB: number
53
+ * }} PitchWheelCallback
54
+ *
55
+ * @typedef {{
56
+ * channel: number,
57
+ * pressure: number
58
+ * }} ChannelPressureCallback
59
+ *
60
+ * @typedef {string} SoundfontErrorCallback
61
+ *
62
+ *
63
+ * @typedef {
64
+ * NoteOnCallback |
65
+ * NoteOffCallback |
66
+ * DrumChangeCallback |
67
+ * ProgramChangeCallback |
68
+ * ControllerChangeCallback |
69
+ * MuteChannelCallback |
70
+ * PresetListChangeCallback |
71
+ * PitchWheelCallback |
72
+ * SoundfontErrorCallback |
73
+ * ChannelPressureCallback |
74
+ * undefined
75
+ * } EventCallbackData
76
+ */
77
+
78
+ /**
79
+ * @typedef {
80
+ * "noteon"|
81
+ * "noteoff"|
82
+ * "pitchwheel"|
83
+ * "controllerchange"|
84
+ * "programchange"|
85
+ * "channelpressure"|
86
+ * "polypressure" |
87
+ * "drumchange"|
88
+ * "stopall"|
89
+ * "newchannel"|
90
+ * "mutechannel"|
91
+ * "presetlistchange"|
92
+ * "allcontrollerreset"|
93
+ * "soundfonterror"} EventTypes
94
+ */
95
+ export class EventHandler
96
+ {
97
+ /**
98
+ * A new synthesizer event handler
99
+ */
100
+ constructor() {
101
+ /**
102
+ * The main list of events
103
+ * @type {Object<EventTypes, Object<string, function(EventCallbackData)>>}
104
+ */
105
+ this.events = {
106
+ "noteoff": {},
107
+ "noteon": {},
108
+ "pitchwheel": {},
109
+ "controllerchange": {},
110
+ "programchange": {},
111
+ "channelpressure": {},
112
+ "polypressure": {},
113
+ "drumchange": {},
114
+ "stopall": {},
115
+ "newchannel": {},
116
+ "mutechannel": {},
117
+ "presetlistchange": {},
118
+ "allcontrollerreset": {},
119
+ "soundfonterror": {}
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Adds a new event listener
125
+ * @param name {EventTypes}
126
+ * @param id {string} the unique identifier for the event (to delete it
127
+ * @param callback {function(EventCallbackData)}
128
+ */
129
+ addEvent(name, id, callback)
130
+ {
131
+ this.events[name][id] = callback;
132
+ }
133
+
134
+ /**
135
+ * Removes an event listener
136
+ * @param name {EventTypes}
137
+ * @param id {string}
138
+ */
139
+ removeEvent(name, id)
140
+ {
141
+ delete this.events[name][id];
142
+ }
143
+
144
+ /**
145
+ * Calls the given event
146
+ * @param name {EventTypes}
147
+ * @param eventData {EventCallbackData}
148
+ */
149
+ callEvent(name, eventData)
150
+ {
151
+ if(this.events[name])
152
+ {
153
+ Object.values(this.events[name]).forEach(ev => ev(eventData));
154
+ }
155
+ }
156
+ }