Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/synth/fluid_synth.c
4396 views
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 Lesser General Public License
7
* as published by the Free Software Foundation; either version 2.1 of
8
* the License, or (at your option) any later version.
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
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
* 02110-1301, USA
19
*/
20
21
#include "fluid_synth.h"
22
#include "fluid_sys.h"
23
#include "fluid_chan.h"
24
#include "fluid_tuning.h"
25
#include "fluid_settings.h"
26
#include "fluid_sfont.h"
27
#include "fluid_defsfont.h"
28
#include "fluid_instpatch.h"
29
30
#ifdef TRAP_ON_FPE
31
#define _GNU_SOURCE
32
#include <fenv.h>
33
34
/* seems to not be declared in fenv.h */
35
extern int feenableexcept(int excepts);
36
#endif
37
38
#define FLUID_API_RETURN(return_value) \
39
do { fluid_synth_api_exit(synth); \
40
return return_value; } while (0)
41
42
#define FLUID_API_RETURN_IF_CHAN_DISABLED(return_value) \
43
do { if (FLUID_LIKELY(synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)) \
44
{} \
45
else \
46
{ FLUID_API_RETURN(return_value); } \
47
} while (0)
48
49
#define FLUID_API_ENTRY_CHAN(fail_value) \
50
fluid_return_val_if_fail (synth != NULL, fail_value); \
51
fluid_return_val_if_fail (chan >= 0, fail_value); \
52
fluid_synth_api_enter(synth); \
53
if (chan >= synth->midi_channels) { \
54
FLUID_API_RETURN(fail_value); \
55
} \
56
57
static void fluid_synth_init(void);
58
static void fluid_synth_api_enter(fluid_synth_t *synth);
59
static void fluid_synth_api_exit(fluid_synth_t *synth);
60
61
static int fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key,
62
int vel);
63
static int fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key);
64
static int fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num);
65
static int fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data,
66
int len, char *response,
67
int *response_len, int avail_response,
68
int *handled, int dryrun);
69
static int fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data,
70
int len, char *response,
71
int *response_len, int avail_response,
72
int *handled, int dryrun);
73
static int fluid_synth_sysex_xg(fluid_synth_t *synth, const char *data,
74
int len, char *response,
75
int *response_len, int avail_response,
76
int *handled, int dryrun);
77
int fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan);
78
static int fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan);
79
static int fluid_synth_system_reset_LOCAL(fluid_synth_t *synth);
80
static int fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan,
81
int is_cc, int ctrl);
82
static int fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan);
83
static int fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int channum);
84
static int fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key);
85
static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan);
86
static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan);
87
static int fluid_synth_set_preset(fluid_synth_t *synth, int chan,
88
fluid_preset_t *preset);
89
static int fluid_synth_reverb_get_param(fluid_synth_t *synth, int fx_group,
90
int param, double *value);
91
static int fluid_synth_chorus_get_param(fluid_synth_t *synth, int fx_group,
92
int param, double *value);
93
94
static fluid_preset_t *
95
fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
96
int banknum, int prognum);
97
static fluid_preset_t *
98
fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname,
99
int banknum, int prognum);
100
101
static void fluid_synth_update_presets(fluid_synth_t *synth);
102
static void fluid_synth_update_gain_LOCAL(fluid_synth_t *synth);
103
static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony);
104
static void init_dither(void);
105
static FLUID_INLINE int16_t round_clip_to_i16(float x);
106
static int fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount);
107
108
static fluid_voice_t *fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth);
109
static void fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
110
fluid_voice_t *new_voice);
111
static int fluid_synth_sfunload_callback(void *data, unsigned int msec);
112
static fluid_tuning_t *fluid_synth_get_tuning(fluid_synth_t *synth,
113
int bank, int prog);
114
static int fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth,
115
fluid_tuning_t *tuning,
116
int bank, int prog, int apply);
117
static void fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth,
118
fluid_tuning_t *old_tuning,
119
fluid_tuning_t *new_tuning,
120
int apply, int unref_new);
121
static void fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth,
122
fluid_channel_t *channel);
123
static int fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
124
fluid_tuning_t *tuning, int apply);
125
static void fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan,
126
int param, float value);
127
static void fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id);
128
129
130
static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels);
131
132
static void fluid_synth_process_awe32_nrpn_LOCAL(fluid_synth_t *synth, int chan, int gen, int data, int data_lsb);
133
134
/* Callback handlers for real-time settings */
135
static void fluid_synth_handle_gain(void *data, const char *name, double value);
136
static void fluid_synth_handle_polyphony(void *data, const char *name, int value);
137
static void fluid_synth_handle_device_id(void *data, const char *name, int value);
138
static void fluid_synth_handle_overflow(void *data, const char *name, double value);
139
static void fluid_synth_handle_important_channels(void *data, const char *name,
140
const char *value);
141
static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value);
142
static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value);
143
144
145
static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan);
146
static int fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val);
147
static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val);
148
149
/***************************************************************
150
*
151
* GLOBAL
152
*/
153
154
/* has the synth module been initialized? */
155
/* fluid_atomic_int_t may be anything, so init with {0} to catch most cases */
156
static fluid_atomic_int_t fluid_synth_initialized = {0};
157
158
/* default modulators
159
* SF2.01 page 52 ff:
160
*
161
* There is a set of predefined default modulators. They have to be
162
* explicitly overridden by the sound font in order to turn them off.
163
*/
164
165
static fluid_mod_t default_vel2att_mod; /* SF2.01 section 8.4.1 */
166
/*not static */ fluid_mod_t default_vel2filter_mod; /* SF2.01 section 8.4.2 */
167
static fluid_mod_t default_at2viblfo_mod; /* SF2.01 section 8.4.3 */
168
static fluid_mod_t default_mod2viblfo_mod; /* SF2.01 section 8.4.4 */
169
static fluid_mod_t default_att_mod; /* SF2.01 section 8.4.5 */
170
static fluid_mod_t default_pan_mod; /* SF2.01 section 8.4.6 */
171
static fluid_mod_t default_expr_mod; /* SF2.01 section 8.4.7 */
172
static fluid_mod_t default_reverb_mod; /* SF2.01 section 8.4.8 */
173
static fluid_mod_t default_chorus_mod; /* SF2.01 section 8.4.9 */
174
static fluid_mod_t default_pitch_bend_mod; /* SF2.01 section 8.4.10 */
175
static fluid_mod_t custom_balance_mod; /* Non-standard modulator */
176
177
178
/* custom_breath2att_modulator is not a default modulator specified in SF
179
it is intended to replace default_vel2att_mod on demand using
180
API fluid_set_breath_mode() or command shell setbreathmode.
181
*/
182
static fluid_mod_t custom_breath2att_mod;
183
184
/* reverb presets */
185
static const fluid_revmodel_presets_t revmodel_preset[] =
186
{
187
/* name */ /* roomsize */ /* damp */ /* width */ /* level */
188
{ "Test 1", 0.2f, 0.0f, 0.5f, 0.9f },
189
{ "Test 2", 0.4f, 0.2f, 0.5f, 0.8f },
190
{ "Test 3", 0.6f, 0.4f, 0.5f, 0.7f },
191
{ "Test 4", 0.8f, 0.7f, 0.5f, 0.6f },
192
{ "Test 5", 0.8f, 1.0f, 0.5f, 0.5f },
193
};
194
195
196
/***************************************************************
197
*
198
* INITIALIZATION & UTILITIES
199
*/
200
201
void fluid_synth_settings(fluid_settings_t *settings)
202
{
203
fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1, FLUID_HINT_TOGGLED);
204
205
fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1, FLUID_HINT_TOGGLED);
206
fluid_settings_register_num(settings, "synth.reverb.room-size", FLUID_REVERB_DEFAULT_ROOMSIZE, 0.0, 1.0, 0);
207
fluid_settings_register_num(settings, "synth.reverb.damp", FLUID_REVERB_DEFAULT_DAMP, 0.0, 1.0, 0);
208
fluid_settings_register_num(settings, "synth.reverb.width", FLUID_REVERB_DEFAULT_WIDTH, 0.0, 100.0, 0);
209
fluid_settings_register_num(settings, "synth.reverb.level", FLUID_REVERB_DEFAULT_LEVEL, 0.0, 1.0, 0);
210
211
fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1, FLUID_HINT_TOGGLED);
212
fluid_settings_register_int(settings, "synth.chorus.nr", FLUID_CHORUS_DEFAULT_N, 0, 99, 0);
213
fluid_settings_register_num(settings, "synth.chorus.level", FLUID_CHORUS_DEFAULT_LEVEL, 0.0, 10.0, 0);
214
fluid_settings_register_num(settings, "synth.chorus.speed", FLUID_CHORUS_DEFAULT_SPEED, 0.1, 5.0, 0);
215
fluid_settings_register_num(settings, "synth.chorus.depth", FLUID_CHORUS_DEFAULT_DEPTH, 0.0, 256.0, 0);
216
217
fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, FLUID_HINT_TOGGLED);
218
fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1, FLUID_HINT_TOGGLED);
219
fluid_settings_register_str(settings, "midi.portname", "", 0);
220
221
#ifdef DEFAULT_SOUNDFONT
222
fluid_settings_register_str(settings, "synth.default-soundfont", DEFAULT_SOUNDFONT, 0);
223
#endif
224
225
fluid_settings_register_int(settings, "synth.polyphony", 256, 1, 65535, 0);
226
fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0);
227
fluid_settings_register_num(settings, "synth.gain", 0.2, 0.0, 10.0, 0);
228
fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 128, 0);
229
fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 128, 0);
230
fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0);
231
fluid_settings_register_int(settings, "synth.effects-groups", 1, 1, 128, 0);
232
fluid_settings_register_num(settings, "synth.sample-rate", 44100.0, 8000.0, 96000.0, 0);
233
fluid_settings_register_int(settings, "synth.device-id", 16, 0, 127, 0);
234
#ifdef ENABLE_MIXER_THREADS
235
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0);
236
#else
237
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 1, 0);
238
#endif
239
240
fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0);
241
242
fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1, FLUID_HINT_TOGGLED);
243
244
fluid_settings_register_num(settings, "synth.overflow.percussion", 4000, -10000, 10000, 0);
245
fluid_settings_register_num(settings, "synth.overflow.sustained", -1000, -10000, 10000, 0);
246
fluid_settings_register_num(settings, "synth.overflow.released", -2000, -10000, 10000, 0);
247
fluid_settings_register_num(settings, "synth.overflow.age", 1000, -10000, 10000, 0);
248
fluid_settings_register_num(settings, "synth.overflow.volume", 500, -10000, 10000, 0);
249
fluid_settings_register_num(settings, "synth.overflow.important", 5000, -50000, 50000, 0);
250
fluid_settings_register_str(settings, "synth.overflow.important-channels", "", 0);
251
252
fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0);
253
fluid_settings_add_option(settings, "synth.midi-bank-select", "gm");
254
fluid_settings_add_option(settings, "synth.midi-bank-select", "gs");
255
fluid_settings_add_option(settings, "synth.midi-bank-select", "xg");
256
fluid_settings_add_option(settings, "synth.midi-bank-select", "mma");
257
258
fluid_settings_register_int(settings, "synth.dynamic-sample-loading", 0, 0, 1, FLUID_HINT_TOGGLED);
259
}
260
261
/**
262
* Get FluidSynth runtime version.
263
* @param major Location to store major number
264
* @param minor Location to store minor number
265
* @param micro Location to store micro number
266
*/
267
void fluid_version(int *major, int *minor, int *micro)
268
{
269
*major = FLUIDSYNTH_VERSION_MAJOR;
270
*minor = FLUIDSYNTH_VERSION_MINOR;
271
*micro = FLUIDSYNTH_VERSION_MICRO;
272
}
273
274
/**
275
* Get FluidSynth runtime version as a string.
276
* @return FluidSynth version string, which is internal and should not be
277
* modified or freed.
278
*/
279
char *
280
fluid_version_str(void)
281
{
282
return FLUIDSYNTH_VERSION;
283
}
284
285
/*
286
* void fluid_synth_init
287
*
288
* Does all the initialization for this module.
289
*/
290
static void
291
fluid_synth_init(void)
292
{
293
#ifdef TRAP_ON_FPE
294
#if !defined(__GLIBC__) && defined(__linux__)
295
#warning "Trap on FPE is only supported when using glibc!"
296
#else
297
/* Turn on floating point exception traps */
298
feenableexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID);
299
#endif
300
#endif
301
302
init_dither();
303
304
#if 0 /* unused in Wine */
305
/* custom_breath2att_mod is not a default modulator specified in SF2.01.
306
it is intended to replace default_vel2att_mod on demand using
307
API fluid_set_breath_mode() or command shell setbreathmode.
308
*/
309
fluid_mod_set_source1(&custom_breath2att_mod, /* The modulator we are programming here */
310
BREATH_MSB, /* Source. breath MSB corresponds to 2. */
311
FLUID_MOD_CC /* MIDI continuous controller */
312
| FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */
313
| FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */
314
| FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */
315
);
316
fluid_mod_set_source2(&custom_breath2att_mod, 0, 0); /* No 2nd source */
317
fluid_mod_set_dest(&custom_breath2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
318
fluid_mod_set_amount(&custom_breath2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */
319
320
/* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */
321
fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */
322
FLUID_MOD_VELOCITY, /* Source. VELOCITY corresponds to 'index=2'. */
323
FLUID_MOD_GC /* Not a MIDI continuous controller */
324
| FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */
325
| FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */
326
| FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */
327
);
328
fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */
329
fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
330
fluid_mod_set_amount(&default_vel2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */
331
332
333
334
/* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff
335
* Have to make a design decision here. The specs don't make any sense this way or another.
336
* One sound font, 'Kingston Piano', which has been praised for its quality, tries to
337
* override this modulator with an amount of 0 and positive polarity (instead of what
338
* the specs say, D=1) for the secondary source.
339
* So if we change the polarity to 'positive', one of the best free sound fonts works...
340
*/
341
fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
342
FLUID_MOD_GC /* CC=0 */
343
| FLUID_MOD_LINEAR /* type=0 */
344
| FLUID_MOD_UNIPOLAR /* P=0 */
345
| FLUID_MOD_NEGATIVE /* D=1 */
346
);
347
fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */
348
FLUID_MOD_GC /* CC=0 */
349
| FLUID_MOD_SWITCH /* type=3 */
350
| FLUID_MOD_UNIPOLAR /* P=0 */
351
// do not remove | FLUID_MOD_NEGATIVE /* D=1 */
352
| FLUID_MOD_POSITIVE /* D=0 */
353
);
354
fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC); /* Target: Initial filter cutoff */
355
fluid_mod_set_amount(&default_vel2filter_mod, -2400);
356
357
358
359
/* SF2.01 page 53 section 8.4.3: MIDI Channel pressure to Vibrato LFO pitch depth */
360
fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE, /* Index=13 */
361
FLUID_MOD_GC /* CC=0 */
362
| FLUID_MOD_LINEAR /* type=0 */
363
| FLUID_MOD_UNIPOLAR /* P=0 */
364
| FLUID_MOD_POSITIVE /* D=0 */
365
);
366
fluid_mod_set_source2(&default_at2viblfo_mod, 0, 0); /* no second source */
367
fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */
368
fluid_mod_set_amount(&default_at2viblfo_mod, 50);
369
370
371
372
/* SF2.01 page 53 section 8.4.4: Mod wheel (Controller 1) to Vibrato LFO pitch depth */
373
fluid_mod_set_source1(&default_mod2viblfo_mod, MODULATION_MSB, /* Index=1 */
374
FLUID_MOD_CC /* CC=1 */
375
| FLUID_MOD_LINEAR /* type=0 */
376
| FLUID_MOD_UNIPOLAR /* P=0 */
377
| FLUID_MOD_POSITIVE /* D=0 */
378
);
379
fluid_mod_set_source2(&default_mod2viblfo_mod, 0, 0); /* no second source */
380
fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */
381
fluid_mod_set_amount(&default_mod2viblfo_mod, 50);
382
383
384
385
/* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/
386
fluid_mod_set_source1(&default_att_mod, VOLUME_MSB, /* index=7 */
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_att_mod, 0, 0); /* No second source */
393
fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
394
fluid_mod_set_amount(&default_att_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
395
396
397
398
/* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */
399
fluid_mod_set_source1(&default_pan_mod, PAN_MSB, /* index=10 */
400
FLUID_MOD_CC /* CC=1 */
401
| FLUID_MOD_LINEAR /* type=0 */
402
| FLUID_MOD_BIPOLAR /* P=1 */
403
| FLUID_MOD_POSITIVE /* D=0 */
404
);
405
fluid_mod_set_source2(&default_pan_mod, 0, 0); /* No second source */
406
fluid_mod_set_dest(&default_pan_mod, GEN_PAN); /* Target: pan */
407
/* Amount: 500. The SF specs $8.4.6, p. 55 says: "Amount = 1000
408
tenths of a percent". The center value (64) corresponds to 50%,
409
so it follows that amount = 50% x 1000/% = 500. */
410
fluid_mod_set_amount(&default_pan_mod, 500.0);
411
412
413
/* SF2.01 page 55 section 8.4.7: MIDI continuous controller 11 to initial attenuation*/
414
fluid_mod_set_source1(&default_expr_mod, EXPRESSION_MSB, /* index=11 */
415
FLUID_MOD_CC /* CC=1 */
416
| FLUID_MOD_CONCAVE /* type=1 */
417
| FLUID_MOD_UNIPOLAR /* P=0 */
418
| FLUID_MOD_NEGATIVE /* D=1 */
419
);
420
fluid_mod_set_source2(&default_expr_mod, 0, 0); /* No second source */
421
fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION); /* Target: Initial attenuation */
422
fluid_mod_set_amount(&default_expr_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
423
424
425
426
/* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */
427
fluid_mod_set_source1(&default_reverb_mod, EFFECTS_DEPTH1, /* index=91 */
428
FLUID_MOD_CC /* CC=1 */
429
| FLUID_MOD_LINEAR /* type=0 */
430
| FLUID_MOD_UNIPOLAR /* P=0 */
431
| FLUID_MOD_POSITIVE /* D=0 */
432
);
433
fluid_mod_set_source2(&default_reverb_mod, 0, 0); /* No second source */
434
fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND); /* Target: Reverb send */
435
fluid_mod_set_amount(&default_reverb_mod, 200); /* Amount: 200 ('tenths of a percent') */
436
437
438
439
/* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Chorus send */
440
fluid_mod_set_source1(&default_chorus_mod, EFFECTS_DEPTH3, /* index=93 */
441
FLUID_MOD_CC /* CC=1 */
442
| FLUID_MOD_LINEAR /* type=0 */
443
| FLUID_MOD_UNIPOLAR /* P=0 */
444
| FLUID_MOD_POSITIVE /* D=0 */
445
);
446
fluid_mod_set_source2(&default_chorus_mod, 0, 0); /* No second source */
447
fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND); /* Target: Chorus */
448
fluid_mod_set_amount(&default_chorus_mod, 200); /* Amount: 200 ('tenths of a percent') */
449
450
451
452
/* SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch ... */
453
/* Initial Pitch is not a "standard" generator, because it isn't mentioned in the
454
list of generators in the SF2 specifications. That's why destination Initial Pitch
455
is replaced here by fine tune generator.
456
*/
457
fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL, /* Index=14 */
458
FLUID_MOD_GC /* CC =0 */
459
| FLUID_MOD_LINEAR /* type=0 */
460
| FLUID_MOD_BIPOLAR /* P=1 */
461
| FLUID_MOD_POSITIVE /* D=0 */
462
);
463
fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS, /* Index = 16 */
464
FLUID_MOD_GC /* CC=0 */
465
| FLUID_MOD_LINEAR /* type=0 */
466
| FLUID_MOD_UNIPOLAR /* P=0 */
467
| FLUID_MOD_POSITIVE /* D=0 */
468
);
469
/* Also see the comment in gen.h about GEN_PITCH */
470
fluid_mod_set_dest(&default_pitch_bend_mod, GEN_FINETUNE); /* Destination: Fine Tune */
471
fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */
472
473
474
/* Non-standard MIDI continuous controller 8 to channel stereo balance */
475
fluid_mod_set_source1(&custom_balance_mod, BALANCE_MSB, /* Index=8 */
476
FLUID_MOD_CC /* CC=1 */
477
| FLUID_MOD_CONCAVE /* type=1 */
478
| FLUID_MOD_BIPOLAR /* P=1 */
479
| FLUID_MOD_POSITIVE /* D=0 */
480
);
481
fluid_mod_set_source2(&custom_balance_mod, 0, 0);
482
fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */
483
/* Amount: 96 dB of attenuation (on the opposite channel) */
484
fluid_mod_set_amount(&custom_balance_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */
485
#endif /* unused in Wine */
486
487
#if defined(LIBINSTPATCH_SUPPORT)
488
/* defer libinstpatch init to fluid_instpatch.c to avoid #include "libinstpatch.h" */
489
if(!fluid_instpatch_supports_multi_init())
490
{
491
fluid_instpatch_init();
492
}
493
#endif
494
}
495
496
static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t *synth)
497
{
498
return fluid_atomic_int_get(&synth->ticks_since_start);
499
}
500
501
static FLUID_INLINE void fluid_synth_add_ticks(fluid_synth_t *synth, int val)
502
{
503
fluid_atomic_int_add(&synth->ticks_since_start, val);
504
}
505
506
507
/***************************************************************
508
* FLUID SAMPLE TIMERS
509
* Timers that use written audio data as timing reference
510
*/
511
struct _fluid_sample_timer_t
512
{
513
fluid_sample_timer_t *next; /* Single linked list of timers */
514
unsigned long starttick;
515
fluid_timer_callback_t callback;
516
void *data;
517
int isfinished;
518
};
519
520
/*
521
* fluid_sample_timer_process - called when synth->ticks is updated
522
*/
523
static void fluid_sample_timer_process(fluid_synth_t *synth)
524
{
525
fluid_sample_timer_t *st;
526
long msec;
527
int cont;
528
unsigned int ticks = fluid_synth_get_ticks(synth);
529
530
for(st = synth->sample_timers; st; st = st->next)
531
{
532
if(st->isfinished)
533
{
534
continue;
535
}
536
537
msec = (long)(1000.0 * ((double)(ticks - st->starttick)) / synth->sample_rate);
538
cont = (*st->callback)(st->data, msec);
539
540
if(cont == 0)
541
{
542
st->isfinished = 1;
543
}
544
}
545
}
546
547
fluid_sample_timer_t *new_fluid_sample_timer(fluid_synth_t *synth, fluid_timer_callback_t callback, void *data)
548
{
549
fluid_sample_timer_t *result = FLUID_NEW(fluid_sample_timer_t);
550
551
if(result == NULL)
552
{
553
FLUID_LOG(FLUID_ERR, "Out of memory");
554
return NULL;
555
}
556
557
fluid_sample_timer_reset(synth, result);
558
result->data = data;
559
result->callback = callback;
560
result->next = synth->sample_timers;
561
synth->sample_timers = result;
562
return result;
563
}
564
565
void delete_fluid_sample_timer(fluid_synth_t *synth, fluid_sample_timer_t *timer)
566
{
567
fluid_sample_timer_t **ptr;
568
fluid_return_if_fail(synth != NULL);
569
fluid_return_if_fail(timer != NULL);
570
571
ptr = &synth->sample_timers;
572
573
while(*ptr)
574
{
575
if(*ptr == timer)
576
{
577
*ptr = timer->next;
578
FLUID_FREE(timer);
579
return;
580
}
581
582
ptr = &((*ptr)->next);
583
}
584
}
585
586
void fluid_sample_timer_reset(fluid_synth_t *synth, fluid_sample_timer_t *timer)
587
{
588
timer->starttick = fluid_synth_get_ticks(synth);
589
timer->isfinished = 0;
590
}
591
592
/***************************************************************
593
*
594
* FLUID SYNTH
595
*/
596
597
static FLUID_INLINE void
598
fluid_synth_update_mixer(fluid_synth_t *synth, fluid_rvoice_function_t method, int intparam,
599
fluid_real_t realparam)
600
{
601
fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL);
602
fluid_return_if_fail(synth->eventhandler->mixer != NULL);
603
fluid_rvoice_eventhandler_push_int_real(synth->eventhandler, method,
604
synth->eventhandler->mixer,
605
intparam, realparam);
606
}
607
608
static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_synth_t *synth)
609
{
610
int i;
611
fluid_settings_getint(synth->settings, "synth.min-note-length", &i);
612
return (unsigned int)(i * synth->sample_rate / 1000.0f);
613
}
614
615
/**
616
* Create new FluidSynth instance.
617
* @param settings Configuration parameters to use (used directly).
618
* @return New FluidSynth instance or NULL on error
619
*
620
* @note The @p settings parameter is used directly, but the synth does not take ownership of it.
621
* Hence, the caller is responsible for freeing it, when no longer needed.
622
* Further note that you may modify FluidSettings of the
623
* @p settings instance. However, only those FluidSettings marked as 'realtime' will
624
* affect the synth immediately. See the \ref fluidsettings for more details.
625
*
626
* @warning The @p settings object should only be used by a single synth at a time. I.e. creating
627
* multiple synth instances with a single @p settings object causes undefined behavior. Once the
628
* "single synth" has been deleted, you may use the @p settings object again for another synth.
629
*/
630
fluid_synth_t *
631
new_fluid_synth(fluid_settings_t *settings)
632
{
633
fluid_synth_t *synth;
634
fluid_sfloader_t *loader;
635
char *important_channels;
636
int i, prio_level = 0;
637
int with_ladspa = 0;
638
double sample_rate_min, sample_rate_max;
639
640
/* initialize all the conversion tables and other stuff */
641
if(fluid_atomic_int_compare_and_exchange(&fluid_synth_initialized, 0, 1))
642
{
643
fluid_synth_init();
644
}
645
646
/* allocate a new synthesizer object */
647
synth = FLUID_NEW(fluid_synth_t);
648
649
if(synth == NULL)
650
{
651
FLUID_LOG(FLUID_ERR, "Out of memory");
652
return NULL;
653
}
654
655
FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t));
656
657
#if defined(LIBINSTPATCH_SUPPORT)
658
if(fluid_instpatch_supports_multi_init())
659
{
660
fluid_instpatch_init();
661
}
662
#endif
663
664
fluid_rec_mutex_init(synth->mutex);
665
fluid_settings_getint(settings, "synth.threadsafe-api", &synth->use_mutex);
666
synth->public_api_count = 0;
667
668
synth->settings = settings;
669
670
fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb);
671
fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus);
672
fluid_settings_getint(settings, "synth.verbose", &synth->verbose);
673
674
fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
675
fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate);
676
fluid_settings_getnum_range(settings, "synth.sample-rate", &sample_rate_min, &sample_rate_max);
677
fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels);
678
fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
679
fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups);
680
fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
681
fluid_settings_getint(settings, "synth.effects-groups", &synth->effects_groups);
682
fluid_settings_getnum_float(settings, "synth.gain", &synth->gain);
683
fluid_settings_getint(settings, "synth.device-id", &synth->device_id);
684
fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores);
685
686
fluid_settings_getnum_float(settings, "synth.overflow.percussion", &synth->overflow.percussion);
687
fluid_settings_getnum_float(settings, "synth.overflow.released", &synth->overflow.released);
688
fluid_settings_getnum_float(settings, "synth.overflow.sustained", &synth->overflow.sustained);
689
fluid_settings_getnum_float(settings, "synth.overflow.volume", &synth->overflow.volume);
690
fluid_settings_getnum_float(settings, "synth.overflow.age", &synth->overflow.age);
691
fluid_settings_getnum_float(settings, "synth.overflow.important", &synth->overflow.important);
692
693
/* register the callbacks */
694
fluid_settings_callback_num(settings, "synth.gain",
695
fluid_synth_handle_gain, synth);
696
fluid_settings_callback_int(settings, "synth.polyphony",
697
fluid_synth_handle_polyphony, synth);
698
fluid_settings_callback_int(settings, "synth.device-id",
699
fluid_synth_handle_device_id, synth);
700
fluid_settings_callback_num(settings, "synth.overflow.percussion",
701
fluid_synth_handle_overflow, synth);
702
fluid_settings_callback_num(settings, "synth.overflow.sustained",
703
fluid_synth_handle_overflow, synth);
704
fluid_settings_callback_num(settings, "synth.overflow.released",
705
fluid_synth_handle_overflow, synth);
706
fluid_settings_callback_num(settings, "synth.overflow.age",
707
fluid_synth_handle_overflow, synth);
708
fluid_settings_callback_num(settings, "synth.overflow.volume",
709
fluid_synth_handle_overflow, synth);
710
fluid_settings_callback_num(settings, "synth.overflow.important",
711
fluid_synth_handle_overflow, synth);
712
fluid_settings_callback_str(settings, "synth.overflow.important-channels",
713
fluid_synth_handle_important_channels, synth);
714
fluid_settings_callback_num(settings, "synth.reverb.room-size",
715
fluid_synth_handle_reverb_chorus_num, synth);
716
fluid_settings_callback_num(settings, "synth.reverb.damp",
717
fluid_synth_handle_reverb_chorus_num, synth);
718
fluid_settings_callback_num(settings, "synth.reverb.width",
719
fluid_synth_handle_reverb_chorus_num, synth);
720
fluid_settings_callback_num(settings, "synth.reverb.level",
721
fluid_synth_handle_reverb_chorus_num, synth);
722
fluid_settings_callback_int(settings, "synth.reverb.active",
723
fluid_synth_handle_reverb_chorus_int, synth);
724
fluid_settings_callback_int(settings, "synth.chorus.active",
725
fluid_synth_handle_reverb_chorus_int, synth);
726
fluid_settings_callback_int(settings, "synth.chorus.nr",
727
fluid_synth_handle_reverb_chorus_int, synth);
728
fluid_settings_callback_num(settings, "synth.chorus.level",
729
fluid_synth_handle_reverb_chorus_num, synth);
730
fluid_settings_callback_num(settings, "synth.chorus.depth",
731
fluid_synth_handle_reverb_chorus_num, synth);
732
fluid_settings_callback_num(settings, "synth.chorus.speed",
733
fluid_synth_handle_reverb_chorus_num, synth);
734
735
/* do some basic sanity checking on the settings */
736
737
if(synth->midi_channels % 16 != 0)
738
{
739
int n = synth->midi_channels / 16;
740
synth->midi_channels = (n + 1) * 16;
741
fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels);
742
FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. "
743
"I'll increase the number of channels to the next multiple.");
744
}
745
746
if(synth->audio_channels < 1)
747
{
748
FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. "
749
"Changing this setting to 1.");
750
synth->audio_channels = 1;
751
}
752
else if(synth->audio_channels > 128)
753
{
754
FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). "
755
"Limiting this setting to 128.", synth->audio_channels);
756
synth->audio_channels = 128;
757
}
758
759
if(synth->audio_groups < 1)
760
{
761
FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. "
762
"Changing this setting to 1.");
763
synth->audio_groups = 1;
764
}
765
else if(synth->audio_groups > 128)
766
{
767
FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). "
768
"Limiting this setting to 128.", synth->audio_groups);
769
synth->audio_groups = 128;
770
}
771
772
if(synth->effects_channels < 2)
773
{
774
FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)."
775
"Setting effects channels to 2.", synth->effects_channels);
776
synth->effects_channels = 2;
777
}
778
779
/*
780
number of buffers rendered by the mixer is determined by synth->audio_groups.
781
audio from MIDI channel is rendered, mapped and mixed in these buffers.
782
783
Typically synth->audio_channels is only used by audio driver and should be set
784
to the same value that synth->audio_groups. In some situation using LADSPA,
785
it is best to diminish audio-channels so that the driver will be able to pass
786
the audio to audio devices in the case these devices have a limited number of
787
audio channels.
788
789
audio-channels must not be greater then audio-groups, otherwise these
790
audio output above audio-groups will not be rendered by the mixeur.
791
*/
792
if(synth->audio_channels > synth->audio_groups)
793
{
794
synth->audio_channels = synth->audio_groups;
795
fluid_settings_setint(settings, "synth.audio-channels", synth->audio_channels);
796
FLUID_LOG(FLUID_WARN, "Requested audio-channels to high. "
797
"Limiting this setting to audio-groups.");
798
}
799
800
if(fluid_settings_dupstr(settings, "synth.overflow.important-channels",
801
&important_channels) == FLUID_OK)
802
{
803
if(fluid_synth_set_important_channels(synth, important_channels) != FLUID_OK)
804
{
805
FLUID_LOG(FLUID_WARN, "Failed to set overflow important channels");
806
}
807
808
FLUID_FREE(important_channels);
809
}
810
811
/* as soon as the synth is created it starts playing. */
812
synth->state = FLUID_SYNTH_PLAYING;
813
814
synth->fromkey_portamento = INVALID_NOTE; /* disable portamento */
815
816
fluid_atomic_int_set(&synth->ticks_since_start, 0);
817
synth->tuning = NULL;
818
fluid_private_init(synth->tuning_iter);
819
820
/* Initialize multi-core variables if multiple cores enabled */
821
if(synth->cores > 1)
822
{
823
fluid_settings_getint(synth->settings, "audio.realtime-prio", &prio_level);
824
}
825
826
/* Allocate event queue for rvoice mixer */
827
/* In an overflow situation, a new voice takes about 50 spaces in the queue! */
828
synth->eventhandler = new_fluid_rvoice_eventhandler(synth->polyphony * 64,
829
synth->polyphony, synth->audio_groups,
830
synth->effects_channels, synth->effects_groups,
831
(fluid_real_t)sample_rate_max, synth->sample_rate,
832
synth->cores - 1, prio_level);
833
834
if(synth->eventhandler == NULL)
835
{
836
goto error_recovery;
837
}
838
839
/* Setup the list of default modulators.
840
* Needs to happen after eventhandler has been set up, as fluid_synth_enter_api is called in the process */
841
synth->default_mod = NULL;
842
fluid_synth_add_default_mod(synth, &default_vel2att_mod, FLUID_SYNTH_ADD);
843
fluid_synth_add_default_mod(synth, &default_vel2filter_mod, FLUID_SYNTH_ADD);
844
fluid_synth_add_default_mod(synth, &default_at2viblfo_mod, FLUID_SYNTH_ADD);
845
fluid_synth_add_default_mod(synth, &default_mod2viblfo_mod, FLUID_SYNTH_ADD);
846
fluid_synth_add_default_mod(synth, &default_att_mod, FLUID_SYNTH_ADD);
847
fluid_synth_add_default_mod(synth, &default_pan_mod, FLUID_SYNTH_ADD);
848
fluid_synth_add_default_mod(synth, &default_expr_mod, FLUID_SYNTH_ADD);
849
fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD);
850
fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD);
851
fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD);
852
fluid_synth_add_default_mod(synth, &custom_balance_mod, FLUID_SYNTH_ADD);
853
854
/* Create and initialize the Fx unit.*/
855
fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);
856
857
if(with_ladspa)
858
{
859
#ifdef LADSPA
860
synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate,
861
FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE);
862
863
if(synth->ladspa_fx == NULL)
864
{
865
FLUID_LOG(FLUID_ERR, "Out of memory");
866
goto error_recovery;
867
}
868
869
fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx,
870
synth->audio_groups);
871
#else /* LADSPA */
872
FLUID_LOG(FLUID_WARN, "FluidSynth has not been compiled with LADSPA support");
873
#endif /* LADSPA */
874
}
875
876
/* allocate and add the dls sfont loader */
877
#ifdef LIBINSTPATCH_SUPPORT
878
loader = new_fluid_instpatch_loader(settings);
879
880
if(loader == NULL)
881
{
882
FLUID_LOG(FLUID_WARN, "Failed to create the instpatch SoundFont loader");
883
}
884
else
885
{
886
fluid_synth_add_sfloader(synth, loader);
887
}
888
#endif
889
890
/* allocate and add the default sfont loader */
891
loader = new_fluid_defsfloader(settings);
892
893
if(loader == NULL)
894
{
895
FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader");
896
}
897
else
898
{
899
fluid_synth_add_sfloader(synth, loader);
900
}
901
902
/* allocate all channel objects */
903
synth->channel = FLUID_ARRAY(fluid_channel_t *, synth->midi_channels);
904
905
if(synth->channel == NULL)
906
{
907
FLUID_LOG(FLUID_ERR, "Out of memory");
908
goto error_recovery;
909
}
910
911
FLUID_MEMSET(synth->channel, 0, synth->midi_channels * sizeof(*synth->channel));
912
for(i = 0; i < synth->midi_channels; i++)
913
{
914
synth->channel[i] = new_fluid_channel(synth, i);
915
916
if(synth->channel[i] == NULL)
917
{
918
goto error_recovery;
919
}
920
}
921
922
/* allocate all synthesis processes */
923
synth->nvoice = synth->polyphony;
924
synth->voice = FLUID_ARRAY(fluid_voice_t *, synth->nvoice);
925
926
if(synth->voice == NULL)
927
{
928
goto error_recovery;
929
}
930
931
FLUID_MEMSET(synth->voice, 0, synth->nvoice * sizeof(*synth->voice));
932
for(i = 0; i < synth->nvoice; i++)
933
{
934
synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
935
936
if(synth->voice[i] == NULL)
937
{
938
goto error_recovery;
939
}
940
}
941
942
/* sets a default basic channel */
943
/* Sets one basic channel: basic channel 0, mode 0 (Omni On - Poly) */
944
/* (i.e all channels are polyphonic) */
945
/* Must be called after channel objects allocation */
946
fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
947
synth->midi_channels);
948
949
synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
950
951
952
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
953
synth->polyphony, 0.0f);
954
fluid_synth_reverb_on(synth, -1, synth->with_reverb);
955
fluid_synth_chorus_on(synth, -1, synth->with_chorus);
956
957
synth->cur = FLUID_BUFSIZE;
958
synth->curmax = 0;
959
synth->dither_index = 0;
960
961
{
962
double values[FLUID_REVERB_PARAM_LAST];
963
964
fluid_settings_getnum(settings, "synth.reverb.room-size", &values[FLUID_REVERB_ROOMSIZE]);
965
fluid_settings_getnum(settings, "synth.reverb.damp", &values[FLUID_REVERB_DAMP]);
966
fluid_settings_getnum(settings, "synth.reverb.width", &values[FLUID_REVERB_WIDTH]);
967
fluid_settings_getnum(settings, "synth.reverb.level", &values[FLUID_REVERB_LEVEL]);
968
969
fluid_synth_set_reverb_full(synth, -1, FLUID_REVMODEL_SET_ALL, values);
970
}
971
972
{
973
double values[FLUID_CHORUS_PARAM_LAST];
974
975
fluid_settings_getint(settings, "synth.chorus.nr", &i);
976
values[FLUID_CHORUS_NR] = (double)i;
977
fluid_settings_getnum(settings, "synth.chorus.level", &values[FLUID_CHORUS_LEVEL]);
978
fluid_settings_getnum(settings, "synth.chorus.speed", &values[FLUID_CHORUS_SPEED]);
979
fluid_settings_getnum(settings, "synth.chorus.depth", &values[FLUID_CHORUS_DEPTH]);
980
values[FLUID_CHORUS_TYPE] = (double)FLUID_CHORUS_DEFAULT_TYPE;
981
982
fluid_synth_set_chorus_full(synth, -1, FLUID_CHORUS_SET_ALL, values);
983
}
984
985
986
synth->bank_select = FLUID_BANK_STYLE_GS;
987
988
if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gm"))
989
{
990
synth->bank_select = FLUID_BANK_STYLE_GM;
991
}
992
else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gs"))
993
{
994
synth->bank_select = FLUID_BANK_STYLE_GS;
995
}
996
else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "xg"))
997
{
998
synth->bank_select = FLUID_BANK_STYLE_XG;
999
}
1000
else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "mma"))
1001
{
1002
synth->bank_select = FLUID_BANK_STYLE_MMA;
1003
}
1004
1005
fluid_synth_process_event_queue(synth);
1006
1007
/* FIXME */
1008
synth->start = fluid_curtime();
1009
1010
return synth;
1011
1012
error_recovery:
1013
delete_fluid_synth(synth);
1014
return NULL;
1015
}
1016
1017
1018
/**
1019
* Delete a FluidSynth instance.
1020
* @param synth FluidSynth instance to delete
1021
*
1022
* @note Other users of a synthesizer instance, such as audio and MIDI drivers,
1023
* should be deleted prior to freeing the FluidSynth instance.
1024
*/
1025
void
1026
delete_fluid_synth(fluid_synth_t *synth)
1027
{
1028
int i, k;
1029
fluid_list_t *list;
1030
fluid_sfont_t *sfont;
1031
fluid_sfloader_t *loader;
1032
1033
fluid_return_if_fail(synth != NULL);
1034
1035
fluid_profiling_print();
1036
1037
/* unregister all real-time settings callback, to avoid a use-after-free when changing those settings after
1038
* this synth has been deleted*/
1039
1040
fluid_settings_callback_num(synth->settings, "synth.gain",
1041
NULL, NULL);
1042
fluid_settings_callback_int(synth->settings, "synth.polyphony",
1043
NULL, NULL);
1044
fluid_settings_callback_int(synth->settings, "synth.device-id",
1045
NULL, NULL);
1046
fluid_settings_callback_num(synth->settings, "synth.overflow.percussion",
1047
NULL, NULL);
1048
fluid_settings_callback_num(synth->settings, "synth.overflow.sustained",
1049
NULL, NULL);
1050
fluid_settings_callback_num(synth->settings, "synth.overflow.released",
1051
NULL, NULL);
1052
fluid_settings_callback_num(synth->settings, "synth.overflow.age",
1053
NULL, NULL);
1054
fluid_settings_callback_num(synth->settings, "synth.overflow.volume",
1055
NULL, NULL);
1056
fluid_settings_callback_num(synth->settings, "synth.overflow.important",
1057
NULL, NULL);
1058
fluid_settings_callback_str(synth->settings, "synth.overflow.important-channels",
1059
NULL, NULL);
1060
fluid_settings_callback_num(synth->settings, "synth.reverb.room-size",
1061
NULL, NULL);
1062
fluid_settings_callback_num(synth->settings, "synth.reverb.damp",
1063
NULL, NULL);
1064
fluid_settings_callback_num(synth->settings, "synth.reverb.width",
1065
NULL, NULL);
1066
fluid_settings_callback_num(synth->settings, "synth.reverb.level",
1067
NULL, NULL);
1068
fluid_settings_callback_int(synth->settings, "synth.reverb.active",
1069
NULL, NULL);
1070
fluid_settings_callback_int(synth->settings, "synth.chorus.active",
1071
NULL, NULL);
1072
fluid_settings_callback_int(synth->settings, "synth.chorus.nr",
1073
NULL, NULL);
1074
fluid_settings_callback_num(synth->settings, "synth.chorus.level",
1075
NULL, NULL);
1076
fluid_settings_callback_num(synth->settings, "synth.chorus.depth",
1077
NULL, NULL);
1078
fluid_settings_callback_num(synth->settings, "synth.chorus.speed",
1079
NULL, NULL);
1080
1081
/* turn off all voices, needed to unload SoundFont data */
1082
if(synth->voice != NULL)
1083
{
1084
for(i = 0; i < synth->nvoice; i++)
1085
{
1086
fluid_voice_t *voice = synth->voice[i];
1087
1088
if(!voice)
1089
{
1090
continue;
1091
}
1092
1093
/* WARNING: A this point we must ensure that the reference counter
1094
of any soundfont sample owned by any rvoice belonging to the voice
1095
are correctly decremented. This is the contrary part to
1096
to fluid_voice_init() where the sample's reference counter is
1097
incremented.
1098
*/
1099
fluid_voice_unlock_rvoice(voice);
1100
fluid_voice_overflow_rvoice_finished(voice);
1101
1102
if(fluid_voice_is_playing(voice))
1103
{
1104
fluid_voice_off(voice);
1105
/* If we only use fluid_voice_off(voice) it will trigger a delayed
1106
* fluid_voice_stop(voice) via fluid_synth_check_finished_voices().
1107
* But here, we are deleting the fluid_synth_t instance so
1108
* fluid_voice_stop() will be never triggered resulting in
1109
* SoundFont data never unloaded (i.e a serious memory leak).
1110
* So, fluid_voice_stop() must be explicitly called to insure
1111
* unloading SoundFont data
1112
*/
1113
fluid_voice_stop(voice);
1114
}
1115
}
1116
}
1117
1118
/* also unset all presets for clean SoundFont unload */
1119
if(synth->channel != NULL)
1120
{
1121
for(i = 0; i < synth->midi_channels; i++)
1122
{
1123
if(synth->channel[i] != NULL)
1124
{
1125
fluid_channel_set_preset(synth->channel[i], NULL);
1126
}
1127
}
1128
}
1129
1130
delete_fluid_rvoice_eventhandler(synth->eventhandler);
1131
1132
/* delete all the SoundFonts */
1133
for(list = synth->sfont; list; list = fluid_list_next(list))
1134
{
1135
sfont = fluid_list_get(list);
1136
fluid_sfont_delete_internal(sfont);
1137
}
1138
1139
delete_fluid_list(synth->sfont);
1140
1141
/* delete all the SoundFont loaders */
1142
1143
for(list = synth->loaders; list; list = fluid_list_next(list))
1144
{
1145
loader = (fluid_sfloader_t *) fluid_list_get(list);
1146
fluid_sfloader_delete(loader);
1147
}
1148
1149
delete_fluid_list(synth->loaders);
1150
1151
/* wait for and delete all the lazy sfont unloading timers */
1152
1153
for(list = synth->fonts_to_be_unloaded; list; list = fluid_list_next(list))
1154
{
1155
fluid_timer_t* timer = fluid_list_get(list);
1156
// explicitly join to wait for the unload really to happen
1157
fluid_timer_join(timer);
1158
// delete_fluid_timer alone would stop the timer, even if it had not unloaded the soundfont yet
1159
delete_fluid_timer(timer);
1160
}
1161
1162
delete_fluid_list(synth->fonts_to_be_unloaded);
1163
1164
if(synth->channel != NULL)
1165
{
1166
for(i = 0; i < synth->midi_channels; i++)
1167
{
1168
delete_fluid_channel(synth->channel[i]);
1169
}
1170
1171
FLUID_FREE(synth->channel);
1172
}
1173
1174
if(synth->voice != NULL)
1175
{
1176
for(i = 0; i < synth->nvoice; i++)
1177
{
1178
delete_fluid_voice(synth->voice[i]);
1179
}
1180
1181
FLUID_FREE(synth->voice);
1182
}
1183
1184
1185
/* free the tunings, if any */
1186
if(synth->tuning != NULL)
1187
{
1188
for(i = 0; i < 128; i++)
1189
{
1190
if(synth->tuning[i] != NULL)
1191
{
1192
for(k = 0; k < 128; k++)
1193
{
1194
delete_fluid_tuning(synth->tuning[i][k]);
1195
}
1196
1197
FLUID_FREE(synth->tuning[i]);
1198
}
1199
}
1200
1201
FLUID_FREE(synth->tuning);
1202
}
1203
1204
fluid_private_free(synth->tuning_iter);
1205
1206
#ifdef LADSPA
1207
/* Release the LADSPA effects unit */
1208
delete_fluid_ladspa_fx(synth->ladspa_fx);
1209
#endif
1210
1211
/* delete all default modulators */
1212
delete_fluid_list_mod(synth->default_mod);
1213
1214
FLUID_FREE(synth->overflow.important_channels);
1215
1216
fluid_rec_mutex_destroy(synth->mutex);
1217
1218
FLUID_FREE(synth);
1219
1220
#if defined(LIBINSTPATCH_SUPPORT)
1221
if(fluid_instpatch_supports_multi_init())
1222
{
1223
fluid_instpatch_deinit();
1224
}
1225
#endif
1226
}
1227
1228
/**
1229
* Get a textual representation of the last error
1230
* @param synth FluidSynth instance
1231
* @return Pointer to string of last error message. Valid until the same
1232
* calling thread calls another FluidSynth function which fails. String is
1233
* internal and should not be modified or freed.
1234
* @deprecated This function is not thread-safe and does not work with multiple synths.
1235
* It has been deprecated. It may return "" in a future release and will eventually be removed.
1236
*/
1237
const char *
1238
fluid_synth_error(fluid_synth_t *synth)
1239
{
1240
return "";
1241
}
1242
1243
/**
1244
* Send a note-on event to a FluidSynth object.
1245
*
1246
* This function will take care of proper legato playing. If a note on channel @p chan is
1247
* already playing at the given key @p key, it will be released (even if it is sustained).
1248
* In other words, overlapping notes are not allowed.
1249
* @param synth FluidSynth instance
1250
* @param chan MIDI channel number (0 to MIDI channel count - 1)
1251
* @param key MIDI note number (0-127)
1252
* @param vel MIDI velocity (0-127, 0=noteoff)
1253
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
1254
*/
1255
int
1256
fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel)
1257
{
1258
int result;
1259
fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1260
fluid_return_val_if_fail(vel >= 0 && vel <= 127, FLUID_FAILED);
1261
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1262
1263
/* Allowed only on MIDI channel enabled */
1264
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1265
1266
result = fluid_synth_noteon_LOCAL(synth, chan, key, vel);
1267
FLUID_API_RETURN(result);
1268
}
1269
1270
/* Local synthesis thread variant of fluid_synth_noteon */
1271
static int
1272
fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key, int vel)
1273
{
1274
fluid_channel_t *channel ;
1275
1276
/* notes with velocity zero go to noteoff */
1277
if(vel == 0)
1278
{
1279
return fluid_synth_noteoff_LOCAL(synth, chan, key);
1280
}
1281
1282
channel = synth->channel[chan];
1283
1284
/* makes sure this channel has a preset */
1285
if(channel->preset == NULL)
1286
{
1287
if(synth->verbose)
1288
{
1289
FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s",
1290
chan, key, vel, 0,
1291
fluid_synth_get_ticks(synth) / 44100.0f,
1292
(fluid_curtime() - synth->start) / 1000.0f,
1293
0.0f, 0, "channel has no preset");
1294
}
1295
1296
return FLUID_FAILED;
1297
}
1298
1299
if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1300
{
1301
/* play the noteOn in monophonic */
1302
return fluid_synth_noteon_mono_LOCAL(synth, chan, key, vel);
1303
}
1304
else
1305
{
1306
/* channel is poly and legato CC is Off) */
1307
1308
/* plays the noteOn in polyphonic */
1309
/* Sets the note at first position in monophonic list */
1310
/* In the case where the musician intends to inter the channel in monophonic
1311
(by depressing the CC legato on), the next noteOn mono could be played legato
1312
with the previous note poly (if the musician choose this).
1313
*/
1314
fluid_channel_set_onenote_monolist(channel, (unsigned char) key,
1315
(unsigned char) vel);
1316
1317
/* If there is another voice process on the same channel and key,
1318
advance it to the release phase. */
1319
fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key);
1320
1321
/* a noteon poly is passed to fluid_synth_noteon_monopoly_legato().
1322
This allows an opportunity to get this note played legato with a previous
1323
note if a CC PTC have been received before this noteon. This behavior is
1324
a MIDI specification (see FluidPolymono-0004.pdf chapter 4.3-a ,3.4.11
1325
for details).
1326
*/
1327
return fluid_synth_noteon_monopoly_legato(synth, chan, INVALID_NOTE, key, vel);
1328
}
1329
}
1330
1331
/**
1332
* Sends a note-off event to a FluidSynth object.
1333
* @param synth FluidSynth instance
1334
* @param chan MIDI channel number (0 to MIDI channel count - 1)
1335
* @param key MIDI note number (0-127)
1336
* @return #FLUID_OK on success, #FLUID_FAILED otherwise (may just mean that no
1337
* voices matched the note off event)
1338
*/
1339
int
1340
fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key)
1341
{
1342
int result;
1343
fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
1344
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1345
1346
/* Allowed only on MIDI channel enabled */
1347
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1348
1349
result = fluid_synth_noteoff_LOCAL(synth, chan, key);
1350
FLUID_API_RETURN(result);
1351
}
1352
1353
/* Local synthesis thread variant of fluid_synth_noteoff */
1354
static int
1355
fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key)
1356
{
1357
int status;
1358
fluid_channel_t *channel = synth->channel[chan];
1359
1360
if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */
1361
{
1362
/* play the noteOff in monophonic */
1363
status = fluid_synth_noteoff_mono_LOCAL(synth, chan, key);
1364
}
1365
else
1366
{
1367
/* channel is poly and legato CC is Off) */
1368
/* removes the note from the monophonic list */
1369
if(channel->n_notes && key == fluid_channel_last_note(channel))
1370
{
1371
fluid_channel_clear_monolist(channel);
1372
}
1373
1374
status = fluid_synth_noteoff_monopoly(synth, chan, key, 0);
1375
}
1376
1377
/* Changes the state (Valid/Invalid) of the most recent note played in a
1378
staccato manner */
1379
fluid_channel_invalid_prev_note_staccato(channel);
1380
return status;
1381
}
1382
1383
/* Damps voices on a channel (turn notes off), if they're sustained by
1384
sustain pedal */
1385
static int
1386
fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t *synth, int chan)
1387
{
1388
fluid_channel_t *channel = synth->channel[chan];
1389
fluid_voice_t *voice;
1390
int i;
1391
1392
for(i = 0; i < synth->polyphony; i++)
1393
{
1394
voice = synth->voice[i];
1395
1396
if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sustained(voice))
1397
{
1398
if(voice->key == channel->key_mono_sustained)
1399
{
1400
/* key_mono_sustained is a possible mono note sustainted
1401
(by sustain or sostenuto pedal). It must be marked released
1402
(INVALID_NOTE) here because it is released only by sustain pedal */
1403
channel->key_mono_sustained = INVALID_NOTE;
1404
}
1405
1406
fluid_voice_release(voice);
1407
}
1408
}
1409
1410
return FLUID_OK;
1411
}
1412
1413
/* Damps voices on a channel (turn notes off), if they're sustained by
1414
sostenuto pedal */
1415
static int
1416
fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t *synth, int chan)
1417
{
1418
fluid_channel_t *channel = synth->channel[chan];
1419
fluid_voice_t *voice;
1420
int i;
1421
1422
for(i = 0; i < synth->polyphony; i++)
1423
{
1424
voice = synth->voice[i];
1425
1426
if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sostenuto(voice))
1427
{
1428
if(voice->key == channel->key_mono_sustained)
1429
{
1430
/* key_mono_sustained is a possible mono note sustainted
1431
(by sustain or sostenuto pedal). It must be marked released
1432
(INVALID_NOTE) here because it is released only by sostenuto pedal */
1433
channel->key_mono_sustained = INVALID_NOTE;
1434
}
1435
1436
fluid_voice_release(voice);
1437
}
1438
}
1439
1440
return FLUID_OK;
1441
}
1442
1443
/**
1444
* Adds the specified modulator \c mod as default modulator to the synth. \c mod will
1445
* take effect for any subsequently created voice.
1446
* @param synth FluidSynth instance
1447
* @param mod Modulator info (values copied, passed in object can be freed immediately afterwards)
1448
* @param mode Determines how to handle an existing identical modulator (#fluid_synth_add_mod)
1449
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
1450
*
1451
* @note Not realtime safe (due to internal memory allocation) and therefore should not be called
1452
* from synthesis context at the risk of stalling audio output.
1453
*/
1454
int
1455
fluid_synth_add_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod, int mode)
1456
{
1457
fluid_mod_t *default_mod;
1458
fluid_mod_t *last_mod = NULL;
1459
fluid_mod_t *new_mod;
1460
1461
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1462
fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1463
fluid_return_val_if_fail((mode == FLUID_SYNTH_ADD) || (mode == FLUID_SYNTH_OVERWRITE) , FLUID_FAILED);
1464
1465
/* Checks if modulators sources are valid */
1466
if(!fluid_mod_check_sources(mod, "api fluid_synth_add_default_mod mod"))
1467
{
1468
return FLUID_FAILED;
1469
}
1470
1471
fluid_synth_api_enter(synth);
1472
1473
default_mod = synth->default_mod;
1474
1475
while(default_mod != NULL)
1476
{
1477
if(fluid_mod_test_identity(default_mod, mod))
1478
{
1479
if(mode == FLUID_SYNTH_ADD)
1480
{
1481
default_mod->amount += mod->amount;
1482
}
1483
else // mode == FLUID_SYNTH_OVERWRITE
1484
{
1485
default_mod->amount = mod->amount;
1486
}
1487
1488
FLUID_API_RETURN(FLUID_OK);
1489
}
1490
1491
last_mod = default_mod;
1492
default_mod = default_mod->next;
1493
}
1494
1495
/* Add a new modulator (no existing modulator to add / overwrite). */
1496
new_mod = new_fluid_mod();
1497
1498
if(new_mod == NULL)
1499
{
1500
FLUID_API_RETURN(FLUID_FAILED);
1501
}
1502
1503
fluid_mod_clone(new_mod, mod);
1504
new_mod->next = NULL;
1505
1506
if(last_mod == NULL)
1507
{
1508
synth->default_mod = new_mod;
1509
}
1510
else
1511
{
1512
last_mod->next = new_mod;
1513
}
1514
1515
FLUID_API_RETURN(FLUID_OK);
1516
}
1517
1518
/**
1519
* Removes the specified modulator \c mod from the synth's default modulator list.
1520
* fluid_mod_test_identity() will be used to test modulator matching.
1521
* @param synth synth instance
1522
* @param mod The modulator to remove
1523
* @return #FLUID_OK if a matching modulator was found and successfully removed, #FLUID_FAILED otherwise
1524
*
1525
* @note Not realtime safe (due to internal memory freeing) and therefore should not be called
1526
* from synthesis context at the risk of stalling audio output.
1527
*/
1528
int
1529
fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod)
1530
{
1531
fluid_mod_t *default_mod;
1532
fluid_mod_t *last_mod;
1533
1534
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
1535
fluid_return_val_if_fail(mod != NULL, FLUID_FAILED);
1536
fluid_synth_api_enter(synth);
1537
1538
last_mod = default_mod = synth->default_mod;
1539
1540
while(default_mod != NULL)
1541
{
1542
if(fluid_mod_test_identity(default_mod, mod))
1543
{
1544
if(synth->default_mod == default_mod)
1545
{
1546
synth->default_mod = default_mod->next;
1547
}
1548
else
1549
{
1550
last_mod->next = default_mod->next;
1551
}
1552
1553
delete_fluid_mod(default_mod);
1554
FLUID_API_RETURN(FLUID_OK);
1555
}
1556
1557
last_mod = default_mod;
1558
default_mod = default_mod->next;
1559
}
1560
1561
FLUID_API_RETURN(FLUID_FAILED);
1562
}
1563
1564
1565
/**
1566
* Send a MIDI controller event on a MIDI channel.
1567
*
1568
* Most CCs are 7-bits wide in FluidSynth. There are a few exceptions which may be 14-bits wide as are documented here:
1569
* https://github.com/FluidSynth/fluidsynth/wiki/FluidFeatures#midi-control-change-implementation-chart
1570
*
1571
* @param synth FluidSynth instance
1572
* @param chan MIDI channel number (0 to MIDI channel count - 1)
1573
* @param num MIDI controller number (0-127)
1574
* @param val MIDI controller value (0-127)
1575
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
1576
* @note This function supports MIDI Global Controllers which will be sent to
1577
* all channels of the basic channel if this basic channel is in mode OmniOff/Mono.
1578
* This is accomplished by sending the CC one MIDI channel below the basic
1579
* channel of the receiver.
1580
* Examples: let a synthesizer with 16 MIDI channels:
1581
* - Let a basic channel 7 in mode 3 (Omni Off, Mono). If MIDI channel 6 is disabled it
1582
* could be used as CC global for all channels belonging to basic channel 7.
1583
* - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used
1584
* as CC global for all channels belonging to basic channel 0.
1585
* @warning Contrary to the MIDI Standard, this function does not clear LSB controllers,
1586
* when MSB controllers are received.
1587
*/
1588
int
1589
fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val)
1590
{
1591
int result = FLUID_FAILED;
1592
fluid_channel_t *channel;
1593
fluid_return_val_if_fail(num >= 0 && num <= 127, FLUID_FAILED);
1594
fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
1595
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1596
1597
channel = synth->channel[chan];
1598
1599
if(channel->mode & FLUID_CHANNEL_ENABLED)
1600
{
1601
/* chan is enabled */
1602
if(synth->verbose)
1603
{
1604
FLUID_LOG(FLUID_INFO, "cc\t\t%d\t%d\t%d", chan, num, val);
1605
}
1606
1607
fluid_channel_set_cc(channel, num, val);
1608
result = fluid_synth_cc_LOCAL(synth, chan, num);
1609
}
1610
else /* chan is disabled so it is a candidate for global channel */
1611
{
1612
/* looks for next basic channel */
1613
int n_chan = synth->midi_channels; /* MIDI Channels number */
1614
int basicchan ;
1615
1616
if(chan < n_chan - 1)
1617
{
1618
basicchan = chan + 1; /* next channel */
1619
}
1620
else
1621
{
1622
basicchan = 0; /* wrap to 0 */
1623
}
1624
1625
channel = synth->channel[basicchan];
1626
1627
/* Channel must be a basicchan in mode OMNIOFF_MONO */
1628
if((channel->mode & FLUID_CHANNEL_BASIC) &&
1629
((channel->mode & FLUID_CHANNEL_MODE_MASK) == FLUID_CHANNEL_MODE_OMNIOFF_MONO))
1630
{
1631
/* sends cc to all channels in this basic channel */
1632
int i, nbr = channel->mode_val;
1633
1634
for(i = basicchan; i < basicchan + nbr; i++)
1635
{
1636
if(synth->verbose)
1637
{
1638
FLUID_LOG(FLUID_INFO, "cc\t\t%d\t%d\t%d", i, num, val);
1639
}
1640
1641
fluid_channel_set_cc(synth->channel[i], num, val);
1642
result = fluid_synth_cc_LOCAL(synth, i, num);
1643
}
1644
}
1645
/* The channel chan is not a valid 'global channel' */
1646
else
1647
{
1648
result = FLUID_FAILED;
1649
}
1650
}
1651
1652
FLUID_API_RETURN(result);
1653
}
1654
1655
/* Local synthesis thread variant of MIDI CC set function.
1656
Most of CC are allowed to modulate but not all. A comment describes if CC num
1657
isn't allowed to modulate.
1658
Following explanations should help to understand both MIDI specifications and
1659
Soundfont specifications in regard to MIDI specs.
1660
1661
MIDI specs:
1662
CC LSB (32 to 63) are LSB contributions to CC MSB (0 to 31).
1663
It's up to the synthesizer to decide to take LSB values into account or not.
1664
Actually Fluidsynth doesn't use CC LSB value inside fluid_voice_update_param()
1665
(once fluid_voice_modulate() has been triggered). This is because actually
1666
fluidsynth needs only 7 bits resolution (and not 14 bits) from these CCs.
1667
So fluidsynth is using only 7 bit MSB (except for portamento time).
1668
In regard to MIDI specs Fluidsynth behaves correctly.
1669
1670
Soundfont specs 2.01 - 8.2.1:
1671
To deal correctly with MIDI CC (regardless if any synth will use CC MSB alone (7 bit)
1672
or both CCs MSB,LSB (14 bits) during synthesis), SF specs recommend not making use of
1673
CC LSB (i.e only CC MSB) in modulator sources to trigger modulation (i.e modulators
1674
with CC LSB connected to sources inputs should be ignored).
1675
These specifics are particularly suited for synths that use 14 bits CCs. In this case,
1676
the MIDI transmitter sends CC LSB first followed by CC MSB. The MIDI synth receives
1677
both CC LSB and CC MSB but only CC MSB will trigger the modulation.
1678
This will produce correct synthesis parameters update from a correct 14 bits CC.
1679
If in SF specs, modulator sources with CC LSB had been accepted, both CC LSB and
1680
CC MSB will triggers 2 modulations. This leads to incorrect synthesis parameters
1681
update followed by correct synthesis parameters update.
1682
1683
However, as long as fluidsynth will use only CC 7 bits resolution, it is safe to ignore
1684
these SF recommendations on CC receive.
1685
*/
1686
static int
1687
fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num)
1688
{
1689
fluid_channel_t *chan = synth->channel[channum];
1690
int nrpn_select;
1691
int value;
1692
1693
value = fluid_channel_get_cc(chan, num);
1694
1695
switch(num)
1696
{
1697
case LOCAL_CONTROL: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1698
break;
1699
1700
/* CC omnioff, omnion, mono, poly */
1701
/* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1702
case POLY_OFF:
1703
case POLY_ON:
1704
case OMNI_OFF:
1705
case OMNI_ON:
1706
1707
/* allowed only if channum is a basic channel */
1708
if(chan->mode & FLUID_CHANNEL_BASIC)
1709
{
1710
/* Construction of new_mode from current channel mode and this CC mode */
1711
int new_mode = chan->mode & FLUID_CHANNEL_MODE_MASK;
1712
1713
switch(num)
1714
{
1715
case POLY_OFF:
1716
new_mode |= FLUID_CHANNEL_POLY_OFF;
1717
break;
1718
1719
case POLY_ON:
1720
new_mode &= ~FLUID_CHANNEL_POLY_OFF;
1721
break;
1722
1723
case OMNI_OFF:
1724
new_mode |= FLUID_CHANNEL_OMNI_OFF;
1725
break;
1726
1727
case OMNI_ON:
1728
new_mode &= ~FLUID_CHANNEL_OMNI_OFF;
1729
break;
1730
1731
default: /* should never happen */
1732
return FLUID_FAILED;
1733
}
1734
1735
/* MIDI specs: if value is 0 it means all channels from channum to next
1736
basic channel minus 1 (if any) or to MIDI channel count minus 1.
1737
However, if value is > 0 (e.g. 4), the group of channels will be be
1738
limited to 4.
1739
value is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY as this mode
1740
implies a group of only one channel.
1741
*/
1742
/* Checks value range and changes this existing basic channel group */
1743
value = fluid_synth_check_next_basic_channel(synth, channum, new_mode, value);
1744
1745
if(value != FLUID_FAILED)
1746
{
1747
/* reset the current basic channel before changing it */
1748
fluid_synth_reset_basic_channel_LOCAL(synth, channum, chan->mode_val);
1749
fluid_synth_set_basic_channel_LOCAL(synth, channum, new_mode, value);
1750
break; /* FLUID_OK */
1751
}
1752
}
1753
1754
return FLUID_FAILED;
1755
1756
case LEGATO_SWITCH: /* not allowed to modulate */
1757
/* handles Poly/mono commutation on Legato pedal On/Off.*/
1758
fluid_channel_cc_legato(chan, value);
1759
break;
1760
1761
case PORTAMENTO_SWITCH: /* not allowed to modulate */
1762
/* Special handling of the monophonic list */
1763
/* Invalids the most recent note played in a staccato manner */
1764
fluid_channel_invalid_prev_note_staccato(chan);
1765
break;
1766
1767
case SUSTAIN_SWITCH: /* not allowed to modulate */
1768
1769
/* Release voices if Sustain switch is released */
1770
if(value < 64) /* Sustain is released */
1771
{
1772
fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
1773
}
1774
1775
break;
1776
1777
case SOSTENUTO_SWITCH: /* not allowed to modulate */
1778
1779
/* Release voices if Sostetuno switch is released */
1780
if(value < 64) /* Sostenuto is released */
1781
{
1782
fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
1783
}
1784
else /* Sostenuto is depressed */
1785
/* Update sostenuto order id when pedaling on Sostenuto */
1786
{
1787
chan->sostenuto_orderid = synth->noteid; /* future voice id value */
1788
}
1789
1790
break;
1791
1792
case BANK_SELECT_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1793
fluid_channel_set_bank_msb(chan, value & 0x7F);
1794
break;
1795
1796
case BANK_SELECT_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1797
fluid_channel_set_bank_lsb(chan, value & 0x7F);
1798
break;
1799
1800
case ALL_NOTES_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1801
fluid_synth_all_notes_off_LOCAL(synth, channum);
1802
break;
1803
1804
case ALL_SOUND_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1805
fluid_synth_all_sounds_off_LOCAL(synth, channum);
1806
break;
1807
1808
case ALL_CTRL_OFF: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1809
fluid_channel_init_ctrl(chan, 1);
1810
// the hold pedals have been reset, we maybe need to release voices
1811
fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum);
1812
fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum);
1813
fluid_synth_modulate_voices_all_LOCAL(synth, channum);
1814
break;
1815
1816
case DATA_ENTRY_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1817
case DATA_ENTRY_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1818
{
1819
/* handle both because msb might come first */
1820
int lsb_value = fluid_channel_get_cc(chan, DATA_ENTRY_LSB);
1821
int msb_value = fluid_channel_get_cc(chan, DATA_ENTRY_MSB);
1822
int data = (msb_value << 7) + lsb_value;
1823
1824
if(chan->nrpn_active) /* NRPN is active? */
1825
{
1826
/* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1827
if((fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1828
&& (fluid_channel_get_cc(chan, NRPN_LSB) < 100))
1829
{
1830
nrpn_select = chan->nrpn_select;
1831
1832
if(nrpn_select < GEN_LAST)
1833
{
1834
float val = fluid_gen_scale_nrpn(nrpn_select, data);
1835
if(synth->verbose)
1836
{
1837
FLUID_LOG(FLUID_INFO, "NRPN\t%d\t%d\t%d\t%f", channum, nrpn_select, data, val);
1838
}
1839
fluid_synth_set_gen_LOCAL(synth, channum, nrpn_select, val);
1840
}
1841
1842
chan->nrpn_select = 0; /* Reset to 0 */
1843
}
1844
else if(fluid_channel_get_cc(chan, NRPN_MSB) == 127) // indicates AWE32 NRPNs
1845
{
1846
// ALTITUDE.MID also manipulates AWE32 NRPNs by only using DATA LSB events - seems to be legal
1847
if(fluid_channel_get_cc(chan, NRPN_MSB) == 127) // indicates AWE32 NRPNs
1848
{
1849
int gen = fluid_channel_get_cc(chan, NRPN_LSB);
1850
if(synth->verbose)
1851
{
1852
FLUID_LOG(FLUID_INFO, "AWE32 NRPN RAW: Chan %d, Gen %d, data %d | 0x%X, MSB: %d, LSB: %d", channum, gen, data, data, msb_value, lsb_value);
1853
}
1854
if(gen <= 26) // Effect 26 (reverb) is the last effect to select
1855
{
1856
fluid_synth_process_awe32_nrpn_LOCAL(synth, channum, gen, data, lsb_value);
1857
}
1858
else
1859
{
1860
FLUID_LOG(FLUID_INFO, "Ignoring unknown AWE32 NRPN targetting effect %d", gen);
1861
}
1862
}
1863
}
1864
}
1865
else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */
1866
{
1867
switch(fluid_channel_get_cc(chan, RPN_LSB))
1868
{
1869
case RPN_PITCH_BEND_RANGE: /* Set bend range in semitones plus cents */
1870
fluid_channel_set_pitch_wheel_sensitivity(synth->channel[channum], msb_value + lsb_value / 100.0f); /* 0-127 maps to 0-100 cents */
1871
fluid_synth_update_pitch_wheel_sens_LOCAL(synth, channum); /* Update bend range */
1872
break;
1873
1874
case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over +/-1 semitone (+/- 100 cents, 8192 = center) */
1875
fluid_synth_set_gen_LOCAL(synth, channum, GEN_FINETUNE,
1876
(float)(data - 8192) * (100.0f / 8192.0f));
1877
break;
1878
1879
case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */
1880
fluid_synth_set_gen_LOCAL(synth, channum, GEN_COARSETUNE,
1881
msb_value - 64);
1882
break;
1883
1884
case RPN_TUNING_PROGRAM_CHANGE:
1885
fluid_channel_set_tuning_prog(chan, msb_value);
1886
fluid_synth_activate_tuning(synth, channum,
1887
fluid_channel_get_tuning_bank(chan),
1888
msb_value, TRUE);
1889
break;
1890
1891
case RPN_TUNING_BANK_SELECT:
1892
fluid_channel_set_tuning_bank(chan, msb_value);
1893
break;
1894
1895
case RPN_MODULATION_DEPTH_RANGE:
1896
break;
1897
}
1898
}
1899
1900
break;
1901
}
1902
1903
case NRPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1904
fluid_channel_set_cc(chan, NRPN_LSB, 0);
1905
chan->nrpn_select = 0;
1906
chan->nrpn_active = 1;
1907
break;
1908
1909
case NRPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1910
1911
/* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */
1912
if(fluid_channel_get_cc(chan, NRPN_MSB) == 120)
1913
{
1914
if(value == 100)
1915
{
1916
chan->nrpn_select += 100;
1917
}
1918
else if(value == 101)
1919
{
1920
chan->nrpn_select += 1000;
1921
}
1922
else if(value == 102)
1923
{
1924
chan->nrpn_select += 10000;
1925
}
1926
else if(value < 100)
1927
{
1928
chan->nrpn_select += value;
1929
}
1930
}
1931
1932
chan->nrpn_active = 1;
1933
break;
1934
1935
case RPN_MSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1936
case RPN_LSB: /* not allowed to modulate (spec SF 2.01 - 8.2.1) */
1937
chan->nrpn_active = 0;
1938
break;
1939
1940
case BREATH_MSB:
1941
/* handles CC Breath On/Off noteOn/noteOff mode */
1942
fluid_channel_cc_breath_note_on_off(chan, value);
1943
1944
/* fall-through */
1945
default:
1946
/* CC lsb shouldn't allowed to modulate (spec SF 2.01 - 8.2.1) */
1947
/* However, as long fluidsynth will use only CC 7 bits resolution, it
1948
is safe to ignore these SF recommendations on CC receive. See
1949
explanations above */
1950
/* if (! (32 <= num && num <= 63)) */
1951
{
1952
return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num);
1953
}
1954
}
1955
1956
return FLUID_OK;
1957
}
1958
1959
/**
1960
* Get current MIDI controller value on a MIDI channel.
1961
* @param synth FluidSynth instance
1962
* @param chan MIDI channel number (0 to MIDI channel count - 1)
1963
* @param num MIDI controller number (0-127)
1964
* @param pval Location to store MIDI controller value (0-127)
1965
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
1966
*/
1967
int
1968
fluid_synth_get_cc(fluid_synth_t *synth, int chan, int num, int *pval)
1969
{
1970
fluid_return_val_if_fail(num >= 0 && num < 128, FLUID_FAILED);
1971
fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
1972
1973
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
1974
1975
/* Allowed only on MIDI channel enabled */
1976
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
1977
1978
*pval = fluid_channel_get_cc(synth->channel[chan], num);
1979
FLUID_API_RETURN(FLUID_OK);
1980
}
1981
1982
/*
1983
* Handler for synth.device-id setting.
1984
*/
1985
static void
1986
fluid_synth_handle_device_id(void *data, const char *name, int value)
1987
{
1988
fluid_synth_t *synth = (fluid_synth_t *)data;
1989
fluid_return_if_fail(synth != NULL);
1990
1991
fluid_synth_api_enter(synth);
1992
synth->device_id = value;
1993
fluid_synth_api_exit(synth);
1994
}
1995
1996
/**
1997
* Process a MIDI SYSEX (system exclusive) message.
1998
* @param synth FluidSynth instance
1999
* @param data Buffer containing SYSEX data (not including 0xF0 and 0xF7)
2000
* @param len Length of data in buffer
2001
* @param response Buffer to store response to or NULL to ignore
2002
* @param response_len IN/OUT parameter, in: size of response buffer, out:
2003
* amount of data written to response buffer (if #FLUID_FAILED is returned and
2004
* this value is non-zero, it indicates the response buffer is too small)
2005
* @param handled Optional location to store boolean value if message was
2006
* recognized and handled or not (set to TRUE if it was handled)
2007
* @param dryrun TRUE to just do a dry run but not actually execute the SYSEX
2008
* command (useful for checking if a SYSEX message would be handled)
2009
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2010
* @since 1.1.0
2011
* @note When Fluidsynth receives an XG System Mode ON message, it compares the @p synth 's deviceID
2012
* directly with the deviceID of the SysEx message. This is contrary to the XG spec (page 42), which
2013
* requires to only compare the lower nibble. However, following the XG spec seems to break drum channels
2014
* for a lot of MIDI files out there and therefore we've decided for this customization. If you rely on
2015
* XG System Mode ON messages, make sure to set the setting \ref settings_synth_device-id to match the
2016
* deviceID provided in the SysEx message (in most cases, this will be <code>deviceID=16</code>).
2017
*
2018
* @code
2019
* SYSEX format (0xF0 and 0xF7 bytes shall not be passed to this function):
2020
* Non-realtime: 0xF0 0x7E <DeviceId> [BODY] 0xF7
2021
* Realtime: 0xF0 0x7F <DeviceId> [BODY] 0xF7
2022
* Tuning messages: 0xF0 0x7E/0x7F <DeviceId> 0x08 <sub ID2> [BODY] <ChkSum> 0xF7
2023
* GS DT1 messages: 0xF0 0x41 <DeviceId> 0x42 0x12 [ADDRESS (3 bytes)] [DATA] <ChkSum> 0xF7
2024
* @endcode
2025
*/
2026
int
2027
fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len,
2028
char *response, int *response_len, int *handled, int dryrun)
2029
{
2030
int avail_response = 0;
2031
2032
if(handled)
2033
{
2034
*handled = FALSE;
2035
}
2036
2037
if(response_len)
2038
{
2039
avail_response = *response_len;
2040
*response_len = 0;
2041
}
2042
2043
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2044
fluid_return_val_if_fail(data != NULL, FLUID_FAILED);
2045
fluid_return_val_if_fail(len > 0, FLUID_FAILED);
2046
fluid_return_val_if_fail(!response || response_len, FLUID_FAILED);
2047
2048
if(len < 4)
2049
{
2050
return FLUID_OK;
2051
}
2052
2053
/* MIDI tuning SYSEX message? */
2054
if((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME)
2055
&& (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL || synth->device_id == MIDI_SYSEX_DEVICE_ID_ALL)
2056
&& data[2] == MIDI_SYSEX_MIDI_TUNING_ID)
2057
{
2058
int result;
2059
fluid_synth_api_enter(synth);
2060
result = fluid_synth_sysex_midi_tuning(synth, data, len, response,
2061
response_len, avail_response,
2062
handled, dryrun);
2063
2064
FLUID_API_RETURN(result);
2065
}
2066
2067
/* GM or GM2 system on */
2068
if(data[0] == MIDI_SYSEX_UNIV_NON_REALTIME
2069
&& (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL || synth->device_id == MIDI_SYSEX_DEVICE_ID_ALL)
2070
&& data[2] == MIDI_SYSEX_GM_ID)
2071
{
2072
if(handled)
2073
{
2074
*handled = TRUE;
2075
}
2076
if(!dryrun && (data[3] == MIDI_SYSEX_GM_ON
2077
|| data[3] == MIDI_SYSEX_GM2_ON))
2078
{
2079
int result;
2080
fluid_synth_api_enter(synth);
2081
synth->bank_select = FLUID_BANK_STYLE_GM;
2082
result = fluid_synth_system_reset_LOCAL(synth);
2083
FLUID_API_RETURN(result);
2084
}
2085
return FLUID_OK;
2086
}
2087
2088
/* GS DT1 message */
2089
if(data[0] == MIDI_SYSEX_MANUF_ROLAND
2090
&& (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL || synth->device_id == MIDI_SYSEX_DEVICE_ID_ALL)
2091
&& data[2] == MIDI_SYSEX_GS_ID
2092
&& data[3] == MIDI_SYSEX_GS_DT1)
2093
{
2094
int result;
2095
fluid_synth_api_enter(synth);
2096
result = fluid_synth_sysex_gs_dt1(synth, data, len, response,
2097
response_len, avail_response,
2098
handled, dryrun);
2099
FLUID_API_RETURN(result);
2100
}
2101
2102
/* XG message */
2103
if(data[0] == MIDI_SYSEX_MANUF_YAMAHA
2104
&& (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL || synth->device_id == MIDI_SYSEX_DEVICE_ID_ALL)
2105
&& data[2] == MIDI_SYSEX_XG_ID)
2106
{
2107
int result;
2108
fluid_synth_api_enter(synth);
2109
result = fluid_synth_sysex_xg(synth, data, len, response,
2110
response_len, avail_response,
2111
handled, dryrun);
2112
FLUID_API_RETURN(result);
2113
}
2114
2115
return FLUID_OK;
2116
}
2117
2118
/* Handler for MIDI tuning SYSEX messages */
2119
static int
2120
fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len,
2121
char *response, int *response_len, int avail_response,
2122
int *handled, int dryrun)
2123
{
2124
int realtime, msgid;
2125
int bank = 0, prog, channels;
2126
double tunedata[128];
2127
int keys[128];
2128
char name[17]={0};
2129
int note, frac, frac2;
2130
uint8_t chksum;
2131
int i, count, index;
2132
const char *dataptr;
2133
char *resptr;
2134
2135
realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME;
2136
msgid = data[3];
2137
2138
switch(msgid)
2139
{
2140
case MIDI_SYSEX_TUNING_BULK_DUMP_REQ:
2141
case MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK:
2142
if(data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
2143
{
2144
if(len != 5 || data[4] & 0x80 || !response)
2145
{
2146
return FLUID_OK;
2147
}
2148
2149
*response_len = 406;
2150
prog = data[4];
2151
}
2152
else
2153
{
2154
if(len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response)
2155
{
2156
return FLUID_OK;
2157
}
2158
2159
*response_len = 407;
2160
bank = data[4];
2161
prog = data[5];
2162
}
2163
2164
if(dryrun)
2165
{
2166
if(handled)
2167
{
2168
*handled = TRUE;
2169
}
2170
2171
return FLUID_OK;
2172
}
2173
2174
if(avail_response < *response_len)
2175
{
2176
return FLUID_FAILED;
2177
}
2178
2179
/* Get tuning data, return if tuning not found */
2180
if(fluid_synth_tuning_dump(synth, bank, prog, name, 17, tunedata) == FLUID_FAILED)
2181
{
2182
*response_len = 0;
2183
return FLUID_OK;
2184
}
2185
2186
resptr = response;
2187
2188
*resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME;
2189
*resptr++ = synth->device_id;
2190
*resptr++ = MIDI_SYSEX_MIDI_TUNING_ID;
2191
*resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP;
2192
2193
if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK)
2194
{
2195
*resptr++ = bank;
2196
}
2197
2198
*resptr++ = prog;
2199
/* copy 16 ASCII characters (potentially not null terminated) to the sysex buffer */
2200
FLUID_MEMCPY(resptr, name, 16);
2201
resptr += 16;
2202
2203
for(i = 0; i < 128; i++)
2204
{
2205
note = tunedata[i] / 100.0;
2206
fluid_clip(note, 0, 127);
2207
2208
frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0;
2209
fluid_clip(frac, 0, 16383);
2210
2211
*resptr++ = note;
2212
*resptr++ = frac >> 7;
2213
*resptr++ = frac & 0x7F;
2214
}
2215
2216
if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ)
2217
{
2218
/* NOTE: Checksum is not as straight forward as the bank based messages */
2219
chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID
2220
^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog;
2221
2222
for(i = 21; i < 128 * 3 + 21; i++)
2223
{
2224
chksum ^= response[i];
2225
}
2226
}
2227
else
2228
{
2229
for(i = 1, chksum = 0; i < 406; i++)
2230
{
2231
chksum ^= response[i];
2232
}
2233
}
2234
2235
*resptr++ = chksum & 0x7F;
2236
2237
if(handled)
2238
{
2239
*handled = TRUE;
2240
}
2241
2242
break;
2243
2244
case MIDI_SYSEX_TUNING_NOTE_TUNE:
2245
case MIDI_SYSEX_TUNING_NOTE_TUNE_BANK:
2246
dataptr = data + 4;
2247
2248
if(msgid == MIDI_SYSEX_TUNING_NOTE_TUNE)
2249
{
2250
if(len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6)
2251
{
2252
return FLUID_OK;
2253
}
2254
}
2255
else
2256
{
2257
if(len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80
2258
|| len != data[6] * 4 + 7)
2259
{
2260
return FLUID_OK;
2261
}
2262
2263
bank = *dataptr++;
2264
}
2265
2266
if(dryrun)
2267
{
2268
if(handled)
2269
{
2270
*handled = TRUE;
2271
}
2272
2273
return FLUID_OK;
2274
}
2275
2276
prog = *dataptr++;
2277
count = *dataptr++;
2278
2279
for(i = 0, index = 0; i < count; i++)
2280
{
2281
note = *dataptr++;
2282
2283
if(note & 0x80)
2284
{
2285
return FLUID_OK;
2286
}
2287
2288
keys[index] = note;
2289
2290
note = *dataptr++;
2291
frac = *dataptr++;
2292
frac2 = *dataptr++;
2293
2294
if(note & 0x80 || frac & 0x80 || frac2 & 0x80)
2295
{
2296
return FLUID_OK;
2297
}
2298
2299
frac = frac << 7 | frac2;
2300
2301
/* No change pitch value? Doesn't really make sense to send that, but.. */
2302
if(note == 0x7F && frac == 16383)
2303
{
2304
continue;
2305
}
2306
2307
tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0);
2308
index++;
2309
}
2310
2311
if(index > 0)
2312
{
2313
if(fluid_synth_tune_notes(synth, bank, prog, index, keys, tunedata,
2314
realtime) == FLUID_FAILED)
2315
{
2316
return FLUID_FAILED;
2317
}
2318
}
2319
2320
if(handled)
2321
{
2322
*handled = TRUE;
2323
}
2324
2325
break;
2326
2327
case MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE:
2328
case MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE:
2329
if((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19)
2330
|| (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31))
2331
{
2332
return FLUID_OK;
2333
}
2334
2335
if(data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80)
2336
{
2337
return FLUID_OK;
2338
}
2339
2340
if(dryrun)
2341
{
2342
if(handled)
2343
{
2344
*handled = TRUE;
2345
}
2346
2347
return FLUID_OK;
2348
}
2349
2350
channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6];
2351
2352
if(msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE)
2353
{
2354
for(i = 0; i < 12; i++)
2355
{
2356
frac = data[i + 7];
2357
2358
if(frac & 0x80)
2359
{
2360
return FLUID_OK;
2361
}
2362
2363
tunedata[i] = (int)frac - 64;
2364
}
2365
}
2366
else
2367
{
2368
for(i = 0; i < 12; i++)
2369
{
2370
frac = data[i * 2 + 7];
2371
frac2 = data[i * 2 + 8];
2372
2373
if(frac & 0x80 || frac2 & 0x80)
2374
{
2375
return FLUID_OK;
2376
}
2377
2378
tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0);
2379
}
2380
}
2381
2382
if(fluid_synth_activate_octave_tuning(synth, 0, 0, "SYSEX",
2383
tunedata, realtime) == FLUID_FAILED)
2384
{
2385
return FLUID_FAILED;
2386
}
2387
2388
if(channels)
2389
{
2390
for(i = 0; i < 16; i++)
2391
{
2392
if(channels & (1 << i))
2393
{
2394
fluid_synth_activate_tuning(synth, i, 0, 0, realtime);
2395
}
2396
}
2397
}
2398
2399
if(handled)
2400
{
2401
*handled = TRUE;
2402
}
2403
2404
break;
2405
}
2406
2407
return FLUID_OK;
2408
}
2409
2410
/* Handler for GS DT1 messages */
2411
static int
2412
fluid_synth_sysex_gs_dt1(fluid_synth_t *synth, const char *data, int len,
2413
char *response, int *response_len, int avail_response,
2414
int *handled, int dryrun)
2415
{
2416
int addr;
2417
int len_data;
2418
int checksum = 0, i;
2419
2420
if(len < 9) // at least one byte of data should be transmitted
2421
{
2422
FLUID_LOG(FLUID_INFO, "SysEx DT1: message too short, dropping it.");
2423
return FLUID_FAILED;
2424
}
2425
len_data = len - 8;
2426
addr = (data[4] << 16) | (data[5] << 8) | data[6];
2427
2428
for (i = 4; i < len - 1; ++i)
2429
{
2430
checksum += data[i];
2431
}
2432
checksum = 0x80 - (checksum & 0x7F);
2433
if (checksum != data[len - 1])
2434
{
2435
FLUID_LOG(FLUID_INFO, "SysEx DT1: dropping message on addr 0x%x due to incorrect checksum 0x%x. Correct checksum: 0x%x", addr, (int)data[len - 1], checksum);
2436
return FLUID_FAILED;
2437
}
2438
2439
if (addr == 0x40007F) // Mode set
2440
{
2441
if (len_data > 1 || (data[7] != 0 && data[7] != 0x7f))
2442
{
2443
FLUID_LOG(FLUID_INFO, "SysEx DT1: dropping invalid mode set message");
2444
return FLUID_FAILED;
2445
}
2446
if (handled)
2447
{
2448
*handled = TRUE;
2449
}
2450
if (!dryrun)
2451
{
2452
if (data[7] == 0)
2453
{
2454
synth->bank_select = FLUID_BANK_STYLE_GS;
2455
}
2456
else
2457
{
2458
synth->bank_select = FLUID_BANK_STYLE_GM;
2459
}
2460
return fluid_synth_system_reset_LOCAL(synth);
2461
}
2462
return FLUID_OK;
2463
}
2464
2465
if (synth->bank_select != FLUID_BANK_STYLE_GS)
2466
{
2467
return FLUID_OK; // Silently ignore all other messages
2468
}
2469
2470
if ((addr & 0xFFF0FF) == 0x401015) // Use for rhythm part
2471
{
2472
if (len_data > 1 || data[7] > 0x02)
2473
{
2474
FLUID_LOG(FLUID_INFO, "SysEx DT1: dropping invalid rhythm part message");
2475
return FLUID_FAILED;
2476
}
2477
if (handled)
2478
{
2479
*handled = TRUE;
2480
}
2481
if (!dryrun)
2482
{
2483
int chan = (addr >> 8) & 0x0F;
2484
//See the Patch Part parameters section in SC-88Pro/8850 owner's manual
2485
chan = chan >= 0x0a ? chan : (chan == 0 ? 9 : chan - 1);
2486
synth->channel[chan]->channel_type =
2487
data[7] == 0x00 ? CHANNEL_TYPE_MELODIC : CHANNEL_TYPE_DRUM;
2488
2489
FLUID_LOG(FLUID_DBG, "SysEx DT1: setting MIDI channel %d to type %d", chan, (int)synth->channel[chan]->channel_type);
2490
//Roland synths seem to "remember" the last instrument a channel
2491
//used in the selected mode. This behavior is not replicated here.
2492
fluid_synth_program_change(synth, chan, 0);
2493
}
2494
return FLUID_OK;
2495
}
2496
2497
//silently ignore
2498
return FLUID_OK;
2499
}
2500
2501
/* Handler for XG messages */
2502
static int
2503
fluid_synth_sysex_xg(fluid_synth_t *synth, const char *data, int len,
2504
char *response, int *response_len, int avail_response,
2505
int *handled, int dryrun)
2506
{
2507
int addr;
2508
int len_data;
2509
2510
if(len < 7) // at least one byte of data should be transmitted
2511
{
2512
return FLUID_FAILED;
2513
}
2514
len_data = len - 6;
2515
addr = (data[3] << 16) | (data[4] << 8) | data[5];
2516
2517
if (addr == 0x00007E // Reset
2518
|| addr == 0x00007F) // Reset to factory
2519
{
2520
if (len_data > 1 || data[6] != 0)
2521
{
2522
return FLUID_FAILED;
2523
}
2524
if (handled)
2525
{
2526
*handled = TRUE;
2527
}
2528
if (!dryrun)
2529
{
2530
synth->bank_select = FLUID_BANK_STYLE_XG;
2531
return fluid_synth_system_reset_LOCAL(synth);
2532
}
2533
return FLUID_OK;
2534
}
2535
2536
/* No other messages handled yet
2537
if (synth->bank_select != FLUID_BANK_STYLE_XG)
2538
{
2539
return FLUID_OK; // Silently ignore all other messages
2540
}*/
2541
2542
//silently ignore
2543
return FLUID_OK;
2544
}
2545
2546
/**
2547
* Turn off all voices that are playing on the given MIDI channel, by putting them into release phase.
2548
* @param synth FluidSynth instance
2549
* @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2550
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2551
* @since 1.1.4
2552
*/
2553
int
2554
fluid_synth_all_notes_off(fluid_synth_t *synth, int chan)
2555
{
2556
int result;
2557
2558
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2559
fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2560
fluid_synth_api_enter(synth);
2561
2562
if(chan >= synth->midi_channels)
2563
{
2564
result = FLUID_FAILED;
2565
}
2566
else
2567
{
2568
/* Allowed (even for channel disabled) as chan = -1 selects all channels */
2569
result = fluid_synth_all_notes_off_LOCAL(synth, chan);
2570
}
2571
2572
FLUID_API_RETURN(result);
2573
}
2574
2575
/* Local synthesis thread variant of all notes off, (chan=-1 selects all channels) */
2576
//static int
2577
int
2578
fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan)
2579
{
2580
fluid_voice_t *voice;
2581
int i;
2582
2583
for(i = 0; i < synth->polyphony; i++)
2584
{
2585
voice = synth->voice[i];
2586
2587
if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2588
{
2589
fluid_voice_noteoff(voice);
2590
}
2591
}
2592
2593
return FLUID_OK;
2594
}
2595
2596
/**
2597
* Immediately stop all voices on the given MIDI channel (skips release phase).
2598
* @param synth FluidSynth instance
2599
* @param chan MIDI channel number (0 to MIDI channel count - 1), (chan=-1 selects all channels)
2600
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2601
* @since 1.1.4
2602
*/
2603
int
2604
fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan)
2605
{
2606
int result;
2607
2608
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2609
fluid_return_val_if_fail(chan >= -1, FLUID_FAILED);
2610
fluid_synth_api_enter(synth);
2611
2612
if(chan >= synth->midi_channels)
2613
{
2614
result = FLUID_FAILED;
2615
}
2616
else
2617
{
2618
/* Allowed (even for channel disabled) as chan = -1 selects all channels */
2619
result = fluid_synth_all_sounds_off_LOCAL(synth, chan);
2620
}
2621
2622
FLUID_API_RETURN(result);
2623
}
2624
2625
/* Local synthesis thread variant of all sounds off, (chan=-1 selects all channels) */
2626
static int
2627
fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan)
2628
{
2629
fluid_voice_t *voice;
2630
int i;
2631
2632
for(i = 0; i < synth->polyphony; i++)
2633
{
2634
voice = synth->voice[i];
2635
2636
if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice))))
2637
{
2638
fluid_voice_off(voice);
2639
}
2640
}
2641
2642
return FLUID_OK;
2643
}
2644
2645
/**
2646
* Reset reverb engine
2647
* @param synth FluidSynth instance
2648
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2649
*/
2650
int
2651
fluid_synth_reset_reverb(fluid_synth_t *synth)
2652
{
2653
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2654
fluid_synth_api_enter(synth);
2655
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2656
FLUID_API_RETURN(FLUID_OK);
2657
}
2658
2659
/**
2660
* Reset chorus engine
2661
* @param synth FluidSynth instance
2662
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2663
*/
2664
int
2665
fluid_synth_reset_chorus(fluid_synth_t *synth)
2666
{
2667
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2668
fluid_synth_api_enter(synth);
2669
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2670
FLUID_API_RETURN(FLUID_OK);
2671
}
2672
2673
2674
/**
2675
* Send MIDI system reset command (big red 'panic' button), turns off notes, resets
2676
* controllers and restores initial basic channel configuration.
2677
* @param synth FluidSynth instance
2678
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2679
*/
2680
int
2681
fluid_synth_system_reset(fluid_synth_t *synth)
2682
{
2683
int result;
2684
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2685
fluid_synth_api_enter(synth);
2686
result = fluid_synth_system_reset_LOCAL(synth);
2687
FLUID_API_RETURN(result);
2688
}
2689
2690
/* Local variant of the system reset command */
2691
static int
2692
fluid_synth_system_reset_LOCAL(fluid_synth_t *synth)
2693
{
2694
int i;
2695
2696
if(synth->verbose)
2697
{
2698
FLUID_LOG(FLUID_INFO, "=== systemreset ===");
2699
}
2700
2701
fluid_synth_all_sounds_off_LOCAL(synth, -1);
2702
2703
for(i = 0; i < synth->midi_channels; i++)
2704
{
2705
fluid_channel_reset(synth->channel[i]);
2706
}
2707
2708
/* Basic channel 0, Mode Omni On Poly */
2709
fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
2710
synth->midi_channels);
2711
2712
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
2713
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
2714
2715
return FLUID_OK;
2716
}
2717
2718
/**
2719
* Update voices on a MIDI channel after a MIDI control change.
2720
* @param synth FluidSynth instance
2721
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2722
* @param is_cc Boolean value indicating if ctrl is a CC controller or not
2723
* @param ctrl MIDI controller value
2724
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2725
*/
2726
static int
2727
fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan, int is_cc, int ctrl)
2728
{
2729
fluid_voice_t *voice;
2730
int i;
2731
2732
for(i = 0; i < synth->polyphony; i++)
2733
{
2734
voice = synth->voice[i];
2735
2736
if(fluid_voice_get_channel(voice) == chan)
2737
{
2738
fluid_voice_modulate(voice, is_cc, ctrl);
2739
}
2740
}
2741
2742
return FLUID_OK;
2743
}
2744
2745
/**
2746
* Update voices on a MIDI channel after all MIDI controllers have been changed.
2747
* @param synth FluidSynth instance
2748
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2749
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2750
*/
2751
static int
2752
fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan)
2753
{
2754
fluid_voice_t *voice;
2755
int i;
2756
2757
for(i = 0; i < synth->polyphony; i++)
2758
{
2759
voice = synth->voice[i];
2760
2761
if(fluid_voice_get_channel(voice) == chan)
2762
{
2763
fluid_voice_modulate_all(voice);
2764
}
2765
}
2766
2767
return FLUID_OK;
2768
}
2769
2770
/**
2771
* Set the MIDI channel pressure controller value.
2772
* @param synth FluidSynth instance
2773
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2774
* @param val MIDI channel pressure value (0-127)
2775
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2776
*/
2777
int
2778
fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val)
2779
{
2780
int result;
2781
fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2782
2783
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2784
2785
/* Allowed only on MIDI channel enabled */
2786
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2787
2788
if(synth->verbose)
2789
{
2790
FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
2791
}
2792
2793
fluid_channel_set_channel_pressure(synth->channel[chan], val);
2794
result = fluid_synth_update_channel_pressure_LOCAL(synth, chan);
2795
2796
FLUID_API_RETURN(result);
2797
}
2798
2799
/* Updates channel pressure from within synthesis thread */
2800
static int
2801
fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int chan)
2802
{
2803
return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_CHANNELPRESSURE);
2804
}
2805
2806
/**
2807
* Set the MIDI polyphonic key pressure controller value.
2808
* @param synth FluidSynth instance
2809
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2810
* @param key MIDI key number (0-127)
2811
* @param val MIDI key pressure value (0-127)
2812
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2813
* @since 2.0.0
2814
*/
2815
int
2816
fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val)
2817
{
2818
int result;
2819
fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
2820
fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED);
2821
2822
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2823
2824
/* Allowed only on MIDI channel enabled */
2825
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2826
2827
if(synth->verbose)
2828
{
2829
FLUID_LOG(FLUID_INFO, "keypressure\t%d\t%d\t%d", chan, key, val);
2830
}
2831
2832
fluid_channel_set_key_pressure(synth->channel[chan], key, val);
2833
result = fluid_synth_update_key_pressure_LOCAL(synth, chan, key);
2834
2835
FLUID_API_RETURN(result);
2836
}
2837
2838
/* Updates key pressure from within synthesis thread */
2839
static int
2840
fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key)
2841
{
2842
fluid_voice_t *voice;
2843
int i;
2844
int result = FLUID_OK;
2845
2846
for(i = 0; i < synth->polyphony; i++)
2847
{
2848
voice = synth->voice[i];
2849
2850
if(voice->chan == chan && voice->key == key)
2851
{
2852
result = fluid_voice_modulate(voice, 0, FLUID_MOD_KEYPRESSURE);
2853
2854
if(result != FLUID_OK)
2855
{
2856
return result;
2857
}
2858
}
2859
}
2860
2861
return result;
2862
}
2863
2864
/**
2865
* Set the MIDI pitch bend controller value on a MIDI channel.
2866
* @param synth FluidSynth instance
2867
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2868
* @param val MIDI pitch bend value (0-16383 with 8192 being center)
2869
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2870
*/
2871
int
2872
fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val)
2873
{
2874
int result;
2875
fluid_return_val_if_fail(val >= 0 && val <= 16383, FLUID_FAILED);
2876
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2877
2878
/* Allowed only on MIDI channel enabled */
2879
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2880
2881
if(synth->verbose)
2882
{
2883
FLUID_LOG(FLUID_INFO, "pitchb\t\t%d\t%d", chan, val);
2884
}
2885
2886
fluid_channel_set_pitch_bend(synth->channel[chan], val);
2887
result = fluid_synth_update_pitch_bend_LOCAL(synth, chan);
2888
2889
FLUID_API_RETURN(result);
2890
}
2891
2892
/* Local synthesis thread variant of pitch bend */
2893
static int
2894
fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan)
2895
{
2896
return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEEL);
2897
}
2898
2899
/**
2900
* Get the MIDI pitch bend controller value on a MIDI channel.
2901
* @param synth FluidSynth instance
2902
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2903
* @param ppitch_bend Location to store MIDI pitch bend value (0-16383 with
2904
* 8192 being center)
2905
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2906
*/
2907
int
2908
fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend)
2909
{
2910
int result;
2911
fluid_return_val_if_fail(ppitch_bend != NULL, FLUID_FAILED);
2912
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2913
2914
/* Allowed only on MIDI channel enabled */
2915
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2916
2917
*ppitch_bend = fluid_channel_get_pitch_bend(synth->channel[chan]);
2918
result = FLUID_OK;
2919
2920
FLUID_API_RETURN(result);
2921
}
2922
2923
/**
2924
* Set MIDI pitch wheel sensitivity on a MIDI channel.
2925
* @param synth FluidSynth instance
2926
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2927
* @param val Pitch wheel sensitivity value in semitones
2928
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2929
*/
2930
int
2931
fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val)
2932
{
2933
int result;
2934
fluid_return_val_if_fail(val >= 0 && val <= 72, FLUID_FAILED); /* 6 octaves!? Better than no limit.. */
2935
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2936
2937
/* Allowed only on MIDI channel enabled */
2938
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2939
2940
if(synth->verbose)
2941
{
2942
FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val);
2943
}
2944
2945
fluid_channel_set_pitch_wheel_sensitivity(synth->channel[chan], val);
2946
result = fluid_synth_update_pitch_wheel_sens_LOCAL(synth, chan);
2947
2948
FLUID_API_RETURN(result);
2949
}
2950
2951
/* Local synthesis thread variant of set pitch wheel sensitivity */
2952
static int
2953
fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan)
2954
{
2955
return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEELSENS);
2956
}
2957
2958
/**
2959
* Get MIDI pitch wheel sensitivity on a MIDI channel.
2960
* @param synth FluidSynth instance
2961
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2962
* @param pval Location to store pitch wheel sensitivity value in semitones
2963
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2964
* @since Sometime AFTER v1.0 API freeze.
2965
*/
2966
int
2967
fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval)
2968
{
2969
int result;
2970
fluid_return_val_if_fail(pval != NULL, FLUID_FAILED);
2971
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
2972
2973
/* Allowed only on MIDI channel enabled */
2974
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
2975
2976
*pval = fluid_channel_get_pitch_wheel_sensitivity(synth->channel[chan]);
2977
result = FLUID_OK;
2978
2979
FLUID_API_RETURN(result);
2980
}
2981
2982
/**
2983
* Assign a preset to a MIDI channel.
2984
* @param synth FluidSynth instance
2985
* @param chan MIDI channel number (0 to MIDI channel count - 1)
2986
* @param preset Preset to assign to channel or NULL to clear (ownership is taken over)
2987
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
2988
*/
2989
static int
2990
fluid_synth_set_preset(fluid_synth_t *synth, int chan, fluid_preset_t *preset)
2991
{
2992
fluid_channel_t *channel;
2993
2994
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
2995
fluid_return_val_if_fail(chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
2996
2997
channel = synth->channel[chan];
2998
2999
return fluid_channel_set_preset(channel, preset);
3000
}
3001
3002
/* Get a preset by SoundFont, bank and program numbers.
3003
* Returns preset pointer or NULL.
3004
*/
3005
static fluid_preset_t *
3006
fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum,
3007
int banknum, int prognum)
3008
{
3009
fluid_sfont_t *sfont;
3010
fluid_list_t *list;
3011
3012
/* 128 indicates an "unset" operation" */
3013
if(prognum == FLUID_UNSET_PROGRAM)
3014
{
3015
return NULL;
3016
}
3017
3018
for(list = synth->sfont; list; list = fluid_list_next(list))
3019
{
3020
sfont = fluid_list_get(list);
3021
3022
if(fluid_sfont_get_id(sfont) == sfontnum)
3023
{
3024
return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
3025
}
3026
}
3027
3028
return NULL;
3029
}
3030
3031
/* Get a preset by SoundFont name, bank and program.
3032
* Returns preset pointer or NULL.
3033
*/
3034
static fluid_preset_t *
3035
fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname,
3036
int banknum, int prognum)
3037
{
3038
fluid_sfont_t *sfont;
3039
fluid_list_t *list;
3040
3041
for(list = synth->sfont; list; list = fluid_list_next(list))
3042
{
3043
sfont = fluid_list_get(list);
3044
3045
if(FLUID_STRCMP(fluid_sfont_get_name(sfont), sfontname) == 0)
3046
{
3047
return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
3048
}
3049
}
3050
3051
return NULL;
3052
}
3053
3054
/* Find a preset by bank and program numbers.
3055
* Returns preset pointer or NULL.
3056
*/
3057
fluid_preset_t *
3058
fluid_synth_find_preset(fluid_synth_t *synth, int banknum,
3059
int prognum)
3060
{
3061
fluid_preset_t *preset;
3062
fluid_sfont_t *sfont;
3063
fluid_list_t *list;
3064
3065
for(list = synth->sfont; list; list = fluid_list_next(list))
3066
{
3067
sfont = fluid_list_get(list);
3068
3069
preset = fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum);
3070
3071
if(preset)
3072
{
3073
return preset;
3074
}
3075
}
3076
3077
return NULL;
3078
}
3079
3080
/**
3081
* Send a program change event on a MIDI channel.
3082
* @param synth FluidSynth instance
3083
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3084
* @param prognum MIDI program number (0-127)
3085
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3086
*/
3087
/* As of 1.1.1 prognum can be set to 128 to unset the preset. Not documented
3088
* since fluid_synth_unset_program() should be used instead. */
3089
int
3090
fluid_synth_program_change(fluid_synth_t *synth, int chan, int prognum)
3091
{
3092
fluid_preset_t *preset = NULL;
3093
fluid_channel_t *channel;
3094
int subst_bank, subst_prog, banknum = 0, result = FLUID_FAILED;
3095
3096
fluid_return_val_if_fail(prognum >= 0 && prognum <= 128, FLUID_FAILED);
3097
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3098
3099
/* Allowed only on MIDI channel enabled */
3100
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3101
3102
channel = synth->channel[chan];
3103
3104
if(channel->channel_type == CHANNEL_TYPE_DRUM)
3105
{
3106
banknum = DRUM_INST_BANK;
3107
}
3108
else
3109
{
3110
fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL);
3111
}
3112
3113
if(synth->verbose)
3114
{
3115
FLUID_LOG(FLUID_INFO, "prog\t\t%d\t%d\t%d", chan, banknum, prognum);
3116
}
3117
3118
/* I think this is a hack for MIDI files that do bank changes in GM mode.
3119
* Proper way to handle this would probably be to ignore bank changes when in
3120
* GM mode. - JG
3121
* This is now possible by setting synth.midi-bank-select=gm, but let the hack
3122
* stay for the time being. - DH
3123
*/
3124
if(prognum != FLUID_UNSET_PROGRAM)
3125
{
3126
subst_bank = banknum;
3127
subst_prog = prognum;
3128
3129
preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
3130
3131
/* Fallback to another preset if not found */
3132
if(!preset)
3133
{
3134
/* Percussion: Fallback to preset 0 in percussion bank */
3135
if(channel->channel_type == CHANNEL_TYPE_DRUM)
3136
{
3137
subst_prog = 0;
3138
subst_bank = DRUM_INST_BANK;
3139
preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
3140
}
3141
/* Melodic instrument */
3142
else
3143
{
3144
/* Fallback first to bank 0:prognum */
3145
subst_bank = 0;
3146
preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
3147
3148
/* Fallback to first preset in bank 0 (usually piano...) */
3149
if(!preset)
3150
{
3151
subst_prog = 0;
3152
preset = fluid_synth_find_preset(synth, subst_bank, subst_prog);
3153
}
3154
}
3155
3156
if(preset)
3157
{
3158
FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
3159
chan, banknum, prognum, subst_bank, subst_prog);
3160
}
3161
else
3162
{
3163
FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]", chan, banknum, prognum);
3164
}
3165
}
3166
}
3167
3168
/* Assign the SoundFont ID and program number to the channel */
3169
fluid_channel_set_sfont_bank_prog(channel, preset ? fluid_sfont_get_id(preset->sfont) : 0,
3170
-1, prognum);
3171
result = fluid_synth_set_preset(synth, chan, preset);
3172
3173
FLUID_API_RETURN(result);
3174
}
3175
3176
/**
3177
* Set instrument bank number on a MIDI channel.
3178
* @param synth FluidSynth instance
3179
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3180
* @param bank MIDI bank number
3181
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3182
* @note This function does not change the instrument currently assigned to \c chan,
3183
* as it is usually called prior to fluid_synth_program_change(). If you still want
3184
* instrument changes to take effect immediately, call fluid_synth_program_reset()
3185
* after having set up the bank configuration.
3186
*
3187
*/
3188
int
3189
fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank)
3190
{
3191
int result;
3192
fluid_return_val_if_fail(bank <= 16383, FLUID_FAILED);
3193
fluid_return_val_if_fail(bank >= 0, FLUID_FAILED);
3194
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3195
3196
/* Allowed only on MIDI channel enabled */
3197
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3198
3199
fluid_channel_set_sfont_bank_prog(synth->channel[chan], -1, bank, -1);
3200
result = FLUID_OK;
3201
3202
FLUID_API_RETURN(result);
3203
}
3204
3205
/**
3206
* Set SoundFont ID on a MIDI channel.
3207
* @param synth FluidSynth instance
3208
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3209
* @param sfont_id ID of a loaded SoundFont
3210
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3211
* @note This function does not change the instrument currently assigned to \c chan,
3212
* as it is usually called prior to fluid_synth_bank_select() or fluid_synth_program_change().
3213
* If you still want instrument changes to take effect immediately, call fluid_synth_program_reset()
3214
* after having selected the soundfont.
3215
*/
3216
int
3217
fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id)
3218
{
3219
int result;
3220
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3221
3222
/* Allowed only on MIDI channel enabled */
3223
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3224
3225
fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1);
3226
result = FLUID_OK;
3227
3228
FLUID_API_RETURN(result);
3229
}
3230
3231
/**
3232
* Set the preset of a MIDI channel to an unassigned state.
3233
* @param synth FluidSynth instance
3234
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3235
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3236
* @since 1.1.1
3237
*
3238
* @note Channel retains its SoundFont ID and bank numbers, while the program
3239
* number is set to an "unset" state. MIDI program changes may re-assign a
3240
* preset if one matches.
3241
*/
3242
int
3243
fluid_synth_unset_program(fluid_synth_t *synth, int chan)
3244
{
3245
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3246
FLUID_API_RETURN(fluid_synth_program_change(synth, chan, FLUID_UNSET_PROGRAM));
3247
}
3248
3249
/**
3250
* Get current SoundFont ID, bank number and program number for a MIDI channel.
3251
* @param synth FluidSynth instance
3252
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3253
* @param sfont_id Location to store SoundFont ID
3254
* @param bank_num Location to store MIDI bank number
3255
* @param preset_num Location to store MIDI program number
3256
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3257
*/
3258
int
3259
fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id,
3260
int *bank_num, int *preset_num)
3261
{
3262
int result;
3263
fluid_channel_t *channel;
3264
3265
fluid_return_val_if_fail(sfont_id != NULL, FLUID_FAILED);
3266
fluid_return_val_if_fail(bank_num != NULL, FLUID_FAILED);
3267
fluid_return_val_if_fail(preset_num != NULL, FLUID_FAILED);
3268
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3269
3270
/* Allowed only on MIDI channel enabled */
3271
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3272
3273
channel = synth->channel[chan];
3274
fluid_channel_get_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
3275
3276
/* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */
3277
if(*preset_num == FLUID_UNSET_PROGRAM)
3278
{
3279
*preset_num = 0;
3280
}
3281
3282
result = FLUID_OK;
3283
3284
FLUID_API_RETURN(result);
3285
}
3286
3287
/**
3288
* Select an instrument on a MIDI channel by SoundFont ID, bank and program numbers.
3289
* @param synth FluidSynth instance
3290
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3291
* @param sfont_id ID of a loaded SoundFont
3292
* @param bank_num MIDI bank number
3293
* @param preset_num MIDI program number
3294
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3295
*/
3296
int
3297
fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
3298
int bank_num, int preset_num)
3299
{
3300
fluid_preset_t *preset = NULL;
3301
fluid_channel_t *channel;
3302
int result;
3303
fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
3304
fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
3305
3306
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3307
3308
/* Allowed only on MIDI channel enabled */
3309
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3310
3311
channel = synth->channel[chan];
3312
3313
preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
3314
3315
if(preset == NULL)
3316
{
3317
FLUID_LOG(FLUID_ERR,
3318
"There is no preset with bank number %d and preset number %d in SoundFont %d",
3319
bank_num, preset_num, sfont_id);
3320
FLUID_API_RETURN(FLUID_FAILED);
3321
}
3322
3323
/* Assign the new SoundFont ID, bank and program number to the channel */
3324
fluid_channel_set_sfont_bank_prog(channel, sfont_id, bank_num, preset_num);
3325
result = fluid_synth_set_preset(synth, chan, preset);
3326
3327
FLUID_API_RETURN(result);
3328
}
3329
3330
/**
3331
* Pins all samples of the given preset.
3332
*
3333
* @param synth FluidSynth instance
3334
* @param sfont_id ID of a loaded SoundFont
3335
* @param bank_num MIDI bank number
3336
* @param preset_num MIDI program number
3337
* @return #FLUID_OK if the preset was found, pinned and loaded
3338
* into memory successfully. #FLUID_FAILED otherwise. Note that #FLUID_OK
3339
* is returned, even if <code>synth.dynamic-sample-loading</code> is disabled or
3340
* the preset doesn't support dynamic-sample-loading.
3341
*
3342
* This function will attempt to pin all samples of the given preset and
3343
* load them into memory, if they are currently unloaded. "To pin" in this
3344
* context means preventing them from being unloaded by an upcoming channel
3345
* prog change.
3346
*
3347
* @note This function is only useful if \ref settings_synth_dynamic-sample-loading is enabled.
3348
* By default, dynamic-sample-loading is disabled and all samples are kept in memory.
3349
* Furthermore, this is only useful for presets which support dynamic-sample-loading (currently,
3350
* only preset loaded with the default soundfont loader do).
3351
*
3352
* @since 2.2.0
3353
*/
3354
int
3355
fluid_synth_pin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num)
3356
{
3357
int ret;
3358
fluid_preset_t *preset;
3359
3360
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3361
fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
3362
fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
3363
3364
fluid_synth_api_enter(synth);
3365
3366
preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
3367
3368
if(preset == NULL)
3369
{
3370
FLUID_LOG(FLUID_ERR,
3371
"There is no preset with bank number %d and preset number %d in SoundFont %d",
3372
bank_num, preset_num, sfont_id);
3373
FLUID_API_RETURN(FLUID_FAILED);
3374
}
3375
3376
ret = fluid_preset_notify(preset, FLUID_PRESET_PIN, -1); // channel unused for pinning messages
3377
3378
FLUID_API_RETURN(ret);
3379
}
3380
3381
/**
3382
* Unpin all samples of the given preset.
3383
*
3384
* @param synth FluidSynth instance
3385
* @param sfont_id ID of a loaded SoundFont
3386
* @param bank_num MIDI bank number
3387
* @param preset_num MIDI program number
3388
* @return #FLUID_OK if preset was found, #FLUID_FAILED otherwise
3389
*
3390
* This function undoes the effect of fluid_synth_pin_preset(). If the preset is
3391
* not currently used, its samples will be unloaded.
3392
*
3393
* @note Only useful for presets loaded with the default soundfont loader and
3394
* only if \ref settings_synth_dynamic-sample-loading is enabled.
3395
*
3396
* @since 2.2.0
3397
*/
3398
int
3399
fluid_synth_unpin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num)
3400
{
3401
int ret;
3402
fluid_preset_t *preset;
3403
3404
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3405
fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED);
3406
fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED);
3407
3408
fluid_synth_api_enter(synth);
3409
3410
preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
3411
3412
if(preset == NULL)
3413
{
3414
FLUID_LOG(FLUID_ERR,
3415
"There is no preset with bank number %d and preset number %d in SoundFont %d",
3416
bank_num, preset_num, sfont_id);
3417
FLUID_API_RETURN(FLUID_FAILED);
3418
}
3419
3420
ret = fluid_preset_notify(preset, FLUID_PRESET_UNPIN, -1); // channel unused for pinning messages
3421
3422
FLUID_API_RETURN(ret);
3423
}
3424
3425
/**
3426
* Select an instrument on a MIDI channel by SoundFont name, bank and program numbers.
3427
* @param synth FluidSynth instance
3428
* @param chan MIDI channel number (0 to MIDI channel count - 1)
3429
* @param sfont_name Name of a loaded SoundFont
3430
* @param bank_num MIDI bank number
3431
* @param preset_num MIDI program number
3432
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3433
* @since 1.1.0
3434
*/
3435
int
3436
fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan,
3437
const char *sfont_name, int bank_num,
3438
int preset_num)
3439
{
3440
fluid_preset_t *preset = NULL;
3441
fluid_channel_t *channel;
3442
int result;
3443
fluid_return_val_if_fail(sfont_name != NULL, FLUID_FAILED);
3444
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
3445
3446
/* Allowed only on MIDI channel enabled */
3447
FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED);
3448
3449
channel = synth->channel[chan];
3450
3451
preset = fluid_synth_get_preset_by_sfont_name(synth, sfont_name, bank_num,
3452
preset_num);
3453
3454
if(preset == NULL)
3455
{
3456
FLUID_LOG(FLUID_ERR,
3457
"There is no preset with bank number %d and preset number %d in SoundFont %s",
3458
bank_num, preset_num, sfont_name);
3459
FLUID_API_RETURN(FLUID_FAILED);
3460
}
3461
3462
/* Assign the new SoundFont ID, bank and program number to the channel */
3463
fluid_channel_set_sfont_bank_prog(channel, fluid_sfont_get_id(preset->sfont),
3464
bank_num, preset_num);
3465
result = fluid_synth_set_preset(synth, chan, preset);
3466
3467
FLUID_API_RETURN(result);
3468
}
3469
3470
/*
3471
* This function assures that every MIDI channel has a valid preset
3472
* (NULL is okay). This function is called after a SoundFont is
3473
* unloaded or reloaded.
3474
*/
3475
static void
3476
fluid_synth_update_presets(fluid_synth_t *synth)
3477
{
3478
fluid_channel_t *channel;
3479
fluid_preset_t *preset;
3480
int sfont, bank, prog;
3481
int chan;
3482
3483
for(chan = 0; chan < synth->midi_channels; chan++)
3484
{
3485
channel = synth->channel[chan];
3486
fluid_channel_get_sfont_bank_prog(channel, &sfont, &bank, &prog);
3487
preset = fluid_synth_get_preset(synth, sfont, bank, prog);
3488
fluid_synth_set_preset(synth, chan, preset);
3489
}
3490
}
3491
3492
static void
3493
fluid_synth_set_sample_rate_LOCAL(fluid_synth_t *synth, float sample_rate)
3494
{
3495
int i;
3496
fluid_clip(sample_rate, 8000.0f, 96000.0f);
3497
synth->sample_rate = sample_rate;
3498
3499
synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
3500
3501
for(i = 0; i < synth->polyphony; i++)
3502
{
3503
fluid_voice_set_output_rate(synth->voice[i], sample_rate);
3504
}
3505
}
3506
3507
/**
3508
* Set up an event to change the sample-rate of the synth during the next rendering call.
3509
* @warning This function is broken-by-design! Don't use it! Instead, specify the sample-rate when creating the synth.
3510
* @deprecated As of fluidsynth 2.1.0 this function has been deprecated.
3511
* Changing the sample-rate is generally not considered to be a real-time use-case, as it always produces some audible artifact ("click", "pop") on the dry sound and effects (because LFOs for chorus and reverb need to be reinitialized).
3512
* The sample-rate change may also require memory allocation deep down in the effect units.
3513
* However, this memory allocation may fail and there is no way for the caller to know that, because the actual change of the sample-rate is executed during rendering.
3514
* This function cannot (must not) do the sample-rate change itself, otherwise the synth needs to be locked down, causing rendering to block.
3515
* Esp. do not use this function if this @p synth instance is used by an audio driver, because the audio driver cannot be notified by this sample-rate change.
3516
* Long story short: don't use it.
3517
* @code{.cpp}
3518
fluid_synth_t* synth; // assume initialized
3519
// [...]
3520
// sample-rate change needed? Delete the audio driver, if any.
3521
delete_fluid_audio_driver(adriver);
3522
// then delete the synth
3523
delete_fluid_synth(synth);
3524
// update the sample-rate
3525
fluid_settings_setnum(settings, "synth.sample-rate", 22050.0);
3526
// and re-create objects
3527
synth = new_fluid_synth(settings);
3528
adriver = new_fluid_audio_driver(settings, synth);
3529
* @endcode
3530
* @param synth FluidSynth instance
3531
* @param sample_rate New sample-rate (Hz)
3532
* @since 1.1.2
3533
*/
3534
void
3535
fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate)
3536
{
3537
fluid_return_if_fail(synth != NULL);
3538
fluid_synth_api_enter(synth);
3539
3540
fluid_synth_set_sample_rate_LOCAL(synth, sample_rate);
3541
3542
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate,
3543
0, synth->sample_rate);
3544
fluid_synth_api_exit(synth);
3545
}
3546
3547
// internal sample rate change function for the jack driver
3548
// executes immediately, therefore, make sure no rendering call is running!
3549
void
3550
fluid_synth_set_sample_rate_immediately(fluid_synth_t *synth, float sample_rate)
3551
{
3552
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
3553
fluid_return_if_fail(synth != NULL);
3554
fluid_synth_api_enter(synth);
3555
3556
fluid_synth_set_sample_rate_LOCAL(synth, sample_rate);
3557
3558
param[0].i = 0;
3559
param[1].real = synth->sample_rate;
3560
fluid_rvoice_mixer_set_samplerate(synth->eventhandler->mixer, param);
3561
3562
fluid_synth_api_exit(synth);
3563
}
3564
3565
3566
/* Handler for synth.gain setting. */
3567
static void
3568
fluid_synth_handle_gain(void *data, const char *name, double value)
3569
{
3570
fluid_synth_t *synth = (fluid_synth_t *)data;
3571
fluid_synth_set_gain(synth, (float) value);
3572
}
3573
3574
/**
3575
* Set synth output gain value.
3576
* @param synth FluidSynth instance
3577
* @param gain Gain value (function clamps value to the range 0.0 to 10.0)
3578
*/
3579
void
3580
fluid_synth_set_gain(fluid_synth_t *synth, float gain)
3581
{
3582
fluid_return_if_fail(synth != NULL);
3583
fluid_synth_api_enter(synth);
3584
3585
fluid_clip(gain, 0.0f, 10.0f);
3586
3587
synth->gain = gain;
3588
fluid_synth_update_gain_LOCAL(synth);
3589
fluid_synth_api_exit(synth);
3590
}
3591
3592
/* Called by synthesis thread to update the gain in all voices */
3593
static void
3594
fluid_synth_update_gain_LOCAL(fluid_synth_t *synth)
3595
{
3596
fluid_voice_t *voice;
3597
float gain;
3598
int i;
3599
3600
gain = synth->gain;
3601
3602
for(i = 0; i < synth->polyphony; i++)
3603
{
3604
voice = synth->voice[i];
3605
3606
if(fluid_voice_is_playing(voice))
3607
{
3608
fluid_voice_set_gain(voice, gain);
3609
}
3610
}
3611
}
3612
3613
/**
3614
* Get synth output gain value.
3615
* @param synth FluidSynth instance
3616
* @return Synth gain value (0.0 to 10.0)
3617
*/
3618
float
3619
fluid_synth_get_gain(fluid_synth_t *synth)
3620
{
3621
float result;
3622
fluid_return_val_if_fail(synth != NULL, 0.0);
3623
fluid_synth_api_enter(synth);
3624
3625
result = synth->gain;
3626
FLUID_API_RETURN(result);
3627
}
3628
3629
/*
3630
* Handler for synth.polyphony setting.
3631
*/
3632
static void
3633
fluid_synth_handle_polyphony(void *data, const char *name, int value)
3634
{
3635
fluid_synth_t *synth = (fluid_synth_t *)data;
3636
fluid_synth_set_polyphony(synth, value);
3637
}
3638
3639
/**
3640
* Set synthesizer polyphony (max number of voices).
3641
* @param synth FluidSynth instance
3642
* @param polyphony Polyphony to assign
3643
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3644
* @since 1.0.6
3645
*/
3646
int
3647
fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony)
3648
{
3649
int result;
3650
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3651
fluid_return_val_if_fail(polyphony >= 1 && polyphony <= 65535, FLUID_FAILED);
3652
fluid_synth_api_enter(synth);
3653
3654
result = fluid_synth_update_polyphony_LOCAL(synth, polyphony);
3655
3656
FLUID_API_RETURN(result);
3657
}
3658
3659
/* Called by synthesis thread to update the polyphony value */
3660
static int
3661
fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony)
3662
{
3663
fluid_voice_t *voice;
3664
int i;
3665
3666
if(new_polyphony > synth->nvoice)
3667
{
3668
/* Create more voices */
3669
fluid_voice_t **new_voices = FLUID_REALLOC(synth->voice,
3670
sizeof(fluid_voice_t *) * new_polyphony);
3671
3672
if(new_voices == NULL)
3673
{
3674
return FLUID_FAILED;
3675
}
3676
3677
synth->voice = new_voices;
3678
3679
for(i = synth->nvoice; i < new_polyphony; i++)
3680
{
3681
synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
3682
3683
if(synth->voice[i] == NULL)
3684
{
3685
return FLUID_FAILED;
3686
}
3687
3688
fluid_voice_set_custom_filter(synth->voice[i], synth->custom_filter_type, synth->custom_filter_flags);
3689
}
3690
3691
synth->nvoice = new_polyphony;
3692
}
3693
3694
synth->polyphony = new_polyphony;
3695
3696
/* turn off any voices above the new limit */
3697
for(i = synth->polyphony; i < synth->nvoice; i++)
3698
{
3699
voice = synth->voice[i];
3700
3701
if(fluid_voice_is_playing(voice))
3702
{
3703
fluid_voice_off(voice);
3704
}
3705
}
3706
3707
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
3708
synth->polyphony, 0.0f);
3709
3710
return FLUID_OK;
3711
}
3712
3713
/**
3714
* Get current synthesizer polyphony (max number of voices).
3715
* @param synth FluidSynth instance
3716
* @return Synth polyphony value.
3717
* @since 1.0.6
3718
*/
3719
int
3720
fluid_synth_get_polyphony(fluid_synth_t *synth)
3721
{
3722
int result;
3723
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3724
fluid_synth_api_enter(synth);
3725
3726
result = synth->polyphony;
3727
FLUID_API_RETURN(result);
3728
}
3729
3730
/**
3731
* @brief Get current number of active voices.
3732
*
3733
* I.e. the no. of voices that have been
3734
* started and have not yet finished. Unless called from synthesis context,
3735
* this number does not necessarily have to be equal to the number of voices
3736
* currently processed by the DSP loop, see below.
3737
* @param synth FluidSynth instance
3738
* @return Number of currently active voices.
3739
* @since 1.1.0
3740
*
3741
* @note To generate accurate continuous statistics of the voice count, caller
3742
* should ensure this function is called synchronously with the audio synthesis
3743
* process. This can be done in the new_fluid_audio_driver2() audio callback
3744
* function for example. Otherwise every call to this function may return different
3745
* voice counts as it may change after any (concurrent) call to fluid_synth_write_*() made by
3746
* e.g. an audio driver or the applications audio rendering thread.
3747
*/
3748
int
3749
fluid_synth_get_active_voice_count(fluid_synth_t *synth)
3750
{
3751
int result;
3752
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3753
fluid_synth_api_enter(synth);
3754
3755
result = synth->active_voice_count;
3756
FLUID_API_RETURN(result);
3757
}
3758
3759
/**
3760
* Get the internal synthesis buffer size value.
3761
* @param synth FluidSynth instance
3762
* @return Internal buffer size in audio frames.
3763
*
3764
* Audio is synthesized at this number of frames at a time. Defaults to 64 frames. I.e. the synth can only react to notes,
3765
* control changes, and other audio affecting events after having processed 64 audio frames.
3766
*/
3767
int
3768
fluid_synth_get_internal_bufsize(fluid_synth_t *synth)
3769
{
3770
return FLUID_BUFSIZE;
3771
}
3772
3773
/**
3774
* Resend a bank select and a program change for every channel and assign corresponding instruments.
3775
* @param synth FluidSynth instance
3776
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3777
*
3778
* This function is called mainly after a SoundFont has been loaded,
3779
* unloaded or reloaded.
3780
*/
3781
int
3782
fluid_synth_program_reset(fluid_synth_t *synth)
3783
{
3784
int i, prog;
3785
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3786
fluid_synth_api_enter(synth);
3787
3788
/* try to set the correct presets */
3789
for(i = 0; i < synth->midi_channels; i++)
3790
{
3791
fluid_channel_get_sfont_bank_prog(synth->channel[i], NULL, NULL, &prog);
3792
fluid_synth_program_change(synth, i, prog);
3793
}
3794
3795
FLUID_API_RETURN(FLUID_OK);
3796
}
3797
3798
/**
3799
* Synthesize a block of floating point audio to separate audio buffers (multi-channel rendering).
3800
*
3801
* @param synth FluidSynth instance
3802
* @param len Count of audio frames to synthesize
3803
* @param left Array of float buffers to store left channel of planar audio (as many as \c synth.audio-channels buffers, each of \c len in size)
3804
* @param right Array of float buffers to store right channel of planar audio (size: dito)
3805
* @param fx_left Since 1.1.7: If not \c NULL, array of float buffers to store left effect channels (as many as \c synth.effects-channels buffers, each of \c len in size)
3806
* @param fx_right Since 1.1.7: If not \c NULL, array of float buffers to store right effect channels (size: dito)
3807
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
3808
*
3809
* First effect channel used by reverb, second for chorus.
3810
*
3811
* @note Should only be called from synthesis thread.
3812
*
3813
* @deprecated fluid_synth_nwrite_float() is deprecated and will be removed in a future release.
3814
* It may continue to work or it may return #FLUID_FAILED in the future. Consider using the more
3815
* powerful and flexible fluid_synth_process().
3816
*
3817
* Usage example:
3818
* @code{.cpp}
3819
const int FramesToRender = 64;
3820
int channels;
3821
// retrieve number of stereo audio channels
3822
fluid_settings_getint(settings, "synth.audio-channels", &channels);
3823
3824
// we need twice as many (mono-)buffers
3825
channels *= 2;
3826
3827
// fluid_synth_nwrite_float renders planar audio, e.g. if synth.audio-channels==16:
3828
// each midi channel gets rendered to its own stereo buffer, rather than having
3829
// one buffer and interleaved PCM
3830
float** mix_buf = new float*[channels];
3831
for(int i = 0; i < channels; i++)
3832
{
3833
mix_buf[i] = new float[FramesToRender];
3834
}
3835
3836
// retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan)
3837
// and chrous (second chan))
3838
fluid_settings_getint(settings, "synth.effects-channels", &channels);
3839
channels *= 2;
3840
3841
float** fx_buf = new float*[channels];
3842
for(int i = 0; i < channels; i++)
3843
{
3844
fx_buf[i] = new float[FramesToRender];
3845
}
3846
3847
float** mix_buf_l = mix_buf;
3848
float** mix_buf_r = &mix_buf[channels/2];
3849
3850
float** fx_buf_l = fx_buf;
3851
float** fx_buf_r = &fx_buf[channels/2];
3852
3853
fluid_synth_nwrite_float(synth, FramesToRender, mix_buf_l, mix_buf_r, fx_buf_l, fx_buf_r)
3854
* @endcode
3855
*/
3856
int
3857
fluid_synth_nwrite_float(fluid_synth_t *synth, int len,
3858
float **left, float **right,
3859
float **fx_left, float **fx_right)
3860
{
3861
fluid_real_t *left_in, *fx_left_in;
3862
fluid_real_t *right_in, *fx_right_in;
3863
double time = fluid_utime();
3864
int i, num, available, count;
3865
#ifdef WITH_FLOAT
3866
int bytes;
3867
#endif
3868
float cpu_load;
3869
3870
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
3871
fluid_return_val_if_fail(left != NULL, FLUID_FAILED);
3872
fluid_return_val_if_fail(right != NULL, FLUID_FAILED);
3873
fluid_return_val_if_fail(len >= 0, FLUID_FAILED);
3874
fluid_return_val_if_fail(len != 0, FLUID_OK); // to avoid raising FE_DIVBYZERO below
3875
3876
/* First, take what's still available in the buffer */
3877
count = 0;
3878
num = synth->cur;
3879
3880
if(synth->cur < FLUID_BUFSIZE)
3881
{
3882
available = FLUID_BUFSIZE - synth->cur;
3883
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3884
fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3885
3886
num = (available > len) ? len : available;
3887
#ifdef WITH_FLOAT
3888
bytes = num * sizeof(float);
3889
#endif
3890
3891
for(i = 0; i < synth->audio_channels; i++)
3892
{
3893
#ifdef WITH_FLOAT
3894
FLUID_MEMCPY(left[i], &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3895
FLUID_MEMCPY(right[i], &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3896
#else //WITH_FLOAT
3897
int j;
3898
3899
for(j = 0; j < num; j++)
3900
{
3901
left[i][j] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3902
right[i][j] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3903
}
3904
3905
#endif //WITH_FLOAT
3906
}
3907
3908
for(i = 0; i < synth->effects_channels; i++)
3909
{
3910
#ifdef WITH_FLOAT
3911
3912
if(fx_left != NULL)
3913
{
3914
FLUID_MEMCPY(fx_left[i], &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3915
}
3916
3917
if(fx_right != NULL)
3918
{
3919
FLUID_MEMCPY(fx_right[i], &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes);
3920
}
3921
3922
#else //WITH_FLOAT
3923
int j;
3924
3925
if(fx_left != NULL)
3926
{
3927
for(j = 0; j < num; j++)
3928
{
3929
fx_left[i][j] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3930
}
3931
}
3932
3933
if(fx_right != NULL)
3934
{
3935
for(j = 0; j < num; j++)
3936
{
3937
fx_right[i][j] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur];
3938
}
3939
}
3940
3941
#endif //WITH_FLOAT
3942
}
3943
3944
count += num;
3945
num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
3946
}
3947
3948
/* Then, run one_block() and copy till we have 'len' samples */
3949
while(count < len)
3950
{
3951
fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0);
3952
fluid_synth_render_blocks(synth, 1); // TODO:
3953
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
3954
fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
3955
3956
num = (FLUID_BUFSIZE > len - count) ? len - count : FLUID_BUFSIZE;
3957
#ifdef WITH_FLOAT
3958
bytes = num * sizeof(float);
3959
#endif
3960
3961
for(i = 0; i < synth->audio_channels; i++)
3962
{
3963
#ifdef WITH_FLOAT
3964
FLUID_MEMCPY(left[i] + count, &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3965
FLUID_MEMCPY(right[i] + count, &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3966
#else //WITH_FLOAT
3967
int j;
3968
3969
for(j = 0; j < num; j++)
3970
{
3971
left[i][j + count] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3972
right[i][j + count] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
3973
}
3974
3975
#endif //WITH_FLOAT
3976
}
3977
3978
for(i = 0; i < synth->effects_channels; i++)
3979
{
3980
#ifdef WITH_FLOAT
3981
3982
if(fx_left != NULL)
3983
{
3984
FLUID_MEMCPY(fx_left[i] + count, &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3985
}
3986
3987
if(fx_right != NULL)
3988
{
3989
FLUID_MEMCPY(fx_right[i] + count, &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes);
3990
}
3991
3992
#else //WITH_FLOAT
3993
int j;
3994
3995
if(fx_left != NULL)
3996
{
3997
for(j = 0; j < num; j++)
3998
{
3999
fx_left[i][j + count] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
4000
}
4001
}
4002
4003
if(fx_right != NULL)
4004
{
4005
for(j = 0; j < num; j++)
4006
{
4007
fx_right[i][j + count] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j];
4008
}
4009
}
4010
4011
#endif //WITH_FLOAT
4012
}
4013
4014
count += num;
4015
}
4016
4017
synth->cur = num;
4018
4019
time = fluid_utime() - time;
4020
cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
4021
fluid_atomic_float_set(&synth->cpu_load, cpu_load);
4022
4023
return FLUID_OK;
4024
}
4025
4026
/**
4027
* mixes the samples of \p in to \p out
4028
*
4029
* @param out the output sample buffer to mix to
4030
* @param ooff sample offset in \p out
4031
* @param in the rvoice_mixer input sample buffer to mix from
4032
* @param ioff sample offset in \p in
4033
* @param buf_idx the sample buffer index of \p in to mix from
4034
* @param num number of samples to mix
4035
*/
4036
static FLUID_INLINE void fluid_synth_mix_single_buffer(float *FLUID_RESTRICT out,
4037
int ooff,
4038
const fluid_real_t *FLUID_RESTRICT in,
4039
int ioff,
4040
int buf_idx,
4041
int num)
4042
{
4043
if(out != NULL)
4044
{
4045
int j;
4046
4047
for(j = 0; j < num; j++)
4048
{
4049
out[j + ooff] += (float) in[buf_idx * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + ioff];
4050
}
4051
}
4052
}
4053
4054
/**
4055
* Synthesize floating point audio to stereo audio channels
4056
* (implements the default interface #fluid_audio_func_t).
4057
*
4058
* @param synth FluidSynth instance
4059
*
4060
* @param len Count of audio frames to synthesize and store in every single buffer provided by \p out and \p fx.
4061
* Zero value is permitted, the function does nothing and return FLUID_OK.
4062
*
4063
* @param nfx Count of arrays in \c fx. Must be a multiple of 2 (because of stereo)
4064
* and in the range <code>0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
4065
* Note that zero value is valid and allows to skip mixing effects in all fx output buffers.
4066
*
4067
* @param fx Array of buffers to store effects audio to. Buffers may
4068
* alias with buffers of \c out. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
4069
*
4070
* @param nout Count of arrays in \c out. Must be a multiple of 2
4071
* (because of stereo) and in the range <code>0 <= nout/2 <= fluid_synth_count_audio_channels()</code>.
4072
* Note that zero value is valid and allows to skip mixing dry audio in all out output buffers.
4073
*
4074
* @param out Array of buffers to store (dry) audio to. Buffers may
4075
* alias with buffers of \c fx. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
4076
*
4077
* @return #FLUID_OK on success,
4078
* #FLUID_FAILED otherwise,
4079
* - <code>fx == NULL</code> while <code>nfx > 0</code>, or <code>out == NULL</code> while <code>nout > 0</code>.
4080
* - \c nfx or \c nout not multiple of 2.
4081
* - <code>len < 0</code>.
4082
* - \c nfx or \c nout exceed the range explained above.
4083
*
4084
* Synthesize and <strong>mix</strong> audio to a given number of planar audio buffers.
4085
* Therefore pass <code>nout = N*2</code> float buffers to \p out in order to render
4086
* the synthesized audio to \p N stereo channels. Each float buffer must be
4087
* able to hold \p len elements.
4088
*
4089
* \p out contains an array of planar buffers for normal, dry, stereo
4090
* audio (alternating left and right). Like:
4091
@code{.cpp}
4092
out[0] = left_buffer_audio_channel_0
4093
out[1] = right_buffer_audio_channel_0
4094
out[2] = left_buffer_audio_channel_1
4095
out[3] = right_buffer_audio_channel_1
4096
...
4097
out[ (i * 2 + 0) % nout ] = left_buffer_audio_channel_i
4098
out[ (i * 2 + 1) % nout ] = right_buffer_audio_channel_i
4099
@endcode
4100
*
4101
* for zero-based channel index \p i.
4102
* The buffer layout of \p fx used for storing effects
4103
* like reverb and chorus looks similar:
4104
@code{.cpp}
4105
fx[0] = left_buffer_channel_of_reverb_unit_0
4106
fx[1] = right_buffer_channel_of_reverb_unit_0
4107
fx[2] = left_buffer_channel_of_chorus_unit_0
4108
fx[3] = right_buffer_channel_of_chorus_unit_0
4109
fx[4] = left_buffer_channel_of_reverb_unit_1
4110
fx[5] = right_buffer_channel_of_reverb_unit_1
4111
fx[6] = left_buffer_channel_of_chorus_unit_1
4112
fx[7] = right_buffer_channel_of_chorus_unit_1
4113
fx[8] = left_buffer_channel_of_reverb_unit_2
4114
...
4115
fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 0) % nfx ] = left_buffer_for_effect_channel_j_of_unit_k
4116
fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 1) % nfx ] = right_buffer_for_effect_channel_j_of_unit_k
4117
@endcode
4118
* where <code>0 <= k < fluid_synth_count_effects_groups()</code> is a zero-based index denoting the effects unit and
4119
* <code>0 <= j < fluid_synth_count_effects_channels()</code> is a zero-based index denoting the effect channel within
4120
* unit \p k.
4121
*
4122
* Any playing voice is assigned to audio channels based on the MIDI channel it's playing on: Let \p chan be the
4123
* zero-based MIDI channel index an arbitrary voice is playing on. To determine the audio channel and effects unit it is
4124
* going to be rendered to use:
4125
*
4126
* <code>i = chan % fluid_synth_count_audio_groups()</code>
4127
*
4128
* <code>k = chan % fluid_synth_count_effects_groups()</code>
4129
*
4130
* @parblock
4131
* @note The owner of the sample buffers must zero them out before calling this
4132
* function, because any synthesized audio is mixed (i.e. added) to the buffers.
4133
* E.g. if fluid_synth_process() is called from a custom audio driver process function
4134
* (see new_fluid_audio_driver2()), the audio driver takes care of zeroing the buffers.
4135
* @endparblock
4136
*
4137
* @parblock
4138
* @note No matter how many buffers you pass in, fluid_synth_process()
4139
* will always render all audio channels to the
4140
* buffers in \c out and all effects channels to the
4141
* buffers in \c fx, provided that <code>nout > 0</code> and <code>nfx > 0</code> respectively. If
4142
* <code>nout/2 < fluid_synth_count_audio_channels()</code> it will wrap around. Same
4143
* is true for effects audio if <code>nfx/2 < (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups())</code>.
4144
* See usage examples below.
4145
* @endparblock
4146
*
4147
* @parblock
4148
* @note Should only be called from synthesis thread.
4149
* @endparblock
4150
*/
4151
int
4152
fluid_synth_process(fluid_synth_t *synth, int len, int nfx, float *fx[],
4153
int nout, float *out[])
4154
{
4155
return fluid_synth_process_LOCAL(synth, len, nfx, fx, nout, out, fluid_synth_render_blocks);
4156
}
4157
4158
/* declared public (instead of static) for testing purpose */
4159
int
4160
fluid_synth_process_LOCAL(fluid_synth_t *synth, int len, int nfx, float *fx[],
4161
int nout, float *out[], int (*block_render_func)(fluid_synth_t *, int))
4162
{
4163
fluid_real_t *left_in, *fx_left_in;
4164
fluid_real_t *right_in, *fx_right_in;
4165
int nfxchan, nfxunits, naudchan;
4166
4167
double time = fluid_utime();
4168
int i, f, num, count, buffered_blocks;
4169
4170
float cpu_load;
4171
4172
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4173
4174
/* fx NULL while nfx > 0 is invalid */
4175
fluid_return_val_if_fail((fx != NULL) || (nfx == 0), FLUID_FAILED);
4176
/* nfx must be multiple of 2. Note that 0 value is valid and
4177
allows to skip mixing in fx output buffers
4178
*/
4179
fluid_return_val_if_fail(nfx % 2 == 0, FLUID_FAILED);
4180
4181
/* out NULL while nout > 0 is invalid */
4182
fluid_return_val_if_fail((out != NULL) || (nout == 0), FLUID_FAILED);
4183
/* nout must be multiple of 2. Note that 0 value is valid and
4184
allows to skip mixing in out output buffers
4185
*/
4186
fluid_return_val_if_fail(nout % 2 == 0, FLUID_FAILED);
4187
4188
/* check len value. Note that 0 value is valid, the function does nothing and returns FLUID_OK.
4189
*/
4190
fluid_return_val_if_fail(len >= 0, FLUID_FAILED);
4191
fluid_return_val_if_fail(len != 0, FLUID_OK); // to avoid raising FE_DIVBYZERO below
4192
4193
nfxchan = synth->effects_channels;
4194
nfxunits = synth->effects_groups;
4195
naudchan = synth->audio_channels;
4196
4197
fluid_return_val_if_fail(0 <= nfx / 2 && nfx / 2 <= nfxchan * nfxunits, FLUID_FAILED);
4198
fluid_return_val_if_fail(0 <= nout / 2 && nout / 2 <= naudchan, FLUID_FAILED);
4199
4200
/* get internal mixer audio dry buffer's pointer (left and right channel) */
4201
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
4202
/* get internal mixer audio effect buffer's pointer (left and right channel) */
4203
fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
4204
4205
/* Conversely to fluid_synth_write_float(),fluid_synth_write_s16() (which handle only one
4206
stereo output) we don't want rendered audio effect mixed in internal audio dry buffers.
4207
FALSE instructs the mixer that internal audio effects will be mixed in respective internal
4208
audio effects buffers.
4209
*/
4210
fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, FALSE);
4211
4212
4213
/* First, take what's still available in the buffer */
4214
count = 0;
4215
/* synth->cur indicates if available samples are still in internal mixer buffer */
4216
num = synth->cur;
4217
4218
buffered_blocks = (synth->cur + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
4219
if(synth->cur < buffered_blocks * FLUID_BUFSIZE)
4220
{
4221
/* yes, available sample are in internal mixer buffer */
4222
int available = (buffered_blocks * FLUID_BUFSIZE) - synth->cur;
4223
num = (available > len) ? len : available;
4224
4225
/* mixing dry samples (or skip if requested by the caller) */
4226
if(nout != 0)
4227
{
4228
for(i = 0; i < naudchan; i++)
4229
{
4230
/* mix num left samples from input mixer buffer (left_in) at input offset
4231
synth->cur to output buffer (out_buf) at offset 0 */
4232
float *out_buf = out[(i * 2) % nout];
4233
fluid_synth_mix_single_buffer(out_buf, 0, left_in, synth->cur, i, num);
4234
4235
/* mix num right samples from input mixer buffer (right_in) at input offset
4236
synth->cur to output buffer (out_buf) at offset 0 */
4237
out_buf = out[(i * 2 + 1) % nout];
4238
fluid_synth_mix_single_buffer(out_buf, 0, right_in, synth->cur, i, num);
4239
}
4240
}
4241
4242
/* mixing effects samples (or skip if requested by the caller) */
4243
if(nfx != 0)
4244
{
4245
// loop over all effects units
4246
for(f = 0; f < nfxunits; f++)
4247
{
4248
// write out all effects (i.e. reverb and chorus)
4249
for(i = 0; i < nfxchan; i++)
4250
{
4251
int buf_idx = f * nfxchan + i;
4252
4253
/* mix num left samples from input mixer buffer (fx_left_in) at input offset
4254
synth->cur to output buffer (out_buf) at offset 0 */
4255
float *out_buf = fx[(buf_idx * 2) % nfx];
4256
fluid_synth_mix_single_buffer(out_buf, 0, fx_left_in, synth->cur, buf_idx, num);
4257
4258
/* mix num right samples from input mixer buffer (fx_right_in) at input offset
4259
synth->cur to output buffer (out_buf) at offset 0 */
4260
out_buf = fx[(buf_idx * 2 + 1) % nfx];
4261
fluid_synth_mix_single_buffer(out_buf, 0, fx_right_in, synth->cur, buf_idx, num);
4262
}
4263
}
4264
}
4265
4266
count += num;
4267
num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
4268
}
4269
4270
/* Then, render blocks and copy till we have 'len' samples */
4271
while(count < len)
4272
{
4273
/* always render full bloc multiple of FLUID_BUFSIZE */
4274
int blocksleft = (len - count + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
4275
/* render audio (dry and effect) to respective internal dry and effect buffers */
4276
int blockcount = block_render_func(synth, blocksleft);
4277
4278
num = (blockcount * FLUID_BUFSIZE > len - count) ? len - count : blockcount * FLUID_BUFSIZE;
4279
4280
/* mixing dry samples (or skip if requested by the caller) */
4281
if(nout != 0)
4282
{
4283
for(i = 0; i < naudchan; i++)
4284
{
4285
/* mix num left samples from input mixer buffer (left_in) at input offset
4286
0 to output buffer (out_buf) at offset count */
4287
float *out_buf = out[(i * 2) % nout];
4288
fluid_synth_mix_single_buffer(out_buf, count, left_in, 0, i, num);
4289
4290
/* mix num right samples from input mixer buffer (right_in) at input offset
4291
0 to output buffer (out_buf) at offset count */
4292
out_buf = out[(i * 2 + 1) % nout];
4293
fluid_synth_mix_single_buffer(out_buf, count, right_in, 0, i, num);
4294
}
4295
}
4296
4297
/* mixing effects samples (or skip if requested by the caller) */
4298
if(nfx != 0)
4299
{
4300
// loop over all effects units
4301
for(f = 0; f < nfxunits; f++)
4302
{
4303
// write out all effects (i.e. reverb and chorus)
4304
for(i = 0; i < nfxchan; i++)
4305
{
4306
int buf_idx = f * nfxchan + i;
4307
4308
/* mix num left samples from input mixer buffer (fx_left_in) at input offset
4309
0 to output buffer (out_buf) at offset count */
4310
float *out_buf = fx[(buf_idx * 2) % nfx];
4311
fluid_synth_mix_single_buffer(out_buf, count, fx_left_in, 0, buf_idx, num);
4312
4313
/* mix num right samples from input mixer buffer (fx_right_in) at input offset
4314
0 to output buffer (out_buf) at offset count */
4315
out_buf = fx[(buf_idx * 2 + 1) % nfx];
4316
fluid_synth_mix_single_buffer(out_buf, count, fx_right_in, 0, buf_idx, num);
4317
}
4318
}
4319
}
4320
4321
count += num;
4322
}
4323
4324
synth->cur = num;
4325
4326
time = fluid_utime() - time;
4327
cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
4328
fluid_atomic_float_set(&synth->cpu_load, cpu_load);
4329
4330
return FLUID_OK;
4331
}
4332
4333
4334
/**
4335
* Synthesize a block of floating point audio samples to audio buffers.
4336
* @param synth FluidSynth instance
4337
* @param len Count of audio frames to synthesize
4338
* @param lout Array of floats to store left channel of audio
4339
* @param loff Offset index in 'lout' for first sample
4340
* @param lincr Increment between samples stored to 'lout'
4341
* @param rout Array of floats to store right channel of audio
4342
* @param roff Offset index in 'rout' for first sample
4343
* @param rincr Increment between samples stored to 'rout'
4344
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
4345
*
4346
* Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
4347
* lincr = 2, rincr = 2).
4348
*
4349
* @note Should only be called from synthesis thread.
4350
* @note Reverb and Chorus are mixed to \c lout resp. \c rout.
4351
*/
4352
int
4353
fluid_synth_write_float(fluid_synth_t *synth, int len,
4354
void *lout, int loff, int lincr,
4355
void *rout, int roff, int rincr)
4356
{
4357
void *channels_out[2] = {lout, rout};
4358
int channels_off[2] = {loff, roff };
4359
int channels_incr[2] = {lincr, rincr };
4360
4361
return fluid_synth_write_float_channels(synth, len, 2, channels_out,
4362
channels_off, channels_incr);
4363
}
4364
4365
/**
4366
* Synthesize a block of float audio samples channels to audio buffers.
4367
* The function is convenient for audio driver to render multiple stereo
4368
* channels pairs on multi channels audio cards (i.e 2, 4, 6, 8,.. channels).
4369
*
4370
* @param synth FluidSynth instance.
4371
* @param len Count of audio frames to synthesize.
4372
* @param channels_count Count of channels in a frame.
4373
* must be multiple of 2 and channel_count/2 must not exceed the number
4374
* of internal mixer buffers (synth->audio_groups)
4375
* @param channels_out Array of channels_count pointers on 16 bit words to
4376
* store sample channels. Modified on return.
4377
* @param channels_off Array of channels_count offset index to add to respective pointer
4378
* in channels_out for first sample.
4379
* @param channels_incr Array of channels_count increment between consecutive
4380
* samples channels.
4381
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
4382
*
4383
* Useful for storing:
4384
* - interleaved channels in a unique buffer.
4385
* - non interleaved channels in an unique buffer (or in distinct buffers).
4386
*
4387
* Example for interleaved 4 channels (c1, c2, c3, c4) and n samples (s1, s2,..sn)
4388
* in a unique buffer:
4389
* { s1:c1, s1:c2, s1:c3, s1:c4, s2:c1, s2:c2, s2:c3, s2:c4,...
4390
* sn:c1, sn:c2, sn:c3, sn:c4 }.
4391
*
4392
* @note Should only be called from synthesis thread.
4393
* @note Reverb and Chorus are mixed to \c lout resp. \c rout.
4394
*/
4395
int
4396
fluid_synth_write_float_channels(fluid_synth_t *synth, int len,
4397
int channels_count,
4398
void *channels_out[], int channels_off[],
4399
int channels_incr[])
4400
{
4401
return fluid_synth_write_float_channels_LOCAL(synth, len, channels_count,
4402
channels_out, channels_off, channels_incr,
4403
fluid_synth_render_blocks);
4404
}
4405
4406
int
4407
fluid_synth_write_float_channels_LOCAL(fluid_synth_t *synth, int len,
4408
int channels_count,
4409
void *channels_out[], int channels_off[],
4410
int channels_incr[],
4411
int (*block_render_func)(fluid_synth_t *, int))
4412
{
4413
float **chan_out = (float **)channels_out;
4414
int n, cur, size;
4415
4416
/* pointers on first input mixer buffer */
4417
fluid_real_t *left_in;
4418
fluid_real_t *right_in;
4419
int bufs_in_count; /* number of stereo input buffers */
4420
int i;
4421
4422
/* start average cpu load probe */
4423
double time = fluid_utime();
4424
float cpu_load;
4425
4426
/* start profiling duration probe (if profiling is enabled) */
4427
fluid_profile_ref_var(prof_ref);
4428
4429
/* check parameters */
4430
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4431
4432
fluid_return_val_if_fail(len >= 0, FLUID_FAILED);
4433
fluid_return_val_if_fail(len != 0, FLUID_OK); // to avoid raising FE_DIVBYZERO below
4434
4435
/* check for valid channel_count: must be multiple of 2 and
4436
channel_count/2 must not exceed the number of internal mixer buffers
4437
(synth->audio_groups)
4438
*/
4439
fluid_return_val_if_fail(!(channels_count & 1) /* must be multiple of 2 */
4440
&& channels_count >= 2, FLUID_FAILED);
4441
4442
bufs_in_count = (unsigned int)channels_count >> 1; /* channels_count/2 */
4443
fluid_return_val_if_fail(bufs_in_count <= synth->audio_groups, FLUID_FAILED);
4444
4445
fluid_return_val_if_fail(channels_out != NULL, FLUID_FAILED);
4446
fluid_return_val_if_fail(channels_off != NULL, FLUID_FAILED);
4447
fluid_return_val_if_fail(channels_incr != NULL, FLUID_FAILED);
4448
4449
/* initialize output channels buffers on first sample position */
4450
i = channels_count;
4451
do
4452
{
4453
i--;
4454
chan_out[i] += channels_off[i];
4455
}
4456
while(i);
4457
4458
/* Conversely to fluid_synth_process(),
4459
we want rendered audio effect mixed in internal audio dry buffers.
4460
TRUE instructs the mixer that internal audio effects will be mixed in internal
4461
audio dry buffers.
4462
*/
4463
fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, TRUE);
4464
4465
/* get first internal mixer audio dry buffer's pointer (left and right channel) */
4466
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
4467
4468
size = len;
4469
4470
/* synth->cur indicates if available samples are still in internal mixer buffer */
4471
cur = synth->cur; /* get previous sample position in internal buffer (due to prvious call) */
4472
4473
do
4474
{
4475
/* fill up the buffers as needed */
4476
if(cur >= synth->curmax)
4477
{
4478
/* render audio (dry and effect) to internal dry buffers */
4479
/* always render full blocs multiple of FLUID_BUFSIZE */
4480
int blocksleft = (size + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
4481
synth->curmax = FLUID_BUFSIZE * block_render_func(synth, blocksleft);
4482
4483
/* get first internal mixer audio dry buffer's pointer (left and right channel) */
4484
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
4485
cur = 0;
4486
}
4487
4488
/* calculate amount of available samples */
4489
n = synth->curmax - cur;
4490
4491
/* keep track of emitted samples */
4492
if(n > size)
4493
{
4494
n = size;
4495
}
4496
4497
size -= n;
4498
4499
/* update pointers to current position */
4500
left_in += cur + n;
4501
right_in += cur + n;
4502
4503
/* set final cursor position */
4504
cur += n;
4505
4506
/* reverse index */
4507
n = 0 - n;
4508
4509
do
4510
{
4511
i = bufs_in_count;
4512
do
4513
{
4514
/* input sample index in stereo buffer i */
4515
int in_idx = --i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + n;
4516
int c = i << 1; /* channel index c to write */
4517
4518
/* write left input sample to channel sample */
4519
*chan_out[c] = (float) left_in[in_idx];
4520
4521
/* write right input sample to next channel sample */
4522
*chan_out[c+1] = (float) right_in[in_idx];
4523
4524
/* advance output pointers */
4525
chan_out[c] += channels_incr[c];
4526
chan_out[c+1] += channels_incr[c+1];
4527
}
4528
while(i);
4529
}
4530
while(++n < 0);
4531
}
4532
while(size);
4533
4534
synth->cur = cur; /* save current sample position. It will be used on next call */
4535
4536
/* save average cpu load, use by API for real time cpu load meter */
4537
time = fluid_utime() - time;
4538
cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
4539
fluid_atomic_float_set(&synth->cpu_load, cpu_load);
4540
4541
/* stop duration probe and save performance measurement (if profiling is enabled) */
4542
fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
4543
fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
4544
len);
4545
return FLUID_OK;
4546
}
4547
4548
/* for testing purpose */
4549
int
4550
fluid_synth_write_float_LOCAL(fluid_synth_t *synth, int len,
4551
void *lout, int loff, int lincr,
4552
void *rout, int roff, int rincr,
4553
int (*block_render_func)(fluid_synth_t *, int)
4554
)
4555
{
4556
void *channels_out[2] = {lout, rout};
4557
int channels_off[2] = {loff, roff };
4558
int channels_incr[2] = {lincr, rincr };
4559
4560
return fluid_synth_write_float_channels_LOCAL(synth, len, 2, channels_out,
4561
channels_off, channels_incr,
4562
block_render_func);
4563
}
4564
4565
4566
#define DITHER_SIZE 48000
4567
#define DITHER_CHANNELS 2
4568
4569
static float rand_table[DITHER_CHANNELS][DITHER_SIZE];
4570
4571
/* Init dither table */
4572
static void
4573
init_dither(void)
4574
{
4575
float d, dp;
4576
int c, i;
4577
4578
for(c = 0; c < DITHER_CHANNELS; c++)
4579
{
4580
dp = 0;
4581
4582
for(i = 0; i < DITHER_SIZE - 1; i++)
4583
{
4584
d = rand() / (float)RAND_MAX - 0.5f;
4585
rand_table[c][i] = d - dp;
4586
dp = d;
4587
}
4588
4589
rand_table[c][DITHER_SIZE - 1] = 0 - dp;
4590
}
4591
}
4592
4593
/* A portable replacement for roundf(), seems it may actually be faster too! */
4594
static FLUID_INLINE int16_t
4595
round_clip_to_i16(float x)
4596
{
4597
long i;
4598
4599
if(x >= 0.0f)
4600
{
4601
i = (long)(x + 0.5f);
4602
4603
if(FLUID_UNLIKELY(i > 32767))
4604
{
4605
i = 32767;
4606
}
4607
}
4608
else
4609
{
4610
i = (long)(x - 0.5f);
4611
4612
if(FLUID_UNLIKELY(i < -32768))
4613
{
4614
i = -32768;
4615
}
4616
}
4617
4618
return (int16_t)i;
4619
}
4620
4621
/**
4622
* Synthesize a block of 16 bit audio samples to audio buffers.
4623
* @param synth FluidSynth instance
4624
* @param len Count of audio frames to synthesize
4625
* @param lout Array of 16 bit words to store left channel of audio
4626
* @param loff Offset index in 'lout' for first sample
4627
* @param lincr Increment between samples stored to 'lout'
4628
* @param rout Array of 16 bit words to store right channel of audio
4629
* @param roff Offset index in 'rout' for first sample
4630
* @param rincr Increment between samples stored to 'rout'
4631
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
4632
*
4633
* Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1,
4634
* lincr = 2, rincr = 2).
4635
*
4636
* @note Should only be called from synthesis thread.
4637
* @note Reverb and Chorus are mixed to \c lout resp. \c rout.
4638
* @note Dithering is performed when converting from internal floating point to
4639
* 16 bit audio.
4640
*/
4641
int
4642
fluid_synth_write_s16(fluid_synth_t *synth, int len,
4643
void *lout, int loff, int lincr,
4644
void *rout, int roff, int rincr)
4645
{
4646
void *channels_out[2] = {lout, rout};
4647
int channels_off[2] = {loff, roff };
4648
int channels_incr[2] = {lincr, rincr };
4649
4650
return fluid_synth_write_s16_channels(synth, len, 2, channels_out,
4651
channels_off, channels_incr);
4652
}
4653
4654
/**
4655
* Synthesize a block of 16 bit audio samples channels to audio buffers.
4656
* The function is convenient for audio driver to render multiple stereo
4657
* channels pairs on multi channels audio cards (i.e 2, 4, 6, 8,.. channels).
4658
*
4659
* @param synth FluidSynth instance.
4660
* @param len Count of audio frames to synthesize.
4661
* @param channels_count Count of channels in a frame.
4662
* must be multiple of 2 and channel_count/2 must not exceed the number
4663
* of internal mixer buffers (synth->audio_groups)
4664
* @param channels_out Array of channels_count pointers on 16 bit words to
4665
* store sample channels. Modified on return.
4666
* @param channels_off Array of channels_count offset index to add to respective pointer
4667
* in channels_out for first sample.
4668
* @param channels_incr Array of channels_count increment between consecutive
4669
* samples channels.
4670
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
4671
*
4672
* Useful for storing:
4673
* - interleaved channels in a unique buffer.
4674
* - non interleaved channels in an unique buffer (or in distinct buffers).
4675
*
4676
* Example for interleaved 4 channels (c1, c2, c3, c4) and n samples (s1, s2,..sn)
4677
* in a unique buffer:
4678
* { s1:c1, s1:c2, s1:c3, s1:c4, s2:c1, s2:c2, s2:c3, s2:c4, ....
4679
* sn:c1, sn:c2, sn:c3, sn:c4 }.
4680
*
4681
* @note Should only be called from synthesis thread.
4682
* @note Reverb and Chorus are mixed to \c lout resp. \c rout.
4683
* @note Dithering is performed when converting from internal floating point to
4684
* 16 bit audio.
4685
*/
4686
int
4687
fluid_synth_write_s16_channels(fluid_synth_t *synth, int len,
4688
int channels_count,
4689
void *channels_out[], int channels_off[],
4690
int channels_incr[])
4691
{
4692
int16_t **chan_out = (int16_t **)channels_out;
4693
int di, n, cur, size;
4694
4695
/* pointers on first input mixer buffer */
4696
fluid_real_t *left_in;
4697
fluid_real_t *right_in;
4698
int bufs_in_count; /* number of stereo input buffers */
4699
int i;
4700
4701
/* start average cpu load probe */
4702
double time = fluid_utime();
4703
float cpu_load;
4704
4705
/* start profiling duration probe (if profiling is enabled) */
4706
fluid_profile_ref_var(prof_ref);
4707
4708
/* check parameters */
4709
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
4710
4711
fluid_return_val_if_fail(len >= 0, FLUID_FAILED);
4712
fluid_return_val_if_fail(len != 0, FLUID_OK); // to avoid raising FE_DIVBYZERO below
4713
4714
/* check for valid channel_count: must be multiple of 2 and
4715
channel_count/2 must not exceed the number of internal mixer buffers
4716
(synth->audio_groups)
4717
*/
4718
fluid_return_val_if_fail(!(channels_count & 1) /* must be multiple of 2 */
4719
&& channels_count >= 2, FLUID_FAILED);
4720
4721
bufs_in_count = (unsigned int)channels_count >> 1; /* channels_count/2 */
4722
fluid_return_val_if_fail(bufs_in_count <= synth->audio_groups, FLUID_FAILED);
4723
4724
fluid_return_val_if_fail(channels_out != NULL, FLUID_FAILED);
4725
fluid_return_val_if_fail(channels_off != NULL, FLUID_FAILED);
4726
fluid_return_val_if_fail(channels_incr != NULL, FLUID_FAILED);
4727
4728
/* initialize output channels buffers on first sample position */
4729
i = channels_count;
4730
do
4731
{
4732
i--;
4733
chan_out[i] += channels_off[i];
4734
}
4735
while(i);
4736
4737
/* Conversely to fluid_synth_process(),
4738
we want rendered audio effect mixed in internal audio dry buffers.
4739
TRUE instructs the mixer that internal audio effects will be mixed in internal
4740
audio dry buffers.
4741
*/
4742
fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, TRUE);
4743
/* get first internal mixer audio dry buffer's pointer (left and right channel) */
4744
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
4745
4746
size = len;
4747
/* synth->cur indicates if available samples are still in internal mixer buffer */
4748
cur = synth->cur; /* get previous sample position in internal buffer (due to prvious call) */
4749
di = synth->dither_index;
4750
4751
do
4752
{
4753
/* fill up the buffers as needed */
4754
if(cur >= synth->curmax)
4755
{
4756
/* render audio (dry and effect) to internal dry buffers */
4757
/* always render full blocs multiple of FLUID_BUFSIZE */
4758
int blocksleft = (size + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE;
4759
synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft);
4760
4761
/* get first internal mixer audio dry buffer's pointer (left and right channel) */
4762
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
4763
cur = 0;
4764
}
4765
4766
/* calculate amount of available samples */
4767
n = synth->curmax - cur;
4768
4769
/* keep track of emitted samples */
4770
if(n > size)
4771
{
4772
n = size;
4773
}
4774
4775
size -= n;
4776
4777
/* update pointers to current position */
4778
left_in += cur + n;
4779
right_in += cur + n;
4780
4781
/* set final cursor position */
4782
cur += n;
4783
4784
/* reverse index */
4785
n = 0 - n;
4786
4787
do
4788
{
4789
i = bufs_in_count;
4790
do
4791
{
4792
/* input sample index in stereo buffer i */
4793
int in_idx = --i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + n;
4794
int c = i << 1; /* channel index c to write */
4795
4796
/* write left input sample to channel sample */
4797
*chan_out[c] = round_clip_to_i16(left_in[in_idx] * 32766.0f +
4798
rand_table[0][di]);
4799
4800
/* write right input sample to next channel sample */
4801
*chan_out[c+1] = round_clip_to_i16(right_in[in_idx] * 32766.0f +
4802
rand_table[1][di]);
4803
/* advance output pointers */
4804
chan_out[c] += channels_incr[c];
4805
chan_out[c+1] += channels_incr[c+1];
4806
}
4807
while(i);
4808
4809
if(++di >= DITHER_SIZE)
4810
{
4811
di = 0;
4812
}
4813
}
4814
while(++n < 0);
4815
}
4816
while(size);
4817
4818
synth->cur = cur; /* save current sample position. It will be used on next call */
4819
synth->dither_index = di; /* keep dither buffer continuous */
4820
4821
/* save average cpu load, used by API for real time cpu load meter */
4822
time = fluid_utime() - time;
4823
cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0);
4824
fluid_atomic_float_set(&synth->cpu_load, cpu_load);
4825
4826
/* stop duration probe and save performance measurement (if profiling is enabled) */
4827
fluid_profile_write(FLUID_PROF_WRITE, prof_ref,
4828
fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
4829
len);
4830
return FLUID_OK;
4831
}
4832
4833
/**
4834
* Converts stereo floating point sample data to signed 16 bit data with dithering.
4835
* @param dither_index Pointer to an integer which should be initialized to 0
4836
* before the first call and passed unmodified to additional calls which are
4837
* part of the same synthesis output.
4838
* @param len Length in frames to convert
4839
* @param lin Buffer of left audio samples to convert from
4840
* @param rin Buffer of right audio samples to convert from
4841
* @param lout Array of 16 bit words to store left channel of audio
4842
* @param loff Offset index in 'lout' for first sample
4843
* @param lincr Increment between samples stored to 'lout'
4844
* @param rout Array of 16 bit words to store right channel of audio
4845
* @param roff Offset index in 'rout' for first sample
4846
* @param rincr Increment between samples stored to 'rout'
4847
*
4848
* @note Currently private to libfluidsynth.
4849
*/
4850
void
4851
fluid_synth_dither_s16(int *dither_index, int len, const float *lin, const float *rin,
4852
void *lout, int loff, int lincr,
4853
void *rout, int roff, int rincr)
4854
{
4855
int i, j, k;
4856
int16_t *left_out = lout;
4857
int16_t *right_out = rout;
4858
int di = *dither_index;
4859
fluid_profile_ref_var(prof_ref);
4860
4861
for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr)
4862
{
4863
left_out[j] = round_clip_to_i16(lin[i] * 32766.0f + rand_table[0][di]);
4864
right_out[k] = round_clip_to_i16(rin[i] * 32766.0f + rand_table[1][di]);
4865
4866
if(++di >= DITHER_SIZE)
4867
{
4868
di = 0;
4869
}
4870
}
4871
4872
*dither_index = di; /* keep dither buffer continuous */
4873
4874
fluid_profile(FLUID_PROF_WRITE, prof_ref, 0, len);
4875
}
4876
4877
static void
4878
fluid_synth_check_finished_voices(fluid_synth_t *synth)
4879
{
4880
int j;
4881
fluid_rvoice_t *fv;
4882
4883
while(NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler)))
4884
{
4885
for(j = 0; j < synth->polyphony; j++)
4886
{
4887
if(synth->voice[j]->rvoice == fv)
4888
{
4889
fluid_voice_unlock_rvoice(synth->voice[j]);
4890
fluid_voice_stop(synth->voice[j]);
4891
break;
4892
}
4893
else if(synth->voice[j]->overflow_rvoice == fv)
4894
{
4895
/* Unlock the overflow_rvoice of the voice.
4896
Decrement the reference count of the sample owned by this
4897
rvoice.
4898
*/
4899
fluid_voice_overflow_rvoice_finished(synth->voice[j]);
4900
4901
/* Decrement synth active voice count. Must not be incorporated
4902
in fluid_voice_overflow_rvoice_finished() because
4903
fluid_voice_overflow_rvoice_finished() is called also
4904
at synth destruction and in this case the variable should be
4905
accessed via voice->channel->synth->active_voice_count.
4906
And for certain voices which are not playing, the field
4907
voice->channel is NULL.
4908
*/
4909
synth->active_voice_count--;
4910
break;
4911
}
4912
}
4913
}
4914
}
4915
4916
/**
4917
* Process all waiting events in the rvoice queue.
4918
* Make sure no (other) rendering is running in parallel when
4919
* you call this function!
4920
*/
4921
void fluid_synth_process_event_queue(fluid_synth_t *synth)
4922
{
4923
fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4924
}
4925
4926
4927
/**
4928
* Process blocks (FLUID_BUFSIZE) of audio.
4929
* Must be called from renderer thread only!
4930
* @return number of blocks rendered. Might (often) return less than requested
4931
*/
4932
static int
4933
fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount)
4934
{
4935
int i, maxblocks;
4936
fluid_profile_ref_var(prof_ref);
4937
4938
/* Assign ID of synthesis thread */
4939
// synth->synth_thread_id = fluid_thread_get_id ();
4940
4941
fluid_check_fpe("??? Just starting up ???");
4942
4943
fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler);
4944
4945
/* do not render more blocks than we can store internally */
4946
maxblocks = fluid_rvoice_mixer_get_bufcount(synth->eventhandler->mixer);
4947
4948
if(blockcount > maxblocks)
4949
{
4950
blockcount = maxblocks;
4951
}
4952
4953
for(i = 0; i < blockcount; i++)
4954
{
4955
fluid_sample_timer_process(synth);
4956
fluid_synth_add_ticks(synth, FLUID_BUFSIZE);
4957
4958
/* If events have been queued waiting for fluid_rvoice_eventhandler_dispatch_all()
4959
* (should only happen with parallel render) stop processing and go for rendering
4960
*/
4961
if(fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler))
4962
{
4963
// Something has happened, we can't process more
4964
blockcount = i + 1;
4965
break;
4966
}
4967
}
4968
4969
fluid_check_fpe("fluid_sample_timer_process");
4970
4971
blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount);
4972
4973
/* Testcase, that provokes a denormal floating point error */
4974
#if 0
4975
{
4976
float num = 1;
4977
4978
while(num != 0)
4979
{
4980
num *= 0.5;
4981
};
4982
};
4983
#endif
4984
fluid_check_fpe("??? Remainder of synth_one_block ???");
4985
fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref,
4986
fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer),
4987
blockcount * FLUID_BUFSIZE);
4988
return blockcount;
4989
}
4990
4991
/*
4992
* Handler for synth.reverb.* and synth.chorus.* double settings.
4993
*/
4994
static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value)
4995
{
4996
fluid_synth_t *synth = (fluid_synth_t *)data;
4997
fluid_return_if_fail(synth != NULL);
4998
4999
if(FLUID_STRCMP(name, "synth.reverb.room-size") == 0)
5000
{
5001
fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_ROOMSIZE, value);
5002
}
5003
else if(FLUID_STRCMP(name, "synth.reverb.damp") == 0)
5004
{
5005
fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_DAMP, value);
5006
}
5007
else if(FLUID_STRCMP(name, "synth.reverb.width") == 0)
5008
{
5009
fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_WIDTH, value);
5010
}
5011
else if(FLUID_STRCMP(name, "synth.reverb.level") == 0)
5012
{
5013
fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_LEVEL, value);
5014
}
5015
else if(FLUID_STRCMP(name, "synth.chorus.depth") == 0)
5016
{
5017
fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_DEPTH, value);
5018
}
5019
else if(FLUID_STRCMP(name, "synth.chorus.speed") == 0)
5020
{
5021
fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_SPEED, value);
5022
}
5023
else if(FLUID_STRCMP(name, "synth.chorus.level") == 0)
5024
{
5025
fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_LEVEL, value);
5026
}
5027
}
5028
5029
/*
5030
* Handler for synth.reverb.* and synth.chorus.* integer settings.
5031
*/
5032
static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value)
5033
{
5034
fluid_synth_t *synth = (fluid_synth_t *)data;
5035
fluid_return_if_fail(synth != NULL);
5036
5037
if(FLUID_STRCMP(name, "synth.reverb.active") == 0)
5038
{
5039
fluid_synth_reverb_on(synth, -1, value);
5040
}
5041
else if(FLUID_STRCMP(name, "synth.chorus.active") == 0)
5042
{
5043
fluid_synth_chorus_on(synth, -1, value);
5044
}
5045
else if(FLUID_STRCMP(name, "synth.chorus.nr") == 0)
5046
{
5047
fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_NR, (double)value);
5048
}
5049
}
5050
5051
/*
5052
* Handler for synth.overflow.* settings.
5053
*/
5054
static void fluid_synth_handle_overflow(void *data, const char *name, double value)
5055
{
5056
fluid_synth_t *synth = (fluid_synth_t *)data;
5057
fluid_return_if_fail(synth != NULL);
5058
5059
fluid_synth_api_enter(synth);
5060
5061
if(FLUID_STRCMP(name, "synth.overflow.percussion") == 0)
5062
{
5063
synth->overflow.percussion = value;
5064
}
5065
else if(FLUID_STRCMP(name, "synth.overflow.released") == 0)
5066
{
5067
synth->overflow.released = value;
5068
}
5069
else if(FLUID_STRCMP(name, "synth.overflow.sustained") == 0)
5070
{
5071
synth->overflow.sustained = value;
5072
}
5073
else if(FLUID_STRCMP(name, "synth.overflow.volume") == 0)
5074
{
5075
synth->overflow.volume = value;
5076
}
5077
else if(FLUID_STRCMP(name, "synth.overflow.age") == 0)
5078
{
5079
synth->overflow.age = value;
5080
}
5081
else if(FLUID_STRCMP(name, "synth.overflow.important") == 0)
5082
{
5083
synth->overflow.important = value;
5084
}
5085
5086
fluid_synth_api_exit(synth);
5087
}
5088
5089
/* Selects a voice for killing. */
5090
static fluid_voice_t *
5091
fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth)
5092
{
5093
int i;
5094
float best_prio = OVERFLOW_PRIO_CANNOT_KILL - 1;
5095
float this_voice_prio;
5096
fluid_voice_t *voice;
5097
int best_voice_index = -1;
5098
unsigned int ticks = fluid_synth_get_ticks(synth);
5099
5100
for(i = 0; i < synth->polyphony; i++)
5101
{
5102
5103
voice = synth->voice[i];
5104
5105
/* safeguard against an available voice. */
5106
if(_AVAILABLE(voice))
5107
{
5108
return voice;
5109
}
5110
5111
this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow,
5112
ticks);
5113
5114
/* check if this voice has less priority than the previous candidate. */
5115
if(this_voice_prio < best_prio)
5116
{
5117
best_voice_index = i;
5118
best_prio = this_voice_prio;
5119
}
5120
}
5121
5122
if(best_voice_index < 0)
5123
{
5124
return NULL;
5125
}
5126
5127
voice = synth->voice[best_voice_index];
5128
FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ",
5129
fluid_voice_get_id(voice), best_voice_index, fluid_voice_get_channel(voice), fluid_voice_get_key(voice));
5130
fluid_voice_off(voice);
5131
5132
return voice;
5133
}
5134
5135
5136
/**
5137
* Allocate a synthesis voice.
5138
* @param synth FluidSynth instance
5139
* @param sample Sample to assign to the voice
5140
* @param chan MIDI channel number (0 to MIDI channel count - 1)
5141
* @param key MIDI note number for the voice (0-127)
5142
* @param vel MIDI velocity for the voice (0-127)
5143
* @return Allocated synthesis voice or NULL on error
5144
*
5145
* This function is called by a SoundFont's preset in response to a noteon event.
5146
* The returned voice comes with default modulators and generators.
5147
* A single noteon event may create any number of voices, when the preset is layered.
5148
*
5149
* @note Should only be called from within synthesis thread, which includes
5150
* SoundFont loader preset noteon method.
5151
*/
5152
fluid_voice_t *
5153
fluid_synth_alloc_voice(fluid_synth_t *synth, fluid_sample_t *sample,
5154
int chan, int key, int vel)
5155
{
5156
fluid_return_val_if_fail(sample != NULL, NULL);
5157
fluid_return_val_if_fail(sample->data != NULL, NULL);
5158
FLUID_API_ENTRY_CHAN(NULL);
5159
FLUID_API_RETURN(fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, NULL));
5160
5161
}
5162
5163
fluid_voice_t *
5164
fluid_synth_alloc_voice_LOCAL(fluid_synth_t *synth, fluid_sample_t *sample, int chan, int key, int vel, fluid_zone_range_t *zone_range)
5165
{
5166
int i, k;
5167
fluid_voice_t *voice = NULL;
5168
fluid_channel_t *channel = NULL;
5169
unsigned int ticks;
5170
5171
/* check if there's an available synthesis process */
5172
for(i = 0; i < synth->polyphony; i++)
5173
{
5174
if(_AVAILABLE(synth->voice[i]))
5175
{
5176
voice = synth->voice[i];
5177
break;
5178
}
5179
}
5180
5181
/* No success yet? Then stop a running voice. */
5182
if(voice == NULL)
5183
{
5184
FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice");
5185
voice = fluid_synth_free_voice_by_kill_LOCAL(synth);
5186
}
5187
5188
if(voice == NULL)
5189
{
5190
FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
5191
return NULL;
5192
}
5193
5194
ticks = fluid_synth_get_ticks(synth);
5195
5196
if(synth->verbose)
5197
{
5198
k = 0;
5199
5200
for(i = 0; i < synth->polyphony; i++)
5201
{
5202
if(!_AVAILABLE(synth->voice[i]))
5203
{
5204
k++;
5205
}
5206
}
5207
5208
FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
5209
chan, key, vel, synth->storeid,
5210
(float) ticks / 44100.0f,
5211
(fluid_curtime() - synth->start) / 1000.0f,
5212
0.0f,
5213
k);
5214
}
5215
5216
channel = synth->channel[chan];
5217
5218
if(fluid_voice_init(voice, sample, zone_range, channel, key, vel,
5219
synth->storeid, ticks, synth->gain) != FLUID_OK)
5220
{
5221
FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
5222
return NULL;
5223
}
5224
5225
/* add the default modulators to the synthesis process. */
5226
/* custom_breath2att_modulator is not a default modulator specified in SF
5227
it is intended to replace default_vel2att_mod for this channel on demand using
5228
API fluid_synth_set_breath_mode() or shell command setbreathmode for this channel.
5229
*/
5230
{
5231
int mono = fluid_channel_is_playing_mono(channel);
5232
fluid_mod_t *default_mod = synth->default_mod;
5233
5234
while(default_mod != NULL)
5235
{
5236
if(
5237
/* See if default_mod is the velocity_to_attenuation modulator */
5238
fluid_mod_test_identity(default_mod, &default_vel2att_mod) &&
5239
// See if a replacement by custom_breath2att_modulator has been demanded
5240
// for this channel
5241
((!mono && (channel->mode & FLUID_CHANNEL_BREATH_POLY)) ||
5242
(mono && (channel->mode & FLUID_CHANNEL_BREATH_MONO)))
5243
)
5244
{
5245
// Replacement of default_vel2att modulator by custom_breath2att_modulator
5246
fluid_voice_add_mod_local(voice, &custom_breath2att_mod, FLUID_VOICE_DEFAULT, 0);
5247
}
5248
else
5249
{
5250
fluid_voice_add_mod_local(voice, default_mod, FLUID_VOICE_DEFAULT, 0);
5251
}
5252
5253
// Next default modulator to add to the voice
5254
default_mod = default_mod->next;
5255
}
5256
}
5257
5258
return voice;
5259
}
5260
5261
/* Kill all voices on a given channel, which have the same exclusive class
5262
* generator as new_voice.
5263
*/
5264
static void
5265
fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth,
5266
fluid_voice_t *new_voice)
5267
{
5268
int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS);
5269
int i;
5270
5271
/* Excl. class 0: No exclusive class */
5272
if(excl_class == 0)
5273
{
5274
return;
5275
}
5276
5277
/* Kill all notes on the same channel with the same exclusive class */
5278
for(i = 0; i < synth->polyphony; i++)
5279
{
5280
fluid_voice_t *existing_voice = synth->voice[i];
5281
5282
/* If voice is playing, on the same channel, has same exclusive
5283
* class and is not part of the same noteon event (voice group), then kill it */
5284
5285
if(fluid_voice_is_playing(existing_voice)
5286
&& fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice)
5287
&& fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS) == excl_class
5288
&& fluid_voice_get_id(existing_voice) != fluid_voice_get_id(new_voice))
5289
{
5290
fluid_voice_kill_excl(existing_voice);
5291
}
5292
}
5293
}
5294
5295
/**
5296
* Activate a voice previously allocated with fluid_synth_alloc_voice().
5297
* @param synth FluidSynth instance
5298
* @param voice Voice to activate
5299
*
5300
* This function is called by a SoundFont's preset in response to a noteon
5301
* event. Exclusive classes are processed here.
5302
*
5303
* @note Should only be called from within synthesis thread, which includes
5304
* SoundFont loader preset noteon method.
5305
*/
5306
void
5307
fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice)
5308
{
5309
fluid_return_if_fail(synth != NULL);
5310
fluid_return_if_fail(voice != NULL);
5311
// fluid_return_if_fail (fluid_synth_is_synth_thread (synth));
5312
fluid_synth_api_enter(synth);
5313
5314
/* Find the exclusive class of this voice. If set, kill all voices
5315
* that match the exclusive class and are younger than the first
5316
* voice process created by this noteon event. */
5317
fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice);
5318
5319
fluid_voice_start(voice); /* Start the new voice */
5320
fluid_voice_lock_rvoice(voice);
5321
fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice);
5322
fluid_synth_api_exit(synth);
5323
}
5324
5325
/**
5326
* Add a SoundFont loader to the synth. This function takes ownership of \c loader
5327
* and frees it automatically upon \c synth destruction.
5328
* @param synth FluidSynth instance
5329
* @param loader Loader API structure
5330
*
5331
* SoundFont loaders are used to add custom instrument loading to FluidSynth.
5332
* The caller supplied functions for loading files, allocating presets,
5333
* retrieving information on them and synthesizing note-on events. Using this
5334
* method even non SoundFont instruments can be synthesized, although limited
5335
* to the SoundFont synthesis model.
5336
*
5337
* @note Should only be called before any SoundFont files are loaded.
5338
*/
5339
void
5340
fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader)
5341
{
5342
fluid_return_if_fail(synth != NULL);
5343
fluid_return_if_fail(loader != NULL);
5344
fluid_synth_api_enter(synth);
5345
5346
/* Test if sfont is already loaded */
5347
if(synth->sfont == NULL)
5348
{
5349
synth->loaders = fluid_list_prepend(synth->loaders, loader);
5350
}
5351
5352
fluid_synth_api_exit(synth);
5353
}
5354
5355
/**
5356
* Load a SoundFont file (filename is interpreted by SoundFont loaders).
5357
* The newly loaded SoundFont will be put on top of the SoundFont
5358
* stack. Presets are searched starting from the SoundFont on the
5359
* top of the stack, working the way down the stack until a preset is found.
5360
*
5361
* @param synth FluidSynth instance
5362
* @param filename File to load
5363
* @param reset_presets TRUE to re-assign presets for all MIDI channels (equivalent to calling fluid_synth_program_reset())
5364
* @return SoundFont ID on success, #FLUID_FAILED on error
5365
*
5366
* @note Since FluidSynth 2.2.0 @c filename is treated as an UTF8 encoded string on Windows. FluidSynth will convert it
5367
* to wide-char internally and then pass it to <code>_wfopen()</code>. Before FluidSynth 2.2.0, @c filename was treated as ANSI string
5368
* on Windows. All other platforms directly pass it to <code>fopen()</code> without any conversion (usually, UTF8 is accepted).
5369
*/
5370
int
5371
fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets)
5372
{
5373
fluid_sfont_t *sfont;
5374
fluid_list_t *list;
5375
fluid_sfloader_t *loader;
5376
int sfont_id;
5377
5378
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5379
fluid_return_val_if_fail(filename != NULL, FLUID_FAILED);
5380
fluid_synth_api_enter(synth);
5381
5382
sfont_id = synth->sfont_id;
5383
5384
if(++sfont_id != FLUID_FAILED)
5385
{
5386
/* MT NOTE: Loaders list should not change. */
5387
5388
for(list = synth->loaders; list; list = fluid_list_next(list))
5389
{
5390
loader = (fluid_sfloader_t *) fluid_list_get(list);
5391
5392
sfont = fluid_sfloader_load(loader, filename);
5393
5394
if(sfont != NULL)
5395
{
5396
sfont->refcount++;
5397
synth->sfont_id = sfont->id = sfont_id;
5398
5399
synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
5400
5401
/* reset the presets for all channels if requested */
5402
if(reset_presets)
5403
{
5404
fluid_synth_program_reset(synth);
5405
}
5406
5407
FLUID_API_RETURN(sfont_id);
5408
}
5409
}
5410
}
5411
5412
FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
5413
FLUID_API_RETURN(FLUID_FAILED);
5414
}
5415
5416
/**
5417
* Schedule a SoundFont for unloading.
5418
*
5419
* If the SoundFont isn't used anymore by any playing voices, it will be unloaded immediately.
5420
*
5421
* If any samples of the given SoundFont are still required by active voices,
5422
* the SoundFont will be unloaded in a lazy manner, once those voices have finished synthesizing.
5423
* If you call delete_fluid_synth(), all voices will be destroyed and the SoundFont
5424
* will be unloaded in any case.
5425
* Once this function returned, fluid_synth_sfcount() and similar functions will behave as if
5426
* the SoundFont has already been unloaded, even though the lazy-unloading is still pending.
5427
*
5428
* @note This lazy-unloading mechanism was broken between FluidSynth 1.1.4 and 2.1.5 . As a
5429
* consequence, SoundFonts scheduled for lazy-unloading may be never freed under certain
5430
* conditions. Calling delete_fluid_synth() does not recover this situation either.
5431
*
5432
* @param synth FluidSynth instance
5433
* @param id ID of SoundFont to unload
5434
* @param reset_presets TRUE to re-assign presets for all MIDI channels
5435
* @return #FLUID_OK if the given @p id was found, #FLUID_FAILED otherwise.
5436
*/
5437
int
5438
fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets)
5439
{
5440
fluid_sfont_t *sfont = NULL;
5441
fluid_list_t *list;
5442
5443
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5444
fluid_synth_api_enter(synth);
5445
5446
/* remove the SoundFont from the list */
5447
for(list = synth->sfont; list; list = fluid_list_next(list))
5448
{
5449
sfont = fluid_list_get(list);
5450
5451
if(fluid_sfont_get_id(sfont) == id)
5452
{
5453
synth->sfont = fluid_list_remove(synth->sfont, sfont);
5454
break;
5455
}
5456
}
5457
5458
if(!list)
5459
{
5460
FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
5461
FLUID_API_RETURN(FLUID_FAILED);
5462
}
5463
5464
/* reset the presets for all channels (SoundFont will be freed when there are no more references) */
5465
if(reset_presets)
5466
{
5467
fluid_synth_program_reset(synth);
5468
}
5469
else
5470
{
5471
fluid_synth_update_presets(synth);
5472
}
5473
5474
/* -- Remove synth->sfont list's reference to SoundFont */
5475
fluid_synth_sfont_unref(synth, sfont);
5476
5477
FLUID_API_RETURN(FLUID_OK);
5478
}
5479
5480
/* Unref a SoundFont and destroy if no more references */
5481
void
5482
fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont)
5483
{
5484
fluid_return_if_fail(sfont != NULL); /* Shouldn't happen, programming error if so */
5485
5486
sfont->refcount--; /* -- Remove the sfont list's reference */
5487
5488
if(sfont->refcount == 0) /* No more references? - Attempt delete */
5489
{
5490
if(fluid_sfont_delete_internal(sfont) == 0) /* SoundFont loader can block SoundFont unload */
5491
{
5492
FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
5493
} /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */
5494
else
5495
{
5496
fluid_timer_t* timer = new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, TRUE, FALSE, FALSE);
5497
synth->fonts_to_be_unloaded = fluid_list_prepend(synth->fonts_to_be_unloaded, timer);
5498
}
5499
}
5500
}
5501
5502
/* Callback to continually attempt to unload a SoundFont,
5503
* only if a SoundFont loader blocked the unload operation */
5504
static int
5505
fluid_synth_sfunload_callback(void *data, unsigned int msec)
5506
{
5507
fluid_sfont_t *sfont = data;
5508
5509
if(fluid_sfont_delete_internal(sfont) == 0)
5510
{
5511
FLUID_LOG(FLUID_DBG, "Unloaded SoundFont");
5512
return FALSE;
5513
}
5514
else
5515
{
5516
return TRUE;
5517
}
5518
}
5519
5520
/**
5521
* Reload a SoundFont. The SoundFont retains its ID and index on the SoundFont stack.
5522
* @param synth FluidSynth instance
5523
* @param id ID of SoundFont to reload
5524
* @return SoundFont ID on success, #FLUID_FAILED on error
5525
*/
5526
int
5527
fluid_synth_sfreload(fluid_synth_t *synth, int id)
5528
{
5529
char *filename = NULL;
5530
fluid_sfont_t *sfont;
5531
fluid_sfloader_t *loader;
5532
fluid_list_t *list;
5533
int index, ret = FLUID_FAILED;
5534
5535
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5536
fluid_synth_api_enter(synth);
5537
5538
/* Search for SoundFont and get its index */
5539
for(list = synth->sfont, index = 0; list; list = fluid_list_next(list), index++)
5540
{
5541
sfont = fluid_list_get(list);
5542
5543
if(fluid_sfont_get_id(sfont) == id)
5544
{
5545
break;
5546
}
5547
}
5548
5549
if(!list)
5550
{
5551
FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
5552
goto exit;
5553
}
5554
5555
/* keep a copy of the SoundFont's filename */
5556
filename = FLUID_STRDUP(fluid_sfont_get_name(sfont));
5557
5558
if(filename == NULL || fluid_synth_sfunload(synth, id, FALSE) != FLUID_OK)
5559
{
5560
goto exit;
5561
}
5562
5563
/* MT Note: SoundFont loader list will not change */
5564
5565
for(list = synth->loaders; list; list = fluid_list_next(list))
5566
{
5567
loader = (fluid_sfloader_t *) fluid_list_get(list);
5568
5569
sfont = fluid_sfloader_load(loader, filename);
5570
5571
if(sfont != NULL)
5572
{
5573
sfont->id = id;
5574
sfont->refcount++;
5575
5576
synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont); /* insert the sfont at the same index */
5577
5578
/* reset the presets for all channels */
5579
fluid_synth_update_presets(synth);
5580
ret = id;
5581
goto exit;
5582
}
5583
}
5584
5585
FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
5586
5587
exit:
5588
FLUID_FREE(filename);
5589
FLUID_API_RETURN(ret);
5590
}
5591
5592
/**
5593
* Add a SoundFont. The SoundFont will be added to the top of the SoundFont stack and ownership is transferred to @p synth.
5594
* @param synth FluidSynth instance
5595
* @param sfont SoundFont to add
5596
* @return New assigned SoundFont ID or #FLUID_FAILED on error
5597
*/
5598
int
5599
fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
5600
{
5601
int sfont_id;
5602
5603
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5604
fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
5605
fluid_synth_api_enter(synth);
5606
5607
sfont_id = synth->sfont_id;
5608
5609
if(++sfont_id != FLUID_FAILED)
5610
{
5611
synth->sfont_id = sfont->id = sfont_id;
5612
synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */
5613
5614
/* reset the presets for all channels */
5615
fluid_synth_program_reset(synth);
5616
}
5617
5618
FLUID_API_RETURN(sfont_id);
5619
}
5620
5621
/**
5622
* Remove a SoundFont from the SoundFont stack without deleting it.
5623
* @param synth FluidSynth instance
5624
* @param sfont SoundFont to remove
5625
* @return #FLUID_OK if \c sfont successfully removed, #FLUID_FAILED otherwise
5626
*
5627
* SoundFont is not freed and is left as the responsibility of the caller.
5628
*
5629
* @note The SoundFont should only be freed after there are no presets
5630
* referencing it. This can only be ensured by the SoundFont loader and
5631
* therefore this function should not normally be used.
5632
*/
5633
int
5634
fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont)
5635
{
5636
fluid_sfont_t *sfont_tmp;
5637
fluid_list_t *list;
5638
int ret = FLUID_FAILED;
5639
5640
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5641
fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED);
5642
fluid_synth_api_enter(synth);
5643
5644
/* remove the SoundFont from the list */
5645
for(list = synth->sfont; list; list = fluid_list_next(list))
5646
{
5647
sfont_tmp = fluid_list_get(list);
5648
5649
if(sfont_tmp == sfont)
5650
{
5651
synth->sfont = fluid_list_remove(synth->sfont, sfont_tmp);
5652
ret = FLUID_OK;
5653
break;
5654
}
5655
}
5656
5657
/* reset the presets for all channels */
5658
fluid_synth_program_reset(synth);
5659
5660
FLUID_API_RETURN(ret);
5661
}
5662
5663
/**
5664
* Count number of loaded SoundFont files.
5665
* @param synth FluidSynth instance
5666
* @return Count of loaded SoundFont files.
5667
*/
5668
int
5669
fluid_synth_sfcount(fluid_synth_t *synth)
5670
{
5671
int count;
5672
5673
fluid_return_val_if_fail(synth != NULL, 0);
5674
fluid_synth_api_enter(synth);
5675
count = fluid_list_size(synth->sfont);
5676
FLUID_API_RETURN(count);
5677
}
5678
5679
/**
5680
* Get SoundFont by index.
5681
* @param synth FluidSynth instance
5682
* @param num SoundFont index on the stack (starting from 0 for top of stack).
5683
* @return SoundFont instance or NULL if invalid index
5684
*
5685
* @note Caller should be certain that SoundFont is not deleted (unloaded) for
5686
* the duration of use of the returned pointer.
5687
*/
5688
fluid_sfont_t *
5689
fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num)
5690
{
5691
fluid_sfont_t *sfont = NULL;
5692
fluid_list_t *list;
5693
5694
fluid_return_val_if_fail(synth != NULL, NULL);
5695
fluid_synth_api_enter(synth);
5696
list = fluid_list_nth(synth->sfont, num);
5697
5698
if(list)
5699
{
5700
sfont = fluid_list_get(list);
5701
}
5702
5703
FLUID_API_RETURN(sfont);
5704
}
5705
5706
/**
5707
* Get SoundFont by ID.
5708
* @param synth FluidSynth instance
5709
* @param id SoundFont ID
5710
* @return SoundFont instance or NULL if invalid ID
5711
*
5712
* @note Caller should be certain that SoundFont is not deleted (unloaded) for
5713
* the duration of use of the returned pointer.
5714
*/
5715
fluid_sfont_t *
5716
fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id)
5717
{
5718
fluid_sfont_t *sfont = NULL;
5719
fluid_list_t *list;
5720
5721
fluid_return_val_if_fail(synth != NULL, NULL);
5722
fluid_synth_api_enter(synth);
5723
5724
for(list = synth->sfont; list; list = fluid_list_next(list))
5725
{
5726
sfont = fluid_list_get(list);
5727
5728
if(fluid_sfont_get_id(sfont) == id)
5729
{
5730
break;
5731
}
5732
}
5733
5734
FLUID_API_RETURN(list ? sfont : NULL);
5735
}
5736
5737
/**
5738
* Get SoundFont by name.
5739
* @param synth FluidSynth instance
5740
* @param name Name of SoundFont
5741
* @return SoundFont instance or NULL if invalid name
5742
* @since 1.1.0
5743
*
5744
* @note Caller should be certain that SoundFont is not deleted (unloaded) for
5745
* the duration of use of the returned pointer.
5746
*/
5747
fluid_sfont_t *
5748
fluid_synth_get_sfont_by_name(fluid_synth_t *synth, const char *name)
5749
{
5750
fluid_sfont_t *sfont = NULL;
5751
fluid_list_t *list;
5752
5753
fluid_return_val_if_fail(synth != NULL, NULL);
5754
fluid_return_val_if_fail(name != NULL, NULL);
5755
fluid_synth_api_enter(synth);
5756
5757
for(list = synth->sfont; list; list = fluid_list_next(list))
5758
{
5759
sfont = fluid_list_get(list);
5760
5761
if(FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0)
5762
{
5763
break;
5764
}
5765
}
5766
5767
FLUID_API_RETURN(list ? sfont : NULL);
5768
}
5769
5770
/**
5771
* Get active preset on a MIDI channel.
5772
* @param synth FluidSynth instance
5773
* @param chan MIDI channel number (0 to MIDI channel count - 1)
5774
* @return Preset or NULL if no preset active on \c chan
5775
*
5776
* @note Should only be called from within synthesis thread, which includes
5777
* SoundFont loader preset noteon methods. Not thread safe otherwise.
5778
*/
5779
fluid_preset_t *
5780
fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan)
5781
{
5782
fluid_preset_t *result;
5783
fluid_channel_t *channel;
5784
FLUID_API_ENTRY_CHAN(NULL);
5785
5786
channel = synth->channel[chan];
5787
result = channel->preset;
5788
fluid_synth_api_exit(synth);
5789
return result;
5790
}
5791
5792
/**
5793
* Get list of currently playing voices.
5794
* @param synth FluidSynth instance
5795
* @param buf Array to store voices to (NULL terminated if not filled completely)
5796
* @param bufsize Count of indexes in buf
5797
* @param id Voice ID to search for or < 0 to return list of all playing voices
5798
*
5799
* @note Should only be called from within synthesis thread, which includes
5800
* SoundFont loader preset noteon methods. Voices are only guaranteed to remain
5801
* unchanged until next synthesis process iteration.
5802
*/
5803
void
5804
fluid_synth_get_voicelist(fluid_synth_t *synth, fluid_voice_t *buf[], int bufsize,
5805
int id)
5806
{
5807
int count = 0;
5808
int i;
5809
5810
fluid_return_if_fail(synth != NULL);
5811
fluid_return_if_fail(buf != NULL);
5812
fluid_synth_api_enter(synth);
5813
5814
for(i = 0; i < synth->polyphony && count < bufsize; i++)
5815
{
5816
fluid_voice_t *voice = synth->voice[i];
5817
5818
if(fluid_voice_is_playing(voice) && (id < 0 || (int)voice->id == id))
5819
{
5820
buf[count++] = voice;
5821
}
5822
}
5823
5824
if(count < bufsize)
5825
{
5826
buf[count] = NULL;
5827
}
5828
5829
fluid_synth_api_exit(synth);
5830
}
5831
5832
/**
5833
* Enable or disable reverb effect.
5834
* @param synth FluidSynth instance
5835
* @param on TRUE to enable chorus, FALSE to disable
5836
* @deprecated Use fluid_synth_reverb_on() instead.
5837
*/
5838
void
5839
fluid_synth_set_reverb_on(fluid_synth_t *synth, int on)
5840
{
5841
fluid_return_if_fail(synth != NULL);
5842
fluid_synth_api_enter(synth);
5843
5844
synth->with_reverb = (on != 0);
5845
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled,
5846
on != 0, 0.0f);
5847
fluid_synth_api_exit(synth);
5848
}
5849
5850
/**
5851
* Enable or disable reverb on one fx group unit.
5852
* @param synth FluidSynth instance
5853
* @param fx_group Index of the fx group.
5854
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
5855
* parameter will be applied to all fx groups.
5856
* @param on TRUE to enable reverb, FALSE to disable
5857
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5858
*/
5859
int
5860
fluid_synth_reverb_on(fluid_synth_t *synth, int fx_group, int on)
5861
{
5862
int ret;
5863
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
5864
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5865
5866
fluid_synth_api_enter(synth);
5867
5868
if(fx_group < -1 || fx_group >= synth->effects_groups)
5869
{
5870
FLUID_API_RETURN(FLUID_FAILED);
5871
}
5872
5873
if(fx_group < 0 )
5874
{
5875
synth->with_reverb = (on != 0);
5876
}
5877
5878
param[0].i = fx_group;
5879
param[1].i = on;
5880
ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
5881
fluid_rvoice_mixer_reverb_enable,
5882
synth->eventhandler->mixer,
5883
param);
5884
5885
FLUID_API_RETURN(ret);
5886
}
5887
5888
/**
5889
* Activate a reverb preset.
5890
* @param synth FluidSynth instance
5891
* @param num Reverb preset number
5892
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5893
*
5894
* @note Currently private to libfluidsynth.
5895
*/
5896
int
5897
fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num)
5898
{
5899
double values[FLUID_REVERB_PARAM_LAST];
5900
5901
fluid_return_val_if_fail(
5902
num < FLUID_N_ELEMENTS(revmodel_preset),
5903
FLUID_FAILED
5904
);
5905
5906
values[FLUID_REVERB_ROOMSIZE] = revmodel_preset[num].roomsize;
5907
values[FLUID_REVERB_DAMP] = revmodel_preset[num].damp;
5908
values[FLUID_REVERB_WIDTH] = revmodel_preset[num].width;
5909
values[FLUID_REVERB_LEVEL] = revmodel_preset[num].level;
5910
fluid_synth_set_reverb_full(synth, -1, FLUID_REVMODEL_SET_ALL, values);
5911
return FLUID_OK;
5912
}
5913
5914
/**
5915
* Set reverb parameters to all groups.
5916
*
5917
* @param synth FluidSynth instance
5918
* @param roomsize Reverb room size value (0.0-1.0)
5919
* @param damping Reverb damping value (0.0-1.0)
5920
* @param width Reverb width value (0.0-100.0)
5921
* @param level Reverb level value (0.0-1.0)
5922
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5923
* @deprecated Use the individual reverb setter functions in new code instead.
5924
*/
5925
int
5926
fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping,
5927
double width, double level)
5928
{
5929
double values[FLUID_REVERB_PARAM_LAST];
5930
5931
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
5932
5933
values[FLUID_REVERB_ROOMSIZE] = roomsize;
5934
values[FLUID_REVERB_DAMP] = damping;
5935
values[FLUID_REVERB_WIDTH] = width;
5936
values[FLUID_REVERB_LEVEL] = level;
5937
return fluid_synth_set_reverb_full(synth, -1, FLUID_REVMODEL_SET_ALL, values);
5938
}
5939
5940
/**
5941
* Set reverb roomsize of all groups.
5942
*
5943
* @param synth FluidSynth instance
5944
* @param roomsize Reverb room size value (0.0-1.0)
5945
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5946
* @deprecated Use fluid_synth_set_reverb_group_roomsize() in new code instead.
5947
*/
5948
int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize)
5949
{
5950
return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_ROOMSIZE, roomsize);
5951
}
5952
5953
/**
5954
* Set reverb damping of all groups.
5955
*
5956
* @param synth FluidSynth instance
5957
* @param damping Reverb damping value (0.0-1.0)
5958
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5959
* @deprecated Use fluid_synth_set_reverb_group_damp() in new code instead.
5960
*/
5961
int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping)
5962
{
5963
return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_DAMP, damping);
5964
}
5965
5966
/**
5967
* Set reverb width of all groups.
5968
*
5969
* @param synth FluidSynth instance
5970
* @param width Reverb width value (0.0-100.0)
5971
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5972
* @deprecated Use fluid_synth_set_reverb_group_width() in new code instead.
5973
*/
5974
int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width)
5975
{
5976
return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_WIDTH, width);
5977
}
5978
5979
/**
5980
* Set reverb level of all groups.
5981
*
5982
* @param synth FluidSynth instance
5983
* @param level Reverb level value (0.0-1.0)
5984
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
5985
* @deprecated Use fluid_synth_set_reverb_group_level() in new code instead.
5986
*/
5987
int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level)
5988
{
5989
return fluid_synth_reverb_set_param(synth, -1, FLUID_REVERB_LEVEL, level);
5990
}
5991
5992
/**
5993
* Set reverb roomsize to one or all fx groups.
5994
* @param synth FluidSynth instance.
5995
* @param fx_group Index of the fx group.
5996
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
5997
* parameter will be applied to all fx groups.
5998
* @param roomsize roomsize value to set. Must be in the range indicated by
5999
* synth.reverb.room-size setting.
6000
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6001
*/
6002
int fluid_synth_set_reverb_group_roomsize(fluid_synth_t *synth, int fx_group,
6003
double roomsize)
6004
{
6005
return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_ROOMSIZE, roomsize);
6006
}
6007
6008
/**
6009
* Set reverb damp to one or all fx groups.
6010
* @param synth FluidSynth instance.
6011
* @param fx_group Index of the fx group.
6012
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6013
* parameter will be applied to all fx groups.
6014
* @param damping damping value to set. Must be in the range indicated by
6015
* synth.reverb.damp setting.
6016
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6017
*/
6018
int fluid_synth_set_reverb_group_damp(fluid_synth_t *synth, int fx_group,
6019
double damping)
6020
{
6021
return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_DAMP, damping);
6022
}
6023
6024
/**
6025
* Set reverb width to one or all fx groups.
6026
* @param synth FluidSynth instance.
6027
* @param fx_group Index of the fx group.
6028
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6029
* parameter will be applied to all fx groups.
6030
* @param width width value to set. Must be in the range indicated by
6031
* synth.reverb.width setting.
6032
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6033
*/
6034
int fluid_synth_set_reverb_group_width(fluid_synth_t *synth, int fx_group,
6035
double width)
6036
{
6037
return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_WIDTH, width);
6038
}
6039
6040
/**
6041
* Set reverb level to one or all fx groups.
6042
* @param synth FluidSynth instance.
6043
* @param fx_group Index of the fx group.
6044
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6045
* parameter will be applied to all fx groups.
6046
* @param level output level to set. Must be in the range indicated by
6047
* synth.reverb.level setting.
6048
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6049
*/
6050
int fluid_synth_set_reverb_group_level(fluid_synth_t *synth, int fx_group,
6051
double level)
6052
{
6053
return fluid_synth_reverb_set_param(synth, fx_group, FLUID_REVERB_LEVEL, level);
6054
}
6055
6056
/**
6057
* Set one reverb parameter to one fx groups.
6058
* @param synth FluidSynth instance.
6059
* @param fx_group Index of the fx group.
6060
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6061
* parameter will be applied to all fx groups.
6062
* @param enum indicating the parameter to set (#fluid_reverb_param).
6063
* FLUID_REVERB_ROOMSIZE, roomsize Reverb room size value (0.0-1.0)
6064
* FLUID_REVERB_DAMP, reverb damping value (0.0-1.0)
6065
* FLUID_REVERB_WIDTH, reverb width value (0.0-100.0)
6066
* FLUID_REVERB_LEVEL, reverb level value (0.0-1.0)
6067
* @param value, parameter value
6068
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6069
*/
6070
int
6071
fluid_synth_reverb_set_param(fluid_synth_t *synth, int fx_group,
6072
int param, double value)
6073
{
6074
int ret;
6075
double values[FLUID_REVERB_PARAM_LAST] = {0.0};
6076
static const char *name[FLUID_REVERB_PARAM_LAST] =
6077
{
6078
"synth.reverb.room-size", "synth.reverb.damp",
6079
"synth.reverb.width", "synth.reverb.level"
6080
};
6081
6082
double min; /* minimum value */
6083
double max; /* maximum value */
6084
6085
/* check parameters */
6086
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6087
fluid_return_val_if_fail((param >= 0) && (param < FLUID_REVERB_PARAM_LAST), FLUID_FAILED);
6088
fluid_synth_api_enter(synth);
6089
6090
if(fx_group < -1 || fx_group >= synth->effects_groups)
6091
{
6092
FLUID_API_RETURN(FLUID_FAILED);
6093
}
6094
6095
/* check if reverb value is in max min range */
6096
fluid_settings_getnum_range(synth->settings, name[param], &min, &max);
6097
if(value < min || value > max)
6098
{
6099
FLUID_API_RETURN(FLUID_FAILED);
6100
}
6101
6102
/* set the value */
6103
values[param] = value;
6104
ret = fluid_synth_set_reverb_full(synth, fx_group, FLUID_REVPARAM_TO_SETFLAG(param), values);
6105
FLUID_API_RETURN(ret);
6106
}
6107
6108
int
6109
fluid_synth_set_reverb_full(fluid_synth_t *synth, int fx_group, int set,
6110
const double values[])
6111
{
6112
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
6113
6114
/* if non of the flags is set, fail */
6115
fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
6116
6117
/* fx group shadow values are set here so that they will be returned if queried */
6118
fluid_rvoice_mixer_set_reverb_full(synth->eventhandler->mixer, fx_group, set,
6119
values);
6120
6121
/* Synth shadow values are set here so that they will be returned if queried */
6122
if (fx_group < 0)
6123
{
6124
int i;
6125
for(i = 0; i < FLUID_REVERB_PARAM_LAST; i++)
6126
{
6127
if(set & FLUID_REVPARAM_TO_SETFLAG(i))
6128
{
6129
synth->reverb_param[i] = values[i];
6130
}
6131
}
6132
}
6133
6134
param[0].i = fx_group;
6135
param[1].i = set;
6136
param[2].real = values[FLUID_REVERB_ROOMSIZE];
6137
param[3].real = values[FLUID_REVERB_DAMP];
6138
param[4].real = values[FLUID_REVERB_WIDTH];
6139
param[5].real = values[FLUID_REVERB_LEVEL];
6140
/* finally enqueue an rvoice event to the mixer to actual update reverb */
6141
return fluid_rvoice_eventhandler_push(synth->eventhandler,
6142
fluid_rvoice_mixer_set_reverb_params,
6143
synth->eventhandler->mixer,
6144
param);
6145
}
6146
6147
/**
6148
* Get reverb room size of all fx groups.
6149
* @param synth FluidSynth instance
6150
* @return Reverb room size (0.0-1.2)
6151
* @deprecated Use fluid_synth_get_reverb_group_roomsize() in new code instead.
6152
*/
6153
double
6154
fluid_synth_get_reverb_roomsize(fluid_synth_t *synth)
6155
{
6156
double roomsize = 0.0;
6157
fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_ROOMSIZE, &roomsize);
6158
return roomsize;
6159
}
6160
6161
/**
6162
* Get reverb damping of all fx groups.
6163
* @param synth FluidSynth instance
6164
* @return Reverb damping value (0.0-1.0)
6165
* @deprecated Use fluid_synth_get_reverb_group_damp() in new code instead.
6166
*/
6167
double
6168
fluid_synth_get_reverb_damp(fluid_synth_t *synth)
6169
{
6170
double damp = 0.0;
6171
fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_DAMP, &damp);
6172
return damp;
6173
}
6174
6175
/**
6176
* Get reverb level of all fx groups.
6177
* @param synth FluidSynth instance
6178
* @return Reverb level value (0.0-1.0)
6179
* @deprecated Use fluid_synth_get_reverb_group_level() in new code instead.
6180
*/
6181
double
6182
fluid_synth_get_reverb_level(fluid_synth_t *synth)
6183
{
6184
double level = 0.0;
6185
fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_LEVEL, &level);
6186
return level;
6187
}
6188
6189
/**
6190
* Get reverb width of all fx groups.
6191
* @param synth FluidSynth instance
6192
* @return Reverb width value (0.0-100.0)
6193
* @deprecated Use fluid_synth_get_reverb_group_width() in new code instead.
6194
*/
6195
double
6196
fluid_synth_get_reverb_width(fluid_synth_t *synth)
6197
{
6198
double width = 0.0;
6199
fluid_synth_reverb_get_param(synth, -1, FLUID_REVERB_WIDTH, &width);
6200
return width;
6201
}
6202
6203
/**
6204
* get reverb roomsize of one or all groups.
6205
* @param synth FluidSynth instance.
6206
* @param fx_group Index of the fx group.
6207
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6208
* parameter common to all fx groups is fetched.
6209
* @param roomsize valid pointer on the value to return.
6210
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6211
*/
6212
int fluid_synth_get_reverb_group_roomsize(fluid_synth_t *synth, int fx_group,
6213
double *roomsize)
6214
{
6215
return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_ROOMSIZE, roomsize);
6216
}
6217
6218
/**
6219
* get reverb damp of one or all groups.
6220
* @param synth FluidSynth instance.
6221
* @param fx_group Index of the fx group.
6222
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6223
* parameter common to all fx groups is fetched.
6224
* @param damping valid pointer on the value to return.
6225
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6226
*/
6227
int fluid_synth_get_reverb_group_damp(fluid_synth_t *synth, int fx_group,
6228
double *damping)
6229
{
6230
return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_DAMP, damping);
6231
}
6232
6233
/**
6234
* get reverb width of one or all groups
6235
* @param synth FluidSynth instance.
6236
* @param fx_group Index of the fx group.
6237
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6238
* parameter common to all fx groups is fetched.
6239
* @param width valid pointer on the value to return.
6240
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6241
*/
6242
int fluid_synth_get_reverb_group_width(fluid_synth_t *synth, int fx_group,
6243
double *width)
6244
{
6245
return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_WIDTH, width);
6246
}
6247
6248
/**
6249
* get reverb level of one or all groups.
6250
* @param synth FluidSynth instance.
6251
* @param fx_group Index of the fx group.
6252
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6253
* parameter common to all fx groups is fetched.
6254
* @param level valid pointer on the value to return.
6255
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6256
*/
6257
int fluid_synth_get_reverb_group_level(fluid_synth_t *synth, int fx_group,
6258
double *level)
6259
{
6260
return fluid_synth_reverb_get_param(synth, fx_group, FLUID_REVERB_LEVEL, level);
6261
}
6262
6263
6264
/**
6265
* Get one reverb parameter value of one fx groups.
6266
* @param synth FluidSynth instance
6267
* @param fx_group index of the fx group to get parameter value from.
6268
* Must be in the range -1 to synth->effects_groups-1. If -1 get the
6269
* parameter common to all fx groups.
6270
* @param enum indicating the parameter to get (#fluid_reverb_param).
6271
* FLUID_REVERB_ROOMSIZE, reverb room size value.
6272
* FLUID_REVERB_DAMP, reverb damping value.
6273
* FLUID_REVERB_WIDTH, reverb width value.
6274
* FLUID_REVERB_LEVEL, reverb level value.
6275
* @param value pointer on the value to return.
6276
* @return FLUID_OK if success, FLUID_FAILED otherwise.
6277
*/
6278
static int fluid_synth_reverb_get_param(fluid_synth_t *synth, int fx_group,
6279
int param, double *value)
6280
{
6281
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6282
fluid_return_val_if_fail((param >= 0) && (param < FLUID_REVERB_PARAM_LAST), FLUID_FAILED);
6283
fluid_return_val_if_fail(value != NULL, FLUID_FAILED);
6284
fluid_synth_api_enter(synth);
6285
6286
if(fx_group < -1 || fx_group >= synth->effects_groups)
6287
{
6288
FLUID_API_RETURN(FLUID_FAILED);
6289
}
6290
6291
if (fx_group < 0)
6292
{
6293
/* return reverb param common to all fx groups */
6294
*value = synth->reverb_param[param];
6295
}
6296
else
6297
{
6298
/* return reverb param of fx group at index fx_group */
6299
*value = fluid_rvoice_mixer_reverb_get_param(synth->eventhandler->mixer,
6300
fx_group, param);
6301
}
6302
6303
FLUID_API_RETURN(FLUID_OK);
6304
}
6305
6306
/**
6307
* Enable or disable all chorus groups.
6308
* @param synth FluidSynth instance
6309
* @param on TRUE to enable chorus, FALSE to disable
6310
* @deprecated Use fluid_synth_chorus_on() in new code instead.
6311
*/
6312
void
6313
fluid_synth_set_chorus_on(fluid_synth_t *synth, int on)
6314
{
6315
fluid_return_if_fail(synth != NULL);
6316
fluid_synth_api_enter(synth);
6317
6318
synth->with_chorus = (on != 0);
6319
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled,
6320
on != 0, 0.0f);
6321
fluid_synth_api_exit(synth);
6322
}
6323
6324
/**
6325
* Enable or disable chorus on one or all groups.
6326
* @param synth FluidSynth instance
6327
* @param fx_group Index of the fx group.
6328
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6329
* parameter will be applied to all fx groups.
6330
* @param on TRUE to enable chorus, FALSE to disable
6331
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6332
*/
6333
int
6334
fluid_synth_chorus_on(fluid_synth_t *synth, int fx_group, int on)
6335
{
6336
int ret;
6337
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
6338
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6339
6340
fluid_synth_api_enter(synth);
6341
6342
if(fx_group < -1 || fx_group >= synth->effects_groups)
6343
{
6344
FLUID_API_RETURN(FLUID_FAILED);
6345
}
6346
6347
if(fx_group < 0 )
6348
{
6349
synth->with_chorus = (on != 0);
6350
}
6351
6352
param[0].i = fx_group;
6353
param[1].i = on;
6354
ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
6355
fluid_rvoice_mixer_chorus_enable,
6356
synth->eventhandler->mixer,
6357
param);
6358
6359
FLUID_API_RETURN(ret);
6360
}
6361
6362
/**
6363
* Set chorus parameters to all fx groups.
6364
* Keep in mind, that the needed CPU time is proportional to 'nr'.
6365
* @param synth FluidSynth instance
6366
* @param nr Chorus voice count (0-99, CPU time consumption proportional to
6367
* this value)
6368
* @param level Chorus level (0.0-10.0)
6369
* @param speed Chorus speed in Hz (0.1-5.0)
6370
* @param depth_ms Chorus depth (max value depends on synth sample-rate,
6371
* 0.0-21.0 is safe for sample-rate values up to 96KHz)
6372
* @param type Chorus waveform type (#fluid_chorus_mod)
6373
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6374
* @deprecated Use the individual chorus setter functions in new code instead.
6375
*
6376
* Keep in mind, that the needed CPU time is proportional to 'nr'.
6377
*/
6378
int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
6379
double speed, double depth_ms, int type)
6380
{
6381
double values[FLUID_CHORUS_PARAM_LAST];
6382
6383
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6384
6385
values[FLUID_CHORUS_NR] = nr;
6386
values[FLUID_CHORUS_LEVEL] = level;
6387
values[FLUID_CHORUS_SPEED] = speed;
6388
values[FLUID_CHORUS_DEPTH] = depth_ms;
6389
values[FLUID_CHORUS_TYPE] = type;
6390
return fluid_synth_set_chorus_full(synth, -1, FLUID_CHORUS_SET_ALL, values);
6391
}
6392
6393
/**
6394
* Set the chorus voice count of all groups.
6395
*
6396
* @param synth FluidSynth instance
6397
* @param nr Chorus voice count (0-99, CPU time consumption proportional to
6398
* this value)
6399
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6400
* @deprecated Use fluid_synth_set_chorus_group_nr() in new code instead.
6401
*/
6402
int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr)
6403
{
6404
return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_NR, nr);
6405
}
6406
6407
/**
6408
* Set the chorus level of all groups.
6409
*
6410
* @param synth FluidSynth instance
6411
* @param level Chorus level (0.0-10.0)
6412
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6413
* @deprecated Use fluid_synth_set_chorus_group_level() in new code instead.
6414
*/
6415
int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level)
6416
{
6417
return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_LEVEL, level);
6418
}
6419
6420
/**
6421
* Set the chorus speed of all groups.
6422
*
6423
* @param synth FluidSynth instance
6424
* @param speed Chorus speed in Hz (0.1-5.0)
6425
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6426
* @deprecated Use fluid_synth_set_chorus_group_speed() in new code instead.
6427
*/
6428
int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed)
6429
{
6430
return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_SPEED, speed);
6431
}
6432
6433
/**
6434
* Set the chorus depth of all groups.
6435
*
6436
* @param synth FluidSynth instance
6437
* @param depth_ms Chorus depth (max value depends on synth sample-rate,
6438
* 0.0-21.0 is safe for sample-rate values up to 96KHz)
6439
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6440
* @deprecated Use fluid_synth_set_chorus_group_depth() in new code instead.
6441
*/
6442
int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms)
6443
{
6444
return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_DEPTH, depth_ms);
6445
}
6446
6447
/**
6448
* Set the chorus type of all groups.
6449
*
6450
* @param synth FluidSynth instance
6451
* @param type Chorus waveform type (#fluid_chorus_mod)
6452
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6453
* @deprecated Use fluid_synth_set_chorus_group_type() in new code instead.
6454
*/
6455
int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type)
6456
{
6457
return fluid_synth_chorus_set_param(synth, -1, FLUID_CHORUS_TYPE, type);
6458
}
6459
6460
/**
6461
* Set chorus voice count nr to one or all chorus groups.
6462
* @param synth FluidSynth instance.
6463
* @param fx_group Index of the fx group.
6464
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6465
* parameter will be applied to all groups.
6466
* @param nr Voice count to set. Must be in the range indicated by \setting{synth_chorus_nr}
6467
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6468
*/
6469
int
6470
fluid_synth_set_chorus_group_nr(fluid_synth_t *synth, int fx_group, int nr)
6471
{
6472
return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_NR, (double)nr);
6473
}
6474
6475
/**
6476
* Set chorus output level to one or all chorus groups.
6477
* @param synth FluidSynth instance.
6478
* @param fx_group Index of the fx group.
6479
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6480
* parameter will be applied to all groups.
6481
* @param level Output level to set. Must be in the range indicated by \setting{synth_chorus_level}
6482
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6483
*/
6484
int
6485
fluid_synth_set_chorus_group_level(fluid_synth_t *synth, int fx_group, double level)
6486
{
6487
return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_LEVEL, level);
6488
}
6489
6490
/**
6491
* Set chorus lfo speed to one or all chorus groups.
6492
* @param synth FluidSynth instance.
6493
* @param fx_group Index of the fx group.
6494
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6495
* parameter will be applied to all groups.
6496
* @param speed Lfo speed to set. Must be in the range indicated by \setting{synth_chorus_speed}
6497
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6498
*/
6499
int
6500
fluid_synth_set_chorus_group_speed(fluid_synth_t *synth, int fx_group, double speed)
6501
{
6502
return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_SPEED, speed);
6503
}
6504
6505
/**
6506
* Set chorus lfo depth to one or all chorus groups.
6507
* @param synth FluidSynth instance.
6508
* @param fx_group Index of the fx group.
6509
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6510
* parameter will be applied to all groups.
6511
* @param depth_ms lfo depth to set. Must be in the range indicated by \setting{synth_chorus_depth}
6512
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6513
*/
6514
int
6515
fluid_synth_set_chorus_group_depth(fluid_synth_t *synth, int fx_group, double depth_ms)
6516
{
6517
return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_DEPTH, depth_ms);
6518
}
6519
6520
/**
6521
* Set chorus lfo waveform type to one or all chorus groups.
6522
* @param synth FluidSynth instance.
6523
* @param fx_group Index of the fx group.
6524
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6525
* parameter will be applied to all groups.
6526
* @param type Lfo waveform type to set. (#fluid_chorus_mod)
6527
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6528
*/
6529
int
6530
fluid_synth_set_chorus_group_type(fluid_synth_t *synth, int fx_group, int type)
6531
{
6532
return fluid_synth_chorus_set_param(synth, fx_group, FLUID_CHORUS_TYPE, (double)type);
6533
}
6534
6535
/**
6536
* Set one chorus parameter to one fx groups.
6537
* @param synth FluidSynth instance.
6538
* @param fx_group Index of the fx group.
6539
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6540
* parameter will be applied to all groups.
6541
* @param enum indicating the parameter to set (#fluid_chorus_param).
6542
* FLUID_CHORUS_NR, chorus voice count (0-99, CPU time consumption proportional to
6543
* this value).
6544
* FLUID_CHORUS_LEVEL, chorus level (0.0-10.0).
6545
* FLUID_CHORUS_SPEED, chorus speed in Hz (0.1-5.0).
6546
* FLUID_CHORUS_DEPTH, chorus depth (max value depends on synth sample-rate,
6547
* 0.0-21.0 is safe for sample-rate values up to 96KHz).
6548
* FLUID_CHORUS_TYPE, chorus waveform type (#fluid_chorus_mod)
6549
* @param value, parameter value
6550
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6551
*/
6552
int
6553
fluid_synth_chorus_set_param(fluid_synth_t *synth, int fx_group, int param,
6554
double value)
6555
{
6556
int ret;
6557
double values[FLUID_CHORUS_PARAM_LAST] = {0.0};
6558
6559
/* setting name (except lfo waveform type) */
6560
static const char *name[FLUID_CHORUS_PARAM_LAST-1] =
6561
{
6562
"synth.chorus.nr", "synth.chorus.level",
6563
"synth.chorus.speed", "synth.chorus.depth"
6564
};
6565
6566
/* check parameters */
6567
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6568
fluid_return_val_if_fail((param >= 0) && (param < FLUID_CHORUS_PARAM_LAST), FLUID_FAILED);
6569
fluid_synth_api_enter(synth);
6570
6571
if(fx_group < -1 || fx_group >= synth->effects_groups)
6572
{
6573
FLUID_API_RETURN(FLUID_FAILED);
6574
}
6575
6576
/* check if chorus value is in max min range */
6577
if(param == FLUID_CHORUS_TYPE || param == FLUID_CHORUS_NR) /* integer value */
6578
{
6579
int min = FLUID_CHORUS_MOD_SINE;
6580
int max = FLUID_CHORUS_MOD_TRIANGLE;
6581
if(param == FLUID_CHORUS_NR)
6582
{
6583
fluid_settings_getint_range(synth->settings, name[param], &min, &max);
6584
}
6585
if((int)value < min || (int)value > max)
6586
{
6587
FLUID_API_RETURN(FLUID_FAILED);
6588
}
6589
}
6590
else /* float value */
6591
{
6592
double min;
6593
double max;
6594
fluid_settings_getnum_range(synth->settings, name[param], &min, &max);
6595
if(value < min || value > max)
6596
{
6597
FLUID_API_RETURN(FLUID_FAILED);
6598
}
6599
}
6600
6601
/* set the value */
6602
values[param] = value;
6603
ret = fluid_synth_set_chorus_full(synth, fx_group,
6604
FLUID_CHORPARAM_TO_SETFLAG(param), values);
6605
FLUID_API_RETURN(ret);
6606
}
6607
6608
int
6609
fluid_synth_set_chorus_full(fluid_synth_t *synth, int fx_group, int set,
6610
const double values[])
6611
{
6612
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
6613
6614
/* if non of the flags is set, fail */
6615
fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
6616
6617
/* fx group shadow values are set here so that they will be returned if queried */
6618
fluid_rvoice_mixer_set_chorus_full(synth->eventhandler->mixer, fx_group,
6619
set, values);
6620
6621
/* Synth shadow values are set here so that they will be returned if queried */
6622
if (fx_group < 0)
6623
{
6624
int i;
6625
for(i = 0; i < FLUID_CHORUS_PARAM_LAST; i++)
6626
{
6627
if(set & FLUID_CHORPARAM_TO_SETFLAG(i))
6628
{
6629
synth->chorus_param[i] = values[i];
6630
}
6631
}
6632
}
6633
6634
param[0].i = fx_group;
6635
param[1].i = set;
6636
param[2].i = (int)values[FLUID_CHORUS_NR];
6637
param[3].real = values[FLUID_CHORUS_LEVEL];
6638
param[4].real = values[FLUID_CHORUS_SPEED];
6639
param[5].real = values[FLUID_CHORUS_DEPTH];
6640
param[6].i = (int)values[FLUID_CHORUS_TYPE];
6641
return fluid_rvoice_eventhandler_push(synth->eventhandler,
6642
fluid_rvoice_mixer_set_chorus_params,
6643
synth->eventhandler->mixer,
6644
param);
6645
}
6646
6647
/**
6648
* Get chorus voice number (delay line count) value of all fx groups.
6649
* @param synth FluidSynth instance
6650
* @return Chorus voice count
6651
* @deprecated Use fluid_synth_get_chorus_group_nr() in new code instead.
6652
*/
6653
int
6654
fluid_synth_get_chorus_nr(fluid_synth_t *synth)
6655
{
6656
double nr = 0.0;
6657
fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_NR, &nr);
6658
return (int)nr;
6659
}
6660
6661
/**
6662
* Get chorus level of all fx groups.
6663
* @param synth FluidSynth instance
6664
* @return Chorus level value
6665
* @deprecated Use fluid_synth_get_chorus_group_level() in new code instead.
6666
*/
6667
double
6668
fluid_synth_get_chorus_level(fluid_synth_t *synth)
6669
{
6670
double level = 0.0;
6671
fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_LEVEL, &level);
6672
return level;
6673
}
6674
6675
/**
6676
* Get chorus speed in Hz of all fx groups.
6677
* @param synth FluidSynth instance
6678
* @return Chorus speed in Hz
6679
* @deprecated Use fluid_synth_get_chorus_group_speed() in new code instead.
6680
*/
6681
double
6682
fluid_synth_get_chorus_speed(fluid_synth_t *synth)
6683
{
6684
double speed = 0.0;
6685
fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_SPEED, &speed);
6686
return speed;
6687
}
6688
6689
/**
6690
* Get chorus depth of all fx groups.
6691
* @param synth FluidSynth instance
6692
* @return Chorus depth
6693
* @deprecated Use fluid_synth_get_chorus_group_depth() in new code instead.
6694
*/
6695
double
6696
fluid_synth_get_chorus_depth(fluid_synth_t *synth)
6697
{
6698
double depth = 0.0;
6699
fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_DEPTH, &depth);
6700
return depth;
6701
}
6702
6703
/**
6704
* Get chorus waveform type of all fx groups.
6705
* @param synth FluidSynth instance
6706
* @return Chorus waveform type (#fluid_chorus_mod)
6707
* @deprecated Use fluid_synth_get_chorus_group_type() in new code instead.
6708
*/
6709
int
6710
fluid_synth_get_chorus_type(fluid_synth_t *synth)
6711
{
6712
double type = 0.0;
6713
fluid_synth_chorus_get_param(synth, -1, FLUID_CHORUS_TYPE, &type);
6714
return (int)type;
6715
}
6716
6717
/**
6718
* Get chorus count nr of one or all fx groups.
6719
* @param synth FluidSynth instance.
6720
* @param fx_group Index of the fx group from which to fetch the chorus voice count.
6721
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6722
* parameter common to all fx groups is fetched.
6723
* @param nr valid pointer on value to return.
6724
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6725
*/
6726
int
6727
fluid_synth_get_chorus_group_nr(fluid_synth_t *synth, int fx_group, int *nr)
6728
{
6729
double num_nr = 0.0;
6730
int status;
6731
status = fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_NR, &num_nr);
6732
*nr = (int)num_nr;
6733
return status;
6734
}
6735
6736
/**
6737
* Get chorus output level of one or all fx groups.
6738
* @param synth FluidSynth instance.
6739
* @param fx_group Index of the fx group from which chorus level to fetch.
6740
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6741
* parameter common to all fx groups is fetched.
6742
* @param level valid pointer on value to return.
6743
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6744
*/
6745
int
6746
fluid_synth_get_chorus_group_level(fluid_synth_t *synth, int fx_group, double *level)
6747
{
6748
return fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_LEVEL, level);
6749
}
6750
6751
/**
6752
* Get chorus waveform lfo speed of one or all fx groups.
6753
* @param synth FluidSynth instance.
6754
* @param fx_group Index of the fx group from which lfo speed to fetch.
6755
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6756
* parameter common to all fx groups is fetched.
6757
* @param speed valid pointer on value to return.
6758
* @return #FLUID_OK on success, #FLUID_FAILED otherwise.
6759
*/
6760
int
6761
fluid_synth_get_chorus_group_speed(fluid_synth_t *synth, int fx_group, double *speed)
6762
{
6763
return fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_SPEED, speed);
6764
}
6765
6766
/**
6767
* Get chorus lfo depth of one or all fx groups.
6768
* @param synth FluidSynth instance
6769
* @param fx_group Index of the fx group from which lfo depth to fetch.
6770
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6771
* parameter common to all fx groups is fetched.
6772
* @param depth_ms valid pointer on value to return.
6773
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6774
*/
6775
int
6776
fluid_synth_get_chorus_group_depth(fluid_synth_t *synth, int fx_group, double *depth_ms)
6777
{
6778
return fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_DEPTH, depth_ms);
6779
}
6780
6781
/**
6782
* Get chorus waveform type of one or all fx groups.
6783
* @param synth FluidSynth instance
6784
* @param fx_group Index of the fx group from which to fetch the waveform type.
6785
* Must be in the range <code>-1 to (fluid_synth_count_effects_groups()-1)</code>. If -1 the
6786
* parameter common to all fx groups is fetched.
6787
* @param type valid pointer on waveform type to return (#fluid_chorus_mod)
6788
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6789
*/
6790
int
6791
fluid_synth_get_chorus_group_type(fluid_synth_t *synth, int fx_group, int *type)
6792
{
6793
double num_type = 0.0;
6794
int status;
6795
status = fluid_synth_chorus_get_param(synth, fx_group, FLUID_CHORUS_TYPE, &num_type);
6796
*type = (int)num_type;
6797
return status;
6798
}
6799
6800
/**
6801
* Get chorus parameter value of one or all fx groups.
6802
* @param synth FluidSynth instance
6803
* @param fx_group index of the fx group
6804
* @param enum indicating the parameter to get.
6805
* FLUID_CHORUS_NR, chorus voice count.
6806
* FLUID_CHORUS_LEVEL, chorus level.
6807
* FLUID_CHORUS_SPEED, chorus speed.
6808
* FLUID_CHORUS_DEPTH, chorus depth.
6809
* FLUID_CHORUS_TYPE, chorus waveform type.
6810
* @param value pointer on the value to return.
6811
* @return FLUID_OK if success, FLUID_FAILED otherwise.
6812
*/
6813
static int fluid_synth_chorus_get_param(fluid_synth_t *synth, int fx_group,
6814
int param, double *value)
6815
{
6816
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6817
fluid_return_val_if_fail((param >= 0) && (param < FLUID_CHORUS_PARAM_LAST), FLUID_FAILED);
6818
fluid_return_val_if_fail(value != NULL, FLUID_FAILED);
6819
fluid_synth_api_enter(synth);
6820
6821
if(fx_group < -1 || fx_group >= synth->effects_groups)
6822
{
6823
FLUID_API_RETURN(FLUID_FAILED);
6824
}
6825
6826
if (fx_group < 0)
6827
{
6828
/* return chorus param common to all fx groups */
6829
*value = synth->chorus_param[param];
6830
}
6831
else
6832
{
6833
/* return chorus param of fx group at index group */
6834
*value = fluid_rvoice_mixer_chorus_get_param(synth->eventhandler->mixer,
6835
fx_group, param);
6836
}
6837
6838
FLUID_API_RETURN(FLUID_OK);
6839
}
6840
6841
/*
6842
* If the same note is hit twice on the same channel, then the older
6843
* voice process is advanced to the release stage. Using a mechanical
6844
* MIDI controller, the only way this can happen is when the sustain
6845
* pedal is held. In this case the behaviour implemented here is
6846
* natural for many instruments. Note: One noteon event can trigger
6847
* several voice processes, for example a stereo sample. Don't
6848
* release those...
6849
*/
6850
void
6851
fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan,
6852
int key)
6853
{
6854
int i;
6855
fluid_voice_t *voice;
6856
6857
/* storeid is a parameter for fluid_voice_init() */
6858
synth->storeid = synth->noteid++;
6859
6860
/* for "monophonic playing" key is the previous sustained note
6861
if it exists (0 to 127) or INVALID_NOTE otherwise */
6862
if(key == INVALID_NOTE)
6863
{
6864
return;
6865
}
6866
6867
for(i = 0; i < synth->polyphony; i++)
6868
{
6869
voice = synth->voice[i];
6870
6871
if(fluid_voice_is_playing(voice)
6872
&& (fluid_voice_get_channel(voice) == chan)
6873
&& (fluid_voice_get_key(voice) == key)
6874
&& (fluid_voice_get_id(voice) != synth->noteid))
6875
{
6876
enum fluid_midi_channel_type type = synth->channel[chan]->channel_type;
6877
6878
/* Id of voices that was sustained by sostenuto */
6879
if(fluid_voice_is_sostenuto(voice))
6880
{
6881
synth->storeid = fluid_voice_get_id(voice);
6882
}
6883
6884
switch(type)
6885
{
6886
case CHANNEL_TYPE_DRUM:
6887
/* release the voice, this should make riding hi-hats or snares sound more
6888
* realistic (Discussion #1196) */
6889
fluid_voice_off(voice);
6890
break;
6891
case CHANNEL_TYPE_MELODIC:
6892
/* Force the voice into release stage except if pedaling (sostenuto or sustain) is active.
6893
* This gives a more realistic sound to pianos and possibly other instruments (see PR #905). */
6894
fluid_voice_noteoff(voice);
6895
break;
6896
default:
6897
FLUID_LOG(FLUID_ERR, "This should never happen: unknown channel type %d", (int)type);
6898
break;
6899
}
6900
}
6901
}
6902
}
6903
6904
/**
6905
* Set synthesis interpolation method on one or all MIDI channels.
6906
* @param synth FluidSynth instance
6907
* @param chan MIDI channel to set interpolation method on or -1 for all channels
6908
* @param interp_method Interpolation method (#fluid_interp)
6909
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
6910
*/
6911
int
6912
fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method)
6913
{
6914
int i;
6915
6916
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
6917
fluid_synth_api_enter(synth);
6918
6919
if(chan < -1 || chan >= synth->midi_channels)
6920
{
6921
FLUID_API_RETURN(FLUID_FAILED);
6922
}
6923
6924
if(synth->channel[0] == NULL)
6925
{
6926
FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!");
6927
FLUID_API_RETURN(FLUID_FAILED);
6928
}
6929
6930
for(i = 0; i < synth->midi_channels; i++)
6931
{
6932
if(chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan)
6933
{
6934
fluid_channel_set_interp_method(synth->channel[i], interp_method);
6935
}
6936
}
6937
6938
FLUID_API_RETURN(FLUID_OK);
6939
};
6940
6941
/**
6942
* Get the total count of MIDI channels.
6943
* @param synth FluidSynth instance
6944
* @return Count of MIDI channels
6945
*/
6946
int
6947
fluid_synth_count_midi_channels(fluid_synth_t *synth)
6948
{
6949
int result;
6950
fluid_return_val_if_fail(synth != NULL, 0);
6951
fluid_synth_api_enter(synth);
6952
6953
result = synth->midi_channels;
6954
FLUID_API_RETURN(result);
6955
}
6956
6957
/**
6958
* Get the total count of audio channels.
6959
* @param synth FluidSynth instance
6960
* @return Count of audio channel stereo pairs (1 = 2 channels, 2 = 4, etc)
6961
*/
6962
int
6963
fluid_synth_count_audio_channels(fluid_synth_t *synth)
6964
{
6965
int result;
6966
fluid_return_val_if_fail(synth != NULL, 0);
6967
fluid_synth_api_enter(synth);
6968
6969
result = synth->audio_channels;
6970
FLUID_API_RETURN(result);
6971
}
6972
6973
/**
6974
* Get the total number of allocated audio channels. Usually identical to the
6975
* number of audio channels. Can be employed by LADSPA effects subsystem.
6976
*
6977
* @param synth FluidSynth instance
6978
* @return Count of audio group stereo pairs (1 = 2 channels, 2 = 4, etc)
6979
*/
6980
int
6981
fluid_synth_count_audio_groups(fluid_synth_t *synth)
6982
{
6983
int result;
6984
fluid_return_val_if_fail(synth != NULL, 0);
6985
fluid_synth_api_enter(synth);
6986
6987
result = synth->audio_groups;
6988
FLUID_API_RETURN(result);
6989
}
6990
6991
/**
6992
* Get the total number of allocated effects channels.
6993
* @param synth FluidSynth instance
6994
* @return Count of allocated effects channels
6995
*/
6996
int
6997
fluid_synth_count_effects_channels(fluid_synth_t *synth)
6998
{
6999
int result;
7000
fluid_return_val_if_fail(synth != NULL, 0);
7001
fluid_synth_api_enter(synth);
7002
7003
result = synth->effects_channels;
7004
FLUID_API_RETURN(result);
7005
}
7006
7007
/**
7008
* Get the total number of allocated effects units.
7009
*
7010
* This is the same number as initially provided by the setting \setting{synth_effects-groups}.
7011
* @param synth FluidSynth instance
7012
* @return Count of allocated effects units
7013
*/
7014
int
7015
fluid_synth_count_effects_groups(fluid_synth_t *synth)
7016
{
7017
int result;
7018
fluid_return_val_if_fail(synth != NULL, 0);
7019
fluid_synth_api_enter(synth);
7020
7021
result = synth->effects_groups;
7022
FLUID_API_RETURN(result);
7023
}
7024
7025
/**
7026
* Get the synth CPU load value.
7027
* @param synth FluidSynth instance
7028
* @return Estimated CPU load value in percent (0-100)
7029
*/
7030
double
7031
fluid_synth_get_cpu_load(fluid_synth_t *synth)
7032
{
7033
fluid_return_val_if_fail(synth != NULL, 0);
7034
return fluid_atomic_float_get(&synth->cpu_load);
7035
}
7036
7037
/* Get tuning for a given bank:program */
7038
static fluid_tuning_t *
7039
fluid_synth_get_tuning(fluid_synth_t *synth, int bank, int prog)
7040
{
7041
7042
if((synth->tuning == NULL) ||
7043
(synth->tuning[bank] == NULL) ||
7044
(synth->tuning[bank][prog] == NULL))
7045
{
7046
return NULL;
7047
}
7048
7049
return synth->tuning[bank][prog];
7050
}
7051
7052
/* Replace tuning on a given bank:program (need not already exist).
7053
* Synth mutex should already be locked by caller. */
7054
static int
7055
fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth, fluid_tuning_t *tuning,
7056
int bank, int prog, int apply)
7057
{
7058
fluid_tuning_t *old_tuning;
7059
7060
if(synth->tuning == NULL)
7061
{
7062
synth->tuning = FLUID_ARRAY(fluid_tuning_t **, 128);
7063
7064
if(synth->tuning == NULL)
7065
{
7066
FLUID_LOG(FLUID_PANIC, "Out of memory");
7067
return FLUID_FAILED;
7068
}
7069
7070
FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t **));
7071
}
7072
7073
if(synth->tuning[bank] == NULL)
7074
{
7075
synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t *, 128);
7076
7077
if(synth->tuning[bank] == NULL)
7078
{
7079
FLUID_LOG(FLUID_PANIC, "Out of memory");
7080
return FLUID_FAILED;
7081
}
7082
7083
FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t *));
7084
}
7085
7086
old_tuning = synth->tuning[bank][prog];
7087
synth->tuning[bank][prog] = tuning;
7088
7089
if(old_tuning)
7090
{
7091
if(!fluid_tuning_unref(old_tuning, 1)) /* -- unref old tuning */
7092
{
7093
/* Replace old tuning if present */
7094
fluid_synth_replace_tuning_LOCAL(synth, old_tuning, tuning, apply, FALSE);
7095
}
7096
}
7097
7098
return FLUID_OK;
7099
}
7100
7101
/* Replace a tuning with a new one in all MIDI channels. new_tuning can be
7102
* NULL, in which case channels are reset to default equal tempered scale. */
7103
static void
7104
fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth, fluid_tuning_t *old_tuning,
7105
fluid_tuning_t *new_tuning, int apply, int unref_new)
7106
{
7107
fluid_channel_t *channel;
7108
int old_tuning_unref = 0;
7109
int i;
7110
7111
for(i = 0; i < synth->midi_channels; i++)
7112
{
7113
channel = synth->channel[i];
7114
7115
if(fluid_channel_get_tuning(channel) == old_tuning)
7116
{
7117
old_tuning_unref++;
7118
7119
if(new_tuning)
7120
{
7121
fluid_tuning_ref(new_tuning); /* ++ ref new tuning for channel */
7122
}
7123
7124
fluid_channel_set_tuning(channel, new_tuning);
7125
7126
if(apply)
7127
{
7128
fluid_synth_update_voice_tuning_LOCAL(synth, channel);
7129
}
7130
}
7131
}
7132
7133
/* Send unref old tuning event if any unrefs */
7134
if(old_tuning && old_tuning_unref)
7135
{
7136
fluid_tuning_unref(old_tuning, old_tuning_unref);
7137
}
7138
7139
if(!unref_new || !new_tuning)
7140
{
7141
return;
7142
}
7143
7144
fluid_tuning_unref(new_tuning, 1);
7145
}
7146
7147
/* Update voice tunings in realtime */
7148
static void
7149
fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth, fluid_channel_t *channel)
7150
{
7151
fluid_voice_t *voice;
7152
int i;
7153
7154
for(i = 0; i < synth->polyphony; i++)
7155
{
7156
voice = synth->voice[i];
7157
7158
if(fluid_voice_is_on(voice) && (voice->channel == channel))
7159
{
7160
fluid_voice_calculate_gen_pitch(voice);
7161
fluid_voice_update_param(voice, GEN_PITCH);
7162
}
7163
}
7164
}
7165
7166
/**
7167
* Set the tuning of the entire MIDI note scale.
7168
* @param synth FluidSynth instance
7169
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
7170
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
7171
* @param name Label name for this tuning
7172
* @param pitch Array of pitch values (length of 128, each value is number of
7173
* cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
7174
* Pass NULL to create a equal tempered (normal) scale.
7175
* @param apply TRUE to apply new tuning in realtime to existing notes which
7176
* are using the replaced tuning (if any), FALSE otherwise
7177
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7178
* @since 1.1.0
7179
*/
7180
int
7181
fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog,
7182
const char *name, const double *pitch, int apply)
7183
{
7184
fluid_tuning_t *tuning;
7185
int retval = FLUID_OK;
7186
7187
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
7188
fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
7189
fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
7190
fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
7191
7192
fluid_synth_api_enter(synth);
7193
7194
tuning = new_fluid_tuning(name, bank, prog);
7195
7196
if(tuning)
7197
{
7198
if(pitch)
7199
{
7200
fluid_tuning_set_all(tuning, pitch);
7201
}
7202
7203
retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
7204
7205
if(retval == FLUID_FAILED)
7206
{
7207
fluid_tuning_unref(tuning, 1);
7208
}
7209
}
7210
else
7211
{
7212
retval = FLUID_FAILED;
7213
}
7214
7215
FLUID_API_RETURN(retval);
7216
}
7217
7218
/**
7219
* Activate an octave tuning on every octave in the MIDI note scale.
7220
* @param synth FluidSynth instance
7221
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
7222
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
7223
* @param name Label name for this tuning
7224
* @param pitch Array of pitch values (length of 12 for each note of an octave
7225
* starting at note C, values are number of offset cents to add to the normal
7226
* tuning amount)
7227
* @param apply TRUE to apply new tuning in realtime to existing notes which
7228
* are using the replaced tuning (if any), FALSE otherwise
7229
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7230
* @since 1.1.0
7231
*/
7232
int
7233
fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog,
7234
const char *name, const double *pitch, int apply)
7235
{
7236
fluid_tuning_t *tuning;
7237
int retval = FLUID_OK;
7238
7239
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
7240
fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
7241
fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
7242
fluid_return_val_if_fail(name != NULL, FLUID_FAILED);
7243
fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
7244
7245
fluid_synth_api_enter(synth);
7246
tuning = new_fluid_tuning(name, bank, prog);
7247
7248
if(tuning)
7249
{
7250
fluid_tuning_set_octave(tuning, pitch);
7251
retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply);
7252
7253
if(retval == FLUID_FAILED)
7254
{
7255
fluid_tuning_unref(tuning, 1);
7256
}
7257
}
7258
else
7259
{
7260
retval = FLUID_FAILED;
7261
}
7262
7263
FLUID_API_RETURN(retval);
7264
}
7265
7266
/**
7267
* Set tuning values for one or more MIDI notes for an existing tuning.
7268
* @param synth FluidSynth instance
7269
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
7270
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
7271
* @param len Number of MIDI notes to assign
7272
* @param key Array of MIDI key numbers (length of 'len', values 0-127)
7273
* @param pitch Array of pitch values (length of 'len', values are number of
7274
* cents from MIDI note 0)
7275
* @param apply TRUE to apply tuning change in realtime to existing notes using
7276
* the specified tuning, FALSE otherwise
7277
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7278
*
7279
* @note Prior to version 1.1.0 it was an error to specify a tuning that didn't
7280
* already exist. Starting with 1.1.0, the default equal tempered scale will be
7281
* used as a basis, if no tuning exists for the given bank and prog.
7282
*/
7283
int
7284
fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog,
7285
int len, const int *key, const double *pitch, int apply)
7286
{
7287
fluid_tuning_t *old_tuning, *new_tuning;
7288
int retval = FLUID_OK;
7289
int i;
7290
7291
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
7292
fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
7293
fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
7294
fluid_return_val_if_fail(len > 0, FLUID_FAILED);
7295
fluid_return_val_if_fail(key != NULL, FLUID_FAILED);
7296
fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED);
7297
7298
fluid_synth_api_enter(synth);
7299
7300
old_tuning = fluid_synth_get_tuning(synth, bank, prog);
7301
7302
if(old_tuning)
7303
{
7304
new_tuning = fluid_tuning_duplicate(old_tuning);
7305
}
7306
else
7307
{
7308
new_tuning = new_fluid_tuning("Unnamed", bank, prog);
7309
}
7310
7311
if(new_tuning)
7312
{
7313
for(i = 0; i < len; i++)
7314
{
7315
fluid_tuning_set_pitch(new_tuning, key[i], pitch[i]);
7316
}
7317
7318
retval = fluid_synth_replace_tuning_LOCK(synth, new_tuning, bank, prog, apply);
7319
7320
if(retval == FLUID_FAILED)
7321
{
7322
fluid_tuning_unref(new_tuning, 1);
7323
}
7324
}
7325
else
7326
{
7327
retval = FLUID_FAILED;
7328
}
7329
7330
FLUID_API_RETURN(retval);
7331
}
7332
7333
/**
7334
* Activate a tuning scale on a MIDI channel.
7335
* @param synth FluidSynth instance
7336
* @param chan MIDI channel number (0 to MIDI channel count - 1)
7337
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
7338
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
7339
* @param apply TRUE to apply tuning change to active notes, FALSE otherwise
7340
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7341
* @since 1.1.0
7342
*
7343
* @note A default equal tempered scale will be created, if no tuning exists
7344
* on the given bank and prog.
7345
*/
7346
int
7347
fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog,
7348
int apply)
7349
{
7350
fluid_tuning_t *tuning;
7351
int retval = FLUID_OK;
7352
7353
//fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
7354
//fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED);
7355
fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED);
7356
fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED);
7357
7358
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7359
7360
tuning = fluid_synth_get_tuning(synth, bank, prog);
7361
7362
/* If no tuning exists, create a new default tuning. We do this, so that
7363
* it can be replaced later, if any changes are made. */
7364
if(!tuning)
7365
{
7366
tuning = new_fluid_tuning("Unnamed", bank, prog);
7367
7368
if(tuning)
7369
{
7370
fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, FALSE);
7371
}
7372
}
7373
7374
if(tuning)
7375
{
7376
fluid_tuning_ref(tuning); /* ++ ref for outside of lock */
7377
}
7378
7379
if(!tuning)
7380
{
7381
FLUID_API_RETURN(FLUID_FAILED);
7382
}
7383
7384
fluid_tuning_ref(tuning); /* ++ ref new tuning for following function */
7385
retval = fluid_synth_set_tuning_LOCAL(synth, chan, tuning, apply);
7386
7387
fluid_tuning_unref(tuning, 1); /* -- unref for outside of lock */
7388
7389
FLUID_API_RETURN(retval);
7390
}
7391
7392
/* Local synthesis thread set tuning function (takes over tuning reference) */
7393
static int
7394
fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan,
7395
fluid_tuning_t *tuning, int apply)
7396
{
7397
fluid_tuning_t *old_tuning;
7398
fluid_channel_t *channel;
7399
7400
channel = synth->channel[chan];
7401
7402
old_tuning = fluid_channel_get_tuning(channel);
7403
fluid_channel_set_tuning(channel, tuning); /* !! Takes over callers reference */
7404
7405
if(apply)
7406
{
7407
fluid_synth_update_voice_tuning_LOCAL(synth, channel);
7408
}
7409
7410
/* Send unref old tuning event */
7411
if(old_tuning)
7412
{
7413
fluid_tuning_unref(old_tuning, 1);
7414
}
7415
7416
7417
return FLUID_OK;
7418
}
7419
7420
/**
7421
* Clear tuning scale on a MIDI channel (use default equal tempered scale).
7422
* @param synth FluidSynth instance
7423
* @param chan MIDI channel number (0 to MIDI channel count - 1)
7424
* @param apply TRUE to apply tuning change to active notes, FALSE otherwise
7425
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7426
* @since 1.1.0
7427
*/
7428
int
7429
fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply)
7430
{
7431
int retval = FLUID_OK;
7432
7433
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7434
7435
retval = fluid_synth_set_tuning_LOCAL(synth, chan, NULL, apply);
7436
7437
FLUID_API_RETURN(retval);
7438
}
7439
7440
/**
7441
* Start tuning iteration.
7442
* @param synth FluidSynth instance
7443
*/
7444
void
7445
fluid_synth_tuning_iteration_start(fluid_synth_t *synth)
7446
{
7447
fluid_return_if_fail(synth != NULL);
7448
fluid_synth_api_enter(synth);
7449
fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER(0));
7450
fluid_synth_api_exit(synth);
7451
}
7452
7453
/**
7454
* Advance to next tuning.
7455
* @param synth FluidSynth instance
7456
* @param bank Location to store MIDI bank number of next tuning scale
7457
* @param prog Location to store MIDI program number of next tuning scale
7458
* @return 1 if tuning iteration advanced, 0 if no more tunings
7459
*/
7460
int
7461
fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog)
7462
{
7463
void *pval;
7464
int b = 0, p = 0;
7465
7466
fluid_return_val_if_fail(synth != NULL, 0);
7467
fluid_return_val_if_fail(bank != NULL, 0);
7468
fluid_return_val_if_fail(prog != NULL, 0);
7469
fluid_synth_api_enter(synth);
7470
7471
/* Current tuning iteration stored as: bank << 8 | program */
7472
pval = fluid_private_get(synth->tuning_iter);
7473
p = FLUID_POINTER_TO_INT(pval);
7474
b = (p >> 8) & 0xFF;
7475
p &= 0xFF;
7476
7477
if(!synth->tuning)
7478
{
7479
FLUID_API_RETURN(0);
7480
}
7481
7482
for(; b < 128; b++, p = 0)
7483
{
7484
if(synth->tuning[b] == NULL)
7485
{
7486
continue;
7487
}
7488
7489
for(; p < 128; p++)
7490
{
7491
if(synth->tuning[b][p] == NULL)
7492
{
7493
continue;
7494
}
7495
7496
*bank = b;
7497
*prog = p;
7498
7499
if(p < 127)
7500
{
7501
fluid_private_set(synth->tuning_iter,
7502
FLUID_INT_TO_POINTER(b << 8 | (p + 1)));
7503
}
7504
else
7505
{
7506
fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER((b + 1) << 8));
7507
}
7508
7509
FLUID_API_RETURN(1);
7510
}
7511
}
7512
7513
FLUID_API_RETURN(0);
7514
}
7515
7516
/**
7517
* Get the entire note tuning for a given MIDI bank and program.
7518
* @param synth FluidSynth instance
7519
* @param bank MIDI bank number of tuning
7520
* @param prog MIDI program number of tuning
7521
* @param name Location to store tuning name or NULL to ignore
7522
* @param len Maximum number of chars to store to 'name' (including NULL byte)
7523
* @param pitch Array to store tuning scale to or NULL to ignore (len of 128)
7524
* @return #FLUID_OK if matching tuning was found, #FLUID_FAILED otherwise
7525
*/
7526
int
7527
fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog,
7528
char *name, int len, double *pitch)
7529
{
7530
fluid_tuning_t *tuning;
7531
7532
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
7533
fluid_synth_api_enter(synth);
7534
7535
tuning = fluid_synth_get_tuning(synth, bank, prog);
7536
7537
if(tuning)
7538
{
7539
if(name)
7540
{
7541
FLUID_SNPRINTF(name, len - 1, "%s", fluid_tuning_get_name(tuning));
7542
name[len - 1] = 0; /* make sure the string is null terminated */
7543
}
7544
7545
if(pitch)
7546
{
7547
FLUID_MEMCPY(pitch, fluid_tuning_get_all(tuning), 128 * sizeof(double));
7548
}
7549
}
7550
7551
FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED);
7552
}
7553
7554
/**
7555
* Get settings assigned to a synth.
7556
* @param synth FluidSynth instance
7557
* @return FluidSynth settings which are assigned to the synth
7558
*/
7559
fluid_settings_t *
7560
fluid_synth_get_settings(fluid_synth_t *synth)
7561
{
7562
fluid_return_val_if_fail(synth != NULL, NULL);
7563
7564
return synth->settings;
7565
}
7566
7567
/**
7568
* Apply an offset to a SoundFont generator on a MIDI channel.
7569
*
7570
* This function allows to set an offset for the specified destination generator in real-time.
7571
* The offset will be applied immediately to all voices that are currently and subsequently playing
7572
* on the given MIDI channel. This functionality works equivalent to using NRPN MIDI messages to
7573
* manipulate synthesis parameters. See SoundFont spec, paragraph 8.1.3, for details on SoundFont
7574
* generator parameters and valid ranges, as well as paragraph 9.6 for details on NRPN messages.
7575
* @param synth FluidSynth instance
7576
* @param chan MIDI channel number (0 to MIDI channel count - 1)
7577
* @param param SoundFont generator ID (#fluid_gen_type)
7578
* @param value Offset value (in native units of the generator) to assign to the MIDI channel
7579
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7580
*/
7581
int fluid_synth_set_gen(fluid_synth_t *synth, int chan, int param, float value)
7582
{
7583
fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
7584
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7585
7586
fluid_synth_set_gen_LOCAL(synth, chan, param, value);
7587
7588
FLUID_API_RETURN(FLUID_OK);
7589
}
7590
7591
/* Synthesis thread local set gen function */
7592
static void
7593
fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, int param, float value)
7594
{
7595
fluid_voice_t *voice;
7596
int i;
7597
7598
fluid_channel_set_gen(synth->channel[chan], param, value);
7599
7600
for(i = 0; i < synth->polyphony; i++)
7601
{
7602
voice = synth->voice[i];
7603
7604
if(fluid_voice_get_channel(voice) == chan)
7605
{
7606
fluid_voice_set_param(voice, param, value);
7607
}
7608
}
7609
}
7610
7611
// The "SB AWE32 Developer's Information Pack" provides a lookup table for the filter resonance.
7612
// Instead of a single Q value, a high and low Q value is given. This suggests a variable-Q filter design, which is
7613
// incompatible to fluidsynth's IIR filter. Therefore we need to somehow derive a single Q value.
7614
// Options are:
7615
// * mean
7616
// * geometric distance (sqrt(q_lo * q_hi))
7617
// * either q_lo or q_hi
7618
// * linear interpolation between low and high fc
7619
// * log interpolation between low and high fc
7620
static fluid_real_t
7621
calc_awe32_filter_q(int data, fluid_real_t* fc)
7622
{
7623
typedef struct
7624
{
7625
fluid_real_t fc_lo;
7626
fluid_real_t fc_hi;
7627
fluid_real_t q_lo;
7628
fluid_real_t q_hi;
7629
fluid_real_t dc_atten;
7630
} awe32_q;
7631
7632
// Q in dB
7633
static const awe32_q awe32_q_table[] =
7634
{
7635
{92, 22000, 5.f, 0.f, -0.0f }, /* coef 0 */
7636
{93, 8500, 6.f, 0.5f, -0.5f }, /* coef 1 */
7637
{94, 8300, 8.f, 1.f, -1.2f }, /* coef 2 */
7638
{95, 8200, 10.f, 2.f, -1.8f }, /* coef 3 */
7639
{96, 8100, 11.f, 3.f, -2.5f }, /* coef 4 */
7640
{97, 8000, 13.f, 4.f, -3.3f }, /* coef 5 */
7641
{98, 7900, 14.f, 5.f, -4.1f }, /* coef 6 */
7642
{99, 7800, 16.f, 6.f, -5.5f}, /* coef 7 */
7643
{100, 7700, 17.f, 7.f, -6.0f }, /* coef 8 */
7644
{100, 7500, 19.f, 9.f, -6.6f }, /* coef 9 */
7645
{100, 7400, 20.f, 10.f, -7.2f }, /* coef 10 */
7646
{100, 7300, 22.f, 11.f, -7.9f }, /* coef 11 */
7647
{100, 7200, 23.f, 13.f, -8.5f }, /* coef 12 */
7648
{100, 7100, 25.f, 15.f, -9.3f }, /* coef 13 */
7649
{100, 7100, 26.f, 16.f, -10.1f },/* coef 14 */
7650
{100, 7000, 28.f, 18.f, -11.0f}, /* coef 15 */
7651
};
7652
7653
const awe32_q* tab;
7654
fluid_real_t alpha;
7655
7656
fluid_clip(data, 0, 127);
7657
data /= 8;
7658
tab = &awe32_q_table[data];
7659
7660
fluid_clip(*fc, tab->fc_lo, tab->fc_hi);
7661
7662
alpha = (*fc - tab->fc_lo) / (tab->fc_hi - tab->fc_lo);
7663
7664
// linearly interpolate between high and low Q
7665
return 10 * /* cB */ (tab->q_lo * (1.0f - alpha) + tab->q_hi * alpha);
7666
7667
// alternatively: log interpolation
7668
// return 10 * /* cB */ FLUID_POW(tab->q_hi, alpha) * FLUID_POW(tab->q_lo, 1.0f - alpha);
7669
}
7670
7671
/**
7672
* This implementation is based on "Frequently Asked Questions for SB AWE32" http://archive.gamedev.net/archive/reference/articles/article445.html
7673
* as well as on the "SB AWE32 Developer's Information Pack" https://github.com/user-attachments/files/15757220/adip301.pdf
7674
*
7675
* @param gen the AWE32 effect or generator to manipulate
7676
* @param data the composed value of DATA_MSB and DATA_LSB
7677
*/
7678
static void fluid_synth_process_awe32_nrpn_LOCAL(fluid_synth_t *synth, int chan, int gen, int data, int data_lsb)
7679
{
7680
static const enum fluid_gen_type awe32_to_sf2_gen[] =
7681
{
7682
// assuming LFO1 maps to MODLFO and LFO2 maps to VIBLFO
7683
// observe how nicely most of the AWE32 generators here match up with the order of SF2 generators in fluid_gen_type
7684
GEN_MODLFODELAY, /**< Modulation LFO delay */
7685
GEN_MODLFOFREQ, /**< Modulation LFO frequency */
7686
GEN_VIBLFODELAY, /**< Vibrato LFO delay */
7687
GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
7688
GEN_MODENVDELAY, /**< Modulation envelope delay */
7689
GEN_MODENVATTACK, /**< Modulation envelope attack */
7690
GEN_MODENVHOLD, /**< Modulation envelope hold */
7691
GEN_MODENVDECAY, /**< Modulation envelope decay */
7692
GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
7693
GEN_MODENVRELEASE, /**< Modulation envelope release */
7694
GEN_VOLENVDELAY, /**< Volume envelope delay */
7695
GEN_VOLENVATTACK, /**< Volume envelope attack */
7696
GEN_VOLENVHOLD, /**< Volume envelope hold */
7697
GEN_VOLENVDECAY, /**< Volume envelope decay */
7698
GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
7699
GEN_VOLENVRELEASE, /**< Volume envelope release */
7700
GEN_PITCH, /**< Initial Pitch */
7701
GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
7702
GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
7703
GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
7704
GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
7705
GEN_FILTERFC, /**< Filter cutoff */
7706
GEN_FILTERQ, /**< Filter Q */
7707
GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
7708
GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
7709
GEN_CHORUSSEND, /**< Chorus send amount */
7710
GEN_REVERBSEND, /**< Reverb send amount */
7711
};
7712
7713
enum fluid_gen_type sf2_gen = awe32_to_sf2_gen[gen];
7714
int is_realtime = FALSE, i, coef;
7715
fluid_real_t converted_sf2_generator_value, q;
7716
7717
// The AWE32 NRPN docs say that a value of 8192 is considered to be the middle, i.e. zero.
7718
// However, it looks like for those generators which work in range [0,127], the AWE32 only inspects the DATA_LSB, i.e. and not doing this subtraction. Found while investigating Uplift.mid.
7719
data -= 8192;
7720
7721
switch(sf2_gen)
7722
{
7723
case GEN_MODLFODELAY:
7724
case GEN_VIBLFODELAY:
7725
case GEN_MODENVDELAY:
7726
case GEN_VOLENVDELAY:
7727
fluid_clip(data, 0, 5900);
7728
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(4.0 / 1000.0));
7729
break;
7730
7731
case GEN_MODLFOFREQ:
7732
case GEN_VIBLFOFREQ:
7733
fluid_clip(data_lsb, 0, 127);
7734
converted_sf2_generator_value = fluid_hz2ct(data_lsb * (fluid_real_t)0.084 /* Hz */);
7735
is_realtime = TRUE;
7736
break;
7737
7738
case GEN_MODENVATTACK:
7739
case GEN_VOLENVATTACK:
7740
fluid_clip(data, 0, 5940);
7741
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(1.0 / 1000.0));
7742
break;
7743
7744
case GEN_MODENVHOLD:
7745
case GEN_VOLENVHOLD:
7746
fluid_clip(data, 0, 8191);
7747
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(1.0 / 1000.0));
7748
break;
7749
7750
case GEN_MODENVDECAY:
7751
case GEN_MODENVRELEASE:
7752
case GEN_VOLENVDECAY:
7753
case GEN_VOLENVRELEASE:
7754
fluid_clip(data, 0, 5940);
7755
converted_sf2_generator_value = fluid_sec2tc(data * (fluid_real_t)(4.0 / 1000.0));
7756
break;
7757
7758
case GEN_MODENVSUSTAIN:
7759
case GEN_VOLENVSUSTAIN:
7760
fluid_clip(data_lsb, 0, 127);
7761
converted_sf2_generator_value = data_lsb * (fluid_real_t)(0.75 /* dB */ * 10) /* cB */;
7762
break;
7763
7764
case GEN_PITCH:
7765
converted_sf2_generator_value = data + 8192;
7766
// This has the side effect of manipulating the modulation state of the channel's pitchwheel, but
7767
// I'll buy it, since pitch bend is not a regular SF2 generator and we do a bit of magic there to
7768
// make it work
7769
fluid_synth_pitch_bend(synth, chan, converted_sf2_generator_value);
7770
return;
7771
7772
case GEN_MODLFOTOPITCH:
7773
case GEN_VIBLFOTOPITCH:
7774
is_realtime = TRUE;
7775
/* fallthrough */
7776
case GEN_MODENVTOPITCH:
7777
fluid_clip(data, -127, 127);
7778
converted_sf2_generator_value = data * (fluid_real_t)9.375 /* cents */;
7779
break;
7780
7781
case GEN_MODLFOTOVOL:
7782
fluid_clip(data_lsb, 0, 127);
7783
converted_sf2_generator_value = data_lsb * (fluid_real_t)(0.1875 /* dB */ * 10.0) /* cB */;
7784
is_realtime = TRUE;
7785
break;
7786
7787
case GEN_FILTERFC:
7788
fluid_clip(data_lsb, 0, 127);
7789
// Yes, DO NOT use data here, Uplift.mid doesn't set MSB=64, therefore we would always get a negative value after subtracting 8192.
7790
// Since Uplift.mid sounds fine on hardware though, it seems like AWE32 only inspects DATA_LSB in this case.
7791
// conversion continues below!
7792
converted_sf2_generator_value = (data_lsb * 62 /* Hz */);
7793
FLUID_LOG(FLUID_DBG, "AWE32 IIR Fc: %f Hz",converted_sf2_generator_value);
7794
is_realtime = TRUE;
7795
break;
7796
7797
case GEN_FILTERQ:
7798
FLUID_LOG(FLUID_DBG, "AWE32 IIR Q Tab: %d",data_lsb);
7799
synth->channel[chan]->awe32_filter_coeff = data_lsb;
7800
return;
7801
7802
case GEN_MODLFOTOFILTERFC:
7803
fluid_clip(data, -64, 63);
7804
converted_sf2_generator_value = data * (fluid_real_t)56.25 /* cents */;
7805
FLUID_LOG(FLUID_DBG, "AWE32 MOD LFO TO FILTER Fc: %f cents", converted_sf2_generator_value);
7806
is_realtime = TRUE;
7807
// not supported, as this modulates the "phase" rather than the filters cutoff frequency
7808
return;
7809
7810
case GEN_MODENVTOFILTERFC:
7811
fluid_clip(data, -127, 127);
7812
converted_sf2_generator_value = data * (fluid_real_t)56.25 /* cents */;
7813
FLUID_LOG(FLUID_DBG, "AWE32 MOD ENV TO FILTER Fc: %f cents", converted_sf2_generator_value);
7814
// not supported, as this modulates the "phase" rather than the filters cutoff frequency
7815
return;
7816
7817
case GEN_REVERBSEND:
7818
fluid_clip(data, 0, 255);
7819
/* transform the input value */
7820
converted_sf2_generator_value = fluid_mod_transform_source_value(data, default_reverb_mod.flags1, 256);
7821
FLUID_LOG(FLUID_DBG, "AWE32 Reverb: %f", converted_sf2_generator_value);
7822
converted_sf2_generator_value*= fluid_mod_get_amount(&default_reverb_mod);
7823
break;
7824
7825
case GEN_CHORUSSEND:
7826
fluid_clip(data, 0, 255);
7827
/* transform the input value */
7828
converted_sf2_generator_value = fluid_mod_transform_source_value(data, default_chorus_mod.flags1, 256);
7829
FLUID_LOG(FLUID_DBG, "AWE32 Chorus: %f", converted_sf2_generator_value);
7830
converted_sf2_generator_value*= fluid_mod_get_amount(&default_chorus_mod);
7831
break;
7832
7833
default:
7834
// should not happen
7835
FLUID_LOG(FLUID_WARN, "AWE32 NPRN %d conversion not implemented", gen);
7836
return;
7837
}
7838
7839
coef = synth->channel[chan]->awe32_filter_coeff;
7840
if(sf2_gen == GEN_FILTERFC)
7841
{
7842
// The cutoff at fc seems to be very steep for SoundBlaster! hardware. Listening tests have shown that lowering the cutoff frequency by 1000Hz gives a closer signal to the SB! hardware filter...
7843
converted_sf2_generator_value -= 1000;
7844
q = calc_awe32_filter_q(coef, &converted_sf2_generator_value);
7845
FLUID_LOG(FLUID_DBG, "AWE32 IIR Fc (corrected): %f Hz", converted_sf2_generator_value);
7846
FLUID_LOG(FLUID_DBG, "AWE32 IIR Q: %f cB", q);
7847
7848
converted_sf2_generator_value = fluid_hz2ct(converted_sf2_generator_value /* Hz */);
7849
7850
// Safe the "true initial Q"
7851
fluid_channel_set_override_gen_default(synth->channel[chan], GEN_FILTERQ, q);
7852
}
7853
7854
fluid_channel_set_override_gen_default(synth->channel[chan], sf2_gen, converted_sf2_generator_value);
7855
7856
for (i = 0; is_realtime && i < synth->polyphony; i++)
7857
{
7858
fluid_voice_t* voice = synth->voice[i];
7859
7860
if (fluid_voice_is_playing(voice) && fluid_voice_get_channel(voice) == chan)
7861
{
7862
// sets the adjusted generator
7863
fluid_voice_gen_set(voice, sf2_gen, converted_sf2_generator_value);
7864
fluid_voice_update_param(voice, sf2_gen);
7865
7866
FLUID_LOG(FLUID_DBG, "AWE32 Realtime: adjusting voice id %d, generator %d, chan %d", fluid_voice_get_id(voice), sf2_gen, chan);
7867
if(sf2_gen == GEN_FILTERFC)
7868
{
7869
// also sets the calculated Q
7870
fluid_voice_gen_set(voice, GEN_FILTERQ, q);
7871
fluid_voice_update_param(voice, GEN_FILTERQ);
7872
}
7873
}
7874
}
7875
}
7876
7877
/**
7878
* Retrieve the generator NRPN offset assigned to a MIDI channel.
7879
*
7880
* The value returned is in native units of the generator. By default, the offset is zero.
7881
* @param synth FluidSynth instance
7882
* @param chan MIDI channel number (0 to MIDI channel count - 1)
7883
* @param param SoundFont generator ID (#fluid_gen_type)
7884
* @return Current NRPN generator offset value assigned to the MIDI channel
7885
*/
7886
float
7887
fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param)
7888
{
7889
float result;
7890
fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED);
7891
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7892
7893
result = fluid_channel_get_gen(synth->channel[chan], param);
7894
FLUID_API_RETURN(result);
7895
}
7896
7897
/**
7898
* Handle MIDI event from MIDI router, used as a callback function.
7899
* @param data FluidSynth instance
7900
* @param event MIDI event to handle
7901
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7902
*/
7903
int
7904
fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event)
7905
{
7906
fluid_synth_t *synth = (fluid_synth_t *) data;
7907
int type = fluid_midi_event_get_type(event);
7908
int chan = fluid_midi_event_get_channel(event);
7909
7910
switch(type)
7911
{
7912
case NOTE_ON:
7913
return fluid_synth_noteon(synth, chan,
7914
fluid_midi_event_get_key(event),
7915
fluid_midi_event_get_velocity(event));
7916
7917
case NOTE_OFF:
7918
return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event));
7919
7920
case CONTROL_CHANGE:
7921
return fluid_synth_cc(synth, chan,
7922
fluid_midi_event_get_control(event),
7923
fluid_midi_event_get_value(event));
7924
7925
case PROGRAM_CHANGE:
7926
return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
7927
7928
case CHANNEL_PRESSURE:
7929
return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
7930
7931
case KEY_PRESSURE:
7932
return fluid_synth_key_pressure(synth, chan,
7933
fluid_midi_event_get_key(event),
7934
fluid_midi_event_get_value(event));
7935
7936
case PITCH_BEND:
7937
return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));
7938
7939
case MIDI_SYSTEM_RESET:
7940
return fluid_synth_system_reset(synth);
7941
7942
case MIDI_SYSEX:
7943
return fluid_synth_sysex(synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE);
7944
7945
case MIDI_TEXT:
7946
case MIDI_LYRIC:
7947
case MIDI_SET_TEMPO:
7948
return FLUID_OK;
7949
}
7950
7951
return FLUID_FAILED;
7952
}
7953
7954
/**
7955
* Create and start voices using an arbitrary preset and a MIDI note on event.
7956
*
7957
* Using this function is only supported when the setting @c synth.dynamic-sample-loading is false!
7958
* @param synth FluidSynth instance
7959
* @param id Voice group ID to use (can be used with fluid_synth_stop()).
7960
* @param preset Preset to synthesize
7961
* @param audio_chan Unused currently, set to 0
7962
* @param chan MIDI channel number (0 to MIDI channel count - 1)
7963
* @param key MIDI note number (0-127)
7964
* @param vel MIDI velocity number (1-127)
7965
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
7966
*
7967
* @note Should only be called from within synthesis thread, which includes
7968
* SoundFont loader preset noteon method.
7969
*/
7970
int
7971
fluid_synth_start(fluid_synth_t *synth, unsigned int id, fluid_preset_t *preset,
7972
int audio_chan, int chan, int key, int vel)
7973
{
7974
int result, dynamic_samples;
7975
fluid_return_val_if_fail(preset != NULL, FLUID_FAILED);
7976
fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED);
7977
fluid_return_val_if_fail(vel >= 1 && vel <= 127, FLUID_FAILED);
7978
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
7979
7980
fluid_settings_getint(fluid_synth_get_settings(synth), "synth.dynamic-sample-loading", &dynamic_samples);
7981
if(dynamic_samples)
7982
{
7983
// The preset might not be currently used, thus its sample data may not be loaded.
7984
// This guard is to avoid a NULL deref in rvoice_write().
7985
FLUID_LOG(FLUID_ERR, "Calling fluid_synth_start() while synth.dynamic-sample-loading is enabled is not supported.");
7986
// Although we would be able to select the preset (and load it's samples) we have no way to
7987
// unselect the preset again in fluid_synth_stop(). Also dynamic sample loading was intended
7988
// to be used only when presets have been selected on a MIDI channel.
7989
// Note that even if the preset is currently selected on a channel, it could be unselected at
7990
// any time. And we would end up with a NULL sample->data again, because we are not referencing
7991
// the preset here. Thus failure is our only option.
7992
result = FLUID_FAILED;
7993
}
7994
else
7995
{
7996
synth->storeid = id;
7997
result = fluid_preset_noteon(preset, synth, chan, key, vel);
7998
}
7999
8000
FLUID_API_RETURN(result);
8001
}
8002
8003
/**
8004
* Stop notes for a given note event voice ID.
8005
* @param synth FluidSynth instance
8006
* @param id Voice note event ID
8007
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
8008
*
8009
* @note In FluidSynth versions prior to 1.1.0 #FLUID_FAILED would be returned
8010
* if no matching voice note event ID was found. Versions after 1.1.0 only
8011
* return #FLUID_FAILED if an error occurs.
8012
*/
8013
int
8014
fluid_synth_stop(fluid_synth_t *synth, unsigned int id)
8015
{
8016
int result;
8017
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
8018
fluid_synth_api_enter(synth);
8019
fluid_synth_stop_LOCAL(synth, id);
8020
result = FLUID_OK;
8021
FLUID_API_RETURN(result);
8022
}
8023
8024
/* Local synthesis thread variant of fluid_synth_stop */
8025
static void
8026
fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id)
8027
{
8028
fluid_voice_t *voice;
8029
int i;
8030
8031
for(i = 0; i < synth->polyphony; i++)
8032
{
8033
voice = synth->voice[i];
8034
8035
if(fluid_voice_is_on(voice) && (fluid_voice_get_id(voice) == id))
8036
{
8037
fluid_voice_noteoff(voice);
8038
}
8039
}
8040
}
8041
8042
/**
8043
* Offset the bank numbers of a loaded SoundFont, i.e.\ subtract
8044
* \c offset from any bank number when assigning instruments.
8045
*
8046
* @param synth FluidSynth instance
8047
* @param sfont_id ID of a loaded SoundFont
8048
* @param offset Bank offset value to apply to all instruments
8049
* @return #FLUID_OK if the offset was set successfully, #FLUID_FAILED otherwise
8050
*/
8051
int
8052
fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset)
8053
{
8054
fluid_sfont_t *sfont;
8055
fluid_list_t *list;
8056
8057
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
8058
fluid_synth_api_enter(synth);
8059
8060
for(list = synth->sfont; list; list = fluid_list_next(list))
8061
{
8062
sfont = fluid_list_get(list);
8063
8064
if(fluid_sfont_get_id(sfont) == sfont_id)
8065
{
8066
sfont->bankofs = offset;
8067
break;
8068
}
8069
}
8070
8071
if(!list)
8072
{
8073
FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
8074
FLUID_API_RETURN(FLUID_FAILED);
8075
}
8076
8077
FLUID_API_RETURN(FLUID_OK);
8078
}
8079
8080
/**
8081
* Get bank offset of a loaded SoundFont.
8082
* @param synth FluidSynth instance
8083
* @param sfont_id ID of a loaded SoundFont
8084
* @return SoundFont bank offset value
8085
*/
8086
int
8087
fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id)
8088
{
8089
fluid_sfont_t *sfont;
8090
fluid_list_t *list;
8091
int offset = 0;
8092
8093
fluid_return_val_if_fail(synth != NULL, 0);
8094
fluid_synth_api_enter(synth);
8095
8096
for(list = synth->sfont; list; list = fluid_list_next(list))
8097
{
8098
sfont = fluid_list_get(list);
8099
8100
if(fluid_sfont_get_id(sfont) == sfont_id)
8101
{
8102
offset = sfont->bankofs;
8103
break;
8104
}
8105
}
8106
8107
if(!list)
8108
{
8109
FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id);
8110
FLUID_API_RETURN(0);
8111
}
8112
8113
FLUID_API_RETURN(offset);
8114
}
8115
8116
void
8117
fluid_synth_api_enter(fluid_synth_t *synth)
8118
{
8119
if(synth->use_mutex)
8120
{
8121
fluid_rec_mutex_lock(synth->mutex);
8122
}
8123
8124
if(!synth->public_api_count)
8125
{
8126
fluid_synth_check_finished_voices(synth);
8127
}
8128
8129
synth->public_api_count++;
8130
}
8131
8132
void fluid_synth_api_exit(fluid_synth_t *synth)
8133
{
8134
synth->public_api_count--;
8135
8136
if(!synth->public_api_count)
8137
{
8138
fluid_rvoice_eventhandler_flush(synth->eventhandler);
8139
}
8140
8141
if(synth->use_mutex)
8142
{
8143
fluid_rec_mutex_unlock(synth->mutex);
8144
}
8145
8146
}
8147
8148
/**
8149
* Set midi channel type
8150
* @param synth FluidSynth instance
8151
* @param chan MIDI channel number (0 to MIDI channel count - 1)
8152
* @param type MIDI channel type (#fluid_midi_channel_type)
8153
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
8154
* @since 1.1.4
8155
*/
8156
int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type)
8157
{
8158
fluid_return_val_if_fail((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED);
8159
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8160
8161
synth->channel[chan]->channel_type = type;
8162
8163
FLUID_API_RETURN(FLUID_OK);
8164
}
8165
8166
/**
8167
* Return the LADSPA effects instance used by FluidSynth
8168
*
8169
* @param synth FluidSynth instance
8170
* @return pointer to LADSPA fx or NULL if compiled without LADSPA support or LADSPA is not active
8171
*/
8172
fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
8173
{
8174
fluid_return_val_if_fail(synth != NULL, NULL);
8175
8176
return synth->ladspa_fx;
8177
}
8178
8179
/**
8180
* Configure a general-purpose IIR biquad filter.
8181
*
8182
* @param synth FluidSynth instance
8183
* @param type Type of the IIR filter to use (see #fluid_iir_filter_type)
8184
* @param flags Additional flags to customize this filter or zero to stay with the default (see #fluid_iir_filter_flags)
8185
* @return #FLUID_OK if the settings have been successfully applied, otherwise #FLUID_FAILED
8186
*
8187
* This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard.
8188
* By default this filter is off (#FLUID_IIR_DISABLED).
8189
*/
8190
int fluid_synth_set_custom_filter(fluid_synth_t *synth, int type, int flags)
8191
{
8192
int i;
8193
fluid_voice_t *voice;
8194
8195
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
8196
fluid_return_val_if_fail(type >= FLUID_IIR_DISABLED && type < FLUID_IIR_LAST, FLUID_FAILED);
8197
8198
fluid_synth_api_enter(synth);
8199
8200
synth->custom_filter_type = type;
8201
synth->custom_filter_flags = flags;
8202
8203
for(i = 0; i < synth->polyphony; i++)
8204
{
8205
voice = synth->voice[i];
8206
8207
fluid_voice_set_custom_filter(voice, type, flags);
8208
}
8209
8210
FLUID_API_RETURN(FLUID_OK);
8211
}
8212
8213
/**
8214
* Set the important channels for voice overflow priority calculation.
8215
*
8216
* @param synth FluidSynth instance
8217
* @param channels comma-separated list of channel numbers
8218
* @return #FLUID_OK on success, otherwise #FLUID_FAILED
8219
*/
8220
static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels)
8221
{
8222
int i;
8223
int retval = FLUID_FAILED;
8224
int *values = NULL;
8225
int num_values;
8226
fluid_overflow_prio_t *scores;
8227
8228
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
8229
8230
scores = &synth->overflow;
8231
8232
if(scores->num_important_channels < synth->midi_channels)
8233
{
8234
scores->important_channels = FLUID_REALLOC(scores->important_channels,
8235
sizeof(*scores->important_channels) * synth->midi_channels);
8236
8237
if(scores->important_channels == NULL)
8238
{
8239
FLUID_LOG(FLUID_ERR, "Out of memory");
8240
goto exit;
8241
}
8242
8243
scores->num_important_channels = synth->midi_channels;
8244
}
8245
8246
FLUID_MEMSET(scores->important_channels, FALSE,
8247
sizeof(*scores->important_channels) * scores->num_important_channels);
8248
8249
if(channels != NULL)
8250
{
8251
values = FLUID_ARRAY(int, synth->midi_channels);
8252
8253
if(values == NULL)
8254
{
8255
FLUID_LOG(FLUID_ERR, "Out of memory");
8256
goto exit;
8257
}
8258
8259
/* Every channel given in the comma-separated list of channel numbers
8260
* is set to TRUE, i.e. flagging it as "important". Channel numbers are
8261
* 1-based. */
8262
num_values = fluid_settings_split_csv(channels, values, synth->midi_channels);
8263
8264
for(i = 0; i < num_values; i++)
8265
{
8266
if(values[i] > 0 && values[i] <= synth->midi_channels)
8267
{
8268
scores->important_channels[values[i] - 1] = TRUE;
8269
}
8270
}
8271
}
8272
8273
retval = FLUID_OK;
8274
8275
exit:
8276
FLUID_FREE(values);
8277
return retval;
8278
}
8279
8280
/*
8281
* Handler for synth.overflow.important-channels setting.
8282
*/
8283
static void fluid_synth_handle_important_channels(void *data, const char *name,
8284
const char *value)
8285
{
8286
fluid_synth_t *synth = (fluid_synth_t *)data;
8287
8288
fluid_synth_api_enter(synth);
8289
fluid_synth_set_important_channels(synth, value);
8290
fluid_synth_api_exit(synth);
8291
}
8292
8293
8294
/* API legato mode *********************************************************/
8295
8296
/**
8297
* Sets the legato mode of a channel.
8298
*
8299
* @param synth the synth instance.
8300
* @param chan MIDI channel number (0 to MIDI channel count - 1).
8301
* @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
8302
*
8303
* @return
8304
* - #FLUID_OK on success.
8305
* - #FLUID_FAILED
8306
* - \a synth is NULL.
8307
* - \a chan is outside MIDI channel count.
8308
* - \a legatomode is invalid.
8309
*/
8310
int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode)
8311
{
8312
/* checks parameters first */
8313
fluid_return_val_if_fail(legatomode >= 0, FLUID_FAILED);
8314
fluid_return_val_if_fail(legatomode < FLUID_CHANNEL_LEGATO_MODE_LAST, FLUID_FAILED);
8315
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8316
/**/
8317
synth->channel[chan]->legatomode = legatomode;
8318
/**/
8319
FLUID_API_RETURN(FLUID_OK);
8320
}
8321
8322
/**
8323
* Gets the legato mode of a channel.
8324
*
8325
* @param synth the synth instance.
8326
* @param chan MIDI channel number (0 to MIDI channel count - 1).
8327
* @param legatomode The legato mode as indicated by #fluid_channel_legato_mode.
8328
*
8329
* @return
8330
* - #FLUID_OK on success.
8331
* - #FLUID_FAILED
8332
* - \a synth is NULL.
8333
* - \a chan is outside MIDI channel count.
8334
* - \a legatomode is NULL.
8335
*/
8336
int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode)
8337
{
8338
/* checks parameters first */
8339
fluid_return_val_if_fail(legatomode != NULL, FLUID_FAILED);
8340
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8341
/**/
8342
* legatomode = synth->channel[chan]->legatomode;
8343
/**/
8344
FLUID_API_RETURN(FLUID_OK);
8345
}
8346
8347
/* API portamento mode *********************************************************/
8348
8349
/**
8350
* Sets the portamento mode of a channel.
8351
*
8352
* @param synth the synth instance.
8353
* @param chan MIDI channel number (0 to MIDI channel count - 1).
8354
* @param portamentomode The portamento mode as indicated by #fluid_channel_portamento_mode.
8355
* @return
8356
* - #FLUID_OK on success.
8357
* - #FLUID_FAILED
8358
* - \a synth is NULL.
8359
* - \a chan is outside MIDI channel count.
8360
* - \a portamentomode is invalid.
8361
*/
8362
int fluid_synth_set_portamento_mode(fluid_synth_t *synth, int chan,
8363
int portamentomode)
8364
{
8365
/* checks parameters first */
8366
fluid_return_val_if_fail(portamentomode >= 0, FLUID_FAILED);
8367
fluid_return_val_if_fail(portamentomode < FLUID_CHANNEL_PORTAMENTO_MODE_LAST, FLUID_FAILED);
8368
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8369
/**/
8370
synth->channel[chan]->portamentomode = portamentomode;
8371
/**/
8372
FLUID_API_RETURN(FLUID_OK);
8373
}
8374
8375
/**
8376
* Gets the portamento mode of a channel.
8377
*
8378
* @param synth the synth instance.
8379
* @param chan MIDI channel number (0 to MIDI channel count - 1).
8380
* @param portamentomode Pointer to the portamento mode as indicated by #fluid_channel_portamento_mode.
8381
* @return
8382
* - #FLUID_OK on success.
8383
* - #FLUID_FAILED
8384
* - \a synth is NULL.
8385
* - \a chan is outside MIDI channel count.
8386
* - \a portamentomode is NULL.
8387
*/
8388
int fluid_synth_get_portamento_mode(fluid_synth_t *synth, int chan,
8389
int *portamentomode)
8390
{
8391
/* checks parameters first */
8392
fluid_return_val_if_fail(portamentomode != NULL, FLUID_FAILED);
8393
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8394
/**/
8395
* portamentomode = synth->channel[chan]->portamentomode;
8396
/**/
8397
FLUID_API_RETURN(FLUID_OK);
8398
}
8399
8400
/* API breath mode *********************************************************/
8401
8402
/**
8403
* Sets the breath mode of a channel.
8404
*
8405
* @param synth the synth instance.
8406
* @param chan MIDI channel number (0 to MIDI channel count - 1).
8407
* @param breathmode The breath mode as indicated by #fluid_channel_breath_flags.
8408
*
8409
* @return
8410
* - #FLUID_OK on success.
8411
* - #FLUID_FAILED
8412
* - \a synth is NULL.
8413
* - \a chan is outside MIDI channel count.
8414
*/
8415
int fluid_synth_set_breath_mode(fluid_synth_t *synth, int chan, int breathmode)
8416
{
8417
/* checks parameters first */
8418
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8419
/**/
8420
fluid_channel_set_breath_info(synth->channel[chan], breathmode);
8421
/**/
8422
FLUID_API_RETURN(FLUID_OK);
8423
}
8424
8425
/**
8426
* Gets the breath mode of a channel.
8427
*
8428
* @param synth the synth instance.
8429
* @param chan MIDI channel number (0 to MIDI channel count - 1).
8430
* @param breathmode Pointer to the returned breath mode as indicated by #fluid_channel_breath_flags.
8431
*
8432
* @return
8433
* - #FLUID_OK on success.
8434
* - #FLUID_FAILED
8435
* - \a synth is NULL.
8436
* - \a chan is outside MIDI channel count.
8437
* - \a breathmode is NULL.
8438
*/
8439
int fluid_synth_get_breath_mode(fluid_synth_t *synth, int chan, int *breathmode)
8440
{
8441
/* checks parameters first */
8442
fluid_return_val_if_fail(breathmode != NULL, FLUID_FAILED);
8443
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8444
/**/
8445
* breathmode = fluid_channel_get_breath_info(synth->channel[chan]);
8446
/**/
8447
FLUID_API_RETURN(FLUID_OK);
8448
}
8449
8450
/** API Poly/mono mode ******************************************************/
8451
8452
/*
8453
* Resets a basic channel group of MIDI channels.
8454
* @param synth the synth instance.
8455
* @param chan the beginning channel of the group.
8456
* @param nbr_chan the number of channel in the group.
8457
*/
8458
static void
8459
fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan)
8460
{
8461
int i;
8462
8463
for(i = chan; i < chan + nbr_chan; i++)
8464
{
8465
fluid_channel_reset_basic_channel_info(synth->channel[i]);
8466
synth->channel[i]->mode_val = 0;
8467
}
8468
}
8469
8470
/**
8471
* Disables and unassigns all channels from a basic channel group.
8472
*
8473
* @param synth The synth instance.
8474
* @param chan The basic channel of the group to reset or -1 to reset all channels.
8475
* @note By default (i.e. on creation after new_fluid_synth() and after fluid_synth_system_reset())
8476
* a synth instance has one basic channel at channel 0 in mode #FLUID_CHANNEL_MODE_OMNION_POLY.
8477
* All other channels belong to this basic channel group. Make sure to call this function before
8478
* setting any custom basic channel setup.
8479
*
8480
* @return
8481
* - #FLUID_OK on success.
8482
* - #FLUID_FAILED
8483
* - \a synth is NULL.
8484
* - \a chan is outside MIDI channel count.
8485
* - \a chan isn't a basic channel.
8486
*/
8487
int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan)
8488
{
8489
int nbr_chan;
8490
8491
/* checks parameters first */
8492
if(chan < 0)
8493
{
8494
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
8495
fluid_synth_api_enter(synth);
8496
/* The range is all MIDI channels from 0 to MIDI channel count -1 */
8497
chan = 0; /* beginning chan */
8498
nbr_chan = synth->midi_channels; /* MIDI Channels number */
8499
}
8500
else
8501
{
8502
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8503
8504
/* checks if chan is a basic channel */
8505
if(!(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC))
8506
{
8507
FLUID_API_RETURN(FLUID_FAILED);
8508
}
8509
8510
/* The range is all MIDI channels in the group from chan */
8511
nbr_chan = synth->channel[chan]->mode_val; /* nbr of channels in the group */
8512
}
8513
8514
/* resets the range of MIDI channels */
8515
fluid_synth_reset_basic_channel_LOCAL(synth, chan, nbr_chan);
8516
FLUID_API_RETURN(FLUID_OK);
8517
}
8518
8519
/**
8520
* Checks if a new basic channel group overlaps the next basic channel group.
8521
*
8522
* On success the function returns the possible number of channel for this
8523
* new basic channel group.
8524
* The function fails if the new group overlaps the next basic channel group.
8525
*
8526
* @param see fluid_synth_set_basic_channel.
8527
* @return
8528
* - On success, the effective number of channels for this new basic channel group,
8529
* #FLUID_FAILED otherwise.
8530
* - #FLUID_FAILED
8531
* - \a val has a number of channels overlapping next basic channel group or been
8532
* above MIDI channel count.
8533
*/
8534
static int
8535
fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val)
8536
{
8537
int i, n_chan = synth->midi_channels; /* MIDI Channels count */
8538
int real_val = val; /* real number of channels in the group */
8539
8540
/* adjusts val range */
8541
if(mode == FLUID_CHANNEL_MODE_OMNIOFF_POLY)
8542
{
8543
real_val = 1; /* mode poly omnioff implies a group of only one channel.*/
8544
}
8545
else if(val == 0)
8546
{
8547
/* mode poly omnion (0), mono omnion (1), mono omni off (3) */
8548
/* value 0 means all possible channels from basicchan to MIDI channel count -1.*/
8549
real_val = n_chan - basicchan;
8550
}
8551
/* checks if val range is above MIDI channel count */
8552
else if(basicchan + val > n_chan)
8553
{
8554
return FLUID_FAILED;
8555
}
8556
8557
/* checks if this basic channel group overlaps next basic channel group */
8558
for(i = basicchan + 1; i < basicchan + real_val; i++)
8559
{
8560
if(synth->channel[i]->mode & FLUID_CHANNEL_BASIC)
8561
{
8562
/* A value of 0 for val means all possible channels from basicchan to
8563
to the next basic channel -1 (if any).
8564
When i reaches the next basic channel group, real_val will be
8565
limited if it is possible */
8566
if(val == 0)
8567
{
8568
/* limitation of real_val */
8569
real_val = i - basicchan;
8570
break;
8571
}
8572
8573
/* overlap with the next basic channel group */
8574
return FLUID_FAILED;
8575
}
8576
}
8577
8578
return real_val;
8579
}
8580
8581
/**
8582
* Sets a new basic channel group only. The function doesn't allow to change an
8583
* existing basic channel.
8584
*
8585
* The function fails if any channel overlaps any existing basic channel group.
8586
* To make room if necessary, basic channel groups can be cleared using
8587
* fluid_synth_reset_basic_channel().
8588
*
8589
* @param synth the synth instance.
8590
* @param chan the basic Channel number (0 to MIDI channel count-1).
8591
* @param mode the MIDI mode to use for chan (see #fluid_basic_channel_modes).
8592
* @param val number of channels in the group.
8593
* @note \a val is only relevant for mode #FLUID_CHANNEL_MODE_OMNION_POLY,
8594
* #FLUID_CHANNEL_MODE_OMNION_MONO and #FLUID_CHANNEL_MODE_OMNIOFF_MONO. A value
8595
* of 0 means all possible channels from \a chan to to next basic channel minus 1 (if any)
8596
* or to MIDI channel count minus 1. Val is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY
8597
* as this mode implies a group of only one channel.
8598
* @return
8599
* - #FLUID_OK on success.
8600
* - #FLUID_FAILED
8601
* - \a synth is NULL.
8602
* - \a chan is outside MIDI channel count.
8603
* - \a mode is invalid.
8604
* - \a val has a number of channels overlapping another basic channel group or been
8605
* above MIDI channel count.
8606
* - When the function fails, any existing basic channels aren't modified.
8607
*/
8608
int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val)
8609
{
8610
/* check parameters */
8611
fluid_return_val_if_fail(mode >= 0, FLUID_FAILED);
8612
fluid_return_val_if_fail(mode < FLUID_CHANNEL_MODE_LAST, FLUID_FAILED);
8613
fluid_return_val_if_fail(val >= 0, FLUID_FAILED);
8614
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8615
8616
/**/
8617
if(val > 0 && chan + val > synth->midi_channels)
8618
{
8619
FLUID_API_RETURN(FLUID_FAILED);
8620
}
8621
8622
/* Checks if there is an overlap with the next basic channel */
8623
val = fluid_synth_check_next_basic_channel(synth, chan, mode, val);
8624
8625
if(val == FLUID_FAILED || synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)
8626
{
8627
/* overlap with the next or previous channel group */
8628
FLUID_LOG(FLUID_INFO, "basic channel %d overlaps another group", chan);
8629
FLUID_API_RETURN(FLUID_FAILED);
8630
}
8631
8632
/* sets a new basic channel group */
8633
fluid_synth_set_basic_channel_LOCAL(synth, chan, mode, val);
8634
/**/
8635
FLUID_API_RETURN(FLUID_OK);
8636
}
8637
8638
/*
8639
* Local version of fluid_synth_set_basic_channel(), called internally:
8640
* - by fluid_synth_set_basic_channel() to set a new basic channel group.
8641
* - during creation new_fluid_synth() or on CC reset to set a default basic channel group.
8642
* - on CC ominoff, CC omnion, CC poly , CC mono to change an existing basic channel group.
8643
*
8644
* @param see fluid_synth_set_basic_channel()
8645
*/
8646
static void
8647
fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val)
8648
{
8649
int i;
8650
8651
/* sets the basic channel group */
8652
for(i = basicchan; i < basicchan + val; i++)
8653
{
8654
int new_mode = mode; /* OMNI_OFF/ON, MONO/POLY ,others bits are zero */
8655
int new_val;
8656
/* MIDI specs: when mode is changed, channel must receive ALL_NOTES_OFF */
8657
fluid_synth_all_notes_off_LOCAL(synth, i);
8658
8659
if(i == basicchan)
8660
{
8661
new_mode |= FLUID_CHANNEL_BASIC; /* First channel in the group */
8662
new_val = val; /* number of channels in the group */
8663
}
8664
else
8665
{
8666
new_val = 0; /* val is 0 for other channel than basic channel */
8667
}
8668
8669
/* Channel is enabled */
8670
new_mode |= FLUID_CHANNEL_ENABLED;
8671
/* Now new_mode is OMNI OFF/ON,MONO/POLY, BASIC_CHANNEL or not and enabled */
8672
fluid_channel_set_basic_channel_info(synth->channel[i], new_mode);
8673
synth->channel[i]->mode_val = new_val;
8674
}
8675
}
8676
8677
/**
8678
* Searches a previous basic channel starting from chan.
8679
*
8680
* @param synth the synth instance.
8681
* @param chan starting index of the search (including chan).
8682
* @return index of the basic channel if found , FLUID_FAILED otherwise.
8683
*/
8684
static int fluid_synth_get_previous_basic_channel(fluid_synth_t *synth, int chan)
8685
{
8686
for(; chan >= 0; chan--)
8687
{
8688
/* searches previous basic channel */
8689
if(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC)
8690
{
8691
/* chan is the previous basic channel */
8692
return chan;
8693
}
8694
}
8695
8696
return FLUID_FAILED;
8697
}
8698
8699
/**
8700
* Returns poly mono mode information of any MIDI channel.
8701
*
8702
* @param synth the synth instance
8703
* @param chan MIDI channel number (0 to MIDI channel count - 1)
8704
* @param basic_chan_out Buffer to store the basic channel \a chan belongs to or #FLUID_FAILED if \a chan is disabled.
8705
* @param mode_out Buffer to store the mode of \a chan (see #fluid_basic_channel_modes) or #FLUID_FAILED if \a chan is disabled.
8706
* @param val_out Buffer to store the total number of channels in this basic channel group or #FLUID_FAILED if \a chan is disabled.
8707
* @note If any of \a basic_chan_out, \a mode_out, \a val_out pointer is NULL
8708
* the corresponding information isn't returned.
8709
*
8710
* @return
8711
* - #FLUID_OK on success.
8712
* - #FLUID_FAILED
8713
* - \a synth is NULL.
8714
* - \a chan is outside MIDI channel count.
8715
*/
8716
int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan,
8717
int *basic_chan_out,
8718
int *mode_out,
8719
int *val_out)
8720
{
8721
int basic_chan = FLUID_FAILED;
8722
int mode = FLUID_FAILED;
8723
int val = FLUID_FAILED;
8724
8725
/* checks parameters first */
8726
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
8727
8728
if((synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) &&
8729
/* chan is enabled , we search the basic channel chan belongs to */
8730
(basic_chan = fluid_synth_get_previous_basic_channel(synth, chan)) != FLUID_FAILED)
8731
{
8732
mode = synth->channel[chan]->mode & FLUID_CHANNEL_MODE_MASK;
8733
val = synth->channel[basic_chan]->mode_val;
8734
}
8735
8736
/* returns the information if they are requested */
8737
if(basic_chan_out)
8738
{
8739
* basic_chan_out = basic_chan;
8740
}
8741
8742
if(mode_out)
8743
{
8744
* mode_out = mode;
8745
}
8746
8747
if(val_out)
8748
{
8749
* val_out = val;
8750
}
8751
8752
FLUID_API_RETURN(FLUID_OK);
8753
}
8754
8755