1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include "fluid_synth.h"
22 #include "fluid_sys.h"
23 #include "fluid_chan.h"
24 #include "fluid_tuning.h"
25 #include "fluid_settings.h"
26 #include "fluid_sfont.h"
27 #include "fluid_defsfont.h"
33 /* seems to not be declared in fenv.h */
34 extern int feenableexcept(int excepts);
37 #define FLUID_API_RETURN(return_value) \
38 do { fluid_synth_api_exit(synth); \
39 return return_value; } while (0)
41 #define FLUID_API_RETURN_IF_CHAN_DISABLED(return_value) \
42 do { if (FLUID_LIKELY(synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)) \
45 { FLUID_API_RETURN(return_value); } \
48 #define FLUID_API_ENTRY_CHAN(fail_value) \
49 fluid_return_val_if_fail (synth != NULL, fail_value); \
50 fluid_return_val_if_fail (chan >= 0, fail_value); \
51 fluid_synth_api_enter(synth); \
52 if (chan >= synth->midi_channels) { \
53 FLUID_API_RETURN(fail_value); \
56 static void fluid_synth_init(void);
57 static void fluid_synth_api_enter(fluid_synth_t *synth);
58 static void fluid_synth_api_exit(fluid_synth_t *synth);
60 static int fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key,
62 static int fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key);
63 static int fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num);
64 static int fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data,
65 int len, char *response,
66 int *response_len, int avail_response,
67 int *handled, int dryrun);
68 int fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan);
69 static int fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan);
70 static int fluid_synth_system_reset_LOCAL(fluid_synth_t *synth);
71 static int fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan,
73 static int fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan);
74 static int fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int channum);
75 static int fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key);
76 static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan);
77 static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan);
78 static int fluid_synth_set_preset(fluid_synth_t *synth, int chan,
79 fluid_preset_t *preset);
80 static fluid_preset_t *
81 fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
82 int banknum, int prognum);
83 static fluid_preset_t *
84 fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname,
85 int banknum, int prognum);
87 static void fluid_synth_update_presets(fluid_synth_t *synth);
88 static void fluid_synth_update_gain_LOCAL(fluid_synth_t *synth);
89 static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony);
90 static void init_dither(void);
91 static FLUID_INLINE int16_t round_clip_to_i16(float x);
92 static int fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount);
94 static fluid_voice_t *fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth);
95 static void fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
96 fluid_voice_t *new_voice);
97 static int fluid_synth_sfunload_callback(void *data, unsigned int msec);
98 static fluid_tuning_t *fluid_synth_get_tuning(fluid_synth_t *synth,
100 static int fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth,
101 fluid_tuning_t *tuning,
102 int bank, int prog, int apply);
103 static void fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth,
104 fluid_tuning_t *old_tuning,
105 fluid_tuning_t *new_tuning,
106 int apply, int unref_new);
107 static void fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth,
108 fluid_channel_t *channel);
109 static int fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
110 fluid_tuning_t *tuning, int apply);
111 static void fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan,
112 int param, float value, int absolute);
113 static void fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id);
116 static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels);
119 /* Callback handlers for real-time settings */
120 static void fluid_synth_handle_sample_rate(void *data, const char *name, double value);
121 static void fluid_synth_handle_gain(void *data, const char *name, double value);
122 static void fluid_synth_handle_polyphony(void *data, const char *name, int value);
123 static void fluid_synth_handle_device_id(void *data, const char *name, int value);
124 static void fluid_synth_handle_overflow(void *data, const char *name, double value);
125 static void fluid_synth_handle_important_channels(void *data, const char *name,
127 static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value);
128 static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value);
131 static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan);
132 static int fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val);
133 static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val);
134 static int fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize,
135 double damping, double width, double level);
137 static int fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level,
138 double speed, double depth_ms, int type);
140 /***************************************************************
145 /* has the synth module been initialized? */
146 /* fluid_atomic_int_t may be anything, so init with {0} to catch most cases */
147 static fluid_atomic_int_t fluid_synth_initialized = {0};
149 /* default modulators
152 * There is a set of predefined default modulators. They have to be
153 * explicitly overridden by the sound font in order to turn them off.
156 static fluid_mod_t default_vel2att_mod; /* SF2.01 section 8.4.1 */
157 /*not static */ fluid_mod_t default_vel2filter_mod; /* SF2.01 section 8.4.2 */
158 static fluid_mod_t default_at2viblfo_mod; /* SF2.01 section 8.4.3 */
159 static fluid_mod_t default_mod2viblfo_mod; /* SF2.01 section 8.4.4 */
160 static fluid_mod_t default_att_mod; /* SF2.01 section 8.4.5 */
161 static fluid_mod_t default_pan_mod; /* SF2.01 section 8.4.6 */
162 static fluid_mod_t default_expr_mod; /* SF2.01 section 8.4.7 */
163 static fluid_mod_t default_reverb_mod; /* SF2.01 section 8.4.8 */
164 static fluid_mod_t default_chorus_mod; /* SF2.01 section 8.4.9 */
165 static fluid_mod_t default_pitch_bend_mod; /* SF2.01 section 8.4.10 */
166 static fluid_mod_t custom_balance_mod; /* Non-standard modulator */
169 /* custom_breath2att_modulator is not a default modulator specified in SF
170 it is intended to replace default_vel2att_mod on demand using
171 API fluid_set_breath_mode() or command shell setbreathmode.
173 static fluid_mod_t custom_breath2att_mod;
176 static const fluid_revmodel_presets_t revmodel_preset[] =
178 /* name */ /* roomsize */ /* damp */ /* width */ /* level */
179 { "Test 1", 0.2f, 0.0f, 0.5f, 0.9f },
180 { "Test 2", 0.4f, 0.2f, 0.5f, 0.8f },
181 { "Test 3", 0.6f, 0.4f, 0.5f, 0.7f },
182 { "Test 4", 0.8f, 0.7f, 0.5f, 0.6f },
183 { "Test 5", 0.8f, 1.0f, 0.5f, 0.5f },
187 /***************************************************************
189 * INITIALIZATION & UTILITIES
192 void fluid_synth_settings(fluid_settings_t *settings)
194 fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1, FLUID_HINT_TOGGLED);
196 fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1, FLUID_HINT_TOGGLED);
197 fluid_settings_register_num(settings, "synth.reverb.room-size", FLUID_REVERB_DEFAULT_ROOMSIZE, 0.0f, 1.0f, 0);
198 fluid_settings_register_num(settings, "synth.reverb.damp", FLUID_REVERB_DEFAULT_DAMP, 0.0f, 1.0f, 0);
199 fluid_settings_register_num(settings, "synth.reverb.width", FLUID_REVERB_DEFAULT_WIDTH, 0.0f, 100.0f, 0);
200 fluid_settings_register_num(settings, "synth.reverb.level", FLUID_REVERB_DEFAULT_LEVEL, 0.0f, 1.0f, 0);
202 fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1, FLUID_HINT_TOGGLED);
203 fluid_settings_register_int(settings, "synth.chorus.nr", FLUID_CHORUS_DEFAULT_N, 0, 99, 0);
204 fluid_settings_register_num(settings, "synth.chorus.level", FLUID_CHORUS_DEFAULT_LEVEL, 0.0f, 10.0f, 0);
205 fluid_settings_register_num(settings, "synth.chorus.speed", FLUID_CHORUS_DEFAULT_SPEED, 0.29f, 5.0f, 0);
206 fluid_settings_register_num(settings, "synth.chorus.depth", FLUID_CHORUS_DEFAULT_DEPTH, 0.0f, 256.0f, 0);
208 fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, FLUID_HINT_TOGGLED);
209 fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1, FLUID_HINT_TOGGLED);
210 fluid_settings_register_str(settings, "midi.portname", "", 0);
212 #ifdef DEFAULT_SOUNDFONT
213 fluid_settings_register_str(settings, "synth.default-soundfont", DEFAULT_SOUNDFONT, 0);
216 fluid_settings_register_int(settings, "synth.polyphony", 256, 1, 65535, 0);
217 fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0);
218 fluid_settings_register_num(settings, "synth.gain", 0.2f, 0.0f, 10.0f, 0);
219 fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 128, 0);
220 fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 128, 0);
221 fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0);
222 fluid_settings_register_int(settings, "synth.effects-groups", 1, 1, 128, 0);
223 fluid_settings_register_num(settings, "synth.sample-rate", 44100.0f, 8000.0f, 96000.0f, 0);
224 fluid_settings_register_int(settings, "synth.device-id", 0, 0, 126, 0);
225 #ifdef ENABLE_MIXER_THREADS
226 fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0);
228 fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 1, 0);
231 fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0);
233 fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1, FLUID_HINT_TOGGLED);
235 fluid_settings_register_num(settings, "synth.overflow.percussion", 4000, -10000, 10000, 0);
236 fluid_settings_register_num(settings, "synth.overflow.sustained", -1000, -10000, 10000, 0);
237 fluid_settings_register_num(settings, "synth.overflow.released", -2000, -10000, 10000, 0);
238 fluid_settings_register_num(settings, "synth.overflow.age", 1000, -10000, 10000, 0);
239 fluid_settings_register_num(settings, "synth.overflow.volume", 500, -10000, 10000, 0);
240 fluid_settings_register_num(settings, "synth.overflow.important", 5000, -50000, 50000, 0);
241 fluid_settings_register_str(settings, "synth.overflow.important-channels", "", 0);
243 fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0);
244 fluid_settings_add_option(settings, "synth.midi-bank-select", "gm");
245 fluid_settings_add_option(settings, "synth.midi-bank-select", "gs");
246 fluid_settings_add_option(settings, "synth.midi-bank-select", "xg");
247 fluid_settings_add_option(settings, "synth.midi-bank-select", "mma");
249 fluid_settings_register_int(settings, "synth.dynamic-sample-loading", 0, 0, 1, FLUID_HINT_TOGGLED);
253 * Get FluidSynth runtime version.
254 * @param major Location to store major number
255 * @param minor Location to store minor number
256 * @param micro Location to store micro number
258 void fluid_version(int *major, int *minor, int *micro)
260 *major = FLUIDSYNTH_VERSION_MAJOR;
261 *minor = FLUIDSYNTH_VERSION_MINOR;
262 *micro = FLUIDSYNTH_VERSION_MICRO;
266 * Get FluidSynth runtime version as a string.
267 * @return FluidSynth version string, which is internal and should not be
271 fluid_version_str(void)
273 return FLUIDSYNTH_VERSION;
277 * void fluid_synth_init
279 * Does all the initialization for this module.
282 fluid_synth_init(void)
285 /* Turn on floating point exception traps */
286 feenableexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID);
291 /* custom_breath2att_mod is not a default modulator specified in SF2.01.
292 it is intended to replace default_vel2att_mod on demand using
293 API fluid_set_breath_mode() or command shell setbreathmode.
295 fluid_mod_set_source1(&custom_breath2att_mod, /* The modulator we are programming here */
296 BREATH_MSB, /* Source. breath MSB corresponds to 2. */
297 FLUID_MOD_CC /* MIDI continuous controller */
298 | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */
299 | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */
300 | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */
302 fluid_mod_set_source2(&custom_breath2att_mod, 0, 0); /* No 2nd source */
303 fluid_mod_set_dest(&custom_breath2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
304 fluid_mod_set_amount(&custom_breath2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */
306 /* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */
307 fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */
308 FLUID_MOD_VELOCITY, /* Source. VELOCITY corresponds to 'index=2'. */
309 FLUID_MOD_GC /* Not a MIDI continuous controller */
310 | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */
311 | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */
312 | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */
314 fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */
315 fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
316 fluid_mod_set_amount(&default_vel2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */
320 /* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff
321 * Have to make a design decision here. The specs don't make any sense this way or another.
322 * One sound font, 'Kingston Piano', which has been praised for its quality, tries to
323 * override this modulator with an amount of 0 and positive polarity (instead of what
324 * the specs say, D=1) for the secondary source.
325 * So if we change the polarity to 'positive', one of the best free sound fonts works...
327 fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
328 FLUID_MOD_GC /* CC=0 */
329 | FLUID_MOD_LINEAR /* type=0 */
330 | FLUID_MOD_UNIPOLAR /* P=0 */
331 | FLUID_MOD_NEGATIVE /* D=1 */
333 fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
334 FLUID_MOD_GC /* CC=0 */
335 | FLUID_MOD_SWITCH /* type=3 */
336 | FLUID_MOD_UNIPOLAR /* P=0 */
337 // do not remove | FLUID_MOD_NEGATIVE /* D=1 */
338 | FLUID_MOD_POSITIVE /* D=0 */
340 fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC); /* Target: Initial filter cutoff */
341 fluid_mod_set_amount(&default_vel2filter_mod, -2400);
345 /* SF2.01 page 53 section 8.4.3: MIDI Channel pressure to Vibrato LFO pitch depth */
346 fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE, /* Index=13 */
347 FLUID_MOD_GC /* CC=0 */
348 | FLUID_MOD_LINEAR /* type=0 */
349 | FLUID_MOD_UNIPOLAR /* P=0 */
350 | FLUID_MOD_POSITIVE /* D=0 */
352 fluid_mod_set_source2(&default_at2viblfo_mod, 0, 0); /* no second source */
353 fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */
354 fluid_mod_set_amount(&default_at2viblfo_mod, 50);
358 /* SF2.01 page 53 section 8.4.4: Mod wheel (Controller 1) to Vibrato LFO pitch depth */
359 fluid_mod_set_source1(&default_mod2viblfo_mod, MODULATION_MSB, /* Index=1 */
360 FLUID_MOD_CC /* CC=1 */
361 | FLUID_MOD_LINEAR /* type=0 */
362 | FLUID_MOD_UNIPOLAR /* P=0 */
363 | FLUID_MOD_POSITIVE /* D=0 */
365 fluid_mod_set_source2(&default_mod2viblfo_mod, 0, 0); /* no second source */
366 fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */
367 fluid_mod_set_amount(&default_mod2viblfo_mod, 50);
371 /* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/
372 fluid_mod_set_source1(&default_att_mod, VOLUME_MSB, /* index=7 */
373 FLUID_MOD_CC /* CC=1 */
374 | FLUID_MOD_CONCAVE /* type=1 */
375 | FLUID_MOD_UNIPOLAR /* P=0 */
376 | FLUID_MOD_NEGATIVE /* D=1 */
378 fluid_mod_set_source2(&default_att_mod, 0, 0); /* No second source */
379 fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
380 fluid_mod_set_amount(&default_att_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
384 /* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */
385 fluid_mod_set_source1(&default_pan_mod, PAN_MSB, /* index=10 */
386 FLUID_MOD_CC /* CC=1 */
387 | FLUID_MOD_LINEAR /* type=0 */
388 | FLUID_MOD_BIPOLAR /* P=1 */
389 | FLUID_MOD_POSITIVE /* D=0 */
391 fluid_mod_set_source2(&default_pan_mod, 0, 0); /* No second source */
392 fluid_mod_set_dest(&default_pan_mod, GEN_PAN); /* Target: pan */
393 /* Amount: 500. The SF specs $8.4.6, p. 55 syas: "Amount = 1000
394 tenths of a percent". The center value (64) corresponds to 50%,
395 so it follows that amount = 50% x 1000/% = 500. */
396 fluid_mod_set_amount(&default_pan_mod, 500.0);
399 /* SF2.01 page 55 section 8.4.7: MIDI continuous controller 11 to initial attenuation*/
400 fluid_mod_set_source1(&default_expr_mod, EXPRESSION_MSB, /* index=11 */
401 FLUID_MOD_CC /* CC=1 */
402 | FLUID_MOD_CONCAVE /* type=1 */
403 | FLUID_MOD_UNIPOLAR /* P=0 */
404 | FLUID_MOD_NEGATIVE /* D=1 */
406 fluid_mod_set_source2(&default_expr_mod, 0, 0); /* No second source */
407 fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
408 fluid_mod_set_amount(&default_expr_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
412 /* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */
413 fluid_mod_set_source1(&default_reverb_mod, EFFECTS_DEPTH1, /* index=91 */
414 FLUID_MOD_CC /* CC=1 */
415 | FLUID_MOD_LINEAR /* type=0 */
416 | FLUID_MOD_UNIPOLAR /* P=0 */
417 | FLUID_MOD_POSITIVE /* D=0 */
419 fluid_mod_set_source2(&default_reverb_mod, 0, 0); /* No second source */
420 fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND); /* Target: Reverb send */
421 fluid_mod_set_amount(&default_reverb_mod, 200); /* Amount: 200 ('tenths of a percent') */
425 /* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Chorus send */
426 fluid_mod_set_source1(&default_chorus_mod, EFFECTS_DEPTH3, /* index=93 */
427 FLUID_MOD_CC /* CC=1 */
428 | FLUID_MOD_LINEAR /* type=0 */
429 | FLUID_MOD_UNIPOLAR /* P=0 */
430 | FLUID_MOD_POSITIVE /* D=0 */
432 fluid_mod_set_source2(&default_chorus_mod, 0, 0); /* No second source */
433 fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND); /* Target: Chorus */
434 fluid_mod_set_amount(&default_chorus_mod, 200); /* Amount: 200 ('tenths of a percent') */
438 /* SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch ... */
439 fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL, /* Index=14 */
440 FLUID_MOD_GC /* CC =0 */
441 | FLUID_MOD_LINEAR /* type=0 */
442 | FLUID_MOD_BIPOLAR /* P=1 */
443 | FLUID_MOD_POSITIVE /* D=0 */
445 fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS, /* Index = 16 */
446 FLUID_MOD_GC /* CC=0 */
447 | FLUID_MOD_LINEAR /* type=0 */
448 | FLUID_MOD_UNIPOLAR /* P=0 */
449 | FLUID_MOD_POSITIVE /* D=0 */
451 fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH); /* Destination: Initial pitch */
452 fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */
455 /* Non-standard MIDI continuous controller 8 to channel stereo balance */
456 fluid_mod_set_source1(&custom_balance_mod, BALANCE_MSB, /* Index=8 */
457 FLUID_MOD_CC /* CC=1 */
458 | FLUID_MOD_CONCAVE /* type=1 */
459 | FLUID_MOD_BIPOLAR /* P=1 */
460 | FLUID_MOD_POSITIVE /* D=0 */
462 fluid_mod_set_source2(&custom_balance_mod, 0, 0);
463 fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */
464 /* Amount: 96 dB of attenuation (on the opposite channel) */
465 fluid_mod_set_amount(&custom_balance_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
468 static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t *synth)
470 return fluid_atomic_int_get(&synth->ticks_since_start);
473 static FLUID_INLINE void fluid_synth_add_ticks(fluid_synth_t *synth, int val)
475 fluid_atomic_int_add(&synth->ticks_since_start, val);
479 /***************************************************************
480 * FLUID SAMPLE TIMERS
481 * Timers that use written audio data as timing reference
483 struct _fluid_sample_timer_t
485 fluid_sample_timer_t *next; /* Single linked list of timers */
486 unsigned long starttick;
487 fluid_timer_callback_t callback;
493 * fluid_sample_timer_process - called when synth->ticks is updated
495 static void fluid_sample_timer_process(fluid_synth_t *synth)
497 fluid_sample_timer_t *st, *stnext;
500 unsigned int ticks = fluid_synth_get_ticks(synth);
502 for(st = synth->sample_timers; st; st = stnext)
504 /* st may be freed in the callback below. cache it's successor now to avoid use after free */
512 msec = (long)(1000.0 * ((double)(ticks - st->starttick)) / synth->sample_rate);
513 cont = (*st->callback)(st->data, msec);
522 fluid_sample_timer_t *new_fluid_sample_timer(fluid_synth_t *synth, fluid_timer_callback_t callback, void *data)
524 fluid_sample_timer_t *result = FLUID_NEW(fluid_sample_timer_t);
528 FLUID_LOG(FLUID_ERR, "Out of memory");
532 result->starttick = fluid_synth_get_ticks(synth);
533 result->isfinished = 0;
535 result->callback = callback;
536 result->next = synth->sample_timers;
537 synth->sample_timers = result;
541 void delete_fluid_sample_timer(fluid_synth_t *synth, fluid_sample_timer_t *timer)
543 fluid_sample_timer_t **ptr;
544 fluid_return_if_fail(synth != NULL);
545 fluid_return_if_fail(timer != NULL);
547 ptr = &synth->sample_timers;
558 ptr = &((*ptr)->next);
563 /***************************************************************
568 static FLUID_INLINE void
569 fluid_synth_update_mixer(fluid_synth_t *synth, fluid_rvoice_function_t method, int intparam,
570 fluid_real_t realparam)
572 fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL);
573 fluid_return_if_fail(synth->eventhandler->mixer != NULL);
574 fluid_rvoice_eventhandler_push_int_real(synth->eventhandler, method,
575 synth->eventhandler->mixer,
576 intparam, realparam);
579 static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_synth_t *synth)
582 fluid_settings_getint(synth->settings, "synth.min-note-length", &i);
583 return (unsigned int)(i * synth->sample_rate / 1000.0f);
587 * Create new FluidSynth instance.
588 * @param settings Configuration parameters to use (used directly).
589 * @return New FluidSynth instance or NULL on error
591 * @note The settings parameter is used directly and should not be modified
592 * or freed independently.
595 new_fluid_synth(fluid_settings_t *settings)
597 fluid_synth_t *synth;
598 fluid_sfloader_t *loader;
599 char *important_channels;
600 int i, nbuf, prio_level = 0;
603 /* initialize all the conversion tables and other stuff */
604 if(fluid_atomic_int_compare_and_exchange(&fluid_synth_initialized, 0, 1))
609 /* allocate a new synthesizer object */
610 synth = FLUID_NEW(fluid_synth_t);
614 FLUID_LOG(FLUID_ERR, "Out of memory");
618 FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t));
620 fluid_rec_mutex_init(synth->mutex);
621 fluid_settings_getint(settings, "synth.threadsafe-api", &synth->use_mutex);
622 synth->public_api_count = 0;
624 synth->settings = settings;
626 fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb);
627 fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus);
628 fluid_settings_getint(settings, "synth.verbose", &synth->verbose);
630 fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
631 fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate);
632 fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels);
633 fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
634 fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups);
635 fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
636 fluid_settings_getint(settings, "synth.effects-groups", &synth->effects_groups);
637 fluid_settings_getnum_float(settings, "synth.gain", &synth->gain);
638 fluid_settings_getint(settings, "synth.device-id", &synth->device_id);
639 fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores);
641 fluid_settings_getnum_float(settings, "synth.overflow.percussion", &synth->overflow.percussion);
642 fluid_settings_getnum_float(settings, "synth.overflow.released", &synth->overflow.released);
643 fluid_settings_getnum_float(settings, "synth.overflow.sustained", &synth->overflow.sustained);
644 fluid_settings_getnum_float(settings, "synth.overflow.volume", &synth->overflow.volume);
645 fluid_settings_getnum_float(settings, "synth.overflow.age", &synth->overflow.age);
646 fluid_settings_getnum_float(settings, "synth.overflow.important", &synth->overflow.important);
648 /* register the callbacks */
649 fluid_settings_callback_num(settings, "synth.sample-rate",
650 fluid_synth_handle_sample_rate, synth);
651 fluid_settings_callback_num(settings, "synth.gain",
652 fluid_synth_handle_gain, synth);
653 fluid_settings_callback_int(settings, "synth.polyphony",
654 fluid_synth_handle_polyphony, synth);
655 fluid_settings_callback_int(settings, "synth.device-id",
656 fluid_synth_handle_device_id, synth);
657 fluid_settings_callback_num(settings, "synth.overflow.percussion",
658 fluid_synth_handle_overflow, synth);
659 fluid_settings_callback_num(settings, "synth.overflow.sustained",
660 fluid_synth_handle_overflow, synth);
661 fluid_settings_callback_num(settings, "synth.overflow.released",
662 fluid_synth_handle_overflow, synth);
663 fluid_settings_callback_num(settings, "synth.overflow.age",
664 fluid_synth_handle_overflow, synth);
665 fluid_settings_callback_num(settings, "synth.overflow.volume",
666 fluid_synth_handle_overflow, synth);
667 fluid_settings_callback_num(settings, "synth.overflow.important",
668 fluid_synth_handle_overflow, synth);
669 fluid_settings_callback_str(settings, "synth.overflow.important-channels",
670 fluid_synth_handle_important_channels, synth);
671 fluid_settings_callback_num(settings, "synth.reverb.room-size",
672 fluid_synth_handle_reverb_chorus_num, synth);
673 fluid_settings_callback_num(settings, "synth.reverb.damp",
674 fluid_synth_handle_reverb_chorus_num, synth);
675 fluid_settings_callback_num(settings, "synth.reverb.width",
676 fluid_synth_handle_reverb_chorus_num, synth);
677 fluid_settings_callback_num(settings, "synth.reverb.level",
678 fluid_synth_handle_reverb_chorus_num, synth);
679 fluid_settings_callback_int(settings, "synth.reverb.active",
680 fluid_synth_handle_reverb_chorus_int, synth);
681 fluid_settings_callback_int(settings, "synth.chorus.active",
682 fluid_synth_handle_reverb_chorus_int, synth);
683 fluid_settings_callback_int(settings, "synth.chorus.nr",
684 fluid_synth_handle_reverb_chorus_int, synth);
685 fluid_settings_callback_num(settings, "synth.chorus.level",
686 fluid_synth_handle_reverb_chorus_num, synth);
687 fluid_settings_callback_num(settings, "synth.chorus.depth",
688 fluid_synth_handle_reverb_chorus_num, synth);
689 fluid_settings_callback_num(settings, "synth.chorus.speed",
690 fluid_synth_handle_reverb_chorus_num, synth);
692 /* do some basic sanity checking on the settings */
694 if(synth->midi_channels % 16 != 0)
696 int n = synth->midi_channels / 16;
697 synth->midi_channels = (n + 1) * 16;
698 fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels);
699 FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. "
700 "I'll increase the number of channels to the next multiple.");
703 if(synth->audio_channels < 1)
705 FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. "
706 "Changing this setting to 1.");
707 synth->audio_channels = 1;
709 else if(synth->audio_channels > 128)
711 FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). "
712 "Limiting this setting to 128.", synth->audio_channels);
713 synth->audio_channels = 128;
716 if(synth->audio_groups < 1)
718 FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. "
719 "Changing this setting to 1.");
720 synth->audio_groups = 1;
722 else if(synth->audio_groups > 128)
724 FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). "
725 "Limiting this setting to 128.", synth->audio_groups);
726 synth->audio_groups = 128;
729 if(synth->effects_channels < 2)
731 FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)."
732 "Setting effects channels to 2.", synth->effects_channels);
733 synth->effects_channels = 2;
736 /* The number of buffers is determined by the higher number of nr
737 * groups / nr audio channels. If LADSPA is unused, they should be
739 nbuf = synth->audio_channels;
741 if(synth->audio_groups > nbuf)
743 nbuf = synth->audio_groups;
746 if(fluid_settings_dupstr(settings, "synth.overflow.important-channels",
747 &important_channels) == FLUID_OK)
749 if(fluid_synth_set_important_channels(synth, important_channels) != FLUID_OK)
751 FLUID_LOG(FLUID_WARN, "Failed to set overflow important channels");
754 FLUID_FREE(important_channels);
757 /* as soon as the synth is created it starts playing. */
758 synth->state = FLUID_SYNTH_PLAYING;
760 synth->fromkey_portamento = INVALID_NOTE; /* disable portamento */
762 fluid_atomic_int_set(&synth->ticks_since_start, 0);
763 synth->tuning = NULL;
764 fluid_private_init(synth->tuning_iter);
766 /* Initialize multi-core variables if multiple cores enabled */
769 fluid_settings_getint(synth->settings, "audio.realtime-prio", &prio_level);
772 /* Allocate event queue for rvoice mixer */
773 /* In an overflow situation, a new voice takes about 50 spaces in the queue! */
774 synth->eventhandler = new_fluid_rvoice_eventhandler(synth->polyphony * 64,
775 synth->polyphony, nbuf, synth->effects_channels, synth->effects_groups, synth->sample_rate, synth->cores - 1, prio_level);
777 if(synth->eventhandler == NULL)
782 /* Setup the list of default modulators.
783 * Needs to happen after eventhandler has been set up, as fluid_synth_enter_api is called in the process */
784 synth->default_mod = NULL;
785 fluid_synth_add_default_mod(synth, &default_vel2att_mod, FLUID_SYNTH_ADD);
786 fluid_synth_add_default_mod(synth, &default_vel2filter_mod, FLUID_SYNTH_ADD);
787 fluid_synth_add_default_mod(synth, &default_at2viblfo_mod, FLUID_SYNTH_ADD);
788 fluid_synth_add_default_mod(synth, &default_mod2viblfo_mod, FLUID_SYNTH_ADD);
789 fluid_synth_add_default_mod(synth, &default_att_mod, FLUID_SYNTH_ADD);
790 fluid_synth_add_default_mod(synth, &default_pan_mod, FLUID_SYNTH_ADD);
791 fluid_synth_add_default_mod(synth, &default_expr_mod, FLUID_SYNTH_ADD);
792 fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD);
793 fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD);
794 fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD);
795 fluid_synth_add_default_mod(synth, &custom_balance_mod, FLUID_SYNTH_ADD);
797 /* Create and initialize the Fx unit.*/
798 fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);
803 synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate,
804 FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE);
806 if(synth->ladspa_fx == NULL)
808 FLUID_LOG(FLUID_ERR, "Out of memory");
812 fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx,
813 synth->audio_groups);
815 FLUID_LOG(FLUID_WARN, "FluidSynth has not been compiled with LADSPA support");
819 /* allocate and add the default sfont loader */
820 loader = new_fluid_defsfloader(settings);
824 FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader");
828 fluid_synth_add_sfloader(synth, loader);
831 /* allocate all channel objects */
832 synth->channel = FLUID_ARRAY(fluid_channel_t *, synth->midi_channels);
834 if(synth->channel == NULL)
836 FLUID_LOG(FLUID_ERR, "Out of memory");
840 for(i = 0; i < synth->midi_channels; i++)
842 synth->channel[i] = new_fluid_channel(synth, i);
844 if(synth->channel[i] == NULL)
850 /* allocate all synthesis processes */
851 synth->nvoice = synth->polyphony;
852 synth->voice = FLUID_ARRAY(fluid_voice_t *, synth->nvoice);
854 if(synth->voice == NULL)
859 for(i = 0; i < synth->nvoice; i++)
861 synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
863 if(synth->voice[i] == NULL)
869 /* sets a default basic channel */
870 /* Sets one basic channel: basic channel 0, mode 0 (Omni On - Poly) */
871 /* (i.e all channels are polyphonic) */
872 /* Must be called after channel objects allocation */
873 fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
874 synth->midi_channels);
876 synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
879 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
880 synth->polyphony, 0.0f);
881 fluid_synth_set_reverb_on(synth, synth->with_reverb);
882 fluid_synth_set_chorus_on(synth, synth->with_chorus);
884 synth->cur = FLUID_BUFSIZE;
886 synth->dither_index = 0;
889 double room, damp, width, level;
891 fluid_settings_getnum(settings, "synth.reverb.room-size", &room);
892 fluid_settings_getnum(settings, "synth.reverb.damp", &damp);
893 fluid_settings_getnum(settings, "synth.reverb.width", &width);
894 fluid_settings_getnum(settings, "synth.reverb.level", &level);
896 fluid_synth_set_reverb_full_LOCAL(synth,
897 FLUID_REVMODEL_SET_ALL,
905 double level, speed, depth;
907 fluid_settings_getint(settings, "synth.chorus.nr", &i);
908 fluid_settings_getnum(settings, "synth.chorus.level", &level);
909 fluid_settings_getnum(settings, "synth.chorus.speed", &speed);
910 fluid_settings_getnum(settings, "synth.chorus.depth", &depth);
912 fluid_synth_set_chorus_full_LOCAL(synth,
913 FLUID_CHORUS_SET_ALL,
918 FLUID_CHORUS_DEFAULT_TYPE);
922 synth->bank_select = FLUID_BANK_STYLE_GS;
924 if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gm"))
926 synth->bank_select = FLUID_BANK_STYLE_GM;
928 else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gs"))
930 synth->bank_select = FLUID_BANK_STYLE_GS;
932 else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "xg"))
934 synth->bank_select = FLUID_BANK_STYLE_XG;
936 else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "mma"))
938 synth->bank_select = FLUID_BANK_STYLE_MMA;
941 fluid_synth_process_event_queue(synth);
944 synth->start = fluid_curtime();
949 delete_fluid_synth(synth);
955 * Delete a FluidSynth instance.
956 * @param synth FluidSynth instance to delete
958 * @note Other users of a synthesizer instance, such as audio and MIDI drivers,
959 * should be deleted prior to freeing the FluidSynth instance.
962 delete_fluid_synth(fluid_synth_t *synth)
966 fluid_sfont_t *sfont;
967 fluid_sfloader_t *loader;
968 fluid_mod_t *default_mod;
971 fluid_return_if_fail(synth != NULL);
973 fluid_profiling_print();
975 /* turn off all voices, needed to unload SoundFont data */
976 if(synth->voice != NULL)
978 for(i = 0; i < synth->nvoice; i++)
980 fluid_voice_t *voice = synth->voice[i];
987 fluid_voice_unlock_rvoice(voice);
988 fluid_voice_overflow_rvoice_finished(voice);
990 if(fluid_voice_is_playing(voice))
992 fluid_voice_off(voice);
993 /* If we only use fluid_voice_off(voice) it will trigger a delayed
994 * fluid_voice_stop(voice) via fluid_synth_check_finished_voices().
995 * But here, we are deleting the fluid_synth_t instance so
996 * fluid_voice_stop() will be never triggered resulting in
997 * SoundFont data never unloaded (i.e a serious memory leak).
998 * So, fluid_voice_stop() must be explicitly called to insure
999 * unloading SoundFont data
1001 fluid_voice_stop(voice);
1006 /* also unset all presets for clean SoundFont unload */
1007 if(synth->channel != NULL)
1009 for(i = 0; i < synth->midi_channels; i++)
1011 fluid_channel_set_preset(synth->channel[i], NULL);
1015 delete_fluid_rvoice_eventhandler(synth->eventhandler);
1017 /* delete all the SoundFonts */
1018 for(list = synth->sfont; list; list = fluid_list_next(list))
1020 sfont = fluid_list_get(list);
1021 fluid_sfont_delete_internal(sfont);
1024 delete_fluid_list(synth->sfont);
1026 /* delete all the SoundFont loaders */
1028 for(list = synth->loaders; list; list = fluid_list_next(list))
1030 loader = (fluid_sfloader_t *) fluid_list_get(list);
1031 fluid_sfloader_delete(loader);
1034 delete_fluid_list(synth->loaders);
1037 if(synth->channel != NULL)
1039 for(i = 0; i < synth->midi_channels; i++)
1041 delete_fluid_channel(synth->channel[i]);
1044 FLUID_FREE(synth->channel);
1047 if(synth->voice != NULL)
1049 for(i = 0; i < synth->nvoice; i++)
1051 delete_fluid_voice(synth->voice[i]);
1054 FLUID_FREE(synth->voice);
1058 /* free the tunings, if any */
1059 if(synth->tuning != NULL)
1061 for(i = 0; i < 128; i++)
1063 if(synth->tuning[i] != NULL)
1065 for(k = 0; k < 128; k++)
1067 delete_fluid_tuning(synth->tuning[i][k]);
1070 FLUID_FREE(synth->tuning[i]);
1074 FLUID_FREE(synth->tuning);
1077 fluid_private_free(synth->tuning_iter);
1080 /* Release the LADSPA effects unit */
1081 delete_fluid_ladspa_fx(synth->ladspa_fx);
1084 /* delete all default modulators */
1085 default_mod = synth->default_mod;
1087 while(default_mod != NULL)
1090 default_mod = mod->next;
1091 delete_fluid_mod(mod);
1094 FLUID_FREE(synth->overflow.important_channels);
1096 fluid_rec_mutex_destroy(synth->mutex);
1102 * Get a textual representation of the last error
1103 * @param synth FluidSynth instance
1104 * @return Pointer to string of last error message. Valid until the same
1105 * calling thread calls another FluidSynth function which fails. String is
1106 * internal and should not be modified or freed.
1107 * @deprecated This function is not thread-safe and does not work with multiple synths.
1108 * It has been deprecated. It may return "" in a future release and will eventually be removed.
1110 /* FIXME - The error messages are not thread-safe, yet. They are still stored
1111 * in a global message buffer (see fluid_sys.c). */
1113 fluid_synth_error(fluid_synth_t *synth)
1115 return fluid_error();
1119 * Send a note-on event to a FluidSynth object.
1120 * @param synth FluidSynth instance
1121 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1122 * @param key MIDI note number (0-127)
1123 * @param vel MIDI velocity (0-127, 0=noteoff)
1124 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1127 fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel)
1130 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1131 fluid_return_val_if_fail(vel >= 0 && vel <= 127, FLUID_FAILED);
1132 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1134 /* Allowed only on MIDI channel enabled */
1135 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1137 result = fluid_synth_noteon_LOCAL(synth, chan, key, vel);
1138 FLUID_API_RETURN(result);
1141 /* Local synthesis thread variant of fluid_synth_noteon */
1143 fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key, int vel)
1145 fluid_channel_t *channel ;
1147 /* notes with velocity zero go to noteoff */
1150 return fluid_synth_noteoff_LOCAL(synth, chan, key);
1153 channel = synth->channel[chan];
1155 /* makes sure this channel has a preset */
1156 if(channel->preset == NULL)
1160 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s",
1162 fluid_synth_get_ticks(synth) / 44100.0f,
1163 (fluid_curtime() - synth->start) / 1000.0f,
1164 0.0f, 0, "channel has no preset");
1167 return FLUID_FAILED;
1170 if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1172 /* play the noteOn in monophonic */
1173 return fluid_synth_noteon_mono_LOCAL(synth, chan, key, vel);
1177 /* channel is poly and legato CC is Off) */
1179 /* plays the noteOn in polyphonic */
1180 /* Sets the note at first position in monophonic list */
1181 /* In the case where the musician intends to inter the channel in monophonic
1182 (by depressing the CC legato on), the next noteOn mono could be played legato
1183 with the previous note poly (if the musician choose this).
1185 fluid_channel_set_onenote_monolist(channel, (unsigned char) key,
1186 (unsigned char) vel);
1188 /* If there is another voice process on the same channel and key,
1189 advance it to the release phase. */
1190 fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key);
1192 /* a noteon poly is passed to fluid_synth_noteon_monopoly_legato().
1193 This allows an opportunity to get this note played legato with a previous
1194 note if a CC PTC have been received before this noteon. This behavior is
1195 a MIDI specification (see FluidPolymono-0004.pdf chapter 4.3-a ,3.4.11
1198 return fluid_synth_noteon_monopoly_legato(synth, chan, INVALID_NOTE, key, vel);
1203 * Sends a note-off event to a FluidSynth object.
1204 * @param synth FluidSynth instance
1205 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1206 * @param key MIDI note number (0-127)
1207 * @return #FLUID_OK on success, #FLUID_FAILED otherwise (may just mean that no
1208 * voices matched the note off event)
1211 fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key)
1214 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1215 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1217 /* Allowed only on MIDI channel enabled */
1218 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1220 result = fluid_synth_noteoff_LOCAL(synth, chan, key);
1221 FLUID_API_RETURN(result);
1224 /* Local synthesis thread variant of fluid_synth_noteoff */
1226 fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key)
1229 fluid_channel_t *channel = synth->channel[chan];
1231 if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1233 /* play the noteOff in monophonic */
1234 status = fluid_synth_noteoff_mono_LOCAL(synth, chan, key);
1238 /* channel is poly and legato CC is Off) */
1239 /* removes the note from the monophonic list */
1240 if(key == fluid_channel_last_note(channel))
1242 fluid_channel_clear_monolist(channel);
1245 status = fluid_synth_noteoff_monopoly(synth, chan, key, 0);
1248 /* Changes the state (Valid/Invalid) of the most recent note played in a
1250 fluid_channel_invalid_prev_note_staccato(channel);
1254 /* Damps voices on a channel (turn notes off), if they're sustained by
1257 fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t *synth, int chan)
1259 fluid_channel_t *channel = synth->channel[chan];
1260 fluid_voice_t *voice;
1263 for(i = 0; i < synth->polyphony; i++)
1265 voice = synth->voice[i];
1267 if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sustained(voice))
1269 if(voice->key == channel->key_mono_sustained)
1271 /* key_mono_sustained is a possible mono note sustainted
1272 (by sustain or sostenuto pedal). It must be marked released
1273 (INVALID_NOTE) here because it is released only by sustain pedal */
1274 channel->key_mono_sustained = INVALID_NOTE;
1277 fluid_voice_release(voice);
1284 /* Damps voices on a channel (turn notes off), if they're sustained by
1287 fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t *synth, int chan)
1289 fluid_channel_t *channel = synth->channel[chan];
1290 fluid_voice_t *voice;
1293 for(i = 0; i < synth->polyphony; i++)
1295 voice = synth->voice[i];
1297 if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sostenuto(voice))
1299 if(voice->key == channel->key_mono_sustained)
1301 /* key_mono_sustained is a possible mono note sustainted
1302 (by sustain or sostenuto pedal). It must be marked released
1303 (INVALID_NOTE) here because it is released only by sostenuto pedal */
1304 channel->key_mono_sustained = INVALID_NOTE;
1307 fluid_voice_release(voice);
1315 * Adds the specified modulator \c mod as default modulator to the synth. \c mod will
1316 * take effect for any subsequently created voice.
1317 * @param synth FluidSynth instance
1318 * @param mod Modulator info (values copied, passed in object can be freed immediately afterwards)
1319 * @param mode Determines how to handle an existing identical modulator (#fluid_synth_add_mod)
1320 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1322 * @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1323 * from synthesis context at the risk of stalling audio output.
1326 fluid_synth_add_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod, int mode)
1328 fluid_mod_t *default_mod;
1329 fluid_mod_t *last_mod = NULL;
1330 fluid_mod_t *new_mod;
1332 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1333 fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1335 /* Checks if modulators sources are valid */
1336 if(!fluid_mod_check_sources(mod, "api fluid_synth_add_default_mod mod"))
1338 return FLUID_FAILED;
1341 fluid_synth_api_enter(synth);
1343 default_mod = synth->default_mod;
1345 while(default_mod != NULL)
1347 if(fluid_mod_test_identity(default_mod, mod))
1349 if(mode == FLUID_SYNTH_ADD)
1351 default_mod->amount += mod->amount;
1353 else if(mode == FLUID_SYNTH_OVERWRITE)
1355 default_mod->amount = mod->amount;
1359 FLUID_API_RETURN(FLUID_FAILED);
1362 FLUID_API_RETURN(FLUID_OK);
1365 last_mod = default_mod;
1366 default_mod = default_mod->next;
1369 /* Add a new modulator (no existing modulator to add / overwrite). */
1370 new_mod = new_fluid_mod();
1374 FLUID_API_RETURN(FLUID_FAILED);
1377 fluid_mod_clone(new_mod, mod);
1378 new_mod->next = NULL;
1380 if(last_mod == NULL)
1382 synth->default_mod = new_mod;
1386 last_mod->next = new_mod;
1389 FLUID_API_RETURN(FLUID_OK);
1393 * Removes the specified modulator \c mod from the synth's default modulator list.
1394 * fluid_mod_test_identity() will be used to test modulator matching.
1395 * @param synth synth instance
1396 * @param mod The modulator to remove
1397 * @return #FLUID_OK if a matching modulator was found and successfully removed, #FLUID_FAILED otherwise
1399 * @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1400 * from synthesis context at the risk of stalling audio output.
1403 fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod)
1405 fluid_mod_t *default_mod;
1406 fluid_mod_t *last_mod;
1408 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1409 fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1410 fluid_synth_api_enter(synth);
1412 last_mod = default_mod = synth->default_mod;
1414 while(default_mod != NULL)
1416 if(fluid_mod_test_identity(default_mod, mod))
1418 if(synth->default_mod == default_mod)
1420 synth->default_mod = synth->default_mod->next;
1424 last_mod->next = default_mod->next;
1427 delete_fluid_mod(default_mod);
1428 FLUID_API_RETURN(FLUID_OK);
1431 last_mod = default_mod;
1432 default_mod = default_mod->next;
1435 FLUID_API_RETURN(FLUID_FAILED);
1440 * Send a MIDI controller event on a MIDI channel.
1441 * @param synth FluidSynth instance
1442 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1443 * @param num MIDI controller number (0-127)
1444 * @param val MIDI controller value (0-127)
1445 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1446 * @note This function supports MIDI Global Controllers which will be sent to
1447 * all channels of the basic channel if this basic channel is in mode OmniOff/Mono.
1448 * This is accomplished by sending the CC one MIDI channel below the basic
1449 * channel of the receiver.
1450 * Examples: let a synthesizer with 16 MIDI channels:
1451 * - Let a basic channel 7 in mode 3 (Omni Off, Mono). If MIDI channel 6 is disabled it
1452 * could be used as CC global for all channels belonging to basic channel 7.
1453 * - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used
1454 * as CC global for all channels belonging to basic channel 0.
1457 fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
1459 int result = FLUID_FAILED;
1460 fluid_channel_t *channel;
1461 fluid_return_val_if_fail(num >= 0 && num <= 127, FLUID_FAILED);
1462 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
1463 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1465 channel = synth->channel[chan];
1467 if(channel->mode & FLUID_CHANNEL_ENABLED)
1469 /* chan is enabled */
1472 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val);
1475 fluid_channel_set_cc(channel, num, val);
1476 result = fluid_synth_cc_LOCAL(synth, chan, num);
1478 else /* chan is disabled so it is a candidate for global channel */
1480 /* looks for next basic channel */
1481 int n_chan = synth->midi_channels; /* MIDI Channels number */
1484 if(chan < n_chan - 1)
1486 basicchan = chan + 1; /* next channel */
1490 basicchan = 0; /* wrap to 0 */
1493 channel = synth->channel[basicchan];
1495 /* Channel must be a basicchan in mode OMNIOFF_MONO */
1496 if((channel->mode & FLUID_CHANNEL_BASIC) &&
1497 ((channel->mode & FLUID_CHANNEL_MODE_MASK) == FLUID_CHANNEL_MODE_OMNIOFF_MONO))
1499 /* sends cc to all channels in this basic channel */
1500 int i, nbr = channel->mode_val;
1502 for(i = basicchan; i < basicchan + nbr; i++)
1506 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", i, num, val);
1509 fluid_channel_set_cc(synth->channel[i], num, val);
1510 result = fluid_synth_cc_LOCAL(synth, i, num);
1513 /* The channel chan is not a valid 'global channel' */
1516 result = FLUID_FAILED;
1520 FLUID_API_RETURN(result);
1523 /* Local synthesis thread variant of MIDI CC set function.
1524 Most of CC are allowed to modulate but not all. A comment describes if CC num
1525 isn't allowed to modulate.
1526 Following explanations should help to understand both MIDI specifications and
1527 Soundfont specifications in regard to MIDI specs.
1530 CC LSB (32 to 63) are LSB contributions to CC MSB (0 to 31).
1531 It's up to the synthesizer to decide to take LSB values into account or not.
1532 Actually Fluidsynth doesn't use CC LSB value inside fluid_voice_update_param()
1533 (once fluid_voice_modulate() has been triggered). This is because actually
1534 fluidsynth needs only 7 bits resolution (and not 14 bits) from these CCs.
1535 So fluidsynth is using only 7 bit MSB (except for portamento time).
1536 In regard to MIDI specs Fluidsynth behaves correctly.
1538 Soundfont specs 2.01 - 8.2.1:
1539 To deal correctly with MIDI CC (regardless if any synth will use CC MSB alone (7 bit)
1540 or both CCs MSB,LSB (14 bits) during synthesis), SF specs recommend not making use of
1541 CC LSB (i.e only CC MSB) in modulator sources to trigger modulation (i.e modulators
1542 with CC LSB connected to sources inputs should be ignored).
1543 These specifics are particularly suited for synths that use 14 bits CCs. In this case,
1544 the MIDI transmitter sends CC LSB first followed by CC MSB. The MIDI synth receives
1545 both CC LSB and CC MSB but only CC MSB will trigger the modulation.
1546 This will produce correct synthesis parameters update from a correct 14 bits CC.
1547 If in SF specs, modulator sources with CC LSB had been accepted, both CC LSB and
1548 CC MSB will triggers 2 modulations. This leads to incorrect synthesis parameters
1549 update followed by correct synthesis parameters update.
1551 However, as long as fluidsynth will use only CC 7 bits resolution, it is safe to ignore
1552 these SF recommendations on CC receive.
1555 fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
1557 fluid_channel_t *chan = synth->channel[channum];
1561 value = fluid_channel_get_cc(chan, num);
1565 case LOCAL_CONTROL: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1568 /* CC omnioff, omnion, mono, poly */
1569 /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1575 /* allowed only if channum is a basic channel */
1576 if(chan->mode & FLUID_CHANNEL_BASIC)
1578 /* Construction of new_mode from current channel mode and this CC mode */
1579 int new_mode = chan->mode & FLUID_CHANNEL_MODE_MASK;
1584 new_mode |= FLUID_CHANNEL_POLY_OFF;
1588 new_mode &= ~FLUID_CHANNEL_POLY_OFF;
1592 new_mode |= FLUID_CHANNEL_OMNI_OFF;
1596 new_mode &= ~FLUID_CHANNEL_OMNI_OFF;
1599 default: /* should never happen */
1600 return FLUID_FAILED;
1603 /* MIDI specs: if value is 0 it means all channels from channum to next
1604 basic channel minus 1 (if any) or to MIDI channel count minus 1.
1605 However, if value is > 0 (e.g. 4), the group of channels will be be
1607 value is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY as this mode
1608 implies a group of only one channel.
1610 /* Checks value range and changes this existing basic channel group */
1611 value = fluid_synth_check_next_basic_channel(synth, channum, new_mode, value);
1613 if(value != FLUID_FAILED)
1615 /* reset the current basic channel before changing it */
1616 fluid_synth_reset_basic_channel_LOCAL(synth, channum, chan->mode_val);
1617 fluid_synth_set_basic_channel_LOCAL(synth, channum, new_mode, value);
1618 break; /* FLUID_OK */
1622 return FLUID_FAILED;
1624 case LEGATO_SWITCH: /* not allowed to modulate */
1625 /* handles Poly/mono commutation on Legato pedal On/Off.*/
1626 fluid_channel_cc_legato(chan, value);
1629 case PORTAMENTO_SWITCH: /* not allowed to modulate */
1630 /* Special handling of the monophonic list */
1631 /* Invalids the most recent note played in a staccato manner */
1632 fluid_channel_invalid_prev_note_staccato(chan);
1635 case SUSTAIN_SWITCH: /* not allowed to modulate */
1637 /* Release voices if Sustain switch is released */
1638 if(value < 64) /* Sustain is released */
1640 fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
1645 case SOSTENUTO_SWITCH: /* not allowed to modulate */
1647 /* Release voices if Sostetuno switch is released */
1648 if(value < 64) /* Sostenuto is released */
1650 fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
1652 else /* Sostenuto is depressed */
1653 /* Update sostenuto order id when pedaling on Sostenuto */
1655 chan->sostenuto_orderid = synth->noteid; /* future voice id value */
1660 case BANK_SELECT_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1661 fluid_channel_set_bank_msb(chan, value & 0x7F);
1664 case BANK_SELECT_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1665 fluid_channel_set_bank_lsb(chan, value & 0x7F);
1668 case ALL_NOTES_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1669 fluid_synth_all_notes_off_LOCAL(synth, channum);
1672 case ALL_SOUND_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1673 fluid_synth_all_sounds_off_LOCAL(synth, channum);
1676 case ALL_CTRL_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1677 fluid_channel_init_ctrl(chan, 1);
1678 fluid_synth_modulate_voices_all_LOCAL(synth, channum);
1681 case DATA_ENTRY_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1684 case DATA_ENTRY_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1686 int data = (value << 7) + fluid_channel_get_cc(chan, DATA_ENTRY_LSB);
1688 if(chan->nrpn_active) /* NRPN is active? */
1690 /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1691 if((fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1692 && (fluid_channel_get_cc(chan, NRPN_LSB) < 100))
1694 nrpn_select = chan->nrpn_select;
1696 if(nrpn_select < GEN_LAST)
1698 float val = fluid_gen_scale_nrpn(nrpn_select, data);
1699 fluid_synth_set_gen_LOCAL(synth, channum, nrpn_select, val, FALSE);
1702 chan->nrpn_select = 0; /* Reset to 0 */
1705 else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */
1707 switch(fluid_channel_get_cc(chan, RPN_LSB))
1709 case RPN_PITCH_BEND_RANGE: /* Set bend range in semitones */
1710 fluid_channel_set_pitch_wheel_sensitivity(synth->channel[channum], value);
1711 fluid_synth_update_pitch_wheel_sens_LOCAL(synth, channum); /* Update bend range */
1712 /* FIXME - Handle LSB? (Fine bend range in cents) */
1715 case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over +/-1 semitone (+/- 100 cents, 8192 = center) */
1716 fluid_synth_set_gen_LOCAL(synth, channum, GEN_FINETUNE,
1717 (data - 8192) / 8192.0 * 100.0, FALSE);
1720 case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */
1721 fluid_synth_set_gen_LOCAL(synth, channum, GEN_COARSETUNE,
1725 case RPN_TUNING_PROGRAM_CHANGE:
1726 fluid_channel_set_tuning_prog(chan, value);
1727 fluid_synth_activate_tuning(synth, channum,
1728 fluid_channel_get_tuning_bank(chan),
1732 case RPN_TUNING_BANK_SELECT:
1733 fluid_channel_set_tuning_bank(chan, value);
1736 case RPN_MODULATION_DEPTH_RANGE:
1744 case NRPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1745 fluid_channel_set_cc(chan, NRPN_LSB, 0);
1746 chan->nrpn_select = 0;
1747 chan->nrpn_active = 1;
1750 case NRPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1752 /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1753 if(fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1757 chan->nrpn_select += 100;
1759 else if(value == 101)
1761 chan->nrpn_select += 1000;
1763 else if(value == 102)
1765 chan->nrpn_select += 10000;
1767 else if(value < 100)
1769 chan->nrpn_select += value;
1773 chan->nrpn_active = 1;
1776 case RPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1777 case RPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1778 chan->nrpn_active = 0;
1782 /* handles CC Breath On/Off noteOn/noteOff mode */
1783 fluid_channel_cc_breath_note_on_off(chan, value);
1787 /* CC lsb shouldn't allowed to modulate (spec SF 2.01 - 8.2.1) */
1788 /* However, as long fluidsynth will use only CC 7 bits resolution, it
1789 is safe to ignore these SF recommendations on CC receive. See
1790 explanations above */
1791 /* if (! (32 <= num && num <= 63)) */
1793 return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num);
1801 * Get current MIDI controller value on a MIDI channel.
1802 * @param synth FluidSynth instance
1803 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1804 * @param num MIDI controller number (0-127)
1805 * @param pval Location to store MIDI controller value (0-127)
1806 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1809 fluid_synth_get_cc(fluid_synth_t *synth, int chan, int num, int *pval)
1811 fluid_return_val_if_fail(num >= 0 && num < 128, FLUID_FAILED);
1812 fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
1814 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1816 /* Allowed only on MIDI channel enabled */
1817 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1819 *pval = fluid_channel_get_cc(synth->channel[chan], num);
1820 FLUID_API_RETURN(FLUID_OK);
1824 * Handler for synth.device-id setting.
1827 fluid_synth_handle_device_id(void *data, const char *name, int value)
1829 fluid_synth_t *synth = (fluid_synth_t *)data;
1830 fluid_return_if_fail(synth != NULL);
1832 fluid_synth_api_enter(synth);
1833 synth->device_id = value;
1834 fluid_synth_api_exit(synth);
1838 * Process a MIDI SYSEX (system exclusive) message.
1839 * @param synth FluidSynth instance
1840 * @param data Buffer containing SYSEX data (not including 0xF0 and 0xF7)
1841 * @param len Length of data in buffer
1842 * @param response Buffer to store response to or NULL to ignore
1843 * @param response_len IN/OUT parameter, in: size of response buffer, out:
1844 * amount of data written to response buffer (if FLUID_FAILED is returned and
1845 * this value is non-zero, it indicates the response buffer is too small)
1846 * @param handled Optional location to store boolean value if message was
1847 * recognized and handled or not (set to TRUE if it was handled)
1848 * @param dryrun TRUE to just do a dry run but not actually execute the SYSEX
1849 * command (useful for checking if a SYSEX message would be handled)
1850 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1853 /* SYSEX format (0xF0 and 0xF7 not passed to this function):
1854 * Non-realtime: 0xF0 0x7E <DeviceId> [BODY] 0xF7
1855 * Realtime: 0xF0 0x7F <DeviceId> [BODY] 0xF7
1856 * Tuning messages: 0xF0 0x7E/0x7F <DeviceId> 0x08 <sub ID2> [BODY] <ChkSum> 0xF7
1859 fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len,
1860 char *response, int *response_len, int *handled, int dryrun)
1862 int avail_response = 0;
1871 avail_response = *response_len;
1875 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1876 fluid_return_val_if_fail(data != NULL, FLUID_FAILED);
1877 fluid_return_val_if_fail(len > 0, FLUID_FAILED);
1878 fluid_return_val_if_fail(!response || response_len, FLUID_FAILED);
1885 /* MIDI tuning SYSEX message? */
1886 if((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME)
1887 && (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL)
1888 && data[2] == MIDI_SYSEX_MIDI_TUNING_ID)
1891 fluid_synth_api_enter(synth);
1892 result = fluid_synth_sysex_midi_tuning(synth, data, len, response,
1893 response_len, avail_response,
1896 FLUID_API_RETURN(result);
1902 /* Handler for MIDI tuning SYSEX messages */
1904 fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len,
1905 char *response, int *response_len, int avail_response,
1906 int *handled, int dryrun)
1908 int realtime, msgid;
1909 int bank = 0, prog, channels;
1910 double tunedata[128];
1913 int note, frac, frac2;
1915 int i, count, index;
1916 const char *dataptr;
1919 realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME;
1924 case MIDI_SYSEX_TUNING_BULK_DUMP_REQ:
1925 case MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK:
1926 if(data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
1928 if(len != 5 || data[4] & 0x80 || !response)
1933 *response_len = 406;
1938 if(len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response)
1943 *response_len = 407;
1958 if(avail_response < *response_len)
1960 return FLUID_FAILED;
1963 /* Get tuning data, return if tuning not found */
1964 if(fluid_synth_tuning_dump(synth, bank, prog, name, 17, tunedata) == FLUID_FAILED)
1972 *resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME;
1973 *resptr++ = synth->device_id;
1974 *resptr++ = MIDI_SYSEX_MIDI_TUNING_ID;
1975 *resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP;
1977 if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK)
1983 /* copy 16 ASCII characters (potentially not null terminated) to the sysex buffer */
1984 FLUID_MEMCPY(resptr, name, 16);
1987 for(i = 0; i < 128; i++)
1989 note = tunedata[i] / 100.0;
1990 fluid_clip(note, 0, 127);
1992 frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0;
1993 fluid_clip(frac, 0, 16383);
1996 *resptr++ = frac >> 7;
1997 *resptr++ = frac & 0x7F;
2000 if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
2002 /* NOTE: Checksum is not as straight forward as the bank based messages */
2003 chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID
2004 ^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog;
2006 for(i = 21; i < 128 * 3 + 21; i++)
2008 chksum ^= response[i];
2013 for(i = 1, chksum = 0; i < 406; i++)
2015 chksum ^= response[i];
2019 *resptr++ = chksum & 0x7F;
2028 case MIDI_SYSEX_TUNING_NOTE_TUNE:
2029 case MIDI_SYSEX_TUNING_NOTE_TUNE_BANK:
2032 if(msgid == MIDI_SYSEX_TUNING_NOTE_TUNE)
2034 if(len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6)
2041 if(len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80
2042 || len != data[6] * 4 + 7)
2063 for(i = 0, index = 0; i < count; i++)
2078 if(note & 0x80 || frac & 0x80 || frac2 & 0x80)
2083 frac = frac << 7 | frac2;
2085 /* No change pitch value? Doesn't really make sense to send that, but.. */
2086 if(note == 0x7F && frac == 16383)
2091 tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0);
2097 if(fluid_synth_tune_notes(synth, bank, prog, index, keys, tunedata,
2098 realtime) == FLUID_FAILED)
2100 return FLUID_FAILED;
2111 case MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE:
2112 case MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE:
2113 if((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19)
2114 || (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31))
2119 if(data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80)
2134 channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6];
2136 if(msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE)
2138 for(i = 0; i < 12; i++)
2147 tunedata[i] = (int)frac - 64;
2152 for(i = 0; i < 12; i++)
2154 frac = data[i * 2 + 7];
2155 frac2 = data[i * 2 + 8];
2157 if(frac & 0x80 || frac2 & 0x80)
2162 tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0);
2166 if(fluid_synth_activate_octave_tuning(synth, 0, 0, "SYSEX",
2167 tunedata, realtime) == FLUID_FAILED)
2169 return FLUID_FAILED;
2174 for(i = 0; i < 16; i++)
2176 if(channels & (1 << i))
2178 fluid_synth_activate_tuning(synth, i, 0, 0, realtime);
2195 * Turn off all notes on a MIDI channel (put them into release phase).
2196 * @param synth FluidSynth instance
2197 * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2198 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2202 fluid_synth_all_notes_off(fluid_synth_t *synth, int chan)
2206 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2207 fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2208 fluid_synth_api_enter(synth);
2210 if(chan >= synth->midi_channels)
2212 result = FLUID_FAILED;
2216 /* Allowed (even for channel disabled) as chan = -1 selects all channels */
2217 result = fluid_synth_all_notes_off_LOCAL(synth, chan);
2220 FLUID_API_RETURN(result);
2223 /* Local synthesis thread variant of all notes off, (chan=-1 selects all channels) */
2226 fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan)
2228 fluid_voice_t *voice;
2231 for(i = 0; i < synth->polyphony; i++)
2233 voice = synth->voice[i];
2235 if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2237 fluid_voice_noteoff(voice);
2245 * Immediately stop all notes on a MIDI channel (skips release phase).
2246 * @param synth FluidSynth instance
2247 * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2248 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2252 fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan)
2256 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2257 fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2258 fluid_synth_api_enter(synth);
2260 if(chan >= synth->midi_channels)
2262 result = FLUID_FAILED;
2266 /* Allowed (even for channel disabled) as chan = -1 selects all channels */
2267 result = fluid_synth_all_sounds_off_LOCAL(synth, chan);
2270 FLUID_API_RETURN(result);
2273 /* Local synthesis thread variant of all sounds off, (chan=-1 selects all channels) */
2275 fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan)
2277 fluid_voice_t *voice;
2280 for(i = 0; i < synth->polyphony; i++)
2282 voice = synth->voice[i];
2284 if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2286 fluid_voice_off(voice);
2294 * Reset reverb engine
2295 * @param synth FluidSynth instance
2296 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2299 fluid_synth_reset_reverb(fluid_synth_t *synth)
2301 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2302 fluid_synth_api_enter(synth);
2303 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2304 FLUID_API_RETURN(FLUID_OK);
2308 * Reset chorus engine
2309 * @param synth FluidSynth instance
2310 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2313 fluid_synth_reset_chorus(fluid_synth_t *synth)
2315 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2316 fluid_synth_api_enter(synth);
2317 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2318 FLUID_API_RETURN(FLUID_OK);
2323 * Send MIDI system reset command (big red 'panic' button), turns off notes, resets
2324 * controllers and restores initial basic channel configuration.
2325 * @param synth FluidSynth instance
2326 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2329 fluid_synth_system_reset(fluid_synth_t *synth)
2332 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2333 fluid_synth_api_enter(synth);
2334 result = fluid_synth_system_reset_LOCAL(synth);
2335 FLUID_API_RETURN(result);
2338 /* Local variant of the system reset command */
2340 fluid_synth_system_reset_LOCAL(fluid_synth_t *synth)
2344 fluid_synth_all_sounds_off_LOCAL(synth, -1);
2346 for(i = 0; i < synth->midi_channels; i++)
2348 fluid_channel_reset(synth->channel[i]);
2351 /* Basic channel 0, Mode Omni On Poly */
2352 fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
2353 synth->midi_channels);
2355 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2356 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2362 * Update voices on a MIDI channel after a MIDI control change.
2363 * @param synth FluidSynth instance
2364 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2365 * @param is_cc Boolean value indicating if ctrl is a CC controller or not
2366 * @param ctrl MIDI controller value
2367 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2370 fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan, int is_cc, int ctrl)
2372 fluid_voice_t *voice;
2375 for(i = 0; i < synth->polyphony; i++)
2377 voice = synth->voice[i];
2379 if(fluid_voice_get_channel(voice) == chan)
2381 fluid_voice_modulate(voice, is_cc, ctrl);
2389 * Update voices on a MIDI channel after all MIDI controllers have been changed.
2390 * @param synth FluidSynth instance
2391 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2392 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2395 fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan)
2397 fluid_voice_t *voice;
2400 for(i = 0; i < synth->polyphony; i++)
2402 voice = synth->voice[i];
2404 if(fluid_voice_get_channel(voice) == chan)
2406 fluid_voice_modulate_all(voice);
2414 * Set the MIDI channel pressure controller value.
2415 * @param synth FluidSynth instance
2416 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2417 * @param val MIDI channel pressure value (0-127)
2418 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2421 fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val)
2424 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2426 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2428 /* Allowed only on MIDI channel enabled */
2429 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2433 FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
2436 fluid_channel_set_channel_pressure(synth->channel[chan], val);
2437 result = fluid_synth_update_channel_pressure_LOCAL(synth, chan);
2439 FLUID_API_RETURN(result);
2442 /* Updates channel pressure from within synthesis thread */
2444 fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int chan)
2446 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_CHANNELPRESSURE);
2450 * Set the MIDI polyphonic key pressure controller value.
2451 * @param synth FluidSynth instance
2452 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2453 * @param key MIDI key number (0-127)
2454 * @param val MIDI key pressure value (0-127)
2455 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2459 fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val)
2462 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
2463 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2465 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2467 /* Allowed only on MIDI channel enabled */
2468 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2472 FLUID_LOG(FLUID_INFO, "keypressure\t%d\t%d\t%d", chan, key, val);
2475 fluid_channel_set_key_pressure(synth->channel[chan], key, val);
2476 result = fluid_synth_update_key_pressure_LOCAL(synth, chan, key);
2478 FLUID_API_RETURN(result);
2481 /* Updates key pressure from within synthesis thread */
2483 fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key)
2485 fluid_voice_t *voice;
2487 int result = FLUID_OK;
2489 for(i = 0; i < synth->polyphony; i++)
2491 voice = synth->voice[i];
2493 if(voice->chan == chan && voice->key == key)
2495 result = fluid_voice_modulate(voice, 0, FLUID_MOD_KEYPRESSURE);
2497 if(result != FLUID_OK)
2508 * Set the MIDI pitch bend controller value on a MIDI channel.
2509 * @param synth FluidSynth instance
2510 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2511 * @param val MIDI pitch bend value (0-16383 with 8192 being center)
2512 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2515 fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val)
2518 fluid_return_val_if_fail(val >= 0 && val <= 16383, FLUID_FAILED);
2519 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2521 /* Allowed only on MIDI channel enabled */
2522 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2526 FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val);
2529 fluid_channel_set_pitch_bend(synth->channel[chan], val);
2530 result = fluid_synth_update_pitch_bend_LOCAL(synth, chan);
2532 FLUID_API_RETURN(result);
2535 /* Local synthesis thread variant of pitch bend */
2537 fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan)
2539 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEEL);
2543 * Get the MIDI pitch bend controller value on a MIDI channel.
2544 * @param synth FluidSynth instance
2545 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2546 * @param ppitch_bend Location to store MIDI pitch bend value (0-16383 with
2547 * 8192 being center)
2548 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2551 fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend)
2554 fluid_return_val_if_fail(ppitch_bend != NULL, FLUID_FAILED);
2555 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2557 /* Allowed only on MIDI channel enabled */
2558 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2560 *ppitch_bend = fluid_channel_get_pitch_bend(synth->channel[chan]);
2563 FLUID_API_RETURN(result);
2567 * Set MIDI pitch wheel sensitivity on a MIDI channel.
2568 * @param synth FluidSynth instance
2569 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2570 * @param val Pitch wheel sensitivity value in semitones
2571 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2574 fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val)
2577 fluid_return_val_if_fail(val >= 0 && val <= 72, FLUID_FAILED); /* 6 octaves!? Better than no limit.. */
2578 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2580 /* Allowed only on MIDI channel enabled */
2581 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2585 FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val);
2588 fluid_channel_set_pitch_wheel_sensitivity(synth->channel[chan], val);
2589 result = fluid_synth_update_pitch_wheel_sens_LOCAL(synth, chan);
2591 FLUID_API_RETURN(result);
2594 /* Local synthesis thread variant of set pitch wheel sensitivity */
2596 fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan)
2598 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEELSENS);
2602 * Get MIDI pitch wheel sensitivity on a MIDI channel.
2603 * @param synth FluidSynth instance
2604 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2605 * @param pval Location to store pitch wheel sensitivity value in semitones
2606 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2607 * @since Sometime AFTER v1.0 API freeze.
2610 fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval)
2613 fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
2614 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2616 /* Allowed only on MIDI channel enabled */
2617 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2619 *pval = fluid_channel_get_pitch_wheel_sensitivity(synth->channel[chan]);
2622 FLUID_API_RETURN(result);
2626 * Assign a preset to a MIDI channel.
2627 * @param synth FluidSynth instance
2628 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2629 * @param preset Preset to assign to channel or NULL to clear (ownership is taken over)
2630 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2633 fluid_synth_set_preset(fluid_synth_t *synth, int chan, fluid_preset_t *preset)
2635 fluid_channel_t *channel;
2637 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2638 fluid_return_val_if_fail(chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
2640 channel = synth->channel[chan];
2642 return fluid_channel_set_preset(channel, preset);
2645 /* Get a preset by SoundFont, bank and program numbers.
2646 * Returns preset pointer or NULL.
2648 static fluid_preset_t *
2649 fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
2650 int banknum, int prognum)
2652 fluid_sfont_t *sfont;
2655 /* 128 indicates an "unset" operation" */
2656 if(prognum == FLUID_UNSET_PROGRAM)
2661 for(list = synth->sfont; list; list = fluid_list_next(list))
2663 sfont = fluid_list_get(list);
2665 if(fluid_sfont_get_id(sfont) == sfontnum)
2667 return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2674 /* Get a preset by SoundFont name, bank and program.
2675 * Returns preset pointer or NULL.
2677 static fluid_preset_t *
2678 fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname,
2679 int banknum, int prognum)
2681 fluid_sfont_t *sfont;
2684 for(list = synth->sfont; list; list = fluid_list_next(list))
2686 sfont = fluid_list_get(list);
2688 if(FLUID_STRCMP(fluid_sfont_get_name(sfont), sfontname) == 0)
2690 return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2697 /* Find a preset by bank and program numbers.
2698 * Returns preset pointer or NULL.
2701 fluid_synth_find_preset(fluid_synth_t *synth, int banknum,
2704 fluid_preset_t *preset;
2705 fluid_sfont_t *sfont;
2708 for(list = synth->sfont; list; list = fluid_list_next(list))
2710 sfont = fluid_list_get(list);
2712 preset = fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2724 * Send a program change event on a MIDI channel.
2725 * @param synth FluidSynth instance
2726 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2727 * @param prognum MIDI program number (0-127)
2728 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2730 /* FIXME - Currently not real-time safe, due to preset allocation and mutex lock,
2731 * and may be called from within synthesis context. */
2733 /* As of 1.1.1 prognum can be set to 128 to unset the preset. Not documented
2734 * since fluid_synth_unset_program() should be used instead. */
2736 fluid_synth_program_change(fluid_synth_t *synth, int chan, int prognum)
2738 fluid_preset_t *preset = NULL;
2739 fluid_channel_t *channel;
2740 int subst_bank, subst_prog, banknum = 0, result = FLUID_FAILED;
2742 fluid_return_val_if_fail(prognum >= 0 && prognum <= 128, FLUID_FAILED);
2743 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2745 /* Allowed only on MIDI channel enabled */
2746 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2748 channel = synth->channel[chan];
2750 if(channel->channel_type == CHANNEL_TYPE_DRUM)
2752 banknum = DRUM_INST_BANK;
2756 fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
2761 FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
2764 /* I think this is a hack for MIDI files that do bank changes in GM mode.
2765 * Proper way to handle this would probably be to ignore bank changes when in
2767 * This is now possible by setting synth.midi-bank-select=gm, but let the hack
2768 * stay for the time being. - DH
2770 if(prognum != FLUID_UNSET_PROGRAM)
2772 subst_bank = banknum;
2773 subst_prog = prognum;
2775 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2777 /* Fallback to another preset if not found */
2780 /* Percussion: Fallback to preset 0 in percussion bank */
2781 if(channel->channel_type == CHANNEL_TYPE_DRUM)
2784 subst_bank = DRUM_INST_BANK;
2785 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2787 /* Melodic instrument */
2790 /* Fallback first to bank 0:prognum */
2792 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2794 /* Fallback to first preset in bank 0 (usually piano...) */
2798 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2804 FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
2805 chan, banknum, prognum, subst_bank, subst_prog);
2809 FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]", chan, banknum, prognum);
2814 /* Assign the SoundFont ID and program number to the channel */
2815 fluid_channel_set_sfont_bank_prog(channel, preset ? fluid_sfont_get_id(preset->sfont) : 0,
2817 result = fluid_synth_set_preset(synth, chan, preset);
2819 FLUID_API_RETURN(result);
2823 * Set instrument bank number on a MIDI channel.
2824 * @param synth FluidSynth instance
2825 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2826 * @param bank MIDI bank number
2827 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2828 * @note This function does not change the instrument currently assigned to \c chan,
2829 * as it is usually called prior to fluid_synth_program_change(). If you still want
2830 * instrument changes to take effect immediately, call fluid_synth_program_reset()
2831 * after having set up the bank configuration.
2835 fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank)
2838 fluid_return_val_if_fail(bank <= 16383, FLUID_FAILED);
2839 fluid_return_val_if_fail(bank >= 0, FLUID_FAILED);
2840 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2842 /* Allowed only on MIDI channel enabled */
2843 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2845 fluid_channel_set_sfont_bank_prog(synth->channel[chan], -1, bank, -1);
2848 FLUID_API_RETURN(result);
2852 * Set SoundFont ID on a MIDI channel.
2853 * @param synth FluidSynth instance
2854 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2855 * @param sfont_id ID of a loaded SoundFont
2856 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2857 * @note This function does not change the instrument currently assigned to \c chan,
2858 * as it is usually called prior to fluid_synth_bank_select() or fluid_synth_program_change().
2859 * If you still want instrument changes to take effect immediately, call fluid_synth_program_reset()
2860 * after having selected the soundfont.
2863 fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id)
2866 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2868 /* Allowed only on MIDI channel enabled */
2869 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2871 fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
2874 FLUID_API_RETURN(result);
2878 * Set the preset of a MIDI channel to an unassigned state.
2879 * @param synth FluidSynth instance
2880 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2881 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2884 * @note Channel retains its SoundFont ID and bank numbers, while the program
2885 * number is set to an "unset" state. MIDI program changes may re-assign a
2886 * preset if one matches.
2889 fluid_synth_unset_program(fluid_synth_t *synth, int chan)
2891 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2892 FLUID_API_RETURN(fluid_synth_program_change(synth, chan, FLUID_UNSET_PROGRAM));
2896 * Get current SoundFont ID, bank number and program number for a MIDI channel.
2897 * @param synth FluidSynth instance
2898 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2899 * @param sfont_id Location to store SoundFont ID
2900 * @param bank_num Location to store MIDI bank number
2901 * @param preset_num Location to store MIDI program number
2902 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2905 fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id,
2906 int *bank_num, int *preset_num)
2909 fluid_channel_t *channel;
2911 fluid_return_val_if_fail(sfont_id != NULL, FLUID_FAILED);
2912 fluid_return_val_if_fail(bank_num != NULL, FLUID_FAILED);
2913 fluid_return_val_if_fail(preset_num != NULL, FLUID_FAILED);
2914 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2916 /* Allowed only on MIDI channel enabled */
2917 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2919 channel = synth->channel[chan];
2920 fluid_channel_get_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
2922 /* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */
2923 if(*preset_num == FLUID_UNSET_PROGRAM)
2930 FLUID_API_RETURN(result);
2934 * Select an instrument on a MIDI channel by SoundFont ID, bank and program numbers.
2935 * @param synth FluidSynth instance
2936 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2937 * @param sfont_id ID of a loaded SoundFont
2938 * @param bank_num MIDI bank number
2939 * @param preset_num MIDI program number
2940 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2943 fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
2944 int bank_num, int preset_num)
2946 fluid_preset_t *preset = NULL;
2947 fluid_channel_t *channel;
2949 fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
2950 fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
2952 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2954 /* Allowed only on MIDI channel enabled */
2955 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2957 channel = synth->channel[chan];
2959 preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
2963 FLUID_LOG(FLUID_ERR,
2964 "There is no preset with bank number %d and preset number %d in SoundFont %d",
2965 bank_num, preset_num, sfont_id);
2966 FLUID_API_RETURN(FLUID_FAILED);
2969 /* Assign the new SoundFont ID, bank and program number to the channel */
2970 fluid_channel_set_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
2971 result = fluid_synth_set_preset(synth, chan, preset);
2973 FLUID_API_RETURN(result);
2977 * Select an instrument on a MIDI channel by SoundFont name, bank and program numbers.
2978 * @param synth FluidSynth instance
2979 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2980 * @param sfont_name Name of a loaded SoundFont
2981 * @param bank_num MIDI bank number
2982 * @param preset_num MIDI program number
2983 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2987 fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan,
2988 const char *sfont_name, int bank_num,
2991 fluid_preset_t *preset = NULL;
2992 fluid_channel_t *channel;
2994 fluid_return_val_if_fail(sfont_name != NULL, FLUID_FAILED);
2995 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2997 /* Allowed only on MIDI channel enabled */
2998 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3000 channel = synth->channel[chan];
3002 preset = fluid_synth_get_preset_by_sfont_name(synth, sfont_name, bank_num,
3007 FLUID_LOG(FLUID_ERR,
3008 "There is no preset with bank number %d and preset number %d in SoundFont %s",
3009 bank_num, preset_num, sfont_name);
3010 FLUID_API_RETURN(FLUID_FAILED);
3013 /* Assign the new SoundFont ID, bank and program number to the channel */
3014 fluid_channel_set_sfont_bank_prog(channel, fluid_sfont_get_id(preset->sfont),
3015 bank_num, preset_num);
3016 result = fluid_synth_set_preset(synth, chan, preset);
3018 FLUID_API_RETURN(result);
3022 * This function assures that every MIDI channel has a valid preset
3023 * (NULL is okay). This function is called after a SoundFont is
3024 * unloaded or reloaded.
3027 fluid_synth_update_presets(fluid_synth_t *synth)
3029 fluid_channel_t *channel;
3030 fluid_preset_t *preset;
3031 int sfont, bank, prog;
3034 for(chan = 0; chan < synth->midi_channels; chan++)
3036 channel = synth->channel[chan];
3037 fluid_channel_get_sfont_bank_prog(channel, &sfont, &bank, &prog);
3038 preset = fluid_synth_get_preset(synth, sfont, bank, prog);
3039 fluid_synth_set_preset(synth, chan, preset);
3043 /* Handler for synth.sample-rate setting. */
3045 fluid_synth_handle_sample_rate(void *data, const char *name, double value)
3047 fluid_synth_t *synth = (fluid_synth_t *)data;
3048 fluid_synth_set_sample_rate(synth, (float) value);
3053 * Set sample rate of the synth.
3054 * @note This function should only be used when no voices or notes are active.
3055 * @param synth FluidSynth instance
3056 * @param sample_rate New sample rate (Hz)
3060 fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate)
3063 fluid_return_if_fail(synth != NULL);
3064 fluid_synth_api_enter(synth);
3065 fluid_clip(sample_rate, 8000.0f, 96000.0f);
3066 synth->sample_rate = sample_rate;
3068 synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
3070 for(i = 0; i < synth->polyphony; i++)
3072 fluid_voice_set_output_rate(synth->voice[i], sample_rate);
3075 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate,
3077 fluid_synth_api_exit(synth);
3081 /* Handler for synth.gain setting. */
3083 fluid_synth_handle_gain(void *data, const char *name, double value)
3085 fluid_synth_t *synth = (fluid_synth_t *)data;
3086 fluid_synth_set_gain(synth, (float) value);
3090 * Set synth output gain value.
3091 * @param synth FluidSynth instance
3092 * @param gain Gain value (function clamps value to the range 0.0 to 10.0)
3095 fluid_synth_set_gain(fluid_synth_t *synth, float gain)
3097 fluid_return_if_fail(synth != NULL);
3098 fluid_synth_api_enter(synth);
3100 fluid_clip(gain, 0.0f, 10.0f);
3103 fluid_synth_update_gain_LOCAL(synth);
3104 fluid_synth_api_exit(synth);
3107 /* Called by synthesis thread to update the gain in all voices */
3109 fluid_synth_update_gain_LOCAL(fluid_synth_t *synth)
3111 fluid_voice_t *voice;
3117 for(i = 0; i < synth->polyphony; i++)
3119 voice = synth->voice[i];
3121 if(fluid_voice_is_playing(voice))
3123 fluid_voice_set_gain(voice, gain);
3129 * Get synth output gain value.
3130 * @param synth FluidSynth instance
3131 * @return Synth gain value (0.0 to 10.0)
3134 fluid_synth_get_gain(fluid_synth_t *synth)
3137 fluid_return_val_if_fail(synth != NULL, 0.0);
3138 fluid_synth_api_enter(synth);
3140 result = synth->gain;
3141 FLUID_API_RETURN(result);
3145 * Handler for synth.polyphony setting.
3148 fluid_synth_handle_polyphony(void *data, const char *name, int value)
3150 fluid_synth_t *synth = (fluid_synth_t *)data;
3151 fluid_synth_set_polyphony(synth, value);
3155 * Set synthesizer polyphony (max number of voices).
3156 * @param synth FluidSynth instance
3157 * @param polyphony Polyphony to assign
3158 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3162 fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony)
3165 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3166 fluid_return_val_if_fail(polyphony >= 1 && polyphony <= 65535, FLUID_FAILED);
3167 fluid_synth_api_enter(synth);
3169 result = fluid_synth_update_polyphony_LOCAL(synth, polyphony);
3171 FLUID_API_RETURN(result);
3174 /* Called by synthesis thread to update the polyphony value */
3176 fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony)
3178 fluid_voice_t *voice;
3181 if(new_polyphony > synth->nvoice)
3183 /* Create more voices */
3184 fluid_voice_t **new_voices = FLUID_REALLOC(synth->voice,
3185 sizeof(fluid_voice_t *) * new_polyphony);
3187 if(new_voices == NULL)
3189 return FLUID_FAILED;
3192 synth->voice = new_voices;
3194 for(i = synth->nvoice; i < new_polyphony; i++)
3196 synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
3198 if(synth->voice[i] == NULL)
3200 return FLUID_FAILED;
3203 fluid_voice_set_custom_filter(synth->voice[i], synth->custom_filter_type, synth->custom_filter_flags);
3206 synth->nvoice = new_polyphony;
3209 synth->polyphony = new_polyphony;
3211 /* turn off any voices above the new limit */
3212 for(i = synth->polyphony; i < synth->nvoice; i++)
3214 voice = synth->voice[i];
3216 if(fluid_voice_is_playing(voice))
3218 fluid_voice_off(voice);
3222 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
3223 synth->polyphony, 0.0f);
3229 * Get current synthesizer polyphony (max number of voices).
3230 * @param synth FluidSynth instance
3231 * @return Synth polyphony value.
3235 fluid_synth_get_polyphony(fluid_synth_t *synth)
3238 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3239 fluid_synth_api_enter(synth);
3241 result = synth->polyphony;
3242 FLUID_API_RETURN(result);
3246 * @brief Get current number of active voices.
3248 * I.e. the no. of voices that have been
3249 * started and have not yet finished. Unless called from synthesis context,
3250 * this number does not necessarily have to be equal to the number of voices
3251 * currently processed by the DSP loop, see below.
3252 * @param synth FluidSynth instance
3253 * @return Number of currently active voices.
3256 * @note To generate accurate continuous statistics of the voice count, caller
3257 * should ensure this function is called synchronously with the audio synthesis
3258 * process. This can be done in the new_fluid_audio_driver2() audio callback
3259 * function for example. Otherwise every call to this function may return different
3260 * voice counts as it may change after any (concurrent) call to fluid_synth_write_*() made by
3261 * e.g. an audio driver or the applications audio rendering thread.
3264 fluid_synth_get_active_voice_count(fluid_synth_t *synth)
3267 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3268 fluid_synth_api_enter(synth);
3270 result = synth->active_voice_count;
3271 FLUID_API_RETURN(result);
3275 * Get the internal synthesis buffer size value.
3276 * @param synth FluidSynth instance
3277 * @return Internal buffer size in audio frames.
3279 * Audio is synthesized this number of frames at a time. Defaults to 64 frames.
3282 fluid_synth_get_internal_bufsize(fluid_synth_t *synth)
3284 return FLUID_BUFSIZE;
3288 * Resend a bank select and a program change for every channel and assign corresponding instruments.
3289 * @param synth FluidSynth instance
3290 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3292 * This function is called mainly after a SoundFont has been loaded,
3293 * unloaded or reloaded.
3296 fluid_synth_program_reset(fluid_synth_t *synth)
3299 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3300 fluid_synth_api_enter(synth);
3302 /* try to set the correct presets */
3303 for(i = 0; i < synth->midi_channels; i++)
3305 fluid_channel_get_sfont_bank_prog(synth->channel[i], NULL, NULL, &prog);
3306 fluid_synth_program_change(synth, i, prog);
3309 FLUID_API_RETURN(FLUID_OK);
3313 * Synthesize a block of floating point audio to separate audio buffers (multichannel rendering). First effect channel used by reverb, second for chorus.
3314 * @param synth FluidSynth instance
3315 * @param len Count of audio frames to synthesize
3316 * @param left Array of float buffers to store left channel of planar audio (as many as \c synth.audio-channels buffers, each of \c len in size)
3317 * @param right Array of float buffers to store right channel of planar audio (size: dito)
3318 * @param fx_left Since 1.1.7: If not \c NULL, array of float buffers to store left effect channels (as many as \c synth.effects-channels buffers, each of \c len in size)
3319 * @param fx_right Since 1.1.7: If not \c NULL, array of float buffers to store right effect channels (size: dito)
3320 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3322 * @note Should only be called from synthesis thread.
3324 * @deprecated fluid_synth_nwrite_float() is deprecated and will be removed in a future release. It may continue to work or it may return #FLUID_FAILED in the future. Consider using the more powerful and flexible fluid_synth_process().
3328 const int FramesToRender = 64;
3330 // retrieve number of stereo audio channels
3331 fluid_settings_getint(settings, "synth.audio-channels", &channels);
3333 // we need twice as many (mono-)buffers
3336 // fluid_synth_nwrite_float renders planar audio, e.g. if synth.audio-channels==16: each midi channel gets rendered to its own stereo buffer, rather than having one buffer and interleaved PCM
3337 float** mix_buf = new float*[channels];
3338 for(int i = 0; i < channels; i++)
3340 mix_buf[i] = new float[FramesToRender];
3343 // retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan) and chrous (second chan))
3344 fluid_settings_getint(settings, "synth.effects-channels", &channels);
3347 float** fx_buf = new float*[channels];
3348 for(int i = 0; i < channels; i++)
3350 fx_buf[i] = new float[FramesToRender];
3353 float** mix_buf_l = mix_buf;
3354 float** mix_buf_r = &mix_buf[channels/2];
3356 float** fx_buf_l = fx_buf;
3357 float** fx_buf_r = &fx_buf[channels/2];
3359 fluid_synth_nwrite_float(synth, FramesToRender, mix_buf_l, mix_buf_r, fx_buf_l, fx_buf_r)
3363 fluid_synth_nwrite_float(fluid_synth_t *synth, int len,
3364 float **left, float **right,
3365 float **fx_left, float **fx_right)
3367 fluid_real_t *left_in, *fx_left_in;
3368 fluid_real_t *right_in, *fx_right_in;
3369 double time = fluid_utime();
3370 int i, num, available, count;
3376 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3377 fluid_return_val_if_fail(left != NULL, FLUID_FAILED);
3378 fluid_return_val_if_fail(right != NULL, FLUID_FAILED);
3380 /* First, take what's still available in the buffer */
3384 if(synth->cur < FLUID_BUFSIZE)
3386 available = FLUID_BUFSIZE - synth->cur;
3387 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3388 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3390 num = (available > len) ? len : available;
3392 bytes = num * sizeof(float);
3395 for(i = 0; i < synth->audio_channels; i++)
3398 FLUID_MEMCPY(left[i], &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3399 FLUID_MEMCPY(right[i], &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3403 for(j = 0; j < num; j++)
3405 left[i][j] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3406 right[i][j] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3412 for(i = 0; i < synth->effects_channels; i++)
3418 FLUID_MEMCPY(fx_left[i], &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3421 if(fx_right != NULL)
3423 FLUID_MEMCPY(fx_right[i], &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3431 for(j = 0; j < num; j++)
3433 fx_left[i][j] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3437 if(fx_right != NULL)
3439 for(j = 0; j < num; j++)
3441 fx_right[i][j] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3449 num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3452 /* Then, run one_block() and copy till we have 'len' samples */
3455 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0);
3456 fluid_synth_render_blocks(synth, 1); // TODO:
3457 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3458 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3460 num = (FLUID_BUFSIZE > len - count) ? len - count : FLUID_BUFSIZE;
3462 bytes = num * sizeof(float);
3465 for(i = 0; i < synth->audio_channels; i++)
3468 FLUID_MEMCPY(left[i] + count, &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3469 FLUID_MEMCPY(right[i] + count, &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3473 for(j = 0; j < num; j++)
3475 left[i][j + count] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3476 right[i][j + count] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3482 for(i = 0; i < synth->effects_channels; i++)
3488 FLUID_MEMCPY(fx_left[i] + count, &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3491 if(fx_right != NULL)
3493 FLUID_MEMCPY(fx_right[i] + count, &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3501 for(j = 0; j < num; j++)
3503 fx_left[i][j + count] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3507 if(fx_right != NULL)
3509 for(j = 0; j < num; j++)
3511 fx_right[i][j + count] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3523 time = fluid_utime() - time;
3524 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3525 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3531 * mixes the samples of \p in to \p out
3533 * @param out the output sample buffer to mix to
3534 * @param ooff sample offset in \p out
3535 * @param in the rvoice_mixer input sample buffer to mix from
3536 * @param ioff sample offset in \p in
3537 * @param buf_idx the sample buffer index of \p in to mix from
3538 * @param num number of samples to mix
3540 static FLUID_INLINE void fluid_synth_mix_single_buffer(float *FLUID_RESTRICT out,
3542 const fluid_real_t *FLUID_RESTRICT in,
3551 for(j = 0; j < num; j++)
3553 out[j + ooff] += (float) in[buf_idx * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + ioff];
3559 * @brief Synthesize floating point audio to stereo audio channels (implements the default interface #fluid_audio_func_t).
3561 * Synthesize and <strong>mix</strong> audio to a given number of planar audio buffers.
3562 * Therefore pass <code>nout = N*2</code> float buffers to \p out in order to render
3563 * the synthesized audio to \p N stereo channels. Each float buffer must be
3564 * able to hold \p len elements.
3566 * \p out contains an array of planar buffers for normal, dry, stereo
3567 * audio (alternating left and right). Like:
3569 out[0] = left_buffer_audio_channel_0
3570 out[1] = right_buffer_audio_channel_0
3571 out[2] = left_buffer_audio_channel_1
3572 out[3] = right_buffer_audio_channel_1
3574 out[ (i * 2 + 0) % nout ] = left_buffer_audio_channel_i
3575 out[ (i * 2 + 1) % nout ] = right_buffer_audio_channel_i
3578 * for zero-based channel index \p i.
3579 * The buffer layout of \p fx used for storing effects
3580 * like reverb and chorus looks similar:
3582 fx[0] = left_buffer_channel_of_reverb_unit_0
3583 fx[1] = right_buffer_channel_of_reverb_unit_0
3584 fx[2] = left_buffer_channel_of_chorus_unit_0
3585 fx[3] = right_buffer_channel_of_chorus_unit_0
3586 fx[4] = left_buffer_channel_of_reverb_unit_1
3587 fx[5] = right_buffer_channel_of_reverb_unit_1
3588 fx[6] = left_buffer_channel_of_chorus_unit_1
3589 fx[7] = right_buffer_channel_of_chorus_unit_1
3590 fx[8] = left_buffer_channel_of_reverb_unit_2
3592 fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 0) % nfx ] = left_buffer_for_effect_channel_j_of_unit_k
3593 fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 1) % nfx ] = right_buffer_for_effect_channel_j_of_unit_k
3595 * where <code>0 <= k < fluid_synth_count_effects_groups()</code> is a zero-based index denoting the effects unit and
3596 * <code>0 <= j < fluid_synth_count_effects_channels()</code> is a zero-based index denoting the effect channel within
3599 * Any voice playing is assigned to audio channels based on the MIDI channel its playing on. Let \p chan be the
3600 * zero-based MIDI channel index an arbitrary voice is playing on. To determine the audio channel and effects unit it is
3601 * going to be rendered to use:
3603 * <code>i = chan % fluid_synth_count_audio_groups()</code>
3605 * <code>k = chan % fluid_synth_count_effects_groups()</code>
3607 * @param synth FluidSynth instance
3608 * @param len Count of audio frames to synthesize and store in every single buffer provided by \p out and \p fx.
3609 * @param nfx Count of arrays in \c fx. Must be a multiple of 2 (because of stereo)
3610 * and in the range <code>0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
3611 * @param fx Array of buffers to store effects audio to. Buffers may
3612 alias with buffers of \c out. NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
3613 * @param nout Count of arrays in \c out. Must be a multiple of 2
3614 (because of stereo) and in the range <code>0 <= nout/2 <= fluid_synth_count_audio_channels()</code>.
3615 * @param out Array of buffers to store (dry) audio to. Buffers may
3616 alias with buffers of \c fx. NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
3617 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
3620 * @note The owner of the sample buffers must zero them out before calling this
3621 * function, because any synthesized audio is mixed (i.e. added) to the buffers.
3622 * E.g. if fluid_synth_process() is called from a custom audio driver process function
3623 * (see new_fluid_audio_driver2()), the audio driver takes care of zeroing the buffers.
3627 * @note No matter how many buffers you pass in, fluid_synth_process()
3628 * will always render all audio channels to the
3629 * buffers in \c out and all effects channels to the
3630 * buffers in \c fx, provided that <code>nout > 0</code> and <code>nfx > 0</code> respectively. If
3631 * <code>nout/2 < fluid_synth_count_audio_channels()</code> it will wrap around. Same
3632 * is true for effects audio if <code>nfx/2 < (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
3633 * See usage examples below.
3637 * @note Should only be called from synthesis thread.
3641 fluid_synth_process(fluid_synth_t *synth, int len, int nfx, float *fx[],
3642 int nout, float *out[])
3644 fluid_real_t *left_in, *fx_left_in;
3645 fluid_real_t *right_in, *fx_right_in;
3646 int nfxchan, nfxunits, naudchan;
3648 double time = fluid_utime();
3649 int i, f, num, count;
3653 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3654 fluid_return_val_if_fail(nfx % 2 == 0, FLUID_FAILED);
3655 fluid_return_val_if_fail(nout % 2 == 0, FLUID_FAILED);
3657 nfxchan = synth->effects_channels;
3658 nfxunits = synth->effects_groups;
3659 naudchan = synth->audio_channels;
3661 fluid_return_val_if_fail(0 <= nfx / 2 && nfx / 2 <= nfxchan * nfxunits, FLUID_FAILED);
3662 fluid_return_val_if_fail(0 <= nout / 2 && nout / 2 <= naudchan, FLUID_FAILED);
3664 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3665 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3666 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, FALSE);
3669 /* First, take what's still available in the buffer */
3673 if(synth->cur < FLUID_BUFSIZE)
3675 int available = FLUID_BUFSIZE - synth->cur;
3676 num = (available > len) ? len : available;
3680 for(i = 0; i < naudchan; i++)
3682 float *out_buf = out[(i * 2) % nout];
3683 fluid_synth_mix_single_buffer(out_buf, 0, left_in, synth->cur, i, num);
3685 out_buf = out[(i * 2 + 1) % nout];
3686 fluid_synth_mix_single_buffer(out_buf, 0, right_in, synth->cur, i, num);
3692 // loop over all effects units
3693 for(f = 0; f < nfxunits; f++)
3695 // write out all effects (i.e. reverb and chorus)
3696 for(i = 0; i < nfxchan; i++)
3698 int buf_idx = f * nfxchan + i;
3700 float *out_buf = fx[(buf_idx * 2) % nfx];
3701 fluid_synth_mix_single_buffer(out_buf, 0, fx_left_in, synth->cur, buf_idx, num);
3703 out_buf = fx[(buf_idx * 2 + 1) % nfx];
3704 fluid_synth_mix_single_buffer(out_buf, 0, fx_right_in, synth->cur, buf_idx, num);
3710 num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3713 /* Then, render blocks and copy till we have 'len' samples */
3716 int blocksleft = (len - count + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3717 int blockcount = fluid_synth_render_blocks(synth, blocksleft);
3719 num = (blockcount * FLUID_BUFSIZE > len - count) ? len - count : blockcount * FLUID_BUFSIZE;
3723 for(i = 0; i < naudchan; i++)
3725 float *out_buf = out[(i * 2) % nout];
3726 fluid_synth_mix_single_buffer(out_buf, count, left_in, 0, i, num);
3728 out_buf = out[(i * 2 + 1) % nout];
3729 fluid_synth_mix_single_buffer(out_buf, count, right_in, 0, i, num);
3735 // loop over all effects units
3736 for(f = 0; f < nfxunits; f++)
3738 // write out all effects (i.e. reverb and chorus)
3739 for(i = 0; i < nfxchan; i++)
3741 int buf_idx = f * nfxchan + i;
3743 float *out_buf = fx[(buf_idx * 2) % nfx];
3744 fluid_synth_mix_single_buffer(out_buf, count, fx_left_in, 0, buf_idx, num);
3746 out_buf = fx[(buf_idx * 2 + 1) % nfx];
3747 fluid_synth_mix_single_buffer(out_buf, count, fx_right_in, 0, buf_idx, num);
3757 time = fluid_utime() - time;
3758 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3759 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3765 * Synthesize a block of floating point audio samples to audio buffers.
3766 * @param synth FluidSynth instance
3767 * @param len Count of audio frames to synthesize
3768 * @param lout Array of floats to store left channel of audio
3769 * @param loff Offset index in 'lout' for first sample
3770 * @param lincr Increment between samples stored to 'lout'
3771 * @param rout Array of floats to store right channel of audio
3772 * @param roff Offset index in 'rout' for first sample
3773 * @param rincr Increment between samples stored to 'rout'
3774 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3776 * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
3777 * lincr = 2, rincr = 2).
3779 * @note Should only be called from synthesis thread.
3780 * @note Reverb and Chorus are mixed to \c lout resp. \c rout.
3783 fluid_synth_write_float(fluid_synth_t *synth, int len,
3784 void *lout, int loff, int lincr,
3785 void *rout, int roff, int rincr)
3788 float *left_out = (float *) lout;
3789 float *right_out = (float *) rout;
3790 fluid_real_t *left_in;
3791 fluid_real_t *right_in;
3792 double time = fluid_utime();
3795 fluid_profile_ref_var(prof_ref);
3797 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3798 fluid_return_val_if_fail(lout != NULL, FLUID_FAILED);
3799 fluid_return_val_if_fail(rout != NULL, FLUID_FAILED);
3801 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
3803 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3805 for(i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr)
3807 /* fill up the buffers as needed */
3808 if(l >= synth->curmax)
3810 int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3811 synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
3812 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3817 left_out[j] = (float) left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l];
3818 right_out[k] = (float) right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l];
3823 time = fluid_utime() - time;
3824 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3825 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3827 fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
3828 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
3833 #define DITHER_SIZE 48000
3834 #define DITHER_CHANNELS 2
3836 static float rand_table[DITHER_CHANNELS][DITHER_SIZE];
3838 /* Init dither table */
3845 for(c = 0; c < DITHER_CHANNELS; c++)
3849 for(i = 0; i < DITHER_SIZE - 1; i++)
3851 d = rand() / (float)RAND_MAX - 0.5f;
3852 rand_table[c][i] = d - dp;
3856 rand_table[c][DITHER_SIZE - 1] = 0 - dp;
3860 /* A portable replacement for roundf(), seems it may actually be faster too! */
3861 static FLUID_INLINE int16_t
3862 round_clip_to_i16(float x)
3868 i = (long)(x + 0.5f);
3870 if(FLUID_UNLIKELY(i > 32767))
3877 i = (long)(x - 0.5f);
3879 if(FLUID_UNLIKELY(i < -32768))
3889 * Synthesize a block of 16 bit audio samples to audio buffers.
3890 * @param synth FluidSynth instance
3891 * @param len Count of audio frames to synthesize
3892 * @param lout Array of 16 bit words to store left channel of audio
3893 * @param loff Offset index in 'lout' for first sample
3894 * @param lincr Increment between samples stored to 'lout'
3895 * @param rout Array of 16 bit words to store right channel of audio
3896 * @param roff Offset index in 'rout' for first sample
3897 * @param rincr Increment between samples stored to 'rout'
3898 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3900 * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
3901 * lincr = 2, rincr = 2).
3903 * @note Should only be called from synthesis thread.
3904 * @note Reverb and Chorus are mixed to \c lout resp. \c rout.
3905 * @note Dithering is performed when converting from internal floating point to
3909 fluid_synth_write_s16(fluid_synth_t *synth, int len,
3910 void *lout, int loff, int lincr,
3911 void *rout, int roff, int rincr)
3914 int16_t *left_out = lout;
3915 int16_t *right_out = rout;
3916 fluid_real_t *left_in;
3917 fluid_real_t *right_in;
3918 double time = fluid_utime();
3922 fluid_profile_ref_var(prof_ref);
3924 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
3925 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3928 di = synth->dither_index;
3930 for(i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr)
3933 /* fill up the buffers as needed */
3934 if(cur >= synth->curmax)
3936 int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3937 synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
3938 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3942 left_out[j] = round_clip_to_i16(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]);
3943 right_out[k] = round_clip_to_i16(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]);
3945 if(++di >= DITHER_SIZE)
3952 synth->dither_index = di; /* keep dither buffer continous */
3954 time = fluid_utime() - time;
3955 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3956 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3958 fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
3959 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
3965 * Converts stereo floating point sample data to signed 16 bit data with dithering.
3966 * @param dither_index Pointer to an integer which should be initialized to 0
3967 * before the first call and passed unmodified to additional calls which are
3968 * part of the same synthesis output.
3969 * @param len Length in frames to convert
3970 * @param lin Buffer of left audio samples to convert from
3971 * @param rin Buffer of right audio samples to convert from
3972 * @param lout Array of 16 bit words to store left channel of audio
3973 * @param loff Offset index in 'lout' for first sample
3974 * @param lincr Increment between samples stored to 'lout'
3975 * @param rout Array of 16 bit words to store right channel of audio
3976 * @param roff Offset index in 'rout' for first sample
3977 * @param rincr Increment between samples stored to 'rout'
3979 * @note Currently private to libfluidsynth.
3982 fluid_synth_dither_s16(int *dither_index, int len, const float *lin, const float *rin,
3983 void *lout, int loff, int lincr,
3984 void *rout, int roff, int rincr)
3987 int16_t *left_out = lout;
3988 int16_t *right_out = rout;
3989 int di = *dither_index;
3990 fluid_profile_ref_var(prof_ref);
3992 for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr)
3994 left_out[j] = round_clip_to_i16(lin[i] * 32766.0f + rand_table[0][di]);
3995 right_out[k] = round_clip_to_i16(rin[i] * 32766.0f + rand_table[1][di]);
3997 if(++di >= DITHER_SIZE)
4003 *dither_index = di; /* keep dither buffer continous */
4005 fluid_profile(FLUID_PROF_WRITE, prof_ref, 0, len);
4009 fluid_synth_check_finished_voices(fluid_synth_t *synth)
4014 while(NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler)))
4016 for(j = 0; j < synth->polyphony; j++)
4018 if(synth->voice[j]->rvoice == fv)
4020 fluid_voice_unlock_rvoice(synth->voice[j]);
4021 fluid_voice_stop(synth->voice[j]);
4024 else if(synth->voice[j]->overflow_rvoice == fv)
4026 fluid_voice_overflow_rvoice_finished(synth->voice[j]);
4034 * Process all waiting events in the rvoice queue.
4035 * Make sure no (other) rendering is running in parallel when
4036 * you call this function!
4038 void fluid_synth_process_event_queue(fluid_synth_t *synth)
4040 fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4045 * Process blocks (FLUID_BUFSIZE) of audio.
4046 * Must be called from renderer thread only!
4047 * @return number of blocks rendered. Might (often) return less than requested
4050 fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount)
4053 fluid_profile_ref_var(prof_ref);
4055 /* Assign ID of synthesis thread */
4056 // synth->synth_thread_id = fluid_thread_get_id ();
4058 fluid_check_fpe("??? Just starting up ???");
4060 fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4062 /* do not render more blocks than we can store internally */
4063 maxblocks = fluid_rvoice_mixer_get_bufcount(synth->eventhandler->mixer);
4065 if(blockcount > maxblocks)
4067 blockcount = maxblocks;
4070 for(i = 0; i < blockcount; i++)
4072 fluid_sample_timer_process(synth);
4073 fluid_synth_add_ticks(synth, FLUID_BUFSIZE);
4075 /* If events have been queued waiting for fluid_rvoice_eventhandler_dispatch_all()
4076 * (should only happen with parallel render) stop processing and go for rendering
4078 if(fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler))
4080 // Something has happened, we can't process more
4086 fluid_check_fpe("fluid_sample_timer_process");
4088 blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount);
4090 /* Testcase, that provokes a denormal floating point error */
4101 fluid_check_fpe("??? Remainder of synth_one_block ???");
4102 fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref,
4103 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
4104 blockcount * FLUID_BUFSIZE);
4109 * Handler for synth.reverb.* and synth.chorus.* double settings.
4111 static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value)
4113 fluid_synth_t *synth = (fluid_synth_t *)data;
4114 fluid_return_if_fail(synth != NULL);
4116 if(FLUID_STRCMP(name, "synth.reverb.room-size") == 0)
4118 fluid_synth_set_reverb_roomsize(synth, value);
4120 else if(FLUID_STRCMP(name, "synth.reverb.damp") == 0)
4122 fluid_synth_set_reverb_damp(synth, value);
4124 else if(FLUID_STRCMP(name, "synth.reverb.width") == 0)
4126 fluid_synth_set_reverb_width(synth, value);
4128 else if(FLUID_STRCMP(name, "synth.reverb.level") == 0)
4130 fluid_synth_set_reverb_level(synth, value);
4132 else if(FLUID_STRCMP(name, "synth.chorus.depth") == 0)
4134 fluid_synth_set_chorus_depth(synth, value);
4136 else if(FLUID_STRCMP(name, "synth.chorus.speed") == 0)
4138 fluid_synth_set_chorus_speed(synth, value);
4140 else if(FLUID_STRCMP(name, "synth.chorus.level") == 0)
4142 fluid_synth_set_chorus_level(synth, value);
4147 * Handler for synth.reverb.* and synth.chorus.* integer settings.
4149 static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value)
4151 fluid_synth_t *synth = (fluid_synth_t *)data;
4152 fluid_return_if_fail(synth != NULL);
4154 if(FLUID_STRCMP(name, "synth.reverb.active") == 0)
4156 fluid_synth_set_reverb_on(synth, value);
4158 else if(FLUID_STRCMP(name, "synth.chorus.active") == 0)
4160 fluid_synth_set_chorus_on(synth, value);
4162 else if(FLUID_STRCMP(name, "synth.chorus.nr") == 0)
4164 fluid_synth_set_chorus_nr(synth, value);
4169 * Handler for synth.overflow.* settings.
4171 static void fluid_synth_handle_overflow(void *data, const char *name, double value)
4173 fluid_synth_t *synth = (fluid_synth_t *)data;
4174 fluid_return_if_fail(synth != NULL);
4176 fluid_synth_api_enter(synth);
4178 if(FLUID_STRCMP(name, "synth.overflow.percussion") == 0)
4180 synth->overflow.percussion = value;
4182 else if(FLUID_STRCMP(name, "synth.overflow.released") == 0)
4184 synth->overflow.released = value;
4186 else if(FLUID_STRCMP(name, "synth.overflow.sustained") == 0)
4188 synth->overflow.sustained = value;
4190 else if(FLUID_STRCMP(name, "synth.overflow.volume") == 0)
4192 synth->overflow.volume = value;
4194 else if(FLUID_STRCMP(name, "synth.overflow.age") == 0)
4196 synth->overflow.age = value;
4198 else if(FLUID_STRCMP(name, "synth.overflow.important") == 0)
4200 synth->overflow.important = value;
4203 fluid_synth_api_exit(synth);
4206 /* Selects a voice for killing. */
4207 static fluid_voice_t *
4208 fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth)
4211 float best_prio = OVERFLOW_PRIO_CANNOT_KILL - 1;
4212 float this_voice_prio;
4213 fluid_voice_t *voice;
4214 int best_voice_index = -1;
4215 unsigned int ticks = fluid_synth_get_ticks(synth);
4217 for(i = 0; i < synth->polyphony; i++)
4220 voice = synth->voice[i];
4222 /* safeguard against an available voice. */
4223 if(_AVAILABLE(voice))
4228 this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow,
4231 /* check if this voice has less priority than the previous candidate. */
4232 if(this_voice_prio < best_prio)
4234 best_voice_index = i;
4235 best_prio = this_voice_prio;
4239 if(best_voice_index < 0)
4244 voice = synth->voice[best_voice_index];
4245 FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ",
4246 fluid_voice_get_id(voice), best_voice_index, fluid_voice_get_channel(voice), fluid_voice_get_key(voice));
4247 fluid_voice_off(voice);
4254 * Allocate a synthesis voice.
4255 * @param synth FluidSynth instance
4256 * @param sample Sample to assign to the voice
4257 * @param chan MIDI channel number (0 to MIDI channel count - 1)
4258 * @param key MIDI note number for the voice (0-127)
4259 * @param vel MIDI velocity for the voice (0-127)
4260 * @return Allocated synthesis voice or NULL on error
4262 * This function is called by a SoundFont's preset in response to a noteon event.
4263 * The returned voice comes with default modulators and generators.
4264 * A single noteon event may create any number of voices, when the preset is layered.
4266 * @note Should only be called from within synthesis thread, which includes
4267 * SoundFont loader preset noteon method.
4270 fluid_synth_alloc_voice(fluid_synth_t *synth, fluid_sample_t *sample,
4271 int chan, int key, int vel)
4273 fluid_return_val_if_fail(sample != NULL, NULL);
4274 FLUID_API_ENTRY_CHAN(NULL);
4275 FLUID_API_RETURN(fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, NULL));
4280 fluid_synth_alloc_voice_LOCAL(fluid_synth_t *synth, fluid_sample_t *sample, int chan, int key, int vel, fluid_zone_range_t *zone_range)
4283 fluid_voice_t *voice = NULL;
4284 fluid_channel_t *channel = NULL;
4287 /* check if there's an available synthesis process */
4288 for(i = 0; i < synth->polyphony; i++)
4290 if(_AVAILABLE(synth->voice[i]))
4292 voice = synth->voice[i];
4297 /* No success yet? Then stop a running voice. */
4300 FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice");
4301 voice = fluid_synth_free_voice_by_kill_LOCAL(synth);
4306 FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
4310 ticks = fluid_synth_get_ticks(synth);
4316 for(i = 0; i < synth->polyphony; i++)
4318 if(!_AVAILABLE(synth->voice[i]))
4324 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
4325 chan, key, vel, synth->storeid,
4326 (float) ticks / 44100.0f,
4327 (fluid_curtime() - synth->start) / 1000.0f,
4332 channel = synth->channel[chan];
4334 if(fluid_voice_init(voice, sample, zone_range, channel, key, vel,
4335 synth->storeid, ticks, synth->gain) != FLUID_OK)
4337 FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
4341 /* add the default modulators to the synthesis process. */
4342 /* custom_breath2att_modulator is not a default modulator specified in SF
4343 it is intended to replace default_vel2att_mod for this channel on demand using
4344 API fluid_synth_set_breath_mode() or shell command setbreathmode for this channel.
4347 int mono = fluid_channel_is_playing_mono(channel);
4348 fluid_mod_t *default_mod = synth->default_mod;
4350 while(default_mod != NULL)
4353 /* See if default_mod is the velocity_to_attenuation modulator */
4354 fluid_mod_test_identity(default_mod, &default_vel2att_mod) &&
4355 // See if a replacement by custom_breath2att_modulator has been demanded
4357 ((!mono && (channel->mode & FLUID_CHANNEL_BREATH_POLY)) ||
4358 (mono && (channel->mode & FLUID_CHANNEL_BREATH_MONO)))
4361 // Replacement of default_vel2att modulator by custom_breath2att_modulator
4362 fluid_voice_add_mod_local(voice, &custom_breath2att_mod, FLUID_VOICE_DEFAULT, 0);
4366 fluid_voice_add_mod_local(voice, default_mod, FLUID_VOICE_DEFAULT, 0);
4369 // Next default modulator to add to the voice
4370 default_mod = default_mod->next;
4377 /* Kill all voices on a given channel, which have the same exclusive class
4378 * generator as new_voice.
4381 fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
4382 fluid_voice_t *new_voice)
4384 int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS);
4387 /* Excl. class 0: No exclusive class */
4393 /* Kill all notes on the same channel with the same exclusive class */
4394 for(i = 0; i < synth->polyphony; i++)
4396 fluid_voice_t *existing_voice = synth->voice[i];
4397 int existing_excl_class = fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS);
4399 /* If voice is playing, on the same channel, has same exclusive
4400 * class and is not part of the same noteon event (voice group), then kill it */
4402 if(fluid_voice_is_playing(existing_voice)
4403 && fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice)
4404 && existing_excl_class == excl_class
4405 && fluid_voice_get_id(existing_voice) != fluid_voice_get_id(new_voice))
4407 fluid_voice_kill_excl(existing_voice);
4413 * Activate a voice previously allocated with fluid_synth_alloc_voice().
4414 * @param synth FluidSynth instance
4415 * @param voice Voice to activate
4417 * This function is called by a SoundFont's preset in response to a noteon
4418 * event. Exclusive classes are processed here.
4420 * @note Should only be called from within synthesis thread, which includes
4421 * SoundFont loader preset noteon method.
4424 fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice)
4426 fluid_return_if_fail(synth != NULL);
4427 fluid_return_if_fail(voice != NULL);
4428 // fluid_return_if_fail (fluid_synth_is_synth_thread (synth));
4429 fluid_synth_api_enter(synth);
4431 /* Find the exclusive class of this voice. If set, kill all voices
4432 * that match the exclusive class and are younger than the first
4433 * voice process created by this noteon event. */
4434 fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice);
4436 fluid_voice_start(voice); /* Start the new voice */
4437 fluid_voice_lock_rvoice(voice);
4438 fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice);
4439 fluid_synth_api_exit(synth);
4443 * Add a SoundFont loader to the synth. This function takes ownership of \c loader
4444 * and frees it automatically upon \c synth destruction.
4445 * @param synth FluidSynth instance
4446 * @param loader Loader API structure
4448 * SoundFont loaders are used to add custom instrument loading to FluidSynth.
4449 * The caller supplied functions for loading files, allocating presets,
4450 * retrieving information on them and synthesizing note-on events. Using this
4451 * method even non SoundFont instruments can be synthesized, although limited
4452 * to the SoundFont synthesis model.
4454 * @note Should only be called before any SoundFont files are loaded.
4457 fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader)
4459 fluid_return_if_fail(synth != NULL);
4460 fluid_return_if_fail(loader != NULL);
4461 fluid_synth_api_enter(synth);
4463 /* Test if sfont is already loaded */
4464 if(synth->sfont == NULL)
4466 synth->loaders = fluid_list_prepend(synth->loaders, loader);
4469 fluid_synth_api_exit(synth);
4473 * Load a SoundFont file (filename is interpreted by SoundFont loaders).
4474 * The newly loaded SoundFont will be put on top of the SoundFont
4475 * stack. Presets are searched starting from the SoundFont on the
4476 * top of the stack, working the way down the stack until a preset is found.
4478 * @param synth FluidSynth instance
4479 * @param filename File to load
4480 * @param reset_presets TRUE to re-assign presets for all MIDI channels (equivalent to calling fluid_synth_program_reset())
4481 * @return SoundFont ID on success, #FLUID_FAILED on error
4484 fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets)
4486 fluid_sfont_t *sfont;
4488 fluid_sfloader_t *loader;
4491 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4492 fluid_return_val_if_fail(filename != NULL, FLUID_FAILED);
4493 fluid_synth_api_enter(synth);
4495 sfont_id = synth->sfont_id;
4497 if(++sfont_id != FLUID_FAILED)
4499 /* MT NOTE: Loaders list should not change. */
4501 for(list = synth->loaders; list; list = fluid_list_next(list))
4503 loader = (fluid_sfloader_t *) fluid_list_get(list);
4505 sfont = fluid_sfloader_load(loader, filename);
4510 synth->sfont_id = sfont->id = sfont_id;
4512 synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
4514 /* reset the presets for all channels if requested */
4517 fluid_synth_program_reset(synth);
4520 FLUID_API_RETURN(sfont_id);
4525 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
4526 FLUID_API_RETURN(FLUID_FAILED);
4530 * Unload a SoundFont.
4531 * @param synth FluidSynth instance
4532 * @param id ID of SoundFont to unload
4533 * @param reset_presets TRUE to re-assign presets for all MIDI channels
4534 * @return #FLUID_OK on success, #FLUID_FAILED on error
4537 fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets)
4539 fluid_sfont_t *sfont = NULL;
4542 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4543 fluid_synth_api_enter(synth);
4545 /* remove the SoundFont from the list */
4546 for(list = synth->sfont; list; list = fluid_list_next(list))
4548 sfont = fluid_list_get(list);
4550 if(fluid_sfont_get_id(sfont) == id)
4552 synth->sfont = fluid_list_remove(synth->sfont, sfont);
4559 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
4560 FLUID_API_RETURN(FLUID_FAILED);
4563 /* reset the presets for all channels (SoundFont will be freed when there are no more references) */
4566 fluid_synth_program_reset(synth);
4570 fluid_synth_update_presets(synth);
4573 /* -- Remove synth->sfont list's reference to SoundFont */
4574 fluid_synth_sfont_unref(synth, sfont);
4576 FLUID_API_RETURN(FLUID_OK);
4579 /* Unref a SoundFont and destroy if no more references */
4581 fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont)
4583 fluid_return_if_fail(sfont != NULL); /* Shouldn't happen, programming error if so */
4585 sfont->refcount--; /* -- Remove the sfont list's reference */
4587 if(sfont->refcount == 0) /* No more references? - Attempt delete */
4589 if(fluid_sfont_delete_internal(sfont) == 0) /* SoundFont loader can block SoundFont unload */
4591 FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
4592 } /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */
4595 new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, TRUE, TRUE, FALSE);
4600 /* Callback to continually attempt to unload a SoundFont,
4601 * only if a SoundFont loader blocked the unload operation */
4603 fluid_synth_sfunload_callback(void *data, unsigned int msec)
4605 fluid_sfont_t *sfont = data;
4607 if(fluid_sfont_delete_internal(sfont) == 0)
4609 FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
4619 * Reload a SoundFont. The SoundFont retains its ID and index on the SoundFont stack.
4620 * @param synth FluidSynth instance
4621 * @param id ID of SoundFont to reload
4622 * @return SoundFont ID on success, #FLUID_FAILED on error
4625 fluid_synth_sfreload(fluid_synth_t *synth, int id)
4627 char *filename = NULL;
4628 fluid_sfont_t *sfont;
4629 fluid_sfloader_t *loader;
4631 int index, ret = FLUID_FAILED;
4633 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4634 fluid_synth_api_enter(synth);
4636 /* Search for SoundFont and get its index */
4637 for(list = synth->sfont, index = 0; list; list = fluid_list_next(list), index++)
4639 sfont = fluid_list_get(list);
4641 if(fluid_sfont_get_id(sfont) == id)
4649 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
4653 /* keep a copy of the SoundFont's filename */
4654 filename = FLUID_STRDUP(fluid_sfont_get_name(sfont));
4656 if(filename == NULL || fluid_synth_sfunload(synth, id, FALSE) != FLUID_OK)
4661 /* MT Note: SoundFont loader list will not change */
4663 for(list = synth->loaders; list; list = fluid_list_next(list))
4665 loader = (fluid_sfloader_t *) fluid_list_get(list);
4667 sfont = fluid_sfloader_load(loader, filename);
4674 synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont); /* insert the sfont at the same index */
4676 /* reset the presets for all channels */
4677 fluid_synth_update_presets(synth);
4683 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
4686 FLUID_FREE(filename);
4687 FLUID_API_RETURN(ret);
4691 * Add a SoundFont. The SoundFont will be added to the top of the SoundFont stack.
4692 * @param synth FluidSynth instance
4693 * @param sfont SoundFont to add
4694 * @return New assigned SoundFont ID or #FLUID_FAILED on error
4697 fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
4701 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4702 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
4703 fluid_synth_api_enter(synth);
4705 sfont_id = synth->sfont_id;
4707 if(++sfont_id != FLUID_FAILED)
4709 synth->sfont_id = sfont->id = sfont_id;
4710 synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
4712 /* reset the presets for all channels */
4713 fluid_synth_program_reset(synth);
4716 FLUID_API_RETURN(sfont_id);
4720 * Remove a SoundFont from the SoundFont stack without deleting it.
4721 * @param synth FluidSynth instance
4722 * @param sfont SoundFont to remove
4723 * @return #FLUID_OK if \c sfont successfully removed, #FLUID_FAILED otherwise
4725 * SoundFont is not freed and is left as the responsibility of the caller.
4727 * @note The SoundFont should only be freed after there are no presets
4728 * referencing it. This can only be ensured by the SoundFont loader and
4729 * therefore this function should not normally be used.
4732 fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
4734 fluid_sfont_t *sfont_tmp;
4736 int ret = FLUID_FAILED;
4738 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4739 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
4740 fluid_synth_api_enter(synth);
4742 /* remove the SoundFont from the list */
4743 for(list = synth->sfont; list; list = fluid_list_next(list))
4745 sfont_tmp = fluid_list_get(list);
4747 if(sfont_tmp == sfont)
4749 synth->sfont = fluid_list_remove(synth->sfont, sfont_tmp);
4755 /* reset the presets for all channels */
4756 fluid_synth_program_reset(synth);
4758 FLUID_API_RETURN(ret);
4762 * Count number of loaded SoundFont files.
4763 * @param synth FluidSynth instance
4764 * @return Count of loaded SoundFont files.
4767 fluid_synth_sfcount(fluid_synth_t *synth)
4771 fluid_return_val_if_fail(synth != NULL, 0);
4772 fluid_synth_api_enter(synth);
4773 count = fluid_list_size(synth->sfont);
4774 FLUID_API_RETURN(count);
4778 * Get SoundFont by index.
4779 * @param synth FluidSynth instance
4780 * @param num SoundFont index on the stack (starting from 0 for top of stack).
4781 * @return SoundFont instance or NULL if invalid index
4783 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4784 * the duration of use of the returned pointer.
4787 fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num)
4789 fluid_sfont_t *sfont = NULL;
4792 fluid_return_val_if_fail(synth != NULL, NULL);
4793 fluid_synth_api_enter(synth);
4794 list = fluid_list_nth(synth->sfont, num);
4798 sfont = fluid_list_get(list);
4801 FLUID_API_RETURN(sfont);
4805 * Get SoundFont by ID.
4806 * @param synth FluidSynth instance
4807 * @param id SoundFont ID
4808 * @return SoundFont instance or NULL if invalid ID
4810 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4811 * the duration of use of the returned pointer.
4814 fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id)
4816 fluid_sfont_t *sfont = NULL;
4819 fluid_return_val_if_fail(synth != NULL, NULL);
4820 fluid_synth_api_enter(synth);
4822 for(list = synth->sfont; list; list = fluid_list_next(list))
4824 sfont = fluid_list_get(list);
4826 if(fluid_sfont_get_id(sfont) == id)
4832 FLUID_API_RETURN(list ? sfont : NULL);
4836 * Get SoundFont by name.
4837 * @param synth FluidSynth instance
4838 * @param name Name of SoundFont
4839 * @return SoundFont instance or NULL if invalid name
4842 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4843 * the duration of use of the returned pointer.
4846 fluid_synth_get_sfont_by_name(fluid_synth_t *synth, const char *name)
4848 fluid_sfont_t *sfont = NULL;
4851 fluid_return_val_if_fail(synth != NULL, NULL);
4852 fluid_return_val_if_fail(name != NULL, NULL);
4853 fluid_synth_api_enter(synth);
4855 for(list = synth->sfont; list; list = fluid_list_next(list))
4857 sfont = fluid_list_get(list);
4859 if(FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0)
4865 FLUID_API_RETURN(list ? sfont : NULL);
4869 * Get active preset on a MIDI channel.
4870 * @param synth FluidSynth instance
4871 * @param chan MIDI channel number (0 to MIDI channel count - 1)
4872 * @return Preset or NULL if no preset active on \c chan
4874 * @note Should only be called from within synthesis thread, which includes
4875 * SoundFont loader preset noteon methods. Not thread safe otherwise.
4878 fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan)
4880 fluid_preset_t *result;
4881 fluid_channel_t *channel;
4882 FLUID_API_ENTRY_CHAN(NULL);
4884 channel = synth->channel[chan];
4885 result = channel->preset;
4886 fluid_synth_api_exit(synth);
4891 * Get list of currently playing voices.
4892 * @param synth FluidSynth instance
4893 * @param buf Array to store voices to (NULL terminated if not filled completely)
4894 * @param bufsize Count of indexes in buf
4895 * @param id Voice ID to search for or < 0 to return list of all playing voices
4897 * @note Should only be called from within synthesis thread, which includes
4898 * SoundFont loader preset noteon methods. Voices are only guaranteed to remain
4899 * unchanged until next synthesis process iteration.
4902 fluid_synth_get_voicelist(fluid_synth_t *synth, fluid_voice_t *buf[], int bufsize,
4908 fluid_return_if_fail(synth != NULL);
4909 fluid_return_if_fail(buf != NULL);
4910 fluid_synth_api_enter(synth);
4912 for(i = 0; i < synth->polyphony && count < bufsize; i++)
4914 fluid_voice_t *voice = synth->voice[i];
4916 if(fluid_voice_is_playing(voice) && (id < 0 || (int)voice->id == id))
4918 buf[count++] = voice;
4927 fluid_synth_api_exit(synth);
4931 * Enable or disable reverb effect.
4932 * @param synth FluidSynth instance
4933 * @param on TRUE to enable reverb, FALSE to disable
4936 fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
4938 fluid_return_if_fail(synth != NULL);
4940 fluid_synth_api_enter(synth);
4942 synth->with_reverb = (on != 0);
4943 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled,
4945 fluid_synth_api_exit(synth);
4949 * Activate a reverb preset.
4950 * @param synth FluidSynth instance
4951 * @param num Reverb preset number
4952 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4954 * @note Currently private to libfluidsynth.
4957 fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
4959 fluid_return_val_if_fail(
4960 num < FLUID_N_ELEMENTS(revmodel_preset),
4964 fluid_synth_set_reverb(synth, revmodel_preset[num].roomsize,
4965 revmodel_preset[num].damp, revmodel_preset[num].width,
4966 revmodel_preset[num].level);
4971 * Set reverb parameters.
4972 * @param synth FluidSynth instance
4973 * @param roomsize Reverb room size value (0.0-1.0)
4974 * @param damping Reverb damping value (0.0-1.0)
4975 * @param width Reverb width value (0.0-100.0)
4976 * @param level Reverb level value (0.0-1.0)
4977 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4979 * @note Not realtime safe and therefore should not be called from synthesis
4980 * context at the risk of stalling audio output.
4983 fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping,
4984 double width, double level)
4986 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ALL,
4987 roomsize, damping, width, level);
4991 * Set reverb roomsize. See fluid_synth_set_reverb() for further info.
4992 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4994 int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
4996 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ROOMSIZE, roomsize, 0, 0, 0);
5000 * Set reverb damping. See fluid_synth_set_reverb() for further info.
5001 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5003 int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
5005 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_DAMPING, 0, damping, 0, 0);
5009 * Set reverb width. See fluid_synth_set_reverb() for further info.
5010 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5012 int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
5014 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_WIDTH, 0, 0, width, 0);
5018 * Set reverb level. See fluid_synth_set_reverb() for further info.
5019 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5021 int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
5023 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_LEVEL, 0, 0, 0, level);
5027 * Set one or more reverb parameters.
5028 * @param synth FluidSynth instance
5029 * @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
5030 * @param roomsize Reverb room size value (0.0-1.2)
5031 * @param damping Reverb damping value (0.0-1.0)
5032 * @param width Reverb width value (0.0-100.0)
5033 * @param level Reverb level value (0.0-1.0)
5034 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5036 * @note Not realtime safe and therefore should not be called from synthesis
5037 * context at the risk of stalling audio output.
5040 fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize,
5041 double damping, double width, double level)
5045 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5046 /* if non of the flags is set, fail */
5047 fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
5049 /* Synth shadow values are set here so that they will be returned if querried */
5051 fluid_synth_api_enter(synth);
5052 ret = fluid_synth_set_reverb_full_LOCAL(synth, set, roomsize, damping, width, level);
5053 FLUID_API_RETURN(ret);
5057 fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize,
5058 double damping, double width, double level)
5061 fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5063 if(set & FLUID_REVMODEL_SET_ROOMSIZE)
5065 synth->reverb_roomsize = roomsize;
5068 if(set & FLUID_REVMODEL_SET_DAMPING)
5070 synth->reverb_damping = damping;
5073 if(set & FLUID_REVMODEL_SET_WIDTH)
5075 synth->reverb_width = width;
5078 if(set & FLUID_REVMODEL_SET_LEVEL)
5080 synth->reverb_level = level;
5084 param[1].real = roomsize;
5085 param[2].real = damping;
5086 param[3].real = width;
5087 param[4].real = level;
5088 /* finally enqueue an rvoice event to the mixer to actual update reverb */
5089 ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5090 fluid_rvoice_mixer_set_reverb_params,
5091 synth->eventhandler->mixer,
5097 * Get reverb room size.
5098 * @param synth FluidSynth instance
5099 * @return Reverb room size (0.0-1.2)
5102 fluid_synth_get_reverb_roomsize(fluid_synth_t *synth)
5105 fluid_return_val_if_fail(synth != NULL, 0.0);
5106 fluid_synth_api_enter(synth);
5107 result = synth->reverb_roomsize;
5108 FLUID_API_RETURN(result);
5112 * Get reverb damping.
5113 * @param synth FluidSynth instance
5114 * @return Reverb damping value (0.0-1.0)
5117 fluid_synth_get_reverb_damp(fluid_synth_t *synth)
5120 fluid_return_val_if_fail(synth != NULL, 0.0);
5121 fluid_synth_api_enter(synth);
5123 result = synth->reverb_damping;
5124 FLUID_API_RETURN(result);
5129 * @param synth FluidSynth instance
5130 * @return Reverb level value (0.0-1.0)
5133 fluid_synth_get_reverb_level(fluid_synth_t *synth)
5136 fluid_return_val_if_fail(synth != NULL, 0.0);
5137 fluid_synth_api_enter(synth);
5139 result = synth->reverb_level;
5140 FLUID_API_RETURN(result);
5145 * @param synth FluidSynth instance
5146 * @return Reverb width value (0.0-100.0)
5149 fluid_synth_get_reverb_width(fluid_synth_t *synth)
5152 fluid_return_val_if_fail(synth != NULL, 0.0);
5153 fluid_synth_api_enter(synth);
5155 result = synth->reverb_width;
5156 FLUID_API_RETURN(result);
5160 * Enable or disable chorus effect.
5161 * @param synth FluidSynth instance
5162 * @param on TRUE to enable chorus, FALSE to disable
5165 fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
5167 fluid_return_if_fail(synth != NULL);
5168 fluid_synth_api_enter(synth);
5170 synth->with_chorus = (on != 0);
5171 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled,
5173 fluid_synth_api_exit(synth);
5177 * Set chorus parameters. It should be turned on with fluid_synth_set_chorus_on().
5178 * Keep in mind, that the needed CPU time is proportional to 'nr'.
5179 * @param synth FluidSynth instance
5180 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
5182 * @param level Chorus level (0.0-10.0)
5183 * @param speed Chorus speed in Hz (0.29-5.0)
5184 * @param depth_ms Chorus depth (max value depends on synth sample rate,
5185 * 0.0-21.0 is safe for sample rate values up to 96KHz)
5186 * @param type Chorus waveform type (#fluid_chorus_mod)
5187 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5189 int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
5190 double speed, double depth_ms, int type)
5192 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_ALL, nr, level, speed,
5197 * Set the chorus voice count. See fluid_synth_set_chorus() for further info.
5198 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5200 int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
5202 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_NR, nr, 0, 0, 0, 0);
5206 * Set the chorus level. See fluid_synth_set_chorus() for further info.
5207 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5209 int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
5211 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_LEVEL, 0, level, 0, 0, 0);
5215 * Set the chorus speed. See fluid_synth_set_chorus() for further info.
5216 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5218 int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
5220 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_SPEED, 0, 0, speed, 0, 0);
5224 * Set the chorus depth. See fluid_synth_set_chorus() for further info.
5225 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5227 int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
5229 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_DEPTH, 0, 0, 0, depth_ms, 0);
5233 * Set the chorus type. See fluid_synth_set_chorus() for further info.
5234 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5236 int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
5238 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_TYPE, 0, 0, 0, 0, type);
5242 * Set one or more chorus parameters.
5243 * @param synth FluidSynth instance
5244 * @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t)
5245 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
5247 * @param level Chorus level (0.0-10.0)
5248 * @param speed Chorus speed in Hz (0.29-5.0)
5249 * @param depth_ms Chorus depth (max value depends on synth sample rate,
5250 * 0.0-21.0 is safe for sample rate values up to 96KHz)
5251 * @param type Chorus waveform type (#fluid_chorus_mod)
5252 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5255 fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level,
5256 double speed, double depth_ms, int type)
5260 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5261 /* if non of the flags is set, fail */
5262 fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
5264 /* Synth shadow values are set here so that they will be returned if queried */
5265 fluid_synth_api_enter(synth);
5267 ret = fluid_synth_set_chorus_full_LOCAL(synth, set, nr, level, speed, depth_ms, type);
5269 FLUID_API_RETURN(ret);
5273 fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level,
5274 double speed, double depth_ms, int type)
5277 fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5279 if(set & FLUID_CHORUS_SET_NR)
5281 synth->chorus_nr = nr;
5284 if(set & FLUID_CHORUS_SET_LEVEL)
5286 synth->chorus_level = level;
5289 if(set & FLUID_CHORUS_SET_SPEED)
5291 synth->chorus_speed = speed;
5294 if(set & FLUID_CHORUS_SET_DEPTH)
5296 synth->chorus_depth = depth_ms;
5299 if(set & FLUID_CHORUS_SET_TYPE)
5301 synth->chorus_type = type;
5306 param[2].real = level;
5307 param[3].real = speed;
5308 param[4].real = depth_ms;
5310 ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5311 fluid_rvoice_mixer_set_chorus_params,
5312 synth->eventhandler->mixer,
5319 * Get chorus voice number (delay line count) value.
5320 * @param synth FluidSynth instance
5321 * @return Chorus voice count (0-99)
5324 fluid_synth_get_chorus_nr(fluid_synth_t *synth)
5327 fluid_return_val_if_fail(synth != NULL, 0.0);
5328 fluid_synth_api_enter(synth);
5330 result = synth->chorus_nr;
5331 FLUID_API_RETURN(result);
5336 * @param synth FluidSynth instance
5337 * @return Chorus level value (0.0-10.0)
5340 fluid_synth_get_chorus_level(fluid_synth_t *synth)
5343 fluid_return_val_if_fail(synth != NULL, 0.0);
5344 fluid_synth_api_enter(synth);
5346 result = synth->chorus_level;
5347 FLUID_API_RETURN(result);
5351 * Get chorus speed in Hz.
5352 * @param synth FluidSynth instance
5353 * @return Chorus speed in Hz (0.29-5.0)
5356 fluid_synth_get_chorus_speed(fluid_synth_t *synth)
5359 fluid_return_val_if_fail(synth != NULL, 0.0);
5360 fluid_synth_api_enter(synth);
5362 result = synth->chorus_speed;
5363 FLUID_API_RETURN(result);
5368 * @param synth FluidSynth instance
5369 * @return Chorus depth
5372 fluid_synth_get_chorus_depth(fluid_synth_t *synth)
5375 fluid_return_val_if_fail(synth != NULL, 0.0);
5376 fluid_synth_api_enter(synth);
5378 result = synth->chorus_depth;
5379 FLUID_API_RETURN(result);
5383 * Get chorus waveform type.
5384 * @param synth FluidSynth instance
5385 * @return Chorus waveform type (#fluid_chorus_mod)
5388 fluid_synth_get_chorus_type(fluid_synth_t *synth)
5391 fluid_return_val_if_fail(synth != NULL, 0.0);
5392 fluid_synth_api_enter(synth);
5394 result = synth->chorus_type;
5395 FLUID_API_RETURN(result);
5399 * If the same note is hit twice on the same channel, then the older
5400 * voice process is advanced to the release stage. Using a mechanical
5401 * MIDI controller, the only way this can happen is when the sustain
5402 * pedal is held. In this case the behaviour implemented here is
5403 * natural for many instruments. Note: One noteon event can trigger
5404 * several voice processes, for example a stereo sample. Don't
5408 fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan,
5412 fluid_voice_t *voice;
5414 /* storeid is a parameter for fluid_voice_init() */
5415 synth->storeid = synth->noteid++;
5417 /* for "monophonic playing" key is the previous sustained note
5418 if it exists (0 to 127) or INVALID_NOTE otherwise */
5419 if(key == INVALID_NOTE)
5424 for(i = 0; i < synth->polyphony; i++)
5426 voice = synth->voice[i];
5428 if(fluid_voice_is_playing(voice)
5429 && (fluid_voice_get_channel(voice) == chan)
5430 && (fluid_voice_get_key(voice) == key)
5431 && (fluid_voice_get_id(voice) != synth->noteid))
5433 /* Id of voices that was sustained by sostenuto */
5434 if(fluid_voice_is_sostenuto(voice))
5436 synth->storeid = fluid_voice_get_id(voice);
5439 /* Force the voice into release stage (pedaling is ignored) */
5440 fluid_voice_release(voice);
5446 * Set synthesis interpolation method on one or all MIDI channels.
5447 * @param synth FluidSynth instance
5448 * @param chan MIDI channel to set interpolation method on or -1 for all channels
5449 * @param interp_method Interpolation method (#fluid_interp)
5450 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5453 fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method)
5457 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5458 fluid_synth_api_enter(synth);
5460 if(chan < -1 || chan >= synth->midi_channels)
5462 FLUID_API_RETURN(FLUID_FAILED);
5465 if(synth->channel[0] == NULL)
5467 FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!");
5468 FLUID_API_RETURN(FLUID_FAILED);
5471 for(i = 0; i < synth->midi_channels; i++)
5473 if(chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan)
5475 fluid_channel_set_interp_method(synth->channel[i], interp_method);
5479 FLUID_API_RETURN(FLUID_OK);
5483 * Get the total count of MIDI channels.
5484 * @param synth FluidSynth instance
5485 * @return Count of MIDI channels
5488 fluid_synth_count_midi_channels(fluid_synth_t *synth)
5491 fluid_return_val_if_fail(synth != NULL, 0);
5492 fluid_synth_api_enter(synth);
5494 result = synth->midi_channels;
5495 FLUID_API_RETURN(result);
5499 * Get the total count of audio channels.
5500 * @param synth FluidSynth instance
5501 * @return Count of audio channel stereo pairs (1 = 2 channels, 2 = 4, etc)
5504 fluid_synth_count_audio_channels(fluid_synth_t *synth)
5507 fluid_return_val_if_fail(synth != NULL, 0);
5508 fluid_synth_api_enter(synth);
5510 result = synth->audio_channels;
5511 FLUID_API_RETURN(result);
5515 * Get the total number of allocated audio channels. Usually identical to the
5516 * number of audio channels. Can be employed by LADSPA effects subsystem.
5518 * @param synth FluidSynth instance
5519 * @return Count of audio group stereo pairs (1 = 2 channels, 2 = 4, etc)
5522 fluid_synth_count_audio_groups(fluid_synth_t *synth)
5525 fluid_return_val_if_fail(synth != NULL, 0);
5526 fluid_synth_api_enter(synth);
5528 result = synth->audio_groups;
5529 FLUID_API_RETURN(result);
5533 * Get the total number of allocated effects channels.
5534 * @param synth FluidSynth instance
5535 * @return Count of allocated effects channels
5538 fluid_synth_count_effects_channels(fluid_synth_t *synth)
5541 fluid_return_val_if_fail(synth != NULL, 0);
5542 fluid_synth_api_enter(synth);
5544 result = synth->effects_channels;
5545 FLUID_API_RETURN(result);
5549 * Get the total number of allocated effects units.
5550 * @param synth FluidSynth instance
5551 * @return Count of allocated effects units
5554 fluid_synth_count_effects_groups(fluid_synth_t *synth)
5557 fluid_return_val_if_fail(synth != NULL, 0);
5558 fluid_synth_api_enter(synth);
5560 result = synth->effects_groups;
5561 FLUID_API_RETURN(result);
5565 * Get the synth CPU load value.
5566 * @param synth FluidSynth instance
5567 * @return Estimated CPU load value in percent (0-100)
5570 fluid_synth_get_cpu_load(fluid_synth_t *synth)
5572 fluid_return_val_if_fail(synth != NULL, 0);
5573 return fluid_atomic_float_get(&synth->cpu_load);
5576 /* Get tuning for a given bank:program */
5577 static fluid_tuning_t *
5578 fluid_synth_get_tuning(fluid_synth_t *synth, int bank, int prog)
5581 if((synth->tuning == NULL) ||
5582 (synth->tuning[bank] == NULL) ||
5583 (synth->tuning[bank][prog] == NULL))
5588 return synth->tuning[bank][prog];
5591 /* Replace tuning on a given bank:program (need not already exist).
5592 * Synth mutex should already be locked by caller. */
5594 fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth, fluid_tuning_t *tuning,
5595 int bank, int prog, int apply)
5597 fluid_tuning_t *old_tuning;
5599 if(synth->tuning == NULL)
5601 synth->tuning = FLUID_ARRAY(fluid_tuning_t **, 128);
5603 if(synth->tuning == NULL)
5605 FLUID_LOG(FLUID_PANIC, "Out of memory");
5606 return FLUID_FAILED;
5609 FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t **));
5612 if(synth->tuning[bank] == NULL)
5614 synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t *, 128);
5616 if(synth->tuning[bank] == NULL)
5618 FLUID_LOG(FLUID_PANIC, "Out of memory");
5619 return FLUID_FAILED;
5622 FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t *));
5625 old_tuning = synth->tuning[bank][prog];
5626 synth->tuning[bank][prog] = tuning;
5630 if(!fluid_tuning_unref(old_tuning, 1)) /* -- unref old tuning */
5632 /* Replace old tuning if present */
5633 fluid_synth_replace_tuning_LOCAL(synth, old_tuning, tuning, apply, FALSE);
5640 /* Replace a tuning with a new one in all MIDI channels. new_tuning can be
5641 * NULL, in which case channels are reset to default equal tempered scale. */
5643 fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth, fluid_tuning_t *old_tuning,
5644 fluid_tuning_t *new_tuning, int apply, int unref_new)
5646 fluid_channel_t *channel;
5647 int old_tuning_unref = 0;
5650 for(i = 0; i < synth->midi_channels; i++)
5652 channel = synth->channel[i];
5654 if(fluid_channel_get_tuning(channel) == old_tuning)
5660 fluid_tuning_ref(new_tuning); /* ++ ref new tuning for channel */
5663 fluid_channel_set_tuning(channel, new_tuning);
5667 fluid_synth_update_voice_tuning_LOCAL(synth, channel);
5672 /* Send unref old tuning event if any unrefs */
5673 if(old_tuning && old_tuning_unref)
5675 fluid_tuning_unref(old_tuning, old_tuning_unref);
5678 if(!unref_new || !new_tuning)
5683 fluid_tuning_unref(new_tuning, 1);
5686 /* Update voice tunings in realtime */
5688 fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth, fluid_channel_t *channel)
5690 fluid_voice_t *voice;
5693 for(i = 0; i < synth->polyphony; i++)
5695 voice = synth->voice[i];
5697 if(fluid_voice_is_on(voice) && (voice->channel == channel))
5699 fluid_voice_calculate_gen_pitch(voice);
5700 fluid_voice_update_param(voice, GEN_PITCH);
5706 * Set the tuning of the entire MIDI note scale.
5707 * @param synth FluidSynth instance
5708 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5709 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5710 * @param name Label name for this tuning
5711 * @param pitch Array of pitch values (length of 128, each value is number of
5712 * cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
5713 * Pass NULL to create a equal tempered (normal) scale.
5714 * @param apply TRUE to apply new tuning in realtime to existing notes which
5715 * are using the replaced tuning (if any), FALSE otherwise
5716 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5720 fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog,
5721 const char *name, const double *pitch, int apply)
5723 fluid_tuning_t *tuning;
5724 int retval = FLUID_OK;
5726 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5727 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5728 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5729 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
5731 fluid_synth_api_enter(synth);
5733 tuning = new_fluid_tuning(name, bank, prog);
5739 fluid_tuning_set_all(tuning, pitch);
5742 retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
5744 if(retval == FLUID_FAILED)
5746 fluid_tuning_unref(tuning, 1);
5751 retval = FLUID_FAILED;
5754 FLUID_API_RETURN(retval);
5758 * Activate an octave tuning on every octave in the MIDI note scale.
5759 * @param synth FluidSynth instance
5760 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5761 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5762 * @param name Label name for this tuning
5763 * @param pitch Array of pitch values (length of 12 for each note of an octave
5764 * starting at note C, values are number of offset cents to add to the normal
5766 * @param apply TRUE to apply new tuning in realtime to existing notes which
5767 * are using the replaced tuning (if any), FALSE otherwise
5768 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5772 fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog,
5773 const char *name, const double *pitch, int apply)
5775 fluid_tuning_t *tuning;
5776 int retval = FLUID_OK;
5778 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5779 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5780 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5781 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
5782 fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
5784 fluid_synth_api_enter(synth);
5785 tuning = new_fluid_tuning(name, bank, prog);
5789 fluid_tuning_set_octave(tuning, pitch);
5790 retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
5792 if(retval == FLUID_FAILED)
5794 fluid_tuning_unref(tuning, 1);
5799 retval = FLUID_FAILED;
5802 FLUID_API_RETURN(retval);
5806 * Set tuning values for one or more MIDI notes for an existing tuning.
5807 * @param synth FluidSynth instance
5808 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5809 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5810 * @param len Number of MIDI notes to assign
5811 * @param key Array of MIDI key numbers (length of 'len', values 0-127)
5812 * @param pitch Array of pitch values (length of 'len', values are number of
5813 * cents from MIDI note 0)
5814 * @param apply TRUE to apply tuning change in realtime to existing notes using
5815 * the specified tuning, FALSE otherwise
5816 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5818 * @note Prior to version 1.1.0 it was an error to specify a tuning that didn't
5819 * already exist. Starting with 1.1.0, the default equal tempered scale will be
5820 * used as a basis, if no tuning exists for the given bank and prog.
5823 fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog,
5824 int len, const int *key, const double *pitch, int apply)
5826 fluid_tuning_t *old_tuning, *new_tuning;
5827 int retval = FLUID_OK;
5830 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5831 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5832 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5833 fluid_return_val_if_fail(len > 0, FLUID_FAILED);
5834 fluid_return_val_if_fail(key != NULL, FLUID_FAILED);
5835 fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
5837 fluid_synth_api_enter(synth);
5839 old_tuning = fluid_synth_get_tuning(synth, bank, prog);
5843 new_tuning = fluid_tuning_duplicate(old_tuning);
5847 new_tuning = new_fluid_tuning("Unnamed", bank, prog);
5852 for(i = 0; i < len; i++)
5854 fluid_tuning_set_pitch(new_tuning, key[i], pitch[i]);
5857 retval = fluid_synth_replace_tuning_LOCK(synth, new_tuning, bank, prog, apply);
5859 if(retval == FLUID_FAILED)
5861 fluid_tuning_unref(new_tuning, 1);
5866 retval = FLUID_FAILED;
5869 FLUID_API_RETURN(retval);
5873 * Activate a tuning scale on a MIDI channel.
5874 * @param synth FluidSynth instance
5875 * @param chan MIDI channel number (0 to MIDI channel count - 1)
5876 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5877 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5878 * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
5879 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5882 * @note A default equal tempered scale will be created, if no tuning exists
5883 * on the given bank and prog.
5886 fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog,
5889 fluid_tuning_t *tuning;
5890 int retval = FLUID_OK;
5892 //fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
5893 //fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
5894 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5895 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5897 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5899 tuning = fluid_synth_get_tuning(synth, bank, prog);
5901 /* If no tuning exists, create a new default tuning. We do this, so that
5902 * it can be replaced later, if any changes are made. */
5905 tuning = new_fluid_tuning("Unnamed", bank, prog);
5909 fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, FALSE);
5915 fluid_tuning_ref(tuning); /* ++ ref for outside of lock */
5920 FLUID_API_RETURN(FLUID_FAILED);
5923 fluid_tuning_ref(tuning); /* ++ ref new tuning for following function */
5924 retval = fluid_synth_set_tuning_LOCAL(synth, chan, tuning, apply);
5926 fluid_tuning_unref(tuning, 1); /* -- unref for outside of lock */
5928 FLUID_API_RETURN(retval);
5931 /* Local synthesis thread set tuning function (takes over tuning reference) */
5933 fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
5934 fluid_tuning_t *tuning, int apply)
5936 fluid_tuning_t *old_tuning;
5937 fluid_channel_t *channel;
5939 channel = synth->channel[chan];
5941 old_tuning = fluid_channel_get_tuning(channel);
5942 fluid_channel_set_tuning(channel, tuning); /* !! Takes over callers reference */
5946 fluid_synth_update_voice_tuning_LOCAL(synth, channel);
5949 /* Send unref old tuning event */
5952 fluid_tuning_unref(old_tuning, 1);
5960 * Clear tuning scale on a MIDI channel (use default equal tempered scale).
5961 * @param synth FluidSynth instance
5962 * @param chan MIDI channel number (0 to MIDI channel count - 1)
5963 * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
5964 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5968 fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply)
5970 int retval = FLUID_OK;
5972 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5974 retval = fluid_synth_set_tuning_LOCAL(synth, chan, NULL, apply);
5976 FLUID_API_RETURN(retval);
5980 * Start tuning iteration.
5981 * @param synth FluidSynth instance
5984 fluid_synth_tuning_iteration_start(fluid_synth_t *synth)
5986 fluid_return_if_fail(synth != NULL);
5987 fluid_synth_api_enter(synth);
5988 fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER(0));
5989 fluid_synth_api_exit(synth);
5993 * Advance to next tuning.
5994 * @param synth FluidSynth instance
5995 * @param bank Location to store MIDI bank number of next tuning scale
5996 * @param prog Location to store MIDI program number of next tuning scale
5997 * @return 1 if tuning iteration advanced, 0 if no more tunings
6000 fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog)
6005 fluid_return_val_if_fail(synth != NULL, 0);
6006 fluid_return_val_if_fail(bank != NULL, 0);
6007 fluid_return_val_if_fail(prog != NULL, 0);
6008 fluid_synth_api_enter(synth);
6010 /* Current tuning iteration stored as: bank << 8 | program */
6011 pval = fluid_private_get(synth->tuning_iter);
6012 p = FLUID_POINTER_TO_INT(pval);
6013 b = (p >> 8) & 0xFF;
6018 FLUID_API_RETURN(0);
6021 for(; b < 128; b++, p = 0)
6023 if(synth->tuning[b] == NULL)
6030 if(synth->tuning[b][p] == NULL)
6040 fluid_private_set(synth->tuning_iter,
6041 FLUID_INT_TO_POINTER(b << 8 | (p + 1)));
6045 fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER((b + 1) << 8));
6048 FLUID_API_RETURN(1);
6052 FLUID_API_RETURN(0);
6056 * Get the entire note tuning for a given MIDI bank and program.
6057 * @param synth FluidSynth instance
6058 * @param bank MIDI bank number of tuning
6059 * @param prog MIDI program number of tuning
6060 * @param name Location to store tuning name or NULL to ignore
6061 * @param len Maximum number of chars to store to 'name' (including NULL byte)
6062 * @param pitch Array to store tuning scale to or NULL to ignore (len of 128)
6063 * @return #FLUID_OK if matching tuning was found, #FLUID_FAILED otherwise
6066 fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog,
6067 char *name, int len, double *pitch)
6069 fluid_tuning_t *tuning;
6071 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6072 fluid_synth_api_enter(synth);
6074 tuning = fluid_synth_get_tuning(synth, bank, prog);
6080 FLUID_SNPRINTF(name, len - 1, "%s", fluid_tuning_get_name(tuning));
6081 name[len - 1] = 0; /* make sure the string is null terminated */
6086 FLUID_MEMCPY(pitch, fluid_tuning_get_all(tuning), 128 * sizeof(double));
6090 FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED);
6094 * Get settings assigned to a synth.
6095 * @param synth FluidSynth instance
6096 * @return FluidSynth settings which are assigned to the synth
6099 fluid_synth_get_settings(fluid_synth_t *synth)
6101 fluid_return_val_if_fail(synth != NULL, NULL);
6103 return synth->settings;
6107 * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
6108 * @param synth FluidSynth instance
6109 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6110 * @param param SoundFont generator ID (#fluid_gen_type)
6111 * @param value Offset or absolute generator value to assign to the MIDI channel
6112 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6114 * This function allows for setting all effect parameters in real time on a
6115 * MIDI channel. Setting absolute to non-zero will cause the value to override
6116 * any generator values set in the instruments played on the MIDI channel.
6117 * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
6118 * generator parameters and valid ranges.
6120 int fluid_synth_set_gen(fluid_synth_t *synth, int chan, int param, float value)
6122 return fluid_synth_set_gen2(synth, chan, param, value, FALSE, FALSE);
6126 * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
6127 * @param synth FluidSynth instance
6128 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6129 * @param param SoundFont generator ID (#fluid_gen_type)
6130 * @param value Offset or absolute generator value to assign to the MIDI channel
6131 * @param absolute FALSE to assign a relative value, TRUE to assign an absolute value
6132 * @param normalized FALSE if value is specified in the native units of the generator,
6133 * TRUE to take the value as a 0.0-1.0 range and apply it to the valid
6134 * generator effect range (scaled and shifted as necessary).
6135 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6137 * This function allows for setting all effect parameters in real time on a
6138 * MIDI channel. Setting absolute to non-zero will cause the value to override
6139 * any generator values set in the instruments played on the MIDI channel.
6140 * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
6141 * generator parameters and valid ranges.
6144 fluid_synth_set_gen2(fluid_synth_t *synth, int chan, int param,
6145 float value, int absolute, int normalized)
6148 fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
6149 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6151 v = normalized ? fluid_gen_scale(param, value) : value;
6153 fluid_synth_set_gen_LOCAL(synth, chan, param, v, absolute);
6155 FLUID_API_RETURN(FLUID_OK);
6158 /* Synthesis thread local set gen function */
6160 fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, int param, float value,
6163 fluid_voice_t *voice;
6166 fluid_channel_set_gen(synth->channel[chan], param, value, absolute);
6168 for(i = 0; i < synth->polyphony; i++)
6170 voice = synth->voice[i];
6172 if(fluid_voice_get_channel(voice) == chan)
6174 fluid_voice_set_param(voice, param, value, absolute);
6180 * Get generator value assigned to a MIDI channel.
6181 * @param synth FluidSynth instance
6182 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6183 * @param param SoundFont generator ID (#fluid_gen_type)
6184 * @return Current generator value assigned to MIDI channel
6187 fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param)
6190 fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
6191 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6193 result = fluid_channel_get_gen(synth->channel[chan], param);
6194 FLUID_API_RETURN(result);
6198 * Handle MIDI event from MIDI router, used as a callback function.
6199 * @param data FluidSynth instance
6200 * @param event MIDI event to handle
6201 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6204 fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event)
6206 fluid_synth_t *synth = (fluid_synth_t *) data;
6207 int type = fluid_midi_event_get_type(event);
6208 int chan = fluid_midi_event_get_channel(event);
6213 return fluid_synth_noteon(synth, chan,
6214 fluid_midi_event_get_key(event),
6215 fluid_midi_event_get_velocity(event));
6218 return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event));
6220 case CONTROL_CHANGE:
6221 return fluid_synth_cc(synth, chan,
6222 fluid_midi_event_get_control(event),
6223 fluid_midi_event_get_value(event));
6225 case PROGRAM_CHANGE:
6226 return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
6228 case CHANNEL_PRESSURE:
6229 return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
6232 return fluid_synth_key_pressure(synth, chan,
6233 fluid_midi_event_get_key(event),
6234 fluid_midi_event_get_value(event));
6237 return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));
6239 case MIDI_SYSTEM_RESET:
6240 return fluid_synth_system_reset(synth);
6243 return fluid_synth_sysex(synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE);
6247 case MIDI_SET_TEMPO:
6251 return FLUID_FAILED;
6255 * Create and start voices using a preset and a MIDI note on event.
6256 * @param synth FluidSynth instance
6257 * @param id Voice group ID to use (can be used with fluid_synth_stop()).
6258 * @param preset Preset to synthesize
6259 * @param audio_chan Unused currently, set to 0
6260 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6261 * @param key MIDI note number (0-127)
6262 * @param vel MIDI velocity number (1-127)
6263 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6265 * @note Should only be called from within synthesis thread, which includes
6266 * SoundFont loader preset noteon method.
6269 fluid_synth_start(fluid_synth_t *synth, unsigned int id, fluid_preset_t *preset,
6270 int audio_chan, int chan, int key, int vel)
6273 fluid_return_val_if_fail(preset != NULL, FLUID_FAILED);
6274 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
6275 fluid_return_val_if_fail(vel >= 1 && vel <= 127, FLUID_FAILED);
6276 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6277 synth->storeid = id;
6278 result = fluid_preset_noteon(preset, synth, chan, key, vel);
6279 FLUID_API_RETURN(result);
6283 * Stop notes for a given note event voice ID.
6284 * @param synth FluidSynth instance
6285 * @param id Voice note event ID
6286 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6288 * @note In FluidSynth versions prior to 1.1.0 #FLUID_FAILED would be returned
6289 * if no matching voice note event ID was found. Versions after 1.1.0 only
6290 * return #FLUID_FAILED if an error occurs.
6293 fluid_synth_stop(fluid_synth_t *synth, unsigned int id)
6296 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6297 fluid_synth_api_enter(synth);
6298 fluid_synth_stop_LOCAL(synth, id);
6300 FLUID_API_RETURN(result);
6303 /* Local synthesis thread variant of fluid_synth_stop */
6305 fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id)
6307 fluid_voice_t *voice;
6310 for(i = 0; i < synth->polyphony; i++)
6312 voice = synth->voice[i];
6314 if(fluid_voice_is_on(voice) && (fluid_voice_get_id(voice) == id))
6316 fluid_voice_noteoff(voice);
6322 * Offset the bank numbers of a loaded SoundFont, i.e.\ subtract
6323 * \c offset from any bank number when assigning instruments.
6325 * @param synth FluidSynth instance
6326 * @param sfont_id ID of a loaded SoundFont
6327 * @param offset Bank offset value to apply to all instruments
6328 * @return #FLUID_OK if the offset was set successfully, #FLUID_FAILED otherwise
6331 fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset)
6333 fluid_sfont_t *sfont;
6336 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6337 fluid_synth_api_enter(synth);
6339 for(list = synth->sfont; list; list = fluid_list_next(list))
6341 sfont = fluid_list_get(list);
6343 if(fluid_sfont_get_id(sfont) == sfont_id)
6345 sfont->bankofs = offset;
6352 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
6353 FLUID_API_RETURN(FLUID_FAILED);
6356 FLUID_API_RETURN(FLUID_OK);
6360 * Get bank offset of a loaded SoundFont.
6361 * @param synth FluidSynth instance
6362 * @param sfont_id ID of a loaded SoundFont
6363 * @return SoundFont bank offset value
6366 fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id)
6368 fluid_sfont_t *sfont;
6372 fluid_return_val_if_fail(synth != NULL, 0);
6373 fluid_synth_api_enter(synth);
6375 for(list = synth->sfont; list; list = fluid_list_next(list))
6377 sfont = fluid_list_get(list);
6379 if(fluid_sfont_get_id(sfont) == sfont_id)
6381 offset = sfont->bankofs;
6388 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
6389 FLUID_API_RETURN(0);
6392 FLUID_API_RETURN(offset);
6396 fluid_synth_api_enter(fluid_synth_t *synth)
6398 if(synth->use_mutex)
6400 fluid_rec_mutex_lock(synth->mutex);
6403 if(!synth->public_api_count)
6405 fluid_synth_check_finished_voices(synth);
6408 synth->public_api_count++;
6411 void fluid_synth_api_exit(fluid_synth_t *synth)
6413 synth->public_api_count--;
6415 if(!synth->public_api_count)
6417 fluid_rvoice_eventhandler_flush(synth->eventhandler);
6420 if(synth->use_mutex)
6422 fluid_rec_mutex_unlock(synth->mutex);
6428 * Set midi channel type
6429 * @param synth FluidSynth instance
6430 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6431 * @param type MIDI channel type (#fluid_midi_channel_type)
6432 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6435 int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type)
6437 fluid_return_val_if_fail((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED);
6438 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6440 synth->channel[chan]->channel_type = type;
6442 FLUID_API_RETURN(FLUID_OK);
6447 * Return the LADSPA effects instance used by FluidSynth
6449 * @param synth FluidSynth instance
6450 * @return pointer to LADSPA fx or NULL if compiled without LADSPA support or LADSPA is not active
6452 fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
6454 fluid_return_val_if_fail(synth != NULL, NULL);
6456 return synth->ladspa_fx;
6461 * Configure a general-purpose IIR biquad filter.
6463 * This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard.
6464 * By default this filter is off (#FLUID_IIR_DISABLED).
6466 * @param synth FluidSynth instance
6467 * @param type Type of the IIR filter to use (see #fluid_iir_filter_type)
6468 * @param flags Additional flags to customize this filter or zero to stay with the default (see #fluid_iir_filter_flags)
6470 * @return #FLUID_OK if the settings have been successfully applied, otherwise #FLUID_FAILED
6472 int fluid_synth_set_custom_filter(fluid_synth_t *synth, int type, int flags)
6475 fluid_voice_t *voice;
6477 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6478 fluid_return_val_if_fail(type >= FLUID_IIR_DISABLED && type < FLUID_IIR_LAST, FLUID_FAILED);
6480 fluid_synth_api_enter(synth);
6482 synth->custom_filter_type = type;
6483 synth->custom_filter_flags = flags;
6485 for(i = 0; i < synth->polyphony; i++)
6487 voice = synth->voice[i];
6489 fluid_voice_set_custom_filter(voice, type, flags);
6492 FLUID_API_RETURN(FLUID_OK);
6496 * Set the important channels for voice overflow priority calculation.
6498 * @param synth FluidSynth instance
6499 * @param channels comma-separated list of channel numbers
6500 * @return #FLUID_OK on success, otherwise #FLUID_FAILED
6502 static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels)
6505 int retval = FLUID_FAILED;
6508 fluid_overflow_prio_t *scores;
6510 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6512 scores = &synth->overflow;
6514 if(scores->num_important_channels < synth->midi_channels)
6516 scores->important_channels = FLUID_REALLOC(scores->important_channels,
6517 sizeof(*scores->important_channels) * synth->midi_channels);
6519 if(scores->important_channels == NULL)
6521 FLUID_LOG(FLUID_ERR, "Out of memory");
6525 scores->num_important_channels = synth->midi_channels;
6528 FLUID_MEMSET(scores->important_channels, FALSE,
6529 sizeof(*scores->important_channels) * scores->num_important_channels);
6531 if(channels != NULL)
6533 values = FLUID_ARRAY(int, synth->midi_channels);
6537 FLUID_LOG(FLUID_ERR, "Out of memory");
6541 /* Every channel given in the comma-separated list of channel numbers
6542 * is set to TRUE, i.e. flagging it as "important". Channel numbers are
6544 num_values = fluid_settings_split_csv(channels, values, synth->midi_channels);
6546 for(i = 0; i < num_values; i++)
6548 if(values[i] > 0 && values[i] <= synth->midi_channels)
6550 scores->important_channels[values[i] - 1] = TRUE;
6563 * Handler for synth.overflow.important-channels setting.
6565 static void fluid_synth_handle_important_channels(void *data, const char *name,
6568 fluid_synth_t *synth = (fluid_synth_t *)data;
6570 fluid_synth_api_enter(synth);
6571 fluid_synth_set_important_channels(synth, value);
6572 fluid_synth_api_exit(synth);
6576 /** API legato mode *********************************************************/
6579 * Sets the legato mode of a channel.
6581 * @param synth the synth instance.
6582 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6583 * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
6586 * - #FLUID_OK on success.
6588 * - \a synth is NULL.
6589 * - \a chan is outside MIDI channel count.
6590 * - \a legatomode is invalid.
6592 int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode)
6594 /* checks parameters first */
6595 fluid_return_val_if_fail(legatomode >= 0, FLUID_FAILED);
6596 fluid_return_val_if_fail(legatomode < FLUID_CHANNEL_LEGATO_MODE_LAST, FLUID_FAILED);
6597 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6599 synth->channel[chan]->legatomode = legatomode;
6601 FLUID_API_RETURN(FLUID_OK);
6605 * Gets the legato mode of a channel.
6607 * @param synth the synth instance.
6608 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6609 * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
6612 * - #FLUID_OK on success.
6614 * - \a synth is NULL.
6615 * - \a chan is outside MIDI channel count.
6616 * - \a legatomode is NULL.
6618 int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode)
6620 /* checks parameters first */
6621 fluid_return_val_if_fail(legatomode != NULL, FLUID_FAILED);
6622 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6624 * legatomode = synth->channel[chan]->legatomode;
6626 FLUID_API_RETURN(FLUID_OK);
6629 /** API portamento mode *********************************************************/
6632 * Sets the portamento mode of a channel.
6634 * @param synth the synth instance.
6635 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6636 * @param portamentomode The portamento mode as indicated by #fluid_channel_portamento_mode.
6638 * - #FLUID_OK on success.
6640 * - \a synth is NULL.
6641 * - \a chan is outside MIDI channel count.
6642 * - \a portamentomode is invalid.
6644 int fluid_synth_set_portamento_mode(fluid_synth_t *synth, int chan,
6647 /* checks parameters first */
6648 fluid_return_val_if_fail(portamentomode >= 0, FLUID_FAILED);
6649 fluid_return_val_if_fail(portamentomode < FLUID_CHANNEL_PORTAMENTO_MODE_LAST, FLUID_FAILED);
6650 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6652 synth->channel[chan]->portamentomode = portamentomode;
6654 FLUID_API_RETURN(FLUID_OK);
6658 * Gets the portamento mode of a channel.
6660 * @param synth the synth instance.
6661 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6662 * @param portamentomode Pointer to the portamento mode as indicated by #fluid_channel_portamento_mode.
6664 * - #FLUID_OK on success.
6666 * - \a synth is NULL.
6667 * - \a chan is outside MIDI channel count.
6668 * - \a portamentomode is NULL.
6670 int fluid_synth_get_portamento_mode(fluid_synth_t *synth, int chan,
6671 int *portamentomode)
6673 /* checks parameters first */
6674 fluid_return_val_if_fail(portamentomode != NULL, FLUID_FAILED);
6675 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6677 * portamentomode = synth->channel[chan]->portamentomode;
6679 FLUID_API_RETURN(FLUID_OK);
6682 /** API breath mode *********************************************************/
6685 * Sets the breath mode of a channel.
6687 * @param synth the synth instance.
6688 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6689 * @param breathmode The breath mode as indicated by #fluid_channel_breath_flags.
6692 * - #FLUID_OK on success.
6694 * - \a synth is NULL.
6695 * - \a chan is outside MIDI channel count.
6697 int fluid_synth_set_breath_mode(fluid_synth_t *synth, int chan, int breathmode)
6699 /* checks parameters first */
6700 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6702 fluid_channel_set_breath_info(synth->channel[chan], breathmode);
6704 FLUID_API_RETURN(FLUID_OK);
6708 * Gets the breath mode of a channel.
6710 * @param synth the synth instance.
6711 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6712 * @param breathmode Pointer to the returned breath mode as indicated by #fluid_channel_breath_flags.
6715 * - #FLUID_OK on success.
6717 * - \a synth is NULL.
6718 * - \a chan is outside MIDI channel count.
6719 * - \a breathmode is NULL.
6721 int fluid_synth_get_breath_mode(fluid_synth_t *synth, int chan, int *breathmode)
6723 /* checks parameters first */
6724 fluid_return_val_if_fail(breathmode != NULL, FLUID_FAILED);
6725 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6727 * breathmode = fluid_channel_get_breath_info(synth->channel[chan]);
6729 FLUID_API_RETURN(FLUID_OK);
6732 /** API Poly/mono mode ******************************************************/
6735 * Resets a basic channel group of MIDI channels.
6736 * @param synth the synth instance.
6737 * @param chan the beginning channel of the group.
6738 * @param nbr_chan the number of channel in the group.
6741 fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan)
6745 for(i = chan; i < chan + nbr_chan; i++)
6747 fluid_channel_reset_basic_channel_info(synth->channel[i]);
6748 synth->channel[i]->mode_val = 0;
6753 * Disables and unassigns all channels from a basic channel group.
6755 * @param synth The synth instance.
6756 * @param chan The basic channel of the group to reset or -1 to reset all channels.
6757 * @note By default (i.e. on creation after new_fluid_synth() and after fluid_synth_system_reset())
6758 * a synth instance has one basic channel at channel 0 in mode #FLUID_CHANNEL_MODE_OMNION_POLY.
6759 * All other channels belong to this basic channel group. Make sure to call this function before
6760 * setting any custom basic channel setup.
6763 * - #FLUID_OK on success.
6765 * - \a synth is NULL.
6766 * - \a chan is outside MIDI channel count.
6767 * - \a chan isn't a basic channel.
6769 int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan)
6773 /* checks parameters first */
6776 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6777 fluid_synth_api_enter(synth);
6778 /* The range is all MIDI channels from 0 to MIDI channel count -1 */
6779 chan = 0; /* beginning chan */
6780 nbr_chan = synth->midi_channels; /* MIDI Channels number */
6784 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6786 /* checks if chan is a basic channel */
6787 if(!(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC))
6789 FLUID_API_RETURN(FLUID_FAILED);
6792 /* The range is all MIDI channels in the group from chan */
6793 nbr_chan = synth->channel[chan]->mode_val; /* nbr of channels in the group */
6796 /* resets the range of MIDI channels */
6797 fluid_synth_reset_basic_channel_LOCAL(synth, chan, nbr_chan);
6798 FLUID_API_RETURN(FLUID_OK);
6802 * Checks if a new basic channel group overlaps the next basic channel group.
6804 * On success the function returns the possible number of channel for this
6805 * new basic channel group.
6806 * The function fails if the new group overlaps the next basic channel group.
6808 * @param see fluid_synth_set_basic_channel.
6810 * - On success, the effective number of channels for this new basic channel group,
6811 * #FLUID_FAILED otherwise.
6813 * - \a val has a number of channels overlapping next basic channel group or been
6814 * above MIDI channel count.
6817 fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val)
6819 int i, n_chan = synth->midi_channels; /* MIDI Channels count */
6820 int real_val = val; /* real number of channels in the group */
6822 /* adjusts val range */
6823 if(mode == FLUID_CHANNEL_MODE_OMNIOFF_POLY)
6825 real_val = 1; /* mode poly omnioff implies a group of only one channel.*/
6829 /* mode poly omnion (0), mono omnion (1), mono omni off (3) */
6830 /* value 0 means all possible channels from basicchan to MIDI channel count -1.*/
6831 real_val = n_chan - basicchan;
6833 /* checks if val range is above MIDI channel count */
6834 else if(basicchan + val > n_chan)
6836 return FLUID_FAILED;
6839 /* checks if this basic channel group overlaps next basic channel group */
6840 for(i = basicchan + 1; i < basicchan + real_val; i++)
6842 if(synth->channel[i]->mode & FLUID_CHANNEL_BASIC)
6844 /* A value of 0 for val means all possible channels from basicchan to
6845 to the next basic channel -1 (if any).
6846 When i reachs the next basic channel group, real_val will be
6847 limited if it is possible */
6850 /* limitation of real_val */
6851 real_val = i - basicchan;
6855 /* overlap with the next basic channel group */
6856 return FLUID_FAILED;
6864 * Sets a new basic channel group only. The function doesn't allow to change an
6865 * existing basic channel.
6867 * The function fails if any channel overlaps any existing basic channel group.
6868 * To make room if necessary, basic channel groups can be cleared using
6869 * fluid_synth_reset_basic_channel().
6871 * @param synth the synth instance.
6872 * @param chan the basic Channel number (0 to MIDI channel count-1).
6873 * @param mode the MIDI mode to use for chan (see #fluid_basic_channel_modes).
6874 * @param val number of channels in the group.
6875 * @note \a val is only relevant for mode #FLUID_CHANNEL_MODE_OMNION_POLY,
6876 * #FLUID_CHANNEL_MODE_OMNION_MONO and #FLUID_CHANNEL_MODE_OMNIOFF_MONO. A value
6877 * of 0 means all possible channels from \a chan to to next basic channel minus 1 (if any)
6878 * or to MIDI channel count minus 1. Val is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY
6879 * as this mode implies a group of only one channel.
6881 * - #FLUID_OK on success.
6883 * - \a synth is NULL.
6884 * - \a chan is outside MIDI channel count.
6885 * - \a mode is invalid.
6886 * - \a val has a number of channels overlapping another basic channel group or been
6887 * above MIDI channel count.
6888 * - When the function fails, any existing basic channels aren't modified.
6890 int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val)
6892 /* check parameters */
6893 fluid_return_val_if_fail(mode >= 0, FLUID_FAILED);
6894 fluid_return_val_if_fail(mode < FLUID_CHANNEL_MODE_LAST, FLUID_FAILED);
6895 fluid_return_val_if_fail(val >= 0, FLUID_FAILED);
6896 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6899 if(val > 0 && chan + val > synth->midi_channels)
6901 FLUID_API_RETURN(FLUID_FAILED);
6904 /* Checks if there is an overlap with the next basic channel */
6905 val = fluid_synth_check_next_basic_channel(synth, chan, mode, val);
6907 if(val == FLUID_FAILED || synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)
6909 /* overlap with the next or previous channel group */
6910 FLUID_LOG(FLUID_INFO, "basic channel %d overlaps another group", chan);
6911 FLUID_API_RETURN(FLUID_FAILED);
6914 /* sets a new basic channel group */
6915 fluid_synth_set_basic_channel_LOCAL(synth, chan, mode, val);
6917 FLUID_API_RETURN(FLUID_OK);
6921 * Local version of fluid_synth_set_basic_channel(), called internally:
6922 * - by fluid_synth_set_basic_channel() to set a new basic channel group.
6923 * - during creation new_fluid_synth() or on CC reset to set a default basic channel group.
6924 * - on CC ominoff, CC omnion, CC poly , CC mono to change an existing basic channel group.
6926 * @param see fluid_synth_set_basic_channel()
6929 fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val)
6933 /* sets the basic channel group */
6934 for(i = basicchan; i < basicchan + val; i++)
6936 int new_mode = mode; /* OMNI_OFF/ON, MONO/POLY ,others bits are zero */
6938 /* MIDI specs: when mode is changed, channel must receive ALL_NOTES_OFF */
6939 fluid_synth_all_notes_off_LOCAL(synth, i);
6943 new_mode |= FLUID_CHANNEL_BASIC; /* First channel in the group */
6944 new_val = val; /* number of channels in the group */
6948 new_val = 0; /* val is 0 for other channel than basic channel */
6951 /* Channel is enabled */
6952 new_mode |= FLUID_CHANNEL_ENABLED;
6953 /* Now new_mode is OMNI OFF/ON,MONO/POLY, BASIC_CHANNEL or not and enabled */
6954 fluid_channel_set_basic_channel_info(synth->channel[i], new_mode);
6955 synth->channel[i]->mode_val = new_val;
6960 * Searchs a previous basic channel starting from chan.
6962 * @param synth the synth instance.
6963 * @param chan starting index of the search (including chan).
6964 * @return index of the basic channel if found , FLUID_FAILED otherwise.
6966 static int fluid_synth_get_previous_basic_channel(fluid_synth_t *synth, int chan)
6968 for(; chan >= 0; chan--)
6970 /* searchs previous basic channel */
6971 if(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC)
6973 /* chan is the previous basic channel */
6978 return FLUID_FAILED;
6982 * Returns poly mono mode information of any MIDI channel.
6984 * @param synth the synth instance
6985 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6986 * @param basic_chan_out Buffer to store the basic channel \a chan belongs to or #FLUID_FAILED if \a chan is disabled.
6987 * @param mode_out Buffer to store the mode of \a chan (see #fluid_basic_channel_modes) or #FLUID_FAILED if \a chan is disabled.
6988 * @param val_out Buffer to store the total number of channels in this basic channel group or #FLUID_FAILED if \a chan is disabled.
6989 * @note If any of \a basic_chan_out, \a mode_out, \a val_out pointer is NULL
6990 * the corresponding information isn't returned.
6993 * - #FLUID_OK on success.
6995 * - \a synth is NULL.
6996 * - \a chan is outside MIDI channel count.
6998 int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan,
6999 int *basic_chan_out,
7003 int basic_chan = FLUID_FAILED;
7004 int mode = FLUID_FAILED;
7005 int val = FLUID_FAILED;
7007 /* checks parameters first */
7008 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7010 if((synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) &&
7011 /* chan is enabled , we search the basic channel chan belongs to */
7012 (basic_chan = fluid_synth_get_previous_basic_channel(synth, chan)) != FLUID_FAILED)
7014 mode = synth->channel[chan]->mode & FLUID_CHANNEL_MODE_MASK;
7015 val = synth->channel[basic_chan]->mode_val;
7018 /* returns the informations if they are requested */
7021 * basic_chan_out = basic_chan;
7034 FLUID_API_RETURN(FLUID_OK);