spessasynth_core 3.27.7 → 4.0.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 +188 -116
- package/dist/index.d.ts +4057 -0
- package/dist/index.js +17188 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -6
- package/index.js +0 -132
- package/src/externals/README.md +0 -6
- package/src/externals/fflate/LICENSE +0 -21
- package/src/externals/fflate/fflate.min.js +0 -1
- package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
- package/src/externals/stbvorbis_sync/LICENSE +0 -202
- package/src/externals/stbvorbis_sync/NOTICE +0 -6
- package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
- package/src/midi/README.md +0 -32
- package/src/midi/basic_midi.js +0 -587
- package/src/midi/midi_builder.js +0 -203
- package/src/midi/midi_loader.js +0 -321
- package/src/midi/midi_message.js +0 -254
- package/src/midi/midi_sequence.js +0 -230
- package/src/midi/midi_tools/get_note_times.js +0 -154
- package/src/midi/midi_tools/midi_editor.js +0 -611
- package/src/midi/midi_tools/midi_writer.js +0 -105
- package/src/midi/midi_tools/rmidi_writer.js +0 -566
- package/src/midi/midi_tools/used_keys_loaded.js +0 -256
- package/src/midi/xmf_loader.js +0 -454
- package/src/sequencer/README.md +0 -9
- package/src/sequencer/events.js +0 -81
- package/src/sequencer/play.js +0 -362
- package/src/sequencer/process_event.js +0 -165
- package/src/sequencer/process_tick.js +0 -104
- package/src/sequencer/sequencer_engine.js +0 -372
- package/src/sequencer/song_control.js +0 -196
- package/src/soundfont/README.md +0 -11
- package/src/soundfont/basic_soundfont/basic_global_zone.js +0 -6
- package/src/soundfont/basic_soundfont/basic_instrument.js +0 -115
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +0 -45
- package/src/soundfont/basic_soundfont/basic_preset.js +0 -313
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +0 -39
- package/src/soundfont/basic_soundfont/basic_sample.js +0 -477
- package/src/soundfont/basic_soundfont/basic_soundbank.js +0 -740
- package/src/soundfont/basic_soundfont/basic_zone.js +0 -145
- package/src/soundfont/basic_soundfont/generator.js +0 -76
- package/src/soundfont/basic_soundfont/generator_types.js +0 -151
- package/src/soundfont/basic_soundfont/modulator.js +0 -581
- package/src/soundfont/basic_soundfont/riff_chunk.js +0 -195
- package/src/soundfont/basic_soundfont/write_dls/art2.js +0 -174
- package/src/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -374
- package/src/soundfont/basic_soundfont/write_dls/ins.js +0 -85
- package/src/soundfont/basic_soundfont/write_dls/lins.js +0 -15
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +0 -120
- package/src/soundfont/basic_soundfont/write_dls/wave.js +0 -71
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +0 -124
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +0 -35
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +0 -60
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +0 -91
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +0 -42
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +0 -57
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +0 -92
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +0 -61
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +0 -131
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +0 -77
- package/src/soundfont/basic_soundfont/write_sf2/write.js +0 -287
- package/src/soundfont/dls/articulator_converter.js +0 -402
- package/src/soundfont/dls/dls_destinations.js +0 -38
- package/src/soundfont/dls/dls_instrument.js +0 -20
- package/src/soundfont/dls/dls_preset.js +0 -43
- package/src/soundfont/dls/dls_sample.js +0 -238
- package/src/soundfont/dls/dls_soundfont.js +0 -183
- package/src/soundfont/dls/dls_sources.js +0 -63
- package/src/soundfont/dls/dls_zone.js +0 -89
- package/src/soundfont/dls/read_articulation.js +0 -300
- package/src/soundfont/dls/read_instrument.js +0 -118
- package/src/soundfont/dls/read_instrument_list.js +0 -17
- package/src/soundfont/dls/read_lart.js +0 -35
- package/src/soundfont/dls/read_region.js +0 -157
- package/src/soundfont/dls/read_samples.js +0 -154
- package/src/soundfont/load_soundfont.js +0 -21
- package/src/soundfont/read_sf2/generators.js +0 -43
- package/src/soundfont/read_sf2/instrument_zones.js +0 -75
- package/src/soundfont/read_sf2/instruments.js +0 -71
- package/src/soundfont/read_sf2/modulators.js +0 -25
- package/src/soundfont/read_sf2/preset_zones.js +0 -79
- package/src/soundfont/read_sf2/presets.js +0 -80
- package/src/soundfont/read_sf2/samples.js +0 -317
- package/src/soundfont/read_sf2/soundfont.js +0 -452
- package/src/soundfont/read_sf2/zones.js +0 -28
- package/src/synthetizer/README.md +0 -7
- package/src/synthetizer/audio_engine/README.md +0 -9
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -289
- package/src/synthetizer/audio_engine/engine_components/controller_tables.js +0 -90
- package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +0 -95
- package/src/synthetizer/audio_engine/engine_components/enums.js +0 -18
- package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -151
- package/src/synthetizer/audio_engine/engine_components/lfo.js +0 -26
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -551
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
- package/src/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
- package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -265
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -124
- package/src/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
- package/src/synthetizer/audio_engine/engine_components/voice.js +0 -525
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -402
- package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -274
- package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -159
- package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
- package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -254
- package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -20
- package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +0 -198
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -281
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -109
- package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
- package/src/synthetizer/audio_engine/engine_methods/program_change.js +0 -35
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/embedded_sound_bank.js +0 -42
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/update_preset_list.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -56
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -1058
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -31
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -29
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
- package/src/synthetizer/audio_engine/main_processor.js +0 -813
- package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -16
- package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
- package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -116
- package/src/synthetizer/audio_engine/synth_processor_options.js +0 -18
- package/src/synthetizer/synth_constants.js +0 -26
- package/src/utils/README.md +0 -8
- package/src/utils/buffer_to_wav.js +0 -197
- package/src/utils/byte_functions/big_endian.js +0 -32
- package/src/utils/byte_functions/little_endian.js +0 -77
- package/src/utils/byte_functions/string.js +0 -92
- package/src/utils/byte_functions/variable_length_quantity.js +0 -42
- package/src/utils/fill_with_defaults.js +0 -21
- package/src/utils/indexed_array.js +0 -34
- package/src/utils/loggin.js +0 -71
- package/src/utils/other.js +0 -92
- package/src/utils/sysex_detector.js +0 -58
- package/src/utils/xg_hacks.js +0 -193
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
|
|
2
|
-
import { SpessaSynthInfo, SpessaSynthWarn } from "../../../../utils/loggin.js";
|
|
3
|
-
import { consoleColors } from "../../../../utils/other.js";
|
|
4
|
-
import { midiControllers } from "../../../../midi/midi_message.js";
|
|
5
|
-
import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @enum {number}
|
|
10
|
-
*/
|
|
11
|
-
export const registeredParameterTypes = {
|
|
12
|
-
pitchBendRange: 0x0000,
|
|
13
|
-
fineTuning: 0x0001,
|
|
14
|
-
coarseTuning: 0x0002,
|
|
15
|
-
modulationDepth: 0x0005,
|
|
16
|
-
resetParameters: 0x3FFF
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @enum {number}
|
|
21
|
-
*/
|
|
22
|
-
export const nonRegisteredMSB = {
|
|
23
|
-
partParameter: 0x01,
|
|
24
|
-
awe32: 0x7F,
|
|
25
|
-
SF2: 120
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* https://cdn.roland.com/assets/media/pdf/SC-88PRO_OM.pdf
|
|
30
|
-
* http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html
|
|
31
|
-
* @enum {number}
|
|
32
|
-
*/
|
|
33
|
-
const nonRegisteredGSLSB = {
|
|
34
|
-
vibratoRate: 0x08,
|
|
35
|
-
vibratoDepth: 0x09,
|
|
36
|
-
vibratoDelay: 0x0A,
|
|
37
|
-
|
|
38
|
-
TVFFilterCutoff: 0x20,
|
|
39
|
-
TVFFilterResonance: 0x21,
|
|
40
|
-
|
|
41
|
-
EGAttackTime: 0x63,
|
|
42
|
-
EGReleaseTime: 0x66
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Executes a data entry for an NRP for a sc88pro NRP (because touhou yes) and RPN tuning
|
|
49
|
-
* @param dataValue {number} dataEntryCoarse MSB
|
|
50
|
-
* @this {MidiAudioChannel}
|
|
51
|
-
* @private
|
|
52
|
-
*/
|
|
53
|
-
export function dataEntryCoarse(dataValue)
|
|
54
|
-
{
|
|
55
|
-
// store in cc table
|
|
56
|
-
this.midiControllers[midiControllers.dataEntryMsb] = dataValue << 7;
|
|
57
|
-
/*
|
|
58
|
-
A note on this vibrato.
|
|
59
|
-
This is a completely custom vibrato, with its own oscillator and parameters.
|
|
60
|
-
It is disabled by default,
|
|
61
|
-
only being enabled when one of the NPRN messages changing it is received
|
|
62
|
-
and stays on until the next system-reset.
|
|
63
|
-
*/
|
|
64
|
-
const addDefaultVibrato = () =>
|
|
65
|
-
{
|
|
66
|
-
if (this.channelVibrato.delay === 0 && this.channelVibrato.rate === 0 && this.channelVibrato.depth === 0)
|
|
67
|
-
{
|
|
68
|
-
this.channelVibrato.depth = 50;
|
|
69
|
-
this.channelVibrato.rate = 8;
|
|
70
|
-
this.channelVibrato.delay = 0.6;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const coolInfo = (what, value, type) =>
|
|
75
|
-
{
|
|
76
|
-
if (type.length > 0)
|
|
77
|
-
{
|
|
78
|
-
type = " " + type;
|
|
79
|
-
}
|
|
80
|
-
SpessaSynthInfo(
|
|
81
|
-
`%c${what} for %c${this.channelNumber}%c is now set to %c${value}%c${type}.`,
|
|
82
|
-
consoleColors.info,
|
|
83
|
-
consoleColors.recognized,
|
|
84
|
-
consoleColors.info,
|
|
85
|
-
consoleColors.value,
|
|
86
|
-
consoleColors.info
|
|
87
|
-
);
|
|
88
|
-
};
|
|
89
|
-
switch (this.dataEntryState)
|
|
90
|
-
{
|
|
91
|
-
default:
|
|
92
|
-
case dataEntryStates.Idle:
|
|
93
|
-
break;
|
|
94
|
-
|
|
95
|
-
// process GS NRPNs
|
|
96
|
-
case dataEntryStates.NRPFine:
|
|
97
|
-
if (this.lockGSNRPNParams)
|
|
98
|
-
{
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* @type {number}
|
|
103
|
-
*/
|
|
104
|
-
const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;
|
|
105
|
-
/**
|
|
106
|
-
* @type {number}
|
|
107
|
-
*/
|
|
108
|
-
const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;
|
|
109
|
-
const dataEntryFine = this.midiControllers[midiControllers.lsbForControl6DataEntry] >> 7;
|
|
110
|
-
switch (NRPNCoarse)
|
|
111
|
-
{
|
|
112
|
-
default:
|
|
113
|
-
if (dataValue === 64)
|
|
114
|
-
{
|
|
115
|
-
// default value
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
SpessaSynthWarn(
|
|
119
|
-
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)
|
|
120
|
-
.toUpperCase()} 0x${NRPNFine.toString(
|
|
121
|
-
16).toUpperCase()})%c data value: %c${dataValue}`,
|
|
122
|
-
consoleColors.warn,
|
|
123
|
-
consoleColors.recognized,
|
|
124
|
-
consoleColors.warn,
|
|
125
|
-
consoleColors.unrecognized,
|
|
126
|
-
consoleColors.warn,
|
|
127
|
-
consoleColors.value
|
|
128
|
-
);
|
|
129
|
-
break;
|
|
130
|
-
|
|
131
|
-
// part parameters: vibrato, cutoff
|
|
132
|
-
case nonRegisteredMSB.partParameter:
|
|
133
|
-
switch (NRPNFine)
|
|
134
|
-
{
|
|
135
|
-
default:
|
|
136
|
-
if (dataValue === 64)
|
|
137
|
-
{
|
|
138
|
-
// default value
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
SpessaSynthWarn(
|
|
142
|
-
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNCoarse.toString(16)} 0x${NRPNFine.toString(
|
|
143
|
-
16)})%c data value: %c${dataValue}`,
|
|
144
|
-
consoleColors.warn,
|
|
145
|
-
consoleColors.recognized,
|
|
146
|
-
consoleColors.warn,
|
|
147
|
-
consoleColors.unrecognized,
|
|
148
|
-
consoleColors.warn,
|
|
149
|
-
consoleColors.value
|
|
150
|
-
);
|
|
151
|
-
break;
|
|
152
|
-
|
|
153
|
-
// vibrato rate
|
|
154
|
-
case nonRegisteredGSLSB.vibratoRate:
|
|
155
|
-
if (dataValue === 64)
|
|
156
|
-
{
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
addDefaultVibrato();
|
|
160
|
-
this.channelVibrato.rate = (dataValue / 64) * 8;
|
|
161
|
-
coolInfo("Vibrato rate", `${dataValue} = ${this.channelVibrato.rate}`, "Hz");
|
|
162
|
-
break;
|
|
163
|
-
|
|
164
|
-
// vibrato depth
|
|
165
|
-
case nonRegisteredGSLSB.vibratoDepth:
|
|
166
|
-
if (dataValue === 64)
|
|
167
|
-
{
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
addDefaultVibrato();
|
|
171
|
-
this.channelVibrato.depth = dataValue / 2;
|
|
172
|
-
coolInfo("Vibrato depth", `${dataValue} = ${this.channelVibrato.depth}`, "cents of detune");
|
|
173
|
-
break;
|
|
174
|
-
|
|
175
|
-
// vibrato delay
|
|
176
|
-
case nonRegisteredGSLSB.vibratoDelay:
|
|
177
|
-
if (dataValue === 64)
|
|
178
|
-
{
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
addDefaultVibrato();
|
|
182
|
-
this.channelVibrato.delay = (dataValue / 64) / 3;
|
|
183
|
-
coolInfo("Vibrato delay", `${dataValue} = ${this.channelVibrato.delay}`, "seconds");
|
|
184
|
-
break;
|
|
185
|
-
|
|
186
|
-
// filter cutoff
|
|
187
|
-
case nonRegisteredGSLSB.TVFFilterCutoff:
|
|
188
|
-
// affect the "brightness" controller as we have a default modulator that controls it
|
|
189
|
-
this.controllerChange(midiControllers.brightness, dataValue);
|
|
190
|
-
coolInfo("Filter cutoff", dataValue.toString(), "");
|
|
191
|
-
break;
|
|
192
|
-
|
|
193
|
-
// attack time
|
|
194
|
-
case nonRegisteredGSLSB.EGAttackTime:
|
|
195
|
-
// affect the "attack time" controller as we have a default modulator that controls it
|
|
196
|
-
this.controllerChange(midiControllers.attackTime, dataValue);
|
|
197
|
-
coolInfo("EG attack time", dataValue.toString(), "");
|
|
198
|
-
break;
|
|
199
|
-
|
|
200
|
-
// release time
|
|
201
|
-
case nonRegisteredGSLSB.EGReleaseTime:
|
|
202
|
-
// affect the "release time" controller as we have a default modulator that controls it
|
|
203
|
-
this.controllerChange(midiControllers.releaseTime, dataValue);
|
|
204
|
-
coolInfo("EG release time", dataValue.toString(), "");
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
break;
|
|
208
|
-
|
|
209
|
-
case nonRegisteredMSB.awe32:
|
|
210
|
-
break;
|
|
211
|
-
|
|
212
|
-
// SF2 NRPN
|
|
213
|
-
case nonRegisteredMSB.SF2:
|
|
214
|
-
if (NRPNFine > 100)
|
|
215
|
-
{
|
|
216
|
-
// sfspec:
|
|
217
|
-
// Note that NRPN Select LSB greater than 100 are for setup only, and should not be used on their own to select a
|
|
218
|
-
// generator parameter.
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
const gen = this.customControllers[customControllers.sf2NPRNGeneratorLSB];
|
|
222
|
-
const offset = (dataValue << 7 | dataEntryFine) - 8192;
|
|
223
|
-
this.setGeneratorOffset(gen, offset);
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
break;
|
|
227
|
-
|
|
228
|
-
case dataEntryStates.RPCoarse:
|
|
229
|
-
case dataEntryStates.RPFine:
|
|
230
|
-
/**
|
|
231
|
-
* @type {number}
|
|
232
|
-
*/
|
|
233
|
-
const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
|
|
234
|
-
switch (rpnValue)
|
|
235
|
-
{
|
|
236
|
-
default:
|
|
237
|
-
SpessaSynthWarn(
|
|
238
|
-
`%cUnrecognized RPN for %c${this.channelNumber}%c: %c(0x${rpnValue.toString(16)})%c data value: %c${dataValue}`,
|
|
239
|
-
consoleColors.warn,
|
|
240
|
-
consoleColors.recognized,
|
|
241
|
-
consoleColors.warn,
|
|
242
|
-
consoleColors.unrecognized,
|
|
243
|
-
consoleColors.warn,
|
|
244
|
-
consoleColors.value
|
|
245
|
-
);
|
|
246
|
-
break;
|
|
247
|
-
|
|
248
|
-
// pitch bend range
|
|
249
|
-
case registeredParameterTypes.pitchBendRange:
|
|
250
|
-
this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] = dataValue << 7;
|
|
251
|
-
coolInfo("Pitch bend range", dataValue.toString(), "semitones");
|
|
252
|
-
break;
|
|
253
|
-
|
|
254
|
-
// coarse tuning
|
|
255
|
-
case registeredParameterTypes.coarseTuning:
|
|
256
|
-
// semitones
|
|
257
|
-
const semitones = dataValue - 64;
|
|
258
|
-
this.setCustomController(customControllers.channelTuningSemitones, semitones);
|
|
259
|
-
coolInfo("Coarse tuning", semitones.toString(), "semitones");
|
|
260
|
-
break;
|
|
261
|
-
|
|
262
|
-
// fine-tuning
|
|
263
|
-
case registeredParameterTypes.fineTuning:
|
|
264
|
-
// note: this will not work properly unless the lsb is sent!
|
|
265
|
-
// here we store the raw value to then adjust in fine
|
|
266
|
-
this.setTuning(dataValue - 64, false);
|
|
267
|
-
break;
|
|
268
|
-
|
|
269
|
-
// modulation depth
|
|
270
|
-
case registeredParameterTypes.modulationDepth:
|
|
271
|
-
this.setModulationDepth(dataValue * 100);
|
|
272
|
-
break;
|
|
273
|
-
|
|
274
|
-
case registeredParameterTypes.resetParameters:
|
|
275
|
-
this.resetParameters();
|
|
276
|
-
break;
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { consoleColors } from "../../../../utils/other.js";
|
|
2
|
-
import { SpessaSynthInfo, SpessaSynthWarn } 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
|
-
import { nonRegisteredMSB, registeredParameterTypes } from "./data_entry_coarse.js";
|
|
7
|
-
import { handleAWE32NRPN } from "./awe32.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Executes a data entry for an RPN tuning
|
|
11
|
-
* @param dataValue {number} dataEntry LSB
|
|
12
|
-
* @this {MidiAudioChannel}
|
|
13
|
-
* @private
|
|
14
|
-
*/
|
|
15
|
-
export function dataEntryFine(dataValue)
|
|
16
|
-
{
|
|
17
|
-
// store in cc table
|
|
18
|
-
this.midiControllers[midiControllers.lsbForControl6DataEntry] = dataValue << 7;
|
|
19
|
-
switch (this.dataEntryState)
|
|
20
|
-
{
|
|
21
|
-
default:
|
|
22
|
-
break;
|
|
23
|
-
|
|
24
|
-
case dataEntryStates.RPCoarse:
|
|
25
|
-
case dataEntryStates.RPFine:
|
|
26
|
-
const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
|
|
27
|
-
switch (rpnValue)
|
|
28
|
-
{
|
|
29
|
-
default:
|
|
30
|
-
break;
|
|
31
|
-
|
|
32
|
-
// pitch bend range fine tune
|
|
33
|
-
case registeredParameterTypes.pitchBendRange:
|
|
34
|
-
if (dataValue === 0)
|
|
35
|
-
{
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
// 14-bit value, so upper 7 are coarse and lower 7 are fine!
|
|
39
|
-
this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] |= dataValue;
|
|
40
|
-
const actualTune = (this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] >> 7) + dataValue / 128;
|
|
41
|
-
SpessaSynthInfo(
|
|
42
|
-
`%cChannel ${this.channelNumber} bend range. Semitones: %c${actualTune}`,
|
|
43
|
-
consoleColors.info,
|
|
44
|
-
consoleColors.value
|
|
45
|
-
);
|
|
46
|
-
break;
|
|
47
|
-
|
|
48
|
-
// fine-tuning
|
|
49
|
-
case registeredParameterTypes.fineTuning:
|
|
50
|
-
// grab the data and shift
|
|
51
|
-
const coarse = this.customControllers[customControllers.channelTuning];
|
|
52
|
-
const finalTuning = (coarse << 7) | dataValue;
|
|
53
|
-
this.setTuning(finalTuning * 0.01220703125); // multiply by 8192 / 100 (cent increments)
|
|
54
|
-
break;
|
|
55
|
-
|
|
56
|
-
// modulation depth
|
|
57
|
-
case registeredParameterTypes.modulationDepth:
|
|
58
|
-
const currentModulationDepthCents = this.customControllers[customControllers.modulationMultiplier] * 50;
|
|
59
|
-
let cents = currentModulationDepthCents + (dataValue / 128) * 100;
|
|
60
|
-
this.setModulationDepth(cents);
|
|
61
|
-
break;
|
|
62
|
-
|
|
63
|
-
case 0x3FFF:
|
|
64
|
-
this.resetParameters();
|
|
65
|
-
break;
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
break;
|
|
69
|
-
|
|
70
|
-
case dataEntryStates.NRPFine:
|
|
71
|
-
/**
|
|
72
|
-
* @type {number}
|
|
73
|
-
*/
|
|
74
|
-
const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;
|
|
75
|
-
/**
|
|
76
|
-
* @type {number}
|
|
77
|
-
*/
|
|
78
|
-
const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;
|
|
79
|
-
if (NRPNCoarse === nonRegisteredMSB.SF2)
|
|
80
|
-
{
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
switch (NRPNCoarse)
|
|
84
|
-
{
|
|
85
|
-
default:
|
|
86
|
-
SpessaSynthWarn(
|
|
87
|
-
`%cUnrecognized NRPN LSB for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)
|
|
88
|
-
.toUpperCase()} 0x${NRPNFine.toString(
|
|
89
|
-
16).toUpperCase()})%c data value: %c${dataValue}`,
|
|
90
|
-
consoleColors.warn,
|
|
91
|
-
consoleColors.recognized,
|
|
92
|
-
consoleColors.warn,
|
|
93
|
-
consoleColors.unrecognized,
|
|
94
|
-
consoleColors.warn,
|
|
95
|
-
consoleColors.value
|
|
96
|
-
);
|
|
97
|
-
break;
|
|
98
|
-
|
|
99
|
-
case nonRegisteredMSB.awe32:
|
|
100
|
-
handleAWE32NRPN.call(
|
|
101
|
-
this,
|
|
102
|
-
NRPNFine,
|
|
103
|
-
dataValue,
|
|
104
|
-
this.midiControllers[midiControllers.dataEntryMsb] >> 7
|
|
105
|
-
);
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
@@ -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,214 +0,0 @@
|
|
|
1
|
-
import { midiControllers } from "../../../midi/midi_message.js";
|
|
2
|
-
import { portamentoTimeToSeconds } from "./portamento_time.js";
|
|
3
|
-
import { customControllers } from "../engine_components/controller_tables.js";
|
|
4
|
-
import { Modulator } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
5
|
-
import { GENERATOR_OVERRIDE_NO_CHANGE_VALUE } from "../../synth_constants.js";
|
|
6
|
-
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
7
|
-
import { SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* sends a "MIDI Note on message"
|
|
11
|
-
* @param midiNote {number}
|
|
12
|
-
* @param velocity {number}
|
|
13
|
-
* @this {MidiAudioChannel}
|
|
14
|
-
*/
|
|
15
|
-
export function noteOn(midiNote, velocity)
|
|
16
|
-
{
|
|
17
|
-
if (velocity < 1)
|
|
18
|
-
{
|
|
19
|
-
this.noteOff(midiNote);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
velocity = Math.min(127, velocity);
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
(this.synth.highPerformanceMode && this.synth.totalVoicesAmount > 200 && velocity < 40) ||
|
|
26
|
-
(this.synth.highPerformanceMode && velocity < 10) ||
|
|
27
|
-
(this.isMuted)
|
|
28
|
-
)
|
|
29
|
-
{
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!this.preset)
|
|
34
|
-
{
|
|
35
|
-
SpessaSynthWarn(`No preset for channel ${this.channelNumber}!`);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const realKey = midiNote + this.channelTransposeKeyShift + this.customControllers[customControllers.channelKeyShift];
|
|
40
|
-
let internalMidiNote = realKey;
|
|
41
|
-
|
|
42
|
-
if (realKey > 127 || realKey < 0)
|
|
43
|
-
{
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const program = this.preset?.program;
|
|
47
|
-
const tune = this.synth.tunings[program]?.[realKey]?.midiNote;
|
|
48
|
-
if (tune >= 0)
|
|
49
|
-
{
|
|
50
|
-
internalMidiNote = tune;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// velocity override
|
|
54
|
-
if (this.velocityOverride > 0)
|
|
55
|
-
{
|
|
56
|
-
velocity = this.velocityOverride;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// key velocity override
|
|
60
|
-
const keyVel = this.synth.keyModifierManager.getVelocity(this.channelNumber, realKey);
|
|
61
|
-
if (keyVel > -1)
|
|
62
|
-
{
|
|
63
|
-
velocity = keyVel;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// gain
|
|
67
|
-
const voiceGain = this.synth.keyModifierManager.getGain(this.channelNumber, realKey);
|
|
68
|
-
|
|
69
|
-
// portamento
|
|
70
|
-
let portamentoFromKey = -1;
|
|
71
|
-
let portamentoDuration = 0;
|
|
72
|
-
// note: the 14-bit value needs to go down to 7-bit
|
|
73
|
-
const portamentoTime = this.midiControllers[midiControllers.portamentoTime] >> 7;
|
|
74
|
-
const control = this.midiControllers[midiControllers.portamentoControl];
|
|
75
|
-
const currentFromKey = control >> 7;
|
|
76
|
-
if (
|
|
77
|
-
!this.drumChannel && // no portamento on drum channel
|
|
78
|
-
currentFromKey !== internalMidiNote && // if the same note, there's no portamento
|
|
79
|
-
this.midiControllers[midiControllers.portamentoOnOff] >= 8192 && // (64 << 7)
|
|
80
|
-
portamentoTime > 0 // 0 duration is no portamento
|
|
81
|
-
)
|
|
82
|
-
{
|
|
83
|
-
// a value of one means the initial portamento
|
|
84
|
-
if (control !== 1)
|
|
85
|
-
{
|
|
86
|
-
const diff = Math.abs(internalMidiNote - currentFromKey);
|
|
87
|
-
portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);
|
|
88
|
-
portamentoFromKey = currentFromKey;
|
|
89
|
-
}
|
|
90
|
-
// set portamento control to previous value
|
|
91
|
-
this.controllerChange(midiControllers.portamentoControl, internalMidiNote);
|
|
92
|
-
}
|
|
93
|
-
// get voices
|
|
94
|
-
const voices = this.synth.getVoices(
|
|
95
|
-
this.channelNumber,
|
|
96
|
-
internalMidiNote,
|
|
97
|
-
velocity,
|
|
98
|
-
realKey
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
// zero means disabled
|
|
102
|
-
let panOverride = 0;
|
|
103
|
-
if (this.randomPan)
|
|
104
|
-
{
|
|
105
|
-
// the range is -500 to 500
|
|
106
|
-
panOverride = Math.round(Math.random() * 1000 - 500);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// add voices
|
|
110
|
-
const channelVoices = this.voices;
|
|
111
|
-
voices.forEach(voice =>
|
|
112
|
-
{
|
|
113
|
-
// apply portamento
|
|
114
|
-
voice.portamentoFromKey = portamentoFromKey;
|
|
115
|
-
voice.portamentoDuration = portamentoDuration;
|
|
116
|
-
|
|
117
|
-
// apply pan override
|
|
118
|
-
voice.overridePan = panOverride;
|
|
119
|
-
|
|
120
|
-
// apply gain override
|
|
121
|
-
voice.gain = voiceGain;
|
|
122
|
-
|
|
123
|
-
// dynamic modulators (if none, this won't iterate over anything)
|
|
124
|
-
this.sysExModulators.modulatorList.forEach(m =>
|
|
125
|
-
{
|
|
126
|
-
const mod = m.mod;
|
|
127
|
-
const existingModIndex = voice.modulators.findIndex(voiceMod => Modulator.isIdentical(voiceMod, mod));
|
|
128
|
-
|
|
129
|
-
// replace or add
|
|
130
|
-
if (existingModIndex !== -1)
|
|
131
|
-
{
|
|
132
|
-
voice.modulators[existingModIndex] = Modulator.copy(mod);
|
|
133
|
-
}
|
|
134
|
-
else
|
|
135
|
-
{
|
|
136
|
-
voice.modulators.push(Modulator.copy(mod));
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// apply generator override
|
|
141
|
-
if (this.generatorOverridesEnabled)
|
|
142
|
-
{
|
|
143
|
-
this.generatorOverrides.forEach((overrideValue, generatorType) =>
|
|
144
|
-
{
|
|
145
|
-
if (overrideValue === GENERATOR_OVERRIDE_NO_CHANGE_VALUE)
|
|
146
|
-
{
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
voice.generators[generatorType] = overrideValue;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// apply exclusive class
|
|
155
|
-
const exclusive = voice.exclusiveClass;
|
|
156
|
-
if (exclusive !== 0)
|
|
157
|
-
{
|
|
158
|
-
// kill all voices with the same exclusive class
|
|
159
|
-
channelVoices.forEach(v =>
|
|
160
|
-
{
|
|
161
|
-
if (v.exclusiveClass === exclusive)
|
|
162
|
-
{
|
|
163
|
-
v.exclusiveRelease(this.synth.currentSynthTime);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
// compute all modulators
|
|
168
|
-
this.computeModulators(voice);
|
|
169
|
-
// modulate sample offsets (these are not real time)
|
|
170
|
-
const cursorStartOffset = voice.modulatedGenerators[generatorTypes.startAddrsOffset] + voice.modulatedGenerators[generatorTypes.startAddrsCoarseOffset] * 32768;
|
|
171
|
-
const endOffset = voice.modulatedGenerators[generatorTypes.endAddrOffset] + voice.modulatedGenerators[generatorTypes.endAddrsCoarseOffset] * 32768;
|
|
172
|
-
const loopStartOffset = voice.modulatedGenerators[generatorTypes.startloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.startloopAddrsCoarseOffset] * 32768;
|
|
173
|
-
const loopEndOffset = voice.modulatedGenerators[generatorTypes.endloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.endloopAddrsCoarseOffset] * 32768;
|
|
174
|
-
const sm = voice.sample;
|
|
175
|
-
// apply them
|
|
176
|
-
const clamp = num => Math.max(0, Math.min(sm.sampleData.length - 1, num));
|
|
177
|
-
sm.cursor = clamp(sm.cursor + cursorStartOffset);
|
|
178
|
-
sm.end = clamp(sm.end + endOffset);
|
|
179
|
-
sm.loopStart = clamp(sm.loopStart + loopStartOffset);
|
|
180
|
-
sm.loopEnd = clamp(sm.loopEnd + loopEndOffset);
|
|
181
|
-
// swap loops if needed
|
|
182
|
-
if (sm.loopEnd < sm.loopStart)
|
|
183
|
-
{
|
|
184
|
-
const temp = sm.loopStart;
|
|
185
|
-
sm.loopStart = sm.loopEnd;
|
|
186
|
-
sm.loopEnd = temp;
|
|
187
|
-
}
|
|
188
|
-
if (sm.loopEnd - sm.loopStart < 1)
|
|
189
|
-
{
|
|
190
|
-
sm.loopingMode = 0;
|
|
191
|
-
sm.isLooping = false;
|
|
192
|
-
}
|
|
193
|
-
// set the current attenuation to target,
|
|
194
|
-
// as it's interpolated (we don't want 0 attenuation for even a split second)
|
|
195
|
-
voice.volumeEnvelope.attenuation = voice.volumeEnvelope.attenuationTargetGain;
|
|
196
|
-
// set initial pan to avoid split second changing from middle to the correct value
|
|
197
|
-
voice.currentPan = Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan])); // -500 to 500
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
this.synth.totalVoicesAmount += voices.length;
|
|
201
|
-
// cap the voices
|
|
202
|
-
if (this.synth.totalVoicesAmount > this.synth.voiceCap)
|
|
203
|
-
{
|
|
204
|
-
this.synth.voiceKilling(voices.length);
|
|
205
|
-
}
|
|
206
|
-
channelVoices.push(...voices);
|
|
207
|
-
this.sendChannelProperty();
|
|
208
|
-
this.synth.callEvent("noteon", {
|
|
209
|
-
midiNote: midiNote,
|
|
210
|
-
channel: this.channelNumber,
|
|
211
|
-
velocity: velocity
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
}
|