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,1058 +0,0 @@
|
|
|
1
|
-
import { arrayToHexString, consoleColors } from "../../../utils/other.js";
|
|
2
|
-
import { SpessaSynthInfo, SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
3
|
-
import { midiControllers } from "../../../midi/midi_message.js";
|
|
4
|
-
import { ALL_CHANNELS_OR_DIFFERENT_ACTION } from "../../synth_constants.js";
|
|
5
|
-
import { isSystemXG } from "../../../utils/xg_hacks.js";
|
|
6
|
-
import { masterParameterType } from "./controller_control/master_parameters.js";
|
|
7
|
-
import { readBytesAsString } from "../../../utils/byte_functions/string.js";
|
|
8
|
-
import { synthDisplayTypes } from "../engine_components/enums.js";
|
|
9
|
-
import { customControllers, NON_CC_INDEX_OFFSET } from "../engine_components/controller_tables.js";
|
|
10
|
-
import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
11
|
-
|
|
12
|
-
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* KeyNum: tuning
|
|
16
|
-
* @typedef {MTSNoteTuning[]} MTSProgramTuning
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @typedef {Object} MTSNoteTuning
|
|
21
|
-
* @property {number} midiNote - the base midi note to use, -1 means no change
|
|
22
|
-
* @property {number} centTuning - additional tuning
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Calculates freqency for MIDI Tuning Standard
|
|
27
|
-
* @param byte1 {number}
|
|
28
|
-
* @param byte2 {number}
|
|
29
|
-
* @param byte3 {number}
|
|
30
|
-
* @return {{midiNote: number, centTuning: number|null}}
|
|
31
|
-
*/
|
|
32
|
-
function getTuning(byte1, byte2, byte3)
|
|
33
|
-
{
|
|
34
|
-
const midiNote = byte1;
|
|
35
|
-
const fraction = (byte2 << 7) | byte3; // Combine byte2 and byte3 into a 14-bit number
|
|
36
|
-
|
|
37
|
-
// no change
|
|
38
|
-
if (byte1 === 0x7F && byte2 === 0x7F && byte3 === 0x7F)
|
|
39
|
-
{
|
|
40
|
-
return { midiNote: -1, centTuning: null };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// calculate cent tuning
|
|
44
|
-
return { midiNote: midiNote, centTuning: fraction * 0.0061 };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Executes a system exclusive
|
|
49
|
-
* @param syx {number[]|IndexedByteArray} - the message data without f0
|
|
50
|
-
* @param channelOffset {number}
|
|
51
|
-
* @this {SpessaSynthProcessor}
|
|
52
|
-
*/
|
|
53
|
-
export function systemExclusive(syx, channelOffset = 0)
|
|
54
|
-
{
|
|
55
|
-
const type = syx[0];
|
|
56
|
-
if (this.deviceID !== ALL_CHANNELS_OR_DIFFERENT_ACTION && syx[1] !== 0x7F)
|
|
57
|
-
{
|
|
58
|
-
if (this.deviceID !== syx[1])
|
|
59
|
-
{
|
|
60
|
-
// not our device ID
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function niceLogging(channel, value, what, units)
|
|
66
|
-
{
|
|
67
|
-
SpessaSynthInfo(
|
|
68
|
-
`%cChannel %c${channel}%c ${what}. %c${value} ${units}%c, with %c${arrayToHexString(syx)}`,
|
|
69
|
-
consoleColors.info,
|
|
70
|
-
consoleColors.recognized,
|
|
71
|
-
consoleColors.info,
|
|
72
|
-
consoleColors.value,
|
|
73
|
-
consoleColors.info,
|
|
74
|
-
consoleColors.value
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function notRecognized()
|
|
79
|
-
{
|
|
80
|
-
// this is some other GS sysex...
|
|
81
|
-
SpessaSynthWarn(
|
|
82
|
-
`%cUnrecognized Roland %cGS %cSysEx: %c${arrayToHexString(syx)}`,
|
|
83
|
-
consoleColors.warn,
|
|
84
|
-
consoleColors.recognized,
|
|
85
|
-
consoleColors.warn,
|
|
86
|
-
consoleColors.unrecognized
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
switch (type)
|
|
91
|
-
{
|
|
92
|
-
default:
|
|
93
|
-
SpessaSynthWarn(
|
|
94
|
-
`%cUnrecognized SysEx: %c${arrayToHexString(syx)}`,
|
|
95
|
-
consoleColors.warn,
|
|
96
|
-
consoleColors.unrecognized
|
|
97
|
-
);
|
|
98
|
-
break;
|
|
99
|
-
|
|
100
|
-
// non realtime
|
|
101
|
-
case 0x7E:
|
|
102
|
-
case 0x7F:
|
|
103
|
-
switch (syx[2])
|
|
104
|
-
{
|
|
105
|
-
case 0x04:
|
|
106
|
-
let cents;
|
|
107
|
-
// device control
|
|
108
|
-
switch (syx[3])
|
|
109
|
-
{
|
|
110
|
-
case 0x01:
|
|
111
|
-
// main volume
|
|
112
|
-
const vol = syx[5] << 7 | syx[4];
|
|
113
|
-
this.setMIDIVolume(vol / 16384);
|
|
114
|
-
SpessaSynthInfo(
|
|
115
|
-
`%cMaster Volume. Volume: %c${vol}`,
|
|
116
|
-
consoleColors.info,
|
|
117
|
-
consoleColors.value
|
|
118
|
-
);
|
|
119
|
-
break;
|
|
120
|
-
|
|
121
|
-
case 0x02:
|
|
122
|
-
// main balance
|
|
123
|
-
// midi spec page 62
|
|
124
|
-
const balance = syx[5] << 7 | syx[4];
|
|
125
|
-
const pan = (balance - 8192) / 8192;
|
|
126
|
-
this.setMasterParameter(masterParameterType.masterPan, pan);
|
|
127
|
-
SpessaSynthInfo(
|
|
128
|
-
`%cMaster Pan. Pan: %c${pan}`,
|
|
129
|
-
consoleColors.info,
|
|
130
|
-
consoleColors.value
|
|
131
|
-
);
|
|
132
|
-
break;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
case 0x03:
|
|
136
|
-
// fine-tuning
|
|
137
|
-
const tuningValue = ((syx[5] << 7) | syx[6]) - 8192;
|
|
138
|
-
cents = Math.floor(tuningValue / 81.92); // [-100;+99] cents range
|
|
139
|
-
this.setMasterTuning(cents);
|
|
140
|
-
SpessaSynthInfo(
|
|
141
|
-
`%cMaster Fine Tuning. Cents: %c${cents}`,
|
|
142
|
-
consoleColors.info,
|
|
143
|
-
consoleColors.value
|
|
144
|
-
);
|
|
145
|
-
break;
|
|
146
|
-
|
|
147
|
-
case 0x04:
|
|
148
|
-
// coarse tuning
|
|
149
|
-
// lsb is ignored
|
|
150
|
-
const semitones = syx[5] - 64;
|
|
151
|
-
cents = semitones * 100;
|
|
152
|
-
this.setMasterTuning(cents);
|
|
153
|
-
SpessaSynthInfo(
|
|
154
|
-
`%cMaster Coarse Tuning. Cents: %c${cents}`,
|
|
155
|
-
consoleColors.info,
|
|
156
|
-
consoleColors.value
|
|
157
|
-
);
|
|
158
|
-
break;
|
|
159
|
-
|
|
160
|
-
default:
|
|
161
|
-
SpessaSynthWarn(
|
|
162
|
-
`%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(syx)}`,
|
|
163
|
-
consoleColors.warn,
|
|
164
|
-
consoleColors.unrecognized
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
break;
|
|
168
|
-
|
|
169
|
-
case 0x09:
|
|
170
|
-
// gm system related
|
|
171
|
-
if (syx[3] === 0x01)
|
|
172
|
-
{
|
|
173
|
-
SpessaSynthInfo("%cGM1 system on", consoleColors.info);
|
|
174
|
-
this.setSystem("gm");
|
|
175
|
-
}
|
|
176
|
-
else if (syx[3] === 0x03)
|
|
177
|
-
{
|
|
178
|
-
SpessaSynthInfo("%cGM2 system on", consoleColors.info);
|
|
179
|
-
this.setSystem("gm2");
|
|
180
|
-
}
|
|
181
|
-
else
|
|
182
|
-
{
|
|
183
|
-
SpessaSynthInfo("%cGM system off, defaulting to GS", consoleColors.info);
|
|
184
|
-
this.setSystem("gs");
|
|
185
|
-
}
|
|
186
|
-
break;
|
|
187
|
-
|
|
188
|
-
// MIDI Tuning standard
|
|
189
|
-
// https://midi.org/midi-tuning-updated-specification
|
|
190
|
-
case 0x08:
|
|
191
|
-
let currentMessageIndex = 4;
|
|
192
|
-
switch (syx[3])
|
|
193
|
-
{
|
|
194
|
-
// bulk tuning dump: all 128 notes
|
|
195
|
-
case 0x01:
|
|
196
|
-
const program = syx[currentMessageIndex++];
|
|
197
|
-
// read the name
|
|
198
|
-
syx.currentIndex = currentMessageIndex;
|
|
199
|
-
const tuningName = readBytesAsString(syx, 16);
|
|
200
|
-
currentMessageIndex += 16;
|
|
201
|
-
if (syx.length < 384)
|
|
202
|
-
{
|
|
203
|
-
SpessaSynthWarn(`The Bulk Tuning Dump is too short! (${syx.length} bytes, at least 384 are expected)`);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
// 128 frequencies follow
|
|
207
|
-
for (let i = 0; i < 128; i++)
|
|
208
|
-
{
|
|
209
|
-
// set the given tuning to the program
|
|
210
|
-
this.tunings[program][i] = getTuning(
|
|
211
|
-
syx[currentMessageIndex++],
|
|
212
|
-
syx[currentMessageIndex++],
|
|
213
|
-
syx[currentMessageIndex++]
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
SpessaSynthInfo(
|
|
217
|
-
`%cBulk Tuning Dump %c${tuningName}%c Program: %c${program}`,
|
|
218
|
-
consoleColors.info,
|
|
219
|
-
consoleColors.value,
|
|
220
|
-
consoleColors.info,
|
|
221
|
-
consoleColors.recognized
|
|
222
|
-
);
|
|
223
|
-
break;
|
|
224
|
-
|
|
225
|
-
// single note change
|
|
226
|
-
// single note change bank
|
|
227
|
-
case 0x02:
|
|
228
|
-
case 0x07:
|
|
229
|
-
if (syx[3] === 0x07)
|
|
230
|
-
{
|
|
231
|
-
// skip the bank
|
|
232
|
-
currentMessageIndex++;
|
|
233
|
-
}
|
|
234
|
-
// get program and number of changes
|
|
235
|
-
const tuningProgram = syx[currentMessageIndex++];
|
|
236
|
-
const numberOfChanges = syx[currentMessageIndex++];
|
|
237
|
-
for (let i = 0; i < numberOfChanges; i++)
|
|
238
|
-
{
|
|
239
|
-
// set the given tuning to the program
|
|
240
|
-
this.tunings[tuningProgram][syx[currentMessageIndex++]] = getTuning(
|
|
241
|
-
syx[currentMessageIndex++],
|
|
242
|
-
syx[currentMessageIndex++],
|
|
243
|
-
syx[currentMessageIndex++]
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
SpessaSynthInfo(
|
|
247
|
-
`%cSingle Note Tuning. Program: %c${tuningProgram}%c Keys affected: %c${numberOfChanges}`,
|
|
248
|
-
consoleColors.info,
|
|
249
|
-
consoleColors.recognized,
|
|
250
|
-
consoleColors.info,
|
|
251
|
-
consoleColors.recognized
|
|
252
|
-
);
|
|
253
|
-
break;
|
|
254
|
-
|
|
255
|
-
// octave tuning (1 byte)
|
|
256
|
-
// and octave tuning (2 bytes)
|
|
257
|
-
case 0x09:
|
|
258
|
-
case 0x08:
|
|
259
|
-
// get tuning:
|
|
260
|
-
const newOctaveTuning = new Int8Array(12);
|
|
261
|
-
// start from bit 7
|
|
262
|
-
if (syx[3] === 0x08)
|
|
263
|
-
{
|
|
264
|
-
// 1 byte tuning: 0 is -64 cents, 64 is 0, 127 is +63
|
|
265
|
-
for (let i = 0; i < 12; i++)
|
|
266
|
-
{
|
|
267
|
-
newOctaveTuning[i] = syx[7 + i] - 64;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
else
|
|
271
|
-
{
|
|
272
|
-
// 2 byte tuning. Like fine tune: 0 is -100 cents, 8192 is 0 cents, 16,383 is +100 cents
|
|
273
|
-
for (let i = 0; i < 24; i += 2)
|
|
274
|
-
{
|
|
275
|
-
const tuning = ((syx[7 + i] << 7) | syx[8 + i]) - 8192;
|
|
276
|
-
newOctaveTuning[i / 2] = Math.floor(tuning / 81.92); // map to [-100;+99] cents
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
// apply to channels (ordered from 0)
|
|
280
|
-
// bit 1: 14 and 15
|
|
281
|
-
if ((syx[4] & 1) === 1)
|
|
282
|
-
{
|
|
283
|
-
this.midiAudioChannels[14 + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
284
|
-
}
|
|
285
|
-
if (((syx[4] >> 1) & 1) === 1)
|
|
286
|
-
{
|
|
287
|
-
this.midiAudioChannels[15 + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// bit 2: channels 7 to 13
|
|
291
|
-
for (let i = 0; i < 7; i++)
|
|
292
|
-
{
|
|
293
|
-
const bit = (syx[5] >> i) & 1;
|
|
294
|
-
if (bit === 1)
|
|
295
|
-
{
|
|
296
|
-
this.midiAudioChannels[7 + i + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// bit 3: channels 0 to 16
|
|
301
|
-
for (let i = 0; i < 7; i++)
|
|
302
|
-
{
|
|
303
|
-
const bit = (syx[6] >> i) & 1;
|
|
304
|
-
if (bit === 1)
|
|
305
|
-
{
|
|
306
|
-
this.midiAudioChannels[i + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
SpessaSynthInfo(
|
|
311
|
-
`%cMIDI Octave Scale ${
|
|
312
|
-
syx[3] === 0x08 ? "(1 byte)" : "(2 bytes)"
|
|
313
|
-
} tuning via Tuning: %c${newOctaveTuning.join(" ")}`,
|
|
314
|
-
consoleColors.info,
|
|
315
|
-
consoleColors.value
|
|
316
|
-
);
|
|
317
|
-
break;
|
|
318
|
-
|
|
319
|
-
default:
|
|
320
|
-
SpessaSynthWarn(
|
|
321
|
-
`%cUnrecognized MIDI Tuning standard message: %c${arrayToHexString(syx)}`,
|
|
322
|
-
consoleColors.warn,
|
|
323
|
-
consoleColors.unrecognized
|
|
324
|
-
);
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
break;
|
|
328
|
-
|
|
329
|
-
default:
|
|
330
|
-
SpessaSynthWarn(
|
|
331
|
-
`%cUnrecognized MIDI Realtime/non realtime message: %c${arrayToHexString(syx)}`,
|
|
332
|
-
consoleColors.warn,
|
|
333
|
-
consoleColors.unrecognized
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
break;
|
|
338
|
-
|
|
339
|
-
// this is a roland sysex
|
|
340
|
-
// http://www.bandtrax.com.au/sysex.htm
|
|
341
|
-
// https://cdn.roland.com/assets/media/pdf/AT-20R_30R_MI.pdf
|
|
342
|
-
case 0x41:
|
|
343
|
-
if (syx[2] === 0x42 && syx[3] === 0x12)
|
|
344
|
-
{
|
|
345
|
-
// this is a GS sysex
|
|
346
|
-
const messageValue = syx[7];
|
|
347
|
-
// syx[5] and [6] is the system parameter, syx[7] is the value
|
|
348
|
-
// either patch common or SC-88 mode set
|
|
349
|
-
if (syx[4] === 0x40 || (syx[4] === 0x00 && syx[6] === 0x7F))
|
|
350
|
-
{
|
|
351
|
-
// this is a channel parameter
|
|
352
|
-
if ((syx[5] & 0x10) > 0)
|
|
353
|
-
{
|
|
354
|
-
// this is an individual part (channel) parameter
|
|
355
|
-
// determine the channel 0 means channel 10 (default), 1 means 1 etc.
|
|
356
|
-
// SC88 manual page 196
|
|
357
|
-
const channel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][syx[5] & 0x0F] + channelOffset;
|
|
358
|
-
// for example, 0x1A means A = 11, which corresponds to channel 12 (counting from 1)
|
|
359
|
-
const channelObject = this.midiAudioChannels[channel];
|
|
360
|
-
switch (syx[6])
|
|
361
|
-
{
|
|
362
|
-
default:
|
|
363
|
-
// this is some other GS sysex...
|
|
364
|
-
notRecognized();
|
|
365
|
-
break;
|
|
366
|
-
|
|
367
|
-
case 0x15:
|
|
368
|
-
// this is the Use for Drum Part sysex (multiple drums)
|
|
369
|
-
const isDrums = messageValue > 0 && syx[5] >> 4; // if set to other than 0, is a drum channel
|
|
370
|
-
channelObject.setDrums(isDrums);
|
|
371
|
-
SpessaSynthInfo(
|
|
372
|
-
`%cChannel %c${channel}%c ${isDrums ?
|
|
373
|
-
"is now a drum channel"
|
|
374
|
-
:
|
|
375
|
-
"now isn't a drum channel"
|
|
376
|
-
}%c via: %c${arrayToHexString(syx)}`,
|
|
377
|
-
consoleColors.info,
|
|
378
|
-
consoleColors.value,
|
|
379
|
-
consoleColors.recognized,
|
|
380
|
-
consoleColors.info,
|
|
381
|
-
consoleColors.value
|
|
382
|
-
);
|
|
383
|
-
return;
|
|
384
|
-
|
|
385
|
-
case 0x16:
|
|
386
|
-
// this is the pitch key shift sysex
|
|
387
|
-
const keyShift = messageValue - 64;
|
|
388
|
-
channelObject.setCustomController(customControllers.channelKeyShift, keyShift);
|
|
389
|
-
niceLogging(channel, keyShift, "key shift", "keys");
|
|
390
|
-
return;
|
|
391
|
-
|
|
392
|
-
// pan position
|
|
393
|
-
case 0x1C:
|
|
394
|
-
// 0 is random
|
|
395
|
-
let panpot = messageValue;
|
|
396
|
-
if (panpot === 0)
|
|
397
|
-
{
|
|
398
|
-
channelObject.randomPan = true;
|
|
399
|
-
SpessaSynthInfo(
|
|
400
|
-
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
401
|
-
consoleColors.info,
|
|
402
|
-
consoleColors.recognized,
|
|
403
|
-
consoleColors.info,
|
|
404
|
-
consoleColors.value
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
else
|
|
408
|
-
{
|
|
409
|
-
channelObject.randomPan = false;
|
|
410
|
-
channelObject.controllerChange(midiControllers.pan, panpot);
|
|
411
|
-
}
|
|
412
|
-
break;
|
|
413
|
-
|
|
414
|
-
// chorus send
|
|
415
|
-
case 0x21:
|
|
416
|
-
channelObject.controllerChange(midiControllers.chorusDepth, messageValue);
|
|
417
|
-
break;
|
|
418
|
-
|
|
419
|
-
// reverb send
|
|
420
|
-
case 0x22:
|
|
421
|
-
channelObject.controllerChange(midiControllers.reverbDepth, messageValue);
|
|
422
|
-
break;
|
|
423
|
-
|
|
424
|
-
case 0x40:
|
|
425
|
-
case 0x41:
|
|
426
|
-
case 0x42:
|
|
427
|
-
case 0x43:
|
|
428
|
-
case 0x44:
|
|
429
|
-
case 0x45:
|
|
430
|
-
case 0x46:
|
|
431
|
-
case 0x47:
|
|
432
|
-
case 0x48:
|
|
433
|
-
case 0x49:
|
|
434
|
-
case 0x4A:
|
|
435
|
-
case 0x4B:
|
|
436
|
-
// scale tuning: up to 12 bytes
|
|
437
|
-
const tuningBytes = syx.length - 9; // data starts at 7, minus checksum and f7
|
|
438
|
-
// read em bytes
|
|
439
|
-
const newTuning = new Int8Array(12);
|
|
440
|
-
for (let i = 0; i < tuningBytes; i++)
|
|
441
|
-
{
|
|
442
|
-
newTuning[i] = syx[i + 7] - 64;
|
|
443
|
-
}
|
|
444
|
-
channelObject.setOctaveTuning(newTuning);
|
|
445
|
-
const cents = messageValue - 64;
|
|
446
|
-
niceLogging(channel, newTuning.join(" "), "octave scale tuning", "cents");
|
|
447
|
-
channelObject.setTuning(cents);
|
|
448
|
-
break;
|
|
449
|
-
}
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
else
|
|
453
|
-
// this is a channel parameter also
|
|
454
|
-
if ((syx[5] & 0x20) > 0)
|
|
455
|
-
{
|
|
456
|
-
// this is an individual part (channel) parameter
|
|
457
|
-
// determine the channel 0 means channel 10 (default), 1 means 1 etc.
|
|
458
|
-
const channel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][syx[5] & 0x0F] + channelOffset;
|
|
459
|
-
// for example, 0x1A means A = 11, which corresponds to channel 12 (counting from 1)
|
|
460
|
-
const channelObject = this.midiAudioChannels[channel];
|
|
461
|
-
const centeredValue = (messageValue - 64);
|
|
462
|
-
const normalizedValue = centeredValue / 64;
|
|
463
|
-
const normalizedNotCentered = messageValue / 128;
|
|
464
|
-
|
|
465
|
-
// setup receivers for cc to parameter (sc-88 manual page 198)
|
|
466
|
-
const setupReceivers = (source, sourceName, bipolar = false) =>
|
|
467
|
-
{
|
|
468
|
-
switch (syx[6] & 0x0F)
|
|
469
|
-
{
|
|
470
|
-
case 0x00:
|
|
471
|
-
// see https://github.com/spessasus/SpessaSynth/issues/154
|
|
472
|
-
// pitch control
|
|
473
|
-
// special case:
|
|
474
|
-
// if the source is a pitch wheel, it's a strange way of setting the bend range
|
|
475
|
-
// testcase: th07_03.mid
|
|
476
|
-
if (source === NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel)
|
|
477
|
-
{
|
|
478
|
-
channelObject.controllerChange(midiControllers.RPNMsb, 0x0);
|
|
479
|
-
channelObject.controllerChange(midiControllers.RPNLsb, 0x0);
|
|
480
|
-
channelObject.controllerChange(
|
|
481
|
-
midiControllers.dataEntryMsb,
|
|
482
|
-
Math.floor(centeredValue)
|
|
483
|
-
);
|
|
484
|
-
}
|
|
485
|
-
else
|
|
486
|
-
{
|
|
487
|
-
channelObject.sysExModulators.setModulator(
|
|
488
|
-
source,
|
|
489
|
-
generatorTypes.fineTune,
|
|
490
|
-
centeredValue * 100,
|
|
491
|
-
bipolar
|
|
492
|
-
);
|
|
493
|
-
niceLogging(channel, centeredValue, `${sourceName} pitch control`, "semitones");
|
|
494
|
-
}
|
|
495
|
-
break;
|
|
496
|
-
|
|
497
|
-
case 0x01:
|
|
498
|
-
// cutoff
|
|
499
|
-
channelObject.sysExModulators.setModulator(
|
|
500
|
-
source,
|
|
501
|
-
generatorTypes.initialFilterFc,
|
|
502
|
-
normalizedValue * 9600,
|
|
503
|
-
bipolar
|
|
504
|
-
);
|
|
505
|
-
niceLogging(
|
|
506
|
-
channel,
|
|
507
|
-
normalizedValue * 9600,
|
|
508
|
-
`${sourceName} pitch control`,
|
|
509
|
-
"cents"
|
|
510
|
-
);
|
|
511
|
-
break;
|
|
512
|
-
|
|
513
|
-
case 0x02:
|
|
514
|
-
// amplitude
|
|
515
|
-
channelObject.sysExModulators.setModulator(
|
|
516
|
-
source,
|
|
517
|
-
generatorTypes.initialAttenuation,
|
|
518
|
-
normalizedValue * 960, // spec says "100%" so 960cB in sf2
|
|
519
|
-
bipolar
|
|
520
|
-
);
|
|
521
|
-
niceLogging(channel, normalizedValue * 960, `${sourceName} amplitude`, "cB");
|
|
522
|
-
break;
|
|
523
|
-
|
|
524
|
-
// rate control is ignored as it is in hertz
|
|
525
|
-
|
|
526
|
-
case 0x04:
|
|
527
|
-
// LFO1 pitch depth
|
|
528
|
-
channelObject.sysExModulators.setModulator(
|
|
529
|
-
source,
|
|
530
|
-
generatorTypes.vibLfoToPitch,
|
|
531
|
-
normalizedNotCentered * 600,
|
|
532
|
-
bipolar
|
|
533
|
-
);
|
|
534
|
-
niceLogging(
|
|
535
|
-
channel,
|
|
536
|
-
normalizedNotCentered * 600,
|
|
537
|
-
`${sourceName} LFO1 pitch depth`,
|
|
538
|
-
"cents"
|
|
539
|
-
);
|
|
540
|
-
break;
|
|
541
|
-
|
|
542
|
-
case 0x05:
|
|
543
|
-
// LFO1 filter depth
|
|
544
|
-
channelObject.sysExModulators.setModulator(
|
|
545
|
-
source,
|
|
546
|
-
generatorTypes.vibLfoToFilterFc,
|
|
547
|
-
normalizedNotCentered * 2400,
|
|
548
|
-
bipolar
|
|
549
|
-
);
|
|
550
|
-
niceLogging(
|
|
551
|
-
channel,
|
|
552
|
-
normalizedNotCentered * 2400,
|
|
553
|
-
`${sourceName} LFO1 filter depth`,
|
|
554
|
-
"cents"
|
|
555
|
-
);
|
|
556
|
-
break;
|
|
557
|
-
|
|
558
|
-
case 0x06:
|
|
559
|
-
// LFO1 amplitude depth
|
|
560
|
-
channelObject.sysExModulators.setModulator(
|
|
561
|
-
source,
|
|
562
|
-
generatorTypes.vibLfoToVolume,
|
|
563
|
-
normalizedValue * 960,
|
|
564
|
-
bipolar
|
|
565
|
-
);
|
|
566
|
-
niceLogging(
|
|
567
|
-
channel,
|
|
568
|
-
normalizedValue * 960,
|
|
569
|
-
`${sourceName} LFO1 amplitude depth`,
|
|
570
|
-
"cB"
|
|
571
|
-
);
|
|
572
|
-
break;
|
|
573
|
-
|
|
574
|
-
// rate control is ignored as it is in hertz
|
|
575
|
-
|
|
576
|
-
case 0x08:
|
|
577
|
-
// LFO2 pitch depth
|
|
578
|
-
channelObject.sysExModulators.setModulator(
|
|
579
|
-
source,
|
|
580
|
-
generatorTypes.modLfoToPitch,
|
|
581
|
-
normalizedNotCentered * 600,
|
|
582
|
-
bipolar
|
|
583
|
-
);
|
|
584
|
-
niceLogging(
|
|
585
|
-
channel,
|
|
586
|
-
normalizedNotCentered * 600,
|
|
587
|
-
`${sourceName} LFO2 pitch depth`,
|
|
588
|
-
"cents"
|
|
589
|
-
);
|
|
590
|
-
break;
|
|
591
|
-
|
|
592
|
-
case 0x09:
|
|
593
|
-
// LFO2 filter depth
|
|
594
|
-
channelObject.sysExModulators.setModulator(
|
|
595
|
-
source,
|
|
596
|
-
generatorTypes.modLfoToFilterFc,
|
|
597
|
-
normalizedNotCentered * 2400,
|
|
598
|
-
bipolar
|
|
599
|
-
);
|
|
600
|
-
niceLogging(
|
|
601
|
-
channel,
|
|
602
|
-
normalizedNotCentered * 2400,
|
|
603
|
-
`${sourceName} LFO2 filter depth`,
|
|
604
|
-
"cents"
|
|
605
|
-
);
|
|
606
|
-
break;
|
|
607
|
-
|
|
608
|
-
case 0x0A:
|
|
609
|
-
// LFO2 amplitude depth
|
|
610
|
-
channelObject.sysExModulators.setModulator(
|
|
611
|
-
source,
|
|
612
|
-
generatorTypes.modLfoToVolume,
|
|
613
|
-
normalizedValue * 960,
|
|
614
|
-
bipolar
|
|
615
|
-
);
|
|
616
|
-
niceLogging(
|
|
617
|
-
channel,
|
|
618
|
-
normalizedValue * 960,
|
|
619
|
-
`${sourceName} LFO2 amplitude depth`,
|
|
620
|
-
"cB"
|
|
621
|
-
);
|
|
622
|
-
break;
|
|
623
|
-
}
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
// SC88 manual page 198
|
|
627
|
-
switch (syx[6] & 0xF0)
|
|
628
|
-
{
|
|
629
|
-
default:
|
|
630
|
-
// this is some other GS sysex...
|
|
631
|
-
notRecognized();
|
|
632
|
-
break;
|
|
633
|
-
|
|
634
|
-
case 0x00:
|
|
635
|
-
// modulation wheel
|
|
636
|
-
setupReceivers(midiControllers.modulationWheel, "mod wheel");
|
|
637
|
-
break;
|
|
638
|
-
|
|
639
|
-
case 0x10:
|
|
640
|
-
// pitch bend
|
|
641
|
-
setupReceivers(NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel, "pitch bend", true);
|
|
642
|
-
break;
|
|
643
|
-
|
|
644
|
-
case 0x20:
|
|
645
|
-
// channel pressure
|
|
646
|
-
setupReceivers(
|
|
647
|
-
NON_CC_INDEX_OFFSET + modulatorSources.channelPressure,
|
|
648
|
-
"channel pressure"
|
|
649
|
-
);
|
|
650
|
-
break;
|
|
651
|
-
|
|
652
|
-
case 0x30:
|
|
653
|
-
// poly pressure
|
|
654
|
-
setupReceivers(
|
|
655
|
-
NON_CC_INDEX_OFFSET + modulatorSources.polyPressure,
|
|
656
|
-
"poly pressure"
|
|
657
|
-
);
|
|
658
|
-
break;
|
|
659
|
-
}
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
else
|
|
663
|
-
// this is a global system parameter
|
|
664
|
-
if (syx[5] === 0x00)
|
|
665
|
-
{
|
|
666
|
-
switch (syx[6])
|
|
667
|
-
{
|
|
668
|
-
default:
|
|
669
|
-
notRecognized();
|
|
670
|
-
break;
|
|
671
|
-
|
|
672
|
-
case 0x7F:
|
|
673
|
-
// roland mode set
|
|
674
|
-
// GS mode set
|
|
675
|
-
if (messageValue === 0x00)
|
|
676
|
-
{
|
|
677
|
-
// this is a GS reset
|
|
678
|
-
SpessaSynthInfo("%cGS Reset received!", consoleColors.info);
|
|
679
|
-
this.resetAllControllers(false);
|
|
680
|
-
this.setSystem("gs");
|
|
681
|
-
}
|
|
682
|
-
else if (messageValue === 0x7F)
|
|
683
|
-
{
|
|
684
|
-
// GS mode off
|
|
685
|
-
SpessaSynthInfo("%cGS system off, switching to GM2", consoleColors.info);
|
|
686
|
-
this.resetAllControllers(false);
|
|
687
|
-
this.setSystem("gm2");
|
|
688
|
-
}
|
|
689
|
-
break;
|
|
690
|
-
|
|
691
|
-
case 0x06:
|
|
692
|
-
// roland master pan
|
|
693
|
-
SpessaSynthInfo(
|
|
694
|
-
`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
695
|
-
syx)}`,
|
|
696
|
-
consoleColors.info,
|
|
697
|
-
consoleColors.value,
|
|
698
|
-
consoleColors.info,
|
|
699
|
-
consoleColors.value
|
|
700
|
-
);
|
|
701
|
-
this.setMasterParameter(masterParameterType.masterPan, (messageValue - 64) / 64);
|
|
702
|
-
break;
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
case 0x04:
|
|
706
|
-
// roland GS master volume
|
|
707
|
-
SpessaSynthInfo(
|
|
708
|
-
`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
709
|
-
syx)}`,
|
|
710
|
-
consoleColors.info,
|
|
711
|
-
consoleColors.value,
|
|
712
|
-
consoleColors.info,
|
|
713
|
-
consoleColors.value
|
|
714
|
-
);
|
|
715
|
-
this.setMIDIVolume(messageValue / 127);
|
|
716
|
-
break;
|
|
717
|
-
|
|
718
|
-
case 0x05:
|
|
719
|
-
// roland master key shift (transpose)
|
|
720
|
-
const transpose = messageValue - 64;
|
|
721
|
-
SpessaSynthInfo(
|
|
722
|
-
`%cRoland GS Master Key-Shift set to: %c${transpose}%c with: %c${arrayToHexString(
|
|
723
|
-
syx)}`,
|
|
724
|
-
consoleColors.info,
|
|
725
|
-
consoleColors.value,
|
|
726
|
-
consoleColors.info,
|
|
727
|
-
consoleColors.value
|
|
728
|
-
);
|
|
729
|
-
this.setMasterTuning(transpose * 100);
|
|
730
|
-
break;
|
|
731
|
-
}
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
|
-
else
|
|
735
|
-
// this is a global system parameter also
|
|
736
|
-
if (syx[5] === 0x01)
|
|
737
|
-
{
|
|
738
|
-
switch (syx[6])
|
|
739
|
-
{
|
|
740
|
-
default:
|
|
741
|
-
notRecognized();
|
|
742
|
-
break;
|
|
743
|
-
|
|
744
|
-
case 0x00:
|
|
745
|
-
// patch name. cool!
|
|
746
|
-
syx.currentIndex = 7;
|
|
747
|
-
const patchName = readBytesAsString(syx, 16);
|
|
748
|
-
SpessaSynthInfo(
|
|
749
|
-
`%cGS Patch name: %c${patchName}`,
|
|
750
|
-
consoleColors.info,
|
|
751
|
-
consoleColors.value
|
|
752
|
-
);
|
|
753
|
-
break;
|
|
754
|
-
|
|
755
|
-
case 0x33:
|
|
756
|
-
// reverb level
|
|
757
|
-
SpessaSynthInfo(
|
|
758
|
-
`%cGS Reverb level: %c${messageValue}`,
|
|
759
|
-
consoleColors.info, consoleColors.value
|
|
760
|
-
);
|
|
761
|
-
// 64 is the default
|
|
762
|
-
this.reverbSend = messageValue / 64;
|
|
763
|
-
break;
|
|
764
|
-
|
|
765
|
-
// unsupported reverb params
|
|
766
|
-
case 0x30:
|
|
767
|
-
case 0x31:
|
|
768
|
-
case 0x32:
|
|
769
|
-
case 0x34:
|
|
770
|
-
case 0x35:
|
|
771
|
-
case 0x37:
|
|
772
|
-
SpessaSynthInfo(
|
|
773
|
-
`%cUnsupported GS Reverb Parameter: %c${syx[6].toString(16)}`,
|
|
774
|
-
consoleColors.warn, consoleColors.unrecognized
|
|
775
|
-
);
|
|
776
|
-
break;
|
|
777
|
-
|
|
778
|
-
case 0x3A:
|
|
779
|
-
// chorus level
|
|
780
|
-
SpessaSynthInfo(
|
|
781
|
-
`%cGS Chorus level: %c${messageValue}`,
|
|
782
|
-
consoleColors.info, consoleColors.value
|
|
783
|
-
);
|
|
784
|
-
// 64 is the default
|
|
785
|
-
this.chorusSend = messageValue / 64;
|
|
786
|
-
break;
|
|
787
|
-
|
|
788
|
-
// unsupported chorus params
|
|
789
|
-
case 0x38:
|
|
790
|
-
case 0x39:
|
|
791
|
-
case 0x3B:
|
|
792
|
-
case 0x3C:
|
|
793
|
-
case 0x3D:
|
|
794
|
-
case 0x3E:
|
|
795
|
-
case 0x3F:
|
|
796
|
-
case 0x40:
|
|
797
|
-
SpessaSynthInfo(
|
|
798
|
-
`%cUnsupported GS Chorus Parameter: %c${syx[6].toString(16)}`,
|
|
799
|
-
consoleColors.warn, consoleColors.unrecognized
|
|
800
|
-
);
|
|
801
|
-
break;
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
else
|
|
806
|
-
{
|
|
807
|
-
// this is some other GS sysex...
|
|
808
|
-
notRecognized();
|
|
809
|
-
}
|
|
810
|
-
return;
|
|
811
|
-
}
|
|
812
|
-
else if (syx[2] === 0x45 && syx[3] === 0x12)
|
|
813
|
-
{
|
|
814
|
-
// 0x45: GS Display Data, 0x12: DT1 (Device Transmit)
|
|
815
|
-
// check for embedded copyright
|
|
816
|
-
// (roland SC display sysex) http://www.bandtrax.com.au/sysex.htm
|
|
817
|
-
|
|
818
|
-
if (
|
|
819
|
-
syx[4] === 0x10 && // Sound Canvas Display
|
|
820
|
-
syx[6] === 0x00 // Data follows
|
|
821
|
-
)
|
|
822
|
-
{
|
|
823
|
-
if (syx[5] === 0x00) // Display letters
|
|
824
|
-
{
|
|
825
|
-
// get the text
|
|
826
|
-
// and header ends with (checksum) F7
|
|
827
|
-
const text = new Uint8Array(syx.slice(7, syx.length - 2));
|
|
828
|
-
this.callEvent(
|
|
829
|
-
"synthdisplay",
|
|
830
|
-
{
|
|
831
|
-
displayData: text,
|
|
832
|
-
displayType: synthDisplayTypes.SoundCanvasText
|
|
833
|
-
}
|
|
834
|
-
);
|
|
835
|
-
}
|
|
836
|
-
else if (syx[5] === 0x01) // Matrix display
|
|
837
|
-
{
|
|
838
|
-
// get the data
|
|
839
|
-
// and header ends with (checksum) F7
|
|
840
|
-
const dotMatrixData = new Uint8Array(syx.slice(7, syx.length - 3));
|
|
841
|
-
this.callEvent(
|
|
842
|
-
"synthdisplay",
|
|
843
|
-
{
|
|
844
|
-
displayData: dotMatrixData,
|
|
845
|
-
displayType: synthDisplayTypes.SoundCanvasDotDisplay
|
|
846
|
-
}
|
|
847
|
-
);
|
|
848
|
-
SpessaSynthInfo(
|
|
849
|
-
`%cRoland SC Display Dot Matrix via: %c${arrayToHexString(
|
|
850
|
-
syx)}`,
|
|
851
|
-
consoleColors.info,
|
|
852
|
-
consoleColors.value
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
else
|
|
856
|
-
{
|
|
857
|
-
// this is some other GS sysex...
|
|
858
|
-
notRecognized();
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
else if (syx[2] === 0x16 && syx[3] === 0x12 && syx[4] === 0x10)
|
|
863
|
-
{
|
|
864
|
-
// this is a roland master volume message
|
|
865
|
-
this.setMIDIVolume(syx[7] / 100);
|
|
866
|
-
SpessaSynthInfo(
|
|
867
|
-
`%cRoland Master Volume control set to: %c${syx[7]}%c via: %c${arrayToHexString(
|
|
868
|
-
syx)}`,
|
|
869
|
-
consoleColors.info,
|
|
870
|
-
consoleColors.value,
|
|
871
|
-
consoleColors.info,
|
|
872
|
-
consoleColors.value
|
|
873
|
-
);
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
else
|
|
877
|
-
{
|
|
878
|
-
// this is something else...
|
|
879
|
-
SpessaSynthWarn(
|
|
880
|
-
`%cUnrecognized Roland SysEx: %c${arrayToHexString(syx)}`,
|
|
881
|
-
consoleColors.warn,
|
|
882
|
-
consoleColors.unrecognized
|
|
883
|
-
);
|
|
884
|
-
return;
|
|
885
|
-
}
|
|
886
|
-
break;
|
|
887
|
-
|
|
888
|
-
// yamaha
|
|
889
|
-
// http://www.studio4all.de/htmle/main91.html
|
|
890
|
-
case 0x43:
|
|
891
|
-
// XG sysex
|
|
892
|
-
if (syx[2] === 0x4C)
|
|
893
|
-
{
|
|
894
|
-
// XG system parameter
|
|
895
|
-
if (syx[3] === 0x00 && syx[4] === 0x00)
|
|
896
|
-
{
|
|
897
|
-
switch (syx[5])
|
|
898
|
-
{
|
|
899
|
-
// master volume
|
|
900
|
-
case 0x04:
|
|
901
|
-
const vol = syx[6];
|
|
902
|
-
this.setMIDIVolume(vol / 127);
|
|
903
|
-
SpessaSynthInfo(
|
|
904
|
-
`%cXG master volume. Volume: %c${vol}`,
|
|
905
|
-
consoleColors.info,
|
|
906
|
-
consoleColors.recognized
|
|
907
|
-
);
|
|
908
|
-
break;
|
|
909
|
-
|
|
910
|
-
// master transpose
|
|
911
|
-
case 0x06:
|
|
912
|
-
const transpose = syx[6] - 64;
|
|
913
|
-
this.transposeAllChannels(transpose);
|
|
914
|
-
SpessaSynthInfo(
|
|
915
|
-
`%cXG master transpose. Volume: %c${transpose}`,
|
|
916
|
-
consoleColors.info,
|
|
917
|
-
consoleColors.recognized
|
|
918
|
-
);
|
|
919
|
-
break;
|
|
920
|
-
|
|
921
|
-
// XG on
|
|
922
|
-
case 0x7E:
|
|
923
|
-
SpessaSynthInfo("%cXG system on", consoleColors.info);
|
|
924
|
-
this.resetAllControllers(false);
|
|
925
|
-
this.setSystem("xg");
|
|
926
|
-
break;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
else
|
|
930
|
-
// XG part parameter
|
|
931
|
-
if (syx[3] === 0x08)
|
|
932
|
-
{
|
|
933
|
-
if (!isSystemXG(this.system))
|
|
934
|
-
{
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
const channel = syx[4] + channelOffset;
|
|
938
|
-
if (channel >= this.midiAudioChannels.length)
|
|
939
|
-
{
|
|
940
|
-
// invalid channel
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
const channelObject = this.midiAudioChannels[channel];
|
|
944
|
-
const value = syx[6];
|
|
945
|
-
switch (syx[5])
|
|
946
|
-
{
|
|
947
|
-
// bank-select MSB
|
|
948
|
-
case 0x01:
|
|
949
|
-
channelObject.controllerChange(midiControllers.bankSelect, value);
|
|
950
|
-
break;
|
|
951
|
-
|
|
952
|
-
// bank-select LSB
|
|
953
|
-
case 0x02:
|
|
954
|
-
channelObject.controllerChange(midiControllers.lsbForControl0BankSelect, value);
|
|
955
|
-
break;
|
|
956
|
-
|
|
957
|
-
// program change
|
|
958
|
-
case 0x03:
|
|
959
|
-
channelObject.programChange(value);
|
|
960
|
-
break;
|
|
961
|
-
|
|
962
|
-
// note shift
|
|
963
|
-
case 0x08:
|
|
964
|
-
if (channelObject.drumChannel)
|
|
965
|
-
{
|
|
966
|
-
return;
|
|
967
|
-
}
|
|
968
|
-
const semitones = value - 64;
|
|
969
|
-
channelObject.channelTransposeKeyShift = semitones;
|
|
970
|
-
break;
|
|
971
|
-
|
|
972
|
-
// volume
|
|
973
|
-
case 0x0B:
|
|
974
|
-
channelObject.controllerChange(midiControllers.mainVolume, value);
|
|
975
|
-
break;
|
|
976
|
-
|
|
977
|
-
// pan position
|
|
978
|
-
case 0x0E:
|
|
979
|
-
let pan = value;
|
|
980
|
-
if (pan === 0)
|
|
981
|
-
{
|
|
982
|
-
// 0 means random
|
|
983
|
-
channelObject.randomPan = true;
|
|
984
|
-
SpessaSynthInfo(
|
|
985
|
-
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
986
|
-
consoleColors.info,
|
|
987
|
-
consoleColors.recognized,
|
|
988
|
-
consoleColors.info,
|
|
989
|
-
consoleColors.value
|
|
990
|
-
);
|
|
991
|
-
}
|
|
992
|
-
else
|
|
993
|
-
{
|
|
994
|
-
channelObject.controllerChange(midiControllers.pan, pan);
|
|
995
|
-
}
|
|
996
|
-
break;
|
|
997
|
-
|
|
998
|
-
// reverb
|
|
999
|
-
case 0x13:
|
|
1000
|
-
channelObject.controllerChange(midiControllers.reverbDepth, value);
|
|
1001
|
-
break;
|
|
1002
|
-
|
|
1003
|
-
// chorus
|
|
1004
|
-
case 0x12:
|
|
1005
|
-
channelObject.controllerChange(midiControllers.chorusDepth, value);
|
|
1006
|
-
break;
|
|
1007
|
-
|
|
1008
|
-
default:
|
|
1009
|
-
SpessaSynthWarn(
|
|
1010
|
-
`%cUnrecognized Yamaha XG Part Setup: %c${syx[5].toString(16)
|
|
1011
|
-
.toUpperCase()}`,
|
|
1012
|
-
consoleColors.warn,
|
|
1013
|
-
consoleColors.unrecognized
|
|
1014
|
-
);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
else if (
|
|
1018
|
-
syx[3] === 0x06 && // XG System parameter
|
|
1019
|
-
syx[4] === 0x00 // System Byte
|
|
1020
|
-
)
|
|
1021
|
-
{
|
|
1022
|
-
// displayed letters (remove F7 at the end)
|
|
1023
|
-
// include byte 5 as it seems to be line information (useful)
|
|
1024
|
-
const textData = new Uint8Array(syx.slice(5, syx.length - 1));
|
|
1025
|
-
this.callEvent(
|
|
1026
|
-
"synthdisplay",
|
|
1027
|
-
{
|
|
1028
|
-
displayData: textData,
|
|
1029
|
-
displayType: synthDisplayTypes.XGText
|
|
1030
|
-
}
|
|
1031
|
-
);
|
|
1032
|
-
}
|
|
1033
|
-
else if (isSystemXG(this.system))
|
|
1034
|
-
{
|
|
1035
|
-
SpessaSynthWarn(
|
|
1036
|
-
`%cUnrecognized Yamaha XG SysEx: %c${arrayToHexString(syx)}`,
|
|
1037
|
-
consoleColors.warn,
|
|
1038
|
-
consoleColors.unrecognized
|
|
1039
|
-
);
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
}
|
|
1043
|
-
else
|
|
1044
|
-
{
|
|
1045
|
-
if (isSystemXG(this.system))
|
|
1046
|
-
{
|
|
1047
|
-
SpessaSynthWarn(
|
|
1048
|
-
`%cUnrecognized Yamaha SysEx: %c${arrayToHexString(syx)}`,
|
|
1049
|
-
consoleColors.warn,
|
|
1050
|
-
consoleColors.unrecognized
|
|
1051
|
-
);
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
break;
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1058
|
-
}
|