second part of: change offset arguments to various <T>Buffer::read/merge methods...
[ardour.git] / libs / fluidsynth / src / fluid_synth.c
1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public License
7  * as published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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
18  * 02110-1301, USA
19  */
20
21 #include <math.h>
22
23 #include "fluid_synth.h"
24 #include "fluid_sys.h"
25 #include "fluid_chan.h"
26 #include "fluid_tuning.h"
27 #include "fluid_settings.h"
28 #include "fluid_sfont.h"
29 #include "fluid_hash.h"
30 #include "fluid_defsfont.h"
31
32 #ifdef TRAP_ON_FPE
33 #define _GNU_SOURCE
34 #include <fenv.h>
35
36 /* seems to not be declared in fenv.h */
37 extern int feenableexcept (int excepts);
38 #endif
39
40 static void fluid_synth_init(void);
41
42 static int fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key,
43                                        int vel);
44 static int fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key);
45 static int fluid_synth_cc_LOCAL(fluid_synth_t* synth, int channum, int num);
46 static int fluid_synth_update_device_id (fluid_synth_t *synth, char *name,
47                                          int value);
48 static int fluid_synth_update_overflow (fluid_synth_t *synth, char *name,
49                                          fluid_real_t value);
50 static int fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data,
51                                           int len, char *response,
52                                           int *response_len, int avail_response,
53                                           int *handled, int dryrun);
54 static int fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan);
55 static int fluid_synth_all_sounds_off_LOCAL(fluid_synth_t* synth, int chan);
56 static int fluid_synth_system_reset_LOCAL(fluid_synth_t* synth);
57 static int fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan,
58                                              int is_cc, int ctrl);
59 static int fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t* synth, int chan);
60 static int fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t* synth, int channum);
61 static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t* synth, int chan);
62 static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t* synth, int chan);
63 static int fluid_synth_set_preset (fluid_synth_t *synth, int chan,
64                                    fluid_preset_t *preset);
65 static fluid_preset_t*
66 fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
67                        unsigned int banknum, unsigned int prognum);
68 static fluid_preset_t*
69 fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname,
70                                      unsigned int banknum, unsigned int prognum);
71
72 static void fluid_synth_update_presets(fluid_synth_t* synth);
73 static int fluid_synth_update_sample_rate(fluid_synth_t* synth,
74                                    char* name, double value);
75 static int fluid_synth_update_gain(fluid_synth_t* synth,
76                                    char* name, double value);
77 static void fluid_synth_update_gain_LOCAL(fluid_synth_t* synth);
78 static int fluid_synth_update_polyphony(fluid_synth_t* synth,
79                                         char* name, int value);
80 static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony);
81 static void init_dither(void);
82 static inline int roundi (float x);
83 static int fluid_synth_render_blocks(fluid_synth_t* synth, int blockcount);
84 //static void fluid_synth_core_thread_func (void* data);
85 //static FLUID_INLINE void fluid_synth_process_event_queue_LOCAL
86 //  (fluid_synth_t *synth, fluid_event_queue_t *queue);
87 static fluid_voice_t* fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth);
88 static void fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth,
89                                                       fluid_voice_t* new_voice);
90 static fluid_sfont_info_t *new_fluid_sfont_info (fluid_synth_t *synth,
91                                                  fluid_sfont_t *sfont);
92 static int fluid_synth_sfunload_callback(void* data, unsigned int msec);
93 static void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth,
94                                                             int chan, int key);
95 static fluid_tuning_t* fluid_synth_get_tuning(fluid_synth_t* synth,
96                                               int bank, int prog);
97 static int fluid_synth_replace_tuning_LOCK (fluid_synth_t* synth,
98                                             fluid_tuning_t *tuning,
99                                             int bank, int prog, int apply);
100 static void fluid_synth_replace_tuning_LOCAL (fluid_synth_t *synth,
101                                               fluid_tuning_t *old_tuning,
102                                               fluid_tuning_t *new_tuning,
103                                               int apply, int unref_new);
104 static void fluid_synth_update_voice_tuning_LOCAL (fluid_synth_t *synth,
105                                                    fluid_channel_t *channel);
106 static int fluid_synth_set_tuning_LOCAL (fluid_synth_t *synth, int chan,
107                                          fluid_tuning_t *tuning, int apply);
108 static void fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan,
109                                        int param, float value, int absolute);
110 static void fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id);
111
112
113
114 /***************************************************************
115  *
116  *                         GLOBAL
117  */
118
119 /* has the synth module been initialized? */
120 static int fluid_synth_initialized = 0;
121 static void fluid_synth_init(void);
122 static void init_dither(void);
123
124 /* default modulators
125  * SF2.01 page 52 ff:
126  *
127  * There is a set of predefined default modulators. They have to be
128  * explicitly overridden by the sound font in order to turn them off.
129  */
130
131 fluid_mod_t default_vel2att_mod;        /* SF2.01 section 8.4.1  */
132 fluid_mod_t default_vel2filter_mod;     /* SF2.01 section 8.4.2  */
133 fluid_mod_t default_at2viblfo_mod;      /* SF2.01 section 8.4.3  */
134 fluid_mod_t default_mod2viblfo_mod;     /* SF2.01 section 8.4.4  */
135 fluid_mod_t default_att_mod;            /* SF2.01 section 8.4.5  */
136 fluid_mod_t default_pan_mod;            /* SF2.01 section 8.4.6  */
137 fluid_mod_t default_expr_mod;           /* SF2.01 section 8.4.7  */
138 fluid_mod_t default_reverb_mod;         /* SF2.01 section 8.4.8  */
139 fluid_mod_t default_chorus_mod;         /* SF2.01 section 8.4.9  */
140 fluid_mod_t default_pitch_bend_mod;     /* SF2.01 section 8.4.10 */
141
142 /* reverb presets */
143 static fluid_revmodel_presets_t revmodel_preset[] = {
144   /* name */    /* roomsize */ /* damp */ /* width */ /* level */
145   { "Test 1",          0.2f,      0.0f,       0.5f,       0.9f },
146   { "Test 2",          0.4f,      0.2f,       0.5f,       0.8f },
147   { "Test 3",          0.6f,      0.4f,       0.5f,       0.7f },
148   { "Test 4",          0.8f,      0.7f,       0.5f,       0.6f },
149   { "Test 5",          0.8f,      1.0f,       0.5f,       0.5f },
150   { NULL, 0.0f, 0.0f, 0.0f, 0.0f }
151 };
152
153
154 /***************************************************************
155  *
156  *               INITIALIZATION & UTILITIES
157  */
158
159 static void fluid_synth_register_overflow(fluid_settings_t* settings,
160                                           fluid_num_update_t update_func,
161                                           void* update_data)
162 {
163   fluid_settings_register_num(settings, "synth.overflow.percussion",
164                               4000, -10000, 10000, 0, update_func, update_data);
165   fluid_settings_register_num(settings, "synth.overflow.sustained",
166                               -1000, -10000, 10000, 0, update_func, update_data);
167   fluid_settings_register_num(settings, "synth.overflow.released",
168                               -2000, -10000, 10000, 0, update_func, update_data);
169   fluid_settings_register_num(settings, "synth.overflow.age",
170                               1000, -10000, 10000, 0, update_func, update_data);
171   fluid_settings_register_num(settings, "synth.overflow.volume",
172                               500, -10000, 10000, 0, update_func, update_data);  
173 }
174
175 void fluid_synth_settings(fluid_settings_t* settings)
176 {
177   fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1,
178                               FLUID_HINT_TOGGLED, NULL, NULL);
179   fluid_settings_register_int(settings, "synth.dump", 0, 0, 1,
180                               FLUID_HINT_TOGGLED, NULL, NULL);
181   fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1,
182                               FLUID_HINT_TOGGLED, NULL, NULL);
183   fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1,
184                               FLUID_HINT_TOGGLED, NULL, NULL);
185   fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1,
186                               FLUID_HINT_TOGGLED, NULL, NULL);
187   fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1,
188                               FLUID_HINT_TOGGLED, NULL, NULL);
189   fluid_settings_register_str(settings, "midi.portname", "", 0, NULL, NULL);
190
191   fluid_settings_register_str(settings, "synth.default-soundfont",
192                               DEFAULT_SOUNDFONT, 0, NULL, NULL);
193
194   fluid_settings_register_int(settings, "synth.polyphony",
195                               256, 1, 65535, 0, NULL, NULL);
196   fluid_settings_register_int(settings, "synth.midi-channels",
197                               16, 16, 256, 0, NULL, NULL);
198   fluid_settings_register_num(settings, "synth.gain",
199                               0.2f, 0.0f, 10.0f,
200                               0, NULL, NULL);
201   fluid_settings_register_int(settings, "synth.audio-channels",
202                               1, 1, 128, 0, NULL, NULL);
203   fluid_settings_register_int(settings, "synth.audio-groups",
204                               1, 1, 128, 0, NULL, NULL);
205   fluid_settings_register_int(settings, "synth.effects-channels",
206                               2, 2, 2, 0, NULL, NULL);
207   fluid_settings_register_num(settings, "synth.sample-rate",
208                               44100.0f, 8000.0f, 96000.0f,
209                               0, NULL, NULL);
210   fluid_settings_register_int(settings, "synth.device-id",
211                               0, 0, 126, 0, NULL, NULL);
212   fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0, NULL, NULL);
213
214   fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0, NULL, NULL);
215   
216   fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1,
217                               FLUID_HINT_TOGGLED, NULL, NULL);
218   fluid_settings_register_int(settings, "synth.parallel-render", 1, 0, 1,
219                               FLUID_HINT_TOGGLED, NULL, NULL);
220
221   fluid_synth_register_overflow(settings, NULL, NULL);
222
223   fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0, NULL, NULL);
224   fluid_settings_add_option(settings, "synth.midi-bank-select", "gm");
225   fluid_settings_add_option(settings, "synth.midi-bank-select", "gs");
226   fluid_settings_add_option(settings, "synth.midi-bank-select", "xg");
227   fluid_settings_add_option(settings, "synth.midi-bank-select", "mma");
228   
229 }
230
231 /**
232  * Get FluidSynth runtime version.
233  * @param major Location to store major number
234  * @param minor Location to store minor number
235  * @param micro Location to store micro number
236  */
237 void fluid_version(int *major, int *minor, int *micro)
238 {
239   *major = FLUIDSYNTH_VERSION_MAJOR;
240   *minor = FLUIDSYNTH_VERSION_MINOR;
241   *micro = FLUIDSYNTH_VERSION_MICRO;
242 }
243
244 /**
245  * Get FluidSynth runtime version as a string.
246  * @return FluidSynth version string, which is internal and should not be
247  *   modified or freed.
248  */
249 char *
250 fluid_version_str (void)
251 {
252   return FLUIDSYNTH_VERSION;
253 }
254
255 #define FLUID_API_ENTRY_CHAN(fail_value)  \
256   fluid_return_val_if_fail (synth != NULL, fail_value); \
257   fluid_return_val_if_fail (chan >= 0, fail_value); \
258   fluid_synth_api_enter(synth); \
259   if (chan >= synth->midi_channels) { \
260     fluid_synth_api_exit(synth); \
261     return fail_value; \
262   } \
263
264 #define FLUID_API_RETURN(return_value) \
265   do { fluid_synth_api_exit(synth); \
266   return return_value; } while (0)
267   
268 /*
269  * void fluid_synth_init
270  *
271  * Does all the initialization for this module.
272  */
273 static void
274 fluid_synth_init(void)
275 {
276   fluid_synth_initialized++;
277
278 #ifdef TRAP_ON_FPE
279   /* Turn on floating point exception traps */
280   feenableexcept (FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID);
281 #endif
282
283   fluid_conversion_config();
284
285   fluid_rvoice_dsp_config();
286
287   fluid_sys_config();
288
289   init_dither();
290
291
292   /* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */
293   fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */
294                        FLUID_MOD_VELOCITY,    /* Source. VELOCITY corresponds to 'index=2'. */
295                        FLUID_MOD_GC           /* Not a MIDI continuous controller */
296                        | FLUID_MOD_CONCAVE    /* Curve shape. Corresponds to 'type=1' */
297                        | FLUID_MOD_UNIPOLAR   /* Polarity. Corresponds to 'P=0' */
298                        | FLUID_MOD_NEGATIVE   /* Direction. Corresponds to 'D=1' */
299                        );
300   fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */
301   fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION);  /* Target: Initial attenuation */
302   fluid_mod_set_amount(&default_vel2att_mod, 960.0);          /* Modulation amount: 960 */
303
304
305
306   /* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff
307    * Have to make a design decision here. The specs don't make any sense this way or another.
308    * One sound font, 'Kingston Piano', which has been praised for its quality, tries to
309    * override this modulator with an amount of 0 and positive polarity (instead of what
310    * the specs say, D=1) for the secondary source.
311    * So if we change the polarity to 'positive', one of the best free sound fonts works...
312    */
313   fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
314                        FLUID_MOD_GC                        /* CC=0 */
315                        | FLUID_MOD_LINEAR                  /* type=0 */
316                        | FLUID_MOD_UNIPOLAR                /* P=0 */
317                        | FLUID_MOD_NEGATIVE                /* D=1 */
318                        );
319   fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
320                        FLUID_MOD_GC                                 /* CC=0 */
321                        | FLUID_MOD_SWITCH                           /* type=3 */
322                        | FLUID_MOD_UNIPOLAR                         /* P=0 */
323                        // do not remove       | FLUID_MOD_NEGATIVE                         /* D=1 */
324                        | FLUID_MOD_POSITIVE                         /* D=0 */
325                        );
326   fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC);        /* Target: Initial filter cutoff */
327   fluid_mod_set_amount(&default_vel2filter_mod, -2400);
328
329
330
331   /* SF2.01 page 53 section 8.4.3: MIDI Channel pressure to Vibrato LFO pitch depth */
332   fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE, /* Index=13 */
333                        FLUID_MOD_GC                        /* CC=0 */
334                        | FLUID_MOD_LINEAR                  /* type=0 */
335                        | FLUID_MOD_UNIPOLAR                /* P=0 */
336                        | FLUID_MOD_POSITIVE                /* D=0 */
337                        );
338   fluid_mod_set_source2(&default_at2viblfo_mod, 0,0); /* no second source */
339   fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH);        /* Target: Vib. LFO => pitch */
340   fluid_mod_set_amount(&default_at2viblfo_mod, 50);
341
342
343
344   /* SF2.01 page 53 section 8.4.4: Mod wheel (Controller 1) to Vibrato LFO pitch depth */
345   fluid_mod_set_source1(&default_mod2viblfo_mod, 1, /* Index=1 */
346                        FLUID_MOD_CC                        /* CC=1 */
347                        | FLUID_MOD_LINEAR                  /* type=0 */
348                        | FLUID_MOD_UNIPOLAR                /* P=0 */
349                        | FLUID_MOD_POSITIVE                /* D=0 */
350                        );
351   fluid_mod_set_source2(&default_mod2viblfo_mod, 0,0); /* no second source */
352   fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH);        /* Target: Vib. LFO => pitch */
353   fluid_mod_set_amount(&default_mod2viblfo_mod, 50);
354
355
356
357   /* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/
358   fluid_mod_set_source1(&default_att_mod, 7,                     /* index=7 */
359                        FLUID_MOD_CC                              /* CC=1 */
360                        | FLUID_MOD_CONCAVE                       /* type=1 */
361                        | FLUID_MOD_UNIPOLAR                      /* P=0 */
362                        | FLUID_MOD_NEGATIVE                      /* D=1 */
363                        );
364   fluid_mod_set_source2(&default_att_mod, 0, 0);                 /* No second source */
365   fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION);         /* Target: Initial attenuation */
366   fluid_mod_set_amount(&default_att_mod, 960.0);                 /* Amount: 960 */
367
368
369
370   /* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */
371   fluid_mod_set_source1(&default_pan_mod, 10,                    /* index=10 */
372                        FLUID_MOD_CC                              /* CC=1 */
373                        | FLUID_MOD_LINEAR                        /* type=0 */
374                        | FLUID_MOD_BIPOLAR                       /* P=1 */
375                        | FLUID_MOD_POSITIVE                      /* D=0 */
376                        );
377   fluid_mod_set_source2(&default_pan_mod, 0, 0);                 /* No second source */
378   fluid_mod_set_dest(&default_pan_mod, GEN_PAN);                 /* Target: pan */
379   /* Amount: 500. The SF specs $8.4.6, p. 55 syas: "Amount = 1000
380      tenths of a percent". The center value (64) corresponds to 50%,
381      so it follows that amount = 50% x 1000/% = 500. */
382   fluid_mod_set_amount(&default_pan_mod, 500.0);
383
384
385   /* SF2.01 page 55 section 8.4.7: MIDI continuous controller 11 to initial attenuation*/
386   fluid_mod_set_source1(&default_expr_mod, 11,                     /* index=11 */
387                        FLUID_MOD_CC                              /* CC=1 */
388                        | FLUID_MOD_CONCAVE                       /* type=1 */
389                        | FLUID_MOD_UNIPOLAR                      /* P=0 */
390                        | FLUID_MOD_NEGATIVE                      /* D=1 */
391                        );
392   fluid_mod_set_source2(&default_expr_mod, 0, 0);                 /* No second source */
393   fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION);         /* Target: Initial attenuation */
394   fluid_mod_set_amount(&default_expr_mod, 960.0);                 /* Amount: 960 */
395
396
397
398   /* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */
399   fluid_mod_set_source1(&default_reverb_mod, 91,                 /* index=91 */
400                        FLUID_MOD_CC                              /* CC=1 */
401                        | FLUID_MOD_LINEAR                        /* type=0 */
402                        | FLUID_MOD_UNIPOLAR                      /* P=0 */
403                        | FLUID_MOD_POSITIVE                      /* D=0 */
404                        );
405   fluid_mod_set_source2(&default_reverb_mod, 0, 0);              /* No second source */
406   fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND);       /* Target: Reverb send */
407   fluid_mod_set_amount(&default_reverb_mod, 200);                /* Amount: 200 ('tenths of a percent') */
408
409
410
411   /* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Chorus send */
412   fluid_mod_set_source1(&default_chorus_mod, 93,                 /* index=93 */
413                        FLUID_MOD_CC                              /* CC=1 */
414                        | FLUID_MOD_LINEAR                        /* type=0 */
415                        | FLUID_MOD_UNIPOLAR                      /* P=0 */
416                        | FLUID_MOD_POSITIVE                      /* D=0 */
417                        );
418   fluid_mod_set_source2(&default_chorus_mod, 0, 0);              /* No second source */
419   fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND);       /* Target: Chorus */
420   fluid_mod_set_amount(&default_chorus_mod, 200);                /* Amount: 200 ('tenths of a percent') */
421
422
423
424   /* SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch ... */
425   fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL, /* Index=14 */
426                        FLUID_MOD_GC                              /* CC =0 */
427                        | FLUID_MOD_LINEAR                        /* type=0 */
428                        | FLUID_MOD_BIPOLAR                       /* P=1 */
429                        | FLUID_MOD_POSITIVE                      /* D=0 */
430                        );
431   fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS,  /* Index = 16 */
432                        FLUID_MOD_GC                                        /* CC=0 */
433                        | FLUID_MOD_LINEAR                                  /* type=0 */
434                        | FLUID_MOD_UNIPOLAR                                /* P=0 */
435                        | FLUID_MOD_POSITIVE                                /* D=0 */
436                        );
437   fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH);                 /* Destination: Initial pitch */
438   fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0);                 /* Amount: 12700 cents */
439 }
440
441 static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t* synth)
442 {
443   if (synth->eventhandler->is_threadsafe)
444     return fluid_atomic_int_get(&synth->ticks_since_start);
445   else
446     return synth->ticks_since_start;
447 }
448
449 static FLUID_INLINE void fluid_synth_add_ticks(fluid_synth_t* synth, int val)
450 {
451   if (synth->eventhandler->is_threadsafe)
452     fluid_atomic_int_add((int*) &synth->ticks_since_start, val);
453   else
454     synth->ticks_since_start += val;
455 }
456
457
458 /***************************************************************
459  *                    FLUID SAMPLE TIMERS 
460  *    Timers that use written audio data as timing reference       
461  */
462 struct _fluid_sample_timer_t
463 {
464         fluid_sample_timer_t* next; /* Single linked list of timers */
465         unsigned long starttick;
466         fluid_timer_callback_t callback;
467         void* data;
468         int isfinished;
469 };
470
471 /*
472  * fluid_sample_timer_process - called when synth->ticks is updated
473  */
474 static void fluid_sample_timer_process(fluid_synth_t* synth)
475 {
476         fluid_sample_timer_t* st;
477         long msec;
478         int cont;
479         unsigned int ticks = fluid_synth_get_ticks(synth);
480         
481         for (st=synth->sample_timers; st; st=st->next) {
482                 if (st->isfinished) {
483                         continue;
484                 }
485
486                 msec = (long) (1000.0*((double) (ticks - st->starttick))/synth->sample_rate);
487                 cont = (*st->callback)(st->data, msec);
488                 if (cont == 0) {
489                         st->isfinished = 1;
490                 }
491         }
492 }
493
494 fluid_sample_timer_t* new_fluid_sample_timer(fluid_synth_t* synth, fluid_timer_callback_t callback, void* data)
495 {
496         fluid_sample_timer_t* result = FLUID_NEW(fluid_sample_timer_t);
497         if (result == NULL) {
498                 FLUID_LOG(FLUID_ERR, "Out of memory");
499                 return NULL;
500         }
501         result->starttick = fluid_synth_get_ticks(synth);
502         result->isfinished = 0;
503         result->data = data;
504         result->callback = callback;
505         result->next = synth->sample_timers;
506         synth->sample_timers = result;
507         return result;          
508 }
509
510 int delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t* timer)
511 {
512         fluid_sample_timer_t** ptr = &synth->sample_timers;
513         while (*ptr) {
514                 if (*ptr == timer) {
515                         *ptr = timer->next; 
516                         FLUID_FREE(timer);
517                         return FLUID_OK;
518                 }
519                 ptr = &((*ptr)->next);
520         }
521         FLUID_LOG(FLUID_ERR,"delete_fluid_sample_timer failed, no timer found");
522         return FLUID_FAILED;
523 }
524
525
526 /***************************************************************
527  *
528  *                      FLUID SYNTH
529  */
530
531 static FLUID_INLINE void
532 fluid_synth_update_mixer(fluid_synth_t* synth, void* method, int intparam,
533                          fluid_real_t realparam)
534 {
535   fluid_return_if_fail(synth != NULL || synth->eventhandler != NULL);
536   fluid_return_if_fail(synth->eventhandler->mixer != NULL);
537   fluid_rvoice_eventhandler_push(synth->eventhandler, method, 
538                                  synth->eventhandler->mixer,
539                                  intparam, realparam);
540 }
541
542
543 /**
544  * Create new FluidSynth instance.
545  * @param settings Configuration parameters to use (used directly).
546  * @return New FluidSynth instance or NULL on error
547  *
548  * NOTE: The settings parameter is used directly and should not be modified
549  * or freed independently.
550  */
551 fluid_synth_t*
552 new_fluid_synth(fluid_settings_t *settings)
553 {
554   fluid_synth_t* synth;
555   fluid_sfloader_t* loader;
556   double gain;
557   int i, nbuf;
558
559   /* initialize all the conversion tables and other stuff */
560   if (fluid_synth_initialized == 0) {
561     fluid_synth_init();
562   }
563
564   /* allocate a new synthesizer object */
565   synth = FLUID_NEW(fluid_synth_t);
566   if (synth == NULL) {
567     FLUID_LOG(FLUID_ERR, "Out of memory");
568     return NULL;
569   }
570   FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t));
571
572   fluid_rec_mutex_init(synth->mutex);
573   fluid_settings_getint(settings, "synth.threadsafe-api", &synth->use_mutex);
574   synth->public_api_count = 0;
575   
576   synth->settings = settings;
577
578   fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb);
579   fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus);
580   fluid_settings_getint(settings, "synth.verbose", &synth->verbose);
581   fluid_settings_getint(settings, "synth.dump", &synth->dump);
582
583   fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
584   fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate);
585   fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels);
586   fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
587   fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups);
588   fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
589   fluid_settings_getnum(settings, "synth.gain", &gain);
590   synth->gain = gain;
591   fluid_settings_getint(settings, "synth.device-id", &synth->device_id);
592   fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores);
593
594   /* register the callbacks */
595   fluid_settings_register_num(settings, "synth.sample-rate",
596                               44100.0f, 8000.0f, 96000.0f, 0,
597                               (fluid_num_update_t) fluid_synth_update_sample_rate, synth);
598   fluid_settings_register_num(settings, "synth.gain",
599                               0.2f, 0.0f, 10.0f, 0,
600                               (fluid_num_update_t) fluid_synth_update_gain, synth);
601   fluid_settings_register_int(settings, "synth.polyphony",
602                               synth->polyphony, 1, 65535, 0,
603                               (fluid_int_update_t) fluid_synth_update_polyphony,
604                               synth);
605   fluid_settings_register_int(settings, "synth.device-id",
606                               synth->device_id, 126, 0, 0,
607                               (fluid_int_update_t) fluid_synth_update_device_id, synth);
608
609   fluid_synth_register_overflow(settings, 
610                                 (fluid_num_update_t) fluid_synth_update_overflow, synth);
611                                 
612   /* do some basic sanity checking on the settings */
613
614   if (synth->midi_channels % 16 != 0) {
615     int n = synth->midi_channels / 16;
616     synth->midi_channels = (n + 1) * 16;
617     fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels);
618     FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. "
619              "I'll increase the number of channels to the next multiple.");
620   }
621
622   if (synth->audio_channels < 1) {
623     FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. "
624              "Changing this setting to 1.");
625     synth->audio_channels = 1;
626   } else if (synth->audio_channels > 128) {
627     FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). "
628              "Limiting this setting to 128.", synth->audio_channels);
629     synth->audio_channels = 128;
630   }
631
632   if (synth->audio_groups < 1) {
633     FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. "
634              "Changing this setting to 1.");
635     synth->audio_groups = 1;
636   } else if (synth->audio_groups > 128) {
637     FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). "
638              "Limiting this setting to 128.", synth->audio_groups);
639     synth->audio_groups = 128;
640   }
641
642   if (synth->effects_channels < 2) {
643     FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)."
644              "Setting effects channels to 2.", synth->effects_channels);
645     synth->effects_channels = 2;
646   }
647
648
649   /* The number of buffers is determined by the higher number of nr
650    * groups / nr audio channels.  If LADSPA is unused, they should be
651    * the same. */
652   nbuf = synth->audio_channels;
653   if (synth->audio_groups > nbuf) {
654     nbuf = synth->audio_groups;
655   }
656
657   /* as soon as the synth is created it starts playing. */
658   synth->state = FLUID_SYNTH_PLAYING;
659   synth->sfont_info = NULL;
660   synth->sfont_hash = new_fluid_hashtable (NULL, NULL);
661   synth->noteid = 0;
662   synth->ticks_since_start = 0;
663   synth->tuning = NULL;
664   fluid_private_init(synth->tuning_iter);
665
666   /* Allocate event queue for rvoice mixer */
667   fluid_settings_getint(settings, "synth.parallel-render", &i);
668   /* In an overflow situation, a new voice takes about 50 spaces in the queue! */
669   synth->eventhandler = new_fluid_rvoice_eventhandler(i, synth->polyphony*64,
670         synth->polyphony, nbuf, synth->effects_channels, synth->sample_rate);
671
672   if (synth->eventhandler == NULL)
673     goto error_recovery; 
674
675 #ifdef LADSPA
676   /* Create and initialize the Fx unit.*/
677   synth->LADSPA_FxUnit = new_fluid_LADSPA_FxUnit(synth);
678   fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->LADSPA_FxUnit);
679 #endif
680   
681   /* allocate and add the default sfont loader */
682   loader = new_fluid_defsfloader(settings);
683
684   if (loader == NULL) {
685     FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader");
686   } else {
687     fluid_synth_add_sfloader(synth, loader);
688   }
689
690   /* allocate all channel objects */
691   synth->channel = FLUID_ARRAY(fluid_channel_t*, synth->midi_channels);
692   if (synth->channel == NULL) {
693     FLUID_LOG(FLUID_ERR, "Out of memory");
694     goto error_recovery;
695   }
696   for (i = 0; i < synth->midi_channels; i++) {
697     synth->channel[i] = new_fluid_channel(synth, i);
698     if (synth->channel[i] == NULL) {
699       goto error_recovery;
700     }
701   }
702
703   /* allocate all synthesis processes */
704   synth->nvoice = synth->polyphony;
705   synth->voice = FLUID_ARRAY(fluid_voice_t*, synth->nvoice);
706   if (synth->voice == NULL) {
707     goto error_recovery;
708   }
709   for (i = 0; i < synth->nvoice; i++) {
710     synth->voice[i] = new_fluid_voice(synth->sample_rate);
711     if (synth->voice[i] == NULL) {
712       goto error_recovery;
713     }
714   }
715
716   fluid_synth_set_sample_rate(synth, synth->sample_rate);
717   
718   fluid_synth_update_overflow(synth, "", 0.0f);
719   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, 
720                            synth->polyphony, 0.0f);
721   fluid_synth_set_reverb_on(synth, synth->with_reverb);
722   fluid_synth_set_chorus_on(synth, synth->with_chorus);
723                                  
724   synth->cur = FLUID_BUFSIZE;
725   synth->curmax = 0;
726   synth->dither_index = 0;
727
728   synth->reverb_roomsize = FLUID_REVERB_DEFAULT_ROOMSIZE;
729   synth->reverb_damping = FLUID_REVERB_DEFAULT_DAMP;
730   synth->reverb_width = FLUID_REVERB_DEFAULT_WIDTH;
731   synth->reverb_level = FLUID_REVERB_DEFAULT_LEVEL;
732
733   fluid_rvoice_eventhandler_push5(synth->eventhandler, 
734                                   fluid_rvoice_mixer_set_reverb_params,
735                                   synth->eventhandler->mixer, 
736                                   FLUID_REVMODEL_SET_ALL, synth->reverb_roomsize, 
737                                   synth->reverb_damping, synth->reverb_width, 
738                                   synth->reverb_level, 0.0f);
739
740   /* Initialize multi-core variables if multiple cores enabled */
741   if (synth->cores > 1)
742   {
743     int prio_level = 0;
744     fluid_settings_getint (synth->settings, "audio.realtime-prio", &prio_level);
745     fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_threads, 
746                              synth->cores-1, prio_level);
747   }
748
749   synth->bank_select = FLUID_BANK_STYLE_GS;
750   if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "gm") == 1)
751     synth->bank_select = FLUID_BANK_STYLE_GM;
752   else if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "gs") == 1)
753     synth->bank_select = FLUID_BANK_STYLE_GS;
754   else if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "xg") == 1)
755     synth->bank_select = FLUID_BANK_STYLE_XG;
756   else if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "mma") == 1)
757     synth->bank_select = FLUID_BANK_STYLE_MMA;
758
759   fluid_synth_process_event_queue(synth);
760
761   /* FIXME */
762   synth->start = fluid_curtime();
763
764   return synth;
765
766  error_recovery:
767   delete_fluid_synth(synth);
768   return NULL;
769 }
770
771
772 /**
773  * Delete a FluidSynth instance.
774  * @param synth FluidSynth instance to delete
775  * @return FLUID_OK
776  *
777  * NOTE: Other users of a synthesizer instance, such as audio and MIDI drivers,
778  * should be deleted prior to freeing the FluidSynth instance.
779  */
780 int
781 delete_fluid_synth(fluid_synth_t* synth)
782 {
783   int i, k;
784   fluid_list_t *list;
785   fluid_sfont_info_t* sfont_info;
786 //  fluid_event_queue_t* queue;
787   fluid_sfloader_t* loader;
788
789   if (synth == NULL) {
790     return FLUID_OK;
791   }
792
793   fluid_profiling_print();
794
795   /* turn off all voices, needed to unload SoundFont data */
796   if (synth->voice != NULL) {
797     for (i = 0; i < synth->nvoice; i++) {
798       fluid_voice_t* voice = synth->voice[i];
799       if (!voice)
800         continue;
801       fluid_voice_unlock_rvoice(voice);
802       fluid_voice_overflow_rvoice_finished(voice); 
803       if (fluid_voice_is_playing(voice))
804         fluid_voice_off(voice);
805     }
806   }
807
808   /* also unset all presets for clean SoundFont unload */
809   if (synth->channel != NULL)
810     for (i = 0; i < synth->midi_channels; i++)
811       if (synth->channel[i] != NULL)
812         fluid_channel_set_preset(synth->channel[i], NULL);
813
814   if (synth->eventhandler)
815     delete_fluid_rvoice_eventhandler(synth->eventhandler);
816
817   /* delete all the SoundFonts */
818   for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
819     sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
820     delete_fluid_sfont (sfont_info->sfont);
821     FLUID_FREE (sfont_info);
822   }
823
824   delete_fluid_list(synth->sfont_info);
825
826
827   /* Delete the SoundFont info hash */
828   if (synth->sfont_hash) delete_fluid_hashtable (synth->sfont_hash);
829
830
831   /* delete all the SoundFont loaders */
832
833   for (list = synth->loaders; list; list = fluid_list_next(list)) {
834     loader = (fluid_sfloader_t*) fluid_list_get(list);
835     fluid_sfloader_delete(loader);
836   }
837
838   delete_fluid_list(synth->loaders);
839
840
841   if (synth->channel != NULL) {
842     for (i = 0; i < synth->midi_channels; i++) {
843       if (synth->channel[i] != NULL) {
844         delete_fluid_channel(synth->channel[i]);
845       }
846     }
847     FLUID_FREE(synth->channel);
848   }
849
850   if (synth->voice != NULL) {
851     for (i = 0; i < synth->nvoice; i++) {
852       if (synth->voice[i] != NULL) {
853         delete_fluid_voice(synth->voice[i]);
854       }
855     }
856     FLUID_FREE(synth->voice);
857   }
858
859
860   /* free the tunings, if any */
861   if (synth->tuning != NULL) {
862     for (i = 0; i < 128; i++) {
863       if (synth->tuning[i] != NULL) {
864         for (k = 0; k < 128; k++) {
865           if (synth->tuning[i][k] != NULL) {
866             delete_fluid_tuning(synth->tuning[i][k]);
867           }
868         }
869         FLUID_FREE(synth->tuning[i]);
870       }
871     }
872     FLUID_FREE(synth->tuning);
873   }
874
875   fluid_private_free (synth->tuning_iter);
876
877 #ifdef LADSPA
878   /* Release the LADSPA Fx unit */
879   fluid_LADSPA_shutdown(synth->LADSPA_FxUnit);
880   FLUID_FREE(synth->LADSPA_FxUnit);
881 #endif
882
883   fluid_rec_mutex_destroy(synth->mutex);
884
885   FLUID_FREE(synth);
886
887   return FLUID_OK;
888 }
889
890 /**
891  * Get a textual representation of the last error
892  * @param synth FluidSynth instance
893  * @return Pointer to string of last error message.  Valid until the same
894  *   calling thread calls another FluidSynth function which fails.  String is
895  *   internal and should not be modified or freed.
896  */
897 /* FIXME - The error messages are not thread-safe, yet. They are still stored
898  * in a global message buffer (see fluid_sys.c). */
899 char*
900 fluid_synth_error(fluid_synth_t* synth)
901 {
902   return fluid_error();
903 }
904
905 /**
906  * Send a note-on event to a FluidSynth object.
907  * @param synth FluidSynth instance
908  * @param chan MIDI channel number (0 to MIDI channel count - 1)
909  * @param key MIDI note number (0-127)
910  * @param vel MIDI velocity (0-127, 0=noteoff)
911  * @return FLUID_OK on success, FLUID_FAILED otherwise
912  */
913 int
914 fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel)
915 {
916   int result;
917   fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED);
918   fluid_return_val_if_fail (vel >= 0 && vel <= 127, FLUID_FAILED);
919   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
920
921   result = fluid_synth_noteon_LOCAL (synth, chan, key, vel);
922   FLUID_API_RETURN(result);
923 }
924
925 /* Local synthesis thread variant of fluid_synth_noteon */
926 static int
927 fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key, int vel)
928 {
929   fluid_channel_t* channel;
930
931   /* notes with velocity zero go to noteoff  */
932   if (vel == 0) return fluid_synth_noteoff_LOCAL(synth, chan, key);
933
934   channel = synth->channel[chan];
935   
936   /* make sure this channel has a preset */
937   if (channel->preset == NULL) {
938     if (synth->verbose) {
939       FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s",
940                chan, key, vel, 0,
941                fluid_synth_get_ticks(synth) / 44100.0f,
942                (fluid_curtime() - synth->start) / 1000.0f,
943                0.0f, 0, "channel has no preset");
944     }
945     return FLUID_FAILED;
946   }
947
948   /* If there is another voice process on the same channel and key,
949      advance it to the release phase. */
950   fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key);
951
952
953   return fluid_preset_noteon(channel->preset, synth, chan, key, vel);
954 }
955
956 /**
957  * Send a note-off event to a FluidSynth object.
958  * @param synth FluidSynth instance
959  * @param chan MIDI channel number (0 to MIDI channel count - 1)
960  * @param key MIDI note number (0-127)
961  * @return FLUID_OK on success, FLUID_FAILED otherwise (may just mean that no
962  *   voices matched the note off event)
963  */
964 int
965 fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key)
966 {
967   int result;
968   fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED);
969   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
970
971   result = fluid_synth_noteoff_LOCAL (synth, chan, key);
972   
973   FLUID_API_RETURN(result);
974 }
975
976 /* Local synthesis thread variant of fluid_synth_noteoff */
977 static int
978 fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key)
979 {
980   fluid_voice_t* voice;
981   int status = FLUID_FAILED;
982   int i;
983
984   for (i = 0; i < synth->polyphony; i++) {
985     voice = synth->voice[i];
986     if (_ON(voice) && (voice->chan == chan) && (voice->key == key)) {
987       if (synth->verbose) {
988         int used_voices = 0;
989         int k;
990         for (k = 0; k < synth->polyphony; k++) {
991           if (!_AVAILABLE(synth->voice[k])) {
992             used_voices++;
993           }
994         }
995         FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%d",
996                  voice->chan, voice->key, 0, voice->id,
997                  (fluid_curtime() - synth->start) / 1000.0f,
998                  used_voices);
999       } /* if verbose */
1000
1001       fluid_voice_noteoff(voice);
1002       status = FLUID_OK;
1003     } /* if voice on */
1004   } /* for all voices */
1005   return status;
1006 }
1007
1008 /* Damp voices on a channel (turn notes off), if they're sustained by
1009    sustain pedal */
1010 static int
1011 fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t* synth, int chan)
1012 {
1013   fluid_voice_t* voice;
1014   int i;
1015
1016   for (i = 0; i < synth->polyphony; i++) {
1017     voice = synth->voice[i];
1018
1019     if ((voice->chan == chan) && _SUSTAINED(voice))
1020      fluid_voice_release(voice);
1021   }
1022
1023   return FLUID_OK;
1024 }
1025
1026 /* Damp voices on a channel (turn notes off), if they're sustained by
1027    sostenuto pedal */
1028 static int
1029 fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t* synth, int chan)
1030 {
1031   fluid_voice_t* voice;
1032   int i;
1033
1034   for (i = 0; i < synth->polyphony; i++) {
1035     voice = synth->voice[i];
1036
1037     if ((voice->chan == chan) && _HELD_BY_SOSTENUTO(voice))
1038      fluid_voice_release(voice);
1039   }
1040
1041   return FLUID_OK;
1042 }
1043
1044
1045 /**
1046  * Send a MIDI controller event on a MIDI channel.
1047  * @param synth FluidSynth instance
1048  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1049  * @param num MIDI controller number (0-127)
1050  * @param val MIDI controller value (0-127)
1051  * @return FLUID_OK on success, FLUID_FAILED otherwise
1052  */
1053 int
1054 fluid_synth_cc(fluid_synth_t* synth, int chan, int num, int val)
1055 {
1056   int result;
1057   fluid_return_val_if_fail (num >= 0 && num <= 127, FLUID_FAILED);
1058   fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED);
1059   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1060
1061   if (synth->verbose)
1062     FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val);
1063
1064   fluid_channel_set_cc (synth->channel[chan], num, val);
1065   result = fluid_synth_cc_LOCAL (synth, chan, num);
1066   FLUID_API_RETURN(result);
1067 }
1068
1069 /* Local synthesis thread variant of MIDI CC set function. */
1070 static int
1071 fluid_synth_cc_LOCAL (fluid_synth_t* synth, int channum, int num)
1072 {
1073   fluid_channel_t* chan = synth->channel[channum];
1074   int nrpn_select;
1075   int value;
1076
1077   value = fluid_channel_get_cc (chan, num);
1078
1079   switch (num) {
1080   case SUSTAIN_SWITCH:
1081     /* Release voices if Sustain switch is released */
1082     if (value < 64) /* Sustain is released */
1083         fluid_synth_damp_voices_by_sustain_LOCAL (synth, channum);
1084     break;
1085
1086   case SOSTENUTO_SWITCH:
1087     /* Release voices if Sostetuno switch is released */
1088     if (value < 64) /* Sostenuto is released */
1089         fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
1090     else /* Sostenuto is depressed */
1091          /* Update sostenuto order id when pedaling on Sostenuto */
1092         chan->sostenuto_orderid = synth->noteid; /* future voice id value */
1093     break;
1094
1095   case BANK_SELECT_MSB:
1096     fluid_channel_set_bank_msb (chan, value & 0x7F);
1097     break;
1098   case BANK_SELECT_LSB:
1099     fluid_channel_set_bank_lsb (chan, value & 0x7F);
1100     break;
1101   case ALL_NOTES_OFF:
1102     fluid_synth_all_notes_off_LOCAL (synth, channum);
1103     break;
1104   case ALL_SOUND_OFF:
1105     fluid_synth_all_sounds_off_LOCAL (synth, channum);
1106     break;
1107   case ALL_CTRL_OFF:
1108     fluid_channel_init_ctrl (chan, 1);
1109     fluid_synth_modulate_voices_all_LOCAL (synth, channum);
1110     break;
1111   case DATA_ENTRY_MSB:
1112     {
1113       int data = (value << 7) + fluid_channel_get_cc (chan, DATA_ENTRY_LSB);
1114
1115       if (chan->nrpn_active)  /* NRPN is active? */
1116       { /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74)  */
1117         if ((fluid_channel_get_cc (chan, NRPN_MSB) == 120)
1118             && (fluid_channel_get_cc (chan, NRPN_LSB) < 100))
1119         {
1120           nrpn_select = chan->nrpn_select;
1121
1122           if (nrpn_select < GEN_LAST)
1123           {
1124             float val = fluid_gen_scale_nrpn (nrpn_select, data);
1125             fluid_synth_set_gen_LOCAL (synth, channum, nrpn_select, val, FALSE);
1126           }
1127
1128           chan->nrpn_select = 0;  /* Reset to 0 */
1129         }
1130       }
1131       else if (fluid_channel_get_cc (chan, RPN_MSB) == 0)    /* RPN is active: MSB = 0? */
1132       {
1133         switch (fluid_channel_get_cc (chan, RPN_LSB))
1134         {
1135           case RPN_PITCH_BEND_RANGE:    /* Set bend range in semitones */
1136             fluid_channel_set_pitch_wheel_sensitivity (synth->channel[channum], value);
1137             fluid_synth_update_pitch_wheel_sens_LOCAL (synth, channum);   /* Update bend range */
1138             /* FIXME - Handle LSB? (Fine bend range in cents) */
1139             break;
1140           case RPN_CHANNEL_FINE_TUNE:   /* Fine tune is 14 bit over 1 semitone (+/- 50 cents, 8192 = center) */
1141             fluid_synth_set_gen_LOCAL (synth, channum, GEN_FINETUNE,
1142                                        (data - 8192) / 8192.0 * 50.0, FALSE);
1143             break;
1144           case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */
1145             fluid_synth_set_gen_LOCAL (synth, channum, GEN_COARSETUNE,
1146                                        value - 64, FALSE);
1147             break;
1148           case RPN_TUNING_PROGRAM_CHANGE:
1149             fluid_channel_set_tuning_prog (chan, value);
1150             fluid_synth_activate_tuning (synth, channum,
1151                                          fluid_channel_get_tuning_bank (chan),
1152                                          value, TRUE);
1153             break;
1154           case RPN_TUNING_BANK_SELECT:
1155             fluid_channel_set_tuning_bank (chan, value);
1156             break;
1157           case RPN_MODULATION_DEPTH_RANGE:
1158             break;
1159         }
1160       }
1161       break;
1162     }
1163   case NRPN_MSB:
1164     fluid_channel_set_cc (chan, NRPN_LSB, 0);
1165     chan->nrpn_select = 0;
1166     chan->nrpn_active = 1;
1167     break;
1168   case NRPN_LSB:
1169     /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74)  */
1170     if (fluid_channel_get_cc (chan, NRPN_MSB) == 120) {
1171       if (value == 100) {
1172         chan->nrpn_select += 100;
1173       } else if (value == 101) {
1174         chan->nrpn_select += 1000;
1175       } else if (value == 102) {
1176         chan->nrpn_select += 10000;
1177       } else if (value < 100) {
1178         chan->nrpn_select += value;
1179       }
1180     }
1181
1182     chan->nrpn_active = 1;
1183     break;
1184   case RPN_MSB:
1185   case RPN_LSB:
1186     chan->nrpn_active = 0;
1187     break;
1188   default:
1189     return fluid_synth_modulate_voices_LOCAL (synth, channum, 1, num);
1190   }
1191
1192   return FLUID_OK;
1193 }
1194
1195 /**
1196  * Get current MIDI controller value on a MIDI channel.
1197  * @param synth FluidSynth instance
1198  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1199  * @param num MIDI controller number (0-127)
1200  * @param pval Location to store MIDI controller value (0-127)
1201  * @return FLUID_OK on success, FLUID_FAILED otherwise
1202  */
1203 int
1204 fluid_synth_get_cc(fluid_synth_t* synth, int chan, int num, int* pval)
1205 {
1206   fluid_return_val_if_fail (num >= 0 && num < 128, FLUID_FAILED);
1207   fluid_return_val_if_fail (pval != NULL, FLUID_FAILED);
1208
1209   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1210   
1211   *pval = fluid_channel_get_cc (synth->channel[chan], num);
1212   FLUID_API_RETURN(FLUID_OK);
1213 }
1214
1215 /*
1216  * Handler for synth.device-id setting.
1217  */
1218 static int
1219 fluid_synth_update_device_id (fluid_synth_t *synth, char *name, int value)
1220 {
1221   fluid_synth_api_enter(synth);
1222   synth->device_id = value;
1223   fluid_synth_api_exit(synth);
1224   return 0;
1225 }
1226
1227 /**
1228  * Process a MIDI SYSEX (system exclusive) message.
1229  * @param synth FluidSynth instance
1230  * @param data Buffer containing SYSEX data (not including 0xF0 and 0xF7)
1231  * @param len Length of data in buffer
1232  * @param response Buffer to store response to or NULL to ignore
1233  * @param response_len IN/OUT parameter, in: size of response buffer, out:
1234  *   amount of data written to response buffer (if FLUID_FAILED is returned and
1235  *   this value is non-zero, it indicates the response buffer is too small)
1236  * @param handled Optional location to store boolean value if message was
1237  *   recognized and handled or not (set to TRUE if it was handled)
1238  * @param dryrun TRUE to just do a dry run but not actually execute the SYSEX
1239  *   command (useful for checking if a SYSEX message would be handled)
1240  * @return FLUID_OK on success, FLUID_FAILED otherwise
1241  * @since 1.1.0
1242  */
1243 /* SYSEX format (0xF0 and 0xF7 not passed to this function):
1244  * Non-realtime:    0xF0 0x7E <DeviceId> [BODY] 0xF7
1245  * Realtime:        0xF0 0x7F <DeviceId> [BODY] 0xF7
1246  * Tuning messages: 0xF0 0x7E/0x7F <DeviceId> 0x08 <sub ID2> [BODY] <ChkSum> 0xF7
1247  */
1248 int
1249 fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len,
1250                   char *response, int *response_len, int *handled, int dryrun)
1251 {
1252   int avail_response = 0;
1253
1254   if (handled) *handled = FALSE;
1255
1256   if (response_len)
1257   {
1258     avail_response = *response_len;
1259     *response_len = 0;
1260   }
1261
1262   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1263   fluid_return_val_if_fail (data != NULL, FLUID_FAILED);
1264   fluid_return_val_if_fail (len > 0, FLUID_FAILED);
1265   fluid_return_val_if_fail (!response || response_len, FLUID_FAILED);
1266
1267   if (len < 4) return FLUID_OK;
1268
1269   /* MIDI tuning SYSEX message? */
1270   if ((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME)
1271       && (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL)
1272       && data[2] == MIDI_SYSEX_MIDI_TUNING_ID)
1273   {
1274     int result;
1275     fluid_synth_api_enter(synth);
1276     result = fluid_synth_sysex_midi_tuning (synth, data, len, response, 
1277                                                 response_len, avail_response, 
1278                                                 handled, dryrun);
1279
1280     FLUID_API_RETURN(result);
1281   }
1282   return FLUID_OK;
1283 }
1284
1285 /* Handler for MIDI tuning SYSEX messages */
1286 static int
1287 fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data, int len,
1288                                char *response, int *response_len, int avail_response,
1289                                int *handled, int dryrun)
1290 {
1291   int realtime, msgid;
1292   int bank = 0, prog, channels;
1293   double tunedata[128];
1294   int keys[128];
1295   char name[17];
1296   int note, frac, frac2;
1297   uint8 chksum;
1298   int i, count, index;
1299   const char *dataptr;
1300   char *resptr;;
1301
1302   realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME;
1303   msgid = data[3];
1304
1305   switch (msgid)
1306   {
1307     case MIDI_SYSEX_TUNING_BULK_DUMP_REQ:
1308     case MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK:
1309       if (data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
1310       {
1311         if (len != 5 || data[4] & 0x80 || !response)
1312           return FLUID_OK;
1313
1314         *response_len = 406;
1315         prog = data[4];
1316       }
1317       else
1318       {
1319         if (len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response)
1320           return FLUID_OK;
1321
1322         *response_len = 407;
1323         bank = data[4];
1324         prog = data[5];
1325       }
1326
1327       if (dryrun)
1328       {
1329         if (handled) *handled = TRUE;
1330         return FLUID_OK;
1331       }
1332
1333       if (avail_response < *response_len) return FLUID_FAILED;
1334
1335       /* Get tuning data, return if tuning not found */
1336       if (fluid_synth_tuning_dump (synth, bank, prog, name, 17, tunedata) == FLUID_FAILED)
1337       {
1338         *response_len = 0;
1339         return FLUID_OK;
1340       }
1341
1342       resptr = response;
1343
1344       *resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME;
1345       *resptr++ = synth->device_id;
1346       *resptr++ = MIDI_SYSEX_MIDI_TUNING_ID;
1347       *resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP;
1348
1349       if (msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK)
1350         *resptr++ = bank;
1351
1352       *resptr++ = prog;
1353       FLUID_STRNCPY (resptr, name, 16);
1354       resptr += 16;
1355
1356       for (i = 0; i < 128; i++)
1357       {
1358         note = tunedata[i] / 100.0;
1359         fluid_clip (note, 0, 127);
1360
1361         frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0;
1362         fluid_clip (frac, 0, 16383);
1363
1364         *resptr++ = note;
1365         *resptr++ = frac >> 7;
1366         *resptr++ = frac & 0x7F;
1367       }
1368
1369       if (msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
1370       {  /* NOTE: Checksum is not as straight forward as the bank based messages */
1371         chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID
1372           ^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog;
1373
1374         for (i = 21; i < 128 * 3 + 21; i++)
1375           chksum ^= response[i];
1376       }
1377       else
1378       {
1379         for (i = 1, chksum = 0; i < 406; i++)
1380           chksum ^= response[i];
1381       }
1382
1383       *resptr++ = chksum & 0x7F;
1384
1385       if (handled) *handled = TRUE;
1386       break;
1387     case MIDI_SYSEX_TUNING_NOTE_TUNE:
1388     case MIDI_SYSEX_TUNING_NOTE_TUNE_BANK:
1389       dataptr = data + 4;
1390
1391       if (msgid == MIDI_SYSEX_TUNING_NOTE_TUNE)
1392       {
1393         if (len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6)
1394           return FLUID_OK;
1395       }
1396       else
1397       {
1398         if (len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80
1399             || len != data[5] * 4 + 7)
1400           return FLUID_OK;
1401
1402         bank = *dataptr++;
1403       }
1404
1405       if (dryrun)
1406       {
1407         if (handled) *handled = TRUE;
1408         return FLUID_OK;
1409       }
1410
1411       prog = *dataptr++;
1412       count = *dataptr++;
1413
1414       for (i = 0, index = 0; i < count; i++)
1415       {
1416         note = *dataptr++;
1417         if (note & 0x80) return FLUID_OK;
1418         keys[index] = note;
1419
1420         note = *dataptr++;
1421         frac = *dataptr++;
1422         frac2 = *dataptr++;
1423
1424         if (note & 0x80 || frac & 0x80 || frac2 & 0x80)
1425           return FLUID_OK;
1426
1427         frac = frac << 7 | frac2;
1428
1429         /* No change pitch value?  Doesn't really make sense to send that, but.. */
1430         if (note == 0x7F && frac == 16383) continue;
1431
1432         tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0);
1433         index++;
1434       }
1435
1436       if (index > 0)
1437       {
1438         if (fluid_synth_tune_notes (synth, bank, prog, index, keys, tunedata,
1439                                     realtime) == FLUID_FAILED)
1440           return FLUID_FAILED;
1441       }
1442
1443       if (handled) *handled = TRUE;
1444       break;
1445     case MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE:
1446     case MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE:
1447       if ((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19)
1448           || (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31))
1449         return FLUID_OK;
1450
1451       if (data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80)
1452         return FLUID_OK;
1453
1454       if (dryrun)
1455       {
1456         if (handled) *handled = TRUE;
1457         return FLUID_OK;
1458       }
1459
1460       channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6];
1461
1462       if (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE)
1463       {
1464         for (i = 0; i < 12; i++)
1465         {
1466           frac = data[i + 7];
1467           if (frac & 0x80) return FLUID_OK;
1468           tunedata[i] = (int)frac - 64;
1469         }
1470       }
1471       else
1472       {
1473         for (i = 0; i < 12; i++)
1474         {
1475           frac = data[i * 2 + 7];
1476           frac2 = data[i * 2 + 8];
1477           if (frac & 0x80 || frac2 & 0x80) return FLUID_OK;
1478           tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0);
1479         }
1480       }
1481
1482       if (fluid_synth_activate_octave_tuning (synth, 0, 0, "SYSEX",
1483                                               tunedata, realtime) == FLUID_FAILED)
1484         return FLUID_FAILED;
1485
1486       if (channels)
1487       {
1488         for (i = 0; i < 16; i++)
1489         {
1490           if (channels & (1 << i))
1491             fluid_synth_activate_tuning (synth, i, 0, 0, realtime);
1492         }
1493       }
1494
1495       if (handled) *handled = TRUE;
1496       break;
1497   }
1498
1499   return FLUID_OK;
1500 }
1501
1502 /**
1503  * Turn off all notes on a MIDI channel (put them into release phase).
1504  * @param synth FluidSynth instance
1505  * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
1506  * @return FLUID_OK on success, FLUID_FAILED otherwise
1507  * @since 1.1.4
1508  */
1509 int
1510 fluid_synth_all_notes_off(fluid_synth_t* synth, int chan)
1511 {
1512   int result;
1513
1514   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1515   fluid_return_val_if_fail (chan >= -1, FLUID_FAILED);
1516   fluid_synth_api_enter(synth);
1517   if (chan >= synth->midi_channels) 
1518     result = FLUID_FAILED;
1519   else
1520     result = fluid_synth_all_notes_off_LOCAL (synth, chan);
1521   FLUID_API_RETURN(result);
1522 }
1523
1524 /* Local synthesis thread variant of all notes off, (chan=-1 selects all channels) */
1525 static int
1526 fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan)
1527 {
1528   fluid_voice_t* voice;
1529   int i;
1530
1531   for (i = 0; i < synth->polyphony; i++) {
1532     voice = synth->voice[i];
1533
1534     if (_PLAYING(voice) && ((-1 == chan) || (chan == voice->chan)))
1535       fluid_voice_noteoff(voice);
1536   }
1537   return FLUID_OK;
1538 }
1539
1540 /**
1541  * Immediately stop all notes on a MIDI channel (skips release phase).
1542  * @param synth FluidSynth instance
1543  * @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
1544  * @return FLUID_OK on success, FLUID_FAILED otherwise
1545  * @since 1.1.4
1546  */
1547 int
1548 fluid_synth_all_sounds_off(fluid_synth_t* synth, int chan)
1549 {
1550   int result;
1551
1552   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1553   fluid_return_val_if_fail (chan >= -1, FLUID_FAILED);
1554   fluid_synth_api_enter(synth);
1555   if (chan >= synth->midi_channels) 
1556     result = FLUID_FAILED;
1557   else
1558     result = fluid_synth_all_sounds_off_LOCAL (synth, chan);
1559   FLUID_API_RETURN(result);
1560 }
1561
1562 /* Local synthesis thread variant of all sounds off, (chan=-1 selects all channels) */
1563 static int
1564 fluid_synth_all_sounds_off_LOCAL(fluid_synth_t* synth, int chan)
1565 {
1566   fluid_voice_t* voice;
1567   int i;
1568
1569   for (i = 0; i < synth->polyphony; i++) {
1570     voice = synth->voice[i];
1571
1572     if (_PLAYING(voice) && ((-1 == chan) || (chan == voice->chan)))
1573       fluid_voice_off(voice);
1574   }
1575   return FLUID_OK;
1576 }
1577
1578 /**
1579  * Reset reverb engine
1580  * @param synth FluidSynth instance
1581  * @return FLUID_OK on success, FLUID_FAILED otherwise
1582  */
1583 int
1584 fluid_synth_reset_reverb(fluid_synth_t* synth)
1585 {
1586   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1587   fluid_synth_api_enter(synth);
1588   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
1589   FLUID_API_RETURN(FLUID_OK);
1590 }
1591
1592 /**
1593  * Reset chorus engine
1594  * @param synth FluidSynth instance
1595  * @return FLUID_OK on success, FLUID_FAILED otherwise
1596  */
1597 int
1598 fluid_synth_reset_chorus(fluid_synth_t* synth)
1599 {
1600   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1601   fluid_synth_api_enter(synth);
1602   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
1603   FLUID_API_RETURN(FLUID_OK);
1604 }
1605
1606
1607 /**
1608  * Send MIDI system reset command (big red 'panic' button), turns off notes and
1609  *   resets controllers.
1610  * @param synth FluidSynth instance
1611  * @return FLUID_OK on success, FLUID_FAILED otherwise
1612  */
1613 int
1614 fluid_synth_system_reset(fluid_synth_t* synth)
1615 {
1616   int result;
1617   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1618   fluid_synth_api_enter(synth);
1619   result = fluid_synth_system_reset_LOCAL (synth);
1620   FLUID_API_RETURN(result);
1621 }
1622
1623 /* Local variant of the system reset command */
1624 static int
1625 fluid_synth_system_reset_LOCAL(fluid_synth_t* synth)
1626 {
1627   fluid_voice_t* voice;
1628   int i;
1629
1630   for (i = 0; i < synth->polyphony; i++) {
1631     voice = synth->voice[i];
1632
1633     if (_PLAYING(voice))
1634       fluid_voice_off(voice);
1635   }
1636
1637   for (i = 0; i < synth->midi_channels; i++)
1638     fluid_channel_reset(synth->channel[i]);
1639
1640   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_fx, 0, 0.0f); 
1641
1642   return FLUID_OK;
1643 }
1644
1645 /**
1646  * Update voices on a MIDI channel after a MIDI control change.
1647  * @param synth FluidSynth instance
1648  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1649  * @param is_cc Boolean value indicating if ctrl is a CC controller or not
1650  * @param ctrl MIDI controller value
1651  * @return FLUID_OK on success, FLUID_FAILED otherwise
1652  */
1653 static int
1654 fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan, int is_cc, int ctrl)
1655 {
1656   fluid_voice_t* voice;
1657   int i;
1658
1659   for (i = 0; i < synth->polyphony; i++) {
1660     voice = synth->voice[i];
1661
1662     if (voice->chan == chan)
1663       fluid_voice_modulate(voice, is_cc, ctrl);
1664   }
1665   return FLUID_OK;
1666 }
1667
1668 /**
1669  * Update voices on a MIDI channel after all MIDI controllers have been changed.
1670  * @param synth FluidSynth instance
1671  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1672  * @return FLUID_OK on success, FLUID_FAILED otherwise
1673  */
1674 static int
1675 fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t* synth, int chan)
1676 {
1677   fluid_voice_t* voice;
1678   int i;
1679
1680   for (i = 0; i < synth->polyphony; i++) {
1681     voice = synth->voice[i];
1682
1683     if (voice->chan == chan)
1684       fluid_voice_modulate_all(voice);
1685   }
1686   return FLUID_OK;
1687 }
1688
1689 /**
1690  * Set the MIDI channel pressure controller value.
1691  * @param synth FluidSynth instance
1692  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1693  * @param val MIDI channel pressure value (0-127)
1694  * @return FLUID_OK on success, FLUID_FAILED otherwise
1695  */
1696 int
1697 fluid_synth_channel_pressure(fluid_synth_t* synth, int chan, int val)
1698 {
1699   int result;
1700   fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED);
1701
1702   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1703   
1704   if (synth->verbose)
1705     FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
1706
1707   fluid_channel_set_channel_pressure (synth->channel[chan], val);
1708
1709   result = fluid_synth_update_channel_pressure_LOCAL (synth, chan);
1710   FLUID_API_RETURN(result);
1711 }
1712
1713 /* Updates channel pressure from within synthesis thread */
1714 static int
1715 fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t* synth, int chan)
1716 {
1717   return fluid_synth_modulate_voices_LOCAL (synth, chan, 0, FLUID_MOD_CHANNELPRESSURE);
1718 }
1719
1720 /**
1721  * Set the MIDI pitch bend controller value on a MIDI channel.
1722  * @param synth FluidSynth instance
1723  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1724  * @param val MIDI pitch bend value (0-16383 with 8192 being center)
1725  * @return FLUID_OK on success, FLUID_FAILED otherwise
1726  */
1727 int
1728 fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val)
1729 {
1730   int result;
1731   fluid_return_val_if_fail (val >= 0 && val <= 16383, FLUID_FAILED);
1732   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1733   
1734   if (synth->verbose)
1735     FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val);
1736
1737   fluid_channel_set_pitch_bend (synth->channel[chan], val);
1738
1739   result = fluid_synth_update_pitch_bend_LOCAL (synth, chan);
1740   FLUID_API_RETURN(result);
1741 }
1742
1743 /* Local synthesis thread variant of pitch bend */
1744 static int
1745 fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t* synth, int chan)
1746 {
1747   return fluid_synth_modulate_voices_LOCAL (synth, chan, 0, FLUID_MOD_PITCHWHEEL);
1748 }
1749
1750 /**
1751  * Get the MIDI pitch bend controller value on a MIDI channel.
1752  * @param synth FluidSynth instance
1753  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1754  * @param ppitch_bend Location to store MIDI pitch bend value (0-16383 with
1755  *   8192 being center)
1756  * @return FLUID_OK on success, FLUID_FAILED otherwise
1757  */
1758 int
1759 fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend)
1760 {
1761   fluid_return_val_if_fail (ppitch_bend != NULL, FLUID_FAILED);
1762   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1763   
1764   *ppitch_bend = fluid_channel_get_pitch_bend (synth->channel[chan]);
1765   FLUID_API_RETURN(FLUID_OK);
1766 }
1767
1768 /**
1769  * Set MIDI pitch wheel sensitivity on a MIDI channel.
1770  * @param synth FluidSynth instance
1771  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1772  * @param val Pitch wheel sensitivity value in semitones
1773  * @return FLUID_OK on success, FLUID_FAILED otherwise
1774  */
1775 int
1776 fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val)
1777 {
1778   int result;
1779   fluid_return_val_if_fail (val >= 0 && val <= 72, FLUID_FAILED);       /* 6 octaves!?  Better than no limit.. */
1780   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1781   
1782   if (synth->verbose)
1783     FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val);
1784
1785   fluid_channel_set_pitch_wheel_sensitivity (synth->channel[chan], val);
1786
1787   result = fluid_synth_update_pitch_wheel_sens_LOCAL (synth, chan);
1788   FLUID_API_RETURN(result);
1789 }
1790
1791 /* Local synthesis thread variant of set pitch wheel sensitivity */
1792 static int
1793 fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t* synth, int chan)
1794 {
1795   return fluid_synth_modulate_voices_LOCAL (synth, chan, 0, FLUID_MOD_PITCHWHEELSENS);
1796 }
1797
1798 /**
1799  * Get MIDI pitch wheel sensitivity on a MIDI channel.
1800  * @param synth FluidSynth instance
1801  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1802  * @param pval Location to store pitch wheel sensitivity value in semitones
1803  * @return FLUID_OK on success, FLUID_FAILED otherwise
1804  * @since Sometime AFTER v1.0 API freeze.
1805  */
1806 int
1807 fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval)
1808 {
1809   fluid_return_val_if_fail (pval != NULL, FLUID_FAILED);
1810   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1811   
1812   *pval = fluid_channel_get_pitch_wheel_sensitivity (synth->channel[chan]);
1813   FLUID_API_RETURN(FLUID_OK);
1814 }
1815
1816 /**
1817  * Assign a preset to a MIDI channel.
1818  * @param synth FluidSynth instance
1819  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1820  * @param preset Preset to assign to channel or NULL to clear (ownership is taken over)
1821  * @return FLUID_OK on success, FLUID_FAILED otherwise
1822  */
1823 static int
1824 fluid_synth_set_preset (fluid_synth_t *synth, int chan, fluid_preset_t *preset)
1825 {
1826   fluid_channel_t *channel;
1827
1828   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
1829   fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
1830
1831   channel = synth->channel[chan];
1832
1833   return fluid_channel_set_preset (channel, preset);
1834 }
1835
1836 /* Get a preset by SoundFont, bank and program numbers.
1837  * Returns preset pointer or NULL.
1838  *
1839  * NOTE: The returned preset has been allocated, caller owns it and should
1840  *       free it when finished using it.
1841  */
1842 static fluid_preset_t*
1843 fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
1844                        unsigned int banknum, unsigned int prognum)
1845 {
1846   fluid_preset_t *preset = NULL;
1847   fluid_sfont_info_t *sfont_info;
1848   fluid_list_t *list;
1849
1850   /* 128 indicates an "unset" operation" */
1851   if (prognum == FLUID_UNSET_PROGRAM) return NULL;
1852
1853   for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
1854     sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
1855
1856     if (fluid_sfont_get_id (sfont_info->sfont) == sfontnum)
1857     {
1858       preset = fluid_sfont_get_preset (sfont_info->sfont,
1859                                        banknum - sfont_info->bankofs, prognum);
1860       if (preset) sfont_info->refcount++;       /* Add reference to SoundFont */
1861       break;
1862     }
1863   }
1864
1865   return preset;
1866 }
1867
1868 /* Get a preset by SoundFont name, bank and program.
1869  * Returns preset pointer or NULL.
1870  *
1871  * NOTE: The returned preset has been allocated, caller owns it and should
1872  *       free it when finished using it.
1873  */
1874 static fluid_preset_t*
1875 fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname,
1876                                      unsigned int banknum, unsigned int prognum)
1877 {
1878   fluid_preset_t *preset = NULL;
1879   fluid_sfont_info_t *sfont_info;
1880   fluid_list_t *list;
1881
1882   for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
1883     sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
1884
1885     if (FLUID_STRCMP (fluid_sfont_get_name (sfont_info->sfont), sfontname) == 0)
1886     {
1887       preset = fluid_sfont_get_preset (sfont_info->sfont,
1888                                        banknum - sfont_info->bankofs, prognum);
1889       if (preset) sfont_info->refcount++;       /* Add reference to SoundFont */
1890       break;
1891     }
1892   }
1893
1894   return preset;
1895 }
1896
1897 /* Find a preset by bank and program numbers.
1898  * Returns preset pointer or NULL.
1899  *
1900  * NOTE: The returned preset has been allocated, caller owns it and should
1901  *       free it when finished using it. */
1902 fluid_preset_t*
1903 fluid_synth_find_preset(fluid_synth_t* synth, unsigned int banknum,
1904                         unsigned int prognum)
1905 {
1906   fluid_preset_t *preset = NULL;
1907   fluid_sfont_info_t *sfont_info;
1908   fluid_list_t *list;
1909
1910   for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
1911     sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
1912
1913     preset = fluid_sfont_get_preset (sfont_info->sfont,
1914                                      banknum - sfont_info->bankofs, prognum);
1915     if (preset)
1916     {
1917       sfont_info->refcount++;       /* Add reference to SoundFont */
1918       break;
1919     }
1920   }
1921
1922   return preset;
1923 }
1924
1925 /**
1926  * Send a program change event on a MIDI channel.
1927  * @param synth FluidSynth instance
1928  * @param chan MIDI channel number (0 to MIDI channel count - 1)
1929  * @param prognum MIDI program number (0-127)
1930  * @return FLUID_OK on success, FLUID_FAILED otherwise
1931  */
1932 /* FIXME - Currently not real-time safe, due to preset allocation and mutex lock,
1933  * and may be called from within synthesis context. */
1934
1935 /* As of 1.1.1 prognum can be set to 128 to unset the preset.  Not documented
1936  * since fluid_synth_unset_program() should be used instead. */
1937 int
1938 fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
1939 {
1940   fluid_preset_t* preset = NULL;
1941   fluid_channel_t* channel;
1942   int subst_bank, subst_prog, banknum = 0, result;
1943
1944   fluid_return_val_if_fail (prognum >= 0 && prognum <= 128, FLUID_FAILED);
1945   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1946   
1947   channel = synth->channel[chan];
1948   if (channel->channel_type == CHANNEL_TYPE_DRUM) 
1949     banknum = DRUM_INST_BANK;
1950   else
1951     fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
1952
1953   if (synth->verbose)
1954     FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
1955
1956   /* I think this is a hack for MIDI files that do bank changes in GM mode.  
1957    * Proper way to handle this would probably be to ignore bank changes when in 
1958    * GM mode. - JG
1959    * This is now possible by setting synth.midi-bank-select=gm, but let the hack
1960    * stay for the time being. - DH
1961    */
1962   if (prognum != FLUID_UNSET_PROGRAM)
1963   {
1964     subst_bank = banknum;
1965     subst_prog = prognum;
1966     
1967     preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
1968     
1969     /* Fallback to another preset if not found */
1970     if (!preset) {
1971       /* Percussion: Fallback to preset 0 in percussion bank */
1972       if (subst_bank == DRUM_INST_BANK) {
1973         subst_prog = 0;
1974         preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
1975       }
1976       /* Melodic instrument */
1977       else { 
1978         /* Fallback first to bank 0:prognum */
1979         subst_bank = 0;
1980         preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
1981
1982         /* Fallback to first preset in bank 0 (usually piano...) */
1983         if (!preset)
1984         {
1985           subst_prog = 0;
1986           preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
1987         }
1988       }
1989
1990       if (preset)
1991         FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
1992                   chan, banknum, prognum, subst_bank, subst_prog); 
1993       else
1994         FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]",
1995                   chan, banknum, prognum); 
1996     }
1997   }
1998
1999   /* Assign the SoundFont ID and program number to the channel */
2000   fluid_channel_set_sfont_bank_prog (channel, preset ? fluid_sfont_get_id (preset->sfont) : 0,
2001                                      -1, prognum);
2002   result = fluid_synth_set_preset (synth, chan, preset);
2003   FLUID_API_RETURN(result);
2004 }
2005
2006 /**
2007  * Set instrument bank number on a MIDI channel.
2008  * @param synth FluidSynth instance
2009  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2010  * @param bank MIDI bank number
2011  * @return FLUID_OK on success, FLUID_FAILED otherwise
2012  */
2013 int
2014 fluid_synth_bank_select(fluid_synth_t* synth, int chan, unsigned int bank)
2015 {
2016   fluid_return_val_if_fail (bank <= 16383, FLUID_FAILED);
2017   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2018   
2019   fluid_channel_set_sfont_bank_prog (synth->channel[chan], -1, bank, -1);
2020   FLUID_API_RETURN(FLUID_OK);
2021 }
2022
2023 /**
2024  * Set SoundFont ID on a MIDI channel.
2025  * @param synth FluidSynth instance
2026  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2027  * @param sfont_id ID of a loaded SoundFont
2028  * @return FLUID_OK on success, FLUID_FAILED otherwise
2029  */
2030 int
2031 fluid_synth_sfont_select(fluid_synth_t* synth, int chan, unsigned int sfont_id)
2032 {
2033   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2034   
2035   fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
2036
2037   FLUID_API_RETURN(FLUID_OK);
2038 }
2039
2040 /**
2041  * Set the preset of a MIDI channel to an unassigned state.
2042  * @param synth FluidSynth instance
2043  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2044  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2045  * @since 1.1.1
2046  *
2047  * Note: Channel retains its SoundFont ID and bank numbers, while the program
2048  * number is set to an "unset" state.  MIDI program changes may re-assign a
2049  * preset if one matches.
2050  */
2051 int
2052 fluid_synth_unset_program (fluid_synth_t *synth, int chan)
2053 {
2054   int result;
2055   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2056
2057   result = fluid_synth_program_change (synth, chan, FLUID_UNSET_PROGRAM);
2058   FLUID_API_RETURN(result);
2059 }
2060
2061 /**
2062  * Get current SoundFont ID, bank number and program number for a MIDI channel.
2063  * @param synth FluidSynth instance
2064  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2065  * @param sfont_id Location to store SoundFont ID
2066  * @param bank_num Location to store MIDI bank number
2067  * @param preset_num Location to store MIDI program number
2068  * @return FLUID_OK on success, FLUID_FAILED otherwise
2069  */
2070 int
2071 fluid_synth_get_program(fluid_synth_t* synth, int chan, unsigned int* sfont_id,
2072                         unsigned int* bank_num, unsigned int* preset_num)
2073 {
2074   fluid_channel_t* channel;
2075
2076   fluid_return_val_if_fail (sfont_id != NULL, FLUID_FAILED);
2077   fluid_return_val_if_fail (bank_num != NULL, FLUID_FAILED);
2078   fluid_return_val_if_fail (preset_num != NULL, FLUID_FAILED);
2079   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2080
2081   channel = synth->channel[chan];
2082   fluid_channel_get_sfont_bank_prog(channel, (int *)sfont_id, (int *)bank_num,
2083                                     (int *)preset_num);
2084
2085   /* 128 indicates that the preset is unset.  Set to 0 to be backwards compatible. */
2086   if (*preset_num == FLUID_UNSET_PROGRAM) *preset_num = 0;
2087
2088   FLUID_API_RETURN(FLUID_OK);
2089 }
2090
2091 /**
2092  * Select an instrument on a MIDI channel by SoundFont ID, bank and program numbers.
2093  * @param synth FluidSynth instance
2094  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2095  * @param sfont_id ID of a loaded SoundFont
2096  * @param bank_num MIDI bank number
2097  * @param preset_num MIDI program number
2098  * @return FLUID_OK on success, FLUID_FAILED otherwise
2099  */
2100 int
2101 fluid_synth_program_select(fluid_synth_t* synth, int chan, unsigned int sfont_id,
2102                            unsigned int bank_num, unsigned int preset_num)
2103 {
2104   fluid_preset_t* preset = NULL;
2105   fluid_channel_t* channel;
2106   int result;
2107   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2108
2109   channel = synth->channel[chan];
2110
2111   /* ++ Allocate preset */
2112   preset = fluid_synth_get_preset (synth, sfont_id, bank_num, preset_num);
2113
2114   if (preset == NULL) {
2115     FLUID_LOG(FLUID_ERR,
2116               "There is no preset with bank number %d and preset number %d in SoundFont %d",
2117               bank_num, preset_num, sfont_id);
2118     FLUID_API_RETURN(FLUID_FAILED);
2119   }
2120
2121   /* Assign the new SoundFont ID, bank and program number to the channel */
2122   fluid_channel_set_sfont_bank_prog (channel, sfont_id, bank_num, preset_num);
2123   result = fluid_synth_set_preset (synth, chan, preset);
2124   
2125   FLUID_API_RETURN(result);
2126 }
2127
2128 /**
2129  * Select an instrument on a MIDI channel by SoundFont name, bank and program numbers.
2130  * @param synth FluidSynth instance
2131  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2132  * @param sfont_name Name of a loaded SoundFont
2133  * @param bank_num MIDI bank number
2134  * @param preset_num MIDI program number
2135  * @return FLUID_OK on success, FLUID_FAILED otherwise
2136  * @since 1.1.0
2137  */
2138 int
2139 fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan,
2140                                           const char *sfont_name, unsigned int bank_num,
2141                                           unsigned int preset_num)
2142 {
2143   fluid_preset_t* preset = NULL;
2144   fluid_channel_t* channel;
2145   int result;
2146   fluid_return_val_if_fail (sfont_name != NULL, FLUID_FAILED);
2147   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2148
2149   channel = synth->channel[chan];
2150
2151   /* ++ Allocate preset */
2152   preset = fluid_synth_get_preset_by_sfont_name (synth, sfont_name, bank_num,
2153                                                  preset_num);
2154   if (preset == NULL) {
2155     FLUID_LOG(FLUID_ERR,
2156               "There is no preset with bank number %d and preset number %d in SoundFont %s",
2157               bank_num, preset_num, sfont_name);
2158     FLUID_API_RETURN(FLUID_FAILED);
2159   }
2160
2161   /* Assign the new SoundFont ID, bank and program number to the channel */
2162   fluid_channel_set_sfont_bank_prog (channel, fluid_sfont_get_id (preset->sfont),
2163                                      bank_num, preset_num);
2164   result = fluid_synth_set_preset (synth, chan, preset);
2165   FLUID_API_RETURN(result);  
2166 }
2167
2168 /*
2169  * This function assures that every MIDI channel has a valid preset
2170  * (NULL is okay). This function is called after a SoundFont is
2171  * unloaded or reloaded.
2172  */
2173 static void
2174 fluid_synth_update_presets(fluid_synth_t* synth)
2175 {
2176   fluid_channel_t *channel;
2177   fluid_preset_t *preset;
2178   int sfont, bank, prog;
2179   int chan;
2180
2181   for (chan = 0; chan < synth->midi_channels; chan++) {
2182     channel = synth->channel[chan];
2183     fluid_channel_get_sfont_bank_prog (channel, &sfont, &bank, &prog);
2184     preset = fluid_synth_get_preset (synth, sfont, bank, prog);
2185     fluid_synth_set_preset (synth, chan, preset);
2186   }
2187 }
2188
2189 /* Handler for synth.gain setting. */
2190 static int
2191 fluid_synth_update_sample_rate(fluid_synth_t* synth, char* name, double value)
2192 {
2193   fluid_synth_set_sample_rate(synth, (float) value);
2194   return 0;
2195 }
2196
2197 /**
2198  * Set sample rate of the synth. 
2199  * NOTE: This function is currently experimental and should only be 
2200  * used when no voices or notes are active, and before any rendering calls.
2201  * @param synth FluidSynth instance
2202  * @param sample_rate New sample rate (Hz)
2203  * @since 1.1.2
2204  */
2205 void 
2206 fluid_synth_set_sample_rate(fluid_synth_t* synth, float sample_rate)
2207 {
2208   int i;
2209   fluid_return_if_fail (synth != NULL);
2210   fluid_synth_api_enter(synth);
2211   fluid_clip (sample_rate, 8000.0f, 96000.0f);
2212   synth->sample_rate = sample_rate;
2213   
2214   fluid_settings_getint(synth->settings, "synth.min-note-length", &i);
2215   synth->min_note_length_ticks = (unsigned int) (i*synth->sample_rate/1000.0f);
2216   
2217   for (i=0; i < synth->polyphony; i++)
2218     fluid_voice_set_output_rate(synth->voice[i], sample_rate);
2219   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate, 
2220                            0, sample_rate);
2221   fluid_synth_api_exit(synth);
2222 }
2223
2224
2225 /* Handler for synth.gain setting. */
2226 static int
2227 fluid_synth_update_gain(fluid_synth_t* synth, char* name, double value)
2228 {
2229   fluid_synth_set_gain(synth, (float) value);
2230   return 0;
2231 }
2232
2233 /**
2234  * Set synth output gain value.
2235  * @param synth FluidSynth instance
2236  * @param gain Gain value (function clamps value to the range 0.0 to 10.0)
2237  */
2238 void
2239 fluid_synth_set_gain(fluid_synth_t* synth, float gain)
2240 {
2241   fluid_return_if_fail (synth != NULL);
2242   fluid_synth_api_enter(synth);
2243   
2244   fluid_clip (gain, 0.0f, 10.0f);
2245
2246   synth->gain = gain;
2247   fluid_synth_update_gain_LOCAL (synth);
2248   fluid_synth_api_exit(synth);
2249 }
2250
2251 /* Called by synthesis thread to update the gain in all voices */
2252 static void
2253 fluid_synth_update_gain_LOCAL(fluid_synth_t* synth)
2254 {
2255   fluid_voice_t *voice;
2256   float gain;
2257   int i;
2258
2259   gain = synth->gain;
2260
2261   for (i = 0; i < synth->polyphony; i++)
2262   {
2263     voice = synth->voice[i];
2264     if (_PLAYING (voice)) fluid_voice_set_gain (voice, gain);
2265   }
2266 }
2267
2268 /**
2269  * Get synth output gain value.
2270  * @param synth FluidSynth instance
2271  * @return Synth gain value (0.0 to 10.0)
2272  */
2273 float
2274 fluid_synth_get_gain(fluid_synth_t* synth)
2275 {
2276   float result;
2277   fluid_return_val_if_fail (synth != NULL, 0.0);
2278   fluid_synth_api_enter(synth);
2279
2280   result = synth->gain;
2281   FLUID_API_RETURN(result);
2282 }
2283
2284 /*
2285  * Handler for synth.polyphony setting.
2286  */
2287 static int
2288 fluid_synth_update_polyphony(fluid_synth_t* synth, char* name, int value)
2289 {
2290   fluid_synth_set_polyphony(synth, value);
2291   return 0;
2292 }
2293
2294 /**
2295  * Set synthesizer polyphony (max number of voices).
2296  * @param synth FluidSynth instance
2297  * @param polyphony Polyphony to assign
2298  * @return FLUID_OK on success, FLUID_FAILED otherwise
2299  * @since 1.0.6
2300  */
2301 int
2302 fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony)
2303 {
2304   int result;
2305   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
2306   fluid_return_val_if_fail (polyphony >= 1 && polyphony <= 65535, FLUID_FAILED);
2307   fluid_synth_api_enter(synth);
2308
2309   result = fluid_synth_update_polyphony_LOCAL(synth, polyphony);
2310
2311   FLUID_API_RETURN(result);
2312 }
2313
2314 /* Called by synthesis thread to update the polyphony value */
2315 static int
2316 fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony)
2317 {
2318   fluid_voice_t *voice;
2319   int i;
2320
2321   if (new_polyphony > synth->nvoice) {
2322     /* Create more voices */
2323     fluid_voice_t** new_voices = FLUID_REALLOC(synth->voice, 
2324                                                sizeof(fluid_voice_t*) * new_polyphony);
2325     if (new_voices == NULL) 
2326       return FLUID_FAILED;
2327     synth->voice = new_voices;
2328     for (i = synth->nvoice; i < new_polyphony; i++) {
2329       synth->voice[i] = new_fluid_voice(synth->sample_rate);
2330       if (synth->voice[i] == NULL) 
2331         return FLUID_FAILED;
2332     }
2333     synth->nvoice = new_polyphony;
2334   }
2335   
2336   synth->polyphony = new_polyphony;
2337   /* turn off any voices above the new limit */
2338   for (i = synth->polyphony; i < synth->nvoice; i++)
2339   {
2340     voice = synth->voice[i];
2341     if (_PLAYING (voice)) fluid_voice_off (voice);
2342   }
2343
2344   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, 
2345                            synth->polyphony, 0.0f);
2346
2347   return FLUID_OK;
2348 }
2349
2350 /**
2351  * Get current synthesizer polyphony (max number of voices).
2352  * @param synth FluidSynth instance
2353  * @return Synth polyphony value.
2354  * @since 1.0.6
2355  */
2356 int
2357 fluid_synth_get_polyphony(fluid_synth_t* synth)
2358 {
2359   int result;
2360   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
2361   fluid_synth_api_enter(synth);
2362   
2363   result = synth->polyphony;
2364   FLUID_API_RETURN(result);
2365 }
2366
2367 /**
2368  * Get current number of active voices.
2369  * @param synth FluidSynth instance
2370  * @return Number of currently active voices.
2371  * @since 1.1.0
2372  *
2373  * Note: To generate accurate continuous statistics of the voice count, caller
2374  * should ensure this function is called synchronously with the audio synthesis
2375  * process.  This can be done in the new_fluid_audio_driver2() audio callback
2376  * function for example.
2377  */
2378 int
2379 fluid_synth_get_active_voice_count(fluid_synth_t* synth)
2380 {
2381   int result;
2382   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
2383   fluid_synth_api_enter(synth);
2384
2385   result = synth->active_voice_count;
2386   FLUID_API_RETURN(result);
2387 }
2388
2389 /**
2390  * Get the internal synthesis buffer size value.
2391  * @param synth FluidSynth instance
2392  * @return Internal buffer size in audio frames.
2393  *
2394  * Audio is synthesized this number of frames at a time.  Defaults to 64 frames.
2395  */
2396 int
2397 fluid_synth_get_internal_bufsize(fluid_synth_t* synth)
2398 {
2399   return FLUID_BUFSIZE;
2400 }
2401
2402 /**
2403  * Resend a bank select and a program change for every channel.
2404  * @param synth FluidSynth instance
2405  * @return FLUID_OK on success, FLUID_FAILED otherwise
2406  *
2407  * This function is called mainly after a SoundFont has been loaded,
2408  * unloaded or reloaded.
2409  */
2410 int
2411 fluid_synth_program_reset(fluid_synth_t* synth)
2412 {
2413   int i, prog;
2414   fluid_synth_api_enter(synth);
2415   /* try to set the correct presets */
2416   for (i = 0; i < synth->midi_channels; i++){
2417     fluid_channel_get_sfont_bank_prog (synth->channel[i], NULL, NULL, &prog);
2418     fluid_synth_program_change(synth, i, prog);
2419   }
2420   FLUID_API_RETURN(FLUID_OK);
2421 }
2422
2423 /**
2424  * Synthesize a block of floating point audio to audio buffers.
2425  * @param synth FluidSynth instance
2426  * @param len Count of audio frames to synthesize
2427  * @param left Array of floats to store left channel of audio (len in size)
2428  * @param right Array of floats to store right channel of audio (len in size)
2429  * @param fx_left Not currently used
2430  * @param fx_right Not currently used
2431  * @return FLUID_OK on success, FLUID_FAIL otherwise
2432  *
2433  * NOTE: Should only be called from synthesis thread.
2434  */
2435 int
2436 fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
2437                          float** left, float** right,
2438                          float** fx_left, float** fx_right)
2439 {
2440   fluid_real_t** left_in;
2441   fluid_real_t** right_in;
2442   double time = fluid_utime();
2443   int i, num, available, count;
2444 #ifdef WITH_FLOAT
2445   int bytes;
2446 #endif
2447   float cpu_load;
2448
2449   if (!synth->eventhandler->is_threadsafe)
2450     fluid_synth_api_enter(synth);
2451   
2452   /* First, take what's still available in the buffer */
2453   count = 0;
2454   num = synth->cur;
2455   if (synth->cur < FLUID_BUFSIZE) {
2456     available = FLUID_BUFSIZE - synth->cur;
2457     fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
2458
2459     num = (available > len)? len : available;
2460 #ifdef WITH_FLOAT
2461     bytes = num * sizeof(float);
2462 #endif
2463
2464     for (i = 0; i < synth->audio_channels; i++) {
2465 #ifdef WITH_FLOAT
2466       FLUID_MEMCPY(left[i], left_in[i] + synth->cur, bytes);
2467       FLUID_MEMCPY(right[i], right_in[i] + synth->cur, bytes);
2468 #else //WITH_FLOAT
2469       int j;
2470       for (j = 0; j < num; j++) {
2471           left[i][j] = (float) left_in[i][j + synth->cur];
2472           right[i][j] = (float) right_in[i][j + synth->cur];
2473       }
2474 #endif //WITH_FLOAT
2475     }
2476     count += num;
2477     num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
2478   }
2479
2480   /* Then, run one_block() and copy till we have 'len' samples  */
2481   while (count < len) {
2482     fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0);
2483     fluid_synth_render_blocks(synth, 1); // TODO: 
2484     fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
2485
2486     num = (FLUID_BUFSIZE > len - count)? len - count : FLUID_BUFSIZE;
2487 #ifdef WITH_FLOAT
2488     bytes = num * sizeof(float);
2489 #endif
2490
2491     for (i = 0; i < synth->audio_channels; i++) {
2492 #ifdef WITH_FLOAT
2493       FLUID_MEMCPY(left[i] + count, left_in[i], bytes);
2494       FLUID_MEMCPY(right[i] + count, right_in[i], bytes);
2495 #else //WITH_FLOAT
2496       int j;
2497       for (j = 0; j < num; j++) {
2498           left[i][j + count] = (float) left_in[i][j];
2499           right[i][j + count] = (float) right_in[i][j];
2500       }
2501 #endif //WITH_FLOAT
2502     }
2503
2504     count += num;
2505   }
2506
2507   synth->cur = num;
2508
2509   time = fluid_utime() - time;
2510   cpu_load = 0.5 * (synth->cpu_load + time * synth->sample_rate / len / 10000.0);
2511   fluid_atomic_float_set (&synth->cpu_load, cpu_load);
2512
2513   if (!synth->eventhandler->is_threadsafe)
2514     fluid_synth_api_exit(synth);
2515   
2516   return FLUID_OK;
2517 }
2518
2519 /**
2520  * Synthesize floating point audio to audio buffers.
2521  * @param synth FluidSynth instance
2522  * @param len Count of audio frames to synthesize
2523  * @param nin Ignored
2524  * @param in Ignored
2525  * @param nout Count of arrays in 'out'
2526  * @param out Array of arrays to store audio to
2527  * @return FLUID_OK on success, FLUID_FAIL otherwise
2528  *
2529  * This function implements the default interface defined in fluidsynth/audio.h.
2530  * NOTE: Should only be called from synthesis thread.
2531  */
2532 /*
2533  * FIXME: Currently if nout != 2 memory allocation will occur!
2534  */
2535 int
2536 fluid_synth_process(fluid_synth_t* synth, int len, int nin, float** in,
2537                     int nout, float** out)
2538 {
2539   if (nout==2) {
2540     return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1);
2541   }
2542   else {
2543     float **left, **right;
2544     int i;
2545     left = FLUID_ARRAY(float*, nout/2);
2546     right = FLUID_ARRAY(float*, nout/2);
2547     for(i=0; i<nout/2; i++) {
2548       left[i] = out[2*i];
2549       right[i] = out[2*i+1];
2550     }
2551     fluid_synth_nwrite_float(synth, len, left, right, NULL, NULL);
2552     FLUID_FREE(left);
2553     FLUID_FREE(right);
2554     return FLUID_OK;
2555   }
2556 }
2557
2558 /**
2559  * Synthesize a block of floating point audio samples to audio buffers.
2560  * @param synth FluidSynth instance
2561  * @param len Count of audio frames to synthesize
2562  * @param lout Array of floats to store left channel of audio
2563  * @param loff Offset index in 'lout' for first sample
2564  * @param lincr Increment between samples stored to 'lout'
2565  * @param rout Array of floats to store right channel of audio
2566  * @param roff Offset index in 'rout' for first sample
2567  * @param rincr Increment between samples stored to 'rout'
2568  * @return FLUID_OK on success, FLUID_FAIL otherwise
2569  *
2570  * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
2571  * lincr = 2, rincr = 2).
2572  *
2573  * NOTE: Should only be called from synthesis thread.
2574  */
2575 int
2576 fluid_synth_write_float(fluid_synth_t* synth, int len,
2577                         void* lout, int loff, int lincr,
2578                         void* rout, int roff, int rincr)
2579 {
2580   int i, j, k, l;
2581   float* left_out = (float*) lout;
2582   float* right_out = (float*) rout;
2583   fluid_real_t** left_in;
2584   fluid_real_t** right_in;
2585   double time = fluid_utime();
2586   float cpu_load;
2587
2588   fluid_profile_ref_var (prof_ref);
2589   if (!synth->eventhandler->is_threadsafe)
2590     fluid_synth_api_enter(synth);
2591   
2592   fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
2593   l = synth->cur;
2594   fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
2595
2596   for (i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr) {
2597     /* fill up the buffers as needed */
2598       if (l >= synth->curmax) {
2599         int blocksleft = (len-i+FLUID_BUFSIZE-1) / FLUID_BUFSIZE;
2600         synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
2601         fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
2602
2603         l = 0;
2604       }
2605
2606       left_out[j] = (float) left_in[0][l];
2607       right_out[k] = (float) right_in[0][l];
2608   }
2609
2610   synth->cur = l;
2611
2612   time = fluid_utime() - time;
2613   cpu_load = 0.5 * (synth->cpu_load + time * synth->sample_rate / len / 10000.0);
2614   fluid_atomic_float_set (&synth->cpu_load, cpu_load);
2615
2616   if (!synth->eventhandler->is_threadsafe)
2617     fluid_synth_api_exit(synth);
2618   fluid_profile(FLUID_PROF_WRITE, prof_ref);
2619   
2620   return FLUID_OK;
2621 }
2622
2623 #define DITHER_SIZE 48000
2624 #define DITHER_CHANNELS 2
2625
2626 static float rand_table[DITHER_CHANNELS][DITHER_SIZE];
2627
2628 /* Init dither table */
2629 static void 
2630 init_dither(void)
2631 {
2632   float d, dp;
2633   int c, i;
2634
2635   for (c = 0; c < DITHER_CHANNELS; c++) {
2636     dp = 0;
2637     for (i = 0; i < DITHER_SIZE-1; i++) {
2638       d = rand() / (float)RAND_MAX - 0.5f;
2639       rand_table[c][i] = d - dp;
2640       dp = d;
2641     }
2642     rand_table[c][DITHER_SIZE-1] = 0 - dp;
2643   }
2644 }
2645
2646 /* A portable replacement for roundf(), seems it may actually be faster too! */
2647 static inline int
2648 roundi (float x)
2649 {
2650   if (x >= 0.0f)
2651     return (int)(x+0.5f);
2652   else
2653     return (int)(x-0.5f);
2654 }
2655
2656 /**
2657  * Synthesize a block of 16 bit audio samples to audio buffers.
2658  * @param synth FluidSynth instance
2659  * @param len Count of audio frames to synthesize
2660  * @param lout Array of 16 bit words to store left channel of audio
2661  * @param loff Offset index in 'lout' for first sample
2662  * @param lincr Increment between samples stored to 'lout'
2663  * @param rout Array of 16 bit words to store right channel of audio
2664  * @param roff Offset index in 'rout' for first sample
2665  * @param rincr Increment between samples stored to 'rout'
2666  * @return FLUID_OK on success, FLUID_FAIL otherwise
2667  *
2668  * Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
2669  * lincr = 2, rincr = 2).
2670  *
2671  * NOTE: Should only be called from synthesis thread.
2672  * NOTE: Dithering is performed when converting from internal floating point to
2673  * 16 bit audio.
2674  */
2675 int
2676 fluid_synth_write_s16(fluid_synth_t* synth, int len,
2677                       void* lout, int loff, int lincr,
2678                       void* rout, int roff, int rincr)
2679 {
2680   int i, j, k, cur;
2681   signed short* left_out = (signed short*) lout;
2682   signed short* right_out = (signed short*) rout;
2683   fluid_real_t** left_in;
2684   fluid_real_t** right_in;
2685   fluid_real_t left_sample;
2686   fluid_real_t right_sample;
2687   double time = fluid_utime();
2688   int di; 
2689   //double prof_ref_on_block;
2690   float cpu_load;
2691   fluid_profile_ref_var (prof_ref);
2692   
2693   if (!synth->eventhandler->is_threadsafe)
2694     fluid_synth_api_enter(synth);
2695   
2696   fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1);
2697   fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
2698
2699   cur = synth->cur;
2700   di = synth->dither_index;
2701
2702   for (i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr) {
2703
2704     /* fill up the buffers as needed */
2705     if (cur >= synth->curmax) { 
2706       int blocksleft = (len-i+FLUID_BUFSIZE-1) / FLUID_BUFSIZE;
2707       //prof_ref_on_block = fluid_profile_ref();
2708       synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
2709       fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
2710       cur = 0;
2711
2712       //fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref_on_block);
2713     }
2714
2715     left_sample = roundi (left_in[0][cur] * 32766.0f + rand_table[0][di]);
2716     right_sample = roundi (right_in[0][cur] * 32766.0f + rand_table[1][di]);
2717
2718     di++;
2719     if (di >= DITHER_SIZE) di = 0;
2720
2721     /* digital clipping */
2722     if (left_sample > 32767.0f) left_sample = 32767.0f;
2723     if (left_sample < -32768.0f) left_sample = -32768.0f;
2724     if (right_sample > 32767.0f) right_sample = 32767.0f;
2725     if (right_sample < -32768.0f) right_sample = -32768.0f;
2726
2727     left_out[j] = (signed short) left_sample;
2728     right_out[k] = (signed short) right_sample;
2729   }
2730
2731   synth->cur = cur;
2732   synth->dither_index = di;     /* keep dither buffer continous */
2733
2734   fluid_profile(FLUID_PROF_WRITE, prof_ref);
2735
2736   time = fluid_utime() - time;
2737   cpu_load = 0.5 * (synth->cpu_load + time * synth->sample_rate / len / 10000.0);
2738   fluid_atomic_float_set (&synth->cpu_load, cpu_load);
2739
2740   if (!synth->eventhandler->is_threadsafe)
2741     fluid_synth_api_exit(synth);
2742   
2743   return 0;
2744 }
2745
2746 /**
2747  * Converts stereo floating point sample data to signed 16 bit data with dithering.
2748  * @param dither_index Pointer to an integer which should be initialized to 0
2749  *   before the first call and passed unmodified to additional calls which are
2750  *   part of the same synthesis output.
2751  * @param len Length in frames to convert
2752  * @param lin Buffer of left audio samples to convert from
2753  * @param rin Buffer of right audio samples to convert from
2754  * @param lout Array of 16 bit words to store left channel of audio
2755  * @param loff Offset index in 'lout' for first sample
2756  * @param lincr Increment between samples stored to 'lout'
2757  * @param rout Array of 16 bit words to store right channel of audio
2758  * @param roff Offset index in 'rout' for first sample
2759  * @param rincr Increment between samples stored to 'rout'
2760  *
2761  * NOTE: Currently private to libfluidsynth.
2762  */
2763 void
2764 fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
2765                        void* lout, int loff, int lincr,
2766                        void* rout, int roff, int rincr)
2767 {
2768   int i, j, k;
2769   signed short* left_out = (signed short*) lout;
2770   signed short* right_out = (signed short*) rout;
2771   fluid_real_t left_sample;
2772   fluid_real_t right_sample;
2773   int di = *dither_index;
2774   fluid_profile_ref_var (prof_ref);
2775
2776   for (i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr) {
2777
2778     left_sample = roundi (lin[i] * 32766.0f + rand_table[0][di]);
2779     right_sample = roundi (rin[i] * 32766.0f + rand_table[1][di]);
2780
2781     di++;
2782     if (di >= DITHER_SIZE) di = 0;
2783
2784     /* digital clipping */
2785     if (left_sample > 32767.0f) left_sample = 32767.0f;
2786     if (left_sample < -32768.0f) left_sample = -32768.0f;
2787     if (right_sample > 32767.0f) right_sample = 32767.0f;
2788     if (right_sample < -32768.0f) right_sample = -32768.0f;
2789
2790     left_out[j] = (signed short) left_sample;
2791     right_out[k] = (signed short) right_sample;
2792   }
2793
2794   *dither_index = di;   /* keep dither buffer continous */
2795
2796   fluid_profile(FLUID_PROF_WRITE, prof_ref);
2797 }
2798
2799 static void
2800 fluid_synth_check_finished_voices(fluid_synth_t* synth)
2801 {
2802   int j;
2803   fluid_rvoice_t* fv;
2804   
2805   while (NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler))) {
2806     for (j=0; j < synth->polyphony; j++) {
2807       if (synth->voice[j]->rvoice == fv) {
2808         fluid_voice_unlock_rvoice(synth->voice[j]);
2809         fluid_voice_off(synth->voice[j]);
2810         break;
2811       }
2812       else if (synth->voice[j]->overflow_rvoice == fv) {
2813         fluid_voice_overflow_rvoice_finished(synth->voice[j]);
2814         break;
2815       }
2816     }
2817   }
2818 }
2819
2820 /**
2821  * Process all waiting events in the rvoice queue.
2822  * Make sure no (other) rendering is running in parallel when
2823  * you call this function!
2824  */
2825 void fluid_synth_process_event_queue(fluid_synth_t* synth)
2826 {
2827   fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
2828 }
2829
2830
2831 /**
2832  * Process blocks (FLUID_BUFSIZE) of audio.
2833  * Must be called from renderer thread only!
2834  * @return number of blocks rendered. Might (often) return less than requested
2835  */
2836 static int
2837 fluid_synth_render_blocks(fluid_synth_t* synth, int blockcount)
2838 {
2839   int i;
2840   fluid_profile_ref_var (prof_ref);
2841
2842   /* Assign ID of synthesis thread */
2843 //  synth->synth_thread_id = fluid_thread_get_id ();
2844
2845   fluid_check_fpe("??? Just starting up ???");
2846   
2847   fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
2848   
2849   for (i=0; i < blockcount; i++) {
2850     fluid_sample_timer_process(synth);
2851     fluid_synth_add_ticks(synth, FLUID_BUFSIZE);
2852     if (fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler)) {
2853       // Something has happened, we can't process more
2854       blockcount = i+1;
2855       break; 
2856     }
2857   }
2858
2859   fluid_check_fpe("fluid_sample_timer_process");
2860
2861   blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount);
2862
2863   /* Testcase, that provokes a denormal floating point error */
2864 #if 0
2865   {float num=1;while (num != 0){num*=0.5;};};
2866 #endif
2867   fluid_check_fpe("??? Remainder of synth_one_block ???");
2868   fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref);
2869   return blockcount;
2870 }
2871
2872
2873 static int fluid_synth_update_overflow (fluid_synth_t *synth, char *name,
2874                                          fluid_real_t value)
2875 {
2876   double d;
2877   fluid_synth_api_enter(synth);
2878   
2879   fluid_settings_getnum(synth->settings, "synth.overflow.percussion", &d);
2880   synth->overflow.percussion = d;
2881   fluid_settings_getnum(synth->settings, "synth.overflow.released", &d);
2882   synth->overflow.released = d;
2883   fluid_settings_getnum(synth->settings, "synth.overflow.sustained", &d);
2884   synth->overflow.sustained = d;
2885   fluid_settings_getnum(synth->settings, "synth.overflow.volume", &d);
2886   synth->overflow.volume = d;
2887   fluid_settings_getnum(synth->settings, "synth.overflow.age", &d);
2888   synth->overflow.age = d;
2889   
2890   FLUID_API_RETURN(0);
2891 }
2892
2893
2894 /* Selects a voice for killing. */
2895 static fluid_voice_t*
2896 fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth)
2897 {
2898   int i;
2899   fluid_real_t best_prio = OVERFLOW_PRIO_CANNOT_KILL-1;
2900   fluid_real_t this_voice_prio;
2901   fluid_voice_t* voice;
2902   int best_voice_index=-1;
2903   unsigned int ticks = fluid_synth_get_ticks(synth);
2904   
2905   for (i = 0; i < synth->polyphony; i++) {
2906
2907     voice = synth->voice[i];
2908
2909     /* safeguard against an available voice. */
2910     if (_AVAILABLE(voice)) {
2911       return voice;
2912     }
2913     this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow,
2914                                                     ticks);
2915
2916     /* check if this voice has less priority than the previous candidate. */
2917     if (this_voice_prio < best_prio) {
2918       best_voice_index = i;
2919       best_prio = this_voice_prio;
2920     }
2921   }
2922
2923   if (best_voice_index < 0) {
2924     return NULL;
2925   }
2926
2927   voice = synth->voice[best_voice_index];
2928   FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ",
2929             voice->id, best_voice_index, voice->chan, voice->key);
2930   fluid_voice_off(voice);
2931
2932   return voice;
2933 }
2934
2935
2936 /**
2937  * Allocate a synthesis voice.
2938  * @param synth FluidSynth instance
2939  * @param sample Sample to assign to the voice
2940  * @param chan MIDI channel number (0 to MIDI channel count - 1)
2941  * @param key MIDI note number for the voice (0-127)
2942  * @param vel MIDI velocity for the voice (0-127)
2943  * @return Allocated synthesis voice or NULL on error
2944  *
2945  * This function is called by a SoundFont's preset in response to a noteon event.
2946  * The returned voice comes with default modulators and generators.
2947  * A single noteon event may create any number of voices, when the preset is layered.
2948  *
2949  * NOTE: Should only be called from within synthesis thread, which includes
2950  * SoundFont loader preset noteon method.
2951  */
2952 fluid_voice_t*
2953 fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int key, int vel)
2954 {
2955   int i, k;
2956   fluid_voice_t* voice = NULL;
2957   fluid_channel_t* channel = NULL;
2958   unsigned int ticks;
2959
2960   fluid_return_val_if_fail (sample != NULL, NULL);
2961   FLUID_API_ENTRY_CHAN(NULL);
2962
2963   /* check if there's an available synthesis process */
2964   for (i = 0; i < synth->polyphony; i++) {
2965     if (_AVAILABLE(synth->voice[i])) {
2966       voice = synth->voice[i];
2967       break;
2968     }
2969   }
2970
2971   /* No success yet? Then stop a running voice. */
2972   if (voice == NULL) {
2973     FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice");
2974     voice = fluid_synth_free_voice_by_kill_LOCAL(synth);
2975   }
2976
2977   if (voice == NULL) {
2978     FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
2979     FLUID_API_RETURN(NULL);
2980   }
2981   ticks = fluid_synth_get_ticks(synth);
2982
2983   if (synth->verbose) {
2984     k = 0;
2985     for (i = 0; i < synth->polyphony; i++) {
2986       if (!_AVAILABLE(synth->voice[i])) {
2987         k++;
2988       }
2989     }
2990
2991     FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
2992              chan, key, vel, synth->storeid,
2993              (float) ticks / 44100.0f,
2994              (fluid_curtime() - synth->start) / 1000.0f,
2995              0.0f,
2996              k);
2997   }
2998
2999   if (chan >= 0) {
3000           channel = synth->channel[chan];
3001   }
3002
3003   if (fluid_voice_init (voice, sample, channel, key, vel,
3004                         synth->storeid, ticks, synth->gain) != FLUID_OK) {
3005     FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
3006     FLUID_API_RETURN(NULL);
3007   }
3008
3009   /* add the default modulators to the synthesis process. */
3010   fluid_voice_add_mod(voice, &default_vel2att_mod, FLUID_VOICE_DEFAULT);    /* SF2.01 $8.4.1  */
3011   fluid_voice_add_mod(voice, &default_vel2filter_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.2  */
3012   fluid_voice_add_mod(voice, &default_at2viblfo_mod, FLUID_VOICE_DEFAULT);  /* SF2.01 $8.4.3  */
3013   fluid_voice_add_mod(voice, &default_mod2viblfo_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.4  */
3014   fluid_voice_add_mod(voice, &default_att_mod, FLUID_VOICE_DEFAULT);        /* SF2.01 $8.4.5  */
3015   fluid_voice_add_mod(voice, &default_pan_mod, FLUID_VOICE_DEFAULT);        /* SF2.01 $8.4.6  */
3016   fluid_voice_add_mod(voice, &default_expr_mod, FLUID_VOICE_DEFAULT);       /* SF2.01 $8.4.7  */
3017   fluid_voice_add_mod(voice, &default_reverb_mod, FLUID_VOICE_DEFAULT);     /* SF2.01 $8.4.8  */
3018   fluid_voice_add_mod(voice, &default_chorus_mod, FLUID_VOICE_DEFAULT);     /* SF2.01 $8.4.9  */
3019   fluid_voice_add_mod(voice, &default_pitch_bend_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.10 */
3020
3021   FLUID_API_RETURN(voice);
3022 }
3023
3024 /* Kill all voices on a given channel, which have the same exclusive class
3025  * generator as new_voice.
3026  */
3027 static void
3028 fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth,
3029                                           fluid_voice_t* new_voice)
3030 {
3031   int excl_class = _GEN(new_voice,GEN_EXCLUSIVECLASS);
3032   fluid_voice_t* existing_voice;
3033   int i;
3034
3035   /* Excl. class 0: No exclusive class */
3036   if (excl_class == 0) return;
3037
3038   /* Kill all notes on the same channel with the same exclusive class */
3039   for (i = 0; i < synth->polyphony; i++) {
3040     existing_voice = synth->voice[i];
3041
3042     /* If voice is playing, on the same channel, has same exclusive
3043      * class and is not part of the same noteon event (voice group), then kill it */
3044
3045     if (_PLAYING(existing_voice)
3046         && existing_voice->chan == new_voice->chan
3047         && (int)_GEN (existing_voice, GEN_EXCLUSIVECLASS) == excl_class
3048         && fluid_voice_get_id (existing_voice) != fluid_voice_get_id(new_voice))
3049       fluid_voice_kill_excl(existing_voice);
3050   }
3051 }
3052
3053 /**
3054  * Activate a voice previously allocated with fluid_synth_alloc_voice().
3055  * @param synth FluidSynth instance
3056  * @param voice Voice to activate
3057  *
3058  * This function is called by a SoundFont's preset in response to a noteon
3059  * event.  Exclusive classes are processed here.
3060  *
3061  * NOTE: Should only be called from within synthesis thread, which includes
3062  * SoundFont loader preset noteon method.
3063  */
3064 void
3065 fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice)
3066 {
3067   fluid_return_if_fail (synth != NULL);
3068   fluid_return_if_fail (voice != NULL);
3069 //  fluid_return_if_fail (fluid_synth_is_synth_thread (synth));
3070   fluid_synth_api_enter(synth);
3071
3072   /* Find the exclusive class of this voice. If set, kill all voices
3073    * that match the exclusive class and are younger than the first
3074    * voice process created by this noteon event. */
3075   fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice);
3076
3077   fluid_voice_start(voice);     /* Start the new voice */
3078   if (synth->eventhandler->is_threadsafe)
3079     fluid_voice_lock_rvoice(voice);
3080   fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice);
3081   fluid_synth_api_exit(synth);
3082 }
3083
3084 /**
3085  * Add a SoundFont loader interface.
3086  * @param synth FluidSynth instance
3087  * @param loader Loader API structure, used directly and should remain allocated
3088  *   as long as the synth instance is used.
3089  *
3090  * SoundFont loaders are used to add custom instrument loading to FluidSynth.
3091  * The caller supplied functions for loading files, allocating presets,
3092  * retrieving information on them and synthesizing note-on events.  Using this
3093  * method even non SoundFont instruments can be synthesized, although limited
3094  * to the SoundFont synthesis model.
3095  *
3096  * NOTE: Should only be called before any SoundFont files are loaded.
3097  */
3098 void
3099 fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader)
3100 {
3101   gboolean sfont_already_loaded;
3102
3103   fluid_return_if_fail (synth != NULL);
3104   fluid_return_if_fail (loader != NULL);
3105   fluid_synth_api_enter(synth);
3106   sfont_already_loaded = synth->sfont_info != NULL;
3107   if (!sfont_already_loaded) 
3108     synth->loaders = fluid_list_prepend(synth->loaders, loader);
3109   fluid_synth_api_exit(synth);
3110 }
3111
3112 /**
3113  * Load a SoundFont file (filename is interpreted by SoundFont loaders).
3114  * The newly loaded SoundFont will be put on top of the SoundFont
3115  * stack. Presets are searched starting from the SoundFont on the
3116  * top of the stack, working the way down the stack until a preset is found.
3117  *
3118  * @param synth SoundFont instance
3119  * @param filename File to load
3120  * @param reset_presets TRUE to re-assign presets for all MIDI channels
3121  * @return SoundFont ID on success, FLUID_FAILED on error
3122  */
3123 int
3124 fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets)
3125 {
3126   fluid_sfont_info_t *sfont_info;
3127   fluid_sfont_t *sfont;
3128   fluid_list_t *list;
3129   fluid_sfloader_t *loader;
3130   unsigned int sfont_id;
3131
3132   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
3133   fluid_return_val_if_fail (filename != NULL, FLUID_FAILED);
3134   fluid_synth_api_enter(synth);
3135   
3136   /* MT NOTE: Loaders list should not change. */
3137
3138   for (list = synth->loaders; list; list = fluid_list_next(list)) {
3139     loader = (fluid_sfloader_t*) fluid_list_get(list);
3140
3141     sfont = fluid_sfloader_load(loader, filename);
3142
3143     if (sfont != NULL) {
3144       sfont_info = new_fluid_sfont_info (synth, sfont);
3145
3146       if (!sfont_info)
3147       {
3148         delete_fluid_sfont (sfont);
3149         FLUID_API_RETURN(FLUID_FAILED);
3150       }
3151
3152       sfont->id = sfont_id = ++synth->sfont_id;
3153       synth->sfont_info = fluid_list_prepend(synth->sfont_info, sfont_info);   /* prepend to list */
3154       fluid_hashtable_insert (synth->sfont_hash, sfont, sfont_info);       /* Hash sfont->sfont_info */
3155
3156       /* reset the presets for all channels if requested */
3157       if (reset_presets) fluid_synth_program_reset(synth);
3158
3159       FLUID_API_RETURN((int)sfont_id);
3160     }
3161   }
3162
3163   FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
3164   FLUID_API_RETURN(FLUID_FAILED);
3165 }
3166
3167 /* Create a new SoundFont info structure, free with FLUID_FREE */
3168 static fluid_sfont_info_t *
3169 new_fluid_sfont_info (fluid_synth_t *synth, fluid_sfont_t *sfont)
3170 {
3171   fluid_sfont_info_t *sfont_info;
3172
3173   sfont_info = FLUID_NEW (fluid_sfont_info_t);
3174
3175   if (!sfont_info)
3176   {
3177     FLUID_LOG(FLUID_ERR, "Out of memory");
3178     return NULL;
3179   }
3180
3181   sfont_info->sfont = sfont;
3182   sfont_info->synth = synth;
3183   sfont_info->refcount = 1;     /* Start with refcount of 1 for owning synth */
3184   sfont_info->bankofs = 0;
3185
3186   return (sfont_info);
3187 }
3188
3189 /**
3190  * Unload a SoundFont.
3191  * @param synth SoundFont instance
3192  * @param id ID of SoundFont to unload
3193  * @param reset_presets TRUE to re-assign presets for all MIDI channels
3194  * @return FLUID_OK on success, FLUID_FAILED on error
3195  */
3196 int
3197 fluid_synth_sfunload(fluid_synth_t* synth, unsigned int id, int reset_presets)
3198 {
3199   fluid_sfont_info_t *sfont_info = NULL;
3200   fluid_list_t *list;
3201
3202   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
3203   fluid_synth_api_enter(synth);
3204   
3205   /* remove the SoundFont from the list */
3206   for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
3207     sfont_info = (fluid_sfont_info_t*) fluid_list_get(list);
3208
3209     if (fluid_sfont_get_id (sfont_info->sfont) == id)
3210     {
3211       synth->sfont_info = fluid_list_remove (synth->sfont_info, sfont_info);
3212       break;
3213     }
3214   }
3215
3216   if (!list) {
3217     FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
3218     FLUID_API_RETURN(FLUID_FAILED);
3219   }
3220
3221   /* reset the presets for all channels (SoundFont will be freed when there are no more references) */
3222   if (reset_presets) fluid_synth_program_reset (synth);
3223   else fluid_synth_update_presets (synth);
3224
3225   /* -- Remove synth->sfont_info list's reference to SoundFont */
3226   fluid_synth_sfont_unref (synth, sfont_info->sfont);
3227
3228   FLUID_API_RETURN(FLUID_OK);
3229 }
3230
3231 /* Unref a SoundFont and destroy if no more references */
3232 void
3233 fluid_synth_sfont_unref (fluid_synth_t *synth, fluid_sfont_t *sfont)
3234 {
3235   fluid_sfont_info_t *sfont_info;
3236   int refcount = 0;
3237   
3238   sfont_info = fluid_hashtable_lookup (synth->sfont_hash, sfont);
3239
3240   if (sfont_info)
3241   {
3242     sfont_info->refcount--;             /* -- Remove the sfont_info list's reference */
3243     refcount = sfont_info->refcount;
3244
3245     if (refcount == 0)    /* Remove SoundFont from hash if no more references */
3246       fluid_hashtable_remove (synth->sfont_hash, sfont_info->sfont);
3247   }
3248
3249   fluid_return_if_fail (sfont_info != NULL);    /* Shouldn't happen, programming error if so */
3250
3251   if (refcount == 0)                    /* No more references? - Attempt delete */
3252   {
3253     if (delete_fluid_sfont (sfont_info->sfont) == 0)    /* SoundFont loader can block SoundFont unload */
3254     {
3255       FLUID_FREE (sfont_info);
3256       FLUID_LOG (FLUID_DBG, "Unloaded SoundFont");
3257     } /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */
3258     else new_fluid_timer (100, fluid_synth_sfunload_callback, sfont_info, TRUE, TRUE, FALSE);    
3259   }
3260 }
3261
3262 /* Callback to continually attempt to unload a SoundFont,
3263  * only if a SoundFont loader blocked the unload operation */
3264 static int
3265 fluid_synth_sfunload_callback(void* data, unsigned int msec)
3266 {
3267   fluid_sfont_info_t *sfont_info = (fluid_sfont_info_t *)data;
3268
3269   if (delete_fluid_sfont (sfont_info->sfont) == 0)
3270   {
3271     FLUID_FREE (sfont_info);
3272     FLUID_LOG (FLUID_DBG, "Unloaded SoundFont");
3273     return FALSE;
3274   }
3275   else return TRUE;
3276 }
3277
3278 /**
3279  * Reload a SoundFont.  The SoundFont retains its ID and index on the SoundFont stack.
3280  * @param synth SoundFont instance
3281  * @param id ID of SoundFont to reload
3282  * @return SoundFont ID on success, FLUID_FAILED on error
3283  */
3284 int
3285 fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id)
3286 {
3287   char filename[1024];
3288   fluid_sfont_info_t *sfont_info, *old_sfont_info;
3289   fluid_sfont_t* sfont;
3290   fluid_sfloader_t* loader;
3291   fluid_list_t *list;
3292   int index;
3293
3294   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
3295   fluid_synth_api_enter(synth);
3296
3297   /* Search for SoundFont and get its index */
3298   for (list = synth->sfont_info, index = 0; list; list = fluid_list_next (list), index++) {
3299     old_sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
3300     if (fluid_sfont_get_id (old_sfont_info->sfont) == id) break;
3301   }
3302
3303   if (!list) {
3304     FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
3305     FLUID_API_RETURN(FLUID_FAILED);
3306   }
3307
3308   /* keep a copy of the SoundFont's filename */
3309   FLUID_STRCPY (filename, fluid_sfont_get_name (old_sfont_info->sfont));
3310
3311   if (fluid_synth_sfunload (synth, id, FALSE) != FLUID_OK)
3312     FLUID_API_RETURN(FLUID_FAILED);
3313
3314   /* MT Note: SoundFont loader list will not change */
3315
3316   for (list = synth->loaders; list; list = fluid_list_next(list)) {
3317     loader = (fluid_sfloader_t*) fluid_list_get(list);
3318
3319     sfont = fluid_sfloader_load(loader, filename);
3320
3321     if (sfont != NULL) {
3322       sfont->id = id;
3323
3324       sfont_info = new_fluid_sfont_info (synth, sfont);
3325
3326       if (!sfont_info)
3327       {
3328         delete_fluid_sfont (sfont);
3329         FLUID_API_RETURN(FLUID_FAILED);
3330       }
3331
3332       synth->sfont_info = fluid_list_insert_at(synth->sfont_info, index, sfont_info);  /* insert the sfont at the same index */
3333       fluid_hashtable_insert (synth->sfont_hash, sfont, sfont_info);       /* Hash sfont->sfont_info */
3334
3335       /* reset the presets for all channels */
3336       fluid_synth_update_presets(synth);
3337       FLUID_API_RETURN(sfont->id);
3338     }
3339   }
3340
3341   FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
3342   FLUID_API_RETURN(FLUID_FAILED);  
3343 }
3344
3345 /**
3346  * Add a SoundFont.  The SoundFont will be added to the top of the SoundFont stack.
3347  * @param synth FluidSynth instance
3348  * @param sfont SoundFont to add
3349  * @return New assigned SoundFont ID or FLUID_FAILED on error
3350  */
3351 int
3352 fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
3353 {
3354   fluid_sfont_info_t *sfont_info;
3355   unsigned int sfont_id;
3356
3357   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
3358   fluid_return_val_if_fail (sfont != NULL, FLUID_FAILED);
3359   fluid_synth_api_enter(synth);
3360   
3361   sfont_info = new_fluid_sfont_info (synth, sfont);
3362   if (!sfont_info) 
3363       FLUID_API_RETURN(FLUID_FAILED);
3364
3365   sfont->id = sfont_id = ++synth->sfont_id;
3366   synth->sfont_info = fluid_list_prepend (synth->sfont_info, sfont_info);       /* prepend to list */
3367   fluid_hashtable_insert (synth->sfont_hash, sfont, sfont_info);   /* Hash sfont->sfont_info */
3368
3369   /* reset the presets for all channels */
3370   fluid_synth_program_reset (synth);
3371
3372   FLUID_API_RETURN(sfont_id);
3373 }
3374
3375 /**
3376  * Remove a SoundFont from the SoundFont stack without deleting it.
3377  * @param synth FluidSynth instance
3378  * @param sfont SoundFont to remove
3379  *
3380  * SoundFont is not freed and is left as the responsibility of the caller.
3381  *
3382  * NOTE: The SoundFont should only be freed after there are no presets
3383  *   referencing it.  This can only be ensured by the SoundFont loader and
3384  *   therefore this function should not normally be used.
3385  */
3386 void
3387 fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
3388 {
3389   fluid_sfont_info_t *sfont_info;
3390   fluid_list_t *list;
3391
3392   fluid_return_if_fail (synth != NULL);
3393   fluid_return_if_fail (sfont != NULL);
3394   fluid_synth_api_enter(synth);
3395   
3396   /* remove the SoundFont from the list */
3397   for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
3398     sfont_info = (fluid_sfont_info_t*) fluid_list_get(list);
3399
3400     if (sfont_info->sfont == sfont)
3401     {
3402       synth->sfont_info = fluid_list_remove (synth->sfont_info, sfont_info);
3403
3404       /* Remove from SoundFont hash regardless of refcount (SoundFont delete is up to caller) */
3405       fluid_hashtable_remove (synth->sfont_hash, sfont_info->sfont);
3406       break;
3407     }
3408   }
3409
3410   /* reset the presets for all channels */
3411   fluid_synth_program_reset (synth);
3412   fluid_synth_api_exit(synth);
3413 }
3414
3415 /**
3416  * Count number of loaded SoundFont files.
3417  * @param synth FluidSynth instance
3418  * @return Count of loaded SoundFont files.
3419  */
3420 int
3421 fluid_synth_sfcount(fluid_synth_t* synth)
3422 {
3423   int count;
3424   
3425   fluid_return_val_if_fail (synth != NULL, 0);
3426   fluid_synth_api_enter(synth);
3427   count = fluid_list_size (synth->sfont_info);
3428   FLUID_API_RETURN(count);
3429 }
3430
3431 /**
3432  * Get SoundFont by index.
3433  * @param synth FluidSynth instance
3434  * @param num SoundFont index on the stack (starting from 0 for top of stack).
3435  * @return SoundFont instance or NULL if invalid index
3436  *
3437  * NOTE: Caller should be certain that SoundFont is not deleted (unloaded) for
3438  * the duration of use of the returned pointer.
3439  */
3440 fluid_sfont_t *
3441 fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num)
3442 {
3443   fluid_sfont_t *sfont = NULL;
3444   fluid_list_t *list;
3445
3446   fluid_return_val_if_fail (synth != NULL, NULL);
3447   fluid_synth_api_enter(synth);
3448   list = fluid_list_nth (synth->sfont_info, num);
3449   if (list) sfont = ((fluid_sfont_info_t *)fluid_list_get (list))->sfont;
3450   FLUID_API_RETURN(sfont);
3451 }
3452
3453 /**
3454  * Get SoundFont by ID.
3455  * @param synth FluidSynth instance
3456  * @param id SoundFont ID
3457  * @return SoundFont instance or NULL if invalid ID
3458  *
3459  * NOTE: Caller should be certain that SoundFont is not deleted (unloaded) for
3460  * the duration of use of the returned pointer.
3461  */
3462 fluid_sfont_t *
3463 fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id)
3464 {
3465   fluid_sfont_t* sfont = NULL;
3466   fluid_list_t* list;
3467
3468   fluid_return_val_if_fail (synth != NULL, NULL);
3469   fluid_synth_api_enter(synth);
3470
3471   for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
3472     sfont = ((fluid_sfont_info_t *)fluid_list_get (list))->sfont;
3473     if (fluid_sfont_get_id (sfont) == id)
3474       break;
3475   }
3476
3477   FLUID_API_RETURN(list ? sfont : NULL);
3478 }
3479
3480 /**
3481  * Get SoundFont by name.
3482  * @param synth FluidSynth instance
3483  * @param name Name of SoundFont
3484  * @return SoundFont instance or NULL if invalid name
3485  * @since 1.1.0
3486  *
3487  * NOTE: Caller should be certain that SoundFont is not deleted (unloaded) for
3488  * the duration of use of the returned pointer.
3489  */
3490 fluid_sfont_t *
3491 fluid_synth_get_sfont_by_name(fluid_synth_t* synth, const char *name)
3492 {
3493   fluid_sfont_t* sfont = NULL;
3494   fluid_list_t* list;
3495
3496   fluid_return_val_if_fail (synth != NULL, NULL);
3497   fluid_return_val_if_fail (name != NULL, NULL);
3498   fluid_synth_api_enter(synth);
3499
3500   for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
3501     sfont = ((fluid_sfont_info_t *)fluid_list_get (list))->sfont;
3502     if (FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0)
3503       break;
3504   }
3505
3506   FLUID_API_RETURN(list ? sfont : NULL);
3507 }
3508
3509 /**
3510  * Get active preset on a MIDI channel.
3511  * @param synth FluidSynth instance
3512  * @param chan MIDI channel number (0 to MIDI channel count - 1)
3513  * @return Preset or NULL if no preset active on channel
3514  * @deprecated fluid_synth_get_channel_info() should replace most use cases.
3515  *
3516  * NOTE: Should only be called from within synthesis thread, which includes
3517  * SoundFont loader preset noteon methods.  Not thread safe otherwise.
3518  */
3519 fluid_preset_t *
3520 fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan)
3521 {
3522   fluid_preset_t* result;
3523   fluid_channel_t *channel;
3524   FLUID_API_ENTRY_CHAN(NULL);
3525
3526   channel = synth->channel[chan];
3527   result = channel->preset;
3528   fluid_synth_api_exit(synth);
3529   return result;
3530 }
3531
3532 /**
3533  * Get information on the currently selected preset on a MIDI channel.
3534  * @param synth FluidSynth instance
3535  * @param chan MIDI channel number (0 to MIDI channel count - 1)
3536  * @param info Caller supplied structure to fill with preset information
3537  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
3538  * @since 1.1.1
3539  */
3540 int
3541 fluid_synth_get_channel_info (fluid_synth_t *synth, int chan,
3542                               fluid_synth_channel_info_t *info)
3543 {
3544   fluid_channel_t *channel;
3545   fluid_preset_t *preset;
3546   char *name;
3547
3548   if (info)
3549   {
3550     info->assigned = FALSE;
3551     info->name[0] = '\0';
3552   }
3553
3554   fluid_return_val_if_fail (info != NULL, FLUID_FAILED);
3555   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3556   
3557   channel = synth->channel[chan];
3558   preset = channel->preset;
3559
3560   if (preset)
3561   {
3562     info->assigned = TRUE;
3563     name = fluid_preset_get_name (preset);
3564
3565     if (name)
3566     {
3567       strncpy (info->name, name, FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE);
3568       info->name[FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE - 1] = '\0';
3569     }
3570     else info->name[0] = '\0';
3571
3572     info->sfont_id = preset->sfont->id;
3573     info->bank = fluid_preset_get_banknum (preset);
3574     info->program = fluid_preset_get_num (preset);
3575   }
3576   else
3577   {
3578     info->assigned = FALSE;
3579     fluid_channel_get_sfont_bank_prog (channel, &info->sfont_id, &info->bank, &info->program);
3580     info->name[0] = '\0';
3581   }
3582
3583   fluid_synth_api_exit(synth);
3584   return FLUID_OK;
3585 }
3586
3587 /**
3588  * Get list of voices.
3589  * @param synth FluidSynth instance
3590  * @param buf Array to store voices to (NULL terminated if not filled completely)
3591  * @param bufsize Count of indexes in buf
3592  * @param id Voice ID to search for or < 0 to return list of all playing voices
3593  *
3594  * NOTE: Should only be called from within synthesis thread, which includes
3595  * SoundFont loader preset noteon methods.  Voices are only guaranteed to remain
3596  * unchanged until next synthesis process iteration.
3597  */
3598 void
3599 fluid_synth_get_voicelist(fluid_synth_t* synth, fluid_voice_t* buf[], int bufsize,
3600                           int id)
3601 {
3602   int count = 0;
3603   int i;
3604
3605   fluid_return_if_fail (synth != NULL);
3606   fluid_return_if_fail (buf != NULL);
3607   fluid_synth_api_enter(synth);
3608
3609   for (i = 0; i < synth->polyphony && count < bufsize; i++) {
3610     fluid_voice_t* voice = synth->voice[i];
3611
3612     if (_PLAYING(voice) && (id < 0 || (int)voice->id == id))
3613       buf[count++] = voice;
3614   }
3615
3616   if (count < bufsize) buf[count] = NULL;
3617   fluid_synth_api_exit(synth);
3618 }
3619
3620 /**
3621  * Enable or disable reverb effect.
3622  * @param synth FluidSynth instance
3623  * @param on TRUE to enable reverb, FALSE to disable
3624  */
3625 void
3626 fluid_synth_set_reverb_on(fluid_synth_t* synth, int on)
3627 {
3628   fluid_return_if_fail (synth != NULL);
3629
3630   fluid_atomic_int_set (&synth->with_reverb, on != 0);
3631   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled,
3632                            on != 0, 0.0f);
3633 }
3634
3635 /**
3636  * Activate a reverb preset.
3637  * @param synth FluidSynth instance
3638  * @param num Reverb preset number
3639  * @return FLUID_OK on success, FLUID_FAILED otherwise
3640  *
3641  * NOTE: Currently private to libfluidsynth.
3642  */
3643 int
3644 fluid_synth_set_reverb_preset(fluid_synth_t* synth, int num)
3645 {
3646   int i = 0;
3647   while (revmodel_preset[i].name != NULL) {
3648     if (i == num) {
3649       fluid_synth_set_reverb (synth, revmodel_preset[i].roomsize,
3650                               revmodel_preset[i].damp, revmodel_preset[i].width,
3651                               revmodel_preset[i].level);
3652       return FLUID_OK;
3653     }
3654     i++;
3655   }
3656   return FLUID_FAILED;
3657 }
3658
3659 /**
3660  * Set reverb parameters.
3661  * @param synth FluidSynth instance
3662  * @param roomsize Reverb room size value (0.0-1.2)
3663  * @param damping Reverb damping value (0.0-1.0)
3664  * @param width Reverb width value (0.0-100.0)
3665  * @param level Reverb level value (0.0-1.0)
3666  *
3667  * NOTE: Not realtime safe and therefore should not be called from synthesis
3668  * context at the risk of stalling audio output.
3669  */
3670 void
3671 fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, double damping,
3672                        double width, double level)
3673 {
3674   fluid_synth_set_reverb_full (synth, FLUID_REVMODEL_SET_ALL,
3675                                roomsize, damping, width, level);
3676 }
3677
3678 /**
3679  * Set one or more reverb parameters.
3680  * @param synth FluidSynth instance
3681  * @param set Flags indicating which parameters should be set (#fluid_revmodel_set_t)
3682  * @param roomsize Reverb room size value (0.0-1.2)
3683  * @param damping Reverb damping value (0.0-1.0)
3684  * @param width Reverb width value (0.0-100.0)
3685  * @param level Reverb level value (0.0-1.0)
3686  * @return FLUID_OK on success, FLUID_FAILED otherwise
3687  *
3688  * NOTE: Not realtime safe and therefore should not be called from synthesis
3689  * context at the risk of stalling audio output.
3690  */
3691 int
3692 fluid_synth_set_reverb_full(fluid_synth_t* synth, int set, double roomsize,
3693                             double damping, double width, double level)
3694 {
3695   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
3696
3697   if (!(set & FLUID_REVMODEL_SET_ALL))
3698     set = FLUID_REVMODEL_SET_ALL; 
3699
3700   /* Synth shadow values are set here so that they will be returned if querried */
3701
3702   fluid_synth_api_enter(synth);
3703
3704   if (set & FLUID_REVMODEL_SET_ROOMSIZE)
3705     fluid_atomic_float_set (&synth->reverb_roomsize, roomsize);
3706
3707   if (set & FLUID_REVMODEL_SET_DAMPING)
3708     fluid_atomic_float_set (&synth->reverb_damping, damping);
3709
3710   if (set & FLUID_REVMODEL_SET_WIDTH)
3711     fluid_atomic_float_set (&synth->reverb_width, width);
3712
3713   if (set & FLUID_REVMODEL_SET_LEVEL)
3714     fluid_atomic_float_set (&synth->reverb_level, level);
3715
3716   fluid_rvoice_eventhandler_push5(synth->eventhandler, 
3717                                   fluid_rvoice_mixer_set_reverb_params, 
3718                                   synth->eventhandler->mixer, set, 
3719                                   roomsize, damping, width, level, 0.0f);
3720   
3721   FLUID_API_RETURN(FLUID_OK);
3722 }
3723
3724 /**
3725  * Get reverb room size.
3726  * @param synth FluidSynth instance
3727  * @return Reverb room size (0.0-1.2)
3728  */
3729 double
3730 fluid_synth_get_reverb_roomsize(fluid_synth_t* synth)
3731 {
3732   double result;
3733   fluid_return_val_if_fail (synth != NULL, 0.0);
3734   fluid_synth_api_enter(synth);
3735   result = fluid_atomic_float_get (&synth->reverb_roomsize);
3736   FLUID_API_RETURN(result);
3737 }
3738
3739 /**
3740  * Get reverb damping.
3741  * @param synth FluidSynth instance
3742  * @return Reverb damping value (0.0-1.0)
3743  */
3744 double
3745 fluid_synth_get_reverb_damp(fluid_synth_t* synth)
3746 {
3747   double result;
3748   fluid_return_val_if_fail (synth != NULL, 0.0);
3749   fluid_synth_api_enter(synth);
3750
3751   result = fluid_atomic_float_get (&synth->reverb_damping);
3752   FLUID_API_RETURN(result);
3753 }
3754
3755 /**
3756  * Get reverb level.
3757  * @param synth FluidSynth instance
3758  * @return Reverb level value (0.0-1.0)
3759  */
3760 double
3761 fluid_synth_get_reverb_level(fluid_synth_t* synth)
3762 {
3763   double result;
3764   fluid_return_val_if_fail (synth != NULL, 0.0);
3765   fluid_synth_api_enter(synth);
3766
3767   result = fluid_atomic_float_get (&synth->reverb_level);
3768   FLUID_API_RETURN(result);
3769 }
3770
3771 /**
3772  * Get reverb width.
3773  * @param synth FluidSynth instance
3774  * @return Reverb width value (0.0-100.0)
3775  */
3776 double
3777 fluid_synth_get_reverb_width(fluid_synth_t* synth)
3778 {
3779   double result;
3780   fluid_return_val_if_fail (synth != NULL, 0.0);
3781   fluid_synth_api_enter(synth);
3782
3783   result = fluid_atomic_float_get (&synth->reverb_width);
3784   FLUID_API_RETURN(result);
3785 }
3786
3787 /**
3788  * Enable or disable chorus effect.
3789  * @param synth FluidSynth instance
3790  * @param on TRUE to enable chorus, FALSE to disable
3791  */
3792 void 
3793 fluid_synth_set_chorus_on(fluid_synth_t* synth, int on)
3794 {
3795   fluid_return_if_fail (synth != NULL);
3796   fluid_synth_api_enter(synth);
3797
3798   fluid_atomic_int_set (&synth->with_chorus, on != 0);
3799   fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled,
3800                            on != 0, 0.0f);
3801   fluid_synth_api_exit(synth);
3802 }
3803
3804 /**
3805  * Set chorus parameters.
3806  * @param synth FluidSynth instance
3807  * @param nr Chorus voice count (0-99, CPU time consumption proportional to
3808  *   this value)
3809  * @param level Chorus level (0.0-10.0)
3810  * @param speed Chorus speed in Hz (0.29-5.0)
3811  * @param depth_ms Chorus depth (max value depends on synth sample rate,
3812  *   0.0-21.0 is safe for sample rate values up to 96KHz)
3813  * @param type Chorus waveform type (#fluid_chorus_mod)
3814  */
3815 void
3816 fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level,
3817                        double speed, double depth_ms, int type)
3818 {
3819   fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_ALL, nr, level, speed,
3820                                depth_ms, type);
3821 }
3822
3823 /**
3824  * Set one or more chorus parameters.
3825  * @param synth FluidSynth instance
3826  * @param set Flags indicating which chorus parameters to set (#fluid_chorus_set_t)
3827  * @param nr Chorus voice count (0-99, CPU time consumption proportional to
3828  *   this value)
3829  * @param level Chorus level (0.0-10.0)
3830  * @param speed Chorus speed in Hz (0.29-5.0)
3831  * @param depth_ms Chorus depth (max value depends on synth sample rate,
3832  *   0.0-21.0 is safe for sample rate values up to 96KHz)
3833  * @param type Chorus waveform type (#fluid_chorus_mod)
3834  */
3835 int
3836 fluid_synth_set_chorus_full(fluid_synth_t* synth, int set, int nr, double level,
3837                             double speed, double depth_ms, int type)
3838 {
3839   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
3840
3841   if (!(set & FLUID_CHORUS_SET_ALL))
3842     set = FLUID_CHORUS_SET_ALL;
3843
3844   /* Synth shadow values are set here so that they will be returned if queried */
3845   fluid_synth_api_enter(synth);
3846
3847   if (set & FLUID_CHORUS_SET_NR)
3848     fluid_atomic_int_set (&synth->chorus_nr, nr);
3849
3850   if (set & FLUID_CHORUS_SET_LEVEL)
3851     fluid_atomic_float_set (&synth->chorus_level, level);
3852
3853   if (set & FLUID_CHORUS_SET_SPEED)
3854     fluid_atomic_float_set (&synth->chorus_speed, speed);
3855
3856   if (set & FLUID_CHORUS_SET_DEPTH)
3857     fluid_atomic_float_set (&synth->chorus_depth, depth_ms);
3858
3859   if (set & FLUID_CHORUS_SET_TYPE)
3860     fluid_atomic_int_set (&synth->chorus_type, type);
3861   
3862   fluid_rvoice_eventhandler_push5(synth->eventhandler, 
3863                                   fluid_rvoice_mixer_set_chorus_params,
3864                                   synth->eventhandler->mixer, set,
3865                                   nr, level, speed, depth_ms, type);
3866
3867   FLUID_API_RETURN(FLUID_OK);
3868 }
3869
3870 /**
3871  * Get chorus voice number (delay line count) value.
3872  * @param synth FluidSynth instance
3873  * @return Chorus voice count (0-99)
3874  */
3875 int
3876 fluid_synth_get_chorus_nr(fluid_synth_t* synth)
3877 {
3878   double result;
3879   fluid_return_val_if_fail (synth != NULL, 0.0);
3880   fluid_synth_api_enter(synth);
3881
3882   result = fluid_atomic_int_get (&synth->chorus_nr);
3883   FLUID_API_RETURN(result);
3884 }
3885
3886 /**
3887  * Get chorus level.
3888  * @param synth FluidSynth instance
3889  * @return Chorus level value (0.0-10.0)
3890  */
3891 double
3892 fluid_synth_get_chorus_level(fluid_synth_t* synth)
3893 {
3894   double result;
3895   fluid_return_val_if_fail (synth != NULL, 0.0);
3896   fluid_synth_api_enter(synth);
3897
3898   result = fluid_atomic_float_get (&synth->chorus_level);
3899   FLUID_API_RETURN(result);
3900 }
3901
3902 /**
3903  * Get chorus speed in Hz.
3904  * @param synth FluidSynth instance
3905  * @return Chorus speed in Hz (0.29-5.0)
3906  */
3907 double
3908 fluid_synth_get_chorus_speed_Hz(fluid_synth_t* synth)
3909 {
3910   double result;
3911   fluid_return_val_if_fail (synth != NULL, 0.0);
3912   fluid_synth_api_enter(synth);
3913
3914   result = fluid_atomic_float_get (&synth->chorus_speed);
3915   FLUID_API_RETURN(result);
3916 }
3917
3918 /**
3919  * Get chorus depth.
3920  * @param synth FluidSynth instance
3921  * @return Chorus depth
3922  */
3923 double
3924 fluid_synth_get_chorus_depth_ms(fluid_synth_t* synth)
3925 {
3926   double result;
3927   fluid_return_val_if_fail (synth != NULL, 0.0);
3928   fluid_synth_api_enter(synth);
3929
3930   result = fluid_atomic_float_get (&synth->chorus_depth);
3931   FLUID_API_RETURN(result);
3932 }
3933
3934 /**
3935  * Get chorus waveform type.
3936  * @param synth FluidSynth instance
3937  * @return Chorus waveform type (#fluid_chorus_mod)
3938  */
3939 int
3940 fluid_synth_get_chorus_type(fluid_synth_t* synth)
3941 {
3942   double result;
3943   fluid_return_val_if_fail (synth != NULL, 0.0);
3944   fluid_synth_api_enter(synth);
3945
3946   result = fluid_atomic_int_get (&synth->chorus_type);
3947   FLUID_API_RETURN(result);
3948 }
3949
3950 /*
3951  * If the same note is hit twice on the same channel, then the older
3952  * voice process is advanced to the release stage.  Using a mechanical
3953  * MIDI controller, the only way this can happen is when the sustain
3954  * pedal is held.  In this case the behaviour implemented here is
3955  * natural for many instruments.  Note: One noteon event can trigger
3956  * several voice processes, for example a stereo sample.  Don't
3957  * release those...
3958  */
3959 static void
3960 fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, int chan,
3961                                              int key)
3962 {
3963   int i;
3964   fluid_voice_t* voice;
3965
3966   synth->storeid = synth->noteid++;
3967
3968   for (i = 0; i < synth->polyphony; i++) {
3969     voice = synth->voice[i];
3970     if (_PLAYING(voice)
3971         && (voice->chan == chan)
3972         && (voice->key == key)
3973         && (fluid_voice_get_id(voice) != synth->noteid)) {
3974       /* Id of voices that was sustained by sostenuto */
3975       if(_HELD_BY_SOSTENUTO(voice))
3976         synth->storeid = voice->id;
3977       /* Force the voice into release stage (pedaling is ignored) */
3978       fluid_voice_release(voice);
3979     }
3980   }
3981 }
3982
3983 /**
3984  * Set synthesis interpolation method on one or all MIDI channels.
3985  * @param synth FluidSynth instance
3986  * @param chan MIDI channel to set interpolation method on or -1 for all channels
3987  * @param interp_method Interpolation method (#fluid_interp)
3988  * @return FLUID_OK on success, FLUID_FAILED otherwise
3989  */
3990 int
3991 fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_method)
3992 {
3993   int i;
3994   
3995   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); 
3996   fluid_synth_api_enter(synth); 
3997   if (chan < -1 || chan >= synth->midi_channels) 
3998     FLUID_API_RETURN(FLUID_FAILED);
3999
4000   if (synth->channel[0] == NULL) {
4001     FLUID_LOG (FLUID_ERR, "Channels don't exist (yet)!");
4002     FLUID_API_RETURN(FLUID_FAILED);
4003   }
4004
4005   for (i = 0; i < synth->midi_channels; i++) {
4006     if (chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan)
4007       fluid_channel_set_interp_method(synth->channel[i], interp_method);
4008   }
4009
4010   FLUID_API_RETURN(FLUID_OK);
4011 };
4012
4013 /**
4014  * Get the total count of MIDI channels.
4015  * @param synth FluidSynth instance
4016  * @return Count of MIDI channels
4017  */
4018 int
4019 fluid_synth_count_midi_channels(fluid_synth_t* synth)
4020 {
4021   int result;
4022   fluid_return_val_if_fail (synth != NULL, 0);
4023   fluid_synth_api_enter(synth);
4024
4025   result = synth->midi_channels;
4026   FLUID_API_RETURN(result);
4027 }
4028
4029 /**
4030  * Get the total count of audio channels.
4031  * @param synth FluidSynth instance
4032  * @return Count of audio channel stereo pairs (1 = 2 channels, 2 = 4, etc)
4033  */
4034 int
4035 fluid_synth_count_audio_channels(fluid_synth_t* synth)
4036 {
4037   int result;
4038   fluid_return_val_if_fail (synth != NULL, 0);
4039   fluid_synth_api_enter(synth);
4040
4041   result = synth->audio_channels;
4042   FLUID_API_RETURN(result);
4043 }
4044
4045 /**
4046  * Get the total number of allocated audio channels.  Usually identical to the
4047  * number of audio channels.  Can be employed by LADSPA effects subsystem.
4048  *
4049  * @param synth FluidSynth instance
4050  * @return Count of audio group stereo pairs (1 = 2 channels, 2 = 4, etc)
4051  */
4052 int
4053 fluid_synth_count_audio_groups(fluid_synth_t* synth)
4054 {
4055   int result;
4056   fluid_return_val_if_fail (synth != NULL, 0);
4057   fluid_synth_api_enter(synth);
4058
4059   result = synth->audio_groups;
4060   FLUID_API_RETURN(result);
4061 }
4062
4063 /**
4064  * Get the total number of allocated effects channels.
4065  * @param synth FluidSynth instance
4066  * @return Count of allocated effects channels
4067  */
4068 int
4069 fluid_synth_count_effects_channels(fluid_synth_t* synth)
4070 {
4071   int result;
4072   fluid_return_val_if_fail (synth != NULL, 0);
4073   fluid_synth_api_enter(synth);
4074
4075   result = synth->effects_channels;
4076   FLUID_API_RETURN(result);
4077 }
4078
4079 /**
4080  * Get the synth CPU load value.
4081  * @param synth FluidSynth instance
4082  * @return Estimated CPU load value in percent (0-100)
4083  */
4084 double
4085 fluid_synth_get_cpu_load(fluid_synth_t* synth)
4086 {
4087   fluid_return_val_if_fail (synth != NULL, 0);
4088   return fluid_atomic_float_get (&synth->cpu_load);
4089 }
4090
4091 /* Get tuning for a given bank:program */
4092 static fluid_tuning_t *
4093 fluid_synth_get_tuning(fluid_synth_t* synth, int bank, int prog)
4094 {
4095
4096   if ((synth->tuning == NULL) ||
4097       (synth->tuning[bank] == NULL) ||
4098       (synth->tuning[bank][prog] == NULL))
4099     return NULL;
4100
4101   return synth->tuning[bank][prog];
4102 }
4103
4104 /* Replace tuning on a given bank:program (need not already exist).
4105  * Synth mutex should already be locked by caller. */
4106 static int
4107 fluid_synth_replace_tuning_LOCK (fluid_synth_t* synth, fluid_tuning_t *tuning,
4108                                  int bank, int prog, int apply)
4109 {
4110   fluid_tuning_t *old_tuning;
4111 //  fluid_event_queue_t *queue;
4112 //  fluid_event_queue_elem_t *event;
4113
4114   if (synth->tuning == NULL) {
4115     synth->tuning = FLUID_ARRAY(fluid_tuning_t**, 128);
4116     if (synth->tuning == NULL) {
4117       FLUID_LOG(FLUID_PANIC, "Out of memory");
4118       return FLUID_FAILED;
4119     }
4120     FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t**));
4121   }
4122
4123   if (synth->tuning[bank] == NULL) {
4124     synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t*, 128);
4125     if (synth->tuning[bank] == NULL) {
4126       FLUID_LOG(FLUID_PANIC, "Out of memory");
4127       return FLUID_FAILED;
4128     }
4129     FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t*));
4130   }
4131
4132   old_tuning = synth->tuning[bank][prog];
4133   synth->tuning[bank][prog] = tuning;
4134
4135   if (old_tuning) {
4136     if (!fluid_tuning_unref (old_tuning, 1))     /* -- unref old tuning */
4137     { /* Replace old tuning if present */
4138       fluid_synth_replace_tuning_LOCAL (synth, old_tuning, tuning, apply, FALSE);
4139     }
4140   }
4141
4142   return FLUID_OK;
4143 }
4144
4145 /* Replace a tuning with a new one in all MIDI channels.  new_tuning can be
4146  * NULL, in which case channels are reset to default equal tempered scale. */
4147 static void
4148 fluid_synth_replace_tuning_LOCAL (fluid_synth_t *synth, fluid_tuning_t *old_tuning,
4149                                   fluid_tuning_t *new_tuning, int apply, int unref_new)
4150 {
4151 //  fluid_event_queue_elem_t *event;
4152   fluid_channel_t *channel;
4153   int old_tuning_unref = 0;
4154   int i;
4155
4156   for (i = 0; i < synth->midi_channels; i++)
4157   {
4158     channel = synth->channel[i];
4159
4160     if (fluid_channel_get_tuning (channel) == old_tuning)
4161     {
4162       old_tuning_unref++;
4163       if (new_tuning) fluid_tuning_ref (new_tuning);    /* ++ ref new tuning for channel */
4164       fluid_channel_set_tuning (channel, new_tuning);
4165
4166       if (apply) fluid_synth_update_voice_tuning_LOCAL (synth, channel);
4167     }
4168   }
4169
4170   /* Send unref old tuning event if any unrefs */
4171   if (old_tuning && old_tuning_unref)
4172     fluid_tuning_unref (old_tuning, old_tuning_unref);
4173   if (!unref_new || !new_tuning) return;
4174
4175   fluid_tuning_unref (new_tuning, 1);
4176 }
4177
4178 /* Update voice tunings in realtime */
4179 static void
4180 fluid_synth_update_voice_tuning_LOCAL (fluid_synth_t *synth, fluid_channel_t *channel)
4181 {
4182   fluid_voice_t *voice;
4183   int i;
4184
4185   for (i = 0; i < synth->polyphony; i++)
4186   {
4187     voice = synth->voice[i];
4188
4189     if (_ON (voice) && (voice->channel == channel))
4190     {
4191       fluid_voice_calculate_gen_pitch (voice);
4192       fluid_voice_update_param (voice, GEN_PITCH);
4193     }
4194   }
4195 }
4196
4197 /**
4198  * Set the tuning of the entire MIDI note scale.
4199  * @param synth FluidSynth instance
4200  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4201  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4202  * @param name Label name for this tuning
4203  * @param pitch Array of pitch values (length of 128, each value is number of
4204  *   cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
4205  *   Pass NULL to create a well-tempered (normal) scale.
4206  * @return FLUID_OK on success, FLUID_FAILED otherwise
4207  *
4208  * NOTE: Tuning is not applied in realtime to existing notes of the replaced
4209  * tuning (if any), use fluid_synth_activate_key_tuning() instead to specify
4210  * this behavior.
4211  */
4212 int
4213 fluid_synth_create_key_tuning(fluid_synth_t* synth, int bank, int prog,
4214                               const char* name, const double* pitch)
4215 {
4216   return fluid_synth_activate_key_tuning (synth, bank, prog, name, pitch, FALSE);
4217 }
4218
4219 /**
4220  * Set the tuning of the entire MIDI note scale.
4221  * @param synth FluidSynth instance
4222  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4223  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4224  * @param name Label name for this tuning
4225  * @param pitch Array of pitch values (length of 128, each value is number of
4226  *   cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
4227  *   Pass NULL to create a well-tempered (normal) scale.
4228  * @param apply TRUE to apply new tuning in realtime to existing notes which
4229  *   are using the replaced tuning (if any), FALSE otherwise
4230  * @return FLUID_OK on success, FLUID_FAILED otherwise
4231  * @since 1.1.0
4232  */
4233 int
4234 fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog,
4235                                 const char* name, const double* pitch, int apply)
4236 {
4237   fluid_tuning_t* tuning;
4238   int retval = FLUID_OK;
4239
4240   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4241   fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED);
4242   fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED);
4243   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4244
4245   fluid_synth_api_enter(synth);
4246
4247   tuning = new_fluid_tuning (name, bank, prog);
4248
4249   if (tuning)
4250   {
4251     if (pitch) fluid_tuning_set_all (tuning, pitch);
4252     retval = fluid_synth_replace_tuning_LOCK (synth, tuning, bank, prog, apply);
4253     if (retval == FLUID_FAILED) fluid_tuning_unref (tuning, 1);
4254   }
4255   else retval = FLUID_FAILED;
4256   FLUID_API_RETURN(retval);
4257 }
4258
4259 /**
4260  * Apply an octave tuning to every octave in the MIDI note scale.
4261  * @param synth FluidSynth instance
4262  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4263  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4264  * @param name Label name for this tuning
4265  * @param pitch Array of pitch values (length of 12 for each note of an octave
4266  *   starting at note C, values are number of offset cents to add to the normal
4267  *   tuning amount)
4268  * @return FLUID_OK on success, FLUID_FAILED otherwise
4269  *
4270  * NOTE: Tuning is not applied in realtime to existing notes of the replaced
4271  * tuning (if any), use fluid_synth_activate_octave_tuning() instead to specify
4272  * this behavior.
4273  */
4274 int
4275 fluid_synth_create_octave_tuning(fluid_synth_t* synth, int bank, int prog,
4276                                  const char* name, const double* pitch)
4277 {
4278   return fluid_synth_activate_octave_tuning (synth, bank, prog, name, pitch, FALSE);
4279 }
4280
4281 /**
4282  * Activate an octave tuning on every octave in the MIDI note scale.
4283  * @param synth FluidSynth instance
4284  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4285  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4286  * @param name Label name for this tuning
4287  * @param pitch Array of pitch values (length of 12 for each note of an octave
4288  *   starting at note C, values are number of offset cents to add to the normal
4289  *   tuning amount)
4290  * @param apply TRUE to apply new tuning in realtime to existing notes which
4291  *   are using the replaced tuning (if any), FALSE otherwise
4292  * @return FLUID_OK on success, FLUID_FAILED otherwise
4293  * @since 1.1.0
4294  */
4295 int
4296 fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog,
4297                                    const char* name, const double* pitch, int apply)
4298 {
4299   fluid_tuning_t* tuning;
4300   int retval = FLUID_OK;
4301
4302   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4303   fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED);
4304   fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED);
4305   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4306   fluid_return_val_if_fail (pitch != NULL, FLUID_FAILED);
4307
4308   fluid_synth_api_enter(synth);
4309   tuning = new_fluid_tuning (name, bank, prog);
4310
4311   if (tuning)
4312   {
4313     fluid_tuning_set_octave (tuning, pitch);
4314     retval = fluid_synth_replace_tuning_LOCK (synth, tuning, bank, prog, apply);
4315     if (retval == FLUID_FAILED) fluid_tuning_unref (tuning, 1);
4316   }
4317   else retval = FLUID_FAILED;
4318
4319   FLUID_API_RETURN(retval);
4320 }
4321
4322 /**
4323  * Set tuning values for one or more MIDI notes for an existing tuning.
4324  * @param synth FluidSynth instance
4325  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4326  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4327  * @param len Number of MIDI notes to assign
4328  * @param key Array of MIDI key numbers (length of 'len', values 0-127)
4329  * @param pitch Array of pitch values (length of 'len', values are number of
4330  *   cents from MIDI note 0)
4331  * @param apply TRUE to apply tuning change in realtime to existing notes using
4332  *   the specified tuning, FALSE otherwise
4333  * @return FLUID_OK on success, FLUID_FAILED otherwise
4334  *
4335  * NOTE: Prior to version 1.1.0 it was an error to specify a tuning that didn't
4336  * already exist.  Starting with 1.1.0, the default equal tempered scale will be
4337  * used as a basis, if no tuning exists for the given bank and prog.
4338  */
4339 int
4340 fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
4341                        int len, const int *key, const double* pitch, int apply)
4342 {
4343   fluid_tuning_t* old_tuning, *new_tuning;
4344   int retval = FLUID_OK;
4345   int i;
4346
4347   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4348   fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED);
4349   fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED);
4350   fluid_return_val_if_fail (len > 0, FLUID_FAILED);
4351   fluid_return_val_if_fail (key != NULL, FLUID_FAILED);
4352   fluid_return_val_if_fail (pitch != NULL, FLUID_FAILED);
4353   
4354   fluid_synth_api_enter(synth);
4355
4356   old_tuning = fluid_synth_get_tuning (synth, bank, prog);
4357
4358   if (old_tuning)
4359     new_tuning = fluid_tuning_duplicate (old_tuning);
4360   else new_tuning = new_fluid_tuning ("Unnamed", bank, prog);
4361
4362   if (new_tuning)
4363   {
4364     for (i = 0; i < len; i++)
4365       fluid_tuning_set_pitch (new_tuning, key[i], pitch[i]);
4366
4367     retval = fluid_synth_replace_tuning_LOCK (synth, new_tuning, bank, prog, apply);
4368     if (retval == FLUID_FAILED) fluid_tuning_unref (new_tuning, 1);
4369   }
4370   else retval = FLUID_FAILED;
4371
4372   FLUID_API_RETURN(retval);
4373 }
4374
4375 /**
4376  * Select a tuning scale on a MIDI channel.
4377  * @param synth FluidSynth instance
4378  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4379  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4380  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4381  * @return FLUID_OK on success, FLUID_FAILED otherwise
4382  *
4383  * NOTE: This function does NOT activate tuning in realtime, use
4384  * fluid_synth_activate_tuning() instead to specify whether tuning change
4385  * should cause existing notes to update.
4386  *
4387  * NOTE: Prior to version 1.1.0 it was an error to select a tuning that didn't
4388  * already exist.  Starting with 1.1.0, a default equal tempered scale will be
4389  * created, if no tuning exists for the given bank and prog.
4390  */
4391 int
4392 fluid_synth_select_tuning(fluid_synth_t* synth, int chan, int bank, int prog)
4393 {
4394   return fluid_synth_activate_tuning (synth, chan, bank, prog, FALSE);
4395 }
4396
4397 /**
4398  * Activate a tuning scale on a MIDI channel.
4399  * @param synth FluidSynth instance
4400  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4401  * @param bank Tuning bank number (0-127), not related to MIDI instrument bank
4402  * @param prog Tuning preset number (0-127), not related to MIDI instrument program
4403  * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
4404  * @return FLUID_OK on success, FLUID_FAILED otherwise
4405  * @since 1.1.0
4406  *
4407  * NOTE: A default equal tempered scale will be created, if no tuning exists
4408  * on the given bank and prog.
4409  */
4410 int
4411 fluid_synth_activate_tuning(fluid_synth_t* synth, int chan, int bank, int prog,
4412                             int apply)
4413 {
4414   //fluid_event_queue_elem_t *event;
4415   //fluid_event_queue_t *queue;
4416   fluid_tuning_t* tuning;
4417   int retval = FLUID_OK;
4418
4419   //fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4420   //fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
4421   fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED);
4422   fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED);
4423
4424   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
4425
4426   tuning = fluid_synth_get_tuning (synth, bank, prog);
4427
4428  /* If no tuning exists, create a new default tuning.  We do this, so that
4429   * it can be replaced later, if any changes are made. */
4430   if (!tuning)
4431   {
4432     tuning = new_fluid_tuning ("Unnamed", bank, prog);
4433     if (tuning) fluid_synth_replace_tuning_LOCK (synth, tuning, bank, prog, FALSE);
4434   }
4435
4436   if (tuning) fluid_tuning_ref (tuning);  /* ++ ref for outside of lock */
4437
4438   if (!tuning) 
4439     FLUID_API_RETURN(FLUID_FAILED);
4440
4441   fluid_tuning_ref (tuning);    /* ++ ref new tuning for following function */
4442   retval = fluid_synth_set_tuning_LOCAL (synth, chan, tuning, apply);
4443
4444   fluid_tuning_unref (tuning, 1);   /* -- unref for outside of lock */
4445
4446   FLUID_API_RETURN(retval);
4447 }
4448
4449 /* Local synthesis thread set tuning function (takes over tuning reference) */
4450 static int
4451 fluid_synth_set_tuning_LOCAL (fluid_synth_t *synth, int chan,
4452                               fluid_tuning_t *tuning, int apply)
4453 {
4454   fluid_tuning_t *old_tuning;
4455   fluid_channel_t *channel;
4456
4457   channel = synth->channel[chan];
4458
4459   old_tuning = fluid_channel_get_tuning (channel);
4460   fluid_channel_set_tuning (channel, tuning);   /* !! Takes over callers reference */
4461
4462   if (apply) fluid_synth_update_voice_tuning_LOCAL (synth, channel);
4463
4464   /* Send unref old tuning event */
4465   if (old_tuning)
4466   {
4467     fluid_tuning_unref (old_tuning, 1);
4468   }
4469
4470
4471   return FLUID_OK;
4472 }
4473
4474 /**
4475  * Clear tuning scale on a MIDI channel (set it to the default well-tempered scale).
4476  * @param synth FluidSynth instance
4477  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4478  * @return FLUID_OK on success, FLUID_FAILED otherwise
4479  *
4480  * NOTE: This function does NOT activate tuning change in realtime, use
4481  * fluid_synth_deactivate_tuning() instead to specify whether tuning change
4482  * should cause existing notes to update.
4483  */
4484 int
4485 fluid_synth_reset_tuning(fluid_synth_t* synth, int chan)
4486 {
4487   return fluid_synth_deactivate_tuning (synth, chan, FALSE);
4488 }
4489
4490 /**
4491  * Clear tuning scale on a MIDI channel (use default equal tempered scale).
4492  * @param synth FluidSynth instance
4493  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4494  * @param apply TRUE to apply tuning change to active notes, FALSE otherwise
4495  * @return FLUID_OK on success, FLUID_FAILED otherwise
4496  * @since 1.1.0
4497  */
4498 int
4499 fluid_synth_deactivate_tuning(fluid_synth_t* synth, int chan, int apply)
4500 {
4501   int retval = FLUID_OK;
4502
4503   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
4504
4505   retval = fluid_synth_set_tuning_LOCAL (synth, chan, NULL, apply);
4506
4507   FLUID_API_RETURN(retval);
4508 }
4509
4510 /**
4511  * Start tuning iteration.
4512  * @param synth FluidSynth instance
4513  */
4514 void
4515 fluid_synth_tuning_iteration_start(fluid_synth_t* synth)
4516 {
4517   fluid_return_if_fail (synth != NULL);
4518   fluid_synth_api_enter(synth);
4519   fluid_private_set (synth->tuning_iter, FLUID_INT_TO_POINTER (0));
4520   fluid_synth_api_exit(synth);
4521 }
4522
4523 /**
4524  * Advance to next tuning.
4525  * @param synth FluidSynth instance
4526  * @param bank Location to store MIDI bank number of next tuning scale
4527  * @param prog Location to store MIDI program number of next tuning scale
4528  * @return 1 if tuning iteration advanced, 0 if no more tunings
4529  */
4530 int
4531 fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog)
4532 {
4533   void *pval;
4534   int b = 0, p = 0;
4535
4536   fluid_return_val_if_fail (synth != NULL, 0);
4537   fluid_return_val_if_fail (bank != NULL, 0);
4538   fluid_return_val_if_fail (prog != NULL, 0);
4539   fluid_synth_api_enter(synth);
4540
4541   /* Current tuning iteration stored as: bank << 8 | program */
4542   pval = fluid_private_get (synth->tuning_iter);
4543   p = FLUID_POINTER_TO_INT (pval);
4544   b = (p >> 8) & 0xFF;
4545   p &= 0xFF;
4546
4547   if (!synth->tuning)
4548   {
4549     FLUID_API_RETURN(0);
4550   }
4551
4552   for (; b < 128; b++, p = 0)
4553   {
4554     if (synth->tuning[b] == NULL) continue;
4555
4556     for (; p < 128; p++)
4557     {
4558       if (synth->tuning[b][p] == NULL) continue;
4559
4560       *bank = b;
4561       *prog = p;
4562
4563       if (p < 127) fluid_private_set (synth->tuning_iter,
4564                                       FLUID_INT_TO_POINTER (b << 8 | (p + 1)));
4565       else fluid_private_set (synth->tuning_iter,
4566                               FLUID_INT_TO_POINTER ((b + 1) << 8));
4567
4568       FLUID_API_RETURN(1);
4569     }
4570   }
4571
4572   FLUID_API_RETURN(0);
4573 }
4574
4575 /**
4576  * Get the entire note tuning for a given MIDI bank and program.
4577  * @param synth FluidSynth instance
4578  * @param bank MIDI bank number of tuning
4579  * @param prog MIDI program number of tuning
4580  * @param name Location to store tuning name or NULL to ignore
4581  * @param len Maximum number of chars to store to 'name' (including NULL byte)
4582  * @param pitch Array to store tuning scale to or NULL to ignore (len of 128)
4583  * @return FLUID_OK if matching tuning was found, FLUID_FAILED otherwise
4584  */
4585 int
4586 fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog,
4587                         char* name, int len, double* pitch)
4588 {
4589   fluid_tuning_t* tuning;
4590
4591   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4592   fluid_synth_api_enter(synth);
4593   
4594   tuning = fluid_synth_get_tuning (synth, bank, prog);
4595
4596   if (tuning)
4597   {
4598     if (name)
4599     {
4600       snprintf (name, len - 1, "%s", fluid_tuning_get_name (tuning));
4601       name[len - 1] = 0;  /* make sure the string is null terminated */
4602     }
4603
4604     if (pitch)
4605       FLUID_MEMCPY (pitch, fluid_tuning_get_all (tuning), 128 * sizeof (double));
4606   }
4607
4608   FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED);
4609 }
4610
4611 /**
4612  * Get settings assigned to a synth.
4613  * @param synth FluidSynth instance
4614  * @return FluidSynth settings which are assigned to the synth
4615  */
4616 fluid_settings_t *
4617 fluid_synth_get_settings(fluid_synth_t* synth)
4618 {
4619   fluid_return_val_if_fail (synth != NULL, NULL);
4620
4621   return synth->settings;
4622 }
4623
4624 /**
4625  * Convenience function to set a string setting of a synth.
4626  * @param synth FluidSynth instance
4627  * @param name Name of setting parameter
4628  * @param str Value to assign to the setting
4629  * @return FLUID_OK on success, FLUID_FAILED otherwise
4630  */
4631 int
4632 fluid_synth_setstr(fluid_synth_t* synth, const char* name, const char* str)
4633 {
4634   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4635   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4636
4637   return fluid_settings_setstr(synth->settings, name, str);
4638 }
4639
4640 /**
4641  * Convenience function to duplicate a string setting of a synth.
4642  * @param synth FluidSynth instance
4643  * @param name Name of setting parameter
4644  * @param str Location to store a pointer to the newly allocated string value
4645  * @return FLUID_OK on success, FLUID_FAILED otherwise
4646  *
4647  * The returned string is owned by the caller and should be freed with free()
4648  * when finished with it.
4649  */
4650 int
4651 fluid_synth_dupstr(fluid_synth_t* synth, const char* name, char** str)
4652 {
4653   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4654   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4655   fluid_return_val_if_fail (str != NULL, FLUID_FAILED);
4656
4657   return fluid_settings_dupstr(synth->settings, name, str);
4658 }
4659
4660 /**
4661  * Convenience function to set a floating point setting of a synth.
4662  * @param synth FluidSynth instance
4663  * @param name Name of setting parameter
4664  * @param val Value to assign to the setting
4665  * @return FLUID_OK on success, FLUID_FAILED otherwise
4666  */
4667 int
4668 fluid_synth_setnum(fluid_synth_t* synth, const char* name, double val)
4669 {
4670   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4671   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4672
4673   return fluid_settings_setnum(synth->settings, name, val);
4674 }
4675
4676 /**
4677  * Convenience function to get a floating point setting of a synth.
4678  * @param synth FluidSynth instance
4679  * @param name Name of setting parameter
4680  * @param val Location to store the current value of the setting
4681  * @return FLUID_OK on success, FLUID_FAILED otherwise
4682  */
4683 int
4684 fluid_synth_getnum(fluid_synth_t* synth, const char* name, double* val)
4685 {
4686   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4687   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4688
4689   return fluid_settings_getnum(synth->settings, name, val);
4690 }
4691
4692 /**
4693  * Convenience function to set an integer setting of a synth.
4694  * @param synth FluidSynth instance
4695  * @param name Name of setting parameter
4696  * @param val Value to assign to the setting
4697  * @return FLUID_OK on success, FLUID_FAILED otherwise
4698  */
4699 int
4700 fluid_synth_setint(fluid_synth_t* synth, const char* name, int val)
4701 {
4702   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4703   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4704
4705   return fluid_settings_setint(synth->settings, name, val);
4706 }
4707
4708 /**
4709  * Convenience function to get an integer setting of a synth.
4710  * @param synth FluidSynth instance
4711  * @param name Name of setting parameter
4712  * @param val Location to store the current value of the setting
4713  * @return FLUID_OK on success, FLUID_FAILED otherwise
4714  */
4715 int
4716 fluid_synth_getint(fluid_synth_t* synth, const char* name, int* val)
4717 {
4718   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4719   fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
4720
4721   return fluid_settings_getint(synth->settings, name, val);
4722 }
4723
4724 /**
4725  * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
4726  * @param synth FluidSynth instance
4727  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4728  * @param param SoundFont generator ID (#fluid_gen_type)
4729  * @param value Offset generator value to assign to the MIDI channel
4730  * @return FLUID_OK on success, FLUID_FAILED otherwise
4731  *
4732  * Parameter numbers and ranges are described in the SoundFont 2.01
4733  * specification PDF, paragraph 8.1.3, page 48.  See #fluid_gen_type.
4734  */
4735 int
4736 fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value)
4737 {
4738   fluid_return_val_if_fail (param >= 0 && param < GEN_LAST, FLUID_FAILED);
4739   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
4740
4741   fluid_synth_set_gen_LOCAL (synth, chan, param, value, FALSE);
4742
4743   FLUID_API_RETURN(FLUID_OK);
4744 }
4745
4746 /* Synthesis thread local set gen function */
4747 static void
4748 fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan, int param, float value,
4749                            int absolute)
4750 {
4751   fluid_voice_t* voice;
4752   int i;
4753
4754   fluid_channel_set_gen (synth->channel[chan], param, value, absolute);
4755
4756   for (i = 0; i < synth->polyphony; i++) {
4757     voice = synth->voice[i];
4758
4759     if (voice->chan == chan)
4760       fluid_voice_set_param (voice, param, value, absolute);
4761   }
4762 }
4763
4764 /**
4765  * Set a SoundFont generator (effect) value on a MIDI channel in real-time.
4766  * @param synth FluidSynth instance
4767  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4768  * @param param SoundFont generator ID (#fluid_gen_type)
4769  * @param value Offset or absolute generator value to assign to the MIDI channel
4770  * @param absolute 0 to assign a relative value, non-zero to assign an absolute value
4771  * @param normalized 0 if value is specified in the native units of the generator,
4772  *   non-zero to take the value as a 0.0-1.0 range and apply it to the valid
4773  *   generator effect range (scaled and shifted as necessary).
4774  * @return FLUID_OK on success, FLUID_FAILED otherwise
4775  * @since 1.1.0
4776  *
4777  * This function allows for setting all effect parameters in real time on a
4778  * MIDI channel.  Setting absolute to non-zero will cause the value to override
4779  * any generator values set in the instruments played on the MIDI channel.
4780  * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
4781  * generator parameters and valid ranges.
4782  */
4783 int
4784 fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param,
4785                      float value, int absolute, int normalized)
4786 {
4787   float v;
4788   fluid_return_val_if_fail (param >= 0 && param < GEN_LAST, FLUID_FAILED);
4789   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
4790
4791   v = normalized ? fluid_gen_scale(param, value) : value;
4792
4793   fluid_synth_set_gen_LOCAL (synth, chan, param, v, absolute);
4794
4795   FLUID_API_RETURN(FLUID_OK);
4796 }
4797
4798 /**
4799  * Get generator value assigned to a MIDI channel.
4800  * @param synth FluidSynth instance
4801  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4802  * @param param SoundFont generator ID (#fluid_gen_type)
4803  * @return Current generator value assigned to MIDI channel
4804  */
4805 float
4806 fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param)
4807 {
4808   float result;
4809   fluid_return_val_if_fail (param >= 0 && param < GEN_LAST, FLUID_FAILED);
4810   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
4811
4812   result = fluid_channel_get_gen(synth->channel[chan], param);
4813   FLUID_API_RETURN(result);
4814 }
4815
4816 /**
4817  * Assign a MIDI router to a synth.
4818  * @param synth FluidSynth instance
4819  * @param router MIDI router to assign to the synth
4820  *
4821  * NOTE: This should only be done once and prior to using the synth.
4822  */
4823 void
4824 fluid_synth_set_midi_router(fluid_synth_t* synth, fluid_midi_router_t* router)
4825 {
4826   fluid_return_if_fail (synth != NULL);
4827   fluid_synth_api_enter(synth);
4828
4829   synth->midi_router = router;
4830   fluid_synth_api_exit(synth);
4831 };
4832
4833 /**
4834  * Handle MIDI event from MIDI router, used as a callback function.
4835  * @param data FluidSynth instance
4836  * @param event MIDI event to handle
4837  * @return FLUID_OK on success, FLUID_FAILED otherwise
4838  */
4839 int
4840 fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event)
4841 {
4842   fluid_synth_t* synth = (fluid_synth_t*) data;
4843   int type = fluid_midi_event_get_type(event);
4844   int chan = fluid_midi_event_get_channel(event);
4845
4846   switch(type) {
4847       case NOTE_ON:
4848         return fluid_synth_noteon(synth, chan,
4849                                   fluid_midi_event_get_key(event),
4850                                   fluid_midi_event_get_velocity(event));
4851
4852       case NOTE_OFF:
4853         return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event));
4854
4855       case CONTROL_CHANGE:
4856         return fluid_synth_cc(synth, chan,
4857                               fluid_midi_event_get_control(event),
4858                               fluid_midi_event_get_value(event));
4859
4860       case PROGRAM_CHANGE:
4861         return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
4862
4863       case CHANNEL_PRESSURE:
4864         return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
4865
4866       case PITCH_BEND:
4867         return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));
4868
4869       case MIDI_SYSTEM_RESET:
4870         return fluid_synth_system_reset(synth);
4871       case MIDI_SYSEX:
4872         return fluid_synth_sysex (synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE);
4873   }
4874   return FLUID_FAILED;
4875 }
4876
4877 /**
4878  * Create and start voices using a preset and a MIDI note on event.
4879  * @param synth FluidSynth instance
4880  * @param id Voice group ID to use (can be used with fluid_synth_stop()).
4881  * @param preset Preset to synthesize
4882  * @param audio_chan Unused currently, set to 0
4883  * @param chan MIDI channel number (0 to MIDI channel count - 1)
4884  * @param key MIDI note number (0-127)
4885  * @param vel MIDI velocity number (1-127)
4886  * @return FLUID_OK on success, FLUID_FAILED otherwise
4887  *
4888  * NOTE: Should only be called from within synthesis thread, which includes
4889  * SoundFont loader preset noteon method.
4890  */
4891 int
4892 fluid_synth_start(fluid_synth_t* synth, unsigned int id, fluid_preset_t* preset, 
4893                   int audio_chan, int chan, int key, int vel)
4894 {
4895   int result;
4896   fluid_return_val_if_fail (preset != NULL, FLUID_FAILED);
4897   fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED);
4898   fluid_return_val_if_fail (vel >= 1 && vel <= 127, FLUID_FAILED);
4899   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
4900   synth->storeid = id;
4901   result = fluid_preset_noteon (preset, synth, chan, key, vel);
4902   FLUID_API_RETURN(result);
4903 }
4904
4905 /**
4906  * Stop notes for a given note event voice ID.
4907  * @param synth FluidSynth instance
4908  * @param id Voice note event ID
4909  * @return FLUID_OK on success, FLUID_FAILED otherwise
4910  *
4911  * NOTE: In FluidSynth versions prior to 1.1.0 #FLUID_FAILED would be returned
4912  * if no matching voice note event ID was found.  Versions after 1.1.0 only
4913  * return #FLUID_FAILED if an error occurs.
4914  */
4915 int
4916 fluid_synth_stop(fluid_synth_t* synth, unsigned int id)
4917 {
4918   int result;
4919   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4920   fluid_synth_api_enter(synth);
4921   fluid_synth_stop_LOCAL (synth, id);
4922   result = FLUID_OK;
4923   FLUID_API_RETURN(result);
4924 }
4925
4926 /* Local synthesis thread variant of fluid_synth_stop */
4927 static void
4928 fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id)
4929 {
4930   fluid_voice_t* voice;
4931   int i;
4932
4933   for (i = 0; i < synth->polyphony; i++) {
4934     voice = synth->voice[i];
4935
4936     if (_ON(voice) && (fluid_voice_get_id (voice) == id))
4937       fluid_voice_noteoff(voice);
4938   }
4939 }
4940
4941 /**
4942  * Offset the bank numbers of a loaded SoundFont.
4943  * @param synth FluidSynth instance
4944  * @param sfont_id ID of a loaded SoundFont
4945  * @param offset Bank offset value to apply to all instruments
4946  */
4947 int
4948 fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset)
4949 {
4950   fluid_sfont_info_t *sfont_info;
4951   fluid_list_t *list;
4952
4953   fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
4954   fluid_synth_api_enter(synth);
4955   
4956   for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
4957     sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
4958
4959     if (fluid_sfont_get_id (sfont_info->sfont) == (unsigned int)sfont_id)
4960     {
4961       sfont_info->bankofs = offset;
4962       break;
4963     }
4964   }
4965
4966   if (!list)
4967   {
4968     FLUID_LOG (FLUID_ERR, "No SoundFont with id = %d", sfont_id);
4969     FLUID_API_RETURN(FLUID_FAILED);
4970   }
4971
4972   FLUID_API_RETURN(FLUID_OK);
4973 }
4974
4975 /**
4976  * Get bank offset of a loaded SoundFont.
4977  * @param synth FluidSynth instance
4978  * @param sfont_id ID of a loaded SoundFont
4979  * @return SoundFont bank offset value
4980  */
4981 int
4982 fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id)
4983 {
4984   fluid_sfont_info_t *sfont_info;
4985   fluid_list_t *list;
4986   int offset = 0;
4987
4988   fluid_return_val_if_fail (synth != NULL, 0);
4989   fluid_synth_api_enter(synth);
4990
4991   for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
4992     sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
4993
4994     if (fluid_sfont_get_id (sfont_info->sfont) == (unsigned int)sfont_id)
4995     {
4996       offset = sfont_info->bankofs;
4997       break;
4998     }
4999   }
5000
5001   if (!list)
5002   {
5003     FLUID_LOG (FLUID_ERR, "No SoundFont with id = %d", sfont_id);
5004     FLUID_API_RETURN(0);
5005   }
5006
5007   FLUID_API_RETURN(offset);
5008 }
5009
5010 void 
5011 fluid_synth_api_enter(fluid_synth_t* synth)
5012 {
5013   if (synth->use_mutex) {
5014     fluid_rec_mutex_lock(synth->mutex);
5015   }
5016   if (!synth->public_api_count) {
5017     fluid_synth_check_finished_voices(synth);
5018   }
5019   synth->public_api_count++;
5020 }
5021
5022 void fluid_synth_api_exit(fluid_synth_t* synth)
5023 {
5024   synth->public_api_count--;
5025   if (!synth->public_api_count) {
5026     fluid_rvoice_eventhandler_flush(synth->eventhandler);
5027   }
5028
5029   if (synth->use_mutex) {
5030     fluid_rec_mutex_unlock(synth->mutex);
5031   }
5032   
5033 }
5034
5035
5036 /**
5037  * Set midi channel type 
5038  * @param synth FluidSynth instance
5039  * @param chan MIDI channel number (0 to MIDI channel count - 1)
5040  * @param type CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM
5041  * @return FLUID_OK on success, FLUID_FAILED otherwise
5042  * @since 1.1.4
5043  */
5044 int fluid_synth_set_channel_type(fluid_synth_t* synth, int chan, int type)
5045 {
5046   fluid_return_val_if_fail ((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED);
5047   FLUID_API_ENTRY_CHAN(FLUID_FAILED);
5048   
5049   synth->channel[chan]->channel_type = type;
5050
5051   FLUID_API_RETURN(FLUID_OK);
5052 }
5053