spessasynth_lib 3.25.23 → 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.
- package/README.md +29 -114
- package/index.js +33 -33
- package/package.json +16 -6
- package/external_midi/README.md +0 -4
- package/external_midi/midi_handler.js +0 -130
- package/external_midi/web_midi_link.js +0 -43
- package/externals/fflate/LICENSE +0 -21
- package/externals/fflate/fflate.min.js +0 -1
- package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
- package/externals/stbvorbis_sync/LICENSE +0 -202
- package/externals/stbvorbis_sync/NOTICE +0 -6
- package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
- package/midi/README.md +0 -32
- package/midi/basic_midi.js +0 -565
- package/midi/midi_builder.js +0 -202
- package/midi/midi_data.js +0 -63
- package/midi/midi_loader.js +0 -324
- package/midi/midi_message.js +0 -254
- package/midi/midi_sequence.js +0 -225
- package/midi/midi_tools/get_note_times.js +0 -154
- package/midi/midi_tools/midi_editor.js +0 -611
- package/midi/midi_tools/midi_writer.js +0 -99
- package/midi/midi_tools/rmidi_writer.js +0 -567
- package/midi/midi_tools/used_keys_loaded.js +0 -238
- package/midi/xmf_loader.js +0 -454
- package/sequencer/README.md +0 -32
- package/sequencer/sequencer_engine/events.js +0 -104
- package/sequencer/sequencer_engine/play.js +0 -353
- package/sequencer/sequencer_engine/process_event.js +0 -169
- package/sequencer/sequencer_engine/process_tick.js +0 -106
- package/sequencer/sequencer_engine/sequencer_engine.js +0 -335
- package/sequencer/sequencer_engine/song_control.js +0 -229
- package/sequencer/worklet_wrapper/default_sequencer_options.js +0 -8
- package/sequencer/worklet_wrapper/sequencer.js +0 -807
- package/sequencer/worklet_wrapper/sequencer_message.js +0 -53
- package/soundfont/README.md +0 -13
- package/soundfont/basic_soundfont/basic_instrument.js +0 -77
- package/soundfont/basic_soundfont/basic_preset.js +0 -336
- package/soundfont/basic_soundfont/basic_sample.js +0 -197
- package/soundfont/basic_soundfont/basic_soundfont.js +0 -565
- package/soundfont/basic_soundfont/basic_zone.js +0 -64
- package/soundfont/basic_soundfont/basic_zones.js +0 -43
- package/soundfont/basic_soundfont/generator.js +0 -220
- package/soundfont/basic_soundfont/modulator.js +0 -378
- package/soundfont/basic_soundfont/riff_chunk.js +0 -149
- package/soundfont/basic_soundfont/write_dls/art2.js +0 -173
- package/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
- package/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -400
- package/soundfont/basic_soundfont/write_dls/ins.js +0 -103
- package/soundfont/basic_soundfont/write_dls/lins.js +0 -18
- package/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
- package/soundfont/basic_soundfont/write_dls/rgn2.js +0 -121
- package/soundfont/basic_soundfont/write_dls/wave.js +0 -94
- package/soundfont/basic_soundfont/write_dls/write_dls.js +0 -119
- package/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
- package/soundfont/basic_soundfont/write_dls/wvpl.js +0 -32
- package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -39
- package/soundfont/basic_soundfont/write_sf2/igen.js +0 -80
- package/soundfont/basic_soundfont/write_sf2/imod.js +0 -46
- package/soundfont/basic_soundfont/write_sf2/inst.js +0 -34
- package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -39
- package/soundfont/basic_soundfont/write_sf2/pgen.js +0 -82
- package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -42
- package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -46
- package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -80
- package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -55
- package/soundfont/basic_soundfont/write_sf2/write.js +0 -222
- package/soundfont/dls/articulator_converter.js +0 -396
- package/soundfont/dls/dls_destinations.js +0 -38
- package/soundfont/dls/dls_preset.js +0 -44
- package/soundfont/dls/dls_sample.js +0 -75
- package/soundfont/dls/dls_soundfont.js +0 -186
- package/soundfont/dls/dls_sources.js +0 -62
- package/soundfont/dls/dls_zone.js +0 -95
- package/soundfont/dls/read_articulation.js +0 -299
- package/soundfont/dls/read_instrument.js +0 -121
- package/soundfont/dls/read_instrument_list.js +0 -17
- package/soundfont/dls/read_lart.js +0 -35
- package/soundfont/dls/read_region.js +0 -152
- package/soundfont/dls/read_samples.js +0 -270
- package/soundfont/load_soundfont.js +0 -21
- package/soundfont/read_sf2/generators.js +0 -46
- package/soundfont/read_sf2/instruments.js +0 -66
- package/soundfont/read_sf2/modulators.js +0 -36
- package/soundfont/read_sf2/presets.js +0 -80
- package/soundfont/read_sf2/samples.js +0 -304
- package/soundfont/read_sf2/soundfont.js +0 -305
- package/soundfont/read_sf2/zones.js +0 -263
- package/synthetizer/README.md +0 -10
- package/synthetizer/audio_effects/effects_config.js +0 -25
- package/synthetizer/audio_effects/fancy_chorus.js +0 -162
- package/synthetizer/audio_effects/rb_compressed.min.js +0 -1
- package/synthetizer/audio_effects/reverb.js +0 -35
- package/synthetizer/audio_effects/reverb_as_binary.js +0 -18
- package/synthetizer/audio_engine/README.md +0 -25
- package/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -266
- package/synthetizer/audio_engine/engine_components/controller_tables.js +0 -88
- package/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -149
- package/synthetizer/audio_engine/engine_components/lfo.js +0 -26
- package/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
- package/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -471
- package/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
- package/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
- package/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -228
- package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
- package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
- package/synthetizer/audio_engine/engine_components/voice.js +0 -519
- package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
- package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
- package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
- package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
- package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
- package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
- package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
- package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
- package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
- package/synthetizer/audio_engine/engine_methods/note_on.js +0 -175
- package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
- package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
- package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
- package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
- package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
- package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
- package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
- package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
- package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
- package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
- package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
- package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
- package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
- package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -776
- package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
- package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
- package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
- package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
- package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
- package/synthetizer/audio_engine/main_processor.js +0 -765
- package/synthetizer/audio_engine/message_protocol/README.md +0 -13
- package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
- package/synthetizer/audio_engine/message_protocol/worklet_message.js +0 -107
- package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
- package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
- package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
- package/synthetizer/synth_constants.js +0 -20
- package/synthetizer/worklet_processor.min.js +0 -21
- package/synthetizer/worklet_wrapper/key_modifier_manager.js +0 -104
- package/synthetizer/worklet_wrapper/sfman_message.js +0 -9
- package/synthetizer/worklet_wrapper/synth_event_handler.js +0 -214
- package/synthetizer/worklet_wrapper/synth_soundfont_manager.js +0 -109
- package/synthetizer/worklet_wrapper/synthetizer.js +0 -1027
- package/synthetizer/worklet_wrapper/worklet_processor.js +0 -454
- package/synthetizer/worklet_wrapper/worklet_url.js +0 -16
- package/utils/README.md +0 -5
- package/utils/buffer_to_wav.js +0 -186
- package/utils/byte_functions/big_endian.js +0 -32
- package/utils/byte_functions/little_endian.js +0 -77
- package/utils/byte_functions/string.js +0 -107
- package/utils/byte_functions/variable_length_quantity.js +0 -42
- package/utils/fill_with_defaults.js +0 -21
- package/utils/indexed_array.js +0 -52
- package/utils/loggin.js +0 -79
- package/utils/other.js +0 -92
- package/utils/sysex_detector.js +0 -58
- package/utils/xg_hacks.js +0 -193
package/README.md
CHANGED
|
@@ -2,15 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
**A powerful SF2/DLS/MIDI JavaScript library for the browsers.**
|
|
4
4
|
|
|
5
|
+
*This is a WebAudioAPI wrapper for the [spessasynth_core](https://github.com/spessasus/spessasynth_core) library.*
|
|
6
|
+
|
|
7
|
+
> **TIP:**
|
|
8
|
+
> Looking for a bare JS version that works without WebAudioAPI? Try [spessasynth_core](https://github.com/spessasus/spessasynth_core)!
|
|
9
|
+
|
|
5
10
|
```shell
|
|
6
11
|
npm install --save spessasynth_lib
|
|
7
12
|
```
|
|
8
13
|
|
|
9
14
|
### [Project site (consider giving it a star!)](https://github.com/spessasus/SpessaSynth)
|
|
10
15
|
|
|
11
|
-
### [Demo](https://spessasus.github.io/
|
|
16
|
+
### [Demo](https://spessasus.github.io/spessasynth_lib)
|
|
12
17
|
|
|
13
|
-
### [Complete documentation](https://github.com/spessasus/
|
|
18
|
+
### [Complete documentation](https://github.com/spessasus/spessasynth_lib/wiki/)
|
|
14
19
|
|
|
15
20
|
#### Basic example: play a single note
|
|
16
21
|
|
|
@@ -32,126 +37,36 @@ document.getElementById("button").onclick = async () =>
|
|
|
32
37
|
|
|
33
38
|
## Current Features
|
|
34
39
|
|
|
35
|
-
###
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- `.kar` - Soft Karaoke MIDI File
|
|
39
|
-
- `.sf2` - SoundFont2 File
|
|
40
|
-
- `.sf3` - SoundFont2 Compressed File
|
|
41
|
-
- `.sfogg` - SF2Pack With Vorbis Compression
|
|
42
|
-
- `.dls` - Downloadable Sounds Levels 1 & 2 (as well as Mobile DLS)
|
|
43
|
-
- `.rmi` - RIFF MIDI File
|
|
44
|
-
- `.rmi` - RIFF MIDI File With Embedded DLS
|
|
45
|
-
- `.rmi` - [RIFF MIDI File With Embedded SF2](https://github.com/spessasus/sf2-rmidi-specification)
|
|
46
|
-
- `.xmf` - eXtensible Music Format
|
|
47
|
-
- `.mxmf` - Mobile eXtensible Music format
|
|
48
|
-
|
|
49
|
-
*With [an easy way of converting between them!](https://github.com/spessasus/SpessaSynth/wiki/Converting-Between-Formats)*
|
|
50
|
-
|
|
51
|
-
### Easy Integration
|
|
40
|
+
### [All the features of spessasynth_core!](https://github.com/spessasus/spessasynth_core?#current-features)
|
|
41
|
+
|
|
42
|
+
### On top of that...
|
|
52
43
|
- **Modular design:** *Easy integration into other projects (load what you need)*
|
|
53
|
-
- **[Detailed documentation:](https://github.com/spessasus/
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
57
|
-
|
|
58
|
-
### Powerful MIDI Synthesizer
|
|
59
|
-
- Suitable for both **real-time** and **offline** synthesis
|
|
60
|
-
- **Excellent SoundFont support:**
|
|
61
|
-
- **Full Generator Support**
|
|
62
|
-
- **Full Modulator Support:** *First (to my knowledge) JavaScript SoundFont synth with that feature!*
|
|
63
|
-
- **GeneralUserGS Compatible:** *[See more here!](https://github.com/mrbumpy409/GeneralUser-GS/blob/main/documentation/README.md)*
|
|
64
|
-
- **SoundFont3 Support:** Play compressed SoundFonts!
|
|
65
|
-
- **Experimental SF2Pack Support:** Play soundfonts compressed with BASSMIDI! (*Note: only works with vorbis compression*)
|
|
66
|
-
- **Can load very large SoundFonts:** up to 4GB! *Note: Only Firefox handles this well; Chromium has a hard-coded memory limit*
|
|
67
|
-
- **Great DLS Support:**
|
|
68
|
-
- **DLS Level 1 Support**
|
|
69
|
-
- **DLS Level 2 Support**
|
|
70
|
-
- **Mobile DLS Support**
|
|
71
|
-
- **Correct articulator support:** *Converts articulators to both modulators and generators!*
|
|
72
|
-
- **Tested and working with gm.dls!**
|
|
73
|
-
- **Correct volume:** *Properly translated to SoundFont volume!*
|
|
74
|
-
- **A-Law encoding support**
|
|
75
|
-
- **Both unsigned 8-bit and signed 16-bit sample support (24-bit theoretically supported as well!)**
|
|
76
|
-
- **Detects special articulator combinations:** *Such as vibratoLfoToPitch*
|
|
77
|
-
- **Soundfont manager:** Stack multiple soundfonts!
|
|
78
|
-
- **Reverb and chorus support:** [customizable!](https://github.com/spessasus/SpessaSynth/wiki/Synthetizer-Class#effects-configuration-object)
|
|
44
|
+
- **[Detailed documentation:](https://github.com/spessasus/spessasynth_lib/wiki/Home)** *With [examples!](https://github.com/spessasus/spessasynth_lib/wiki/Usage-As-Library#examples)*
|
|
45
|
+
- **Easy to Use:** *Basic setup is just [two lines of code!](https://github.com/spessasus/spessasynth_lib/wiki/Usage-As-Library#minimal-setup)*
|
|
46
|
+
- **No external dependencies:** *Just spessasynth_core!*
|
|
47
|
+
- **Reverb and chorus support:** [customizable!](https://github.com/spessasus/spessasynth_lib/wiki/Synthetizer-Class#effects-configuration-object)
|
|
79
48
|
- **Export audio files** using [OfflineAudioContext](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext)
|
|
80
|
-
- **[Custom modulators for additional controllers](https://github.com/spessasus/SpessaSynth/wiki/Modulator-Class#default-modulators):** *Why not?*
|
|
81
49
|
- **Written using AudioWorklets:**
|
|
82
50
|
- Runs in a **separate thread** for maximum performance
|
|
83
51
|
- Doesn't stop playing even when the main thread is frozen
|
|
84
52
|
- Supported by all modern browsers
|
|
85
|
-
- **Unlimited channel count:** Your CPU is the limit!
|
|
86
|
-
- **Excellent MIDI Standards Support:**
|
|
87
|
-
- **MIDI Controller Support:** Default supported controllers [here](https://github.com/spessasus/SpessaSynth/wiki/MIDI-Implementation#supported-controllers)
|
|
88
|
-
- **Portamento Support:** Glide the notes!
|
|
89
|
-
- **Sound Controllers:** Real-time filter and envelope control!
|
|
90
|
-
- **MIDI Tuning Standard Support:** [more info here](https://github.com/spessasus/SpessaSynth/wiki/MIDI-Implementation#midi-tuning-standard)
|
|
91
|
-
- [Full **RPN** and limited **NRPN** support](https://github.com/spessasus/SpessaSynth/wiki/MIDI-Implementation#supported-registered-parameters)
|
|
92
|
-
- Supports some [**Roland GS** and **Yamaha XG** system exclusives](https://github.com/spessasus/SpessaSynth/wiki/MIDI-Implementation#supported-system-exclusives)
|
|
93
53
|
- **High-performance mode:** Play Rush E! *note: may kill your browser ;)*
|
|
94
54
|
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
- **Key range detection:** Detect the key range of the MIDI
|
|
111
|
-
- **Easy MIDI editing:** Use [helper functions](https://github.com/spessasus/SpessaSynth/wiki/Writing-MIDI-Files#modifymidi) to modify the song to your needs!
|
|
112
|
-
- **Loop detection:** Automatically detects loops in MIDIs (e.g., from *Touhou Project*)
|
|
113
|
-
- **First note detection:** Skip unnecessary silence at the start by jumping to the first note!
|
|
114
|
-
- **Lyrics support:** Both regular MIDI and .kar files!
|
|
115
|
-
- **[Write MIDI files from scratch](https://github.com/spessasus/SpessaSynth/wiki/Creating-MIDI-Files)**
|
|
116
|
-
- **Easy saving:** Save with just [one function!](https://github.com/spessasus/SpessaSynth/wiki/Writing-MIDI-Files#writemidi)
|
|
117
|
-
|
|
118
|
-
#### Read and write [RMID files with embedded SF2 soundfonts](https://github.com/spessasus/sf2-rmidi-specification#readme)
|
|
119
|
-
- **[Level 4](https://github.com/spessasus/sf2-rmidi-specification#level-4) compliance:** Reads and writes *everything!*
|
|
120
|
-
- **Compression and trimming support:** Reduce a MIDI file with a 1GB soundfont to **as small as 5MB**!
|
|
121
|
-
- **DLS Version support:** The original legacy format with bank offset detection!
|
|
122
|
-
- **Automatic bank shifting and validation:** Every soundfont *just works!*
|
|
123
|
-
- **Metadata support:** Add title, artist, album name and cover and more! And of course read them too! *(In any encoding!)*
|
|
124
|
-
- **Compatible with [Falcosoft Midi Player 6!](https://falcosoft.hu/softwares.html#midiplayer)**
|
|
125
|
-
- **Easy saving:** [As simple as saving a MIDI file!](https://github.com/spessasus/SpessaSynth/wiki/Writing-MIDI-Files#writermidi)
|
|
126
|
-
|
|
127
|
-
#### Read and write SoundFont2 files
|
|
128
|
-
- **Easy info access:** Just an [object of strings!](https://github.com/spessasus/SpessaSynth/wiki/SoundFont2-Class#soundfontinfo)
|
|
129
|
-
- **Smart trimming:** Trim the SoundFont to only include samples used in the MIDI *(down to key and velocity!)*
|
|
130
|
-
- **sf3 conversion:** Compress SoundFont2 files to SoundFont3 with variable quality!
|
|
131
|
-
- **Easy saving:** Also just [one function!](https://github.com/spessasus/SpessaSynth/wiki/SoundFont2-Class#write)
|
|
132
|
-
|
|
133
|
-
#### Read and write SoundFont3 files
|
|
134
|
-
- Same features as SoundFont2 but with now with **Ogg Vorbis compression!**
|
|
135
|
-
- **Variable compression quality:** You choose between file size and quality!
|
|
136
|
-
- **Compression preserving:** Avoid decompressing and recompressing uncompressed samples for minimal quality loss!
|
|
137
|
-
|
|
138
|
-
#### Read and write DLS Level One or Two files
|
|
139
|
-
- Read DLS (DownLoadable Sounds) files as SF2 files!
|
|
140
|
-
- **Works like a normal soundfont:** *Saving it as sf2 is still [just one function!](https://github.com/spessasus/SpessaSynth/wiki/SoundFont2-Class#write)*
|
|
141
|
-
- Converts articulators to both **modulators** and **generators**!
|
|
142
|
-
- Works with both unsigned 8-bit samples and signed 16-bit samples!
|
|
143
|
-
- A-Law encoding support
|
|
144
|
-
- **Covers special generator cases:** *such as modLfoToPitch*!
|
|
145
|
-
- **Correct volume:** *looking at you, Viena and gm.sf2!*
|
|
146
|
-
- Support built right into the synthesizer!
|
|
147
|
-
- **Convert SF2 to DLS:** [with limitations](https://github.com/spessasus/SpessaSynth/wiki/DLS-Conversion-Problem)
|
|
148
|
-
|
|
149
|
-
### Export MIDI as WAV
|
|
150
|
-
- Save the MIDI file as WAV audio!
|
|
151
|
-
- **Metadata support:** *Embed metadata such as title, artist, album and more!*
|
|
152
|
-
- **Cue points:** *Write MIDI loop points as cue points!*
|
|
153
|
-
- **Loop multiple times:** *Render two (or more) loops into the file for seamless transitions!*
|
|
154
|
-
- *That's right, saving as WAV is also [just one function!](https://github.com/spessasus/SpessaSynth/wiki/Writing-Wave-Files#audiobuffertowav)*
|
|
55
|
+
#### TODO
|
|
56
|
+
- Enhance the built-in chorus and reverb effects (suggestions welcome!)
|
|
57
|
+
|
|
58
|
+
### Special Thanks
|
|
59
|
+
- [FluidSynth](https://github.com/FluidSynth/fluidsynth) - for the source code that helped implement functionality and fixes
|
|
60
|
+
- [Polyphone](https://www.polyphone-soundfonts.com/) - for the soundfont testing and editing tool
|
|
61
|
+
- [Meltysynth](https://github.com/sinshu/meltysynth) - for the initial low-pass filter implementation
|
|
62
|
+
- [RecordingBlogs](https://www.recordingblogs.com/) - for detailed explanations on MIDI messages
|
|
63
|
+
- [stbvorbis.js](https://github.com/hajimehoshi/stbvorbis.js) - for the Vorbis decoder
|
|
64
|
+
- [fflate](https://github.com/101arrowz/fflate) - for the MIT DEFLATE implementation
|
|
65
|
+
- [foo_midi](https://github.com/stuerp/foo_midi) - for useful resources on XMF file format
|
|
66
|
+
- [Falcosoft](https://falcosoft.hu) - for help with the RMIDI format
|
|
67
|
+
- [Christian Collins](https://schristiancollins.com) - for various bug reports regarding the synthesizer
|
|
68
|
+
- **And You!** - for checking out this project. I hope you like it :)
|
|
69
|
+
|
|
155
70
|
|
|
156
71
|
# License
|
|
157
72
|
Copyright © 2025 Spessasus
|
package/index.js
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
// Import modules
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
2
|
+
import {
|
|
3
|
+
ALL_CHANNELS_OR_DIFFERENT_ACTION,
|
|
4
|
+
BasicInstrument,
|
|
5
|
+
BasicInstrumentZone,
|
|
6
|
+
BasicMIDI,
|
|
7
|
+
BasicPreset,
|
|
8
|
+
BasicPresetZone,
|
|
9
|
+
BasicSample,
|
|
10
|
+
BasicSoundBank,
|
|
11
|
+
ChannelSnapshot,
|
|
12
|
+
DEFAULT_PERCUSSION,
|
|
13
|
+
Generator,
|
|
14
|
+
IndexedByteArray,
|
|
15
|
+
loadSoundFont,
|
|
16
|
+
messageTypes,
|
|
17
|
+
MIDI,
|
|
18
|
+
MIDIBuilder,
|
|
19
|
+
midiControllers,
|
|
20
|
+
MIDIMessage,
|
|
21
|
+
Modulator,
|
|
22
|
+
modulatorSources,
|
|
23
|
+
NON_CC_INDEX_OFFSET,
|
|
24
|
+
RMIDINFOChunks,
|
|
25
|
+
SpessaSynthLogging,
|
|
26
|
+
SynthesizerSnapshot,
|
|
27
|
+
VOICE_CAP
|
|
28
|
+
} from "spessasynth_core";
|
|
29
|
+
import { Synthetizer } from "./synthetizer/synthetizer.js";
|
|
30
|
+
import { Sequencer } from "./sequencer/sequencer.js";
|
|
31
|
+
import { audioBufferToWav } from "./utils/buffer_to_wav.js";
|
|
32
|
+
import { MIDIDeviceHandler } from "./external_midi/midi_handler.js";
|
|
33
|
+
import { WebMIDILinkHandler } from "./external_midi/web_midi_link.js";
|
|
26
34
|
import { DEFAULT_SYNTH_CONFIG } from "./synthetizer/audio_effects/effects_config.js";
|
|
27
|
-
import { WORKLET_URL_ABSOLUTE } from "./synthetizer/
|
|
28
|
-
import { SynthesizerSnapshot } from "./synthetizer/audio_engine/snapshot/synthesizer_snapshot.js";
|
|
29
|
-
import { ChannelSnapshot } from "./synthetizer/audio_engine/snapshot/channel_snapshot.js";
|
|
30
|
-
import { SpessaSynthProcessor } from "./synthetizer/audio_engine/main_processor.js";
|
|
31
|
-
import { NON_CC_INDEX_OFFSET } from "./synthetizer/audio_engine/engine_components/controller_tables.js";
|
|
32
|
-
import { ALL_CHANNELS_OR_DIFFERENT_ACTION } from "./synthetizer/audio_engine/message_protocol/worklet_message.js";
|
|
35
|
+
import { WORKLET_URL_ABSOLUTE } from "./synthetizer/worklet_url.js";
|
|
33
36
|
|
|
34
37
|
// Export modules
|
|
35
38
|
export {
|
|
@@ -44,9 +47,6 @@ export {
|
|
|
44
47
|
ALL_CHANNELS_OR_DIFFERENT_ACTION,
|
|
45
48
|
NON_CC_INDEX_OFFSET,
|
|
46
49
|
|
|
47
|
-
// Audio Engine
|
|
48
|
-
SpessaSynthProcessor,
|
|
49
|
-
|
|
50
50
|
// SoundFont
|
|
51
51
|
BasicSoundBank,
|
|
52
52
|
BasicSample,
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spessasynth_lib",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "MIDI and SoundFont2/DLS library with no compromises",
|
|
3
|
+
"version": "3.26.0",
|
|
4
|
+
"description": "MIDI and SoundFont2/DLS library for the browsers with no compromises",
|
|
5
5
|
"browser": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
|
+
"build": "./minify_processor.sh"
|
|
9
10
|
},
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/spessasus/
|
|
13
|
+
"url": "git+https://github.com/spessasus/spessasynth_lib.git"
|
|
13
14
|
},
|
|
14
15
|
"main": "index.js",
|
|
15
16
|
"keywords": [
|
|
@@ -36,8 +37,17 @@
|
|
|
36
37
|
},
|
|
37
38
|
"license": "Apache-2.0",
|
|
38
39
|
"bugs": {
|
|
39
|
-
"url": "https://github.com/spessasus/
|
|
40
|
+
"url": "https://github.com/spessasus/spessasynth_lib/issues",
|
|
40
41
|
"email": "spesekspesek@gmail.com"
|
|
41
42
|
},
|
|
42
|
-
"homepage": "https://github.com/spessasus/
|
|
43
|
+
"homepage": "https://github.com/spessasus/spessasynth_lib#readme",
|
|
44
|
+
"files": [
|
|
45
|
+
"index.js",
|
|
46
|
+
"LICENSE",
|
|
47
|
+
"README.md",
|
|
48
|
+
"src"
|
|
49
|
+
],
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"spessasynth_core": "latest"
|
|
52
|
+
}
|
|
43
53
|
}
|
package/external_midi/README.md
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { Synthetizer } from "../synthetizer/worklet_wrapper/synthetizer.js";
|
|
2
|
-
import { consoleColors } from "../utils/other.js";
|
|
3
|
-
import { SpessaSynthInfo, SpessaSynthWarn } from "../utils/loggin.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* midi_handler.js
|
|
7
|
-
* purpose: handles the connection between MIDI devices and synthesizer/sequencer via Web MIDI API
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const NO_INPUT = null;
|
|
11
|
-
|
|
12
|
-
export class MIDIDeviceHandler
|
|
13
|
-
{
|
|
14
|
-
constructor()
|
|
15
|
-
{
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @returns {Promise<boolean>} if succeded
|
|
20
|
-
*/
|
|
21
|
-
async createMIDIDeviceHandler()
|
|
22
|
-
{
|
|
23
|
-
/**
|
|
24
|
-
* @type {MIDIInput}
|
|
25
|
-
*/
|
|
26
|
-
this.selectedInput = NO_INPUT;
|
|
27
|
-
/**
|
|
28
|
-
* @type {MIDIOutput}
|
|
29
|
-
*/
|
|
30
|
-
this.selectedOutput = NO_INPUT;
|
|
31
|
-
if (navigator.requestMIDIAccess)
|
|
32
|
-
{
|
|
33
|
-
// prepare the midi access
|
|
34
|
-
try
|
|
35
|
-
{
|
|
36
|
-
const response = await navigator.requestMIDIAccess({ sysex: true, software: true });
|
|
37
|
-
this.inputs = response.inputs;
|
|
38
|
-
this.outputs = response.outputs;
|
|
39
|
-
SpessaSynthInfo("%cMIDI handler created!", consoleColors.recognized);
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
catch (e)
|
|
43
|
-
{
|
|
44
|
-
SpessaSynthWarn(`Could not get MIDI Devices:`, e);
|
|
45
|
-
this.inputs = [];
|
|
46
|
-
this.outputs = [];
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
else
|
|
51
|
-
{
|
|
52
|
-
SpessaSynthWarn("Web MIDI Api not supported!", consoleColors.unrecognized);
|
|
53
|
-
this.inputs = [];
|
|
54
|
-
this.outputs = [];
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Connects the sequencer to a given MIDI output port
|
|
61
|
-
* @param output {MIDIOutput}
|
|
62
|
-
* @param seq {Sequencer}
|
|
63
|
-
*/
|
|
64
|
-
connectMIDIOutputToSeq(output, seq)
|
|
65
|
-
{
|
|
66
|
-
this.selectedOutput = output;
|
|
67
|
-
seq.connectMidiOutput(output);
|
|
68
|
-
SpessaSynthInfo(
|
|
69
|
-
`%cPlaying MIDI to %c${output.name}`,
|
|
70
|
-
consoleColors.info,
|
|
71
|
-
consoleColors.recognized
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Disconnects a midi output port from the sequencer
|
|
77
|
-
* @param seq {Sequencer}
|
|
78
|
-
*/
|
|
79
|
-
disconnectSeqFromMIDI(seq)
|
|
80
|
-
{
|
|
81
|
-
this.selectedOutput = NO_INPUT;
|
|
82
|
-
seq.connectMidiOutput(undefined);
|
|
83
|
-
SpessaSynthInfo(
|
|
84
|
-
"%cDisconnected from MIDI out.",
|
|
85
|
-
consoleColors.info
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Connects a MIDI input to the synthesizer
|
|
91
|
-
* @param input {MIDIInput}
|
|
92
|
-
* @param synth {Synthetizer}
|
|
93
|
-
*/
|
|
94
|
-
connectDeviceToSynth(input, synth)
|
|
95
|
-
{
|
|
96
|
-
this.selectedInput = input;
|
|
97
|
-
input.onmidimessage = event =>
|
|
98
|
-
{
|
|
99
|
-
synth.sendMessage(event.data);
|
|
100
|
-
};
|
|
101
|
-
SpessaSynthInfo(
|
|
102
|
-
`%cListening for messages on %c${input.name}`,
|
|
103
|
-
consoleColors.info,
|
|
104
|
-
consoleColors.recognized
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @param input {MIDIInput}
|
|
110
|
-
*/
|
|
111
|
-
disconnectDeviceFromSynth(input)
|
|
112
|
-
{
|
|
113
|
-
this.selectedInput = NO_INPUT;
|
|
114
|
-
input.onmidimessage = undefined;
|
|
115
|
-
SpessaSynthInfo(
|
|
116
|
-
`%cDisconnected from %c${input.name}`,
|
|
117
|
-
consoleColors.info,
|
|
118
|
-
consoleColors.recognized
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
disconnectAllDevicesFromSynth()
|
|
123
|
-
{
|
|
124
|
-
this.selectedInput = NO_INPUT;
|
|
125
|
-
for (const i of this.inputs)
|
|
126
|
-
{
|
|
127
|
-
i[1].onmidimessage = undefined;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Synthetizer } from "../synthetizer/worklet_wrapper/synthetizer.js";
|
|
2
|
-
import { consoleColors } from "../utils/other.js";
|
|
3
|
-
import { SpessaSynthInfo } from "../utils/loggin.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* web_midi_link.js
|
|
7
|
-
* purpose: handles the web midi link connection to the synthesizer
|
|
8
|
-
* https://www.g200kg.com/en/docs/webmidilink/
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export class WebMIDILinkHandler
|
|
12
|
-
{
|
|
13
|
-
/**
|
|
14
|
-
* @param synth {Synthetizer} the synth to play to
|
|
15
|
-
*/
|
|
16
|
-
constructor(synth)
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
window.addEventListener("message", msg =>
|
|
20
|
-
{
|
|
21
|
-
if (typeof msg.data !== "string")
|
|
22
|
-
{
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* @type {string[]}
|
|
27
|
-
*/
|
|
28
|
-
const data = msg.data.split(",");
|
|
29
|
-
if (data[0] !== "midi")
|
|
30
|
-
{
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
data.shift(); // remove MIDI
|
|
35
|
-
|
|
36
|
-
const midiData = data.map(byte => parseInt(byte, 16));
|
|
37
|
-
|
|
38
|
-
synth.sendMessage(midiData);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
SpessaSynthInfo("%cWeb MIDI Link handler created!", consoleColors.recognized);
|
|
42
|
-
}
|
|
43
|
-
}
|
package/externals/fflate/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 Arjun Barrett
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let tr;(()=>{var l=Uint8Array,T=Uint16Array,ur=Int32Array,W=new l([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),X=new l([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),wr=new l([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Y=function(r,a){for(var e=new T(31),f=0;f<31;++f)e[f]=a+=1<<r[f-1];for(var v=new ur(e[30]),f=1;f<30;++f)for(var g=e[f];g<e[f+1];++g)v[g]=g-e[f]<<5|f;return{b:e,r:v}},Z=Y(W,2),$=Z.b,cr=Z.r;$[28]=258,cr[258]=28;var j=Y(X,0),hr=j.b,Fr=j.r,_=new T(32768);for(i=0;i<32768;++i)c=(i&43690)>>1|(i&21845)<<1,c=(c&52428)>>2|(c&13107)<<2,c=(c&61680)>>4|(c&3855)<<4,_[i]=((c&65280)>>8|(c&255)<<8)>>1;var c,i,A=function(r,a,e){for(var f=r.length,v=0,g=new T(a);v<f;++v)r[v]&&++g[r[v]-1];var k=new T(a);for(v=1;v<a;++v)k[v]=k[v-1]+g[v-1]<<1;var b;if(e){b=new T(1<<a);var m=15-a;for(v=0;v<f;++v)if(r[v])for(var U=v<<4|r[v],x=a-r[v],n=k[r[v]-1]++<<x,o=n|(1<<x)-1;n<=o;++n)b[_[n]>>m]=U}else for(b=new T(f),v=0;v<f;++v)r[v]&&(b[v]=_[k[r[v]-1]++]>>15-r[v]);return b},M=new l(288);for(i=0;i<144;++i)M[i]=8;var i;for(i=144;i<256;++i)M[i]=9;var i;for(i=256;i<280;++i)M[i]=7;var i;for(i=280;i<288;++i)M[i]=8;var i,L=new l(32);for(i=0;i<32;++i)L[i]=5;var i,gr=A(M,9,1),br=A(L,5,1),q=function(r){for(var a=r[0],e=1;e<r.length;++e)r[e]>a&&(a=r[e]);return a},u=function(r,a,e){var f=a/8|0;return(r[f]|r[f+1]<<8)>>(a&7)&e},C=function(r,a){var e=a/8|0;return(r[e]|r[e+1]<<8|r[e+2]<<16)>>(a&7)},kr=function(r){return(r+7)/8|0},xr=function(r,a,e){return(a==null||a<0)&&(a=0),(e==null||e>r.length)&&(e=r.length),new l(r.subarray(a,e))},yr=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],h=function(r,a,e){var f=new Error(a||yr[r]);if(f.code=r,Error.captureStackTrace&&Error.captureStackTrace(f,h),!e)throw f;return f},Sr=function(r,a,e,f){var v=r.length,g=f?f.length:0;if(!v||a.f&&!a.l)return e||new l(0);var k=!e,b=k||a.i!=2,m=a.i;k&&(e=new l(v*3));var U=function(fr){var or=e.length;if(fr>or){var lr=new l(Math.max(or*2,fr));lr.set(e),e=lr}},x=a.f||0,n=a.p||0,o=a.b||0,S=a.l,I=a.d,z=a.m,D=a.n,G=v*8;do{if(!S){x=u(r,n,1);var H=u(r,n+1,3);if(n+=3,H)if(H==1)S=gr,I=br,z=9,D=5;else if(H==2){var N=u(r,n,31)+257,s=u(r,n+10,15)+4,d=N+u(r,n+5,31)+1;n+=14;for(var F=new l(d),P=new l(19),t=0;t<s;++t)P[wr[t]]=u(r,n+t*3,7);n+=s*3;for(var rr=q(P),Ar=(1<<rr)-1,Mr=A(P,rr,1),t=0;t<d;){var ar=Mr[u(r,n,Ar)];n+=ar&15;var w=ar>>4;if(w<16)F[t++]=w;else{var E=0,O=0;for(w==16?(O=3+u(r,n,3),n+=2,E=F[t-1]):w==17?(O=3+u(r,n,7),n+=3):w==18&&(O=11+u(r,n,127),n+=7);O--;)F[t++]=E}}var er=F.subarray(0,N),y=F.subarray(N);z=q(er),D=q(y),S=A(er,z,1),I=A(y,D,1)}else h(1);else{var w=kr(n)+4,J=r[w-4]|r[w-3]<<8,K=w+J;if(K>v){m&&h(0);break}b&&U(o+J),e.set(r.subarray(w,K),o),a.b=o+=J,a.p=n=K*8,a.f=x;continue}if(n>G){m&&h(0);break}}b&&U(o+131072);for(var Ur=(1<<z)-1,zr=(1<<D)-1,Q=n;;Q=n){var E=S[C(r,n)&Ur],p=E>>4;if(n+=E&15,n>G){m&&h(0);break}if(E||h(2),p<256)e[o++]=p;else if(p==256){Q=n,S=null;break}else{var nr=p-254;if(p>264){var t=p-257,B=W[t];nr=u(r,n,(1<<B)-1)+$[t],n+=B}var R=I[C(r,n)&zr],V=R>>4;R||h(3),n+=R&15;var y=hr[V];if(V>3){var B=X[V];y+=C(r,n)&(1<<B)-1,n+=B}if(n>G){m&&h(0);break}b&&U(o+131072);var vr=o+nr;if(o<y){var ir=g-y,Dr=Math.min(y,vr);for(ir+o<0&&h(3);o<Dr;++o)e[o]=f[ir+o]}for(;o<vr;++o)e[o]=e[o-y]}}a.l=S,a.p=Q,a.b=o,a.f=x,S&&(x=1,a.m=z,a.d=I,a.n=D)}while(!x);return o!=e.length&&k?xr(e,0,o):e.subarray(0,o)},Tr=new l(0);function mr(r,a){return Sr(r,{i:2},a&&a.out,a&&a.dictionary)}var Er=typeof TextDecoder<"u"&&new TextDecoder,pr=0;try{Er.decode(Tr,{stream:!0}),pr=1}catch{}tr=mr})();export{tr as inflateSync};
|