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