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 int roundi(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 void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth,
100 static fluid_tuning_t *fluid_synth_get_tuning(fluid_synth_t *synth,
102 static int fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth,
103 fluid_tuning_t *tuning,
104 int bank, int prog, int apply);
105 static void fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth,
106 fluid_tuning_t *old_tuning,
107 fluid_tuning_t *new_tuning,
108 int apply, int unref_new);
109 static void fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth,
110 fluid_channel_t *channel);
111 static int fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
112 fluid_tuning_t *tuning, int apply);
113 static void fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan,
114 int param, float value, int absolute);
115 static void fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id);
118 static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels);
121 /* Callback handlers for real-time settings */
122 static void fluid_synth_handle_sample_rate(void *data, const char *name, double value);
123 static void fluid_synth_handle_gain(void *data, const char *name, double value);
124 static void fluid_synth_handle_polyphony(void *data, const char *name, int value);
125 static void fluid_synth_handle_device_id(void *data, const char *name, int value);
126 static void fluid_synth_handle_overflow(void *data, const char *name, double value);
127 static void fluid_synth_handle_important_channels(void *data, const char *name,
129 static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value);
130 static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value);
133 static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan);
134 static int fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val);
135 static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val);
136 static int fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize,
137 double damping, double width, double level);
139 static int fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level,
140 double speed, double depth_ms, int type);
142 /***************************************************************
147 /* has the synth module been initialized? */
148 /* fluid_atomic_int_t may be anything, so init with {0} to catch most cases */
149 static fluid_atomic_int_t fluid_synth_initialized = {0};
150 static void fluid_synth_init(void);
151 static void init_dither(void);
153 /* default modulators
156 * There is a set of predefined default modulators. They have to be
157 * explicitly overridden by the sound font in order to turn them off.
160 static fluid_mod_t default_vel2att_mod; /* SF2.01 section 8.4.1 */
161 /*not static */ fluid_mod_t default_vel2filter_mod; /* SF2.01 section 8.4.2 */
162 static fluid_mod_t default_at2viblfo_mod; /* SF2.01 section 8.4.3 */
163 static fluid_mod_t default_mod2viblfo_mod; /* SF2.01 section 8.4.4 */
164 static fluid_mod_t default_att_mod; /* SF2.01 section 8.4.5 */
165 static fluid_mod_t default_pan_mod; /* SF2.01 section 8.4.6 */
166 static fluid_mod_t default_expr_mod; /* SF2.01 section 8.4.7 */
167 static fluid_mod_t default_reverb_mod; /* SF2.01 section 8.4.8 */
168 static fluid_mod_t default_chorus_mod; /* SF2.01 section 8.4.9 */
169 static fluid_mod_t default_pitch_bend_mod; /* SF2.01 section 8.4.10 */
170 static fluid_mod_t custom_balance_mod; /* Non-standard modulator */
173 /* custom_breath2att_modulator is not a default modulator specified in SF
174 it is intended to replace default_vel2att_mod on demand using
175 API fluid_set_breath_mode() or command shell setbreathmode.
177 static fluid_mod_t custom_breath2att_mod;
180 static const fluid_revmodel_presets_t revmodel_preset[] =
182 /* name */ /* roomsize */ /* damp */ /* width */ /* level */
183 { "Test 1", 0.2f, 0.0f, 0.5f, 0.9f },
184 { "Test 2", 0.4f, 0.2f, 0.5f, 0.8f },
185 { "Test 3", 0.6f, 0.4f, 0.5f, 0.7f },
186 { "Test 4", 0.8f, 0.7f, 0.5f, 0.6f },
187 { "Test 5", 0.8f, 1.0f, 0.5f, 0.5f },
191 /***************************************************************
193 * INITIALIZATION & UTILITIES
196 void fluid_synth_settings(fluid_settings_t *settings)
198 fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1, FLUID_HINT_TOGGLED);
200 fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1, FLUID_HINT_TOGGLED);
201 fluid_settings_register_num(settings, "synth.reverb.room-size", FLUID_REVERB_DEFAULT_ROOMSIZE, 0.0f, 1.0f, 0);
202 fluid_settings_register_num(settings, "synth.reverb.damp", FLUID_REVERB_DEFAULT_DAMP, 0.0f, 1.0f, 0);
203 fluid_settings_register_num(settings, "synth.reverb.width", FLUID_REVERB_DEFAULT_WIDTH, 0.0f, 100.0f, 0);
204 fluid_settings_register_num(settings, "synth.reverb.level", FLUID_REVERB_DEFAULT_LEVEL, 0.0f, 1.0f, 0);
206 fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1, FLUID_HINT_TOGGLED);
207 fluid_settings_register_int(settings, "synth.chorus.nr", FLUID_CHORUS_DEFAULT_N, 0, 99, 0);
208 fluid_settings_register_num(settings, "synth.chorus.level", FLUID_CHORUS_DEFAULT_LEVEL, 0.0f, 10.0f, 0);
209 fluid_settings_register_num(settings, "synth.chorus.speed", FLUID_CHORUS_DEFAULT_SPEED, 0.29f, 5.0f, 0);
210 fluid_settings_register_num(settings, "synth.chorus.depth", FLUID_CHORUS_DEFAULT_DEPTH, 0.0f, 256.0f, 0);
212 fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, FLUID_HINT_TOGGLED);
213 fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1, FLUID_HINT_TOGGLED);
214 fluid_settings_register_str(settings, "midi.portname", "", 0);
216 #ifdef DEFAULT_SOUNDFONT
217 fluid_settings_register_str(settings, "synth.default-soundfont", DEFAULT_SOUNDFONT, 0);
220 fluid_settings_register_int(settings, "synth.polyphony", 256, 1, 65535, 0);
221 fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0);
222 fluid_settings_register_num(settings, "synth.gain", 0.2f, 0.0f, 10.0f, 0);
223 fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 128, 0);
224 fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 128, 0);
225 fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0);
226 fluid_settings_register_int(settings, "synth.effects-groups", 1, 1, 128, 0);
227 fluid_settings_register_num(settings, "synth.sample-rate", 44100.0f, 8000.0f, 96000.0f, 0);
228 fluid_settings_register_int(settings, "synth.device-id", 0, 0, 126, 0);
229 fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 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);
289 fluid_conversion_config();
291 fluid_rvoice_dsp_config();
295 /* custom_breath2att_mod is not a default modulator specified in SF2.01.
296 it is intended to replace default_vel2att_mod on demand using
297 API fluid_set_breath_mode() or command shell setbreathmode.
299 fluid_mod_set_source1(&custom_breath2att_mod, /* The modulator we are programming here */
300 BREATH_MSB, /* Source. breath MSB corresponds to 2. */
301 FLUID_MOD_CC /* MIDI continuous controller */
302 | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */
303 | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */
304 | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */
306 fluid_mod_set_source2(&custom_breath2att_mod, 0, 0); /* No 2nd source */
307 fluid_mod_set_dest(&custom_breath2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
308 fluid_mod_set_amount(&custom_breath2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */
310 /* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */
311 fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */
312 FLUID_MOD_VELOCITY, /* Source. VELOCITY corresponds to 'index=2'. */
313 FLUID_MOD_GC /* Not a MIDI continuous controller */
314 | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */
315 | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */
316 | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */
318 fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */
319 fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
320 fluid_mod_set_amount(&default_vel2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */
324 /* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff
325 * Have to make a design decision here. The specs don't make any sense this way or another.
326 * One sound font, 'Kingston Piano', which has been praised for its quality, tries to
327 * override this modulator with an amount of 0 and positive polarity (instead of what
328 * the specs say, D=1) for the secondary source.
329 * So if we change the polarity to 'positive', one of the best free sound fonts works...
331 fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
332 FLUID_MOD_GC /* CC=0 */
333 | FLUID_MOD_LINEAR /* type=0 */
334 | FLUID_MOD_UNIPOLAR /* P=0 */
335 | FLUID_MOD_NEGATIVE /* D=1 */
337 fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
338 FLUID_MOD_GC /* CC=0 */
339 | FLUID_MOD_SWITCH /* type=3 */
340 | FLUID_MOD_UNIPOLAR /* P=0 */
341 // do not remove | FLUID_MOD_NEGATIVE /* D=1 */
342 | FLUID_MOD_POSITIVE /* D=0 */
344 fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC); /* Target: Initial filter cutoff */
345 fluid_mod_set_amount(&default_vel2filter_mod, -2400);
349 /* SF2.01 page 53 section 8.4.3: MIDI Channel pressure to Vibrato LFO pitch depth */
350 fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE, /* Index=13 */
351 FLUID_MOD_GC /* CC=0 */
352 | FLUID_MOD_LINEAR /* type=0 */
353 | FLUID_MOD_UNIPOLAR /* P=0 */
354 | FLUID_MOD_POSITIVE /* D=0 */
356 fluid_mod_set_source2(&default_at2viblfo_mod, 0, 0); /* no second source */
357 fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */
358 fluid_mod_set_amount(&default_at2viblfo_mod, 50);
362 /* SF2.01 page 53 section 8.4.4: Mod wheel (Controller 1) to Vibrato LFO pitch depth */
363 fluid_mod_set_source1(&default_mod2viblfo_mod, MODULATION_MSB, /* Index=1 */
364 FLUID_MOD_CC /* CC=1 */
365 | FLUID_MOD_LINEAR /* type=0 */
366 | FLUID_MOD_UNIPOLAR /* P=0 */
367 | FLUID_MOD_POSITIVE /* D=0 */
369 fluid_mod_set_source2(&default_mod2viblfo_mod, 0, 0); /* no second source */
370 fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */
371 fluid_mod_set_amount(&default_mod2viblfo_mod, 50);
375 /* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/
376 fluid_mod_set_source1(&default_att_mod, VOLUME_MSB, /* index=7 */
377 FLUID_MOD_CC /* CC=1 */
378 | FLUID_MOD_CONCAVE /* type=1 */
379 | FLUID_MOD_UNIPOLAR /* P=0 */
380 | FLUID_MOD_NEGATIVE /* D=1 */
382 fluid_mod_set_source2(&default_att_mod, 0, 0); /* No second source */
383 fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
384 fluid_mod_set_amount(&default_att_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
388 /* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */
389 fluid_mod_set_source1(&default_pan_mod, PAN_MSB, /* index=10 */
390 FLUID_MOD_CC /* CC=1 */
391 | FLUID_MOD_LINEAR /* type=0 */
392 | FLUID_MOD_BIPOLAR /* P=1 */
393 | FLUID_MOD_POSITIVE /* D=0 */
395 fluid_mod_set_source2(&default_pan_mod, 0, 0); /* No second source */
396 fluid_mod_set_dest(&default_pan_mod, GEN_PAN); /* Target: pan */
397 /* Amount: 500. The SF specs $8.4.6, p. 55 syas: "Amount = 1000
398 tenths of a percent". The center value (64) corresponds to 50%,
399 so it follows that amount = 50% x 1000/% = 500. */
400 fluid_mod_set_amount(&default_pan_mod, 500.0);
403 /* SF2.01 page 55 section 8.4.7: MIDI continuous controller 11 to initial attenuation*/
404 fluid_mod_set_source1(&default_expr_mod, EXPRESSION_MSB, /* index=11 */
405 FLUID_MOD_CC /* CC=1 */
406 | FLUID_MOD_CONCAVE /* type=1 */
407 | FLUID_MOD_UNIPOLAR /* P=0 */
408 | FLUID_MOD_NEGATIVE /* D=1 */
410 fluid_mod_set_source2(&default_expr_mod, 0, 0); /* No second source */
411 fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
412 fluid_mod_set_amount(&default_expr_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
416 /* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */
417 fluid_mod_set_source1(&default_reverb_mod, EFFECTS_DEPTH1, /* index=91 */
418 FLUID_MOD_CC /* CC=1 */
419 | FLUID_MOD_LINEAR /* type=0 */
420 | FLUID_MOD_UNIPOLAR /* P=0 */
421 | FLUID_MOD_POSITIVE /* D=0 */
423 fluid_mod_set_source2(&default_reverb_mod, 0, 0); /* No second source */
424 fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND); /* Target: Reverb send */
425 fluid_mod_set_amount(&default_reverb_mod, 200); /* Amount: 200 ('tenths of a percent') */
429 /* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Chorus send */
430 fluid_mod_set_source1(&default_chorus_mod, EFFECTS_DEPTH3, /* index=93 */
431 FLUID_MOD_CC /* CC=1 */
432 | FLUID_MOD_LINEAR /* type=0 */
433 | FLUID_MOD_UNIPOLAR /* P=0 */
434 | FLUID_MOD_POSITIVE /* D=0 */
436 fluid_mod_set_source2(&default_chorus_mod, 0, 0); /* No second source */
437 fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND); /* Target: Chorus */
438 fluid_mod_set_amount(&default_chorus_mod, 200); /* Amount: 200 ('tenths of a percent') */
442 /* SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch ... */
443 fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL, /* Index=14 */
444 FLUID_MOD_GC /* CC =0 */
445 | FLUID_MOD_LINEAR /* type=0 */
446 | FLUID_MOD_BIPOLAR /* P=1 */
447 | FLUID_MOD_POSITIVE /* D=0 */
449 fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS, /* Index = 16 */
450 FLUID_MOD_GC /* CC=0 */
451 | FLUID_MOD_LINEAR /* type=0 */
452 | FLUID_MOD_UNIPOLAR /* P=0 */
453 | FLUID_MOD_POSITIVE /* D=0 */
455 fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH); /* Destination: Initial pitch */
456 fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */
459 /* Non-standard MIDI continuous controller 8 to channel stereo balance */
460 fluid_mod_set_source1(&custom_balance_mod, BALANCE_MSB, /* Index=8 */
461 FLUID_MOD_CC /* CC=1 */
462 | FLUID_MOD_CONCAVE /* type=1 */
463 | FLUID_MOD_BIPOLAR /* P=1 */
464 | FLUID_MOD_POSITIVE /* D=0 */
466 fluid_mod_set_source2(&custom_balance_mod, 0, 0);
467 fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */
468 /* Amount: 96 dB of attenuation (on the opposite channel) */
469 fluid_mod_set_amount(&custom_balance_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
472 static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t *synth)
474 return fluid_atomic_int_get(&synth->ticks_since_start);
477 static FLUID_INLINE void fluid_synth_add_ticks(fluid_synth_t *synth, int val)
479 fluid_atomic_int_add(&synth->ticks_since_start, val);
483 /***************************************************************
484 * FLUID SAMPLE TIMERS
485 * Timers that use written audio data as timing reference
487 struct _fluid_sample_timer_t
489 fluid_sample_timer_t *next; /* Single linked list of timers */
490 unsigned long starttick;
491 fluid_timer_callback_t callback;
497 * fluid_sample_timer_process - called when synth->ticks is updated
499 static void fluid_sample_timer_process(fluid_synth_t *synth)
501 fluid_sample_timer_t *st, *stnext;
504 unsigned int ticks = fluid_synth_get_ticks(synth);
506 for(st = synth->sample_timers; st; st = stnext)
508 /* st may be freed in the callback below. cache it's successor now to avoid use after free */
516 msec = (long)(1000.0 * ((double)(ticks - st->starttick)) / synth->sample_rate);
517 cont = (*st->callback)(st->data, msec);
526 fluid_sample_timer_t *new_fluid_sample_timer(fluid_synth_t *synth, fluid_timer_callback_t callback, void *data)
528 fluid_sample_timer_t *result = FLUID_NEW(fluid_sample_timer_t);
532 FLUID_LOG(FLUID_ERR, "Out of memory");
536 result->starttick = fluid_synth_get_ticks(synth);
537 result->isfinished = 0;
539 result->callback = callback;
540 result->next = synth->sample_timers;
541 synth->sample_timers = result;
545 void delete_fluid_sample_timer(fluid_synth_t *synth, fluid_sample_timer_t *timer)
547 fluid_sample_timer_t **ptr;
548 fluid_return_if_fail(synth != NULL);
549 fluid_return_if_fail(timer != NULL);
551 ptr = &synth->sample_timers;
562 ptr = &((*ptr)->next);
567 /***************************************************************
572 static FLUID_INLINE void
573 fluid_synth_update_mixer(fluid_synth_t *synth, fluid_rvoice_function_t method, int intparam,
574 fluid_real_t realparam)
576 fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL);
577 fluid_return_if_fail(synth->eventhandler->mixer != NULL);
578 fluid_rvoice_eventhandler_push_int_real(synth->eventhandler, method,
579 synth->eventhandler->mixer,
580 intparam, realparam);
583 static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_synth_t *synth)
586 fluid_settings_getint(synth->settings, "synth.min-note-length", &i);
587 return (unsigned int)(i * synth->sample_rate / 1000.0f);
591 * Create new FluidSynth instance.
592 * @param settings Configuration parameters to use (used directly).
593 * @return New FluidSynth instance or NULL on error
595 * @note The settings parameter is used directly and should not be modified
596 * or freed independently.
599 new_fluid_synth(fluid_settings_t *settings)
601 fluid_synth_t *synth;
602 fluid_sfloader_t *loader;
603 char *important_channels;
604 int i, nbuf, prio_level = 0;
607 /* initialize all the conversion tables and other stuff */
608 if(fluid_atomic_int_compare_and_exchange(&fluid_synth_initialized, 0, 1))
613 /* allocate a new synthesizer object */
614 synth = FLUID_NEW(fluid_synth_t);
618 FLUID_LOG(FLUID_ERR, "Out of memory");
622 FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t));
624 fluid_rec_mutex_init(synth->mutex);
625 fluid_settings_getint(settings, "synth.threadsafe-api", &synth->use_mutex);
626 synth->public_api_count = 0;
628 synth->settings = settings;
630 fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb);
631 fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus);
632 fluid_settings_getint(settings, "synth.verbose", &synth->verbose);
634 fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
635 fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate);
636 fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels);
637 fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
638 fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups);
639 fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
640 fluid_settings_getint(settings, "synth.effects-groups", &synth->effects_groups);
641 fluid_settings_getnum_float(settings, "synth.gain", &synth->gain);
642 fluid_settings_getint(settings, "synth.device-id", &synth->device_id);
643 fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores);
645 fluid_settings_getnum_float(settings, "synth.overflow.percussion", &synth->overflow.percussion);
646 fluid_settings_getnum_float(settings, "synth.overflow.released", &synth->overflow.released);
647 fluid_settings_getnum_float(settings, "synth.overflow.sustained", &synth->overflow.sustained);
648 fluid_settings_getnum_float(settings, "synth.overflow.volume", &synth->overflow.volume);
649 fluid_settings_getnum_float(settings, "synth.overflow.age", &synth->overflow.age);
650 fluid_settings_getnum_float(settings, "synth.overflow.important", &synth->overflow.important);
652 /* register the callbacks */
653 fluid_settings_callback_num(settings, "synth.sample-rate",
654 fluid_synth_handle_sample_rate, synth);
655 fluid_settings_callback_num(settings, "synth.gain",
656 fluid_synth_handle_gain, synth);
657 fluid_settings_callback_int(settings, "synth.polyphony",
658 fluid_synth_handle_polyphony, synth);
659 fluid_settings_callback_int(settings, "synth.device-id",
660 fluid_synth_handle_device_id, synth);
661 fluid_settings_callback_num(settings, "synth.overflow.percussion",
662 fluid_synth_handle_overflow, synth);
663 fluid_settings_callback_num(settings, "synth.overflow.sustained",
664 fluid_synth_handle_overflow, synth);
665 fluid_settings_callback_num(settings, "synth.overflow.released",
666 fluid_synth_handle_overflow, synth);
667 fluid_settings_callback_num(settings, "synth.overflow.age",
668 fluid_synth_handle_overflow, synth);
669 fluid_settings_callback_num(settings, "synth.overflow.volume",
670 fluid_synth_handle_overflow, synth);
671 fluid_settings_callback_num(settings, "synth.overflow.important",
672 fluid_synth_handle_overflow, synth);
673 fluid_settings_callback_str(settings, "synth.overflow.important-channels",
674 fluid_synth_handle_important_channels, synth);
675 fluid_settings_callback_num(settings, "synth.reverb.room-size",
676 fluid_synth_handle_reverb_chorus_num, synth);
677 fluid_settings_callback_num(settings, "synth.reverb.damp",
678 fluid_synth_handle_reverb_chorus_num, synth);
679 fluid_settings_callback_num(settings, "synth.reverb.width",
680 fluid_synth_handle_reverb_chorus_num, synth);
681 fluid_settings_callback_num(settings, "synth.reverb.level",
682 fluid_synth_handle_reverb_chorus_num, synth);
683 fluid_settings_callback_int(settings, "synth.reverb.active",
684 fluid_synth_handle_reverb_chorus_int, synth);
685 fluid_settings_callback_int(settings, "synth.chorus.active",
686 fluid_synth_handle_reverb_chorus_int, synth);
687 fluid_settings_callback_int(settings, "synth.chorus.nr",
688 fluid_synth_handle_reverb_chorus_int, synth);
689 fluid_settings_callback_num(settings, "synth.chorus.level",
690 fluid_synth_handle_reverb_chorus_num, synth);
691 fluid_settings_callback_num(settings, "synth.chorus.depth",
692 fluid_synth_handle_reverb_chorus_num, synth);
693 fluid_settings_callback_num(settings, "synth.chorus.speed",
694 fluid_synth_handle_reverb_chorus_num, synth);
696 /* do some basic sanity checking on the settings */
698 if(synth->midi_channels % 16 != 0)
700 int n = synth->midi_channels / 16;
701 synth->midi_channels = (n + 1) * 16;
702 fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels);
703 FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. "
704 "I'll increase the number of channels to the next multiple.");
707 if(synth->audio_channels < 1)
709 FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. "
710 "Changing this setting to 1.");
711 synth->audio_channels = 1;
713 else if(synth->audio_channels > 128)
715 FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). "
716 "Limiting this setting to 128.", synth->audio_channels);
717 synth->audio_channels = 128;
720 if(synth->audio_groups < 1)
722 FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. "
723 "Changing this setting to 1.");
724 synth->audio_groups = 1;
726 else if(synth->audio_groups > 128)
728 FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). "
729 "Limiting this setting to 128.", synth->audio_groups);
730 synth->audio_groups = 128;
733 if(synth->effects_channels < 2)
735 FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)."
736 "Setting effects channels to 2.", synth->effects_channels);
737 synth->effects_channels = 2;
740 /* The number of buffers is determined by the higher number of nr
741 * groups / nr audio channels. If LADSPA is unused, they should be
743 nbuf = synth->audio_channels;
745 if(synth->audio_groups > nbuf)
747 nbuf = synth->audio_groups;
750 if(fluid_settings_dupstr(settings, "synth.overflow.important-channels",
751 &important_channels) == FLUID_OK)
753 if(fluid_synth_set_important_channels(synth, important_channels) != FLUID_OK)
755 FLUID_LOG(FLUID_WARN, "Failed to set overflow important channels");
758 FLUID_FREE(important_channels);
761 /* as soon as the synth is created it starts playing. */
762 synth->state = FLUID_SYNTH_PLAYING;
764 synth->fromkey_portamento = INVALID_NOTE; /* disable portamento */
766 fluid_atomic_int_set(&synth->ticks_since_start, 0);
767 synth->tuning = NULL;
768 fluid_private_init(synth->tuning_iter);
770 /* Initialize multi-core variables if multiple cores enabled */
773 fluid_settings_getint(synth->settings, "audio.realtime-prio", &prio_level);
776 /* Allocate event queue for rvoice mixer */
777 /* In an overflow situation, a new voice takes about 50 spaces in the queue! */
778 synth->eventhandler = new_fluid_rvoice_eventhandler(synth->polyphony * 64,
779 synth->polyphony, nbuf, synth->effects_channels, synth->effects_groups, synth->sample_rate, synth->cores - 1, prio_level);
781 if(synth->eventhandler == NULL)
786 /* Setup the list of default modulators.
787 * Needs to happen after eventhandler has been set up, as fluid_synth_enter_api is called in the process */
788 synth->default_mod = NULL;
789 fluid_synth_add_default_mod(synth, &default_vel2att_mod, FLUID_SYNTH_ADD);
790 fluid_synth_add_default_mod(synth, &default_vel2filter_mod, FLUID_SYNTH_ADD);
791 fluid_synth_add_default_mod(synth, &default_at2viblfo_mod, FLUID_SYNTH_ADD);
792 fluid_synth_add_default_mod(synth, &default_mod2viblfo_mod, FLUID_SYNTH_ADD);
793 fluid_synth_add_default_mod(synth, &default_att_mod, FLUID_SYNTH_ADD);
794 fluid_synth_add_default_mod(synth, &default_pan_mod, FLUID_SYNTH_ADD);
795 fluid_synth_add_default_mod(synth, &default_expr_mod, FLUID_SYNTH_ADD);
796 fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD);
797 fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD);
798 fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD);
799 fluid_synth_add_default_mod(synth, &custom_balance_mod, FLUID_SYNTH_ADD);
801 /* Create and initialize the Fx unit.*/
802 fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);
807 synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate,
808 FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE);
810 if(synth->ladspa_fx == NULL)
812 FLUID_LOG(FLUID_ERR, "Out of memory");
816 fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx,
817 synth->audio_groups);
819 FLUID_LOG(FLUID_WARN, "FluidSynth has not been compiled with LADSPA support");
823 /* allocate and add the default sfont loader */
824 loader = new_fluid_defsfloader(settings);
828 FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader");
832 fluid_synth_add_sfloader(synth, loader);
835 /* allocate all channel objects */
836 synth->channel = FLUID_ARRAY(fluid_channel_t *, synth->midi_channels);
838 if(synth->channel == NULL)
840 FLUID_LOG(FLUID_ERR, "Out of memory");
844 for(i = 0; i < synth->midi_channels; i++)
846 synth->channel[i] = new_fluid_channel(synth, i);
848 if(synth->channel[i] == NULL)
854 /* allocate all synthesis processes */
855 synth->nvoice = synth->polyphony;
856 synth->voice = FLUID_ARRAY(fluid_voice_t *, synth->nvoice);
858 if(synth->voice == NULL)
863 for(i = 0; i < synth->nvoice; i++)
865 synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
867 if(synth->voice[i] == NULL)
873 /* sets a default basic channel */
874 /* Sets one basic channel: basic channel 0, mode 0 (Omni On - Poly) */
875 /* (i.e all channels are polyphonic) */
876 /* Must be called after channel objects allocation */
877 fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
878 synth->midi_channels);
880 synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
883 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
884 synth->polyphony, 0.0f);
885 fluid_synth_set_reverb_on(synth, synth->with_reverb);
886 fluid_synth_set_chorus_on(synth, synth->with_chorus);
888 synth->cur = FLUID_BUFSIZE;
890 synth->dither_index = 0;
893 double room, damp, width, level;
895 fluid_settings_getnum(settings, "synth.reverb.room-size", &room);
896 fluid_settings_getnum(settings, "synth.reverb.damp", &damp);
897 fluid_settings_getnum(settings, "synth.reverb.width", &width);
898 fluid_settings_getnum(settings, "synth.reverb.level", &level);
900 fluid_synth_set_reverb_full_LOCAL(synth,
901 FLUID_REVMODEL_SET_ALL,
909 double level, speed, depth;
911 fluid_settings_getint(settings, "synth.chorus.nr", &i);
912 fluid_settings_getnum(settings, "synth.chorus.level", &level);
913 fluid_settings_getnum(settings, "synth.chorus.speed", &speed);
914 fluid_settings_getnum(settings, "synth.chorus.depth", &depth);
916 fluid_synth_set_chorus_full_LOCAL(synth,
917 FLUID_CHORUS_SET_ALL,
922 FLUID_CHORUS_DEFAULT_TYPE);
926 synth->bank_select = FLUID_BANK_STYLE_GS;
928 if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gm"))
930 synth->bank_select = FLUID_BANK_STYLE_GM;
932 else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gs"))
934 synth->bank_select = FLUID_BANK_STYLE_GS;
936 else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "xg"))
938 synth->bank_select = FLUID_BANK_STYLE_XG;
940 else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "mma"))
942 synth->bank_select = FLUID_BANK_STYLE_MMA;
945 fluid_synth_process_event_queue(synth);
948 synth->start = fluid_curtime();
953 delete_fluid_synth(synth);
959 * Delete a FluidSynth instance.
960 * @param synth FluidSynth instance to delete
962 * @note Other users of a synthesizer instance, such as audio and MIDI drivers,
963 * should be deleted prior to freeing the FluidSynth instance.
966 delete_fluid_synth(fluid_synth_t *synth)
970 fluid_sfont_t *sfont;
971 fluid_sfloader_t *loader;
972 fluid_mod_t *default_mod;
975 fluid_return_if_fail(synth != NULL);
977 fluid_profiling_print();
979 /* turn off all voices, needed to unload SoundFont data */
980 if(synth->voice != NULL)
982 for(i = 0; i < synth->nvoice; i++)
984 fluid_voice_t *voice = synth->voice[i];
991 fluid_voice_unlock_rvoice(voice);
992 fluid_voice_overflow_rvoice_finished(voice);
994 if(fluid_voice_is_playing(voice))
996 fluid_voice_off(voice);
997 /* If we only use fluid_voice_off(voice) it will trigger a delayed
998 * fluid_voice_stop(voice) via fluid_synth_check_finished_voices().
999 * But here, we are deleting the fluid_synth_t instance so
1000 * fluid_voice_stop() will be never triggered resulting in
1001 * SoundFont data never unloaded (i.e a serious memory leak).
1002 * So, fluid_voice_stop() must be explicitly called to insure
1003 * unloading SoundFont data
1005 fluid_voice_stop(voice);
1010 /* also unset all presets for clean SoundFont unload */
1011 if(synth->channel != NULL)
1013 for(i = 0; i < synth->midi_channels; i++)
1015 fluid_channel_set_preset(synth->channel[i], NULL);
1019 delete_fluid_rvoice_eventhandler(synth->eventhandler);
1021 /* delete all the SoundFonts */
1022 for(list = synth->sfont; list; list = fluid_list_next(list))
1024 sfont = fluid_list_get(list);
1025 fluid_sfont_delete_internal(sfont);
1028 delete_fluid_list(synth->sfont);
1030 /* delete all the SoundFont loaders */
1032 for(list = synth->loaders; list; list = fluid_list_next(list))
1034 loader = (fluid_sfloader_t *) fluid_list_get(list);
1035 fluid_sfloader_delete(loader);
1038 delete_fluid_list(synth->loaders);
1041 if(synth->channel != NULL)
1043 for(i = 0; i < synth->midi_channels; i++)
1045 delete_fluid_channel(synth->channel[i]);
1048 FLUID_FREE(synth->channel);
1051 if(synth->voice != NULL)
1053 for(i = 0; i < synth->nvoice; i++)
1055 delete_fluid_voice(synth->voice[i]);
1058 FLUID_FREE(synth->voice);
1062 /* free the tunings, if any */
1063 if(synth->tuning != NULL)
1065 for(i = 0; i < 128; i++)
1067 if(synth->tuning[i] != NULL)
1069 for(k = 0; k < 128; k++)
1071 delete_fluid_tuning(synth->tuning[i][k]);
1074 FLUID_FREE(synth->tuning[i]);
1078 FLUID_FREE(synth->tuning);
1081 fluid_private_free(synth->tuning_iter);
1084 /* Release the LADSPA effects unit */
1085 delete_fluid_ladspa_fx(synth->ladspa_fx);
1088 /* delete all default modulators */
1089 default_mod = synth->default_mod;
1091 while(default_mod != NULL)
1094 default_mod = mod->next;
1095 delete_fluid_mod(mod);
1098 FLUID_FREE(synth->overflow.important_channels);
1100 fluid_rec_mutex_destroy(synth->mutex);
1106 * Get a textual representation of the last error
1107 * @param synth FluidSynth instance
1108 * @return Pointer to string of last error message. Valid until the same
1109 * calling thread calls another FluidSynth function which fails. String is
1110 * internal and should not be modified or freed.
1112 /* FIXME - The error messages are not thread-safe, yet. They are still stored
1113 * in a global message buffer (see fluid_sys.c). */
1115 fluid_synth_error(fluid_synth_t *synth)
1117 return fluid_error();
1121 * Send a note-on event to a FluidSynth object.
1122 * @param synth FluidSynth instance
1123 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1124 * @param key MIDI note number (0-127)
1125 * @param vel MIDI velocity (0-127, 0=noteoff)
1126 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1129 fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel)
1132 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1133 fluid_return_val_if_fail(vel >= 0 && vel <= 127, FLUID_FAILED);
1134 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1136 /* Allowed only on MIDI channel enabled */
1137 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1139 result = fluid_synth_noteon_LOCAL(synth, chan, key, vel);
1140 FLUID_API_RETURN(result);
1143 /* Local synthesis thread variant of fluid_synth_noteon */
1145 fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key, int vel)
1147 fluid_channel_t *channel ;
1149 /* notes with velocity zero go to noteoff */
1152 return fluid_synth_noteoff_LOCAL(synth, chan, key);
1155 channel = synth->channel[chan];
1157 /* makes sure this channel has a preset */
1158 if(channel->preset == NULL)
1162 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s",
1164 fluid_synth_get_ticks(synth) / 44100.0f,
1165 (fluid_curtime() - synth->start) / 1000.0f,
1166 0.0f, 0, "channel has no preset");
1169 return FLUID_FAILED;
1172 if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1174 /* play the noteOn in monophonic */
1175 return fluid_synth_noteon_mono_LOCAL(synth, chan, key, vel);
1179 /* channel is poly and legato CC is Off) */
1181 /* plays the noteOn in polyphonic */
1182 /* Sets the note at first position in monophonic list */
1183 /* In the case where the musician intends to inter the channel in monophonic
1184 (by depressing the CC legato on), the next noteOn mono could be played legato
1185 with the previous note poly (if the musician choose this).
1187 fluid_channel_set_onenote_monolist(channel, (unsigned char) key,
1188 (unsigned char) vel);
1190 /* If there is another voice process on the same channel and key,
1191 advance it to the release phase. */
1192 fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key);
1194 /* a noteon poly is passed to fluid_synth_noteon_monopoly_legato().
1195 This allows an opportunity to get this note played legato with a previous
1196 note if a CC PTC have been received before this noteon. This behavior is
1197 a MIDI specification (see FluidPolymono-0004.pdf chapter 4.3-a ,3.4.11
1200 return fluid_synth_noteon_monopoly_legato(synth, chan, INVALID_NOTE, key, vel);
1205 * Sends a note-off event to a FluidSynth object.
1206 * @param synth FluidSynth instance
1207 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1208 * @param key MIDI note number (0-127)
1209 * @return #FLUID_OK on success, #FLUID_FAILED otherwise (may just mean that no
1210 * voices matched the note off event)
1213 fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key)
1216 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1217 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1219 /* Allowed only on MIDI channel enabled */
1220 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1222 result = fluid_synth_noteoff_LOCAL(synth, chan, key);
1223 FLUID_API_RETURN(result);
1226 /* Local synthesis thread variant of fluid_synth_noteoff */
1228 fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key)
1231 fluid_channel_t *channel = synth->channel[chan];
1233 if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1235 /* play the noteOff in monophonic */
1236 status = fluid_synth_noteoff_mono_LOCAL(synth, chan, key);
1240 /* channel is poly and legato CC is Off) */
1241 /* removes the note from the monophonic list */
1242 if(key == fluid_channel_last_note(channel))
1244 fluid_channel_clear_monolist(channel);
1247 status = fluid_synth_noteoff_monopoly(synth, chan, key, 0);
1250 /* Changes the state (Valid/Invalid) of the most recent note played in a
1252 fluid_channel_invalid_prev_note_staccato(channel);
1256 /* Damps voices on a channel (turn notes off), if they're sustained by
1259 fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t *synth, int chan)
1261 fluid_channel_t *channel = synth->channel[chan];
1262 fluid_voice_t *voice;
1265 for(i = 0; i < synth->polyphony; i++)
1267 voice = synth->voice[i];
1269 if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sustained(voice))
1271 if(voice->key == channel->key_mono_sustained)
1273 /* key_mono_sustained is a possible mono note sustainted
1274 (by sustain or sostenuto pedal). It must be marked released
1275 (INVALID_NOTE) here because it is released only by sustain pedal */
1276 channel->key_mono_sustained = INVALID_NOTE;
1279 fluid_voice_release(voice);
1286 /* Damps voices on a channel (turn notes off), if they're sustained by
1289 fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t *synth, int chan)
1291 fluid_channel_t *channel = synth->channel[chan];
1292 fluid_voice_t *voice;
1295 for(i = 0; i < synth->polyphony; i++)
1297 voice = synth->voice[i];
1299 if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sostenuto(voice))
1301 if(voice->key == channel->key_mono_sustained)
1303 /* key_mono_sustained is a possible mono note sustainted
1304 (by sustain or sostenuto pedal). It must be marked released
1305 (INVALID_NOTE) here because it is released only by sostenuto pedal */
1306 channel->key_mono_sustained = INVALID_NOTE;
1309 fluid_voice_release(voice);
1317 * Adds the specified modulator \c mod as default modulator to the synth. \c mod will
1318 * take effect for any subsequently created voice.
1319 * @param synth FluidSynth instance
1320 * @param mod Modulator info (values copied, passed in object can be freed immediately afterwards)
1321 * @param mode Determines how to handle an existing identical modulator (#fluid_synth_add_mod)
1322 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1324 * @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1325 * from synthesis context at the risk of stalling audio output.
1328 fluid_synth_add_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod, int mode)
1330 fluid_mod_t *default_mod;
1331 fluid_mod_t *last_mod = NULL;
1332 fluid_mod_t *new_mod;
1334 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1335 fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1336 fluid_synth_api_enter(synth);
1338 default_mod = synth->default_mod;
1340 while(default_mod != NULL)
1342 if(fluid_mod_test_identity(default_mod, mod))
1344 if(mode == FLUID_SYNTH_ADD)
1346 default_mod->amount += mod->amount;
1348 else if(mode == FLUID_SYNTH_OVERWRITE)
1350 default_mod->amount = mod->amount;
1354 FLUID_API_RETURN(FLUID_FAILED);
1357 FLUID_API_RETURN(FLUID_OK);
1360 last_mod = default_mod;
1361 default_mod = default_mod->next;
1364 /* Add a new modulator (no existing modulator to add / overwrite). */
1365 new_mod = new_fluid_mod();
1369 FLUID_API_RETURN(FLUID_FAILED);
1372 fluid_mod_clone(new_mod, mod);
1373 new_mod->next = NULL;
1375 if(last_mod == NULL)
1377 synth->default_mod = new_mod;
1381 last_mod->next = new_mod;
1384 FLUID_API_RETURN(FLUID_OK);
1388 * Removes the specified modulator \c mod from the synth's default modulator list.
1389 * fluid_mod_test_identity() will be used to test modulator matching.
1390 * @param synth synth instance
1391 * @param mod The modulator to remove
1392 * @return #FLUID_OK if a matching modulator was found and successfully removed, #FLUID_FAILED otherwise
1394 * @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1395 * from synthesis context at the risk of stalling audio output.
1398 fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod)
1400 fluid_mod_t *default_mod;
1401 fluid_mod_t *last_mod;
1403 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1404 fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1405 fluid_synth_api_enter(synth);
1407 last_mod = default_mod = synth->default_mod;
1409 while(default_mod != NULL)
1411 if(fluid_mod_test_identity(default_mod, mod))
1413 if(synth->default_mod == default_mod)
1415 synth->default_mod = synth->default_mod->next;
1419 last_mod->next = default_mod->next;
1422 delete_fluid_mod(default_mod);
1423 FLUID_API_RETURN(FLUID_OK);
1426 last_mod = default_mod;
1427 default_mod = default_mod->next;
1430 FLUID_API_RETURN(FLUID_FAILED);
1435 * Send a MIDI controller event on a MIDI channel.
1436 * @param synth FluidSynth instance
1437 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1438 * @param num MIDI controller number (0-127)
1439 * @param val MIDI controller value (0-127)
1440 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1441 * @note This function supports MIDI Global Controllers which will be sent to
1442 * all channels of the basic channel if this basic channel is in mode OmniOff/Mono.
1443 * This is accomplished by sending the CC one MIDI channel below the basic
1444 * channel of the receiver.
1445 * Examples: let a synthesizer with 16 MIDI channels:
1446 * - Let a basic channel 7 in mode 3 (Omni Off, Mono). If MIDI channel 6 is disabled it
1447 * could be used as CC global for all channels belonging to basic channel 7.
1448 * - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used
1449 * as CC global for all channels belonging to basic channel 0.
1452 fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
1454 int result = FLUID_FAILED;
1455 fluid_channel_t *channel;
1456 fluid_return_val_if_fail(num >= 0 && num <= 127, FLUID_FAILED);
1457 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
1458 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1460 channel = synth->channel[chan];
1462 if(channel->mode & FLUID_CHANNEL_ENABLED)
1464 /* chan is enabled */
1467 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val);
1470 fluid_channel_set_cc(channel, num, val);
1471 result = fluid_synth_cc_LOCAL(synth, chan, num);
1473 else /* chan is disabled so it is a candidate for global channel */
1475 /* looks for next basic channel */
1476 int n_chan = synth->midi_channels; /* MIDI Channels number */
1479 if(chan < n_chan - 1)
1481 basicchan = chan + 1; /* next channel */
1485 basicchan = 0; /* wrap to 0 */
1488 channel = synth->channel[basicchan];
1490 /* Channel must be a basicchan in mode OMNIOFF_MONO */
1491 if((channel->mode & FLUID_CHANNEL_BASIC) &&
1492 ((channel->mode & FLUID_CHANNEL_MODE_MASK) == FLUID_CHANNEL_MODE_OMNIOFF_MONO))
1494 /* sends cc to all channels in this basic channel */
1495 int i, nbr = channel->mode_val;
1497 for(i = basicchan; i < basicchan + nbr; i++)
1501 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", i, num, val);
1504 fluid_channel_set_cc(synth->channel[i], num, val);
1505 result = fluid_synth_cc_LOCAL(synth, i, num);
1508 /* The channel chan is not a valid 'global channel' */
1511 result = FLUID_FAILED;
1515 FLUID_API_RETURN(result);
1518 /* Local synthesis thread variant of MIDI CC set function. */
1520 fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
1522 fluid_channel_t *chan = synth->channel[channum];
1526 value = fluid_channel_get_cc(chan, num);
1531 /* CC omnioff, omnion, mono, poly */
1537 /* allowed only if channum is a basic channel */
1538 if(chan->mode & FLUID_CHANNEL_BASIC)
1540 /* Construction of new_mode from current channel mode and this CC mode */
1541 int new_mode = chan->mode & FLUID_CHANNEL_MODE_MASK;
1546 new_mode |= FLUID_CHANNEL_POLY_OFF;
1550 new_mode &= ~FLUID_CHANNEL_POLY_OFF;
1554 new_mode |= FLUID_CHANNEL_OMNI_OFF;
1558 new_mode &= ~FLUID_CHANNEL_OMNI_OFF;
1561 default: /* should never happen */
1562 return FLUID_FAILED;
1565 /* MIDI specs: if value is 0 it means all channels from channum to next
1566 basic channel minus 1 (if any) or to MIDI channel count minus 1.
1567 However, if value is > 0 (e.g. 4), the group of channels will be be
1569 value is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY as this mode
1570 implies a group of only one channel.
1572 /* Checks value range and changes this existing basic channel group */
1573 value = fluid_synth_check_next_basic_channel(synth, channum, new_mode, value);
1575 if(value != FLUID_FAILED)
1577 /* reset the current basic channel before changing it */
1578 fluid_synth_reset_basic_channel_LOCAL(synth, channum, chan->mode_val);
1579 fluid_synth_set_basic_channel_LOCAL(synth, channum, new_mode, value);
1580 break; /* FLUID_OK */
1584 return FLUID_FAILED;
1587 /* handles Poly/mono commutation on Legato pedal On/Off.*/
1588 fluid_channel_cc_legato(chan, value);
1591 case PORTAMENTO_SWITCH:
1592 /* Special handling of the monophonic list */
1593 /* Invalids the most recent note played in a staccato manner */
1594 fluid_channel_invalid_prev_note_staccato(chan);
1597 case SUSTAIN_SWITCH:
1599 /* Release voices if Sustain switch is released */
1600 if(value < 64) /* Sustain is released */
1602 fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
1607 case SOSTENUTO_SWITCH:
1609 /* Release voices if Sostetuno switch is released */
1610 if(value < 64) /* Sostenuto is released */
1612 fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
1614 else /* Sostenuto is depressed */
1615 /* Update sostenuto order id when pedaling on Sostenuto */
1617 chan->sostenuto_orderid = synth->noteid; /* future voice id value */
1622 case BANK_SELECT_MSB:
1623 fluid_channel_set_bank_msb(chan, value & 0x7F);
1626 case BANK_SELECT_LSB:
1627 fluid_channel_set_bank_lsb(chan, value & 0x7F);
1631 fluid_synth_all_notes_off_LOCAL(synth, channum);
1635 fluid_synth_all_sounds_off_LOCAL(synth, channum);
1639 fluid_channel_init_ctrl(chan, 1);
1640 fluid_synth_modulate_voices_all_LOCAL(synth, channum);
1643 case DATA_ENTRY_MSB:
1645 int data = (value << 7) + fluid_channel_get_cc(chan, DATA_ENTRY_LSB);
1647 if(chan->nrpn_active) /* NRPN is active? */
1649 /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1650 if((fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1651 && (fluid_channel_get_cc(chan, NRPN_LSB) < 100))
1653 nrpn_select = chan->nrpn_select;
1655 if(nrpn_select < GEN_LAST)
1657 float val = fluid_gen_scale_nrpn(nrpn_select, data);
1658 fluid_synth_set_gen_LOCAL(synth, channum, nrpn_select, val, FALSE);
1661 chan->nrpn_select = 0; /* Reset to 0 */
1664 else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */
1666 switch(fluid_channel_get_cc(chan, RPN_LSB))
1668 case RPN_PITCH_BEND_RANGE: /* Set bend range in semitones */
1669 fluid_channel_set_pitch_wheel_sensitivity(synth->channel[channum], value);
1670 fluid_synth_update_pitch_wheel_sens_LOCAL(synth, channum); /* Update bend range */
1671 /* FIXME - Handle LSB? (Fine bend range in cents) */
1674 case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over +/-1 semitone (+/- 100 cents, 8192 = center) */
1675 fluid_synth_set_gen_LOCAL(synth, channum, GEN_FINETUNE,
1676 (data - 8192) / 8192.0 * 100.0, FALSE);
1679 case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */
1680 fluid_synth_set_gen_LOCAL(synth, channum, GEN_COARSETUNE,
1684 case RPN_TUNING_PROGRAM_CHANGE:
1685 fluid_channel_set_tuning_prog(chan, value);
1686 fluid_synth_activate_tuning(synth, channum,
1687 fluid_channel_get_tuning_bank(chan),
1691 case RPN_TUNING_BANK_SELECT:
1692 fluid_channel_set_tuning_bank(chan, value);
1695 case RPN_MODULATION_DEPTH_RANGE:
1704 fluid_channel_set_cc(chan, NRPN_LSB, 0);
1705 chan->nrpn_select = 0;
1706 chan->nrpn_active = 1;
1711 /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1712 if(fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1716 chan->nrpn_select += 100;
1718 else if(value == 101)
1720 chan->nrpn_select += 1000;
1722 else if(value == 102)
1724 chan->nrpn_select += 10000;
1726 else if(value < 100)
1728 chan->nrpn_select += value;
1732 chan->nrpn_active = 1;
1737 chan->nrpn_active = 0;
1741 /* handles CC Breath On/Off noteOn/noteOff mode */
1742 fluid_channel_cc_breath_note_on_off(chan, value);
1746 return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num);
1753 * Get current MIDI controller value on a MIDI channel.
1754 * @param synth FluidSynth instance
1755 * @param chan MIDI channel number (0 to MIDI channel count - 1)
1756 * @param num MIDI controller number (0-127)
1757 * @param pval Location to store MIDI controller value (0-127)
1758 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1761 fluid_synth_get_cc(fluid_synth_t *synth, int chan, int num, int *pval)
1763 fluid_return_val_if_fail(num >= 0 && num < 128, FLUID_FAILED);
1764 fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
1766 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1768 /* Allowed only on MIDI channel enabled */
1769 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1771 *pval = fluid_channel_get_cc(synth->channel[chan], num);
1772 FLUID_API_RETURN(FLUID_OK);
1776 * Handler for synth.device-id setting.
1779 fluid_synth_handle_device_id(void *data, const char *name, int value)
1781 fluid_synth_t *synth = (fluid_synth_t *)data;
1782 fluid_return_if_fail(synth != NULL);
1784 fluid_synth_api_enter(synth);
1785 synth->device_id = value;
1786 fluid_synth_api_exit(synth);
1790 * Process a MIDI SYSEX (system exclusive) message.
1791 * @param synth FluidSynth instance
1792 * @param data Buffer containing SYSEX data (not including 0xF0 and 0xF7)
1793 * @param len Length of data in buffer
1794 * @param response Buffer to store response to or NULL to ignore
1795 * @param response_len IN/OUT parameter, in: size of response buffer, out:
1796 * amount of data written to response buffer (if FLUID_FAILED is returned and
1797 * this value is non-zero, it indicates the response buffer is too small)
1798 * @param handled Optional location to store boolean value if message was
1799 * recognized and handled or not (set to TRUE if it was handled)
1800 * @param dryrun TRUE to just do a dry run but not actually execute the SYSEX
1801 * command (useful for checking if a SYSEX message would be handled)
1802 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
1805 /* SYSEX format (0xF0 and 0xF7 not passed to this function):
1806 * Non-realtime: 0xF0 0x7E <DeviceId> [BODY] 0xF7
1807 * Realtime: 0xF0 0x7F <DeviceId> [BODY] 0xF7
1808 * Tuning messages: 0xF0 0x7E/0x7F <DeviceId> 0x08 <sub ID2> [BODY] <ChkSum> 0xF7
1811 fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len,
1812 char *response, int *response_len, int *handled, int dryrun)
1814 int avail_response = 0;
1823 avail_response = *response_len;
1827 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1828 fluid_return_val_if_fail(data != NULL, FLUID_FAILED);
1829 fluid_return_val_if_fail(len > 0, FLUID_FAILED);
1830 fluid_return_val_if_fail(!response || response_len, FLUID_FAILED);
1837 /* MIDI tuning SYSEX message? */
1838 if((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME)
1839 && (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL)
1840 && data[2] == MIDI_SYSEX_MIDI_TUNING_ID)
1843 fluid_synth_api_enter(synth);
1844 result = fluid_synth_sysex_midi_tuning(synth, data, len, response,
1845 response_len, avail_response,
1848 FLUID_API_RETURN(result);
1854 /* Handler for MIDI tuning SYSEX messages */
1856 fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len,
1857 char *response, int *response_len, int avail_response,
1858 int *handled, int dryrun)
1860 int realtime, msgid;
1861 int bank = 0, prog, channels;
1862 double tunedata[128];
1865 int note, frac, frac2;
1867 int i, count, index;
1868 const char *dataptr;
1871 realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME;
1876 case MIDI_SYSEX_TUNING_BULK_DUMP_REQ:
1877 case MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK:
1878 if(data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
1880 if(len != 5 || data[4] & 0x80 || !response)
1885 *response_len = 406;
1890 if(len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response)
1895 *response_len = 407;
1910 if(avail_response < *response_len)
1912 return FLUID_FAILED;
1915 /* Get tuning data, return if tuning not found */
1916 if(fluid_synth_tuning_dump(synth, bank, prog, name, 17, tunedata) == FLUID_FAILED)
1924 *resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME;
1925 *resptr++ = synth->device_id;
1926 *resptr++ = MIDI_SYSEX_MIDI_TUNING_ID;
1927 *resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP;
1929 if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK)
1935 FLUID_STRNCPY(resptr, name, 16);
1938 for(i = 0; i < 128; i++)
1940 note = tunedata[i] / 100.0;
1941 fluid_clip(note, 0, 127);
1943 frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0;
1944 fluid_clip(frac, 0, 16383);
1947 *resptr++ = frac >> 7;
1948 *resptr++ = frac & 0x7F;
1951 if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
1953 /* NOTE: Checksum is not as straight forward as the bank based messages */
1954 chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID
1955 ^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog;
1957 for(i = 21; i < 128 * 3 + 21; i++)
1959 chksum ^= response[i];
1964 for(i = 1, chksum = 0; i < 406; i++)
1966 chksum ^= response[i];
1970 *resptr++ = chksum & 0x7F;
1979 case MIDI_SYSEX_TUNING_NOTE_TUNE:
1980 case MIDI_SYSEX_TUNING_NOTE_TUNE_BANK:
1983 if(msgid == MIDI_SYSEX_TUNING_NOTE_TUNE)
1985 if(len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6)
1992 if(len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80
1993 || len != data[6] * 4 + 7)
2014 for(i = 0, index = 0; i < count; i++)
2029 if(note & 0x80 || frac & 0x80 || frac2 & 0x80)
2034 frac = frac << 7 | frac2;
2036 /* No change pitch value? Doesn't really make sense to send that, but.. */
2037 if(note == 0x7F && frac == 16383)
2042 tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0);
2048 if(fluid_synth_tune_notes(synth, bank, prog, index, keys, tunedata,
2049 realtime) == FLUID_FAILED)
2051 return FLUID_FAILED;
2062 case MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE:
2063 case MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE:
2064 if((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19)
2065 || (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31))
2070 if(data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80)
2085 channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6];
2087 if(msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE)
2089 for(i = 0; i < 12; i++)
2098 tunedata[i] = (int)frac - 64;
2103 for(i = 0; i < 12; i++)
2105 frac = data[i * 2 + 7];
2106 frac2 = data[i * 2 + 8];
2108 if(frac & 0x80 || frac2 & 0x80)
2113 tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0);
2117 if(fluid_synth_activate_octave_tuning(synth, 0, 0, "SYSEX",
2118 tunedata, realtime) == FLUID_FAILED)
2120 return FLUID_FAILED;
2125 for(i = 0; i < 16; i++)
2127 if(channels & (1 << i))
2129 fluid_synth_activate_tuning(synth, i, 0, 0, realtime);
2146 * Turn off all notes on a MIDI channel (put them into release phase).
2147 * @param synth FluidSynth instance
2148 * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2149 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2153 fluid_synth_all_notes_off(fluid_synth_t *synth, int chan)
2157 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2158 fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2159 fluid_synth_api_enter(synth);
2161 if(chan >= synth->midi_channels)
2163 result = FLUID_FAILED;
2167 /* Allowed (even for channel disabled) as chan = -1 selects all channels */
2168 result = fluid_synth_all_notes_off_LOCAL(synth, chan);
2171 FLUID_API_RETURN(result);
2174 /* Local synthesis thread variant of all notes off, (chan=-1 selects all channels) */
2177 fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan)
2179 fluid_voice_t *voice;
2182 for(i = 0; i < synth->polyphony; i++)
2184 voice = synth->voice[i];
2186 if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2188 fluid_voice_noteoff(voice);
2196 * Immediately stop all notes on a MIDI channel (skips release phase).
2197 * @param synth FluidSynth instance
2198 * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2199 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2203 fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan)
2207 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2208 fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2209 fluid_synth_api_enter(synth);
2211 if(chan >= synth->midi_channels)
2213 result = FLUID_FAILED;
2217 /* Allowed (even for channel disabled) as chan = -1 selects all channels */
2218 result = fluid_synth_all_sounds_off_LOCAL(synth, chan);
2221 FLUID_API_RETURN(result);
2224 /* Local synthesis thread variant of all sounds off, (chan=-1 selects all channels) */
2226 fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan)
2228 fluid_voice_t *voice;
2231 for(i = 0; i < synth->polyphony; i++)
2233 voice = synth->voice[i];
2235 if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2237 fluid_voice_off(voice);
2245 * Reset reverb engine
2246 * @param synth FluidSynth instance
2247 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2250 fluid_synth_reset_reverb(fluid_synth_t *synth)
2252 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2253 fluid_synth_api_enter(synth);
2254 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2255 FLUID_API_RETURN(FLUID_OK);
2259 * Reset chorus engine
2260 * @param synth FluidSynth instance
2261 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2264 fluid_synth_reset_chorus(fluid_synth_t *synth)
2266 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2267 fluid_synth_api_enter(synth);
2268 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2269 FLUID_API_RETURN(FLUID_OK);
2274 * Send MIDI system reset command (big red 'panic' button), turns off notes, resets
2275 * controllers and restores initial basic channel configuration.
2276 * @param synth FluidSynth instance
2277 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2280 fluid_synth_system_reset(fluid_synth_t *synth)
2283 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2284 fluid_synth_api_enter(synth);
2285 result = fluid_synth_system_reset_LOCAL(synth);
2286 FLUID_API_RETURN(result);
2289 /* Local variant of the system reset command */
2291 fluid_synth_system_reset_LOCAL(fluid_synth_t *synth)
2295 fluid_synth_all_sounds_off_LOCAL(synth, -1);
2297 for(i = 0; i < synth->midi_channels; i++)
2299 fluid_channel_reset(synth->channel[i]);
2302 /* Basic channel 0, Mode Omni On Poly */
2303 fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
2304 synth->midi_channels);
2306 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2307 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2313 * Update voices on a MIDI channel after a MIDI control change.
2314 * @param synth FluidSynth instance
2315 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2316 * @param is_cc Boolean value indicating if ctrl is a CC controller or not
2317 * @param ctrl MIDI controller value
2318 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2321 fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan, int is_cc, int ctrl)
2323 fluid_voice_t *voice;
2326 for(i = 0; i < synth->polyphony; i++)
2328 voice = synth->voice[i];
2330 if(fluid_voice_get_channel(voice) == chan)
2332 fluid_voice_modulate(voice, is_cc, ctrl);
2340 * Update voices on a MIDI channel after all MIDI controllers have been changed.
2341 * @param synth FluidSynth instance
2342 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2343 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2346 fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan)
2348 fluid_voice_t *voice;
2351 for(i = 0; i < synth->polyphony; i++)
2353 voice = synth->voice[i];
2355 if(fluid_voice_get_channel(voice) == chan)
2357 fluid_voice_modulate_all(voice);
2365 * Set the MIDI channel pressure controller value.
2366 * @param synth FluidSynth instance
2367 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2368 * @param val MIDI channel pressure value (0-127)
2369 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2372 fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val)
2375 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2377 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2379 /* Allowed only on MIDI channel enabled */
2380 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2384 FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
2387 fluid_channel_set_channel_pressure(synth->channel[chan], val);
2388 result = fluid_synth_update_channel_pressure_LOCAL(synth, chan);
2390 FLUID_API_RETURN(result);
2393 /* Updates channel pressure from within synthesis thread */
2395 fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int chan)
2397 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_CHANNELPRESSURE);
2401 * Set the MIDI polyphonic key pressure controller value.
2402 * @param synth FluidSynth instance
2403 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2404 * @param key MIDI key number (0-127)
2405 * @param val MIDI key pressure value (0-127)
2406 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2410 fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val)
2413 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
2414 fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2416 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2418 /* Allowed only on MIDI channel enabled */
2419 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2423 FLUID_LOG(FLUID_INFO, "keypressure\t%d\t%d\t%d", chan, key, val);
2426 fluid_channel_set_key_pressure(synth->channel[chan], key, val);
2427 result = fluid_synth_update_key_pressure_LOCAL(synth, chan, key);
2429 FLUID_API_RETURN(result);
2432 /* Updates key pressure from within synthesis thread */
2434 fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key)
2436 fluid_voice_t *voice;
2438 int result = FLUID_OK;
2440 for(i = 0; i < synth->polyphony; i++)
2442 voice = synth->voice[i];
2444 if(voice->chan == chan && voice->key == key)
2446 result = fluid_voice_modulate(voice, 0, FLUID_MOD_KEYPRESSURE);
2448 if(result != FLUID_OK)
2459 * Set the MIDI pitch bend controller value on a MIDI channel.
2460 * @param synth FluidSynth instance
2461 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2462 * @param val MIDI pitch bend value (0-16383 with 8192 being center)
2463 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2466 fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val)
2469 fluid_return_val_if_fail(val >= 0 && val <= 16383, FLUID_FAILED);
2470 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2472 /* Allowed only on MIDI channel enabled */
2473 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2477 FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val);
2480 fluid_channel_set_pitch_bend(synth->channel[chan], val);
2481 result = fluid_synth_update_pitch_bend_LOCAL(synth, chan);
2483 FLUID_API_RETURN(result);
2486 /* Local synthesis thread variant of pitch bend */
2488 fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan)
2490 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEEL);
2494 * Get the MIDI pitch bend controller value on a MIDI channel.
2495 * @param synth FluidSynth instance
2496 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2497 * @param ppitch_bend Location to store MIDI pitch bend value (0-16383 with
2498 * 8192 being center)
2499 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2502 fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend)
2505 fluid_return_val_if_fail(ppitch_bend != NULL, FLUID_FAILED);
2506 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2508 /* Allowed only on MIDI channel enabled */
2509 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2511 *ppitch_bend = fluid_channel_get_pitch_bend(synth->channel[chan]);
2514 FLUID_API_RETURN(result);
2518 * Set MIDI pitch wheel sensitivity on a MIDI channel.
2519 * @param synth FluidSynth instance
2520 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2521 * @param val Pitch wheel sensitivity value in semitones
2522 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2525 fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val)
2528 fluid_return_val_if_fail(val >= 0 && val <= 72, FLUID_FAILED); /* 6 octaves!? Better than no limit.. */
2529 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2531 /* Allowed only on MIDI channel enabled */
2532 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2536 FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val);
2539 fluid_channel_set_pitch_wheel_sensitivity(synth->channel[chan], val);
2540 result = fluid_synth_update_pitch_wheel_sens_LOCAL(synth, chan);
2542 FLUID_API_RETURN(result);
2545 /* Local synthesis thread variant of set pitch wheel sensitivity */
2547 fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan)
2549 return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEELSENS);
2553 * Get MIDI pitch wheel sensitivity on a MIDI channel.
2554 * @param synth FluidSynth instance
2555 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2556 * @param pval Location to store pitch wheel sensitivity value in semitones
2557 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2558 * @since Sometime AFTER v1.0 API freeze.
2561 fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval)
2564 fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
2565 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2567 /* Allowed only on MIDI channel enabled */
2568 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2570 *pval = fluid_channel_get_pitch_wheel_sensitivity(synth->channel[chan]);
2573 FLUID_API_RETURN(result);
2577 * Assign a preset to a MIDI channel.
2578 * @param synth FluidSynth instance
2579 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2580 * @param preset Preset to assign to channel or NULL to clear (ownership is taken over)
2581 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2584 fluid_synth_set_preset(fluid_synth_t *synth, int chan, fluid_preset_t *preset)
2586 fluid_channel_t *channel;
2588 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2589 fluid_return_val_if_fail(chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
2591 channel = synth->channel[chan];
2593 return fluid_channel_set_preset(channel, preset);
2596 /* Get a preset by SoundFont, bank and program numbers.
2597 * Returns preset pointer or NULL.
2599 static fluid_preset_t *
2600 fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
2601 int banknum, int prognum)
2603 fluid_sfont_t *sfont;
2606 /* 128 indicates an "unset" operation" */
2607 if(prognum == FLUID_UNSET_PROGRAM)
2612 for(list = synth->sfont; list; list = fluid_list_next(list))
2614 sfont = fluid_list_get(list);
2616 if(fluid_sfont_get_id(sfont) == sfontnum)
2618 return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2625 /* Get a preset by SoundFont name, bank and program.
2626 * Returns preset pointer or NULL.
2628 static fluid_preset_t *
2629 fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname,
2630 int banknum, int prognum)
2632 fluid_sfont_t *sfont;
2635 for(list = synth->sfont; list; list = fluid_list_next(list))
2637 sfont = fluid_list_get(list);
2639 if(FLUID_STRCMP(fluid_sfont_get_name(sfont), sfontname) == 0)
2641 return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2648 /* Find a preset by bank and program numbers.
2649 * Returns preset pointer or NULL.
2652 fluid_synth_find_preset(fluid_synth_t *synth, int banknum,
2655 fluid_preset_t *preset;
2656 fluid_sfont_t *sfont;
2659 for(list = synth->sfont; list; list = fluid_list_next(list))
2661 sfont = fluid_list_get(list);
2663 preset = fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
2675 * Send a program change event on a MIDI channel.
2676 * @param synth FluidSynth instance
2677 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2678 * @param prognum MIDI program number (0-127)
2679 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2681 /* FIXME - Currently not real-time safe, due to preset allocation and mutex lock,
2682 * and may be called from within synthesis context. */
2684 /* As of 1.1.1 prognum can be set to 128 to unset the preset. Not documented
2685 * since fluid_synth_unset_program() should be used instead. */
2687 fluid_synth_program_change(fluid_synth_t *synth, int chan, int prognum)
2689 fluid_preset_t *preset = NULL;
2690 fluid_channel_t *channel;
2691 int subst_bank, subst_prog, banknum = 0, result = FLUID_FAILED;
2693 fluid_return_val_if_fail(prognum >= 0 && prognum <= 128, FLUID_FAILED);
2694 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2696 /* Allowed only on MIDI channel enabled */
2697 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2699 channel = synth->channel[chan];
2701 if(channel->channel_type == CHANNEL_TYPE_DRUM)
2703 banknum = DRUM_INST_BANK;
2707 fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
2712 FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
2715 /* I think this is a hack for MIDI files that do bank changes in GM mode.
2716 * Proper way to handle this would probably be to ignore bank changes when in
2718 * This is now possible by setting synth.midi-bank-select=gm, but let the hack
2719 * stay for the time being. - DH
2721 if(prognum != FLUID_UNSET_PROGRAM)
2723 subst_bank = banknum;
2724 subst_prog = prognum;
2726 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2728 /* Fallback to another preset if not found */
2731 /* Percussion: Fallback to preset 0 in percussion bank */
2732 if(channel->channel_type == CHANNEL_TYPE_DRUM)
2735 subst_bank = DRUM_INST_BANK;
2736 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2738 /* Melodic instrument */
2741 /* Fallback first to bank 0:prognum */
2743 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2745 /* Fallback to first preset in bank 0 (usually piano...) */
2749 preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
2755 FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
2756 chan, banknum, prognum, subst_bank, subst_prog);
2760 FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]", chan, banknum, prognum);
2765 /* Assign the SoundFont ID and program number to the channel */
2766 fluid_channel_set_sfont_bank_prog(channel, preset ? fluid_sfont_get_id(preset->sfont) : 0,
2768 result = fluid_synth_set_preset(synth, chan, preset);
2770 FLUID_API_RETURN(result);
2774 * Set instrument bank number on a MIDI channel.
2775 * @param synth FluidSynth instance
2776 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2777 * @param bank MIDI bank number
2778 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2779 * @note This function does not change the instrument currently assigned to \c chan,
2780 * as it is usually called prior to fluid_synth_program_change(). If you still want
2781 * instrument changes to take effect immediately, call fluid_synth_program_reset()
2782 * after having set up the bank configuration.
2786 fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank)
2789 fluid_return_val_if_fail(bank <= 16383, FLUID_FAILED);
2790 fluid_return_val_if_fail(bank >= 0, FLUID_FAILED);
2791 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2793 /* Allowed only on MIDI channel enabled */
2794 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2796 fluid_channel_set_sfont_bank_prog(synth->channel[chan], -1, bank, -1);
2799 FLUID_API_RETURN(result);
2803 * Set SoundFont ID on a MIDI channel.
2804 * @param synth FluidSynth instance
2805 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2806 * @param sfont_id ID of a loaded SoundFont
2807 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2808 * @note This function does not change the instrument currently assigned to \c chan,
2809 * as it is usually called prior to fluid_synth_bank_select() or fluid_synth_program_change().
2810 * If you still want instrument changes to take effect immediately, call fluid_synth_program_reset()
2811 * after having selected the soundfont.
2814 fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id)
2817 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2819 /* Allowed only on MIDI channel enabled */
2820 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2822 fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
2825 FLUID_API_RETURN(result);
2829 * Set the preset of a MIDI channel to an unassigned state.
2830 * @param synth FluidSynth instance
2831 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2832 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2835 * @note Channel retains its SoundFont ID and bank numbers, while the program
2836 * number is set to an "unset" state. MIDI program changes may re-assign a
2837 * preset if one matches.
2840 fluid_synth_unset_program(fluid_synth_t *synth, int chan)
2842 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2843 FLUID_API_RETURN(fluid_synth_program_change(synth, chan, FLUID_UNSET_PROGRAM));
2847 * Get current SoundFont ID, bank number and program number for a MIDI channel.
2848 * @param synth FluidSynth instance
2849 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2850 * @param sfont_id Location to store SoundFont ID
2851 * @param bank_num Location to store MIDI bank number
2852 * @param preset_num Location to store MIDI program number
2853 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2856 fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id,
2857 int *bank_num, int *preset_num)
2860 fluid_channel_t *channel;
2862 fluid_return_val_if_fail(sfont_id != NULL, FLUID_FAILED);
2863 fluid_return_val_if_fail(bank_num != NULL, FLUID_FAILED);
2864 fluid_return_val_if_fail(preset_num != NULL, FLUID_FAILED);
2865 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2867 /* Allowed only on MIDI channel enabled */
2868 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2870 channel = synth->channel[chan];
2871 fluid_channel_get_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
2873 /* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */
2874 if(*preset_num == FLUID_UNSET_PROGRAM)
2881 FLUID_API_RETURN(result);
2885 * Select an instrument on a MIDI channel by SoundFont ID, bank and program numbers.
2886 * @param synth FluidSynth instance
2887 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2888 * @param sfont_id ID of a loaded SoundFont
2889 * @param bank_num MIDI bank number
2890 * @param preset_num MIDI program number
2891 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2894 fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
2895 int bank_num, int preset_num)
2897 fluid_preset_t *preset = NULL;
2898 fluid_channel_t *channel;
2900 fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
2901 fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
2903 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2905 /* Allowed only on MIDI channel enabled */
2906 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2908 channel = synth->channel[chan];
2910 preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
2914 FLUID_LOG(FLUID_ERR,
2915 "There is no preset with bank number %d and preset number %d in SoundFont %d",
2916 bank_num, preset_num, sfont_id);
2917 FLUID_API_RETURN(FLUID_FAILED);
2920 /* Assign the new SoundFont ID, bank and program number to the channel */
2921 fluid_channel_set_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
2922 result = fluid_synth_set_preset(synth, chan, preset);
2924 FLUID_API_RETURN(result);
2928 * Select an instrument on a MIDI channel by SoundFont name, bank and program numbers.
2929 * @param synth FluidSynth instance
2930 * @param chan MIDI channel number (0 to MIDI channel count - 1)
2931 * @param sfont_name Name of a loaded SoundFont
2932 * @param bank_num MIDI bank number
2933 * @param preset_num MIDI program number
2934 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2938 fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan,
2939 const char *sfont_name, int bank_num,
2942 fluid_preset_t *preset = NULL;
2943 fluid_channel_t *channel;
2945 fluid_return_val_if_fail(sfont_name != NULL, FLUID_FAILED);
2946 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2948 /* Allowed only on MIDI channel enabled */
2949 FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2951 channel = synth->channel[chan];
2953 preset = fluid_synth_get_preset_by_sfont_name(synth, sfont_name, bank_num,
2958 FLUID_LOG(FLUID_ERR,
2959 "There is no preset with bank number %d and preset number %d in SoundFont %s",
2960 bank_num, preset_num, sfont_name);
2961 FLUID_API_RETURN(FLUID_FAILED);
2964 /* Assign the new SoundFont ID, bank and program number to the channel */
2965 fluid_channel_set_sfont_bank_prog(channel, fluid_sfont_get_id(preset->sfont),
2966 bank_num, preset_num);
2967 result = fluid_synth_set_preset(synth, chan, preset);
2969 FLUID_API_RETURN(result);
2973 * This function assures that every MIDI channel has a valid preset
2974 * (NULL is okay). This function is called after a SoundFont is
2975 * unloaded or reloaded.
2978 fluid_synth_update_presets(fluid_synth_t *synth)
2980 fluid_channel_t *channel;
2981 fluid_preset_t *preset;
2982 int sfont, bank, prog;
2985 for(chan = 0; chan < synth->midi_channels; chan++)
2987 channel = synth->channel[chan];
2988 fluid_channel_get_sfont_bank_prog(channel, &sfont, &bank, &prog);
2989 preset = fluid_synth_get_preset(synth, sfont, bank, prog);
2990 fluid_synth_set_preset(synth, chan, preset);
2994 /* Handler for synth.sample-rate setting. */
2996 fluid_synth_handle_sample_rate(void *data, const char *name, double value)
2998 fluid_synth_t *synth = (fluid_synth_t *)data;
2999 fluid_synth_set_sample_rate(synth, (float) value);
3004 * Set sample rate of the synth.
3005 * @note This function should only be used when no voices or notes are active.
3006 * @param synth FluidSynth instance
3007 * @param sample_rate New sample rate (Hz)
3011 fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate)
3014 fluid_return_if_fail(synth != NULL);
3015 fluid_synth_api_enter(synth);
3016 fluid_clip(sample_rate, 8000.0f, 96000.0f);
3017 synth->sample_rate = sample_rate;
3019 synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
3021 for(i = 0; i < synth->polyphony; i++)
3023 fluid_voice_set_output_rate(synth->voice[i], sample_rate);
3026 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate,
3028 fluid_synth_api_exit(synth);
3032 /* Handler for synth.gain setting. */
3034 fluid_synth_handle_gain(void *data, const char *name, double value)
3036 fluid_synth_t *synth = (fluid_synth_t *)data;
3037 fluid_synth_set_gain(synth, (float) value);
3041 * Set synth output gain value.
3042 * @param synth FluidSynth instance
3043 * @param gain Gain value (function clamps value to the range 0.0 to 10.0)
3046 fluid_synth_set_gain(fluid_synth_t *synth, float gain)
3048 fluid_return_if_fail(synth != NULL);
3049 fluid_synth_api_enter(synth);
3051 fluid_clip(gain, 0.0f, 10.0f);
3054 fluid_synth_update_gain_LOCAL(synth);
3055 fluid_synth_api_exit(synth);
3058 /* Called by synthesis thread to update the gain in all voices */
3060 fluid_synth_update_gain_LOCAL(fluid_synth_t *synth)
3062 fluid_voice_t *voice;
3068 for(i = 0; i < synth->polyphony; i++)
3070 voice = synth->voice[i];
3072 if(fluid_voice_is_playing(voice))
3074 fluid_voice_set_gain(voice, gain);
3080 * Get synth output gain value.
3081 * @param synth FluidSynth instance
3082 * @return Synth gain value (0.0 to 10.0)
3085 fluid_synth_get_gain(fluid_synth_t *synth)
3088 fluid_return_val_if_fail(synth != NULL, 0.0);
3089 fluid_synth_api_enter(synth);
3091 result = synth->gain;
3092 FLUID_API_RETURN(result);
3096 * Handler for synth.polyphony setting.
3099 fluid_synth_handle_polyphony(void *data, const char *name, int value)
3101 fluid_synth_t *synth = (fluid_synth_t *)data;
3102 fluid_synth_set_polyphony(synth, value);
3106 * Set synthesizer polyphony (max number of voices).
3107 * @param synth FluidSynth instance
3108 * @param polyphony Polyphony to assign
3109 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3113 fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony)
3116 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3117 fluid_return_val_if_fail(polyphony >= 1 && polyphony <= 65535, FLUID_FAILED);
3118 fluid_synth_api_enter(synth);
3120 result = fluid_synth_update_polyphony_LOCAL(synth, polyphony);
3122 FLUID_API_RETURN(result);
3125 /* Called by synthesis thread to update the polyphony value */
3127 fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony)
3129 fluid_voice_t *voice;
3132 if(new_polyphony > synth->nvoice)
3134 /* Create more voices */
3135 fluid_voice_t **new_voices = FLUID_REALLOC(synth->voice,
3136 sizeof(fluid_voice_t *) * new_polyphony);
3138 if(new_voices == NULL)
3140 return FLUID_FAILED;
3143 synth->voice = new_voices;
3145 for(i = synth->nvoice; i < new_polyphony; i++)
3147 synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
3149 if(synth->voice[i] == NULL)
3151 return FLUID_FAILED;
3154 fluid_voice_set_custom_filter(synth->voice[i], synth->custom_filter_type, synth->custom_filter_flags);
3157 synth->nvoice = new_polyphony;
3160 synth->polyphony = new_polyphony;
3162 /* turn off any voices above the new limit */
3163 for(i = synth->polyphony; i < synth->nvoice; i++)
3165 voice = synth->voice[i];
3167 if(fluid_voice_is_playing(voice))
3169 fluid_voice_off(voice);
3173 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
3174 synth->polyphony, 0.0f);
3180 * Get current synthesizer polyphony (max number of voices).
3181 * @param synth FluidSynth instance
3182 * @return Synth polyphony value.
3186 fluid_synth_get_polyphony(fluid_synth_t *synth)
3189 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3190 fluid_synth_api_enter(synth);
3192 result = synth->polyphony;
3193 FLUID_API_RETURN(result);
3197 * @brief Get current number of active voices.
3199 * I.e. the no. of voices that have been
3200 * started and have not yet finished. Unless called from synthesis context,
3201 * this number does not necessarily have to be equal to the number of voices
3202 * currently processed by the DSP loop, see below.
3203 * @param synth FluidSynth instance
3204 * @return Number of currently active voices.
3207 * @note To generate accurate continuous statistics of the voice count, caller
3208 * should ensure this function is called synchronously with the audio synthesis
3209 * process. This can be done in the new_fluid_audio_driver2() audio callback
3210 * function for example. Otherwise every call to this function may return different
3211 * voice counts as it may change after any (concurrent) call to fluid_synth_write_*() made by
3212 * e.g. an audio driver or the applications audio rendering thread.
3215 fluid_synth_get_active_voice_count(fluid_synth_t *synth)
3218 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3219 fluid_synth_api_enter(synth);
3221 result = synth->active_voice_count;
3222 FLUID_API_RETURN(result);
3226 * Get the internal synthesis buffer size value.
3227 * @param synth FluidSynth instance
3228 * @return Internal buffer size in audio frames.
3230 * Audio is synthesized this number of frames at a time. Defaults to 64 frames.
3233 fluid_synth_get_internal_bufsize(fluid_synth_t *synth)
3235 return FLUID_BUFSIZE;
3239 * Resend a bank select and a program change for every channel and assign corresponding instruments.
3240 * @param synth FluidSynth instance
3241 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3243 * This function is called mainly after a SoundFont has been loaded,
3244 * unloaded or reloaded.
3247 fluid_synth_program_reset(fluid_synth_t *synth)
3250 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3251 fluid_synth_api_enter(synth);
3253 /* try to set the correct presets */
3254 for(i = 0; i < synth->midi_channels; i++)
3256 fluid_channel_get_sfont_bank_prog(synth->channel[i], NULL, NULL, &prog);
3257 fluid_synth_program_change(synth, i, prog);
3260 FLUID_API_RETURN(FLUID_OK);
3264 * Synthesize a block of floating point audio to separate audio buffers (multichannel rendering). First effect channel used by reverb, second for chorus.
3265 * @param synth FluidSynth instance
3266 * @param len Count of audio frames to synthesize
3267 * @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)
3268 * @param right Array of float buffers to store right channel of planar audio (size: dito)
3269 * @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)
3270 * @param fx_right Since 1.1.7: If not \c NULL, array of float buffers to store right effect channels (size: dito)
3271 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3273 * @note Should only be called from synthesis thread.
3275 * @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().
3279 const int FramesToRender = 64;
3281 // retrieve number of stereo audio channels
3282 fluid_settings_getint(settings, "synth.audio-channels", &channels);
3284 // we need twice as many (mono-)buffers
3287 // 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
3288 float** mix_buf = new float*[channels];
3289 for(int i = 0; i < channels; i++)
3291 mix_buf[i] = new float[FramesToRender];
3294 // retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan) and chrous (second chan))
3295 fluid_settings_getint(settings, "synth.effects-channels", &channels);
3298 float** fx_buf = new float*[channels];
3299 for(int i = 0; i < channels; i++)
3301 fx_buf[i] = new float[FramesToRender];
3304 float** mix_buf_l = mix_buf;
3305 float** mix_buf_r = &mix_buf[channels/2];
3307 float** fx_buf_l = fx_buf;
3308 float** fx_buf_r = &fx_buf[channels/2];
3310 fluid_synth_nwrite_float(synth, FramesToRender, mix_buf_l, mix_buf_r, fx_buf_l, fx_buf_r)
3314 fluid_synth_nwrite_float(fluid_synth_t *synth, int len,
3315 float **left, float **right,
3316 float **fx_left, float **fx_right)
3318 fluid_real_t *left_in, *fx_left_in;
3319 fluid_real_t *right_in, *fx_right_in;
3320 double time = fluid_utime();
3321 int i, num, available, count;
3327 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3328 fluid_return_val_if_fail(left != NULL, FLUID_FAILED);
3329 fluid_return_val_if_fail(right != NULL, FLUID_FAILED);
3331 /* First, take what's still available in the buffer */
3335 if(synth->cur < FLUID_BUFSIZE)
3337 available = FLUID_BUFSIZE - synth->cur;
3338 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3339 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3341 num = (available > len) ? len : available;
3343 bytes = num * sizeof(float);
3346 for(i = 0; i < synth->audio_channels; i++)
3349 FLUID_MEMCPY(left[i], &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3350 FLUID_MEMCPY(right[i], &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3354 for(j = 0; j < num; j++)
3356 left[i][j] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3357 right[i][j] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3363 for(i = 0; i < synth->effects_channels; i++)
3369 FLUID_MEMCPY(fx_left[i], &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3372 if(fx_right != NULL)
3374 FLUID_MEMCPY(fx_right[i], &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3382 for(j = 0; j < num; j++)
3384 fx_left[i][j] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3388 if(fx_right != NULL)
3390 for(j = 0; j < num; j++)
3392 fx_right[i][j] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3400 num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3403 /* Then, run one_block() and copy till we have 'len' samples */
3406 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0);
3407 fluid_synth_render_blocks(synth, 1); // TODO:
3408 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3409 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3411 num = (FLUID_BUFSIZE > len - count) ? len - count : FLUID_BUFSIZE;
3413 bytes = num * sizeof(float);
3416 for(i = 0; i < synth->audio_channels; i++)
3419 FLUID_MEMCPY(left[i] + count, &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3420 FLUID_MEMCPY(right[i] + count, &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3424 for(j = 0; j < num; j++)
3426 left[i][j + count] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3427 right[i][j + count] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3433 for(i = 0; i < synth->effects_channels; i++)
3439 FLUID_MEMCPY(fx_left[i] + count, &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3442 if(fx_right != NULL)
3444 FLUID_MEMCPY(fx_right[i] + count, &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3452 for(j = 0; j < num; j++)
3454 fx_left[i][j + count] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3458 if(fx_right != NULL)
3460 for(j = 0; j < num; j++)
3462 fx_right[i][j + count] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3474 time = fluid_utime() - time;
3475 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3476 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3482 * mixes the samples of \p in to \p out
3484 * @param out the output sample buffer to mix to
3485 * @param ooff sample offset in \p out
3486 * @param in the rvoice_mixer input sample buffer to mix from
3487 * @param ioff sample offset in \p in
3488 * @param buf_idx the sample buffer index of \p in to mix from
3489 * @param num number of samples to mix
3491 static FLUID_INLINE void fluid_synth_mix_single_buffer(float *FLUID_RESTRICT out,
3493 const fluid_real_t *FLUID_RESTRICT in,
3501 for(j = 0; j < num; j++)
3503 out[j + ooff] += (float) in[buf_idx * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + ioff];
3509 * @brief Synthesize floating point audio to stereo audio channels (implements the default interface #fluid_audio_func_t).
3511 * Synthesize and <strong>mix</strong> audio to a given number of planar audio buffers.
3512 * Therefore pass <code>nout = N*2</code> float buffers to \p out in order to render
3513 * the synthesized audio to \p N stereo channels. Each float buffer must be
3514 * able to hold \p len elements.
3516 * \p out contains an array of planar buffers for normal, dry, stereo
3517 * audio (alternating left and right). Like:
3519 out[0] = left_buffer_audio_channel_0
3520 out[1] = right_buffer_audio_channel_0
3521 out[2] = left_buffer_audio_channel_1
3522 out[3] = right_buffer_audio_channel_1
3524 out[ (i * 2 + 0) % nout ] = left_buffer_audio_channel_i
3525 out[ (i * 2 + 1) % nout ] = right_buffer_audio_channel_i
3528 * for zero-based channel index \p i.
3529 * The buffer layout of \p fx used for storing effects
3530 * like reverb and chorus looks similar:
3532 fx[0] = left_buffer_channel_of_reverb_unit_0
3533 fx[1] = right_buffer_channel_of_reverb_unit_0
3534 fx[2] = left_buffer_channel_of_chorus_unit_0
3535 fx[3] = right_buffer_channel_of_chorus_unit_0
3536 fx[4] = left_buffer_channel_of_reverb_unit_1
3537 fx[5] = right_buffer_channel_of_reverb_unit_1
3538 fx[6] = left_buffer_channel_of_chorus_unit_1
3539 fx[7] = right_buffer_channel_of_chorus_unit_1
3540 fx[8] = left_buffer_channel_of_reverb_unit_2
3542 fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 0) % nfx ] = left_buffer_for_effect_channel_j_of_unit_k
3543 fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 1) % nfx ] = right_buffer_for_effect_channel_j_of_unit_k
3545 * where <code>0 <= k < fluid_synth_count_effects_groups()</code> is a zero-based index denoting the effects unit and
3546 * <code>0 <= j < fluid_synth_count_effects_channels()</code> is a zero-based index denoting the effect channel within
3549 * Any voice playing is assigned to audio channels based on the MIDI channel its playing on. Let \p chan be the
3550 * zero-based MIDI channel index an arbitrary voice is playing on. To determine the audio channel and effects unit it is
3551 * going to be rendered to use:
3553 * <code>i = chan % fluid_synth_count_audio_groups()</code>
3555 * <code>k = chan % fluid_synth_count_effects_groups()</code>
3557 * @param synth FluidSynth instance
3558 * @param len Count of audio frames to synthesize and store in every single buffer provided by \p out and \p fx.
3559 * @param nfx Count of arrays in \c fx. Must be a multiple of 2 (because of stereo)
3560 * and in the range <code>0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
3561 * @param fx Array of buffers to store effects audio to. Buffers may
3562 alias with buffers of \c out. NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
3563 * @param nout Count of arrays in \c out. Must be a multiple of 2
3564 (because of stereo) and in the range <code>0 <= nout/2 <= fluid_synth_count_audio_channels()</code>.
3565 * @param out Array of buffers to store (dry) audio to. Buffers may
3566 alias with buffers of \c fx. NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
3567 * @return #FLUID_OK on success, #FLUID_FAILED otherwise.
3570 * @note The owner of the sample buffers must zero them out before calling this
3571 * function, because any synthesized audio is mixed (i.e. added) to the buffers.
3572 * E.g. if fluid_synth_process() is called from a custom audio driver process function
3573 * (see new_fluid_audio_driver2()), the audio driver takes care of zeroing the buffers.
3577 * @note No matter how many buffers you pass in, fluid_synth_process()
3578 * will always render all audio channels to the
3579 * buffers in \c out and all effects channels to the
3580 * buffers in \c fx, provided that <code>nout > 0</code> and <code>nfx > 0</code> respectively. If
3581 * <code>nout/2 < fluid_synth_count_audio_channels()</code> it will wrap around. Same
3582 * is true for effects audio if <code>nfx/2 < (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
3583 * See usage examples below.
3587 * @note Should only be called from synthesis thread.
3591 fluid_synth_process(fluid_synth_t *synth, int len, int nfx, float *fx[],
3592 int nout, float *out[])
3594 fluid_real_t *left_in, *fx_left_in;
3595 fluid_real_t *right_in, *fx_right_in;
3596 int nfxchan, nfxunits, naudchan;
3598 double time = fluid_utime();
3599 int i, f, num, count;
3603 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3604 fluid_return_val_if_fail(nfx % 2 == 0, FLUID_FAILED);
3605 fluid_return_val_if_fail(nout % 2 == 0, FLUID_FAILED);
3607 nfxchan = synth->effects_channels;
3608 nfxunits = synth->effects_groups;
3609 naudchan = synth->audio_channels;
3611 fluid_return_val_if_fail(0 <= nfx / 2 && nfx / 2 <= nfxchan * nfxunits, FLUID_FAILED);
3612 fluid_return_val_if_fail(0 <= nout / 2 && nout / 2 <= naudchan, FLUID_FAILED);
3614 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3615 fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3616 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, FALSE);
3619 /* First, take what's still available in the buffer */
3623 if(synth->cur < FLUID_BUFSIZE)
3625 int available = FLUID_BUFSIZE - synth->cur;
3626 num = (available > len) ? len : available;
3630 for(i = 0; i < naudchan; i++)
3632 float *out_buf = out[(i * 2) % nout];
3633 fluid_synth_mix_single_buffer(out_buf, 0, left_in, synth->cur, i, num);
3635 out_buf = out[(i * 2 + 1) % nout];
3636 fluid_synth_mix_single_buffer(out_buf, 0, right_in, synth->cur, i, num);
3642 // loop over all effects units
3643 for(f = 0; f < nfxunits; f++)
3645 // write out all effects (i.e. reverb and chorus)
3646 for(i = 0; i < nfxchan; i++)
3648 int buf_idx = f * nfxchan + i;
3650 float *out_buf = fx[(buf_idx * 2) % nfx];
3651 fluid_synth_mix_single_buffer(out_buf, 0, fx_left_in, synth->cur, buf_idx, num);
3653 out_buf = fx[(buf_idx * 2 + 1) % nfx];
3654 fluid_synth_mix_single_buffer(out_buf, 0, fx_right_in, synth->cur, buf_idx, num);
3660 num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3663 /* Then, render blocks and copy till we have 'len' samples */
3666 int blocksleft = (len - count + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3667 int blockcount = fluid_synth_render_blocks(synth, blocksleft);
3669 num = (blockcount * FLUID_BUFSIZE > len - count) ? len - count : blockcount * FLUID_BUFSIZE;
3673 for(i = 0; i < naudchan; i++)
3675 float *out_buf = out[(i * 2) % nout];
3676 fluid_synth_mix_single_buffer(out_buf, count, left_in, 0, i, num);
3678 out_buf = out[(i * 2 + 1) % nout];
3679 fluid_synth_mix_single_buffer(out_buf, count, right_in, 0, i, num);
3685 // loop over all effects units
3686 for(f = 0; f < nfxunits; f++)
3688 // write out all effects (i.e. reverb and chorus)
3689 for(i = 0; i < nfxchan; i++)
3691 int buf_idx = f * nfxchan + i;
3693 float *out_buf = fx[(buf_idx * 2) % nfx];
3694 fluid_synth_mix_single_buffer(out_buf, count, fx_left_in, 0, buf_idx, num);
3696 out_buf = fx[(buf_idx * 2 + 1) % nfx];
3697 fluid_synth_mix_single_buffer(out_buf, count, fx_right_in, 0, buf_idx, num);
3707 time = fluid_utime() - time;
3708 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3709 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3715 * Synthesize a block of floating point audio samples to audio buffers.
3716 * @param synth FluidSynth instance
3717 * @param len Count of audio frames to synthesize
3718 * @param lout Array of floats to store left channel of audio
3719 * @param loff Offset index in 'lout' for first sample
3720 * @param lincr Increment between samples stored to 'lout'
3721 * @param rout Array of floats to store right channel of audio
3722 * @param roff Offset index in 'rout' for first sample
3723 * @param rincr Increment between samples stored to 'rout'
3724 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3726 * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
3727 * lincr = 2, rincr = 2).
3729 * @note Should only be called from synthesis thread.
3730 * @note Reverb and Chorus are mixed to \c lout resp. \c rout.
3733 fluid_synth_write_float(fluid_synth_t *synth, int len,
3734 void *lout, int loff, int lincr,
3735 void *rout, int roff, int rincr)
3738 float *left_out = (float *) lout;
3739 float *right_out = (float *) rout;
3740 fluid_real_t *left_in;
3741 fluid_real_t *right_in;
3742 double time = fluid_utime();
3745 fluid_profile_ref_var(prof_ref);
3747 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3748 fluid_return_val_if_fail(lout != NULL, FLUID_FAILED);
3749 fluid_return_val_if_fail(rout != NULL, FLUID_FAILED);
3751 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
3753 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3755 for(i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr)
3757 /* fill up the buffers as needed */
3758 if(l >= synth->curmax)
3760 int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3761 synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
3762 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3767 left_out[j] = (float) left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l];
3768 right_out[k] = (float) right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l];
3773 time = fluid_utime() - time;
3774 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3775 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3777 fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
3778 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
3783 #define DITHER_SIZE 48000
3784 #define DITHER_CHANNELS 2
3786 static float rand_table[DITHER_CHANNELS][DITHER_SIZE];
3788 /* Init dither table */
3795 for(c = 0; c < DITHER_CHANNELS; c++)
3799 for(i = 0; i < DITHER_SIZE - 1; i++)
3801 d = rand() / (float)RAND_MAX - 0.5f;
3802 rand_table[c][i] = d - dp;
3806 rand_table[c][DITHER_SIZE - 1] = 0 - dp;
3810 /* A portable replacement for roundf(), seems it may actually be faster too! */
3811 static FLUID_INLINE int
3816 return (int)(x + 0.5f);
3820 return (int)(x - 0.5f);
3825 * Synthesize a block of 16 bit audio samples to audio buffers.
3826 * @param synth FluidSynth instance
3827 * @param len Count of audio frames to synthesize
3828 * @param lout Array of 16 bit words to store left channel of audio
3829 * @param loff Offset index in 'lout' for first sample
3830 * @param lincr Increment between samples stored to 'lout'
3831 * @param rout Array of 16 bit words to store right channel of audio
3832 * @param roff Offset index in 'rout' for first sample
3833 * @param rincr Increment between samples stored to 'rout'
3834 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3836 * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
3837 * lincr = 2, rincr = 2).
3839 * @note Should only be called from synthesis thread.
3840 * @note Reverb and Chorus are mixed to \c lout resp. \c rout.
3841 * @note Dithering is performed when converting from internal floating point to
3845 fluid_synth_write_s16(fluid_synth_t *synth, int len,
3846 void *lout, int loff, int lincr,
3847 void *rout, int roff, int rincr)
3850 signed short *left_out = (signed short *) lout;
3851 signed short *right_out = (signed short *) rout;
3852 fluid_real_t *left_in;
3853 fluid_real_t *right_in;
3854 fluid_real_t left_sample;
3855 fluid_real_t right_sample;
3856 double time = fluid_utime();
3860 fluid_profile_ref_var(prof_ref);
3862 fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
3863 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3866 di = synth->dither_index;
3868 for(i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr)
3871 /* fill up the buffers as needed */
3872 if(cur >= synth->curmax)
3874 int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
3875 synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
3876 fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3880 left_sample = roundi(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]);
3881 right_sample = roundi(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]);
3885 if(di >= DITHER_SIZE)
3890 /* digital clipping */
3891 if(left_sample > 32767.0f)
3893 left_sample = 32767.0f;
3896 if(left_sample < -32768.0f)
3898 left_sample = -32768.0f;
3901 if(right_sample > 32767.0f)
3903 right_sample = 32767.0f;
3906 if(right_sample < -32768.0f)
3908 right_sample = -32768.0f;
3911 left_out[j] = (signed short) left_sample;
3912 right_out[k] = (signed short) right_sample;
3916 synth->dither_index = di; /* keep dither buffer continous */
3918 time = fluid_utime() - time;
3919 cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
3920 fluid_atomic_float_set(&synth->cpu_load, cpu_load);
3922 fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
3923 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
3929 * Converts stereo floating point sample data to signed 16 bit data with dithering.
3930 * @param dither_index Pointer to an integer which should be initialized to 0
3931 * before the first call and passed unmodified to additional calls which are
3932 * part of the same synthesis output.
3933 * @param len Length in frames to convert
3934 * @param lin Buffer of left audio samples to convert from
3935 * @param rin Buffer of right audio samples to convert from
3936 * @param lout Array of 16 bit words to store left channel of audio
3937 * @param loff Offset index in 'lout' for first sample
3938 * @param lincr Increment between samples stored to 'lout'
3939 * @param rout Array of 16 bit words to store right channel of audio
3940 * @param roff Offset index in 'rout' for first sample
3941 * @param rincr Increment between samples stored to 'rout'
3943 * @note Currently private to libfluidsynth.
3946 fluid_synth_dither_s16(int *dither_index, int len, float *lin, float *rin,
3947 void *lout, int loff, int lincr,
3948 void *rout, int roff, int rincr)
3951 signed short *left_out = (signed short *) lout;
3952 signed short *right_out = (signed short *) rout;
3953 fluid_real_t left_sample;
3954 fluid_real_t right_sample;
3955 int di = *dither_index;
3956 fluid_profile_ref_var(prof_ref);
3958 for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr)
3961 left_sample = roundi(lin[i] * 32766.0f + rand_table[0][di]);
3962 right_sample = roundi(rin[i] * 32766.0f + rand_table[1][di]);
3966 if(di >= DITHER_SIZE)
3971 /* digital clipping */
3972 if(left_sample > 32767.0f)
3974 left_sample = 32767.0f;
3977 if(left_sample < -32768.0f)
3979 left_sample = -32768.0f;
3982 if(right_sample > 32767.0f)
3984 right_sample = 32767.0f;
3987 if(right_sample < -32768.0f)
3989 right_sample = -32768.0f;
3992 left_out[j] = (signed short) left_sample;
3993 right_out[k] = (signed short) right_sample;
3996 *dither_index = di; /* keep dither buffer continous */
3998 fluid_profile(FLUID_PROF_WRITE, prof_ref, 0, len);
4002 fluid_synth_check_finished_voices(fluid_synth_t *synth)
4007 while(NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler)))
4009 for(j = 0; j < synth->polyphony; j++)
4011 if(synth->voice[j]->rvoice == fv)
4013 fluid_voice_unlock_rvoice(synth->voice[j]);
4014 fluid_voice_stop(synth->voice[j]);
4017 else if(synth->voice[j]->overflow_rvoice == fv)
4019 fluid_voice_overflow_rvoice_finished(synth->voice[j]);
4027 * Process all waiting events in the rvoice queue.
4028 * Make sure no (other) rendering is running in parallel when
4029 * you call this function!
4031 void fluid_synth_process_event_queue(fluid_synth_t *synth)
4033 fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4038 * Process blocks (FLUID_BUFSIZE) of audio.
4039 * Must be called from renderer thread only!
4040 * @return number of blocks rendered. Might (often) return less than requested
4043 fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount)
4046 fluid_profile_ref_var(prof_ref);
4048 /* Assign ID of synthesis thread */
4049 // synth->synth_thread_id = fluid_thread_get_id ();
4051 fluid_check_fpe("??? Just starting up ???");
4053 fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4055 /* do not render more blocks than we can store internally */
4056 maxblocks = fluid_rvoice_mixer_get_bufcount(synth->eventhandler->mixer);
4058 if(blockcount > maxblocks)
4060 blockcount = maxblocks;
4063 for(i = 0; i < blockcount; i++)
4065 fluid_sample_timer_process(synth);
4066 fluid_synth_add_ticks(synth, FLUID_BUFSIZE);
4068 /* If events have been queued waiting for fluid_rvoice_eventhandler_dispatch_all()
4069 * (should only happen with parallel render) stop processing and go for rendering
4071 if(fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler))
4073 // Something has happened, we can't process more
4079 fluid_check_fpe("fluid_sample_timer_process");
4081 blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount);
4083 /* Testcase, that provokes a denormal floating point error */
4094 fluid_check_fpe("??? Remainder of synth_one_block ???");
4095 fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref,
4096 fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
4097 blockcount * FLUID_BUFSIZE);
4102 * Handler for synth.reverb.* and synth.chorus.* double settings.
4104 static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value)
4106 fluid_synth_t *synth = (fluid_synth_t *)data;
4107 fluid_return_if_fail(synth != NULL);
4109 if(FLUID_STRCMP(name, "synth.reverb.room-size") == 0)
4111 fluid_synth_set_reverb_roomsize(synth, value);
4113 else if(FLUID_STRCMP(name, "synth.reverb.damp") == 0)
4115 fluid_synth_set_reverb_damp(synth, value);
4117 else if(FLUID_STRCMP(name, "synth.reverb.width") == 0)
4119 fluid_synth_set_reverb_width(synth, value);
4121 else if(FLUID_STRCMP(name, "synth.reverb.level") == 0)
4123 fluid_synth_set_reverb_level(synth, value);
4125 else if(FLUID_STRCMP(name, "synth.chorus.depth") == 0)
4127 fluid_synth_set_chorus_depth(synth, value);
4129 else if(FLUID_STRCMP(name, "synth.chorus.speed") == 0)
4131 fluid_synth_set_chorus_speed(synth, value);
4133 else if(FLUID_STRCMP(name, "synth.chorus.level") == 0)
4135 fluid_synth_set_chorus_level(synth, value);
4140 * Handler for synth.reverb.* and synth.chorus.* integer settings.
4142 static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value)
4144 fluid_synth_t *synth = (fluid_synth_t *)data;
4145 fluid_return_if_fail(synth != NULL);
4147 if(FLUID_STRCMP(name, "synth.reverb.active") == 0)
4149 fluid_synth_set_reverb_on(synth, value);
4151 else if(FLUID_STRCMP(name, "synth.chorus.active") == 0)
4153 fluid_synth_set_chorus_on(synth, value);
4155 else if(FLUID_STRCMP(name, "synth.chorus.nr") == 0)
4157 fluid_synth_set_chorus_nr(synth, value);
4162 * Handler for synth.overflow.* settings.
4164 static void fluid_synth_handle_overflow(void *data, const char *name, double value)
4166 fluid_synth_t *synth = (fluid_synth_t *)data;
4167 fluid_return_if_fail(synth != NULL);
4169 fluid_synth_api_enter(synth);
4171 if(FLUID_STRCMP(name, "synth.overflow.percussion") == 0)
4173 synth->overflow.percussion = value;
4175 else if(FLUID_STRCMP(name, "synth.overflow.released") == 0)
4177 synth->overflow.released = value;
4179 else if(FLUID_STRCMP(name, "synth.overflow.sustained") == 0)
4181 synth->overflow.sustained = value;
4183 else if(FLUID_STRCMP(name, "synth.overflow.volume") == 0)
4185 synth->overflow.volume = value;
4187 else if(FLUID_STRCMP(name, "synth.overflow.age") == 0)
4189 synth->overflow.age = value;
4191 else if(FLUID_STRCMP(name, "synth.overflow.important") == 0)
4193 synth->overflow.important = value;
4196 fluid_synth_api_exit(synth);
4199 /* Selects a voice for killing. */
4200 static fluid_voice_t *
4201 fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth)
4204 float best_prio = OVERFLOW_PRIO_CANNOT_KILL - 1;
4205 float this_voice_prio;
4206 fluid_voice_t *voice;
4207 int best_voice_index = -1;
4208 unsigned int ticks = fluid_synth_get_ticks(synth);
4210 for(i = 0; i < synth->polyphony; i++)
4213 voice = synth->voice[i];
4215 /* safeguard against an available voice. */
4216 if(_AVAILABLE(voice))
4221 this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow,
4224 /* check if this voice has less priority than the previous candidate. */
4225 if(this_voice_prio < best_prio)
4227 best_voice_index = i;
4228 best_prio = this_voice_prio;
4232 if(best_voice_index < 0)
4237 voice = synth->voice[best_voice_index];
4238 FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ",
4239 fluid_voice_get_id(voice), best_voice_index, fluid_voice_get_channel(voice), fluid_voice_get_key(voice));
4240 fluid_voice_off(voice);
4247 * Allocate a synthesis voice.
4248 * @param synth FluidSynth instance
4249 * @param sample Sample to assign to the voice
4250 * @param chan MIDI channel number (0 to MIDI channel count - 1)
4251 * @param key MIDI note number for the voice (0-127)
4252 * @param vel MIDI velocity for the voice (0-127)
4253 * @return Allocated synthesis voice or NULL on error
4255 * This function is called by a SoundFont's preset in response to a noteon event.
4256 * The returned voice comes with default modulators and generators.
4257 * A single noteon event may create any number of voices, when the preset is layered.
4259 * @note Should only be called from within synthesis thread, which includes
4260 * SoundFont loader preset noteon method.
4263 fluid_synth_alloc_voice(fluid_synth_t *synth, fluid_sample_t *sample,
4264 int chan, int key, int vel)
4266 fluid_return_val_if_fail(sample != NULL, NULL);
4267 FLUID_API_ENTRY_CHAN(NULL);
4268 FLUID_API_RETURN(fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, NULL));
4273 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)
4276 fluid_voice_t *voice = NULL;
4277 fluid_channel_t *channel = NULL;
4280 /* check if there's an available synthesis process */
4281 for(i = 0; i < synth->polyphony; i++)
4283 if(_AVAILABLE(synth->voice[i]))
4285 voice = synth->voice[i];
4290 /* No success yet? Then stop a running voice. */
4293 FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice");
4294 voice = fluid_synth_free_voice_by_kill_LOCAL(synth);
4299 FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
4303 ticks = fluid_synth_get_ticks(synth);
4309 for(i = 0; i < synth->polyphony; i++)
4311 if(!_AVAILABLE(synth->voice[i]))
4317 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
4318 chan, key, vel, synth->storeid,
4319 (float) ticks / 44100.0f,
4320 (fluid_curtime() - synth->start) / 1000.0f,
4325 channel = synth->channel[chan];
4327 if(fluid_voice_init(voice, sample, zone_range, channel, key, vel,
4328 synth->storeid, ticks, synth->gain) != FLUID_OK)
4330 FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
4334 /* add the default modulators to the synthesis process. */
4335 /* custom_breath2att_modulator is not a default modulator specified in SF
4336 it is intended to replace default_vel2att_mod for this channel on demand using
4337 API fluid_synth_set_breath_mode() or shell command setbreathmode for this channel.
4340 int mono = fluid_channel_is_playing_mono(channel);
4341 fluid_mod_t *default_mod = synth->default_mod;
4343 while(default_mod != NULL)
4346 /* See if default_mod is the velocity_to_attenuation modulator */
4347 fluid_mod_test_identity(default_mod, &default_vel2att_mod) &&
4348 // See if a replacement by custom_breath2att_modulator has been demanded
4350 ((!mono && (channel->mode & FLUID_CHANNEL_BREATH_POLY)) ||
4351 (mono && (channel->mode & FLUID_CHANNEL_BREATH_MONO)))
4354 // Replacement of default_vel2att modulator by custom_breath2att_modulator
4355 fluid_voice_add_mod(voice, &custom_breath2att_mod, FLUID_VOICE_DEFAULT);
4359 fluid_voice_add_mod(voice, default_mod, FLUID_VOICE_DEFAULT);
4362 // Next default modulator to add to the voice
4363 default_mod = default_mod->next;
4370 /* Kill all voices on a given channel, which have the same exclusive class
4371 * generator as new_voice.
4374 fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
4375 fluid_voice_t *new_voice)
4377 int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS);
4380 /* Excl. class 0: No exclusive class */
4386 /* Kill all notes on the same channel with the same exclusive class */
4387 for(i = 0; i < synth->polyphony; i++)
4389 fluid_voice_t *existing_voice = synth->voice[i];
4390 int existing_excl_class = fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS);
4392 /* If voice is playing, on the same channel, has same exclusive
4393 * class and is not part of the same noteon event (voice group), then kill it */
4395 if(fluid_voice_is_playing(existing_voice)
4396 && fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice)
4397 && existing_excl_class == excl_class
4398 && fluid_voice_get_id(existing_voice) != fluid_voice_get_id(new_voice))
4400 fluid_voice_kill_excl(existing_voice);
4406 * Activate a voice previously allocated with fluid_synth_alloc_voice().
4407 * @param synth FluidSynth instance
4408 * @param voice Voice to activate
4410 * This function is called by a SoundFont's preset in response to a noteon
4411 * event. Exclusive classes are processed here.
4413 * @note Should only be called from within synthesis thread, which includes
4414 * SoundFont loader preset noteon method.
4417 fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice)
4419 fluid_return_if_fail(synth != NULL);
4420 fluid_return_if_fail(voice != NULL);
4421 // fluid_return_if_fail (fluid_synth_is_synth_thread (synth));
4422 fluid_synth_api_enter(synth);
4424 /* Find the exclusive class of this voice. If set, kill all voices
4425 * that match the exclusive class and are younger than the first
4426 * voice process created by this noteon event. */
4427 fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice);
4429 fluid_voice_start(voice); /* Start the new voice */
4430 fluid_voice_lock_rvoice(voice);
4431 fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice);
4432 fluid_synth_api_exit(synth);
4436 * Add a SoundFont loader to the synth. This function takes ownership of \c loader
4437 * and frees it automatically upon \c synth destruction.
4438 * @param synth FluidSynth instance
4439 * @param loader Loader API structure
4441 * SoundFont loaders are used to add custom instrument loading to FluidSynth.
4442 * The caller supplied functions for loading files, allocating presets,
4443 * retrieving information on them and synthesizing note-on events. Using this
4444 * method even non SoundFont instruments can be synthesized, although limited
4445 * to the SoundFont synthesis model.
4447 * @note Should only be called before any SoundFont files are loaded.
4450 fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader)
4452 fluid_return_if_fail(synth != NULL);
4453 fluid_return_if_fail(loader != NULL);
4454 fluid_synth_api_enter(synth);
4456 /* Test if sfont is already loaded */
4457 if(synth->sfont == NULL)
4459 synth->loaders = fluid_list_prepend(synth->loaders, loader);
4462 fluid_synth_api_exit(synth);
4466 * Load a SoundFont file (filename is interpreted by SoundFont loaders).
4467 * The newly loaded SoundFont will be put on top of the SoundFont
4468 * stack. Presets are searched starting from the SoundFont on the
4469 * top of the stack, working the way down the stack until a preset is found.
4471 * @param synth FluidSynth instance
4472 * @param filename File to load
4473 * @param reset_presets TRUE to re-assign presets for all MIDI channels (equivalent to calling fluid_synth_program_reset())
4474 * @return SoundFont ID on success, #FLUID_FAILED on error
4477 fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets)
4479 fluid_sfont_t *sfont;
4481 fluid_sfloader_t *loader;
4484 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4485 fluid_return_val_if_fail(filename != NULL, FLUID_FAILED);
4486 fluid_synth_api_enter(synth);
4488 sfont_id = synth->sfont_id;
4490 if(++sfont_id != FLUID_FAILED)
4492 /* MT NOTE: Loaders list should not change. */
4494 for(list = synth->loaders; list; list = fluid_list_next(list))
4496 loader = (fluid_sfloader_t *) fluid_list_get(list);
4498 sfont = fluid_sfloader_load(loader, filename);
4503 synth->sfont_id = sfont->id = sfont_id;
4505 synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
4507 /* reset the presets for all channels if requested */
4510 fluid_synth_program_reset(synth);
4513 FLUID_API_RETURN(sfont_id);
4518 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
4519 FLUID_API_RETURN(FLUID_FAILED);
4523 * Unload a SoundFont.
4524 * @param synth FluidSynth instance
4525 * @param id ID of SoundFont to unload
4526 * @param reset_presets TRUE to re-assign presets for all MIDI channels
4527 * @return #FLUID_OK on success, #FLUID_FAILED on error
4530 fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets)
4532 fluid_sfont_t *sfont = NULL;
4535 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4536 fluid_synth_api_enter(synth);
4538 /* remove the SoundFont from the list */
4539 for(list = synth->sfont; list; list = fluid_list_next(list))
4541 sfont = fluid_list_get(list);
4543 if(fluid_sfont_get_id(sfont) == id)
4545 synth->sfont = fluid_list_remove(synth->sfont, sfont);
4552 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
4553 FLUID_API_RETURN(FLUID_FAILED);
4556 /* reset the presets for all channels (SoundFont will be freed when there are no more references) */
4559 fluid_synth_program_reset(synth);
4563 fluid_synth_update_presets(synth);
4566 /* -- Remove synth->sfont list's reference to SoundFont */
4567 fluid_synth_sfont_unref(synth, sfont);
4569 FLUID_API_RETURN(FLUID_OK);
4572 /* Unref a SoundFont and destroy if no more references */
4574 fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont)
4576 fluid_return_if_fail(sfont != NULL); /* Shouldn't happen, programming error if so */
4578 sfont->refcount--; /* -- Remove the sfont list's reference */
4580 if(sfont->refcount == 0) /* No more references? - Attempt delete */
4582 if(fluid_sfont_delete_internal(sfont) == 0) /* SoundFont loader can block SoundFont unload */
4584 FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
4585 } /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */
4588 new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, TRUE, TRUE, FALSE);
4593 /* Callback to continually attempt to unload a SoundFont,
4594 * only if a SoundFont loader blocked the unload operation */
4596 fluid_synth_sfunload_callback(void *data, unsigned int msec)
4598 fluid_sfont_t *sfont = data;
4600 if(fluid_sfont_delete_internal(sfont) == 0)
4602 FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
4612 * Reload a SoundFont. The SoundFont retains its ID and index on the SoundFont stack.
4613 * @param synth FluidSynth instance
4614 * @param id ID of SoundFont to reload
4615 * @return SoundFont ID on success, #FLUID_FAILED on error
4618 fluid_synth_sfreload(fluid_synth_t *synth, int id)
4620 char *filename = NULL;
4621 fluid_sfont_t *sfont;
4622 fluid_sfloader_t *loader;
4624 int index, ret = FLUID_FAILED;
4626 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4627 fluid_synth_api_enter(synth);
4629 /* Search for SoundFont and get its index */
4630 for(list = synth->sfont, index = 0; list; list = fluid_list_next(list), index++)
4632 sfont = fluid_list_get(list);
4634 if(fluid_sfont_get_id(sfont) == id)
4642 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
4646 /* keep a copy of the SoundFont's filename */
4647 filename = FLUID_STRDUP(fluid_sfont_get_name(sfont));
4649 if(filename == NULL || fluid_synth_sfunload(synth, id, FALSE) != FLUID_OK)
4654 /* MT Note: SoundFont loader list will not change */
4656 for(list = synth->loaders; list; list = fluid_list_next(list))
4658 loader = (fluid_sfloader_t *) fluid_list_get(list);
4660 sfont = fluid_sfloader_load(loader, filename);
4667 synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont); /* insert the sfont at the same index */
4669 /* reset the presets for all channels */
4670 fluid_synth_update_presets(synth);
4676 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
4679 FLUID_FREE(filename);
4680 FLUID_API_RETURN(ret);
4684 * Add a SoundFont. The SoundFont will be added to the top of the SoundFont stack.
4685 * @param synth FluidSynth instance
4686 * @param sfont SoundFont to add
4687 * @return New assigned SoundFont ID or #FLUID_FAILED on error
4690 fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
4694 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4695 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
4696 fluid_synth_api_enter(synth);
4698 sfont_id = synth->sfont_id;
4700 if(++sfont_id != FLUID_FAILED)
4702 synth->sfont_id = sfont->id = sfont_id;
4703 synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
4705 /* reset the presets for all channels */
4706 fluid_synth_program_reset(synth);
4709 FLUID_API_RETURN(sfont_id);
4713 * Remove a SoundFont from the SoundFont stack without deleting it.
4714 * @param synth FluidSynth instance
4715 * @param sfont SoundFont to remove
4716 * @return #FLUID_OK if \c sfont successfully removed, #FLUID_FAILED otherwise
4718 * SoundFont is not freed and is left as the responsibility of the caller.
4720 * @note The SoundFont should only be freed after there are no presets
4721 * referencing it. This can only be ensured by the SoundFont loader and
4722 * therefore this function should not normally be used.
4725 fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
4727 fluid_sfont_t *sfont_tmp;
4729 int ret = FLUID_FAILED;
4731 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4732 fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
4733 fluid_synth_api_enter(synth);
4735 /* remove the SoundFont from the list */
4736 for(list = synth->sfont; list; list = fluid_list_next(list))
4738 sfont_tmp = fluid_list_get(list);
4740 if(sfont_tmp == sfont)
4742 synth->sfont = fluid_list_remove(synth->sfont, sfont_tmp);
4748 /* reset the presets for all channels */
4749 fluid_synth_program_reset(synth);
4751 FLUID_API_RETURN(ret);
4755 * Count number of loaded SoundFont files.
4756 * @param synth FluidSynth instance
4757 * @return Count of loaded SoundFont files.
4760 fluid_synth_sfcount(fluid_synth_t *synth)
4764 fluid_return_val_if_fail(synth != NULL, 0);
4765 fluid_synth_api_enter(synth);
4766 count = fluid_list_size(synth->sfont);
4767 FLUID_API_RETURN(count);
4771 * Get SoundFont by index.
4772 * @param synth FluidSynth instance
4773 * @param num SoundFont index on the stack (starting from 0 for top of stack).
4774 * @return SoundFont instance or NULL if invalid index
4776 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4777 * the duration of use of the returned pointer.
4780 fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num)
4782 fluid_sfont_t *sfont = NULL;
4785 fluid_return_val_if_fail(synth != NULL, NULL);
4786 fluid_synth_api_enter(synth);
4787 list = fluid_list_nth(synth->sfont, num);
4791 sfont = fluid_list_get(list);
4794 FLUID_API_RETURN(sfont);
4798 * Get SoundFont by ID.
4799 * @param synth FluidSynth instance
4800 * @param id SoundFont ID
4801 * @return SoundFont instance or NULL if invalid ID
4803 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4804 * the duration of use of the returned pointer.
4807 fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id)
4809 fluid_sfont_t *sfont = NULL;
4812 fluid_return_val_if_fail(synth != NULL, NULL);
4813 fluid_synth_api_enter(synth);
4815 for(list = synth->sfont; list; list = fluid_list_next(list))
4817 sfont = fluid_list_get(list);
4819 if(fluid_sfont_get_id(sfont) == id)
4825 FLUID_API_RETURN(list ? sfont : NULL);
4829 * Get SoundFont by name.
4830 * @param synth FluidSynth instance
4831 * @param name Name of SoundFont
4832 * @return SoundFont instance or NULL if invalid name
4835 * @note Caller should be certain that SoundFont is not deleted (unloaded) for
4836 * the duration of use of the returned pointer.
4839 fluid_synth_get_sfont_by_name(fluid_synth_t *synth, const char *name)
4841 fluid_sfont_t *sfont = NULL;
4844 fluid_return_val_if_fail(synth != NULL, NULL);
4845 fluid_return_val_if_fail(name != NULL, NULL);
4846 fluid_synth_api_enter(synth);
4848 for(list = synth->sfont; list; list = fluid_list_next(list))
4850 sfont = fluid_list_get(list);
4852 if(FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0)
4858 FLUID_API_RETURN(list ? sfont : NULL);
4862 * Get active preset on a MIDI channel.
4863 * @param synth FluidSynth instance
4864 * @param chan MIDI channel number (0 to MIDI channel count - 1)
4865 * @return Preset or NULL if no preset active on \c chan
4867 * @note Should only be called from within synthesis thread, which includes
4868 * SoundFont loader preset noteon methods. Not thread safe otherwise.
4871 fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan)
4873 fluid_preset_t *result;
4874 fluid_channel_t *channel;
4875 FLUID_API_ENTRY_CHAN(NULL);
4877 channel = synth->channel[chan];
4878 result = channel->preset;
4879 fluid_synth_api_exit(synth);
4884 * Get list of currently playing voices.
4885 * @param synth FluidSynth instance
4886 * @param buf Array to store voices to (NULL terminated if not filled completely)
4887 * @param bufsize Count of indexes in buf
4888 * @param id Voice ID to search for or < 0 to return list of all playing voices
4890 * @note Should only be called from within synthesis thread, which includes
4891 * SoundFont loader preset noteon methods. Voices are only guaranteed to remain
4892 * unchanged until next synthesis process iteration.
4895 fluid_synth_get_voicelist(fluid_synth_t *synth, fluid_voice_t *buf[], int bufsize,
4901 fluid_return_if_fail(synth != NULL);
4902 fluid_return_if_fail(buf != NULL);
4903 fluid_synth_api_enter(synth);
4905 for(i = 0; i < synth->polyphony && count < bufsize; i++)
4907 fluid_voice_t *voice = synth->voice[i];
4909 if(fluid_voice_is_playing(voice) && (id < 0 || (int)voice->id == id))
4911 buf[count++] = voice;
4920 fluid_synth_api_exit(synth);
4924 * Enable or disable reverb effect.
4925 * @param synth FluidSynth instance
4926 * @param on TRUE to enable reverb, FALSE to disable
4929 fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
4931 fluid_return_if_fail(synth != NULL);
4933 fluid_synth_api_enter(synth);
4935 synth->with_reverb = (on != 0);
4936 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled,
4938 fluid_synth_api_exit(synth);
4942 * Activate a reverb preset.
4943 * @param synth FluidSynth instance
4944 * @param num Reverb preset number
4945 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4947 * @note Currently private to libfluidsynth.
4950 fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
4952 fluid_return_val_if_fail(
4953 num < FLUID_N_ELEMENTS(revmodel_preset),
4957 fluid_synth_set_reverb(synth, revmodel_preset[num].roomsize,
4958 revmodel_preset[num].damp, revmodel_preset[num].width,
4959 revmodel_preset[num].level);
4964 * Set reverb parameters.
4965 * @param synth FluidSynth instance
4966 * @param roomsize Reverb room size value (0.0-1.0)
4967 * @param damping Reverb damping value (0.0-1.0)
4968 * @param width Reverb width value (0.0-100.0)
4969 * @param level Reverb level value (0.0-1.0)
4970 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4972 * @note Not realtime safe and therefore should not be called from synthesis
4973 * context at the risk of stalling audio output.
4976 fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping,
4977 double width, double level)
4979 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ALL,
4980 roomsize, damping, width, level);
4984 * Set reverb roomsize. See fluid_synth_set_reverb() for further info.
4985 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4987 int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
4989 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ROOMSIZE, roomsize, 0, 0, 0);
4993 * Set reverb damping. See fluid_synth_set_reverb() for further info.
4994 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
4996 int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
4998 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_DAMPING, 0, damping, 0, 0);
5002 * Set reverb width. See fluid_synth_set_reverb() for further info.
5003 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5005 int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
5007 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_WIDTH, 0, 0, width, 0);
5011 * Set reverb level. See fluid_synth_set_reverb() for further info.
5012 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5014 int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
5016 return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_LEVEL, 0, 0, 0, level);
5020 * Set one or more reverb parameters.
5021 * @param synth FluidSynth instance
5022 * @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
5023 * @param roomsize Reverb room size value (0.0-1.2)
5024 * @param damping Reverb damping value (0.0-1.0)
5025 * @param width Reverb width value (0.0-100.0)
5026 * @param level Reverb level value (0.0-1.0)
5027 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5029 * @note Not realtime safe and therefore should not be called from synthesis
5030 * context at the risk of stalling audio output.
5033 fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize,
5034 double damping, double width, double level)
5038 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5039 /* if non of the flags is set, fail */
5040 fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
5042 /* Synth shadow values are set here so that they will be returned if querried */
5044 fluid_synth_api_enter(synth);
5045 ret = fluid_synth_set_reverb_full_LOCAL(synth, set, roomsize, damping, width, level);
5046 FLUID_API_RETURN(ret);
5050 fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize,
5051 double damping, double width, double level)
5054 fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5056 if(set & FLUID_REVMODEL_SET_ROOMSIZE)
5058 synth->reverb_roomsize = roomsize;
5061 if(set & FLUID_REVMODEL_SET_DAMPING)
5063 synth->reverb_damping = damping;
5066 if(set & FLUID_REVMODEL_SET_WIDTH)
5068 synth->reverb_width = width;
5071 if(set & FLUID_REVMODEL_SET_LEVEL)
5073 synth->reverb_level = level;
5077 param[1].real = roomsize;
5078 param[2].real = damping;
5079 param[3].real = width;
5080 param[4].real = level;
5081 /* finally enqueue an rvoice event to the mixer to actual update reverb */
5082 ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5083 fluid_rvoice_mixer_set_reverb_params,
5084 synth->eventhandler->mixer,
5090 * Get reverb room size.
5091 * @param synth FluidSynth instance
5092 * @return Reverb room size (0.0-1.2)
5095 fluid_synth_get_reverb_roomsize(fluid_synth_t *synth)
5098 fluid_return_val_if_fail(synth != NULL, 0.0);
5099 fluid_synth_api_enter(synth);
5100 result = synth->reverb_roomsize;
5101 FLUID_API_RETURN(result);
5105 * Get reverb damping.
5106 * @param synth FluidSynth instance
5107 * @return Reverb damping value (0.0-1.0)
5110 fluid_synth_get_reverb_damp(fluid_synth_t *synth)
5113 fluid_return_val_if_fail(synth != NULL, 0.0);
5114 fluid_synth_api_enter(synth);
5116 result = synth->reverb_damping;
5117 FLUID_API_RETURN(result);
5122 * @param synth FluidSynth instance
5123 * @return Reverb level value (0.0-1.0)
5126 fluid_synth_get_reverb_level(fluid_synth_t *synth)
5129 fluid_return_val_if_fail(synth != NULL, 0.0);
5130 fluid_synth_api_enter(synth);
5132 result = synth->reverb_level;
5133 FLUID_API_RETURN(result);
5138 * @param synth FluidSynth instance
5139 * @return Reverb width value (0.0-100.0)
5142 fluid_synth_get_reverb_width(fluid_synth_t *synth)
5145 fluid_return_val_if_fail(synth != NULL, 0.0);
5146 fluid_synth_api_enter(synth);
5148 result = synth->reverb_width;
5149 FLUID_API_RETURN(result);
5153 * Enable or disable chorus effect.
5154 * @param synth FluidSynth instance
5155 * @param on TRUE to enable chorus, FALSE to disable
5158 fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
5160 fluid_return_if_fail(synth != NULL);
5161 fluid_synth_api_enter(synth);
5163 synth->with_chorus = (on != 0);
5164 fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled,
5166 fluid_synth_api_exit(synth);
5170 * Set chorus parameters. It should be turned on with fluid_synth_set_chorus_on().
5171 * Keep in mind, that the needed CPU time is proportional to 'nr'.
5172 * @param synth FluidSynth instance
5173 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
5175 * @param level Chorus level (0.0-10.0)
5176 * @param speed Chorus speed in Hz (0.29-5.0)
5177 * @param depth_ms Chorus depth (max value depends on synth sample rate,
5178 * 0.0-21.0 is safe for sample rate values up to 96KHz)
5179 * @param type Chorus waveform type (#fluid_chorus_mod)
5180 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5182 int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
5183 double speed, double depth_ms, int type)
5185 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_ALL, nr, level, speed,
5190 * Set the chorus voice count. See fluid_synth_set_chorus() for further info.
5191 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5193 int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
5195 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_NR, nr, 0, 0, 0, 0);
5199 * Set the chorus level. See fluid_synth_set_chorus() for further info.
5200 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5202 int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
5204 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_LEVEL, 0, level, 0, 0, 0);
5208 * Set the chorus speed. See fluid_synth_set_chorus() for further info.
5209 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5211 int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
5213 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_SPEED, 0, 0, speed, 0, 0);
5217 * Set the chorus depth. See fluid_synth_set_chorus() for further info.
5218 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5220 int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
5222 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_DEPTH, 0, 0, 0, depth_ms, 0);
5226 * Set the chorus type. See fluid_synth_set_chorus() for further info.
5227 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5229 int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
5231 return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_TYPE, 0, 0, 0, 0, type);
5235 * Set one or more chorus parameters.
5236 * @param synth FluidSynth instance
5237 * @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t)
5238 * @param nr Chorus voice count (0-99, CPU time consumption proportional to
5240 * @param level Chorus level (0.0-10.0)
5241 * @param speed Chorus speed in Hz (0.29-5.0)
5242 * @param depth_ms Chorus depth (max value depends on synth sample rate,
5243 * 0.0-21.0 is safe for sample rate values up to 96KHz)
5244 * @param type Chorus waveform type (#fluid_chorus_mod)
5245 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5248 fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level,
5249 double speed, double depth_ms, int type)
5253 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5254 /* if non of the flags is set, fail */
5255 fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
5257 /* Synth shadow values are set here so that they will be returned if queried */
5258 fluid_synth_api_enter(synth);
5260 ret = fluid_synth_set_chorus_full_LOCAL(synth, set, nr, level, speed, depth_ms, type);
5262 FLUID_API_RETURN(ret);
5266 fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level,
5267 double speed, double depth_ms, int type)
5270 fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5272 if(set & FLUID_CHORUS_SET_NR)
5274 synth->chorus_nr = nr;
5277 if(set & FLUID_CHORUS_SET_LEVEL)
5279 synth->chorus_level = level;
5282 if(set & FLUID_CHORUS_SET_SPEED)
5284 synth->chorus_speed = speed;
5287 if(set & FLUID_CHORUS_SET_DEPTH)
5289 synth->chorus_depth = depth_ms;
5292 if(set & FLUID_CHORUS_SET_TYPE)
5294 synth->chorus_type = type;
5299 param[2].real = level;
5300 param[3].real = speed;
5301 param[4].real = depth_ms;
5303 ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5304 fluid_rvoice_mixer_set_chorus_params,
5305 synth->eventhandler->mixer,
5312 * Get chorus voice number (delay line count) value.
5313 * @param synth FluidSynth instance
5314 * @return Chorus voice count (0-99)
5317 fluid_synth_get_chorus_nr(fluid_synth_t *synth)
5320 fluid_return_val_if_fail(synth != NULL, 0.0);
5321 fluid_synth_api_enter(synth);
5323 result = synth->chorus_nr;
5324 FLUID_API_RETURN(result);
5329 * @param synth FluidSynth instance
5330 * @return Chorus level value (0.0-10.0)
5333 fluid_synth_get_chorus_level(fluid_synth_t *synth)
5336 fluid_return_val_if_fail(synth != NULL, 0.0);
5337 fluid_synth_api_enter(synth);
5339 result = synth->chorus_level;
5340 FLUID_API_RETURN(result);
5344 * Get chorus speed in Hz.
5345 * @param synth FluidSynth instance
5346 * @return Chorus speed in Hz (0.29-5.0)
5349 fluid_synth_get_chorus_speed(fluid_synth_t *synth)
5352 fluid_return_val_if_fail(synth != NULL, 0.0);
5353 fluid_synth_api_enter(synth);
5355 result = synth->chorus_speed;
5356 FLUID_API_RETURN(result);
5361 * @param synth FluidSynth instance
5362 * @return Chorus depth
5365 fluid_synth_get_chorus_depth(fluid_synth_t *synth)
5368 fluid_return_val_if_fail(synth != NULL, 0.0);
5369 fluid_synth_api_enter(synth);
5371 result = synth->chorus_depth;
5372 FLUID_API_RETURN(result);
5376 * Get chorus waveform type.
5377 * @param synth FluidSynth instance
5378 * @return Chorus waveform type (#fluid_chorus_mod)
5381 fluid_synth_get_chorus_type(fluid_synth_t *synth)
5384 fluid_return_val_if_fail(synth != NULL, 0.0);
5385 fluid_synth_api_enter(synth);
5387 result = synth->chorus_type;
5388 FLUID_API_RETURN(result);
5392 * If the same note is hit twice on the same channel, then the older
5393 * voice process is advanced to the release stage. Using a mechanical
5394 * MIDI controller, the only way this can happen is when the sustain
5395 * pedal is held. In this case the behaviour implemented here is
5396 * natural for many instruments. Note: One noteon event can trigger
5397 * several voice processes, for example a stereo sample. Don't
5401 fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan,
5405 fluid_voice_t *voice;
5407 /* storeid is a parameter for fluid_voice_init() */
5408 synth->storeid = synth->noteid++;
5410 /* for "monophonic playing" key is the previous sustained note
5411 if it exists (0 to 127) or INVALID_NOTE otherwise */
5412 if(key == INVALID_NOTE)
5417 for(i = 0; i < synth->polyphony; i++)
5419 voice = synth->voice[i];
5421 if(fluid_voice_is_playing(voice)
5422 && (fluid_voice_get_channel(voice) == chan)
5423 && (fluid_voice_get_key(voice) == key)
5424 && (fluid_voice_get_id(voice) != synth->noteid))
5426 /* Id of voices that was sustained by sostenuto */
5427 if(fluid_voice_is_sostenuto(voice))
5429 synth->storeid = fluid_voice_get_id(voice);
5432 /* Force the voice into release stage (pedaling is ignored) */
5433 fluid_voice_release(voice);
5439 * Set synthesis interpolation method on one or all MIDI channels.
5440 * @param synth FluidSynth instance
5441 * @param chan MIDI channel to set interpolation method on or -1 for all channels
5442 * @param interp_method Interpolation method (#fluid_interp)
5443 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5446 fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method)
5450 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5451 fluid_synth_api_enter(synth);
5453 if(chan < -1 || chan >= synth->midi_channels)
5455 FLUID_API_RETURN(FLUID_FAILED);
5458 if(synth->channel[0] == NULL)
5460 FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!");
5461 FLUID_API_RETURN(FLUID_FAILED);
5464 for(i = 0; i < synth->midi_channels; i++)
5466 if(chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan)
5468 fluid_channel_set_interp_method(synth->channel[i], interp_method);
5472 FLUID_API_RETURN(FLUID_OK);
5476 * Get the total count of MIDI channels.
5477 * @param synth FluidSynth instance
5478 * @return Count of MIDI channels
5481 fluid_synth_count_midi_channels(fluid_synth_t *synth)
5484 fluid_return_val_if_fail(synth != NULL, 0);
5485 fluid_synth_api_enter(synth);
5487 result = synth->midi_channels;
5488 FLUID_API_RETURN(result);
5492 * Get the total count of audio channels.
5493 * @param synth FluidSynth instance
5494 * @return Count of audio channel stereo pairs (1 = 2 channels, 2 = 4, etc)
5497 fluid_synth_count_audio_channels(fluid_synth_t *synth)
5500 fluid_return_val_if_fail(synth != NULL, 0);
5501 fluid_synth_api_enter(synth);
5503 result = synth->audio_channels;
5504 FLUID_API_RETURN(result);
5508 * Get the total number of allocated audio channels. Usually identical to the
5509 * number of audio channels. Can be employed by LADSPA effects subsystem.
5511 * @param synth FluidSynth instance
5512 * @return Count of audio group stereo pairs (1 = 2 channels, 2 = 4, etc)
5515 fluid_synth_count_audio_groups(fluid_synth_t *synth)
5518 fluid_return_val_if_fail(synth != NULL, 0);
5519 fluid_synth_api_enter(synth);
5521 result = synth->audio_groups;
5522 FLUID_API_RETURN(result);
5526 * Get the total number of allocated effects channels.
5527 * @param synth FluidSynth instance
5528 * @return Count of allocated effects channels
5531 fluid_synth_count_effects_channels(fluid_synth_t *synth)
5534 fluid_return_val_if_fail(synth != NULL, 0);
5535 fluid_synth_api_enter(synth);
5537 result = synth->effects_channels;
5538 FLUID_API_RETURN(result);
5542 * Get the total number of allocated effects units.
5543 * @param synth FluidSynth instance
5544 * @return Count of allocated effects units
5547 fluid_synth_count_effects_groups(fluid_synth_t *synth)
5550 fluid_return_val_if_fail(synth != NULL, 0);
5551 fluid_synth_api_enter(synth);
5553 result = synth->effects_groups;
5554 FLUID_API_RETURN(result);
5558 * Get the synth CPU load value.
5559 * @param synth FluidSynth instance
5560 * @return Estimated CPU load value in percent (0-100)
5563 fluid_synth_get_cpu_load(fluid_synth_t *synth)
5565 fluid_return_val_if_fail(synth != NULL, 0);
5566 return fluid_atomic_float_get(&synth->cpu_load);
5569 /* Get tuning for a given bank:program */
5570 static fluid_tuning_t *
5571 fluid_synth_get_tuning(fluid_synth_t *synth, int bank, int prog)
5574 if((synth->tuning == NULL) ||
5575 (synth->tuning[bank] == NULL) ||
5576 (synth->tuning[bank][prog] == NULL))
5581 return synth->tuning[bank][prog];
5584 /* Replace tuning on a given bank:program (need not already exist).
5585 * Synth mutex should already be locked by caller. */
5587 fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth, fluid_tuning_t *tuning,
5588 int bank, int prog, int apply)
5590 fluid_tuning_t *old_tuning;
5592 if(synth->tuning == NULL)
5594 synth->tuning = FLUID_ARRAY(fluid_tuning_t **, 128);
5596 if(synth->tuning == NULL)
5598 FLUID_LOG(FLUID_PANIC, "Out of memory");
5599 return FLUID_FAILED;
5602 FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t **));
5605 if(synth->tuning[bank] == NULL)
5607 synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t *, 128);
5609 if(synth->tuning[bank] == NULL)
5611 FLUID_LOG(FLUID_PANIC, "Out of memory");
5612 return FLUID_FAILED;
5615 FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t *));
5618 old_tuning = synth->tuning[bank][prog];
5619 synth->tuning[bank][prog] = tuning;
5623 if(!fluid_tuning_unref(old_tuning, 1)) /* -- unref old tuning */
5625 /* Replace old tuning if present */
5626 fluid_synth_replace_tuning_LOCAL(synth, old_tuning, tuning, apply, FALSE);
5633 /* Replace a tuning with a new one in all MIDI channels. new_tuning can be
5634 * NULL, in which case channels are reset to default equal tempered scale. */
5636 fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth, fluid_tuning_t *old_tuning,
5637 fluid_tuning_t *new_tuning, int apply, int unref_new)
5639 fluid_channel_t *channel;
5640 int old_tuning_unref = 0;
5643 for(i = 0; i < synth->midi_channels; i++)
5645 channel = synth->channel[i];
5647 if(fluid_channel_get_tuning(channel) == old_tuning)
5653 fluid_tuning_ref(new_tuning); /* ++ ref new tuning for channel */
5656 fluid_channel_set_tuning(channel, new_tuning);
5660 fluid_synth_update_voice_tuning_LOCAL(synth, channel);
5665 /* Send unref old tuning event if any unrefs */
5666 if(old_tuning && old_tuning_unref)
5668 fluid_tuning_unref(old_tuning, old_tuning_unref);
5671 if(!unref_new || !new_tuning)
5676 fluid_tuning_unref(new_tuning, 1);
5679 /* Update voice tunings in realtime */
5681 fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth, fluid_channel_t *channel)
5683 fluid_voice_t *voice;
5686 for(i = 0; i < synth->polyphony; i++)
5688 voice = synth->voice[i];
5690 if(fluid_voice_is_on(voice) && (voice->channel == channel))
5692 fluid_voice_calculate_gen_pitch(voice);
5693 fluid_voice_update_param(voice, GEN_PITCH);
5699 * Set the tuning of the entire MIDI note scale.
5700 * @param synth FluidSynth instance
5701 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5702 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5703 * @param name Label name for this tuning
5704 * @param pitch Array of pitch values (length of 128, each value is number of
5705 * cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
5706 * Pass NULL to create a equal tempered (normal) scale.
5707 * @param apply TRUE to apply new tuning in realtime to existing notes which
5708 * are using the replaced tuning (if any), FALSE otherwise
5709 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5713 fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog,
5714 const char *name, const double *pitch, int apply)
5716 fluid_tuning_t *tuning;
5717 int retval = FLUID_OK;
5719 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5720 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5721 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5722 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
5724 fluid_synth_api_enter(synth);
5726 tuning = new_fluid_tuning(name, bank, prog);
5732 fluid_tuning_set_all(tuning, pitch);
5735 retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
5737 if(retval == FLUID_FAILED)
5739 fluid_tuning_unref(tuning, 1);
5744 retval = FLUID_FAILED;
5747 FLUID_API_RETURN(retval);
5751 * Activate an octave tuning on every octave in the MIDI note scale.
5752 * @param synth FluidSynth instance
5753 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5754 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5755 * @param name Label name for this tuning
5756 * @param pitch Array of pitch values (length of 12 for each note of an octave
5757 * starting at note C, values are number of offset cents to add to the normal
5759 * @param apply TRUE to apply new tuning in realtime to existing notes which
5760 * are using the replaced tuning (if any), FALSE otherwise
5761 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5765 fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog,
5766 const char *name, const double *pitch, int apply)
5768 fluid_tuning_t *tuning;
5769 int retval = FLUID_OK;
5771 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5772 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5773 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5774 fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
5775 fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
5777 fluid_synth_api_enter(synth);
5778 tuning = new_fluid_tuning(name, bank, prog);
5782 fluid_tuning_set_octave(tuning, pitch);
5783 retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
5785 if(retval == FLUID_FAILED)
5787 fluid_tuning_unref(tuning, 1);
5792 retval = FLUID_FAILED;
5795 FLUID_API_RETURN(retval);
5799 * Set tuning values for one or more MIDI notes for an existing tuning.
5800 * @param synth FluidSynth instance
5801 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5802 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5803 * @param len Number of MIDI notes to assign
5804 * @param key Array of MIDI key numbers (length of 'len', values 0-127)
5805 * @param pitch Array of pitch values (length of 'len', values are number of
5806 * cents from MIDI note 0)
5807 * @param apply TRUE to apply tuning change in realtime to existing notes using
5808 * the specified tuning, FALSE otherwise
5809 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5811 * @note Prior to version 1.1.0 it was an error to specify a tuning that didn't
5812 * already exist. Starting with 1.1.0, the default equal tempered scale will be
5813 * used as a basis, if no tuning exists for the given bank and prog.
5816 fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog,
5817 int len, const int *key, const double *pitch, int apply)
5819 fluid_tuning_t *old_tuning, *new_tuning;
5820 int retval = FLUID_OK;
5823 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5824 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5825 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5826 fluid_return_val_if_fail(len > 0, FLUID_FAILED);
5827 fluid_return_val_if_fail(key != NULL, FLUID_FAILED);
5828 fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
5830 fluid_synth_api_enter(synth);
5832 old_tuning = fluid_synth_get_tuning(synth, bank, prog);
5836 new_tuning = fluid_tuning_duplicate(old_tuning);
5840 new_tuning = new_fluid_tuning("Unnamed", bank, prog);
5845 for(i = 0; i < len; i++)
5847 fluid_tuning_set_pitch(new_tuning, key[i], pitch[i]);
5850 retval = fluid_synth_replace_tuning_LOCK(synth, new_tuning, bank, prog, apply);
5852 if(retval == FLUID_FAILED)
5854 fluid_tuning_unref(new_tuning, 1);
5859 retval = FLUID_FAILED;
5862 FLUID_API_RETURN(retval);
5866 * Activate a tuning scale on a MIDI channel.
5867 * @param synth FluidSynth instance
5868 * @param chan MIDI channel number (0 to MIDI channel count - 1)
5869 * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
5870 * @param prog Tuning preset number (0-127), not related to MIDI instrument program
5871 * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
5872 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5875 * @note A default equal tempered scale will be created, if no tuning exists
5876 * on the given bank and prog.
5879 fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog,
5882 fluid_tuning_t *tuning;
5883 int retval = FLUID_OK;
5885 //fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
5886 //fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
5887 fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
5888 fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
5890 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5892 tuning = fluid_synth_get_tuning(synth, bank, prog);
5894 /* If no tuning exists, create a new default tuning. We do this, so that
5895 * it can be replaced later, if any changes are made. */
5898 tuning = new_fluid_tuning("Unnamed", bank, prog);
5902 fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, FALSE);
5908 fluid_tuning_ref(tuning); /* ++ ref for outside of lock */
5913 FLUID_API_RETURN(FLUID_FAILED);
5916 fluid_tuning_ref(tuning); /* ++ ref new tuning for following function */
5917 retval = fluid_synth_set_tuning_LOCAL(synth, chan, tuning, apply);
5919 fluid_tuning_unref(tuning, 1); /* -- unref for outside of lock */
5921 FLUID_API_RETURN(retval);
5924 /* Local synthesis thread set tuning function (takes over tuning reference) */
5926 fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
5927 fluid_tuning_t *tuning, int apply)
5929 fluid_tuning_t *old_tuning;
5930 fluid_channel_t *channel;
5932 channel = synth->channel[chan];
5934 old_tuning = fluid_channel_get_tuning(channel);
5935 fluid_channel_set_tuning(channel, tuning); /* !! Takes over callers reference */
5939 fluid_synth_update_voice_tuning_LOCAL(synth, channel);
5942 /* Send unref old tuning event */
5945 fluid_tuning_unref(old_tuning, 1);
5953 * Clear tuning scale on a MIDI channel (use default equal tempered scale).
5954 * @param synth FluidSynth instance
5955 * @param chan MIDI channel number (0 to MIDI channel count - 1)
5956 * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
5957 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
5961 fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply)
5963 int retval = FLUID_OK;
5965 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5967 retval = fluid_synth_set_tuning_LOCAL(synth, chan, NULL, apply);
5969 FLUID_API_RETURN(retval);
5973 * Start tuning iteration.
5974 * @param synth FluidSynth instance
5977 fluid_synth_tuning_iteration_start(fluid_synth_t *synth)
5979 fluid_return_if_fail(synth != NULL);
5980 fluid_synth_api_enter(synth);
5981 fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER(0));
5982 fluid_synth_api_exit(synth);
5986 * Advance to next tuning.
5987 * @param synth FluidSynth instance
5988 * @param bank Location to store MIDI bank number of next tuning scale
5989 * @param prog Location to store MIDI program number of next tuning scale
5990 * @return 1 if tuning iteration advanced, 0 if no more tunings
5993 fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog)
5998 fluid_return_val_if_fail(synth != NULL, 0);
5999 fluid_return_val_if_fail(bank != NULL, 0);
6000 fluid_return_val_if_fail(prog != NULL, 0);
6001 fluid_synth_api_enter(synth);
6003 /* Current tuning iteration stored as: bank << 8 | program */
6004 pval = fluid_private_get(synth->tuning_iter);
6005 p = FLUID_POINTER_TO_INT(pval);
6006 b = (p >> 8) & 0xFF;
6011 FLUID_API_RETURN(0);
6014 for(; b < 128; b++, p = 0)
6016 if(synth->tuning[b] == NULL)
6023 if(synth->tuning[b][p] == NULL)
6033 fluid_private_set(synth->tuning_iter,
6034 FLUID_INT_TO_POINTER(b << 8 | (p + 1)));
6038 fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER((b + 1) << 8));
6041 FLUID_API_RETURN(1);
6045 FLUID_API_RETURN(0);
6049 * Get the entire note tuning for a given MIDI bank and program.
6050 * @param synth FluidSynth instance
6051 * @param bank MIDI bank number of tuning
6052 * @param prog MIDI program number of tuning
6053 * @param name Location to store tuning name or NULL to ignore
6054 * @param len Maximum number of chars to store to 'name' (including NULL byte)
6055 * @param pitch Array to store tuning scale to or NULL to ignore (len of 128)
6056 * @return #FLUID_OK if matching tuning was found, #FLUID_FAILED otherwise
6059 fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog,
6060 char *name, int len, double *pitch)
6062 fluid_tuning_t *tuning;
6064 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6065 fluid_synth_api_enter(synth);
6067 tuning = fluid_synth_get_tuning(synth, bank, prog);
6073 FLUID_SNPRINTF(name, len - 1, "%s", fluid_tuning_get_name(tuning));
6074 name[len - 1] = 0; /* make sure the string is null terminated */
6079 FLUID_MEMCPY(pitch, fluid_tuning_get_all(tuning), 128 * sizeof(double));
6083 FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED);
6087 * Get settings assigned to a synth.
6088 * @param synth FluidSynth instance
6089 * @return FluidSynth settings which are assigned to the synth
6092 fluid_synth_get_settings(fluid_synth_t *synth)
6094 fluid_return_val_if_fail(synth != NULL, NULL);
6096 return synth->settings;
6100 * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
6101 * @param synth FluidSynth instance
6102 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6103 * @param param SoundFont generator ID (#fluid_gen_type)
6104 * @param value Offset or absolute generator value to assign to the MIDI channel
6105 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6107 * This function allows for setting all effect parameters in real time on a
6108 * MIDI channel. Setting absolute to non-zero will cause the value to override
6109 * any generator values set in the instruments played on the MIDI channel.
6110 * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
6111 * generator parameters and valid ranges.
6113 int fluid_synth_set_gen(fluid_synth_t *synth, int chan, int param, float value)
6115 return fluid_synth_set_gen2(synth, chan, param, value, FALSE, FALSE);
6119 * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
6120 * @param synth FluidSynth instance
6121 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6122 * @param param SoundFont generator ID (#fluid_gen_type)
6123 * @param value Offset or absolute generator value to assign to the MIDI channel
6124 * @param absolute FALSE to assign a relative value, TRUE to assign an absolute value
6125 * @param normalized FALSE if value is specified in the native units of the generator,
6126 * TRUE to take the value as a 0.0-1.0 range and apply it to the valid
6127 * generator effect range (scaled and shifted as necessary).
6128 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6130 * This function allows for setting all effect parameters in real time on a
6131 * MIDI channel. Setting absolute to non-zero will cause the value to override
6132 * any generator values set in the instruments played on the MIDI channel.
6133 * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
6134 * generator parameters and valid ranges.
6137 fluid_synth_set_gen2(fluid_synth_t *synth, int chan, int param,
6138 float value, int absolute, int normalized)
6141 fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
6142 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6144 v = normalized ? fluid_gen_scale(param, value) : value;
6146 fluid_synth_set_gen_LOCAL(synth, chan, param, v, absolute);
6148 FLUID_API_RETURN(FLUID_OK);
6151 /* Synthesis thread local set gen function */
6153 fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, int param, float value,
6156 fluid_voice_t *voice;
6159 fluid_channel_set_gen(synth->channel[chan], param, value, absolute);
6161 for(i = 0; i < synth->polyphony; i++)
6163 voice = synth->voice[i];
6165 if(fluid_voice_get_channel(voice) == chan)
6167 fluid_voice_set_param(voice, param, value, absolute);
6173 * Get generator value assigned to a MIDI channel.
6174 * @param synth FluidSynth instance
6175 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6176 * @param param SoundFont generator ID (#fluid_gen_type)
6177 * @return Current generator value assigned to MIDI channel
6180 fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param)
6183 fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
6184 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6186 result = fluid_channel_get_gen(synth->channel[chan], param);
6187 FLUID_API_RETURN(result);
6191 * Handle MIDI event from MIDI router, used as a callback function.
6192 * @param data FluidSynth instance
6193 * @param event MIDI event to handle
6194 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6197 fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event)
6199 fluid_synth_t *synth = (fluid_synth_t *) data;
6200 int type = fluid_midi_event_get_type(event);
6201 int chan = fluid_midi_event_get_channel(event);
6206 return fluid_synth_noteon(synth, chan,
6207 fluid_midi_event_get_key(event),
6208 fluid_midi_event_get_velocity(event));
6211 return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event));
6213 case CONTROL_CHANGE:
6214 return fluid_synth_cc(synth, chan,
6215 fluid_midi_event_get_control(event),
6216 fluid_midi_event_get_value(event));
6218 case PROGRAM_CHANGE:
6219 return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
6221 case CHANNEL_PRESSURE:
6222 return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
6225 return fluid_synth_key_pressure(synth, chan,
6226 fluid_midi_event_get_key(event),
6227 fluid_midi_event_get_value(event));
6230 return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));
6232 case MIDI_SYSTEM_RESET:
6233 return fluid_synth_system_reset(synth);
6236 return fluid_synth_sysex(synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE);
6240 case MIDI_SET_TEMPO:
6244 return FLUID_FAILED;
6248 * Create and start voices using a preset and a MIDI note on event.
6249 * @param synth FluidSynth instance
6250 * @param id Voice group ID to use (can be used with fluid_synth_stop()).
6251 * @param preset Preset to synthesize
6252 * @param audio_chan Unused currently, set to 0
6253 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6254 * @param key MIDI note number (0-127)
6255 * @param vel MIDI velocity number (1-127)
6256 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6258 * @note Should only be called from within synthesis thread, which includes
6259 * SoundFont loader preset noteon method.
6262 fluid_synth_start(fluid_synth_t *synth, unsigned int id, fluid_preset_t *preset,
6263 int audio_chan, int chan, int key, int vel)
6266 fluid_return_val_if_fail(preset != NULL, FLUID_FAILED);
6267 fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
6268 fluid_return_val_if_fail(vel >= 1 && vel <= 127, FLUID_FAILED);
6269 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6270 synth->storeid = id;
6271 result = fluid_preset_noteon(preset, synth, chan, key, vel);
6272 FLUID_API_RETURN(result);
6276 * Stop notes for a given note event voice ID.
6277 * @param synth FluidSynth instance
6278 * @param id Voice note event ID
6279 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6281 * @note In FluidSynth versions prior to 1.1.0 #FLUID_FAILED would be returned
6282 * if no matching voice note event ID was found. Versions after 1.1.0 only
6283 * return #FLUID_FAILED if an error occurs.
6286 fluid_synth_stop(fluid_synth_t *synth, unsigned int id)
6289 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6290 fluid_synth_api_enter(synth);
6291 fluid_synth_stop_LOCAL(synth, id);
6293 FLUID_API_RETURN(result);
6296 /* Local synthesis thread variant of fluid_synth_stop */
6298 fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id)
6300 fluid_voice_t *voice;
6303 for(i = 0; i < synth->polyphony; i++)
6305 voice = synth->voice[i];
6307 if(fluid_voice_is_on(voice) && (fluid_voice_get_id(voice) == id))
6309 fluid_voice_noteoff(voice);
6315 * Offset the bank numbers of a loaded SoundFont, i.e.\ subtract
6316 * \c offset from any bank number when assigning instruments.
6318 * @param synth FluidSynth instance
6319 * @param sfont_id ID of a loaded SoundFont
6320 * @param offset Bank offset value to apply to all instruments
6321 * @return #FLUID_OK if the offset was set successfully, #FLUID_FAILED otherwise
6324 fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset)
6326 fluid_sfont_t *sfont;
6329 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6330 fluid_synth_api_enter(synth);
6332 for(list = synth->sfont; list; list = fluid_list_next(list))
6334 sfont = fluid_list_get(list);
6336 if(fluid_sfont_get_id(sfont) == sfont_id)
6338 sfont->bankofs = offset;
6345 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
6346 FLUID_API_RETURN(FLUID_FAILED);
6349 FLUID_API_RETURN(FLUID_OK);
6353 * Get bank offset of a loaded SoundFont.
6354 * @param synth FluidSynth instance
6355 * @param sfont_id ID of a loaded SoundFont
6356 * @return SoundFont bank offset value
6359 fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id)
6361 fluid_sfont_t *sfont;
6365 fluid_return_val_if_fail(synth != NULL, 0);
6366 fluid_synth_api_enter(synth);
6368 for(list = synth->sfont; list; list = fluid_list_next(list))
6370 sfont = fluid_list_get(list);
6372 if(fluid_sfont_get_id(sfont) == sfont_id)
6374 offset = sfont->bankofs;
6381 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
6382 FLUID_API_RETURN(0);
6385 FLUID_API_RETURN(offset);
6389 fluid_synth_api_enter(fluid_synth_t *synth)
6391 if(synth->use_mutex)
6393 fluid_rec_mutex_lock(synth->mutex);
6396 if(!synth->public_api_count)
6398 fluid_synth_check_finished_voices(synth);
6401 synth->public_api_count++;
6404 void fluid_synth_api_exit(fluid_synth_t *synth)
6406 synth->public_api_count--;
6408 if(!synth->public_api_count)
6410 fluid_rvoice_eventhandler_flush(synth->eventhandler);
6413 if(synth->use_mutex)
6415 fluid_rec_mutex_unlock(synth->mutex);
6421 * Set midi channel type
6422 * @param synth FluidSynth instance
6423 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6424 * @param type MIDI channel type (#fluid_midi_channel_type)
6425 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
6428 int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type)
6430 fluid_return_val_if_fail((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED);
6431 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6433 synth->channel[chan]->channel_type = type;
6435 FLUID_API_RETURN(FLUID_OK);
6440 * Return the LADSPA effects instance used by FluidSynth
6442 * @param synth FluidSynth instance
6443 * @return pointer to LADSPA fx or NULL if compiled without LADSPA support or LADSPA is not active
6445 fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
6447 fluid_return_val_if_fail(synth != NULL, NULL);
6449 return synth->ladspa_fx;
6454 * Configure a general-purpose IIR biquad filter.
6456 * This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard.
6457 * By default this filter is off (#FLUID_IIR_DISABLED).
6459 * @param synth FluidSynth instance
6460 * @param type Type of the IIR filter to use (see #fluid_iir_filter_type)
6461 * @param flags Additional flags to customize this filter or zero to stay with the default (see #fluid_iir_filter_flags)
6463 * @return #FLUID_OK if the settings have been successfully applied, otherwise #FLUID_FAILED
6465 int fluid_synth_set_custom_filter(fluid_synth_t *synth, int type, int flags)
6468 fluid_voice_t *voice;
6470 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6471 fluid_return_val_if_fail(type >= FLUID_IIR_DISABLED && type < FLUID_IIR_LAST, FLUID_FAILED);
6473 fluid_synth_api_enter(synth);
6475 synth->custom_filter_type = type;
6476 synth->custom_filter_flags = flags;
6478 for(i = 0; i < synth->polyphony; i++)
6480 voice = synth->voice[i];
6482 fluid_voice_set_custom_filter(voice, type, flags);
6485 FLUID_API_RETURN(FLUID_OK);
6489 * Set the important channels for voice overflow priority calculation.
6491 * @param synth FluidSynth instance
6492 * @param channels comma-separated list of channel numbers
6493 * @return #FLUID_OK on success, otherwise #FLUID_FAILED
6495 static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels)
6498 int retval = FLUID_FAILED;
6501 fluid_overflow_prio_t *scores;
6503 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6505 scores = &synth->overflow;
6507 if(scores->num_important_channels < synth->midi_channels)
6509 scores->important_channels = FLUID_REALLOC(scores->important_channels,
6510 sizeof(*scores->important_channels) * synth->midi_channels);
6512 if(scores->important_channels == NULL)
6514 FLUID_LOG(FLUID_ERR, "Out of memory");
6518 scores->num_important_channels = synth->midi_channels;
6521 FLUID_MEMSET(scores->important_channels, FALSE,
6522 sizeof(*scores->important_channels) * scores->num_important_channels);
6524 if(channels != NULL)
6526 values = FLUID_ARRAY(int, synth->midi_channels);
6530 FLUID_LOG(FLUID_ERR, "Out of memory");
6534 /* Every channel given in the comma-separated list of channel numbers
6535 * is set to TRUE, i.e. flagging it as "important". Channel numbers are
6537 num_values = fluid_settings_split_csv(channels, values, synth->midi_channels);
6539 for(i = 0; i < num_values; i++)
6541 if(values[i] > 0 && values[i] <= synth->midi_channels)
6543 scores->important_channels[values[i] - 1] = TRUE;
6556 * Handler for synth.overflow.important-channels setting.
6558 static void fluid_synth_handle_important_channels(void *data, const char *name,
6561 fluid_synth_t *synth = (fluid_synth_t *)data;
6563 fluid_synth_api_enter(synth);
6564 fluid_synth_set_important_channels(synth, value);
6565 fluid_synth_api_exit(synth);
6569 /** API legato mode *********************************************************/
6572 * Sets the legato mode of a channel.
6574 * @param synth the synth instance.
6575 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6576 * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
6579 * - #FLUID_OK on success.
6581 * - \a synth is NULL.
6582 * - \a chan is outside MIDI channel count.
6583 * - \a legatomode is invalid.
6585 int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode)
6587 /* checks parameters first */
6588 fluid_return_val_if_fail(legatomode >= 0, FLUID_FAILED);
6589 fluid_return_val_if_fail(legatomode < FLUID_CHANNEL_LEGATO_MODE_LAST, FLUID_FAILED);
6590 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6592 synth->channel[chan]->legatomode = legatomode;
6594 FLUID_API_RETURN(FLUID_OK);
6598 * Gets the legato mode of a channel.
6600 * @param synth the synth instance.
6601 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6602 * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
6605 * - #FLUID_OK on success.
6607 * - \a synth is NULL.
6608 * - \a chan is outside MIDI channel count.
6609 * - \a legatomode is NULL.
6611 int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode)
6613 /* checks parameters first */
6614 fluid_return_val_if_fail(legatomode != NULL, FLUID_FAILED);
6615 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6617 * legatomode = synth->channel[chan]->legatomode;
6619 FLUID_API_RETURN(FLUID_OK);
6622 /** API portamento mode *********************************************************/
6625 * Sets the portamento mode of a channel.
6627 * @param synth the synth instance.
6628 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6629 * @param portamentomode The portamento mode as indicated by #fluid_channel_portamento_mode.
6631 * - #FLUID_OK on success.
6633 * - \a synth is NULL.
6634 * - \a chan is outside MIDI channel count.
6635 * - \a portamentomode is invalid.
6637 int fluid_synth_set_portamento_mode(fluid_synth_t *synth, int chan,
6640 /* checks parameters first */
6641 fluid_return_val_if_fail(portamentomode >= 0, FLUID_FAILED);
6642 fluid_return_val_if_fail(portamentomode < FLUID_CHANNEL_PORTAMENTO_MODE_LAST, FLUID_FAILED);
6643 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6645 synth->channel[chan]->portamentomode = portamentomode;
6647 FLUID_API_RETURN(FLUID_OK);
6651 * Gets the portamento mode of a channel.
6653 * @param synth the synth instance.
6654 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6655 * @param portamentomode Pointer to the portamento mode as indicated by #fluid_channel_portamento_mode.
6657 * - #FLUID_OK on success.
6659 * - \a synth is NULL.
6660 * - \a chan is outside MIDI channel count.
6661 * - \a portamentomode is NULL.
6663 int fluid_synth_get_portamento_mode(fluid_synth_t *synth, int chan,
6664 int *portamentomode)
6666 /* checks parameters first */
6667 fluid_return_val_if_fail(portamentomode != NULL, FLUID_FAILED);
6668 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6670 * portamentomode = synth->channel[chan]->portamentomode;
6672 FLUID_API_RETURN(FLUID_OK);
6675 /** API breath mode *********************************************************/
6678 * Sets the breath mode of a channel.
6680 * @param synth the synth instance.
6681 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6682 * @param breathmode The breath mode as indicated by #fluid_channel_breath_flags.
6685 * - #FLUID_OK on success.
6687 * - \a synth is NULL.
6688 * - \a chan is outside MIDI channel count.
6690 int fluid_synth_set_breath_mode(fluid_synth_t *synth, int chan, int breathmode)
6692 /* checks parameters first */
6693 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6695 fluid_channel_set_breath_info(synth->channel[chan], breathmode);
6697 FLUID_API_RETURN(FLUID_OK);
6701 * Gets the breath mode of a channel.
6703 * @param synth the synth instance.
6704 * @param chan MIDI channel number (0 to MIDI channel count - 1).
6705 * @param breathmode Pointer to the returned breath mode as indicated by #fluid_channel_breath_flags.
6708 * - #FLUID_OK on success.
6710 * - \a synth is NULL.
6711 * - \a chan is outside MIDI channel count.
6712 * - \a breathmode is NULL.
6714 int fluid_synth_get_breath_mode(fluid_synth_t *synth, int chan, int *breathmode)
6716 /* checks parameters first */
6717 fluid_return_val_if_fail(breathmode != NULL, FLUID_FAILED);
6718 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6720 * breathmode = fluid_channel_get_breath_info(synth->channel[chan]);
6722 FLUID_API_RETURN(FLUID_OK);
6725 /** API Poly/mono mode ******************************************************/
6728 * Resets a basic channel group of MIDI channels.
6729 * @param synth the synth instance.
6730 * @param chan the beginning channel of the group.
6731 * @param nbr_chan the number of channel in the group.
6734 fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan)
6738 for(i = chan; i < chan + nbr_chan; i++)
6740 fluid_channel_reset_basic_channel_info(synth->channel[i]);
6741 synth->channel[i]->mode_val = 0;
6746 * Disables and unassigns all channels from a basic channel group.
6748 * @param synth The synth instance.
6749 * @param chan The basic channel of the group to reset or -1 to reset all channels.
6750 * @note By default (i.e. on creation after new_fluid_synth() and after fluid_synth_system_reset())
6751 * a synth instance has one basic channel at channel 0 in mode #FLUID_CHANNEL_MODE_OMNION_POLY.
6752 * All other channels belong to this basic channel group. Make sure to call this function before
6753 * setting any custom basic channel setup.
6756 * - #FLUID_OK on success.
6758 * - \a synth is NULL.
6759 * - \a chan is outside MIDI channel count.
6760 * - \a chan isn't a basic channel.
6762 int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan)
6766 /* checks parameters first */
6769 fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6770 fluid_synth_api_enter(synth);
6771 /* The range is all MIDI channels from 0 to MIDI channel count -1 */
6772 chan = 0; /* beginning chan */
6773 nbr_chan = synth->midi_channels; /* MIDI Channels number */
6777 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6779 /* checks if chan is a basic channel */
6780 if(!(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC))
6782 FLUID_API_RETURN(FLUID_FAILED);
6785 /* The range is all MIDI channels in the group from chan */
6786 nbr_chan = synth->channel[chan]->mode_val; /* nbr of channels in the group */
6789 /* resets the range of MIDI channels */
6790 fluid_synth_reset_basic_channel_LOCAL(synth, chan, nbr_chan);
6791 FLUID_API_RETURN(FLUID_OK);
6795 * Checks if a new basic channel group overlaps the next basic channel group.
6797 * On success the function returns the possible number of channel for this
6798 * new basic channel group.
6799 * The function fails if the new group overlaps the next basic channel group.
6801 * @param see fluid_synth_set_basic_channel.
6803 * - On success, the effective number of channels for this new basic channel group,
6804 * #FLUID_FAILED otherwise.
6806 * - \a val has a number of channels overlapping next basic channel group or been
6807 * above MIDI channel count.
6810 fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val)
6812 int i, n_chan = synth->midi_channels; /* MIDI Channels count */
6813 int real_val = val; /* real number of channels in the group */
6815 /* adjusts val range */
6816 if(mode == FLUID_CHANNEL_MODE_OMNIOFF_POLY)
6818 real_val = 1; /* mode poly omnioff implies a group of only one channel.*/
6822 /* mode poly omnion (0), mono omnion (1), mono omni off (3) */
6823 /* value 0 means all possible channels from basicchan to MIDI channel count -1.*/
6824 real_val = n_chan - basicchan;
6826 /* checks if val range is above MIDI channel count */
6827 else if(basicchan + val > n_chan)
6829 return FLUID_FAILED;
6832 /* checks if this basic channel group overlaps next basic channel group */
6833 for(i = basicchan + 1; i < basicchan + real_val; i++)
6835 if(synth->channel[i]->mode & FLUID_CHANNEL_BASIC)
6837 /* A value of 0 for val means all possible channels from basicchan to
6838 to the next basic channel -1 (if any).
6839 When i reachs the next basic channel group, real_val will be
6840 limited if it is possible */
6843 /* limitation of real_val */
6844 real_val = i - basicchan;
6848 /* overlap with the next basic channel group */
6849 return FLUID_FAILED;
6857 * Sets a new basic channel group only. The function doesn't allow to change an
6858 * existing basic channel.
6860 * The function fails if any channel overlaps any existing basic channel group.
6861 * To make room if necessary, basic channel groups can be cleared using
6862 * fluid_synth_reset_basic_channel().
6864 * @param synth the synth instance.
6865 * @param chan the basic Channel number (0 to MIDI channel count-1).
6866 * @param mode the MIDI mode to use for chan (see #fluid_basic_channel_modes).
6867 * @param val number of channels in the group.
6868 * @note \a val is only relevant for mode #FLUID_CHANNEL_MODE_OMNION_POLY,
6869 * #FLUID_CHANNEL_MODE_OMNION_MONO and #FLUID_CHANNEL_MODE_OMNIOFF_MONO. A value
6870 * of 0 means all possible channels from \a chan to to next basic channel minus 1 (if any)
6871 * or to MIDI channel count minus 1. Val is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY
6872 * as this mode implies a group of only one channel.
6874 * - #FLUID_OK on success.
6876 * - \a synth is NULL.
6877 * - \a chan is outside MIDI channel count.
6878 * - \a mode is invalid.
6879 * - \a val has a number of channels overlapping another basic channel group or been
6880 * above MIDI channel count.
6881 * - When the function fails, any existing basic channels aren't modified.
6883 int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val)
6885 /* check parameters */
6886 fluid_return_val_if_fail(mode >= 0, FLUID_FAILED);
6887 fluid_return_val_if_fail(mode < FLUID_CHANNEL_MODE_LAST, FLUID_FAILED);
6888 fluid_return_val_if_fail(val >= 0, FLUID_FAILED);
6889 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
6892 if(val > 0 && chan + val > synth->midi_channels)
6894 FLUID_API_RETURN(FLUID_FAILED);
6897 /* Checks if there is an overlap with the next basic channel */
6898 val = fluid_synth_check_next_basic_channel(synth, chan, mode, val);
6900 if(val == FLUID_FAILED || synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)
6902 /* overlap with the next or previous channel group */
6903 FLUID_LOG(FLUID_INFO, "basic channel %d overlaps another group", chan);
6904 FLUID_API_RETURN(FLUID_FAILED);
6907 /* sets a new basic channel group */
6908 fluid_synth_set_basic_channel_LOCAL(synth, chan, mode, val);
6910 FLUID_API_RETURN(FLUID_OK);
6914 * Local version of fluid_synth_set_basic_channel(), called internally:
6915 * - by fluid_synth_set_basic_channel() to set a new basic channel group.
6916 * - during creation new_fluid_synth() or on CC reset to set a default basic channel group.
6917 * - on CC ominoff, CC omnion, CC poly , CC mono to change an existing basic channel group.
6919 * @param see fluid_synth_set_basic_channel()
6922 fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val)
6926 /* sets the basic channel group */
6927 for(i = basicchan; i < basicchan + val; i++)
6929 int new_mode = mode; /* OMNI_OFF/ON, MONO/POLY ,others bits are zero */
6931 /* MIDI specs: when mode is changed, channel must receive ALL_NOTES_OFF */
6932 fluid_synth_all_notes_off_LOCAL(synth, i);
6936 new_mode |= FLUID_CHANNEL_BASIC; /* First channel in the group */
6937 new_val = val; /* number of channels in the group */
6941 new_val = 0; /* val is 0 for other channel than basic channel */
6944 /* Channel is enabled */
6945 new_mode |= FLUID_CHANNEL_ENABLED;
6946 /* Now new_mode is OMNI OFF/ON,MONO/POLY, BASIC_CHANNEL or not and enabled */
6947 fluid_channel_set_basic_channel_info(synth->channel[i], new_mode);
6948 synth->channel[i]->mode_val = new_val;
6953 * Searchs a previous basic channel starting from chan.
6955 * @param synth the synth instance.
6956 * @param chan starting index of the search (including chan).
6957 * @return index of the basic channel if found , FLUID_FAILED otherwise.
6959 static int fluid_synth_get_previous_basic_channel(fluid_synth_t *synth, int chan)
6961 for(; chan >= 0; chan--)
6963 /* searchs previous basic channel */
6964 if(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC)
6966 /* chan is the previous basic channel */
6971 return FLUID_FAILED;
6975 * Returns poly mono mode information of any MIDI channel.
6977 * @param synth the synth instance
6978 * @param chan MIDI channel number (0 to MIDI channel count - 1)
6979 * @param basic_chan_out Buffer to store the basic channel \a chan belongs to or #FLUID_FAILED if \a chan is disabled.
6980 * @param mode_out Buffer to store the mode of \a chan (see #fluid_basic_channel_modes) or #FLUID_FAILED if \a chan is disabled.
6981 * @param val_out Buffer to store the total number of channels in this basic channel group or #FLUID_FAILED if \a chan is disabled.
6982 * @note If any of \a basic_chan_out, \a mode_out, \a val_out pointer is NULL
6983 * the corresponding information isn't returned.
6986 * - #FLUID_OK on success.
6988 * - \a synth is NULL.
6989 * - \a chan is outside MIDI channel count.
6991 int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan,
6992 int *basic_chan_out,
6996 int basic_chan = FLUID_FAILED;
6997 int mode = FLUID_FAILED;
6998 int val = FLUID_FAILED;
7000 /* checks parameters first */
7001 FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7003 if((synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) &&
7004 /* chan is enabled , we search the basic channel chan belongs to */
7005 (basic_chan = fluid_synth_get_previous_basic_channel(synth, chan)) != FLUID_FAILED)
7007 mode = synth->channel[chan]->mode & FLUID_CHANNEL_MODE_MASK;
7008 val = synth->channel[basic_chan]->mode_val;
7011 /* returns the informations if they are requested */
7014 * basic_chan_out = basic_chan;
7027 FLUID_API_RETURN(FLUID_OK);