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);
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.
1111 fluid_synth_error(fluid_synth_t *synth)
1117 * Send a note-on event to a FluidSynth object.
1118 * @param synth FluidSynth instance
1119 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1120 * @param key MIDI note number (0-127)
1121 * @param vel MIDI velocity (0-127, 0=noteoff)
1122 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1125 fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel)
1128 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1129 fluid_return_val_if_fail(vel >= 0 && vel <= 127, FLUID_FAILED);
1130 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1132 /* Allowed only on MIDI channel enabled */
1133 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1135 result = fluid_synth_noteon_LOCAL(synth, chan, key, vel);
1136 FLUID_API_RETURN(result);
1139 /* Local synthesis thread variant of fluid_synth_noteon */
1141 fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key, int vel)
1143 fluid_channel_t *channel ;
1145 /* notes with velocity zero go to noteoff */
1148 return fluid_synth_noteoff_LOCAL(synth, chan, key);
1151 channel = synth->channel[chan];
1153 /* makes sure this channel has a preset */
1154 if(channel->preset == NULL)
1158 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s",
1160 fluid_synth_get_ticks(synth) / 44100.0f,
1161 (fluid_curtime() - synth->start) / 1000.0f,
1162 0.0f, 0, "channel has no preset");
1165 return FLUID_FAILED;
1168 if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1170 /* play the noteOn in monophonic */
1171 return fluid_synth_noteon_mono_LOCAL(synth, chan, key, vel);
1175 /* channel is poly and legato CC is Off) */
1177 /* plays the noteOn in polyphonic */
1178 /* Sets the note at first position in monophonic list */
1179 /* In the case where the musician intends to inter the channel in monophonic
1180 (by depressing the CC legato on), the next noteOn mono could be played legato
1181 with the previous note poly (if the musician choose this).
1183 fluid_channel_set_onenote_monolist(channel, (unsigned char) key,
1184 (unsigned char) vel);
1186 /* If there is another voice process on the same channel and key,
1187 advance it to the release phase. */
1188 fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key);
1190 /* a noteon poly is passed to fluid_synth_noteon_monopoly_legato().
1191 This allows an opportunity to get this note played legato with a previous
1192 note if a CC PTC have been received before this noteon. This behavior is
1193 a MIDI specification (see FluidPolymono-0004.pdf chapter 4.3-a ,3.4.11
1196 return fluid_synth_noteon_monopoly_legato(synth, chan, INVALID_NOTE, key, vel);
1201 * Sends a note-off event to a FluidSynth object.
1202 * @param synth FluidSynth instance
1203 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1204 * @param key MIDI note number (0-127)
1205 * @return #FLUID_OK on success, #FLUID_FAILED otherwise (may just mean that no
1206 * voices matched the note off event)
1209 fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key)
1212 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1213 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1215 /* Allowed only on MIDI channel enabled */
1216 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1218 result = fluid_synth_noteoff_LOCAL(synth, chan, key);
1219 FLUID_API_RETURN(result);
1222 /* Local synthesis thread variant of fluid_synth_noteoff */
1224 fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key)
1227 fluid_channel_t *channel = synth->channel[chan];
1229 if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1231 /* play the noteOff in monophonic */
1232 status = fluid_synth_noteoff_mono_LOCAL(synth, chan, key);
1236 /* channel is poly and legato CC is Off) */
1237 /* removes the note from the monophonic list */
1238 if(key == fluid_channel_last_note(channel))
1240 fluid_channel_clear_monolist(channel);
1243 status = fluid_synth_noteoff_monopoly(synth, chan, key, 0);
1246 /* Changes the state (Valid/Invalid) of the most recent note played in a
1248 fluid_channel_invalid_prev_note_staccato(channel);
1252 /* Damps voices on a channel (turn notes off), if they're sustained by
1255 fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t *synth, int chan)
1257 fluid_channel_t *channel = synth->channel[chan];
1258 fluid_voice_t *voice;
1261 for(i = 0; i < synth->polyphony; i++)
1263 voice = synth->voice[i];
1265 if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sustained(voice))
1267 if(voice->key == channel->key_mono_sustained)
1269 /* key_mono_sustained is a possible mono note sustainted
1270 (by sustain or sostenuto pedal). It must be marked released
1271 (INVALID_NOTE) here because it is released only by sustain pedal */
1272 channel->key_mono_sustained = INVALID_NOTE;
1275 fluid_voice_release(voice);
1282 /* Damps voices on a channel (turn notes off), if they're sustained by
1285 fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t *synth, int chan)
1287 fluid_channel_t *channel = synth->channel[chan];
1288 fluid_voice_t *voice;
1291 for(i = 0; i < synth->polyphony; i++)
1293 voice = synth->voice[i];
1295 if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sostenuto(voice))
1297 if(voice->key == channel->key_mono_sustained)
1299 /* key_mono_sustained is a possible mono note sustainted
1300 (by sustain or sostenuto pedal). It must be marked released
1301 (INVALID_NOTE) here because it is released only by sostenuto pedal */
1302 channel->key_mono_sustained = INVALID_NOTE;
1305 fluid_voice_release(voice);
1313 * Adds the specified modulator \c mod as default modulator to the synth. \c mod will
1314 * take effect for any subsequently created voice.
1315 * @param synth FluidSynth instance
1316 * @param mod Modulator info (values copied, passed in object can be freed immediately afterwards)
1317 * @param mode Determines how to handle an existing identical modulator (#fluid_synth_add_mod)
1318 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1320 * @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1321 * from synthesis context at the risk of stalling audio output.
1324 fluid_synth_add_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod, int mode)
1326 fluid_mod_t *default_mod;
1327 fluid_mod_t *last_mod = NULL;
1328 fluid_mod_t *new_mod;
1330 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1331 fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1333 /* Checks if modulators sources are valid */
1334 if(!fluid_mod_check_sources(mod, "api fluid_synth_add_default_mod mod"))
1336 return FLUID_FAILED;
1339 fluid_synth_api_enter(synth);
1341 default_mod = synth->default_mod;
1343 while(default_mod != NULL)
1345 if(fluid_mod_test_identity(default_mod, mod))
1347 if(mode == FLUID_SYNTH_ADD)
1349 default_mod->amount += mod->amount;
1351 else if(mode == FLUID_SYNTH_OVERWRITE)
1353 default_mod->amount = mod->amount;
1357 FLUID_API_RETURN(FLUID_FAILED);
1360 FLUID_API_RETURN(FLUID_OK);
1363 last_mod = default_mod;
1364 default_mod = default_mod->next;
1367 /* Add a new modulator (no existing modulator to add / overwrite). */
1368 new_mod = new_fluid_mod();
1372 FLUID_API_RETURN(FLUID_FAILED);
1375 fluid_mod_clone(new_mod, mod);
1376 new_mod->next = NULL;
1378 if(last_mod == NULL)
1380 synth->default_mod = new_mod;
1384 last_mod->next = new_mod;
1387 FLUID_API_RETURN(FLUID_OK);
1391 * Removes the specified modulator \c mod from the synth's default modulator list.
1392 * fluid_mod_test_identity() will be used to test modulator matching.
1393 * @param synth synth instance
1394 * @param mod The modulator to remove
1395 * @return #FLUID_OK if a matching modulator was found and successfully removed, #FLUID_FAILED otherwise
1397 * @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1398 * from synthesis context at the risk of stalling audio output.
1401 fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod)
1403 fluid_mod_t *default_mod;
1404 fluid_mod_t *last_mod;
1406 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1407 fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1408 fluid_synth_api_enter(synth);
1410 last_mod = default_mod = synth->default_mod;
1412 while(default_mod != NULL)
1414 if(fluid_mod_test_identity(default_mod, mod))
1416 if(synth->default_mod == default_mod)
1418 synth->default_mod = synth->default_mod->next;
1422 last_mod->next = default_mod->next;
1425 delete_fluid_mod(default_mod);
1426 FLUID_API_RETURN(FLUID_OK);
1429 last_mod = default_mod;
1430 default_mod = default_mod->next;
1433 FLUID_API_RETURN(FLUID_FAILED);
1438 * Send a MIDI controller event on a MIDI channel.
1439 * @param synth FluidSynth instance
1440 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1441 * @param num MIDI controller number (0-127)
1442 * @param val MIDI controller value (0-127)
1443 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1444 * @note This function supports MIDI Global Controllers which will be sent to
1445 * all channels of the basic channel if this basic channel is in mode OmniOff/Mono.
1446 * This is accomplished by sending the CC one MIDI channel below the basic
1447 * channel of the receiver.
1448 * Examples: let a synthesizer with 16 MIDI channels:
1449 * - Let a basic channel 7 in mode 3 (Omni Off, Mono). If MIDI channel 6 is disabled it
1450 * could be used as CC global for all channels belonging to basic channel 7.
1451 * - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used
1452 * as CC global for all channels belonging to basic channel 0.
1455 fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
1457 int result = FLUID_FAILED;
1458 fluid_channel_t *channel;
1459 fluid_return_val_if_fail(num >= 0 && num <= 127, FLUID_FAILED);
1460 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
1461 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1463 channel = synth->channel[chan];
1465 if(channel->mode & FLUID_CHANNEL_ENABLED)
1467 /* chan is enabled */
1470 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val);
1473 fluid_channel_set_cc(channel, num, val);
1474 result = fluid_synth_cc_LOCAL(synth, chan, num);
1476 else /* chan is disabled so it is a candidate for global channel */
1478 /* looks for next basic channel */
1479 int n_chan = synth->midi_channels; /* MIDI Channels number */
1482 if(chan < n_chan - 1)
1484 basicchan = chan + 1; /* next channel */
1488 basicchan = 0; /* wrap to 0 */
1491 channel = synth->channel[basicchan];
1493 /* Channel must be a basicchan in mode OMNIOFF_MONO */
1494 if((channel->mode & FLUID_CHANNEL_BASIC) &&
1495 ((channel->mode & FLUID_CHANNEL_MODE_MASK) == FLUID_CHANNEL_MODE_OMNIOFF_MONO))
1497 /* sends cc to all channels in this basic channel */
1498 int i, nbr = channel->mode_val;
1500 for(i = basicchan; i < basicchan + nbr; i++)
1504 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", i, num, val);
1507 fluid_channel_set_cc(synth->channel[i], num, val);
1508 result = fluid_synth_cc_LOCAL(synth, i, num);
1511 /* The channel chan is not a valid 'global channel' */
1514 result = FLUID_FAILED;
1518 FLUID_API_RETURN(result);
1521 /* Local synthesis thread variant of MIDI CC set function.
1522 Most of CC are allowed to modulate but not all. A comment describes if CC num
1523 isn't allowed to modulate.
1524 Following explanations should help to understand both MIDI specifications and
1525 Soundfont specifications in regard to MIDI specs.
1528 CC LSB (32 to 63) are LSB contributions to CC MSB (0 to 31).
1529 It's up to the synthesizer to decide to take LSB values into account or not.
1530 Actually Fluidsynth doesn't use CC LSB value inside fluid_voice_update_param()
1531 (once fluid_voice_modulate() has been triggered). This is because actually
1532 fluidsynth needs only 7 bits resolution (and not 14 bits) from these CCs.
1533 So fluidsynth is using only 7 bit MSB (except for portamento time).
1534 In regard to MIDI specs Fluidsynth behaves correctly.
1536 Soundfont specs 2.01 - 8.2.1:
1537 To deal correctly with MIDI CC (regardless if any synth will use CC MSB alone (7 bit)
1538 or both CCs MSB,LSB (14 bits) during synthesis), SF specs recommend not making use of
1539 CC LSB (i.e only CC MSB) in modulator sources to trigger modulation (i.e modulators
1540 with CC LSB connected to sources inputs should be ignored).
1541 These specifics are particularly suited for synths that use 14 bits CCs. In this case,
1542 the MIDI transmitter sends CC LSB first followed by CC MSB. The MIDI synth receives
1543 both CC LSB and CC MSB but only CC MSB will trigger the modulation.
1544 This will produce correct synthesis parameters update from a correct 14 bits CC.
1545 If in SF specs, modulator sources with CC LSB had been accepted, both CC LSB and
1546 CC MSB will triggers 2 modulations. This leads to incorrect synthesis parameters
1547 update followed by correct synthesis parameters update.
1549 However, as long as fluidsynth will use only CC 7 bits resolution, it is safe to ignore
1550 these SF recommendations on CC receive.
1553 fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
1555 fluid_channel_t *chan = synth->channel[channum];
1559 value = fluid_channel_get_cc(chan, num);
1563 case LOCAL_CONTROL: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1566 /* CC omnioff, omnion, mono, poly */
1567 /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1573 /* allowed only if channum is a basic channel */
1574 if(chan->mode & FLUID_CHANNEL_BASIC)
1576 /* Construction of new_mode from current channel mode and this CC mode */
1577 int new_mode = chan->mode & FLUID_CHANNEL_MODE_MASK;
1582 new_mode |= FLUID_CHANNEL_POLY_OFF;
1586 new_mode &= ~FLUID_CHANNEL_POLY_OFF;
1590 new_mode |= FLUID_CHANNEL_OMNI_OFF;
1594 new_mode &= ~FLUID_CHANNEL_OMNI_OFF;
1597 default: /* should never happen */
1598 return FLUID_FAILED;
1601 /* MIDI specs: if value is 0 it means all channels from channum to next
1602 basic channel minus 1 (if any) or to MIDI channel count minus 1.
1603 However, if value is > 0 (e.g. 4), the group of channels will be be
1605 value is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY as this mode
1606 implies a group of only one channel.
1608 /* Checks value range and changes this existing basic channel group */
1609 value = fluid_synth_check_next_basic_channel(synth, channum, new_mode, value);
1611 if(value != FLUID_FAILED)
1613 /* reset the current basic channel before changing it */
1614 fluid_synth_reset_basic_channel_LOCAL(synth, channum, chan->mode_val);
1615 fluid_synth_set_basic_channel_LOCAL(synth, channum, new_mode, value);
1616 break; /* FLUID_OK */
1620 return FLUID_FAILED;
1622 case LEGATO_SWITCH: /* not allowed to modulate */
1623 /* handles Poly/mono commutation on Legato pedal On/Off.*/
1624 fluid_channel_cc_legato(chan, value);
1627 case PORTAMENTO_SWITCH: /* not allowed to modulate */
1628 /* Special handling of the monophonic list */
1629 /* Invalids the most recent note played in a staccato manner */
1630 fluid_channel_invalid_prev_note_staccato(chan);
1633 case SUSTAIN_SWITCH: /* not allowed to modulate */
1635 /* Release voices if Sustain switch is released */
1636 if(value < 64) /* Sustain is released */
1638 fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
1643 case SOSTENUTO_SWITCH: /* not allowed to modulate */
1645 /* Release voices if Sostetuno switch is released */
1646 if(value < 64) /* Sostenuto is released */
1648 fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
1650 else /* Sostenuto is depressed */
1651 /* Update sostenuto order id when pedaling on Sostenuto */
1653 chan->sostenuto_orderid = synth->noteid; /* future voice id value */
1658 case BANK_SELECT_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1659 fluid_channel_set_bank_msb(chan, value & 0x7F);
1662 case BANK_SELECT_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1663 fluid_channel_set_bank_lsb(chan, value & 0x7F);
1666 case ALL_NOTES_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1667 fluid_synth_all_notes_off_LOCAL(synth, channum);
1670 case ALL_SOUND_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1671 fluid_synth_all_sounds_off_LOCAL(synth, channum);
1674 case ALL_CTRL_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1675 fluid_channel_init_ctrl(chan, 1);
1676 fluid_synth_modulate_voices_all_LOCAL(synth, channum);
1679 case DATA_ENTRY_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1682 case DATA_ENTRY_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1684 int data = (value << 7) + fluid_channel_get_cc(chan, DATA_ENTRY_LSB);
1686 if(chan->nrpn_active) /* NRPN is active? */
1688 /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1689 if((fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1690 && (fluid_channel_get_cc(chan, NRPN_LSB) < 100))
1692 nrpn_select = chan->nrpn_select;
1694 if(nrpn_select < GEN_LAST)
1696 float val = fluid_gen_scale_nrpn(nrpn_select, data);
1697 fluid_synth_set_gen_LOCAL(synth, channum, nrpn_select, val);
1700 chan->nrpn_select = 0; /* Reset to 0 */
1703 else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */
1705 switch(fluid_channel_get_cc(chan, RPN_LSB))
1707 case RPN_PITCH_BEND_RANGE: /* Set bend range in semitones */
1708 fluid_channel_set_pitch_wheel_sensitivity(synth->channel[channum], value);
1709 fluid_synth_update_pitch_wheel_sens_LOCAL(synth, channum); /* Update bend range */
1710 /* FIXME - Handle LSB? (Fine bend range in cents) */
1713 case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over +/-1 semitone (+/- 100 cents, 8192 = center) */
1714 fluid_synth_set_gen_LOCAL(synth, channum, GEN_FINETUNE,
1715 (data - 8192) / 8192.0 * 100.0);
1718 case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */
1719 fluid_synth_set_gen_LOCAL(synth, channum, GEN_COARSETUNE,
1723 case RPN_TUNING_PROGRAM_CHANGE:
1724 fluid_channel_set_tuning_prog(chan, value);
1725 fluid_synth_activate_tuning(synth, channum,
1726 fluid_channel_get_tuning_bank(chan),
1730 case RPN_TUNING_BANK_SELECT:
1731 fluid_channel_set_tuning_bank(chan, value);
1734 case RPN_MODULATION_DEPTH_RANGE:
1742 case NRPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1743 fluid_channel_set_cc(chan, NRPN_LSB, 0);
1744 chan->nrpn_select = 0;
1745 chan->nrpn_active = 1;
1748 case NRPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1750 /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1751 if(fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1755 chan->nrpn_select += 100;
1757 else if(value == 101)
1759 chan->nrpn_select += 1000;
1761 else if(value == 102)
1763 chan->nrpn_select += 10000;
1765 else if(value < 100)
1767 chan->nrpn_select += value;
1771 chan->nrpn_active = 1;
1774 case RPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1775 case RPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1776 chan->nrpn_active = 0;
1780 /* handles CC Breath On/Off noteOn/noteOff mode */
1781 fluid_channel_cc_breath_note_on_off(chan, value);
1785 /* CC lsb shouldn't allowed to modulate (spec SF 2.01 - 8.2.1) */
1786 /* However, as long fluidsynth will use only CC 7 bits resolution, it
1787 is safe to ignore these SF recommendations on CC receive. See
1788 explanations above */
1789 /* if (! (32 <= num && num <= 63)) */
1791 return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num);
1799 * Get current MIDI controller value on a MIDI channel.
1800 * @param synth FluidSynth instance
1801 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1802 * @param num MIDI controller number (0-127)
1803 * @param pval Location to store MIDI controller value (0-127)
1804 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1807 fluid_synth_get_cc(fluid_synth_t *synth, int chan, int num, int *pval)
1809 fluid_return_val_if_fail(num >= 0 && num < 128, FLUID_FAILED);
1810 fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
1812 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1814 /* Allowed only on MIDI channel enabled */
1815 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1817 *pval = fluid_channel_get_cc(synth->channel[chan], num);
1818 FLUID_API_RETURN(FLUID_OK);
1822 * Handler for synth.device-id setting.
1825 fluid_synth_handle_device_id(void *data, const char *name, int value)
1827 fluid_synth_t *synth = (fluid_synth_t *)data;
1828 fluid_return_if_fail(synth != NULL);
1830 fluid_synth_api_enter(synth);
1831 synth->device_id = value;
1832 fluid_synth_api_exit(synth);
1836 * Process a MIDI SYSEX (system exclusive) message.
1837 * @param synth FluidSynth instance
1838 * @param data Buffer containing SYSEX data (not including 0xF0 and 0xF7)
1839 * @param len Length of data in buffer
1840 * @param response Buffer to store response to or NULL to ignore
1841 * @param response_len IN/OUT parameter, in: size of response buffer, out:
1842 * amount of data written to response buffer (if FLUID_FAILED is returned and
1843 * this value is non-zero, it indicates the response buffer is too small)
1844 * @param handled Optional location to store boolean value if message was
1845 * recognized and handled or not (set to TRUE if it was handled)
1846 * @param dryrun TRUE to just do a dry run but not actually execute the SYSEX
1847 * command (useful for checking if a SYSEX message would be handled)
1848 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1851 /* SYSEX format (0xF0 and 0xF7 not passed to this function):
1852 * Non-realtime: 0xF0 0x7E <DeviceId> [BODY] 0xF7
1853 * Realtime: 0xF0 0x7F <DeviceId> [BODY] 0xF7
1854 * Tuning messages: 0xF0 0x7E/0x7F <DeviceId> 0x08 <sub ID2> [BODY] <ChkSum> 0xF7
1857 fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len,
1858 char *response, int *response_len, int *handled, int dryrun)
1860 int avail_response = 0;
1869 avail_response = *response_len;
1873 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1874 fluid_return_val_if_fail(data != NULL, FLUID_FAILED);
1875 fluid_return_val_if_fail(len > 0, FLUID_FAILED);
1876 fluid_return_val_if_fail(!response || response_len, FLUID_FAILED);
1883 /* MIDI tuning SYSEX message? */
1884 if((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME)
1885 && (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL)
1886 && data[2] == MIDI_SYSEX_MIDI_TUNING_ID)
1889 fluid_synth_api_enter(synth);
1890 result = fluid_synth_sysex_midi_tuning(synth, data, len, response,
1891 response_len, avail_response,
1894 FLUID_API_RETURN(result);
1900 /* Handler for MIDI tuning SYSEX messages */
1902 fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len,
1903 char *response, int *response_len, int avail_response,
1904 int *handled, int dryrun)
1906 int realtime, msgid;
1907 int bank = 0, prog, channels;
1908 double tunedata[128];
1911 int note, frac, frac2;
1913 int i, count, index;
1914 const char *dataptr;
1917 realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME;
1922 case MIDI_SYSEX_TUNING_BULK_DUMP_REQ:
1923 case MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK:
1924 if(data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
1926 if(len != 5 || data[4] & 0x80 || !response)
1931 *response_len = 406;
1936 if(len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response)
1941 *response_len = 407;
1956 if(avail_response < *response_len)
1958 return FLUID_FAILED;
1961 /* Get tuning data, return if tuning not found */
1962 if(fluid_synth_tuning_dump(synth, bank, prog, name, 17, tunedata) == FLUID_FAILED)
1970 *resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME;
1971 *resptr++ = synth->device_id;
1972 *resptr++ = MIDI_SYSEX_MIDI_TUNING_ID;
1973 *resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP;
1975 if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK)
1981 /* copy 16 ASCII characters (potentially not null terminated) to the sysex buffer */
1982 FLUID_MEMCPY(resptr, name, 16);
1985 for(i = 0; i < 128; i++)
1987 note = tunedata[i] / 100.0;
1988 fluid_clip(note, 0, 127);
1990 frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0;
1991 fluid_clip(frac, 0, 16383);
1994 *resptr++ = frac >> 7;
1995 *resptr++ = frac & 0x7F;
1998 if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
2000 /* NOTE: Checksum is not as straight forward as the bank based messages */
2001 chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID
2002 ^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog;
2004 for(i = 21; i < 128 * 3 + 21; i++)
2006 chksum ^= response[i];
2011 for(i = 1, chksum = 0; i < 406; i++)
2013 chksum ^= response[i];
2017 *resptr++ = chksum & 0x7F;
2026 case MIDI_SYSEX_TUNING_NOTE_TUNE:
2027 case MIDI_SYSEX_TUNING_NOTE_TUNE_BANK:
2030 if(msgid == MIDI_SYSEX_TUNING_NOTE_TUNE)
2032 if(len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6)
2039 if(len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80
2040 || len != data[6] * 4 + 7)
2061 for(i = 0, index = 0; i < count; i++)
2076 if(note & 0x80 || frac & 0x80 || frac2 & 0x80)
2081 frac = frac << 7 | frac2;
2083 /* No change pitch value? Doesn't really make sense to send that, but.. */
2084 if(note == 0x7F && frac == 16383)
2089 tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0);
2095 if(fluid_synth_tune_notes(synth, bank, prog, index, keys, tunedata,
2096 realtime) == FLUID_FAILED)
2098 return FLUID_FAILED;
2109 case MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE:
2110 case MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE:
2111 if((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19)
2112 || (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31))
2117 if(data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80)
2132 channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6];
2134 if(msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE)
2136 for(i = 0; i < 12; i++)
2145 tunedata[i] = (int)frac - 64;
2150 for(i = 0; i < 12; i++)
2152 frac = data[i * 2 + 7];
2153 frac2 = data[i * 2 + 8];
2155 if(frac & 0x80 || frac2 & 0x80)
2160 tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0);
2164 if(fluid_synth_activate_octave_tuning(synth, 0, 0, "SYSEX",
2165 tunedata, realtime) == FLUID_FAILED)
2167 return FLUID_FAILED;
2172 for(i = 0; i < 16; i++)
2174 if(channels & (1 << i))
2176 fluid_synth_activate_tuning(synth, i, 0, 0, realtime);
2193 * Turn off all notes on a MIDI channel (put them into release phase).
2194 * @param synth FluidSynth instance
2195 * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2196 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2200 fluid_synth_all_notes_off(fluid_synth_t *synth, int chan)
2204 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2205 fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2206 fluid_synth_api_enter(synth);
2208 if(chan >= synth->midi_channels)
2210 result = FLUID_FAILED;
2214 /* Allowed (even for channel disabled) as chan = -1 selects all channels */
2215 result = fluid_synth_all_notes_off_LOCAL(synth, chan);
2218 FLUID_API_RETURN(result);
2221 /* Local synthesis thread variant of all notes off, (chan=-1 selects all channels) */
2224 fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan)
2226 fluid_voice_t *voice;
2229 for(i = 0; i < synth->polyphony; i++)
2231 voice = synth->voice[i];
2233 if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2235 fluid_voice_noteoff(voice);
2243 * Immediately stop all notes on a MIDI channel (skips release phase).
2244 * @param synth FluidSynth instance
2245 * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2246 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2250 fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan)
2254 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2255 fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2256 fluid_synth_api_enter(synth);
2258 if(chan >= synth->midi_channels)
2260 result = FLUID_FAILED;
2264 /* Allowed (even for channel disabled) as chan = -1 selects all channels */
2265 result = fluid_synth_all_sounds_off_LOCAL(synth, chan);
2268 FLUID_API_RETURN(result);
2271 /* Local synthesis thread variant of all sounds off, (chan=-1 selects all channels) */
2273 fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan)
2275 fluid_voice_t *voice;
2278 for(i = 0; i < synth->polyphony; i++)
2280 voice = synth->voice[i];
2282 if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2284 fluid_voice_off(voice);
2292 * Reset reverb engine
2293 * @param synth FluidSynth instance
2294 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2297 fluid_synth_reset_reverb(fluid_synth_t *synth)
2299 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2300 fluid_synth_api_enter(synth);
2301 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2302 FLUID_API_RETURN(FLUID_OK);
2306 * Reset chorus engine
2307 * @param synth FluidSynth instance
2308 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2311 fluid_synth_reset_chorus(fluid_synth_t *synth)
2313 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2314 fluid_synth_api_enter(synth);
2315 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2316 FLUID_API_RETURN(FLUID_OK);
2321 * Send MIDI system reset command (big red 'panic' button), turns off notes, resets
2322 * controllers and restores initial basic channel configuration.
2323 * @param synth FluidSynth instance
2324 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2327 fluid_synth_system_reset(fluid_synth_t *synth)
2330 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2331 fluid_synth_api_enter(synth);
2332 result = fluid_synth_system_reset_LOCAL(synth);
2333 FLUID_API_RETURN(result);
2336 /* Local variant of the system reset command */
2338 fluid_synth_system_reset_LOCAL(fluid_synth_t *synth)
2342 fluid_synth_all_sounds_off_LOCAL(synth, -1);
2344 for(i = 0; i < synth->midi_channels; i++)
2346 fluid_channel_reset(synth->channel[i]);
2349 /* Basic channel 0, Mode Omni On Poly */
2350 fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
2351 synth->midi_channels);
2353 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2354 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2360 * Update voices on a MIDI channel after a MIDI control change.
2361 * @param synth FluidSynth instance
2362 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2363 * @param is_cc Boolean value indicating if ctrl is a CC controller or not
2364 * @param ctrl MIDI controller value
2365 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2368 fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan, int is_cc, int ctrl)
2370 fluid_voice_t *voice;
2373 for(i = 0; i < synth->polyphony; i++)
2375 voice = synth->voice[i];
2377 if(fluid_voice_get_channel(voice) == chan)
2379 fluid_voice_modulate(voice, is_cc, ctrl);
2387 * Update voices on a MIDI channel after all MIDI controllers have been changed.
2388 * @param synth FluidSynth instance
2389 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2390 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2393 fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan)
2395 fluid_voice_t *voice;
2398 for(i = 0; i < synth->polyphony; i++)
2400 voice = synth->voice[i];
2402 if(fluid_voice_get_channel(voice) == chan)
2404 fluid_voice_modulate_all(voice);
2412 * Set the MIDI channel pressure controller value.
2413 * @param synth FluidSynth instance
2414 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2415 * @param val MIDI channel pressure value (0-127)
2416 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2419 fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val)
2422 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2424 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2426 /* Allowed only on MIDI channel enabled */
2427 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2431 FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
2434 fluid_channel_set_channel_pressure(synth->channel[chan], val);
2435 result = fluid_synth_update_channel_pressure_LOCAL(synth, chan);
2437 FLUID_API_RETURN(result);
2440 /* Updates channel pressure from within synthesis thread */
2442 fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int chan)
2444 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_CHANNELPRESSURE);
2448 * Set the MIDI polyphonic key pressure controller value.
2449 * @param synth FluidSynth instance
2450 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2451 * @param key MIDI key number (0-127)
2452 * @param val MIDI key pressure value (0-127)
2453 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2457 fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val)
2460 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
2461 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2463 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2465 /* Allowed only on MIDI channel enabled */
2466 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2470 FLUID_LOG(FLUID_INFO, "keypressure\t%d\t%d\t%d", chan, key, val);
2473 fluid_channel_set_key_pressure(synth->channel[chan], key, val);
2474 result = fluid_synth_update_key_pressure_LOCAL(synth, chan, key);
2476 FLUID_API_RETURN(result);
2479 /* Updates key pressure from within synthesis thread */
2481 fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key)
2483 fluid_voice_t *voice;
2485 int result = FLUID_OK;
2487 for(i = 0; i < synth->polyphony; i++)
2489 voice = synth->voice[i];
2491 if(voice->chan == chan && voice->key == key)
2493 result = fluid_voice_modulate(voice, 0, FLUID_MOD_KEYPRESSURE);
2495 if(result != FLUID_OK)
2506 * Set the MIDI pitch bend controller value on a MIDI channel.
2507 * @param synth FluidSynth instance
2508 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2509 * @param val MIDI pitch bend value (0-16383 with 8192 being center)
2510 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2513 fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val)
2516 fluid_return_val_if_fail(val >= 0 && val <= 16383, FLUID_FAILED);
2517 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2519 /* Allowed only on MIDI channel enabled */
2520 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2524 FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val);
2527 fluid_channel_set_pitch_bend(synth->channel[chan], val);
2528 result = fluid_synth_update_pitch_bend_LOCAL(synth, chan);
2530 FLUID_API_RETURN(result);
2533 /* Local synthesis thread variant of pitch bend */
2535 fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan)
2537 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEEL);
2541 * Get the MIDI pitch bend controller value on a MIDI channel.
2542 * @param synth FluidSynth instance
2543 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2544 * @param ppitch_bend Location to store MIDI pitch bend value (0-16383 with
2545 * 8192 being center)
2546 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2549 fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend)
2552 fluid_return_val_if_fail(ppitch_bend != NULL, FLUID_FAILED);
2553 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2555 /* Allowed only on MIDI channel enabled */
2556 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2558 *ppitch_bend = fluid_channel_get_pitch_bend(synth->channel[chan]);
2561 FLUID_API_RETURN(result);
2565 * Set MIDI pitch wheel sensitivity on a MIDI channel.
2566 * @param synth FluidSynth instance
2567 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2568 * @param val Pitch wheel sensitivity value in semitones
2569 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2572 fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val)
2575 fluid_return_val_if_fail(val >= 0 && val <= 72, FLUID_FAILED); /* 6 octaves!? Better than no limit.. */
2576 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2578 /* Allowed only on MIDI channel enabled */
2579 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2583 FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val);
2586 fluid_channel_set_pitch_wheel_sensitivity(synth->channel[chan], val);
2587 result = fluid_synth_update_pitch_wheel_sens_LOCAL(synth, chan);
2589 FLUID_API_RETURN(result);
2592 /* Local synthesis thread variant of set pitch wheel sensitivity */
2594 fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan)
2596 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEELSENS);
2600 * Get MIDI pitch wheel sensitivity on a MIDI channel.
2601 * @param synth FluidSynth instance
2602 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2603 * @param pval Location to store pitch wheel sensitivity value in semitones
2604 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2605 * @since Sometime AFTER v1.0 API freeze.
2608 fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval)
2611 fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
2612 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2614 /* Allowed only on MIDI channel enabled */
2615 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2617 *pval = fluid_channel_get_pitch_wheel_sensitivity(synth->channel[chan]);
2620 FLUID_API_RETURN(result);
2624 * Assign a preset to a MIDI channel.
2625 * @param synth FluidSynth instance
2626 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2627 * @param preset Preset to assign to channel or NULL to clear (ownership is taken over)
2628 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2631 fluid_synth_set_preset(fluid_synth_t *synth, int chan, fluid_preset_t *preset)
2633 fluid_channel_t *channel;
2635 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2636 fluid_return_val_if_fail(chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
2638 channel = synth->channel[chan];
2640 return fluid_channel_set_preset(channel, preset);
2643 /* Get a preset by SoundFont, bank and program numbers.
2644 * Returns preset pointer or NULL.
2646 static fluid_preset_t *
2647 fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
2648 int banknum, int prognum)
2650 fluid_sfont_t *sfont;
2653 /* 128 indicates an "unset" operation" */
2654 if(prognum == FLUID_UNSET_PROGRAM)
2659 for(list = synth->sfont; list; list = fluid_list_next(list))
2661 sfont = fluid_list_get(list);
2663 if(fluid_sfont_get_id(sfont) == sfontnum)
2665 return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2672 /* Get a preset by SoundFont name, bank and program.
2673 * Returns preset pointer or NULL.
2675 static fluid_preset_t *
2676 fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname,
2677 int banknum, int prognum)
2679 fluid_sfont_t *sfont;
2682 for(list = synth->sfont; list; list = fluid_list_next(list))
2684 sfont = fluid_list_get(list);
2686 if(FLUID_STRCMP(fluid_sfont_get_name(sfont), sfontname) == 0)
2688 return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2695 /* Find a preset by bank and program numbers.
2696 * Returns preset pointer or NULL.
2699 fluid_synth_find_preset(fluid_synth_t *synth, int banknum,
2702 fluid_preset_t *preset;
2703 fluid_sfont_t *sfont;
2706 for(list = synth->sfont; list; list = fluid_list_next(list))
2708 sfont = fluid_list_get(list);
2710 preset = fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2722 * Send a program change event on a MIDI channel.
2723 * @param synth FluidSynth instance
2724 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2725 * @param prognum MIDI program number (0-127)
2726 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2728 /* FIXME - Currently not real-time safe, due to preset allocation and mutex lock,
2729 * and may be called from within synthesis context. */
2731 /* As of 1.1.1 prognum can be set to 128 to unset the preset. Not documented
2732 * since fluid_synth_unset_program() should be used instead. */
2734 fluid_synth_program_change(fluid_synth_t *synth, int chan, int prognum)
2736 fluid_preset_t *preset = NULL;
2737 fluid_channel_t *channel;
2738 int subst_bank, subst_prog, banknum = 0, result = FLUID_FAILED;
2740 fluid_return_val_if_fail(prognum >= 0 && prognum <= 128, FLUID_FAILED);
2741 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2743 /* Allowed only on MIDI channel enabled */
2744 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2746 channel = synth->channel[chan];
2748 if(channel->channel_type == CHANNEL_TYPE_DRUM)
2750 banknum = DRUM_INST_BANK;
2754 fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
2759 FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
2762 /* I think this is a hack for MIDI files that do bank changes in GM mode.
2763 * Proper way to handle this would probably be to ignore bank changes when in
2765 * This is now possible by setting synth.midi-bank-select=gm, but let the hack
2766 * stay for the time being. - DH
2768 if(prognum != FLUID_UNSET_PROGRAM)
2770 subst_bank = banknum;
2771 subst_prog = prognum;
2773 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2775 /* Fallback to another preset if not found */
2778 /* Percussion: Fallback to preset 0 in percussion bank */
2779 if(channel->channel_type == CHANNEL_TYPE_DRUM)
2782 subst_bank = DRUM_INST_BANK;
2783 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2785 /* Melodic instrument */
2788 /* Fallback first to bank 0:prognum */
2790 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2792 /* Fallback to first preset in bank 0 (usually piano...) */
2796 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2802 FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
2803 chan, banknum, prognum, subst_bank, subst_prog);
2807 FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]", chan, banknum, prognum);
2812 /* Assign the SoundFont ID and program number to the channel */
2813 fluid_channel_set_sfont_bank_prog(channel, preset ? fluid_sfont_get_id(preset->sfont) : 0,
2815 result = fluid_synth_set_preset(synth, chan, preset);
2817 FLUID_API_RETURN(result);
2821 * Set instrument bank number on a MIDI channel.
2822 * @param synth FluidSynth instance
2823 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2824 * @param bank MIDI bank number
2825 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2826 * @note This function does not change the instrument currently assigned to \c chan,
2827 * as it is usually called prior to fluid_synth_program_change(). If you still want
2828 * instrument changes to take effect immediately, call fluid_synth_program_reset()
2829 * after having set up the bank configuration.
2833 fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank)
2836 fluid_return_val_if_fail(bank <= 16383, FLUID_FAILED);
2837 fluid_return_val_if_fail(bank >= 0, FLUID_FAILED);
2838 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2840 /* Allowed only on MIDI channel enabled */
2841 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2843 fluid_channel_set_sfont_bank_prog(synth->channel[chan], -1, bank, -1);
2846 FLUID_API_RETURN(result);
2850 * Set SoundFont ID on a MIDI channel.
2851 * @param synth FluidSynth instance
2852 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2853 * @param sfont_id ID of a loaded SoundFont
2854 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2855 * @note This function does not change the instrument currently assigned to \c chan,
2856 * as it is usually called prior to fluid_synth_bank_select() or fluid_synth_program_change().
2857 * If you still want instrument changes to take effect immediately, call fluid_synth_program_reset()
2858 * after having selected the soundfont.
2861 fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id)
2864 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2866 /* Allowed only on MIDI channel enabled */
2867 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2869 fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
2872 FLUID_API_RETURN(result);
2876 * Set the preset of a MIDI channel to an unassigned state.
2877 * @param synth FluidSynth instance
2878 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2879 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2882 * @note Channel retains its SoundFont ID and bank numbers, while the program
2883 * number is set to an "unset" state. MIDI program changes may re-assign a
2884 * preset if one matches.
2887 fluid_synth_unset_program(fluid_synth_t *synth, int chan)
2889 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2890 FLUID_API_RETURN(fluid_synth_program_change(synth, chan, FLUID_UNSET_PROGRAM));
2894 * Get current SoundFont ID, bank number and program number for a MIDI channel.
2895 * @param synth FluidSynth instance
2896 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2897 * @param sfont_id Location to store SoundFont ID
2898 * @param bank_num Location to store MIDI bank number
2899 * @param preset_num Location to store MIDI program number
2900 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2903 fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id,
2904 int *bank_num, int *preset_num)
2907 fluid_channel_t *channel;
2909 fluid_return_val_if_fail(sfont_id != NULL, FLUID_FAILED);
2910 fluid_return_val_if_fail(bank_num != NULL, FLUID_FAILED);
2911 fluid_return_val_if_fail(preset_num != NULL, FLUID_FAILED);
2912 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2914 /* Allowed only on MIDI channel enabled */
2915 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2917 channel = synth->channel[chan];
2918 fluid_channel_get_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
2920 /* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */
2921 if(*preset_num == FLUID_UNSET_PROGRAM)
2928 FLUID_API_RETURN(result);
2932 * Select an instrument on a MIDI channel by SoundFont ID, bank and program numbers.
2933 * @param synth FluidSynth instance
2934 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2935 * @param sfont_id ID of a loaded SoundFont
2936 * @param bank_num MIDI bank number
2937 * @param preset_num MIDI program number
2938 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2941 fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
2942 int bank_num, int preset_num)
2944 fluid_preset_t *preset = NULL;
2945 fluid_channel_t *channel;
2947 fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
2948 fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
2950 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2952 /* Allowed only on MIDI channel enabled */
2953 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2955 channel = synth->channel[chan];
2957 preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
2961 FLUID_LOG(FLUID_ERR,
2962 "There is no preset with bank number %d and preset number %d in SoundFont %d",
2963 bank_num, preset_num, sfont_id);
2964 FLUID_API_RETURN(FLUID_FAILED);
2967 /* Assign the new SoundFont ID, bank and program number to the channel */
2968 fluid_channel_set_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
2969 result = fluid_synth_set_preset(synth, chan, preset);
2971 FLUID_API_RETURN(result);
2975 * Select an instrument on a MIDI channel by SoundFont name, bank and program numbers.
2976 * @param synth FluidSynth instance
2977 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2978 * @param sfont_name Name of a loaded SoundFont
2979 * @param bank_num MIDI bank number
2980 * @param preset_num MIDI program number
2981 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2985 fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan,
2986 const char *sfont_name, int bank_num,
2989 fluid_preset_t *preset = NULL;
2990 fluid_channel_t *channel;
2992 fluid_return_val_if_fail(sfont_name != NULL, FLUID_FAILED);
2993 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2995 /* Allowed only on MIDI channel enabled */
2996 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2998 channel = synth->channel[chan];
3000 preset = fluid_synth_get_preset_by_sfont_name(synth, sfont_name, bank_num,
3005 FLUID_LOG(FLUID_ERR,
3006 "There is no preset with bank number %d and preset number %d in SoundFont %s",
3007 bank_num, preset_num, sfont_name);
3008 FLUID_API_RETURN(FLUID_FAILED);
3011 /* Assign the new SoundFont ID, bank and program number to the channel */
3012 fluid_channel_set_sfont_bank_prog(channel, fluid_sfont_get_id(preset->sfont),
3013 bank_num, preset_num);
3014 result = fluid_synth_set_preset(synth, chan, preset);
3016 FLUID_API_RETURN(result);
3020 * This function assures that every MIDI channel has a valid preset
3021 * (NULL is okay). This function is called after a SoundFont is
3022 * unloaded or reloaded.
3025 fluid_synth_update_presets(fluid_synth_t *synth)
3027 fluid_channel_t *channel;
3028 fluid_preset_t *preset;
3029 int sfont, bank, prog;
3032 for(chan = 0; chan < synth->midi_channels; chan++)
3034 channel = synth->channel[chan];
3035 fluid_channel_get_sfont_bank_prog(channel, &sfont, &bank, &prog);
3036 preset = fluid_synth_get_preset(synth, sfont, bank, prog);
3037 fluid_synth_set_preset(synth, chan, preset);
3041 /* Handler for synth.sample-rate setting. */
3043 fluid_synth_handle_sample_rate(void *data, const char *name, double value)
3045 fluid_synth_t *synth = (fluid_synth_t *)data;
3046 fluid_synth_set_sample_rate(synth, (float) value);
3051 * Set sample rate of the synth.
3052 * @note This function should only be used when no voices or notes are active.
3053 * @param synth FluidSynth instance
3054 * @param sample_rate New sample rate (Hz)
3058 fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate)
3061 fluid_return_if_fail(synth != NULL);
3062 fluid_synth_api_enter(synth);
3063 fluid_clip(sample_rate, 8000.0f, 96000.0f);
3064 synth->sample_rate = sample_rate;
3066 synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
3068 for(i = 0; i < synth->polyphony; i++)
3070 fluid_voice_set_output_rate(synth->voice[i], sample_rate);
3073 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate,
3075 fluid_synth_api_exit(synth);
3079 /* Handler for synth.gain setting. */
3081 fluid_synth_handle_gain(void *data, const char *name, double value)
3083 fluid_synth_t *synth = (fluid_synth_t *)data;
3084 fluid_synth_set_gain(synth, (float) value);
3088 * Set synth output gain value.
3089 * @param synth FluidSynth instance
3090 * @param gain Gain value (function clamps value to the range 0.0 to 10.0)
3093 fluid_synth_set_gain(fluid_synth_t *synth, float gain)
3095 fluid_return_if_fail(synth != NULL);
3096 fluid_synth_api_enter(synth);
3098 fluid_clip(gain, 0.0f, 10.0f);
3101 fluid_synth_update_gain_LOCAL(synth);
3102 fluid_synth_api_exit(synth);
3105 /* Called by synthesis thread to update the gain in all voices */
3107 fluid_synth_update_gain_LOCAL(fluid_synth_t *synth)
3109 fluid_voice_t *voice;
3115 for(i = 0; i < synth->polyphony; i++)
3117 voice = synth->voice[i];
3119 if(fluid_voice_is_playing(voice))
3121 fluid_voice_set_gain(voice, gain);
3127 * Get synth output gain value.
3128 * @param synth FluidSynth instance
3129 * @return Synth gain value (0.0 to 10.0)
3132 fluid_synth_get_gain(fluid_synth_t *synth)
3135 fluid_return_val_if_fail(synth != NULL, 0.0);
3136 fluid_synth_api_enter(synth);
3138 result = synth->gain;
3139 FLUID_API_RETURN(result);
3143 * Handler for synth.polyphony setting.
3146 fluid_synth_handle_polyphony(void *data, const char *name, int value)
3148 fluid_synth_t *synth = (fluid_synth_t *)data;
3149 fluid_synth_set_polyphony(synth, value);
3153 * Set synthesizer polyphony (max number of voices).
3154 * @param synth FluidSynth instance
3155 * @param polyphony Polyphony to assign
3156 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3160 fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony)
3163 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3164 fluid_return_val_if_fail(polyphony >= 1 && polyphony <= 65535, FLUID_FAILED);
3165 fluid_synth_api_enter(synth);
3167 result = fluid_synth_update_polyphony_LOCAL(synth, polyphony);
3169 FLUID_API_RETURN(result);
3172 /* Called by synthesis thread to update the polyphony value */
3174 fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony)
3176 fluid_voice_t *voice;
3179 if(new_polyphony > synth->nvoice)
3181 /* Create more voices */
3182 fluid_voice_t **new_voices = FLUID_REALLOC(synth->voice,
3183 sizeof(fluid_voice_t *) * new_polyphony);
3185 if(new_voices == NULL)
3187 return FLUID_FAILED;
3190 synth->voice = new_voices;
3192 for(i = synth->nvoice; i < new_polyphony; i++)
3194 synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
3196 if(synth->voice[i] == NULL)
3198 return FLUID_FAILED;
3201 fluid_voice_set_custom_filter(synth->voice[i], synth->custom_filter_type, synth->custom_filter_flags);
3204 synth->nvoice = new_polyphony;
3207 synth->polyphony = new_polyphony;
3209 /* turn off any voices above the new limit */
3210 for(i = synth->polyphony; i < synth->nvoice; i++)
3212 voice = synth->voice[i];
3214 if(fluid_voice_is_playing(voice))
3216 fluid_voice_off(voice);
3220 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
3221 synth->polyphony, 0.0f);
3227 * Get current synthesizer polyphony (max number of voices).
3228 * @param synth FluidSynth instance
3229 * @return Synth polyphony value.
3233 fluid_synth_get_polyphony(fluid_synth_t *synth)
3236 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3237 fluid_synth_api_enter(synth);
3239 result = synth->polyphony;
3240 FLUID_API_RETURN(result);
3244 * @brief Get current number of active voices.
3246 * I.e. the no. of voices that have been
3247 * started and have not yet finished. Unless called from synthesis context,
3248 * this number does not necessarily have to be equal to the number of voices
3249 * currently processed by the DSP loop, see below.
3250 * @param synth FluidSynth instance
3251 * @return Number of currently active voices.
3254 * @note To generate accurate continuous statistics of the voice count, caller
3255 * should ensure this function is called synchronously with the audio synthesis
3256 * process. This can be done in the new_fluid_audio_driver2() audio callback
3257 * function for example. Otherwise every call to this function may return different
3258 * voice counts as it may change after any (concurrent) call to fluid_synth_write_*() made by
3259 * e.g. an audio driver or the applications audio rendering thread.
3262 fluid_synth_get_active_voice_count(fluid_synth_t *synth)
3265 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3266 fluid_synth_api_enter(synth);
3268 result = synth->active_voice_count;
3269 FLUID_API_RETURN(result);
3273 * Get the internal synthesis buffer size value.
3274 * @param synth FluidSynth instance
3275 * @return Internal buffer size in audio frames.
3277 * Audio is synthesized this number of frames at a time. Defaults to 64 frames.
3280 fluid_synth_get_internal_bufsize(fluid_synth_t *synth)
3282 return FLUID_BUFSIZE;
3286 * Resend a bank select and a program change for every channel and assign corresponding instruments.
3287 * @param synth FluidSynth instance
3288 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3290 * This function is called mainly after a SoundFont has been loaded,
3291 * unloaded or reloaded.
3294 fluid_synth_program_reset(fluid_synth_t *synth)
3297 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3298 fluid_synth_api_enter(synth);
3300 /* try to set the correct presets */
3301 for(i = 0; i < synth->midi_channels; i++)
3303 fluid_channel_get_sfont_bank_prog(synth->channel[i], NULL, NULL, &prog);
3304 fluid_synth_program_change(synth, i, prog);
3307 FLUID_API_RETURN(FLUID_OK);
3311 * Synthesize a block of floating point audio to separate audio buffers (multichannel rendering). First effect channel used by reverb, second for chorus.
3312 * @param synth FluidSynth instance
3313 * @param len Count of audio frames to synthesize
3314 * @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)
3315 * @param right Array of float buffers to store right channel of planar audio (size: dito)
3316 * @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)
3317 * @param fx_right Since 1.1.7: If not \c NULL, array of float buffers to store right effect channels (size: dito)
3318 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3320 * @note Should only be called from synthesis thread.
3322 * @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().
3326 const int FramesToRender = 64;
3328 // retrieve number of stereo audio channels
3329 fluid_settings_getint(settings, "synth.audio-channels", &channels);
3331 // we need twice as many (mono-)buffers
3334 // 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
3335 float** mix_buf = new float*[channels];
3336 for(int i = 0; i < channels; i++)
3338 mix_buf[i] = new float[FramesToRender];
3341 // retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan) and chrous (second chan))
3342 fluid_settings_getint(settings, "synth.effects-channels", &channels);
3345 float** fx_buf = new float*[channels];
3346 for(int i = 0; i < channels; i++)
3348 fx_buf[i] = new float[FramesToRender];
3351 float** mix_buf_l = mix_buf;
3352 float** mix_buf_r = &mix_buf[channels/2];
3354 float** fx_buf_l = fx_buf;
3355 float** fx_buf_r = &fx_buf[channels/2];
3357 fluid_synth_nwrite_float(synth, FramesToRender, mix_buf_l, mix_buf_r, fx_buf_l, fx_buf_r)
3361 fluid_synth_nwrite_float(fluid_synth_t *synth, int len,
3362 float **left, float **right,
3363 float **fx_left, float **fx_right)
3365 fluid_real_t *left_in, *fx_left_in;
3366 fluid_real_t *right_in, *fx_right_in;
3367 double time = fluid_utime();
3368 int i, num, available, count;
3374 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3375 fluid_return_val_if_fail(left != NULL, FLUID_FAILED);
3376 fluid_return_val_if_fail(right != NULL, FLUID_FAILED);
3378 /* First, take what's still available in the buffer */
3382 if(synth->cur < FLUID_BUFSIZE)
3384 available = FLUID_BUFSIZE - synth->cur;
3385 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3386 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3388 num = (available > len) ? len : available;
3390 bytes = num * sizeof(float);
3393 for(i = 0; i < synth->audio_channels; i++)
3396 FLUID_MEMCPY(left[i], &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3397 FLUID_MEMCPY(right[i], &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3401 for(j = 0; j < num; j++)
3403 left[i][j] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3404 right[i][j] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3410 for(i = 0; i < synth->effects_channels; i++)
3416 FLUID_MEMCPY(fx_left[i], &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3419 if(fx_right != NULL)
3421 FLUID_MEMCPY(fx_right[i], &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3429 for(j = 0; j < num; j++)
3431 fx_left[i][j] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3435 if(fx_right != NULL)
3437 for(j = 0; j < num; j++)
3439 fx_right[i][j] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3447 num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3450 /* Then, run one_block() and copy till we have 'len' samples */
3453 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0);
3454 fluid_synth_render_blocks(synth, 1); // TODO:
3455 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3456 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3458 num = (FLUID_BUFSIZE > len - count) ? len - count : FLUID_BUFSIZE;
3460 bytes = num * sizeof(float);
3463 for(i = 0; i < synth->audio_channels; i++)
3466 FLUID_MEMCPY(left[i] + count, &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3467 FLUID_MEMCPY(right[i] + count, &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3471 for(j = 0; j < num; j++)
3473 left[i][j + count] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3474 right[i][j + count] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3480 for(i = 0; i < synth->effects_channels; i++)
3486 FLUID_MEMCPY(fx_left[i] + count, &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3489 if(fx_right != NULL)
3491 FLUID_MEMCPY(fx_right[i] + count, &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3499 for(j = 0; j < num; j++)
3501 fx_left[i][j + count] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3505 if(fx_right != NULL)
3507 for(j = 0; j < num; j++)
3509 fx_right[i][j + count] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3521 time = fluid_utime() - time;
3522 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3523 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3529 * mixes the samples of \p in to \p out
3531 * @param out the output sample buffer to mix to
3532 * @param ooff sample offset in \p out
3533 * @param in the rvoice_mixer input sample buffer to mix from
3534 * @param ioff sample offset in \p in
3535 * @param buf_idx the sample buffer index of \p in to mix from
3536 * @param num number of samples to mix
3538 static FLUID_INLINE void fluid_synth_mix_single_buffer(float *FLUID_RESTRICT out,
3540 const fluid_real_t *FLUID_RESTRICT in,
3549 for(j = 0; j < num; j++)
3551 out[j + ooff] += (float) in[buf_idx * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + ioff];
3557 * @brief Synthesize floating point audio to stereo audio channels (implements the default interface #fluid_audio_func_t).
3559 * Synthesize and <strong>mix</strong> audio to a given number of planar audio buffers.
3560 * Therefore pass <code>nout = N*2</code> float buffers to \p out in order to render
3561 * the synthesized audio to \p N stereo channels. Each float buffer must be
3562 * able to hold \p len elements.
3564 * \p out contains an array of planar buffers for normal, dry, stereo
3565 * audio (alternating left and right). Like:
3567 out[0] = left_buffer_audio_channel_0
3568 out[1] = right_buffer_audio_channel_0
3569 out[2] = left_buffer_audio_channel_1
3570 out[3] = right_buffer_audio_channel_1
3572 out[ (i * 2 + 0) % nout ] = left_buffer_audio_channel_i
3573 out[ (i * 2 + 1) % nout ] = right_buffer_audio_channel_i
3576 * for zero-based channel index \p i.
3577 * The buffer layout of \p fx used for storing effects
3578 * like reverb and chorus looks similar:
3580 fx[0] = left_buffer_channel_of_reverb_unit_0
3581 fx[1] = right_buffer_channel_of_reverb_unit_0
3582 fx[2] = left_buffer_channel_of_chorus_unit_0
3583 fx[3] = right_buffer_channel_of_chorus_unit_0
3584 fx[4] = left_buffer_channel_of_reverb_unit_1
3585 fx[5] = right_buffer_channel_of_reverb_unit_1
3586 fx[6] = left_buffer_channel_of_chorus_unit_1
3587 fx[7] = right_buffer_channel_of_chorus_unit_1
3588 fx[8] = left_buffer_channel_of_reverb_unit_2
3590 fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 0) % nfx ] = left_buffer_for_effect_channel_j_of_unit_k
3591 fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 1) % nfx ] = right_buffer_for_effect_channel_j_of_unit_k
3593 * where <code>0 <= k < fluid_synth_count_effects_groups()</code> is a zero-based index denoting the effects unit and
3594 * <code>0 <= j < fluid_synth_count_effects_channels()</code> is a zero-based index denoting the effect channel within
3597 * Any voice playing is assigned to audio channels based on the MIDI channel its playing on. Let \p chan be the
3598 * zero-based MIDI channel index an arbitrary voice is playing on. To determine the audio channel and effects unit it is
3599 * going to be rendered to use:
3601 * <code>i = chan % fluid_synth_count_audio_groups()</code>
3603 * <code>k = chan % fluid_synth_count_effects_groups()</code>
3605 * @param synth FluidSynth instance
3606 * @param len Count of audio frames to synthesize and store in every single buffer provided by \p out and \p fx.
3607 * @param nfx Count of arrays in \c fx. Must be a multiple of 2 (because of stereo)
3608 * and in the range <code>0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
3609 * @param fx Array of buffers to store effects audio to. Buffers may
3610 alias with buffers of \c out. NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
3611 * @param nout Count of arrays in \c out. Must be a multiple of 2
3612 (because of stereo) and in the range <code>0 <= nout/2 <= fluid_synth_count_audio_channels()</code>.
3613 * @param out Array of buffers to store (dry) audio to. Buffers may
3614 alias with buffers of \c fx. NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
3615 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
3618 * @note The owner of the sample buffers must zero them out before calling this
3619 * function, because any synthesized audio is mixed (i.e. added) to the buffers.
3620 * E.g. if fluid_synth_process() is called from a custom audio driver process function
3621 * (see new_fluid_audio_driver2()), the audio driver takes care of zeroing the buffers.
3625 * @note No matter how many buffers you pass in, fluid_synth_process()
3626 * will always render all audio channels to the
3627 * buffers in \c out and all effects channels to the
3628 * buffers in \c fx, provided that <code>nout > 0</code> and <code>nfx > 0</code> respectively. If
3629 * <code>nout/2 < fluid_synth_count_audio_channels()</code> it will wrap around. Same
3630 * is true for effects audio if <code>nfx/2 < (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
3631 * See usage examples below.
3635 * @note Should only be called from synthesis thread.
3639 fluid_synth_process(fluid_synth_t *synth, int len, int nfx, float *fx[],
3640 int nout, float *out[])
3642 fluid_real_t *left_in, *fx_left_in;
3643 fluid_real_t *right_in, *fx_right_in;
3644 int nfxchan, nfxunits, naudchan;
3646 double time = fluid_utime();
3647 int i, f, num, count;
3651 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3652 fluid_return_val_if_fail(nfx % 2 == 0, FLUID_FAILED);
3653 fluid_return_val_if_fail(nout % 2 == 0, FLUID_FAILED);
3655 nfxchan = synth->effects_channels;
3656 nfxunits = synth->effects_groups;
3657 naudchan = synth->audio_channels;
3659 fluid_return_val_if_fail(0 <= nfx / 2 && nfx / 2 <= nfxchan * nfxunits, FLUID_FAILED);
3660 fluid_return_val_if_fail(0 <= nout / 2 && nout / 2 <= naudchan, FLUID_FAILED);
3662 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3663 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3664 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, FALSE);
3667 /* First, take what's still available in the buffer */
3671 if(synth->cur < FLUID_BUFSIZE)
3673 int available = FLUID_BUFSIZE - synth->cur;
3674 num = (available > len) ? len : available;
3678 for(i = 0; i < naudchan; i++)
3680 float *out_buf = out[(i * 2) % nout];
3681 fluid_synth_mix_single_buffer(out_buf, 0, left_in, synth->cur, i, num);
3683 out_buf = out[(i * 2 + 1) % nout];
3684 fluid_synth_mix_single_buffer(out_buf, 0, right_in, synth->cur, i, num);
3690 // loop over all effects units
3691 for(f = 0; f < nfxunits; f++)
3693 // write out all effects (i.e. reverb and chorus)
3694 for(i = 0; i < nfxchan; i++)
3696 int buf_idx = f * nfxchan + i;
3698 float *out_buf = fx[(buf_idx * 2) % nfx];
3699 fluid_synth_mix_single_buffer(out_buf, 0, fx_left_in, synth->cur, buf_idx, num);
3701 out_buf = fx[(buf_idx * 2 + 1) % nfx];
3702 fluid_synth_mix_single_buffer(out_buf, 0, fx_right_in, synth->cur, buf_idx, num);
3708 num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3711 /* Then, render blocks and copy till we have 'len' samples */
3714 int blocksleft = (len - count + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3715 int blockcount = fluid_synth_render_blocks(synth, blocksleft);
3717 num = (blockcount * FLUID_BUFSIZE > len - count) ? len - count : blockcount * FLUID_BUFSIZE;
3721 for(i = 0; i < naudchan; i++)
3723 float *out_buf = out[(i * 2) % nout];
3724 fluid_synth_mix_single_buffer(out_buf, count, left_in, 0, i, num);
3726 out_buf = out[(i * 2 + 1) % nout];
3727 fluid_synth_mix_single_buffer(out_buf, count, right_in, 0, i, num);
3733 // loop over all effects units
3734 for(f = 0; f < nfxunits; f++)
3736 // write out all effects (i.e. reverb and chorus)
3737 for(i = 0; i < nfxchan; i++)
3739 int buf_idx = f * nfxchan + i;
3741 float *out_buf = fx[(buf_idx * 2) % nfx];
3742 fluid_synth_mix_single_buffer(out_buf, count, fx_left_in, 0, buf_idx, num);
3744 out_buf = fx[(buf_idx * 2 + 1) % nfx];
3745 fluid_synth_mix_single_buffer(out_buf, count, fx_right_in, 0, buf_idx, num);
3755 time = fluid_utime() - time;
3756 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3757 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3763 * Synthesize a block of floating point audio samples to audio buffers.
3764 * @param synth FluidSynth instance
3765 * @param len Count of audio frames to synthesize
3766 * @param lout Array of floats to store left channel of audio
3767 * @param loff Offset index in 'lout' for first sample
3768 * @param lincr Increment between samples stored to 'lout'
3769 * @param rout Array of floats to store right channel of audio
3770 * @param roff Offset index in 'rout' for first sample
3771 * @param rincr Increment between samples stored to 'rout'
3772 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3774 * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
3775 * lincr = 2, rincr = 2).
3777 * @note Should only be called from synthesis thread.
3778 * @note Reverb and Chorus are mixed to \c lout resp. \c rout.
3781 fluid_synth_write_float(fluid_synth_t *synth, int len,
3782 void *lout, int loff, int lincr,
3783 void *rout, int roff, int rincr)
3786 float *left_out = (float *) lout;
3787 float *right_out = (float *) rout;
3788 fluid_real_t *left_in;
3789 fluid_real_t *right_in;
3790 double time = fluid_utime();
3793 fluid_profile_ref_var(prof_ref);
3795 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3796 fluid_return_val_if_fail(lout != NULL, FLUID_FAILED);
3797 fluid_return_val_if_fail(rout != NULL, FLUID_FAILED);
3799 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
3801 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3803 for(i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr)
3805 /* fill up the buffers as needed */
3806 if(l >= synth->curmax)
3808 int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3809 synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
3810 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3815 left_out[j] = (float) left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l];
3816 right_out[k] = (float) right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l];
3821 time = fluid_utime() - time;
3822 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3823 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3825 fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
3826 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
3831 #define DITHER_SIZE 48000
3832 #define DITHER_CHANNELS 2
3834 static float rand_table[DITHER_CHANNELS][DITHER_SIZE];
3836 /* Init dither table */
3843 for(c = 0; c < DITHER_CHANNELS; c++)
3847 for(i = 0; i < DITHER_SIZE - 1; i++)
3849 d = rand() / (float)RAND_MAX - 0.5f;
3850 rand_table[c][i] = d - dp;
3854 rand_table[c][DITHER_SIZE - 1] = 0 - dp;
3858 /* A portable replacement for roundf(), seems it may actually be faster too! */
3859 static FLUID_INLINE int16_t
3860 round_clip_to_i16(float x)
3866 i = (long)(x + 0.5f);
3868 if(FLUID_UNLIKELY(i > 32767))
3875 i = (long)(x - 0.5f);
3877 if(FLUID_UNLIKELY(i < -32768))
3887 * Synthesize a block of 16 bit audio samples to audio buffers.
3888 * @param synth FluidSynth instance
3889 * @param len Count of audio frames to synthesize
3890 * @param lout Array of 16 bit words to store left channel of audio
3891 * @param loff Offset index in 'lout' for first sample
3892 * @param lincr Increment between samples stored to 'lout'
3893 * @param rout Array of 16 bit words to store right channel of audio
3894 * @param roff Offset index in 'rout' for first sample
3895 * @param rincr Increment between samples stored to 'rout'
3896 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3898 * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
3899 * lincr = 2, rincr = 2).
3901 * @note Should only be called from synthesis thread.
3902 * @note Reverb and Chorus are mixed to \c lout resp. \c rout.
3903 * @note Dithering is performed when converting from internal floating point to
3907 fluid_synth_write_s16(fluid_synth_t *synth, int len,
3908 void *lout, int loff, int lincr,
3909 void *rout, int roff, int rincr)
3912 int16_t *left_out = lout;
3913 int16_t *right_out = rout;
3914 fluid_real_t *left_in;
3915 fluid_real_t *right_in;
3916 double time = fluid_utime();
3920 fluid_profile_ref_var(prof_ref);
3922 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
3923 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3926 di = synth->dither_index;
3928 for(i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr)
3931 /* fill up the buffers as needed */
3932 if(cur >= synth->curmax)
3934 int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3935 synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
3936 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3940 left_out[j] = round_clip_to_i16(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]);
3941 right_out[k] = round_clip_to_i16(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]);
3943 if(++di >= DITHER_SIZE)
3950 synth->dither_index = di; /* keep dither buffer continous */
3952 time = fluid_utime() - time;
3953 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3954 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3956 fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
3957 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
3963 * Converts stereo floating point sample data to signed 16 bit data with dithering.
3964 * @param dither_index Pointer to an integer which should be initialized to 0
3965 * before the first call and passed unmodified to additional calls which are
3966 * part of the same synthesis output.
3967 * @param len Length in frames to convert
3968 * @param lin Buffer of left audio samples to convert from
3969 * @param rin Buffer of right audio samples to convert from
3970 * @param lout Array of 16 bit words to store left channel of audio
3971 * @param loff Offset index in 'lout' for first sample
3972 * @param lincr Increment between samples stored to 'lout'
3973 * @param rout Array of 16 bit words to store right channel of audio
3974 * @param roff Offset index in 'rout' for first sample
3975 * @param rincr Increment between samples stored to 'rout'
3977 * @note Currently private to libfluidsynth.
3980 fluid_synth_dither_s16(int *dither_index, int len, const float *lin, const float *rin,
3981 void *lout, int loff, int lincr,
3982 void *rout, int roff, int rincr)
3985 int16_t *left_out = lout;
3986 int16_t *right_out = rout;
3987 int di = *dither_index;
3988 fluid_profile_ref_var(prof_ref);
3990 for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr)
3992 left_out[j] = round_clip_to_i16(lin[i] * 32766.0f + rand_table[0][di]);
3993 right_out[k] = round_clip_to_i16(rin[i] * 32766.0f + rand_table[1][di]);
3995 if(++di >= DITHER_SIZE)
4001 *dither_index = di; /* keep dither buffer continous */
4003 fluid_profile(FLUID_PROF_WRITE, prof_ref, 0, len);
4007 fluid_synth_check_finished_voices(fluid_synth_t *synth)
4012 while(NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler)))
4014 for(j = 0; j < synth->polyphony; j++)
4016 if(synth->voice[j]->rvoice == fv)
4018 fluid_voice_unlock_rvoice(synth->voice[j]);
4019 fluid_voice_stop(synth->voice[j]);
4022 else if(synth->voice[j]->overflow_rvoice == fv)
4024 fluid_voice_overflow_rvoice_finished(synth->voice[j]);
4032 * Process all waiting events in the rvoice queue.
4033 * Make sure no (other) rendering is running in parallel when
4034 * you call this function!
4036 void fluid_synth_process_event_queue(fluid_synth_t *synth)
4038 fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4043 * Process blocks (FLUID_BUFSIZE) of audio.
4044 * Must be called from renderer thread only!
4045 * @return number of blocks rendered. Might (often) return less than requested
4048 fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount)
4051 fluid_profile_ref_var(prof_ref);
4053 /* Assign ID of synthesis thread */
4054 // synth->synth_thread_id = fluid_thread_get_id ();
4056 fluid_check_fpe("??? Just starting up ???");
4058 fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4060 /* do not render more blocks than we can store internally */
4061 maxblocks = fluid_rvoice_mixer_get_bufcount(synth->eventhandler->mixer);
4063 if(blockcount > maxblocks)
4065 blockcount = maxblocks;
4068 for(i = 0; i < blockcount; i++)
4070 fluid_sample_timer_process(synth);
4071 fluid_synth_add_ticks(synth, FLUID_BUFSIZE);
4073 /* If events have been queued waiting for fluid_rvoice_eventhandler_dispatch_all()
4074 * (should only happen with parallel render) stop processing and go for rendering
4076 if(fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler))
4078 // Something has happened, we can't process more
4084 fluid_check_fpe("fluid_sample_timer_process");
4086 blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount);
4088 /* Testcase, that provokes a denormal floating point error */
4099 fluid_check_fpe("??? Remainder of synth_one_block ???");
4100 fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref,
4101 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
4102 blockcount * FLUID_BUFSIZE);
4107 * Handler for synth.reverb.* and synth.chorus.* double settings.
4109 static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value)
4111 fluid_synth_t *synth = (fluid_synth_t *)data;
4112 fluid_return_if_fail(synth != NULL);
4114 if(FLUID_STRCMP(name, "synth.reverb.room-size") == 0)
4116 fluid_synth_set_reverb_roomsize(synth, value);
4118 else if(FLUID_STRCMP(name, "synth.reverb.damp") == 0)
4120 fluid_synth_set_reverb_damp(synth, value);
4122 else if(FLUID_STRCMP(name, "synth.reverb.width") == 0)
4124 fluid_synth_set_reverb_width(synth, value);
4126 else if(FLUID_STRCMP(name, "synth.reverb.level") == 0)
4128 fluid_synth_set_reverb_level(synth, value);
4130 else if(FLUID_STRCMP(name, "synth.chorus.depth") == 0)
4132 fluid_synth_set_chorus_depth(synth, value);
4134 else if(FLUID_STRCMP(name, "synth.chorus.speed") == 0)
4136 fluid_synth_set_chorus_speed(synth, value);
4138 else if(FLUID_STRCMP(name, "synth.chorus.level") == 0)
4140 fluid_synth_set_chorus_level(synth, value);
4145 * Handler for synth.reverb.* and synth.chorus.* integer settings.
4147 static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value)
4149 fluid_synth_t *synth = (fluid_synth_t *)data;
4150 fluid_return_if_fail(synth != NULL);
4152 if(FLUID_STRCMP(name, "synth.reverb.active") == 0)
4154 fluid_synth_set_reverb_on(synth, value);
4156 else if(FLUID_STRCMP(name, "synth.chorus.active") == 0)
4158 fluid_synth_set_chorus_on(synth, value);
4160 else if(FLUID_STRCMP(name, "synth.chorus.nr") == 0)
4162 fluid_synth_set_chorus_nr(synth, value);
4167 * Handler for synth.overflow.* settings.
4169 static void fluid_synth_handle_overflow(void *data, const char *name, double value)
4171 fluid_synth_t *synth = (fluid_synth_t *)data;
4172 fluid_return_if_fail(synth != NULL);
4174 fluid_synth_api_enter(synth);
4176 if(FLUID_STRCMP(name, "synth.overflow.percussion") == 0)
4178 synth->overflow.percussion = value;
4180 else if(FLUID_STRCMP(name, "synth.overflow.released") == 0)
4182 synth->overflow.released = value;
4184 else if(FLUID_STRCMP(name, "synth.overflow.sustained") == 0)
4186 synth->overflow.sustained = value;
4188 else if(FLUID_STRCMP(name, "synth.overflow.volume") == 0)
4190 synth->overflow.volume = value;
4192 else if(FLUID_STRCMP(name, "synth.overflow.age") == 0)
4194 synth->overflow.age = value;
4196 else if(FLUID_STRCMP(name, "synth.overflow.important") == 0)
4198 synth->overflow.important = value;
4201 fluid_synth_api_exit(synth);
4204 /* Selects a voice for killing. */
4205 static fluid_voice_t *
4206 fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth)
4209 float best_prio = OVERFLOW_PRIO_CANNOT_KILL - 1;
4210 float this_voice_prio;
4211 fluid_voice_t *voice;
4212 int best_voice_index = -1;
4213 unsigned int ticks = fluid_synth_get_ticks(synth);
4215 for(i = 0; i < synth->polyphony; i++)
4218 voice = synth->voice[i];
4220 /* safeguard against an available voice. */
4221 if(_AVAILABLE(voice))
4226 this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow,
4229 /* check if this voice has less priority than the previous candidate. */
4230 if(this_voice_prio < best_prio)
4232 best_voice_index = i;
4233 best_prio = this_voice_prio;
4237 if(best_voice_index < 0)
4242 voice = synth->voice[best_voice_index];
4243 FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ",
4244 fluid_voice_get_id(voice), best_voice_index, fluid_voice_get_channel(voice), fluid_voice_get_key(voice));
4245 fluid_voice_off(voice);
4252 * Allocate a synthesis voice.
4253 * @param synth FluidSynth instance
4254 * @param sample Sample to assign to the voice
4255 * @param chan MIDI channel number (0 to MIDI channel count - 1)
4256 * @param key MIDI note number for the voice (0-127)
4257 * @param vel MIDI velocity for the voice (0-127)
4258 * @return Allocated synthesis voice or NULL on error
4260 * This function is called by a SoundFont's preset in response to a noteon event.
4261 * The returned voice comes with default modulators and generators.
4262 * A single noteon event may create any number of voices, when the preset is layered.
4264 * @note Should only be called from within synthesis thread, which includes
4265 * SoundFont loader preset noteon method.
4268 fluid_synth_alloc_voice(fluid_synth_t *synth, fluid_sample_t *sample,
4269 int chan, int key, int vel)
4271 fluid_return_val_if_fail(sample != NULL, NULL);
4272 FLUID_API_ENTRY_CHAN(NULL);
4273 FLUID_API_RETURN(fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, NULL));
4278 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)
4281 fluid_voice_t *voice = NULL;
4282 fluid_channel_t *channel = NULL;
4285 /* check if there's an available synthesis process */
4286 for(i = 0; i < synth->polyphony; i++)
4288 if(_AVAILABLE(synth->voice[i]))
4290 voice = synth->voice[i];
4295 /* No success yet? Then stop a running voice. */
4298 FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice");
4299 voice = fluid_synth_free_voice_by_kill_LOCAL(synth);
4304 FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
4308 ticks = fluid_synth_get_ticks(synth);
4314 for(i = 0; i < synth->polyphony; i++)
4316 if(!_AVAILABLE(synth->voice[i]))
4322 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
4323 chan, key, vel, synth->storeid,
4324 (float) ticks / 44100.0f,
4325 (fluid_curtime() - synth->start) / 1000.0f,
4330 channel = synth->channel[chan];
4332 if(fluid_voice_init(voice, sample, zone_range, channel, key, vel,
4333 synth->storeid, ticks, synth->gain) != FLUID_OK)
4335 FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
4339 /* add the default modulators to the synthesis process. */
4340 /* custom_breath2att_modulator is not a default modulator specified in SF
4341 it is intended to replace default_vel2att_mod for this channel on demand using
4342 API fluid_synth_set_breath_mode() or shell command setbreathmode for this channel.
4345 int mono = fluid_channel_is_playing_mono(channel);
4346 fluid_mod_t *default_mod = synth->default_mod;
4348 while(default_mod != NULL)
4351 /* See if default_mod is the velocity_to_attenuation modulator */
4352 fluid_mod_test_identity(default_mod, &default_vel2att_mod) &&
4353 // See if a replacement by custom_breath2att_modulator has been demanded
4355 ((!mono && (channel->mode & FLUID_CHANNEL_BREATH_POLY)) ||
4356 (mono && (channel->mode & FLUID_CHANNEL_BREATH_MONO)))
4359 // Replacement of default_vel2att modulator by custom_breath2att_modulator
4360 fluid_voice_add_mod_local(voice, &custom_breath2att_mod, FLUID_VOICE_DEFAULT, 0);
4364 fluid_voice_add_mod_local(voice, default_mod, FLUID_VOICE_DEFAULT, 0);
4367 // Next default modulator to add to the voice
4368 default_mod = default_mod->next;
4375 /* Kill all voices on a given channel, which have the same exclusive class
4376 * generator as new_voice.
4379 fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
4380 fluid_voice_t *new_voice)
4382 int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS);
4385 /* Excl. class 0: No exclusive class */
4391 /* Kill all notes on the same channel with the same exclusive class */
4392 for(i = 0; i < synth->polyphony; i++)
4394 fluid_voice_t *existing_voice = synth->voice[i];
4395 int existing_excl_class = fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS);
4397 /* If voice is playing, on the same channel, has same exclusive
4398 * class and is not part of the same noteon event (voice group), then kill it */
4400 if(fluid_voice_is_playing(existing_voice)
4401 && fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice)
4402 && existing_excl_class == excl_class
4403 && fluid_voice_get_id(existing_voice) != fluid_voice_get_id(new_voice))
4405 fluid_voice_kill_excl(existing_voice);
4411 * Activate a voice previously allocated with fluid_synth_alloc_voice().
4412 * @param synth FluidSynth instance
4413 * @param voice Voice to activate
4415 * This function is called by a SoundFont's preset in response to a noteon
4416 * event. Exclusive classes are processed here.
4418 * @note Should only be called from within synthesis thread, which includes
4419 * SoundFont loader preset noteon method.
4422 fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice)
4424 fluid_return_if_fail(synth != NULL);
4425 fluid_return_if_fail(voice != NULL);
4426 // fluid_return_if_fail (fluid_synth_is_synth_thread (synth));
4427 fluid_synth_api_enter(synth);
4429 /* Find the exclusive class of this voice. If set, kill all voices
4430 * that match the exclusive class and are younger than the first
4431 * voice process created by this noteon event. */
4432 fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice);
4434 fluid_voice_start(voice); /* Start the new voice */
4435 fluid_voice_lock_rvoice(voice);
4436 fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice);
4437 fluid_synth_api_exit(synth);
4441 * Add a SoundFont loader to the synth. This function takes ownership of \c loader
4442 * and frees it automatically upon \c synth destruction.
4443 * @param synth FluidSynth instance
4444 * @param loader Loader API structure
4446 * SoundFont loaders are used to add custom instrument loading to FluidSynth.
4447 * The caller supplied functions for loading files, allocating presets,
4448 * retrieving information on them and synthesizing note-on events. Using this
4449 * method even non SoundFont instruments can be synthesized, although limited
4450 * to the SoundFont synthesis model.
4452 * @note Should only be called before any SoundFont files are loaded.
4455 fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader)
4457 fluid_return_if_fail(synth != NULL);
4458 fluid_return_if_fail(loader != NULL);
4459 fluid_synth_api_enter(synth);
4461 /* Test if sfont is already loaded */
4462 if(synth->sfont == NULL)
4464 synth->loaders = fluid_list_prepend(synth->loaders, loader);
4467 fluid_synth_api_exit(synth);
4471 * Load a SoundFont file (filename is interpreted by SoundFont loaders).
4472 * The newly loaded SoundFont will be put on top of the SoundFont
4473 * stack. Presets are searched starting from the SoundFont on the
4474 * top of the stack, working the way down the stack until a preset is found.
4476 * @param synth FluidSynth instance
4477 * @param filename File to load
4478 * @param reset_presets TRUE to re-assign presets for all MIDI channels (equivalent to calling fluid_synth_program_reset())
4479 * @return SoundFont ID on success, #FLUID_FAILED on error
4482 fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets)
4484 fluid_sfont_t *sfont;
4486 fluid_sfloader_t *loader;
4489 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4490 fluid_return_val_if_fail(filename != NULL, FLUID_FAILED);
4491 fluid_synth_api_enter(synth);
4493 sfont_id = synth->sfont_id;
4495 if(++sfont_id != FLUID_FAILED)
4497 /* MT NOTE: Loaders list should not change. */
4499 for(list = synth->loaders; list; list = fluid_list_next(list))
4501 loader = (fluid_sfloader_t *) fluid_list_get(list);
4503 sfont = fluid_sfloader_load(loader, filename);
4508 synth->sfont_id = sfont->id = sfont_id;
4510 synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
4512 /* reset the presets for all channels if requested */
4515 fluid_synth_program_reset(synth);
4518 FLUID_API_RETURN(sfont_id);
4523 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
4524 FLUID_API_RETURN(FLUID_FAILED);
4528 * Unload a SoundFont.
4529 * @param synth FluidSynth instance
4530 * @param id ID of SoundFont to unload
4531 * @param reset_presets TRUE to re-assign presets for all MIDI channels
4532 * @return #FLUID_OK on success, #FLUID_FAILED on error
4535 fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets)
4537 fluid_sfont_t *sfont = NULL;
4540 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4541 fluid_synth_api_enter(synth);
4543 /* remove the SoundFont from the list */
4544 for(list = synth->sfont; list; list = fluid_list_next(list))
4546 sfont = fluid_list_get(list);
4548 if(fluid_sfont_get_id(sfont) == id)
4550 synth->sfont = fluid_list_remove(synth->sfont, sfont);
4557 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
4558 FLUID_API_RETURN(FLUID_FAILED);
4561 /* reset the presets for all channels (SoundFont will be freed when there are no more references) */
4564 fluid_synth_program_reset(synth);
4568 fluid_synth_update_presets(synth);
4571 /* -- Remove synth->sfont list's reference to SoundFont */
4572 fluid_synth_sfont_unref(synth, sfont);
4574 FLUID_API_RETURN(FLUID_OK);
4577 /* Unref a SoundFont and destroy if no more references */
4579 fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont)
4581 fluid_return_if_fail(sfont != NULL); /* Shouldn't happen, programming error if so */
4583 sfont->refcount--; /* -- Remove the sfont list's reference */
4585 if(sfont->refcount == 0) /* No more references? - Attempt delete */
4587 if(fluid_sfont_delete_internal(sfont) == 0) /* SoundFont loader can block SoundFont unload */
4589 FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
4590 } /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */
4593 new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, TRUE, TRUE, FALSE);
4598 /* Callback to continually attempt to unload a SoundFont,
4599 * only if a SoundFont loader blocked the unload operation */
4601 fluid_synth_sfunload_callback(void *data, unsigned int msec)
4603 fluid_sfont_t *sfont = data;
4605 if(fluid_sfont_delete_internal(sfont) == 0)
4607 FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
4617 * Reload a SoundFont. The SoundFont retains its ID and index on the SoundFont stack.
4618 * @param synth FluidSynth instance
4619 * @param id ID of SoundFont to reload
4620 * @return SoundFont ID on success, #FLUID_FAILED on error
4623 fluid_synth_sfreload(fluid_synth_t *synth, int id)
4625 char *filename = NULL;
4626 fluid_sfont_t *sfont;
4627 fluid_sfloader_t *loader;
4629 int index, ret = FLUID_FAILED;
4631 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4632 fluid_synth_api_enter(synth);
4634 /* Search for SoundFont and get its index */
4635 for(list = synth->sfont, index = 0; list; list = fluid_list_next(list), index++)
4637 sfont = fluid_list_get(list);
4639 if(fluid_sfont_get_id(sfont) == id)
4647 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
4651 /* keep a copy of the SoundFont's filename */
4652 filename = FLUID_STRDUP(fluid_sfont_get_name(sfont));
4654 if(filename == NULL || fluid_synth_sfunload(synth, id, FALSE) != FLUID_OK)
4659 /* MT Note: SoundFont loader list will not change */
4661 for(list = synth->loaders; list; list = fluid_list_next(list))
4663 loader = (fluid_sfloader_t *) fluid_list_get(list);
4665 sfont = fluid_sfloader_load(loader, filename);
4672 synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont); /* insert the sfont at the same index */
4674 /* reset the presets for all channels */
4675 fluid_synth_update_presets(synth);
4681 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
4684 FLUID_FREE(filename);
4685 FLUID_API_RETURN(ret);
4689 * Add a SoundFont. The SoundFont will be added to the top of the SoundFont stack.
4690 * @param synth FluidSynth instance
4691 * @param sfont SoundFont to add
4692 * @return New assigned SoundFont ID or #FLUID_FAILED on error
4695 fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
4699 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4700 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
4701 fluid_synth_api_enter(synth);
4703 sfont_id = synth->sfont_id;
4705 if(++sfont_id != FLUID_FAILED)
4707 synth->sfont_id = sfont->id = sfont_id;
4708 synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
4710 /* reset the presets for all channels */
4711 fluid_synth_program_reset(synth);
4714 FLUID_API_RETURN(sfont_id);
4718 * Remove a SoundFont from the SoundFont stack without deleting it.
4719 * @param synth FluidSynth instance
4720 * @param sfont SoundFont to remove
4721 * @return #FLUID_OK if \c sfont successfully removed, #FLUID_FAILED otherwise
4723 * SoundFont is not freed and is left as the responsibility of the caller.
4725 * @note The SoundFont should only be freed after there are no presets
4726 * referencing it. This can only be ensured by the SoundFont loader and
4727 * therefore this function should not normally be used.
4730 fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
4732 fluid_sfont_t *sfont_tmp;
4734 int ret = FLUID_FAILED;
4736 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4737 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
4738 fluid_synth_api_enter(synth);
4740 /* remove the SoundFont from the list */
4741 for(list = synth->sfont; list; list = fluid_list_next(list))
4743 sfont_tmp = fluid_list_get(list);
4745 if(sfont_tmp == sfont)
4747 synth->sfont = fluid_list_remove(synth->sfont, sfont_tmp);
4753 /* reset the presets for all channels */
4754 fluid_synth_program_reset(synth);
4756 FLUID_API_RETURN(ret);
4760 * Count number of loaded SoundFont files.
4761 * @param synth FluidSynth instance
4762 * @return Count of loaded SoundFont files.
4765 fluid_synth_sfcount(fluid_synth_t *synth)
4769 fluid_return_val_if_fail(synth != NULL, 0);
4770 fluid_synth_api_enter(synth);
4771 count = fluid_list_size(synth->sfont);
4772 FLUID_API_RETURN(count);
4776 * Get SoundFont by index.
4777 * @param synth FluidSynth instance
4778 * @param num SoundFont index on the stack (starting from 0 for top of stack).
4779 * @return SoundFont instance or NULL if invalid index
4781 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4782 * the duration of use of the returned pointer.
4785 fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num)
4787 fluid_sfont_t *sfont = NULL;
4790 fluid_return_val_if_fail(synth != NULL, NULL);
4791 fluid_synth_api_enter(synth);
4792 list = fluid_list_nth(synth->sfont, num);
4796 sfont = fluid_list_get(list);
4799 FLUID_API_RETURN(sfont);
4803 * Get SoundFont by ID.
4804 * @param synth FluidSynth instance
4805 * @param id SoundFont ID
4806 * @return SoundFont instance or NULL if invalid ID
4808 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4809 * the duration of use of the returned pointer.
4812 fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id)
4814 fluid_sfont_t *sfont = NULL;
4817 fluid_return_val_if_fail(synth != NULL, NULL);
4818 fluid_synth_api_enter(synth);
4820 for(list = synth->sfont; list; list = fluid_list_next(list))
4822 sfont = fluid_list_get(list);
4824 if(fluid_sfont_get_id(sfont) == id)
4830 FLUID_API_RETURN(list ? sfont : NULL);
4834 * Get SoundFont by name.
4835 * @param synth FluidSynth instance
4836 * @param name Name of SoundFont
4837 * @return SoundFont instance or NULL if invalid name
4840 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4841 * the duration of use of the returned pointer.
4844 fluid_synth_get_sfont_by_name(fluid_synth_t *synth, const char *name)
4846 fluid_sfont_t *sfont = NULL;
4849 fluid_return_val_if_fail(synth != NULL, NULL);
4850 fluid_return_val_if_fail(name != NULL, NULL);
4851 fluid_synth_api_enter(synth);
4853 for(list = synth->sfont; list; list = fluid_list_next(list))
4855 sfont = fluid_list_get(list);
4857 if(FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0)
4863 FLUID_API_RETURN(list ? sfont : NULL);
4867 * Get active preset on a MIDI channel.
4868 * @param synth FluidSynth instance
4869 * @param chan MIDI channel number (0 to MIDI channel count - 1)
4870 * @return Preset or NULL if no preset active on \c chan
4872 * @note Should only be called from within synthesis thread, which includes
4873 * SoundFont loader preset noteon methods. Not thread safe otherwise.
4876 fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan)
4878 fluid_preset_t *result;
4879 fluid_channel_t *channel;
4880 FLUID_API_ENTRY_CHAN(NULL);
4882 channel = synth->channel[chan];
4883 result = channel->preset;
4884 fluid_synth_api_exit(synth);
4889 * Get list of currently playing voices.
4890 * @param synth FluidSynth instance
4891 * @param buf Array to store voices to (NULL terminated if not filled completely)
4892 * @param bufsize Count of indexes in buf
4893 * @param id Voice ID to search for or < 0 to return list of all playing voices
4895 * @note Should only be called from within synthesis thread, which includes
4896 * SoundFont loader preset noteon methods. Voices are only guaranteed to remain
4897 * unchanged until next synthesis process iteration.
4900 fluid_synth_get_voicelist(fluid_synth_t *synth, fluid_voice_t *buf[], int bufsize,
4906 fluid_return_if_fail(synth != NULL);
4907 fluid_return_if_fail(buf != NULL);
4908 fluid_synth_api_enter(synth);
4910 for(i = 0; i < synth->polyphony && count < bufsize; i++)
4912 fluid_voice_t *voice = synth->voice[i];
4914 if(fluid_voice_is_playing(voice) && (id < 0 || (int)voice->id == id))
4916 buf[count++] = voice;
4925 fluid_synth_api_exit(synth);
4929 * Enable or disable reverb effect.
4930 * @param synth FluidSynth instance
4931 * @param on TRUE to enable reverb, FALSE to disable
4934 fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
4936 fluid_return_if_fail(synth != NULL);
4938 fluid_synth_api_enter(synth);
4940 synth->with_reverb = (on != 0);
4941 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled,
4943 fluid_synth_api_exit(synth);
4947 * Activate a reverb preset.
4948 * @param synth FluidSynth instance
4949 * @param num Reverb preset number
4950 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4952 * @note Currently private to libfluidsynth.
4955 fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
4957 fluid_return_val_if_fail(
4958 num < FLUID_N_ELEMENTS(revmodel_preset),
4962 fluid_synth_set_reverb(synth, revmodel_preset[num].roomsize,
4963 revmodel_preset[num].damp, revmodel_preset[num].width,
4964 revmodel_preset[num].level);
4969 * Set reverb parameters.
4970 * @param synth FluidSynth instance
4971 * @param roomsize Reverb room size value (0.0-1.0)
4972 * @param damping Reverb damping value (0.0-1.0)
4973 * @param width Reverb width value (0.0-100.0)
4974 * @param level Reverb level value (0.0-1.0)
4975 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4977 * @note Not realtime safe and therefore should not be called from synthesis
4978 * context at the risk of stalling audio output.
4981 fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping,
4982 double width, double level)
4984 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ALL,
4985 roomsize, damping, width, level);
4989 * Set reverb roomsize. See fluid_synth_set_reverb() for further info.
4990 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4992 int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
4994 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ROOMSIZE, roomsize, 0, 0, 0);
4998 * Set reverb damping. See fluid_synth_set_reverb() for further info.
4999 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5001 int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
5003 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_DAMPING, 0, damping, 0, 0);
5007 * Set reverb width. See fluid_synth_set_reverb() for further info.
5008 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5010 int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
5012 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_WIDTH, 0, 0, width, 0);
5016 * Set reverb level. See fluid_synth_set_reverb() for further info.
5017 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5019 int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
5021 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_LEVEL, 0, 0, 0, level);
5025 * Set one or more reverb parameters.
5026 * @param synth FluidSynth instance
5027 * @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
5028 * @param roomsize Reverb room size value (0.0-1.2)
5029 * @param damping Reverb damping value (0.0-1.0)
5030 * @param width Reverb width value (0.0-100.0)
5031 * @param level Reverb level value (0.0-1.0)
5032 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5034 * @note Not realtime safe and therefore should not be called from synthesis
5035 * context at the risk of stalling audio output.
5038 fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize,
5039 double damping, double width, double level)
5043 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5044 /* if non of the flags is set, fail */
5045 fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
5047 /* Synth shadow values are set here so that they will be returned if querried */
5049 fluid_synth_api_enter(synth);
5050 ret = fluid_synth_set_reverb_full_LOCAL(synth, set, roomsize, damping, width, level);
5051 FLUID_API_RETURN(ret);
5055 fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize,
5056 double damping, double width, double level)
5059 fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5061 if(set & FLUID_REVMODEL_SET_ROOMSIZE)
5063 synth->reverb_roomsize = roomsize;
5066 if(set & FLUID_REVMODEL_SET_DAMPING)
5068 synth->reverb_damping = damping;
5071 if(set & FLUID_REVMODEL_SET_WIDTH)
5073 synth->reverb_width = width;
5076 if(set & FLUID_REVMODEL_SET_LEVEL)
5078 synth->reverb_level = level;
5082 param[1].real = roomsize;
5083 param[2].real = damping;
5084 param[3].real = width;
5085 param[4].real = level;
5086 /* finally enqueue an rvoice event to the mixer to actual update reverb */
5087 ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5088 fluid_rvoice_mixer_set_reverb_params,
5089 synth->eventhandler->mixer,
5095 * Get reverb room size.
5096 * @param synth FluidSynth instance
5097 * @return Reverb room size (0.0-1.2)
5100 fluid_synth_get_reverb_roomsize(fluid_synth_t *synth)
5103 fluid_return_val_if_fail(synth != NULL, 0.0);
5104 fluid_synth_api_enter(synth);
5105 result = synth->reverb_roomsize;
5106 FLUID_API_RETURN(result);
5110 * Get reverb damping.
5111 * @param synth FluidSynth instance
5112 * @return Reverb damping value (0.0-1.0)
5115 fluid_synth_get_reverb_damp(fluid_synth_t *synth)
5118 fluid_return_val_if_fail(synth != NULL, 0.0);
5119 fluid_synth_api_enter(synth);
5121 result = synth->reverb_damping;
5122 FLUID_API_RETURN(result);
5127 * @param synth FluidSynth instance
5128 * @return Reverb level value (0.0-1.0)
5131 fluid_synth_get_reverb_level(fluid_synth_t *synth)
5134 fluid_return_val_if_fail(synth != NULL, 0.0);
5135 fluid_synth_api_enter(synth);
5137 result = synth->reverb_level;
5138 FLUID_API_RETURN(result);
5143 * @param synth FluidSynth instance
5144 * @return Reverb width value (0.0-100.0)
5147 fluid_synth_get_reverb_width(fluid_synth_t *synth)
5150 fluid_return_val_if_fail(synth != NULL, 0.0);
5151 fluid_synth_api_enter(synth);
5153 result = synth->reverb_width;
5154 FLUID_API_RETURN(result);
5158 * Enable or disable chorus effect.
5159 * @param synth FluidSynth instance
5160 * @param on TRUE to enable chorus, FALSE to disable
5163 fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
5165 fluid_return_if_fail(synth != NULL);
5166 fluid_synth_api_enter(synth);
5168 synth->with_chorus = (on != 0);
5169 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled,
5171 fluid_synth_api_exit(synth);
5175 * Set chorus parameters. It should be turned on with fluid_synth_set_chorus_on().
5176 * Keep in mind, that the needed CPU time is proportional to 'nr'.
5177 * @param synth FluidSynth instance
5178 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
5180 * @param level Chorus level (0.0-10.0)
5181 * @param speed Chorus speed in Hz (0.29-5.0)
5182 * @param depth_ms Chorus depth (max value depends on synth sample rate,
5183 * 0.0-21.0 is safe for sample rate values up to 96KHz)
5184 * @param type Chorus waveform type (#fluid_chorus_mod)
5185 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5187 int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
5188 double speed, double depth_ms, int type)
5190 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_ALL, nr, level, speed,
5195 * Set the chorus voice count. See fluid_synth_set_chorus() for further info.
5196 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5198 int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
5200 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_NR, nr, 0, 0, 0, 0);
5204 * Set the chorus level. See fluid_synth_set_chorus() for further info.
5205 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5207 int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
5209 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_LEVEL, 0, level, 0, 0, 0);
5213 * Set the chorus speed. See fluid_synth_set_chorus() for further info.
5214 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5216 int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
5218 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_SPEED, 0, 0, speed, 0, 0);
5222 * Set the chorus depth. See fluid_synth_set_chorus() for further info.
5223 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5225 int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
5227 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_DEPTH, 0, 0, 0, depth_ms, 0);
5231 * Set the chorus type. See fluid_synth_set_chorus() for further info.
5232 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5234 int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
5236 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_TYPE, 0, 0, 0, 0, type);
5240 * Set one or more chorus parameters.
5241 * @param synth FluidSynth instance
5242 * @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t)
5243 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
5245 * @param level Chorus level (0.0-10.0)
5246 * @param speed Chorus speed in Hz (0.29-5.0)
5247 * @param depth_ms Chorus depth (max value depends on synth sample rate,
5248 * 0.0-21.0 is safe for sample rate values up to 96KHz)
5249 * @param type Chorus waveform type (#fluid_chorus_mod)
5250 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5253 fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level,
5254 double speed, double depth_ms, int type)
5258 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5259 /* if non of the flags is set, fail */
5260 fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
5262 /* Synth shadow values are set here so that they will be returned if queried */
5263 fluid_synth_api_enter(synth);
5265 ret = fluid_synth_set_chorus_full_LOCAL(synth, set, nr, level, speed, depth_ms, type);
5267 FLUID_API_RETURN(ret);
5271 fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level,
5272 double speed, double depth_ms, int type)
5275 fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5277 if(set & FLUID_CHORUS_SET_NR)
5279 synth->chorus_nr = nr;
5282 if(set & FLUID_CHORUS_SET_LEVEL)
5284 synth->chorus_level = level;
5287 if(set & FLUID_CHORUS_SET_SPEED)
5289 synth->chorus_speed = speed;
5292 if(set & FLUID_CHORUS_SET_DEPTH)
5294 synth->chorus_depth = depth_ms;
5297 if(set & FLUID_CHORUS_SET_TYPE)
5299 synth->chorus_type = type;
5304 param[2].real = level;
5305 param[3].real = speed;
5306 param[4].real = depth_ms;
5308 ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5309 fluid_rvoice_mixer_set_chorus_params,
5310 synth->eventhandler->mixer,
5317 * Get chorus voice number (delay line count) value.
5318 * @param synth FluidSynth instance
5319 * @return Chorus voice count (0-99)
5322 fluid_synth_get_chorus_nr(fluid_synth_t *synth)
5325 fluid_return_val_if_fail(synth != NULL, 0.0);
5326 fluid_synth_api_enter(synth);
5328 result = synth->chorus_nr;
5329 FLUID_API_RETURN(result);
5334 * @param synth FluidSynth instance
5335 * @return Chorus level value (0.0-10.0)
5338 fluid_synth_get_chorus_level(fluid_synth_t *synth)
5341 fluid_return_val_if_fail(synth != NULL, 0.0);
5342 fluid_synth_api_enter(synth);
5344 result = synth->chorus_level;
5345 FLUID_API_RETURN(result);
5349 * Get chorus speed in Hz.
5350 * @param synth FluidSynth instance
5351 * @return Chorus speed in Hz (0.29-5.0)
5354 fluid_synth_get_chorus_speed(fluid_synth_t *synth)
5357 fluid_return_val_if_fail(synth != NULL, 0.0);
5358 fluid_synth_api_enter(synth);
5360 result = synth->chorus_speed;
5361 FLUID_API_RETURN(result);
5366 * @param synth FluidSynth instance
5367 * @return Chorus depth
5370 fluid_synth_get_chorus_depth(fluid_synth_t *synth)
5373 fluid_return_val_if_fail(synth != NULL, 0.0);
5374 fluid_synth_api_enter(synth);
5376 result = synth->chorus_depth;
5377 FLUID_API_RETURN(result);
5381 * Get chorus waveform type.
5382 * @param synth FluidSynth instance
5383 * @return Chorus waveform type (#fluid_chorus_mod)
5386 fluid_synth_get_chorus_type(fluid_synth_t *synth)
5389 fluid_return_val_if_fail(synth != NULL, 0.0);
5390 fluid_synth_api_enter(synth);
5392 result = synth->chorus_type;
5393 FLUID_API_RETURN(result);
5397 * If the same note is hit twice on the same channel, then the older
5398 * voice process is advanced to the release stage. Using a mechanical
5399 * MIDI controller, the only way this can happen is when the sustain
5400 * pedal is held. In this case the behaviour implemented here is
5401 * natural for many instruments. Note: One noteon event can trigger
5402 * several voice processes, for example a stereo sample. Don't
5406 fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan,
5410 fluid_voice_t *voice;
5412 /* storeid is a parameter for fluid_voice_init() */
5413 synth->storeid = synth->noteid++;
5415 /* for "monophonic playing" key is the previous sustained note
5416 if it exists (0 to 127) or INVALID_NOTE otherwise */
5417 if(key == INVALID_NOTE)
5422 for(i = 0; i < synth->polyphony; i++)
5424 voice = synth->voice[i];
5426 if(fluid_voice_is_playing(voice)
5427 && (fluid_voice_get_channel(voice) == chan)
5428 && (fluid_voice_get_key(voice) == key)
5429 && (fluid_voice_get_id(voice) != synth->noteid))
5431 /* Id of voices that was sustained by sostenuto */
5432 if(fluid_voice_is_sostenuto(voice))
5434 synth->storeid = fluid_voice_get_id(voice);
5437 /* Force the voice into release stage (pedaling is ignored) */
5438 fluid_voice_release(voice);
5444 * Set synthesis interpolation method on one or all MIDI channels.
5445 * @param synth FluidSynth instance
5446 * @param chan MIDI channel to set interpolation method on or -1 for all channels
5447 * @param interp_method Interpolation method (#fluid_interp)
5448 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5451 fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method)
5455 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5456 fluid_synth_api_enter(synth);
5458 if(chan < -1 || chan >= synth->midi_channels)
5460 FLUID_API_RETURN(FLUID_FAILED);
5463 if(synth->channel[0] == NULL)
5465 FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!");
5466 FLUID_API_RETURN(FLUID_FAILED);
5469 for(i = 0; i < synth->midi_channels; i++)
5471 if(chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan)
5473 fluid_channel_set_interp_method(synth->channel[i], interp_method);
5477 FLUID_API_RETURN(FLUID_OK);
5481 * Get the total count of MIDI channels.
5482 * @param synth FluidSynth instance
5483 * @return Count of MIDI channels
5486 fluid_synth_count_midi_channels(fluid_synth_t *synth)
5489 fluid_return_val_if_fail(synth != NULL, 0);
5490 fluid_synth_api_enter(synth);
5492 result = synth->midi_channels;
5493 FLUID_API_RETURN(result);
5497 * Get the total count of audio channels.
5498 * @param synth FluidSynth instance
5499 * @return Count of audio channel stereo pairs (1 = 2 channels, 2 = 4, etc)
5502 fluid_synth_count_audio_channels(fluid_synth_t *synth)
5505 fluid_return_val_if_fail(synth != NULL, 0);
5506 fluid_synth_api_enter(synth);
5508 result = synth->audio_channels;
5509 FLUID_API_RETURN(result);
5513 * Get the total number of allocated audio channels. Usually identical to the
5514 * number of audio channels. Can be employed by LADSPA effects subsystem.
5516 * @param synth FluidSynth instance
5517 * @return Count of audio group stereo pairs (1 = 2 channels, 2 = 4, etc)
5520 fluid_synth_count_audio_groups(fluid_synth_t *synth)
5523 fluid_return_val_if_fail(synth != NULL, 0);
5524 fluid_synth_api_enter(synth);
5526 result = synth->audio_groups;
5527 FLUID_API_RETURN(result);
5531 * Get the total number of allocated effects channels.
5532 * @param synth FluidSynth instance
5533 * @return Count of allocated effects channels
5536 fluid_synth_count_effects_channels(fluid_synth_t *synth)
5539 fluid_return_val_if_fail(synth != NULL, 0);
5540 fluid_synth_api_enter(synth);
5542 result = synth->effects_channels;
5543 FLUID_API_RETURN(result);
5547 * Get the total number of allocated effects units.
5548 * @param synth FluidSynth instance
5549 * @return Count of allocated effects units
5552 fluid_synth_count_effects_groups(fluid_synth_t *synth)
5555 fluid_return_val_if_fail(synth != NULL, 0);
5556 fluid_synth_api_enter(synth);
5558 result = synth->effects_groups;
5559 FLUID_API_RETURN(result);
5563 * Get the synth CPU load value.
5564 * @param synth FluidSynth instance
5565 * @return Estimated CPU load value in percent (0-100)
5568 fluid_synth_get_cpu_load(fluid_synth_t *synth)
5570 fluid_return_val_if_fail(synth != NULL, 0);
5571 return fluid_atomic_float_get(&synth->cpu_load);
5574 /* Get tuning for a given bank:program */
5575 static fluid_tuning_t *
5576 fluid_synth_get_tuning(fluid_synth_t *synth, int bank, int prog)
5579 if((synth->tuning == NULL) ||
5580 (synth->tuning[bank] == NULL) ||
5581 (synth->tuning[bank][prog] == NULL))
5586 return synth->tuning[bank][prog];
5589 /* Replace tuning on a given bank:program (need not already exist).
5590 * Synth mutex should already be locked by caller. */
5592 fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth, fluid_tuning_t *tuning,
5593 int bank, int prog, int apply)
5595 fluid_tuning_t *old_tuning;
5597 if(synth->tuning == NULL)
5599 synth->tuning = FLUID_ARRAY(fluid_tuning_t **, 128);
5601 if(synth->tuning == NULL)
5603 FLUID_LOG(FLUID_PANIC, "Out of memory");
5604 return FLUID_FAILED;
5607 FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t **));
5610 if(synth->tuning[bank] == NULL)
5612 synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t *, 128);
5614 if(synth->tuning[bank] == NULL)
5616 FLUID_LOG(FLUID_PANIC, "Out of memory");
5617 return FLUID_FAILED;
5620 FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t *));
5623 old_tuning = synth->tuning[bank][prog];
5624 synth->tuning[bank][prog] = tuning;
5628 if(!fluid_tuning_unref(old_tuning, 1)) /* -- unref old tuning */
5630 /* Replace old tuning if present */
5631 fluid_synth_replace_tuning_LOCAL(synth, old_tuning, tuning, apply, FALSE);
5638 /* Replace a tuning with a new one in all MIDI channels. new_tuning can be
5639 * NULL, in which case channels are reset to default equal tempered scale. */
5641 fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth, fluid_tuning_t *old_tuning,
5642 fluid_tuning_t *new_tuning, int apply, int unref_new)
5644 fluid_channel_t *channel;
5645 int old_tuning_unref = 0;
5648 for(i = 0; i < synth->midi_channels; i++)
5650 channel = synth->channel[i];
5652 if(fluid_channel_get_tuning(channel) == old_tuning)
5658 fluid_tuning_ref(new_tuning); /* ++ ref new tuning for channel */
5661 fluid_channel_set_tuning(channel, new_tuning);
5665 fluid_synth_update_voice_tuning_LOCAL(synth, channel);
5670 /* Send unref old tuning event if any unrefs */
5671 if(old_tuning && old_tuning_unref)
5673 fluid_tuning_unref(old_tuning, old_tuning_unref);
5676 if(!unref_new || !new_tuning)
5681 fluid_tuning_unref(new_tuning, 1);
5684 /* Update voice tunings in realtime */
5686 fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth, fluid_channel_t *channel)
5688 fluid_voice_t *voice;
5691 for(i = 0; i < synth->polyphony; i++)
5693 voice = synth->voice[i];
5695 if(fluid_voice_is_on(voice) && (voice->channel == channel))
5697 fluid_voice_calculate_gen_pitch(voice);
5698 fluid_voice_update_param(voice, GEN_PITCH);
5704 * Set the tuning of the entire MIDI note scale.
5705 * @param synth FluidSynth instance
5706 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5707 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5708 * @param name Label name for this tuning
5709 * @param pitch Array of pitch values (length of 128, each value is number of
5710 * cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
5711 * Pass NULL to create a equal tempered (normal) scale.
5712 * @param apply TRUE to apply new tuning in realtime to existing notes which
5713 * are using the replaced tuning (if any), FALSE otherwise
5714 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5718 fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog,
5719 const char *name, const double *pitch, int apply)
5721 fluid_tuning_t *tuning;
5722 int retval = FLUID_OK;
5724 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5725 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5726 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5727 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
5729 fluid_synth_api_enter(synth);
5731 tuning = new_fluid_tuning(name, bank, prog);
5737 fluid_tuning_set_all(tuning, pitch);
5740 retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
5742 if(retval == FLUID_FAILED)
5744 fluid_tuning_unref(tuning, 1);
5749 retval = FLUID_FAILED;
5752 FLUID_API_RETURN(retval);
5756 * Activate an octave tuning on every octave in the MIDI note scale.
5757 * @param synth FluidSynth instance
5758 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5759 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5760 * @param name Label name for this tuning
5761 * @param pitch Array of pitch values (length of 12 for each note of an octave
5762 * starting at note C, values are number of offset cents to add to the normal
5764 * @param apply TRUE to apply new tuning in realtime to existing notes which
5765 * are using the replaced tuning (if any), FALSE otherwise
5766 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5770 fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog,
5771 const char *name, const double *pitch, int apply)
5773 fluid_tuning_t *tuning;
5774 int retval = FLUID_OK;
5776 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5777 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5778 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5779 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
5780 fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
5782 fluid_synth_api_enter(synth);
5783 tuning = new_fluid_tuning(name, bank, prog);
5787 fluid_tuning_set_octave(tuning, pitch);
5788 retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
5790 if(retval == FLUID_FAILED)
5792 fluid_tuning_unref(tuning, 1);
5797 retval = FLUID_FAILED;
5800 FLUID_API_RETURN(retval);
5804 * Set tuning values for one or more MIDI notes for an existing tuning.
5805 * @param synth FluidSynth instance
5806 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5807 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5808 * @param len Number of MIDI notes to assign
5809 * @param key Array of MIDI key numbers (length of 'len', values 0-127)
5810 * @param pitch Array of pitch values (length of 'len', values are number of
5811 * cents from MIDI note 0)
5812 * @param apply TRUE to apply tuning change in realtime to existing notes using
5813 * the specified tuning, FALSE otherwise
5814 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5816 * @note Prior to version 1.1.0 it was an error to specify a tuning that didn't
5817 * already exist. Starting with 1.1.0, the default equal tempered scale will be
5818 * used as a basis, if no tuning exists for the given bank and prog.
5821 fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog,
5822 int len, const int *key, const double *pitch, int apply)
5824 fluid_tuning_t *old_tuning, *new_tuning;
5825 int retval = FLUID_OK;
5828 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5829 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5830 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5831 fluid_return_val_if_fail(len > 0, FLUID_FAILED);
5832 fluid_return_val_if_fail(key != NULL, FLUID_FAILED);
5833 fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
5835 fluid_synth_api_enter(synth);
5837 old_tuning = fluid_synth_get_tuning(synth, bank, prog);
5841 new_tuning = fluid_tuning_duplicate(old_tuning);
5845 new_tuning = new_fluid_tuning("Unnamed", bank, prog);
5850 for(i = 0; i < len; i++)
5852 fluid_tuning_set_pitch(new_tuning, key[i], pitch[i]);
5855 retval = fluid_synth_replace_tuning_LOCK(synth, new_tuning, bank, prog, apply);
5857 if(retval == FLUID_FAILED)
5859 fluid_tuning_unref(new_tuning, 1);
5864 retval = FLUID_FAILED;
5867 FLUID_API_RETURN(retval);
5871 * Activate a tuning scale on a MIDI channel.
5872 * @param synth FluidSynth instance
5873 * @param chan MIDI channel number (0 to MIDI channel count - 1)
5874 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5875 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5876 * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
5877 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5880 * @note A default equal tempered scale will be created, if no tuning exists
5881 * on the given bank and prog.
5884 fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog,
5887 fluid_tuning_t *tuning;
5888 int retval = FLUID_OK;
5890 //fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
5891 //fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
5892 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5893 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5895 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5897 tuning = fluid_synth_get_tuning(synth, bank, prog);
5899 /* If no tuning exists, create a new default tuning. We do this, so that
5900 * it can be replaced later, if any changes are made. */
5903 tuning = new_fluid_tuning("Unnamed", bank, prog);
5907 fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, FALSE);
5913 fluid_tuning_ref(tuning); /* ++ ref for outside of lock */
5918 FLUID_API_RETURN(FLUID_FAILED);
5921 fluid_tuning_ref(tuning); /* ++ ref new tuning for following function */
5922 retval = fluid_synth_set_tuning_LOCAL(synth, chan, tuning, apply);
5924 fluid_tuning_unref(tuning, 1); /* -- unref for outside of lock */
5926 FLUID_API_RETURN(retval);
5929 /* Local synthesis thread set tuning function (takes over tuning reference) */
5931 fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
5932 fluid_tuning_t *tuning, int apply)
5934 fluid_tuning_t *old_tuning;
5935 fluid_channel_t *channel;
5937 channel = synth->channel[chan];
5939 old_tuning = fluid_channel_get_tuning(channel);
5940 fluid_channel_set_tuning(channel, tuning); /* !! Takes over callers reference */
5944 fluid_synth_update_voice_tuning_LOCAL(synth, channel);
5947 /* Send unref old tuning event */
5950 fluid_tuning_unref(old_tuning, 1);
5958 * Clear tuning scale on a MIDI channel (use default equal tempered scale).
5959 * @param synth FluidSynth instance
5960 * @param chan MIDI channel number (0 to MIDI channel count - 1)
5961 * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
5962 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5966 fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply)
5968 int retval = FLUID_OK;
5970 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5972 retval = fluid_synth_set_tuning_LOCAL(synth, chan, NULL, apply);
5974 FLUID_API_RETURN(retval);
5978 * Start tuning iteration.
5979 * @param synth FluidSynth instance
5982 fluid_synth_tuning_iteration_start(fluid_synth_t *synth)
5984 fluid_return_if_fail(synth != NULL);
5985 fluid_synth_api_enter(synth);
5986 fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER(0));
5987 fluid_synth_api_exit(synth);
5991 * Advance to next tuning.
5992 * @param synth FluidSynth instance
5993 * @param bank Location to store MIDI bank number of next tuning scale
5994 * @param prog Location to store MIDI program number of next tuning scale
5995 * @return 1 if tuning iteration advanced, 0 if no more tunings
5998 fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog)
6003 fluid_return_val_if_fail(synth != NULL, 0);
6004 fluid_return_val_if_fail(bank != NULL, 0);
6005 fluid_return_val_if_fail(prog != NULL, 0);
6006 fluid_synth_api_enter(synth);
6008 /* Current tuning iteration stored as: bank << 8 | program */
6009 pval = fluid_private_get(synth->tuning_iter);
6010 p = FLUID_POINTER_TO_INT(pval);
6011 b = (p >> 8) & 0xFF;
6016 FLUID_API_RETURN(0);
6019 for(; b < 128; b++, p = 0)
6021 if(synth->tuning[b] == NULL)
6028 if(synth->tuning[b][p] == NULL)
6038 fluid_private_set(synth->tuning_iter,
6039 FLUID_INT_TO_POINTER(b << 8 | (p + 1)));
6043 fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER((b + 1) << 8));
6046 FLUID_API_RETURN(1);
6050 FLUID_API_RETURN(0);
6054 * Get the entire note tuning for a given MIDI bank and program.
6055 * @param synth FluidSynth instance
6056 * @param bank MIDI bank number of tuning
6057 * @param prog MIDI program number of tuning
6058 * @param name Location to store tuning name or NULL to ignore
6059 * @param len Maximum number of chars to store to 'name' (including NULL byte)
6060 * @param pitch Array to store tuning scale to or NULL to ignore (len of 128)
6061 * @return #FLUID_OK if matching tuning was found, #FLUID_FAILED otherwise
6064 fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog,
6065 char *name, int len, double *pitch)
6067 fluid_tuning_t *tuning;
6069 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6070 fluid_synth_api_enter(synth);
6072 tuning = fluid_synth_get_tuning(synth, bank, prog);
6078 FLUID_SNPRINTF(name, len - 1, "%s", fluid_tuning_get_name(tuning));
6079 name[len - 1] = 0; /* make sure the string is null terminated */
6084 FLUID_MEMCPY(pitch, fluid_tuning_get_all(tuning), 128 * sizeof(double));
6088 FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED);
6092 * Get settings assigned to a synth.
6093 * @param synth FluidSynth instance
6094 * @return FluidSynth settings which are assigned to the synth
6097 fluid_synth_get_settings(fluid_synth_t *synth)
6099 fluid_return_val_if_fail(synth != NULL, NULL);
6101 return synth->settings;
6105 * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
6106 * @param synth FluidSynth instance
6107 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6108 * @param param SoundFont generator ID (#fluid_gen_type)
6109 * @param value Offset or absolute generator value to assign to the MIDI channel
6110 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6112 * This function allows for setting all effect parameters in real time on a
6113 * MIDI channel. Setting absolute to non-zero will cause the value to override
6114 * any generator values set in the instruments played on the MIDI channel.
6115 * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
6116 * generator parameters and valid ranges.
6118 int fluid_synth_set_gen(fluid_synth_t *synth, int chan, int param, float value)
6120 fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
6121 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6123 fluid_synth_set_gen_LOCAL(synth, chan, param, value);
6125 FLUID_API_RETURN(FLUID_OK);
6128 /* Synthesis thread local set gen function */
6130 fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, int param, float value)
6132 fluid_voice_t *voice;
6135 fluid_channel_set_gen(synth->channel[chan], param, value);
6137 for(i = 0; i < synth->polyphony; i++)
6139 voice = synth->voice[i];
6141 if(fluid_voice_get_channel(voice) == chan)
6143 fluid_voice_set_param(voice, param, value);
6149 * Get generator value assigned to a MIDI channel.
6150 * @param synth FluidSynth instance
6151 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6152 * @param param SoundFont generator ID (#fluid_gen_type)
6153 * @return Current generator value assigned to MIDI channel
6156 fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param)
6159 fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
6160 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6162 result = fluid_channel_get_gen(synth->channel[chan], param);
6163 FLUID_API_RETURN(result);
6167 * Handle MIDI event from MIDI router, used as a callback function.
6168 * @param data FluidSynth instance
6169 * @param event MIDI event to handle
6170 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6173 fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event)
6175 fluid_synth_t *synth = (fluid_synth_t *) data;
6176 int type = fluid_midi_event_get_type(event);
6177 int chan = fluid_midi_event_get_channel(event);
6182 return fluid_synth_noteon(synth, chan,
6183 fluid_midi_event_get_key(event),
6184 fluid_midi_event_get_velocity(event));
6187 return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event));
6189 case CONTROL_CHANGE:
6190 return fluid_synth_cc(synth, chan,
6191 fluid_midi_event_get_control(event),
6192 fluid_midi_event_get_value(event));
6194 case PROGRAM_CHANGE:
6195 return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
6197 case CHANNEL_PRESSURE:
6198 return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
6201 return fluid_synth_key_pressure(synth, chan,
6202 fluid_midi_event_get_key(event),
6203 fluid_midi_event_get_value(event));
6206 return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));
6208 case MIDI_SYSTEM_RESET:
6209 return fluid_synth_system_reset(synth);
6212 return fluid_synth_sysex(synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE);
6216 case MIDI_SET_TEMPO:
6220 return FLUID_FAILED;
6224 * Create and start voices using a preset and a MIDI note on event.
6225 * @param synth FluidSynth instance
6226 * @param id Voice group ID to use (can be used with fluid_synth_stop()).
6227 * @param preset Preset to synthesize
6228 * @param audio_chan Unused currently, set to 0
6229 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6230 * @param key MIDI note number (0-127)
6231 * @param vel MIDI velocity number (1-127)
6232 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6234 * @note Should only be called from within synthesis thread, which includes
6235 * SoundFont loader preset noteon method.
6238 fluid_synth_start(fluid_synth_t *synth, unsigned int id, fluid_preset_t *preset,
6239 int audio_chan, int chan, int key, int vel)
6242 fluid_return_val_if_fail(preset != NULL, FLUID_FAILED);
6243 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
6244 fluid_return_val_if_fail(vel >= 1 && vel <= 127, FLUID_FAILED);
6245 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6246 synth->storeid = id;
6247 result = fluid_preset_noteon(preset, synth, chan, key, vel);
6248 FLUID_API_RETURN(result);
6252 * Stop notes for a given note event voice ID.
6253 * @param synth FluidSynth instance
6254 * @param id Voice note event ID
6255 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6257 * @note In FluidSynth versions prior to 1.1.0 #FLUID_FAILED would be returned
6258 * if no matching voice note event ID was found. Versions after 1.1.0 only
6259 * return #FLUID_FAILED if an error occurs.
6262 fluid_synth_stop(fluid_synth_t *synth, unsigned int id)
6265 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6266 fluid_synth_api_enter(synth);
6267 fluid_synth_stop_LOCAL(synth, id);
6269 FLUID_API_RETURN(result);
6272 /* Local synthesis thread variant of fluid_synth_stop */
6274 fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id)
6276 fluid_voice_t *voice;
6279 for(i = 0; i < synth->polyphony; i++)
6281 voice = synth->voice[i];
6283 if(fluid_voice_is_on(voice) && (fluid_voice_get_id(voice) == id))
6285 fluid_voice_noteoff(voice);
6291 * Offset the bank numbers of a loaded SoundFont, i.e.\ subtract
6292 * \c offset from any bank number when assigning instruments.
6294 * @param synth FluidSynth instance
6295 * @param sfont_id ID of a loaded SoundFont
6296 * @param offset Bank offset value to apply to all instruments
6297 * @return #FLUID_OK if the offset was set successfully, #FLUID_FAILED otherwise
6300 fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset)
6302 fluid_sfont_t *sfont;
6305 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6306 fluid_synth_api_enter(synth);
6308 for(list = synth->sfont; list; list = fluid_list_next(list))
6310 sfont = fluid_list_get(list);
6312 if(fluid_sfont_get_id(sfont) == sfont_id)
6314 sfont->bankofs = offset;
6321 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
6322 FLUID_API_RETURN(FLUID_FAILED);
6325 FLUID_API_RETURN(FLUID_OK);
6329 * Get bank offset of a loaded SoundFont.
6330 * @param synth FluidSynth instance
6331 * @param sfont_id ID of a loaded SoundFont
6332 * @return SoundFont bank offset value
6335 fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id)
6337 fluid_sfont_t *sfont;
6341 fluid_return_val_if_fail(synth != NULL, 0);
6342 fluid_synth_api_enter(synth);
6344 for(list = synth->sfont; list; list = fluid_list_next(list))
6346 sfont = fluid_list_get(list);
6348 if(fluid_sfont_get_id(sfont) == sfont_id)
6350 offset = sfont->bankofs;
6357 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
6358 FLUID_API_RETURN(0);
6361 FLUID_API_RETURN(offset);
6365 fluid_synth_api_enter(fluid_synth_t *synth)
6367 if(synth->use_mutex)
6369 fluid_rec_mutex_lock(synth->mutex);
6372 if(!synth->public_api_count)
6374 fluid_synth_check_finished_voices(synth);
6377 synth->public_api_count++;
6380 void fluid_synth_api_exit(fluid_synth_t *synth)
6382 synth->public_api_count--;
6384 if(!synth->public_api_count)
6386 fluid_rvoice_eventhandler_flush(synth->eventhandler);
6389 if(synth->use_mutex)
6391 fluid_rec_mutex_unlock(synth->mutex);
6397 * Set midi channel type
6398 * @param synth FluidSynth instance
6399 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6400 * @param type MIDI channel type (#fluid_midi_channel_type)
6401 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6404 int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type)
6406 fluid_return_val_if_fail((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED);
6407 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6409 synth->channel[chan]->channel_type = type;
6411 FLUID_API_RETURN(FLUID_OK);
6416 * Return the LADSPA effects instance used by FluidSynth
6418 * @param synth FluidSynth instance
6419 * @return pointer to LADSPA fx or NULL if compiled without LADSPA support or LADSPA is not active
6421 fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
6423 fluid_return_val_if_fail(synth != NULL, NULL);
6425 return synth->ladspa_fx;
6430 * Configure a general-purpose IIR biquad filter.
6432 * This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard.
6433 * By default this filter is off (#FLUID_IIR_DISABLED).
6435 * @param synth FluidSynth instance
6436 * @param type Type of the IIR filter to use (see #fluid_iir_filter_type)
6437 * @param flags Additional flags to customize this filter or zero to stay with the default (see #fluid_iir_filter_flags)
6439 * @return #FLUID_OK if the settings have been successfully applied, otherwise #FLUID_FAILED
6441 int fluid_synth_set_custom_filter(fluid_synth_t *synth, int type, int flags)
6444 fluid_voice_t *voice;
6446 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6447 fluid_return_val_if_fail(type >= FLUID_IIR_DISABLED && type < FLUID_IIR_LAST, FLUID_FAILED);
6449 fluid_synth_api_enter(synth);
6451 synth->custom_filter_type = type;
6452 synth->custom_filter_flags = flags;
6454 for(i = 0; i < synth->polyphony; i++)
6456 voice = synth->voice[i];
6458 fluid_voice_set_custom_filter(voice, type, flags);
6461 FLUID_API_RETURN(FLUID_OK);
6465 * Set the important channels for voice overflow priority calculation.
6467 * @param synth FluidSynth instance
6468 * @param channels comma-separated list of channel numbers
6469 * @return #FLUID_OK on success, otherwise #FLUID_FAILED
6471 static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels)
6474 int retval = FLUID_FAILED;
6477 fluid_overflow_prio_t *scores;
6479 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6481 scores = &synth->overflow;
6483 if(scores->num_important_channels < synth->midi_channels)
6485 scores->important_channels = FLUID_REALLOC(scores->important_channels,
6486 sizeof(*scores->important_channels) * synth->midi_channels);
6488 if(scores->important_channels == NULL)
6490 FLUID_LOG(FLUID_ERR, "Out of memory");
6494 scores->num_important_channels = synth->midi_channels;
6497 FLUID_MEMSET(scores->important_channels, FALSE,
6498 sizeof(*scores->important_channels) * scores->num_important_channels);
6500 if(channels != NULL)
6502 values = FLUID_ARRAY(int, synth->midi_channels);
6506 FLUID_LOG(FLUID_ERR, "Out of memory");
6510 /* Every channel given in the comma-separated list of channel numbers
6511 * is set to TRUE, i.e. flagging it as "important". Channel numbers are
6513 num_values = fluid_settings_split_csv(channels, values, synth->midi_channels);
6515 for(i = 0; i < num_values; i++)
6517 if(values[i] > 0 && values[i] <= synth->midi_channels)
6519 scores->important_channels[values[i] - 1] = TRUE;
6532 * Handler for synth.overflow.important-channels setting.
6534 static void fluid_synth_handle_important_channels(void *data, const char *name,
6537 fluid_synth_t *synth = (fluid_synth_t *)data;
6539 fluid_synth_api_enter(synth);
6540 fluid_synth_set_important_channels(synth, value);
6541 fluid_synth_api_exit(synth);
6545 /** API legato mode *********************************************************/
6548 * Sets the legato mode of a channel.
6550 * @param synth the synth instance.
6551 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6552 * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
6555 * - #FLUID_OK on success.
6557 * - \a synth is NULL.
6558 * - \a chan is outside MIDI channel count.
6559 * - \a legatomode is invalid.
6561 int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode)
6563 /* checks parameters first */
6564 fluid_return_val_if_fail(legatomode >= 0, FLUID_FAILED);
6565 fluid_return_val_if_fail(legatomode < FLUID_CHANNEL_LEGATO_MODE_LAST, FLUID_FAILED);
6566 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6568 synth->channel[chan]->legatomode = legatomode;
6570 FLUID_API_RETURN(FLUID_OK);
6574 * Gets the legato mode of a channel.
6576 * @param synth the synth instance.
6577 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6578 * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
6581 * - #FLUID_OK on success.
6583 * - \a synth is NULL.
6584 * - \a chan is outside MIDI channel count.
6585 * - \a legatomode is NULL.
6587 int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode)
6589 /* checks parameters first */
6590 fluid_return_val_if_fail(legatomode != NULL, FLUID_FAILED);
6591 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6593 * legatomode = synth->channel[chan]->legatomode;
6595 FLUID_API_RETURN(FLUID_OK);
6598 /** API portamento mode *********************************************************/
6601 * Sets the portamento mode of a channel.
6603 * @param synth the synth instance.
6604 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6605 * @param portamentomode The portamento mode as indicated by #fluid_channel_portamento_mode.
6607 * - #FLUID_OK on success.
6609 * - \a synth is NULL.
6610 * - \a chan is outside MIDI channel count.
6611 * - \a portamentomode is invalid.
6613 int fluid_synth_set_portamento_mode(fluid_synth_t *synth, int chan,
6616 /* checks parameters first */
6617 fluid_return_val_if_fail(portamentomode >= 0, FLUID_FAILED);
6618 fluid_return_val_if_fail(portamentomode < FLUID_CHANNEL_PORTAMENTO_MODE_LAST, FLUID_FAILED);
6619 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6621 synth->channel[chan]->portamentomode = portamentomode;
6623 FLUID_API_RETURN(FLUID_OK);
6627 * Gets the portamento mode of a channel.
6629 * @param synth the synth instance.
6630 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6631 * @param portamentomode Pointer to the portamento mode as indicated by #fluid_channel_portamento_mode.
6633 * - #FLUID_OK on success.
6635 * - \a synth is NULL.
6636 * - \a chan is outside MIDI channel count.
6637 * - \a portamentomode is NULL.
6639 int fluid_synth_get_portamento_mode(fluid_synth_t *synth, int chan,
6640 int *portamentomode)
6642 /* checks parameters first */
6643 fluid_return_val_if_fail(portamentomode != NULL, FLUID_FAILED);
6644 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6646 * portamentomode = synth->channel[chan]->portamentomode;
6648 FLUID_API_RETURN(FLUID_OK);
6651 /** API breath mode *********************************************************/
6654 * Sets the breath mode of a channel.
6656 * @param synth the synth instance.
6657 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6658 * @param breathmode The breath mode as indicated by #fluid_channel_breath_flags.
6661 * - #FLUID_OK on success.
6663 * - \a synth is NULL.
6664 * - \a chan is outside MIDI channel count.
6666 int fluid_synth_set_breath_mode(fluid_synth_t *synth, int chan, int breathmode)
6668 /* checks parameters first */
6669 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6671 fluid_channel_set_breath_info(synth->channel[chan], breathmode);
6673 FLUID_API_RETURN(FLUID_OK);
6677 * Gets the breath mode of a channel.
6679 * @param synth the synth instance.
6680 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6681 * @param breathmode Pointer to the returned breath mode as indicated by #fluid_channel_breath_flags.
6684 * - #FLUID_OK on success.
6686 * - \a synth is NULL.
6687 * - \a chan is outside MIDI channel count.
6688 * - \a breathmode is NULL.
6690 int fluid_synth_get_breath_mode(fluid_synth_t *synth, int chan, int *breathmode)
6692 /* checks parameters first */
6693 fluid_return_val_if_fail(breathmode != NULL, FLUID_FAILED);
6694 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6696 * breathmode = fluid_channel_get_breath_info(synth->channel[chan]);
6698 FLUID_API_RETURN(FLUID_OK);
6701 /** API Poly/mono mode ******************************************************/
6704 * Resets a basic channel group of MIDI channels.
6705 * @param synth the synth instance.
6706 * @param chan the beginning channel of the group.
6707 * @param nbr_chan the number of channel in the group.
6710 fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan)
6714 for(i = chan; i < chan + nbr_chan; i++)
6716 fluid_channel_reset_basic_channel_info(synth->channel[i]);
6717 synth->channel[i]->mode_val = 0;
6722 * Disables and unassigns all channels from a basic channel group.
6724 * @param synth The synth instance.
6725 * @param chan The basic channel of the group to reset or -1 to reset all channels.
6726 * @note By default (i.e. on creation after new_fluid_synth() and after fluid_synth_system_reset())
6727 * a synth instance has one basic channel at channel 0 in mode #FLUID_CHANNEL_MODE_OMNION_POLY.
6728 * All other channels belong to this basic channel group. Make sure to call this function before
6729 * setting any custom basic channel setup.
6732 * - #FLUID_OK on success.
6734 * - \a synth is NULL.
6735 * - \a chan is outside MIDI channel count.
6736 * - \a chan isn't a basic channel.
6738 int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan)
6742 /* checks parameters first */
6745 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6746 fluid_synth_api_enter(synth);
6747 /* The range is all MIDI channels from 0 to MIDI channel count -1 */
6748 chan = 0; /* beginning chan */
6749 nbr_chan = synth->midi_channels; /* MIDI Channels number */
6753 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6755 /* checks if chan is a basic channel */
6756 if(!(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC))
6758 FLUID_API_RETURN(FLUID_FAILED);
6761 /* The range is all MIDI channels in the group from chan */
6762 nbr_chan = synth->channel[chan]->mode_val; /* nbr of channels in the group */
6765 /* resets the range of MIDI channels */
6766 fluid_synth_reset_basic_channel_LOCAL(synth, chan, nbr_chan);
6767 FLUID_API_RETURN(FLUID_OK);
6771 * Checks if a new basic channel group overlaps the next basic channel group.
6773 * On success the function returns the possible number of channel for this
6774 * new basic channel group.
6775 * The function fails if the new group overlaps the next basic channel group.
6777 * @param see fluid_synth_set_basic_channel.
6779 * - On success, the effective number of channels for this new basic channel group,
6780 * #FLUID_FAILED otherwise.
6782 * - \a val has a number of channels overlapping next basic channel group or been
6783 * above MIDI channel count.
6786 fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val)
6788 int i, n_chan = synth->midi_channels; /* MIDI Channels count */
6789 int real_val = val; /* real number of channels in the group */
6791 /* adjusts val range */
6792 if(mode == FLUID_CHANNEL_MODE_OMNIOFF_POLY)
6794 real_val = 1; /* mode poly omnioff implies a group of only one channel.*/
6798 /* mode poly omnion (0), mono omnion (1), mono omni off (3) */
6799 /* value 0 means all possible channels from basicchan to MIDI channel count -1.*/
6800 real_val = n_chan - basicchan;
6802 /* checks if val range is above MIDI channel count */
6803 else if(basicchan + val > n_chan)
6805 return FLUID_FAILED;
6808 /* checks if this basic channel group overlaps next basic channel group */
6809 for(i = basicchan + 1; i < basicchan + real_val; i++)
6811 if(synth->channel[i]->mode & FLUID_CHANNEL_BASIC)
6813 /* A value of 0 for val means all possible channels from basicchan to
6814 to the next basic channel -1 (if any).
6815 When i reachs the next basic channel group, real_val will be
6816 limited if it is possible */
6819 /* limitation of real_val */
6820 real_val = i - basicchan;
6824 /* overlap with the next basic channel group */
6825 return FLUID_FAILED;
6833 * Sets a new basic channel group only. The function doesn't allow to change an
6834 * existing basic channel.
6836 * The function fails if any channel overlaps any existing basic channel group.
6837 * To make room if necessary, basic channel groups can be cleared using
6838 * fluid_synth_reset_basic_channel().
6840 * @param synth the synth instance.
6841 * @param chan the basic Channel number (0 to MIDI channel count-1).
6842 * @param mode the MIDI mode to use for chan (see #fluid_basic_channel_modes).
6843 * @param val number of channels in the group.
6844 * @note \a val is only relevant for mode #FLUID_CHANNEL_MODE_OMNION_POLY,
6845 * #FLUID_CHANNEL_MODE_OMNION_MONO and #FLUID_CHANNEL_MODE_OMNIOFF_MONO. A value
6846 * of 0 means all possible channels from \a chan to to next basic channel minus 1 (if any)
6847 * or to MIDI channel count minus 1. Val is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY
6848 * as this mode implies a group of only one channel.
6850 * - #FLUID_OK on success.
6852 * - \a synth is NULL.
6853 * - \a chan is outside MIDI channel count.
6854 * - \a mode is invalid.
6855 * - \a val has a number of channels overlapping another basic channel group or been
6856 * above MIDI channel count.
6857 * - When the function fails, any existing basic channels aren't modified.
6859 int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val)
6861 /* check parameters */
6862 fluid_return_val_if_fail(mode >= 0, FLUID_FAILED);
6863 fluid_return_val_if_fail(mode < FLUID_CHANNEL_MODE_LAST, FLUID_FAILED);
6864 fluid_return_val_if_fail(val >= 0, FLUID_FAILED);
6865 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6868 if(val > 0 && chan + val > synth->midi_channels)
6870 FLUID_API_RETURN(FLUID_FAILED);
6873 /* Checks if there is an overlap with the next basic channel */
6874 val = fluid_synth_check_next_basic_channel(synth, chan, mode, val);
6876 if(val == FLUID_FAILED || synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)
6878 /* overlap with the next or previous channel group */
6879 FLUID_LOG(FLUID_INFO, "basic channel %d overlaps another group", chan);
6880 FLUID_API_RETURN(FLUID_FAILED);
6883 /* sets a new basic channel group */
6884 fluid_synth_set_basic_channel_LOCAL(synth, chan, mode, val);
6886 FLUID_API_RETURN(FLUID_OK);
6890 * Local version of fluid_synth_set_basic_channel(), called internally:
6891 * - by fluid_synth_set_basic_channel() to set a new basic channel group.
6892 * - during creation new_fluid_synth() or on CC reset to set a default basic channel group.
6893 * - on CC ominoff, CC omnion, CC poly , CC mono to change an existing basic channel group.
6895 * @param see fluid_synth_set_basic_channel()
6898 fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val)
6902 /* sets the basic channel group */
6903 for(i = basicchan; i < basicchan + val; i++)
6905 int new_mode = mode; /* OMNI_OFF/ON, MONO/POLY ,others bits are zero */
6907 /* MIDI specs: when mode is changed, channel must receive ALL_NOTES_OFF */
6908 fluid_synth_all_notes_off_LOCAL(synth, i);
6912 new_mode |= FLUID_CHANNEL_BASIC; /* First channel in the group */
6913 new_val = val; /* number of channels in the group */
6917 new_val = 0; /* val is 0 for other channel than basic channel */
6920 /* Channel is enabled */
6921 new_mode |= FLUID_CHANNEL_ENABLED;
6922 /* Now new_mode is OMNI OFF/ON,MONO/POLY, BASIC_CHANNEL or not and enabled */
6923 fluid_channel_set_basic_channel_info(synth->channel[i], new_mode);
6924 synth->channel[i]->mode_val = new_val;
6929 * Searchs a previous basic channel starting from chan.
6931 * @param synth the synth instance.
6932 * @param chan starting index of the search (including chan).
6933 * @return index of the basic channel if found , FLUID_FAILED otherwise.
6935 static int fluid_synth_get_previous_basic_channel(fluid_synth_t *synth, int chan)
6937 for(; chan >= 0; chan--)
6939 /* searchs previous basic channel */
6940 if(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC)
6942 /* chan is the previous basic channel */
6947 return FLUID_FAILED;
6951 * Returns poly mono mode information of any MIDI channel.
6953 * @param synth the synth instance
6954 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6955 * @param basic_chan_out Buffer to store the basic channel \a chan belongs to or #FLUID_FAILED if \a chan is disabled.
6956 * @param mode_out Buffer to store the mode of \a chan (see #fluid_basic_channel_modes) or #FLUID_FAILED if \a chan is disabled.
6957 * @param val_out Buffer to store the total number of channels in this basic channel group or #FLUID_FAILED if \a chan is disabled.
6958 * @note If any of \a basic_chan_out, \a mode_out, \a val_out pointer is NULL
6959 * the corresponding information isn't returned.
6962 * - #FLUID_OK on success.
6964 * - \a synth is NULL.
6965 * - \a chan is outside MIDI channel count.
6967 int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan,
6968 int *basic_chan_out,
6972 int basic_chan = FLUID_FAILED;
6973 int mode = FLUID_FAILED;
6974 int val = FLUID_FAILED;
6976 /* checks parameters first */
6977 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6979 if((synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) &&
6980 /* chan is enabled , we search the basic channel chan belongs to */
6981 (basic_chan = fluid_synth_get_previous_basic_channel(synth, chan)) != FLUID_FAILED)
6983 mode = synth->channel[chan]->mode & FLUID_CHANNEL_MODE_MASK;
6984 val = synth->channel[basic_chan]->mode_val;
6987 /* returns the informations if they are requested */
6990 * basic_chan_out = basic_chan;
7003 FLUID_API_RETURN(FLUID_OK);