00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <math.h>
00022
00023 #include "fluid_synth.h"
00024 #include "fluid_sys.h"
00025 #include "fluid_chan.h"
00026 #include "fluid_tuning.h"
00027 #include "fluid_settings.h"
00028 #include "fluid_sfont.h"
00029
00030 #ifdef TRAP_ON_FPE
00031 #define _GNU_SOURCE
00032 #include <fenv.h>
00033
00034
00035 extern int feenableexcept (int excepts);
00036 #endif
00037
00038
00039 fluid_sfloader_t* new_fluid_defsfloader(void);
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 int fluid_synth_program_select2(fluid_synth_t* synth,
00050 int chan,
00051 char* sfont_name,
00052 unsigned int bank_num,
00053 unsigned int preset_num);
00054
00055 fluid_sfont_t* fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name);
00056
00057 int fluid_synth_set_gen2(fluid_synth_t* synth, int chan,
00058 int param, float value,
00059 int absolute, int normalized);
00060
00061
00062
00063
00064
00065
00066
00067
00068 static int fluid_synth_initialized = 0;
00069 static void fluid_synth_init(void);
00070 static void init_dither(void);
00071
00072
00073
00074
00075
00076
00077
00078
00079 fluid_mod_t default_vel2att_mod;
00080 fluid_mod_t default_vel2filter_mod;
00081 fluid_mod_t default_at2viblfo_mod;
00082 fluid_mod_t default_mod2viblfo_mod;
00083 fluid_mod_t default_att_mod;
00084 fluid_mod_t default_pan_mod;
00085 fluid_mod_t default_expr_mod;
00086 fluid_mod_t default_reverb_mod;
00087 fluid_mod_t default_chorus_mod;
00088 fluid_mod_t default_pitch_bend_mod;
00089
00090
00091 static fluid_revmodel_presets_t revmodel_preset[] = {
00092
00093 { "Test 1", 0.2f, 0.0f, 0.5f, 0.9f },
00094 { "Test 2", 0.4f, 0.2f, 0.5f, 0.8f },
00095 { "Test 3", 0.6f, 0.4f, 0.5f, 0.7f },
00096 { "Test 4", 0.8f, 0.7f, 0.5f, 0.6f },
00097 { "Test 5", 0.8f, 1.0f, 0.5f, 0.5f },
00098 { NULL, 0.0f, 0.0f, 0.0f, 0.0f }
00099 };
00100
00101
00102
00103
00104
00105
00106
00107
00108 void fluid_synth_settings(fluid_settings_t* settings)
00109 {
00110 fluid_settings_register_str(settings, "synth.verbose", "no", 0, NULL, NULL);
00111 fluid_settings_register_str(settings, "synth.dump", "no", 0, NULL, NULL);
00112 fluid_settings_register_str(settings, "synth.reverb.active", "yes", 0, NULL, NULL);
00113 fluid_settings_register_str(settings, "synth.chorus.active", "yes", 0, NULL, NULL);
00114 fluid_settings_register_str(settings, "synth.ladspa.active", "no", 0, NULL, NULL);
00115 fluid_settings_register_str(settings, "midi.portname", "", 0, NULL, NULL);
00116
00117 fluid_settings_register_int(settings, "synth.polyphony",
00118 256, 16, 4096, 0, NULL, NULL);
00119 fluid_settings_register_int(settings, "synth.midi-channels",
00120 16, 16, 256, 0, NULL, NULL);
00121 fluid_settings_register_num(settings, "synth.gain",
00122 0.2f, 0.0f, 10.0f,
00123 0, NULL, NULL);
00124 fluid_settings_register_int(settings, "synth.audio-channels",
00125 1, 1, 256, 0, NULL, NULL);
00126 fluid_settings_register_int(settings, "synth.audio-groups",
00127 1, 1, 256, 0, NULL, NULL);
00128 fluid_settings_register_int(settings, "synth.effects-channels",
00129 2, 2, 2, 0, NULL, NULL);
00130 fluid_settings_register_num(settings, "synth.sample-rate",
00131 44100.0f, 22050.0f, 96000.0f,
00132 0, NULL, NULL);
00133 }
00134
00135
00136
00137
00138 void fluid_version(int *major, int *minor, int *micro)
00139 {
00140 *major = FLUIDSYNTH_VERSION_MAJOR;
00141 *minor = FLUIDSYNTH_VERSION_MINOR;
00142 *micro = FLUIDSYNTH_VERSION_MICRO;
00143 }
00144
00145
00146
00147
00148 char* fluid_version_str(void)
00149 {
00150 return FLUIDSYNTH_VERSION;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 static void
00160 fluid_synth_init()
00161 {
00162 fluid_synth_initialized++;
00163
00164 #ifdef TRAP_ON_FPE
00165
00166 feenableexcept (FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID);
00167 #endif
00168
00169 fluid_conversion_config();
00170
00171 fluid_dsp_float_config();
00172
00173 fluid_sys_config();
00174
00175 init_dither();
00176
00177
00178
00179 fluid_mod_set_source1(&default_vel2att_mod,
00180 FLUID_MOD_VELOCITY,
00181 FLUID_MOD_GC
00182 | FLUID_MOD_CONCAVE
00183 | FLUID_MOD_UNIPOLAR
00184 | FLUID_MOD_NEGATIVE
00185 );
00186 fluid_mod_set_source2(&default_vel2att_mod, 0, 0);
00187 fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION);
00188 fluid_mod_set_amount(&default_vel2att_mod, 960.0);
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY,
00200 FLUID_MOD_GC
00201 | FLUID_MOD_LINEAR
00202 | FLUID_MOD_UNIPOLAR
00203 | FLUID_MOD_NEGATIVE
00204 );
00205 fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY,
00206 FLUID_MOD_GC
00207 | FLUID_MOD_SWITCH
00208 | FLUID_MOD_UNIPOLAR
00209
00210 | FLUID_MOD_POSITIVE
00211 );
00212 fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC);
00213 fluid_mod_set_amount(&default_vel2filter_mod, -2400);
00214
00215
00216
00217
00218 fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE,
00219 FLUID_MOD_GC
00220 | FLUID_MOD_LINEAR
00221 | FLUID_MOD_UNIPOLAR
00222 | FLUID_MOD_POSITIVE
00223 );
00224 fluid_mod_set_source2(&default_at2viblfo_mod, 0,0);
00225 fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH);
00226 fluid_mod_set_amount(&default_at2viblfo_mod, 50);
00227
00228
00229
00230
00231 fluid_mod_set_source1(&default_mod2viblfo_mod, 1,
00232 FLUID_MOD_CC
00233 | FLUID_MOD_LINEAR
00234 | FLUID_MOD_UNIPOLAR
00235 | FLUID_MOD_POSITIVE
00236 );
00237 fluid_mod_set_source2(&default_mod2viblfo_mod, 0,0);
00238 fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH);
00239 fluid_mod_set_amount(&default_mod2viblfo_mod, 50);
00240
00241
00242
00243
00244 fluid_mod_set_source1(&default_att_mod, 7,
00245 FLUID_MOD_CC
00246 | FLUID_MOD_CONCAVE
00247 | FLUID_MOD_UNIPOLAR
00248 | FLUID_MOD_NEGATIVE
00249 );
00250 fluid_mod_set_source2(&default_att_mod, 0, 0);
00251 fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION);
00252 fluid_mod_set_amount(&default_att_mod, 960.0);
00253
00254
00255
00256
00257 fluid_mod_set_source1(&default_pan_mod, 10,
00258 FLUID_MOD_CC
00259 | FLUID_MOD_LINEAR
00260 | FLUID_MOD_BIPOLAR
00261 | FLUID_MOD_POSITIVE
00262 );
00263 fluid_mod_set_source2(&default_pan_mod, 0, 0);
00264 fluid_mod_set_dest(&default_pan_mod, GEN_PAN);
00265
00266
00267
00268 fluid_mod_set_amount(&default_pan_mod, 500.0);
00269
00270
00271
00272 fluid_mod_set_source1(&default_expr_mod, 11,
00273 FLUID_MOD_CC
00274 | FLUID_MOD_CONCAVE
00275 | FLUID_MOD_UNIPOLAR
00276 | FLUID_MOD_NEGATIVE
00277 );
00278 fluid_mod_set_source2(&default_expr_mod, 0, 0);
00279 fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION);
00280 fluid_mod_set_amount(&default_expr_mod, 960.0);
00281
00282
00283
00284
00285 fluid_mod_set_source1(&default_reverb_mod, 91,
00286 FLUID_MOD_CC
00287 | FLUID_MOD_LINEAR
00288 | FLUID_MOD_UNIPOLAR
00289 | FLUID_MOD_POSITIVE
00290 );
00291 fluid_mod_set_source2(&default_reverb_mod, 0, 0);
00292 fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND);
00293 fluid_mod_set_amount(&default_reverb_mod, 200);
00294
00295
00296
00297
00298 fluid_mod_set_source1(&default_chorus_mod, 93,
00299 FLUID_MOD_CC
00300 | FLUID_MOD_LINEAR
00301 | FLUID_MOD_UNIPOLAR
00302 | FLUID_MOD_POSITIVE
00303 );
00304 fluid_mod_set_source2(&default_chorus_mod, 0, 0);
00305 fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND);
00306 fluid_mod_set_amount(&default_chorus_mod, 200);
00307
00308
00309
00310
00311 fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL,
00312 FLUID_MOD_GC
00313 | FLUID_MOD_LINEAR
00314 | FLUID_MOD_BIPOLAR
00315 | FLUID_MOD_POSITIVE
00316 );
00317 fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS,
00318 FLUID_MOD_GC
00319 | FLUID_MOD_LINEAR
00320 | FLUID_MOD_UNIPOLAR
00321 | FLUID_MOD_POSITIVE
00322 );
00323 fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH);
00324 fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0);
00325 }
00326
00327
00328 int fluid_synth_verify_settings(fluid_settings_t *settings)
00329 {
00330 return 0;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 fluid_synth_t*
00342 new_fluid_synth(fluid_settings_t *settings)
00343 {
00344 int i;
00345 fluid_synth_t* synth;
00346 fluid_sfloader_t* loader;
00347
00348
00349 if (fluid_synth_initialized == 0) {
00350 fluid_synth_init();
00351 }
00352
00353 fluid_synth_verify_settings(settings);
00354
00355
00356 synth = FLUID_NEW(fluid_synth_t);
00357 if (synth == NULL) {
00358 FLUID_LOG(FLUID_ERR, "Out of memory");
00359 return NULL;
00360 }
00361 FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t));
00362
00363 fluid_mutex_init(synth->busy);
00364
00365 synth->settings = settings;
00366
00367 synth->with_reverb = fluid_settings_str_equal(settings, "synth.reverb.active", "yes");
00368 synth->with_chorus = fluid_settings_str_equal(settings, "synth.chorus.active", "yes");
00369 synth->verbose = fluid_settings_str_equal(settings, "synth.verbose", "yes");
00370 synth->dump = fluid_settings_str_equal(settings, "synth.dump", "yes");
00371
00372 fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
00373 fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate);
00374 fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels);
00375 fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
00376 fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups);
00377 fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
00378 fluid_settings_getnum(settings, "synth.gain", &synth->gain);
00379
00380
00381 fluid_settings_register_num(settings, "synth.gain",
00382 0.2f, 0.0f, 10.0f, 0,
00383 (fluid_num_update_t) fluid_synth_update_gain, synth);
00384 fluid_settings_register_int(settings, "synth.polyphony",
00385 synth->polyphony, 16, 4096, 0,
00386 (fluid_int_update_t) fluid_synth_update_polyphony,
00387 synth);
00388
00389
00390
00391 if (synth->midi_channels % 16 != 0) {
00392 int n = synth->midi_channels / 16;
00393 synth->midi_channels = (n + 1) * 16;
00394 fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels);
00395 FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. "
00396 "I'll increase the number of channels to the next multiple.");
00397 }
00398
00399 if (synth->audio_channels < 1) {
00400 FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. "
00401 "Changing this setting to 1.");
00402 synth->audio_channels = 1;
00403 } else if (synth->audio_channels > 128) {
00404 FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). "
00405 "Limiting this setting to 128.", synth->audio_channels);
00406 synth->audio_channels = 128;
00407 }
00408
00409 if (synth->audio_groups < 1) {
00410 FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. "
00411 "Changing this setting to 1.");
00412 synth->audio_groups = 1;
00413 } else if (synth->audio_groups > 128) {
00414 FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). "
00415 "Limiting this setting to 128.", synth->audio_groups);
00416 synth->audio_groups = 128;
00417 }
00418
00419 if (synth->effects_channels != 2) {
00420 FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)."
00421 "Setting effects channels to 2.", synth->effects_channels);
00422 synth->effects_channels = 2;
00423 }
00424
00425
00426
00427
00428
00429 synth->nbuf = synth->audio_channels;
00430 if (synth->audio_groups > synth->nbuf) {
00431 synth->nbuf = synth->audio_groups;
00432 }
00433
00434 #ifdef LADSPA
00435
00436 synth->LADSPA_FxUnit = new_fluid_LADSPA_FxUnit(synth);
00437 #endif
00438
00439
00440 synth->state = FLUID_SYNTH_PLAYING;
00441 synth->sfont = NULL;
00442 synth->noteid = 0;
00443 synth->ticks = 0;
00444 synth->tuning = NULL;
00445
00446
00447 loader = new_fluid_defsfloader();
00448
00449 if (loader == NULL) {
00450 FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader");
00451 } else {
00452 fluid_synth_add_sfloader(synth, loader);
00453 }
00454
00455
00456 synth->channel = FLUID_ARRAY(fluid_channel_t*, synth->midi_channels);
00457 if (synth->channel == NULL) {
00458 FLUID_LOG(FLUID_ERR, "Out of memory");
00459 goto error_recovery;
00460 }
00461 for (i = 0; i < synth->midi_channels; i++) {
00462 synth->channel[i] = new_fluid_channel(synth, i);
00463 if (synth->channel[i] == NULL) {
00464 goto error_recovery;
00465 }
00466 }
00467
00468
00469 synth->nvoice = synth->polyphony;
00470 synth->voice = FLUID_ARRAY(fluid_voice_t*, synth->nvoice);
00471 if (synth->voice == NULL) {
00472 goto error_recovery;
00473 }
00474 for (i = 0; i < synth->nvoice; i++) {
00475 synth->voice[i] = new_fluid_voice(synth->sample_rate);
00476 if (synth->voice[i] == NULL) {
00477 goto error_recovery;
00478 }
00479 }
00480
00481
00482 synth->left_buf = NULL;
00483 synth->right_buf = NULL;
00484 synth->fx_left_buf = NULL;
00485 synth->fx_right_buf = NULL;
00486
00487
00488
00489 synth->left_buf = FLUID_ARRAY(fluid_real_t*, synth->nbuf);
00490 synth->right_buf = FLUID_ARRAY(fluid_real_t*, synth->nbuf);
00491
00492 if ((synth->left_buf == NULL) || (synth->right_buf == NULL)) {
00493 FLUID_LOG(FLUID_ERR, "Out of memory");
00494 goto error_recovery;
00495 }
00496
00497 FLUID_MEMSET(synth->left_buf, 0, synth->nbuf * sizeof(fluid_real_t*));
00498 FLUID_MEMSET(synth->right_buf, 0, synth->nbuf * sizeof(fluid_real_t*));
00499
00500 for (i = 0; i < synth->nbuf; i++) {
00501
00502 synth->left_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE);
00503 synth->right_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE);
00504
00505 if ((synth->left_buf[i] == NULL) || (synth->right_buf[i] == NULL)) {
00506 FLUID_LOG(FLUID_ERR, "Out of memory");
00507 goto error_recovery;
00508 }
00509 }
00510
00511
00512
00513 synth->fx_left_buf = FLUID_ARRAY(fluid_real_t*, synth->effects_channels);
00514 synth->fx_right_buf = FLUID_ARRAY(fluid_real_t*, synth->effects_channels);
00515
00516 if ((synth->fx_left_buf == NULL) || (synth->fx_right_buf == NULL)) {
00517 FLUID_LOG(FLUID_ERR, "Out of memory");
00518 goto error_recovery;
00519 }
00520
00521 FLUID_MEMSET(synth->fx_left_buf, 0, 2 * sizeof(fluid_real_t*));
00522 FLUID_MEMSET(synth->fx_right_buf, 0, 2 * sizeof(fluid_real_t*));
00523
00524 for (i = 0; i < synth->effects_channels; i++) {
00525 synth->fx_left_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE);
00526 synth->fx_right_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE);
00527
00528 if ((synth->fx_left_buf[i] == NULL) || (synth->fx_right_buf[i] == NULL)) {
00529 FLUID_LOG(FLUID_ERR, "Out of memory");
00530 goto error_recovery;
00531 }
00532 }
00533
00534
00535 synth->cur = FLUID_BUFSIZE;
00536 synth->dither_index = 0;
00537
00538
00539 synth->reverb = new_fluid_revmodel();
00540 if (synth->reverb == NULL) {
00541 FLUID_LOG(FLUID_ERR, "Out of memory");
00542 goto error_recovery;
00543 }
00544
00545 fluid_synth_set_reverb(synth,
00546 FLUID_REVERB_DEFAULT_ROOMSIZE,
00547 FLUID_REVERB_DEFAULT_DAMP,
00548 FLUID_REVERB_DEFAULT_WIDTH,
00549 FLUID_REVERB_DEFAULT_LEVEL);
00550
00551
00552 synth->chorus = new_fluid_chorus(synth->sample_rate);
00553 if (synth->chorus == NULL) {
00554 FLUID_LOG(FLUID_ERR, "Out of memory");
00555 goto error_recovery;
00556 }
00557
00558
00559 synth->start = fluid_curtime();
00560
00561 return synth;
00562
00563 error_recovery:
00564 delete_fluid_synth(synth);
00565 return NULL;
00566 }
00567
00568
00569
00570
00571 int
00572 delete_fluid_synth(fluid_synth_t* synth)
00573 {
00574 int i, k;
00575 fluid_list_t *list;
00576 fluid_sfont_t* sfont;
00577 fluid_bank_offset_t* bank_offset;
00578 fluid_sfloader_t* loader;
00579
00580 if (synth == NULL) {
00581 return FLUID_OK;
00582 }
00583
00584 fluid_profiling_print();
00585
00586 synth->state = FLUID_SYNTH_STOPPED;
00587
00588
00589 if (synth->voice != NULL) {
00590 for (i = 0; i < synth->nvoice; i++) {
00591 if (synth->voice[i] && fluid_voice_is_playing (synth->voice[i]))
00592 fluid_voice_off (synth->voice[i]);
00593 }
00594 }
00595
00596
00597 for (list = synth->sfont; list; list = fluid_list_next(list)) {
00598 sfont = (fluid_sfont_t*) fluid_list_get(list);
00599 delete_fluid_sfont(sfont);
00600 }
00601
00602 delete_fluid_list(synth->sfont);
00603
00604
00605 for (list = synth->bank_offsets; list; list = fluid_list_next(list)) {
00606 bank_offset = (fluid_bank_offset_t*) fluid_list_get(list);
00607 FLUID_FREE(bank_offset);
00608 }
00609
00610 delete_fluid_list(synth->bank_offsets);
00611
00612
00613
00614
00615 for (list = synth->loaders; list; list = fluid_list_next(list)) {
00616 loader = (fluid_sfloader_t*) fluid_list_get(list);
00617 fluid_sfloader_delete(loader);
00618 }
00619
00620 delete_fluid_list(synth->loaders);
00621
00622
00623 if (synth->channel != NULL) {
00624 for (i = 0; i < synth->midi_channels; i++) {
00625 if (synth->channel[i] != NULL) {
00626 delete_fluid_channel(synth->channel[i]);
00627 }
00628 }
00629 FLUID_FREE(synth->channel);
00630 }
00631
00632 if (synth->voice != NULL) {
00633 for (i = 0; i < synth->nvoice; i++) {
00634 if (synth->voice[i] != NULL) {
00635 delete_fluid_voice(synth->voice[i]);
00636 }
00637 }
00638 FLUID_FREE(synth->voice);
00639 }
00640
00641
00642 if (synth->left_buf != NULL) {
00643 for (i = 0; i < synth->nbuf; i++) {
00644 if (synth->left_buf[i] != NULL) {
00645 FLUID_FREE(synth->left_buf[i]);
00646 }
00647 }
00648 FLUID_FREE(synth->left_buf);
00649 }
00650
00651 if (synth->right_buf != NULL) {
00652 for (i = 0; i < synth->nbuf; i++) {
00653 if (synth->right_buf[i] != NULL) {
00654 FLUID_FREE(synth->right_buf[i]);
00655 }
00656 }
00657 FLUID_FREE(synth->right_buf);
00658 }
00659
00660 if (synth->fx_left_buf != NULL) {
00661 for (i = 0; i < 2; i++) {
00662 if (synth->fx_left_buf[i] != NULL) {
00663 FLUID_FREE(synth->fx_left_buf[i]);
00664 }
00665 }
00666 FLUID_FREE(synth->fx_left_buf);
00667 }
00668
00669 if (synth->fx_right_buf != NULL) {
00670 for (i = 0; i < 2; i++) {
00671 if (synth->fx_right_buf[i] != NULL) {
00672 FLUID_FREE(synth->fx_right_buf[i]);
00673 }
00674 }
00675 FLUID_FREE(synth->fx_right_buf);
00676 }
00677
00678
00679 if (synth->reverb != NULL) {
00680 delete_fluid_revmodel(synth->reverb);
00681 }
00682
00683
00684 if (synth->chorus != NULL) {
00685 delete_fluid_chorus(synth->chorus);
00686 }
00687
00688
00689 if (synth->tuning != NULL) {
00690 for (i = 0; i < 128; i++) {
00691 if (synth->tuning[i] != NULL) {
00692 for (k = 0; k < 128; k++) {
00693 if (synth->tuning[i][k] != NULL) {
00694 FLUID_FREE(synth->tuning[i][k]);
00695 }
00696 }
00697 FLUID_FREE(synth->tuning[i]);
00698 }
00699 }
00700 FLUID_FREE(synth->tuning);
00701 }
00702
00703 #ifdef LADSPA
00704
00705 fluid_LADSPA_shutdown(synth->LADSPA_FxUnit);
00706 FLUID_FREE(synth->LADSPA_FxUnit);
00707 #endif
00708
00709 fluid_mutex_destroy(synth->busy);
00710
00711 FLUID_FREE(synth);
00712
00713 return FLUID_OK;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722 char*
00723 fluid_synth_error(fluid_synth_t* synth)
00724 {
00725 return fluid_error();
00726 }
00727
00728
00729
00730
00731 int
00732 fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel)
00733 {
00734 fluid_channel_t* channel;
00735 int r = FLUID_FAILED;
00736
00737
00738 if ((chan < 0) || (chan >= synth->midi_channels)) {
00739 FLUID_LOG(FLUID_WARN, "Channel out of range");
00740 return FLUID_FAILED;
00741 }
00742
00743
00744 if (vel == 0) {
00745 return fluid_synth_noteoff(synth, chan, key);
00746 }
00747
00748 channel = synth->channel[chan];
00749
00750
00751 if (channel->preset == NULL) {
00752 if (synth->verbose) {
00753 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s",
00754 chan, key, vel, 0,
00755 (float) synth->ticks / 44100.0f,
00756 (fluid_curtime() - synth->start) / 1000.0f,
00757 0.0f, 0, "channel has no preset");
00758 }
00759 return FLUID_FAILED;
00760 }
00761
00762
00763
00764 fluid_synth_release_voice_on_same_note(synth, chan, key);
00765
00766 return fluid_synth_start(synth, synth->noteid++, channel->preset, 0, chan, key, vel);
00767 }
00768
00769
00770
00771
00772 int
00773 fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key)
00774 {
00775 int i;
00776 fluid_voice_t* voice;
00777 int status = FLUID_FAILED;
00778
00779
00780
00781 for (i = 0; i < synth->polyphony; i++) {
00782 voice = synth->voice[i];
00783 if (_ON(voice) && (voice->chan == chan) && (voice->key == key)) {
00784 if (synth->verbose) {
00785 int used_voices = 0;
00786 int k;
00787 for (k = 0; k < synth->polyphony; k++) {
00788 if (!_AVAILABLE(synth->voice[k])) {
00789 used_voices++;
00790 }
00791 }
00792 FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
00793 voice->chan, voice->key, 0, voice->id,
00794 (float) (voice->start_time + voice->ticks) / 44100.0f,
00795 (fluid_curtime() - synth->start) / 1000.0f,
00796 (float) voice->ticks / 44100.0f,
00797 used_voices);
00798 }
00799 fluid_voice_noteoff(voice);
00800 status = FLUID_OK;
00801 }
00802 }
00803 return status;
00804 }
00805
00806
00807
00808
00809 int
00810 fluid_synth_damp_voices(fluid_synth_t* synth, int chan)
00811 {
00812 int i;
00813 fluid_voice_t* voice;
00814
00815
00816
00817
00818 for (i = 0; i < synth->polyphony; i++) {
00819 voice = synth->voice[i];
00820 if ((voice->chan == chan) && _SUSTAINED(voice)) {
00821
00822 fluid_voice_noteoff(voice);
00823 }
00824 }
00825
00826 return FLUID_OK;
00827 }
00828
00829
00830
00831
00832 int
00833 fluid_synth_cc(fluid_synth_t* synth, int chan, int num, int val)
00834 {
00835
00836
00837
00838
00839 if ((chan < 0) || (chan >= synth->midi_channels)) {
00840 FLUID_LOG(FLUID_WARN, "Channel out of range");
00841 return FLUID_FAILED;
00842 }
00843 if ((num < 0) || (num >= 128)) {
00844 FLUID_LOG(FLUID_WARN, "Ctrl out of range");
00845 return FLUID_FAILED;
00846 }
00847 if ((val < 0) || (val >= 128)) {
00848 FLUID_LOG(FLUID_WARN, "Value out of range");
00849 return FLUID_FAILED;
00850 }
00851
00852 if (synth->verbose) {
00853 FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val);
00854 }
00855
00856
00857 fluid_channel_cc(synth->channel[chan], num, val);
00858
00859 return FLUID_OK;
00860 }
00861
00862
00863
00864
00865 int
00866 fluid_synth_get_cc(fluid_synth_t* synth, int chan, int num, int* pval)
00867 {
00868
00869 if ((chan < 0) || (chan >= synth->midi_channels)) {
00870 FLUID_LOG(FLUID_WARN, "Channel out of range");
00871 return FLUID_FAILED;
00872 }
00873 if ((num < 0) || (num >= 128)) {
00874 FLUID_LOG(FLUID_WARN, "Ctrl out of range");
00875 return FLUID_FAILED;
00876 }
00877
00878 *pval = synth->channel[chan]->cc[num];
00879 return FLUID_OK;
00880 }
00881
00882
00883
00884
00885
00886
00887 int
00888 fluid_synth_all_notes_off(fluid_synth_t* synth, int chan)
00889 {
00890 int i;
00891 fluid_voice_t* voice;
00892
00893 for (i = 0; i < synth->polyphony; i++) {
00894 voice = synth->voice[i];
00895 if (_PLAYING(voice) && (voice->chan == chan)) {
00896 fluid_voice_noteoff(voice);
00897 }
00898 }
00899 return FLUID_OK;
00900 }
00901
00902
00903
00904
00905
00906
00907 int
00908 fluid_synth_all_sounds_off(fluid_synth_t* synth, int chan)
00909 {
00910 int i;
00911 fluid_voice_t* voice;
00912
00913 for (i = 0; i < synth->polyphony; i++) {
00914 voice = synth->voice[i];
00915 if (_PLAYING(voice) && (voice->chan == chan)) {
00916 fluid_voice_off(voice);
00917 }
00918 }
00919 return FLUID_OK;
00920 }
00921
00922
00923
00924
00925
00926
00927
00928 int
00929 fluid_synth_system_reset(fluid_synth_t* synth)
00930 {
00931 int i;
00932 fluid_voice_t* voice;
00933
00934 for (i = 0; i < synth->polyphony; i++) {
00935 voice = synth->voice[i];
00936 if (_PLAYING(voice)) {
00937 fluid_voice_off(voice);
00938 }
00939 }
00940
00941 for (i = 0; i < synth->midi_channels; i++) {
00942 fluid_channel_reset(synth->channel[i]);
00943 }
00944
00945 fluid_chorus_reset(synth->chorus);
00946 fluid_revmodel_reset(synth->reverb);
00947
00948 return FLUID_OK;
00949 }
00950
00951
00952
00953
00954
00955
00956
00957 int
00958 fluid_synth_modulate_voices(fluid_synth_t* synth, int chan, int is_cc, int ctrl)
00959 {
00960 int i;
00961 fluid_voice_t* voice;
00962
00963
00964
00965
00966 for (i = 0; i < synth->polyphony; i++) {
00967 voice = synth->voice[i];
00968 if (voice->chan == chan) {
00969 fluid_voice_modulate(voice, is_cc, ctrl);
00970 }
00971 }
00972 return FLUID_OK;
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982 int
00983 fluid_synth_modulate_voices_all(fluid_synth_t* synth, int chan)
00984 {
00985 int i;
00986 fluid_voice_t* voice;
00987
00988
00989
00990
00991 for (i = 0; i < synth->polyphony; i++) {
00992 voice = synth->voice[i];
00993 if (voice->chan == chan) {
00994 fluid_voice_modulate_all(voice);
00995 }
00996 }
00997 return FLUID_OK;
00998 }
00999
01010 int
01011 fluid_synth_channel_pressure(fluid_synth_t* synth, int chan, int val)
01012 {
01013
01014
01015
01016
01017
01018 if ((chan < 0) || (chan >= synth->midi_channels)) {
01019 FLUID_LOG(FLUID_WARN, "Channel out of range");
01020 return FLUID_FAILED;
01021 }
01022
01023 if (synth->verbose) {
01024 FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val);
01025 }
01026
01027
01028 fluid_channel_pressure(synth->channel[chan], val);
01029
01030 return FLUID_OK;
01031 }
01032
01043 int
01044 fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val)
01045 {
01046
01047
01048
01049
01050
01051 if ((chan < 0) || (chan >= synth->midi_channels)) {
01052 FLUID_LOG(FLUID_WARN, "Channel out of range");
01053 return FLUID_FAILED;
01054 }
01055
01056 if (synth->verbose) {
01057 FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val);
01058 }
01059
01060
01061 fluid_channel_pitch_bend(synth->channel[chan], val);
01062
01063 return FLUID_OK;
01064 }
01065
01066
01067
01068
01069 int
01070 fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend)
01071 {
01072
01073 if ((chan < 0) || (chan >= synth->midi_channels)) {
01074 FLUID_LOG(FLUID_WARN, "Channel out of range");
01075 return FLUID_FAILED;
01076 }
01077
01078 *ppitch_bend = synth->channel[chan]->pitch_bend;
01079 return FLUID_OK;
01080 }
01081
01082
01083
01084
01085 int
01086 fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val)
01087 {
01088
01089
01090 if ((chan < 0) || (chan >= synth->midi_channels)) {
01091 FLUID_LOG(FLUID_WARN, "Channel out of range");
01092 return FLUID_FAILED;
01093 }
01094
01095 if (synth->verbose) {
01096 FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val);
01097 }
01098
01099
01100 fluid_channel_pitch_wheel_sens(synth->channel[chan], val);
01101
01102 return FLUID_OK;
01103 }
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 int
01114 fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval)
01115 {
01116
01117
01118 if ((chan < 0) || (chan >= synth->midi_channels)) {
01119 FLUID_LOG(FLUID_WARN, "Channel out of range");
01120 return FLUID_FAILED;
01121 }
01122
01123
01124 *pval = synth->channel[chan]->pitch_wheel_sensitivity;
01125
01126 return FLUID_OK;
01127 }
01128
01129
01130
01131
01132 fluid_preset_t*
01133 fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
01134 unsigned int banknum, unsigned int prognum)
01135 {
01136 fluid_preset_t* preset = NULL;
01137 fluid_sfont_t* sfont = NULL;
01138 fluid_list_t* list = synth->sfont;
01139 int offset;
01140
01141 sfont = fluid_synth_get_sfont_by_id(synth, sfontnum);
01142
01143 if (sfont != NULL) {
01144 offset = fluid_synth_get_bank_offset(synth, sfontnum);
01145 preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum);
01146 if (preset != NULL) {
01147 return preset;
01148 }
01149 }
01150 return NULL;
01151 }
01152
01153
01154
01155
01156 fluid_preset_t*
01157 fluid_synth_get_preset2(fluid_synth_t* synth, char* sfont_name,
01158 unsigned int banknum, unsigned int prognum)
01159 {
01160 fluid_preset_t* preset = NULL;
01161 fluid_sfont_t* sfont = NULL;
01162 int offset;
01163
01164 sfont = fluid_synth_get_sfont_by_name(synth, sfont_name);
01165
01166 if (sfont != NULL) {
01167 offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont));
01168 preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum);
01169 if (preset != NULL) {
01170 return preset;
01171 }
01172 }
01173 return NULL;
01174 }
01175
01176 fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
01177 unsigned int banknum,
01178 unsigned int prognum)
01179 {
01180 fluid_preset_t* preset = NULL;
01181 fluid_sfont_t* sfont = NULL;
01182 fluid_list_t* list = synth->sfont;
01183 int offset;
01184
01185 while (list) {
01186
01187 sfont = (fluid_sfont_t*) fluid_list_get(list);
01188 offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont));
01189 preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum);
01190
01191 if (preset != NULL) {
01192 preset->sfont = sfont;
01193 return preset;
01194 }
01195
01196 list = fluid_list_next(list);
01197
01198 }
01199 return NULL;
01200 }
01201
01202
01203
01204
01205
01206 int
01207 fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum)
01208 {
01209 fluid_preset_t* preset = NULL;
01210 fluid_channel_t* channel;
01211 unsigned int banknum;
01212 unsigned int sfont_id;
01213 int subst_bank, subst_prog;
01214
01215 if ((prognum < 0) || (prognum >= FLUID_NUM_PROGRAMS) ||
01216 (chan < 0) || (chan >= synth->midi_channels))
01217 {
01218 FLUID_LOG(FLUID_ERR, "Index out of range (chan=%d, prog=%d)", chan, prognum);
01219 return FLUID_FAILED;
01220 }
01221
01222 channel = synth->channel[chan];
01223 banknum = fluid_channel_get_banknum(channel);
01224
01225
01226 fluid_channel_set_prognum(channel, prognum);
01227
01228 if (synth->verbose)
01229 FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum);
01230
01231
01232
01233
01234
01235
01236
01237
01238 if (channel->channum == 9)
01239 preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, prognum);
01240 else preset = fluid_synth_find_preset(synth, banknum, prognum);
01241
01242
01243 if (!preset)
01244 {
01245 subst_bank = banknum;
01246 subst_prog = prognum;
01247
01248
01249 if (channel->channum != 9 && banknum != DRUM_INST_BANK)
01250 {
01251 subst_bank = 0;
01252
01253
01254 preset = fluid_synth_find_preset(synth, 0, prognum);
01255
01256
01257 if (!preset && prognum != 0)
01258 {
01259 preset = fluid_synth_find_preset(synth, 0, 0);
01260 subst_prog = 0;
01261 }
01262 }
01263 else
01264 {
01265 preset = fluid_synth_find_preset(synth, DRUM_INST_BANK, 0);
01266 subst_prog = 0;
01267 }
01268
01269 if (preset)
01270 FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]",
01271 chan, banknum, prognum, subst_bank, subst_prog);
01272 }
01273
01274 sfont_id = preset? fluid_sfont_get_id(preset->sfont) : 0;
01275 fluid_channel_set_sfontnum(channel, sfont_id);
01276 fluid_channel_set_preset(channel, preset);
01277
01278 return FLUID_OK;
01279 }
01280
01281
01282
01283
01284 int fluid_synth_bank_select(fluid_synth_t* synth, int chan, unsigned int bank)
01285 {
01286 if ((chan >= 0) && (chan < synth->midi_channels)) {
01287 fluid_channel_set_banknum(synth->channel[chan], bank);
01288 return FLUID_OK;
01289 }
01290 return FLUID_FAILED;
01291 }
01292
01293
01294
01295
01296
01297 int fluid_synth_sfont_select(fluid_synth_t* synth, int chan, unsigned int sfont_id)
01298 {
01299 if ((chan >= 0) && (chan < synth->midi_channels)) {
01300 fluid_channel_set_sfontnum(synth->channel[chan], sfont_id);
01301 return FLUID_OK;
01302 }
01303 return FLUID_FAILED;
01304 }
01305
01306
01307
01308
01309 int
01310 fluid_synth_get_program(fluid_synth_t* synth, int chan,
01311 unsigned int* sfont_id, unsigned int* bank_num, unsigned int* preset_num)
01312 {
01313 fluid_channel_t* channel;
01314 if ((chan >= 0) && (chan < synth->midi_channels)) {
01315 channel = synth->channel[chan];
01316 *sfont_id = fluid_channel_get_sfontnum(channel);
01317 *bank_num = fluid_channel_get_banknum(channel);
01318 *preset_num = fluid_channel_get_prognum(channel);
01319 return FLUID_OK;
01320 }
01321 return FLUID_FAILED;
01322 }
01323
01324
01325
01326
01327 int fluid_synth_program_select(fluid_synth_t* synth,
01328 int chan,
01329 unsigned int sfont_id,
01330 unsigned int bank_num,
01331 unsigned int preset_num)
01332 {
01333 fluid_preset_t* preset = NULL;
01334 fluid_channel_t* channel;
01335
01336 if ((chan < 0) || (chan >= synth->midi_channels)) {
01337 FLUID_LOG(FLUID_ERR, "Channel number out of range (chan=%d)", chan);
01338 return FLUID_FAILED;
01339 }
01340 channel = synth->channel[chan];
01341
01342 preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num);
01343 if (preset == NULL) {
01344 FLUID_LOG(FLUID_ERR,
01345 "There is no preset with bank number %d and preset number %d in SoundFont %d",
01346 bank_num, preset_num, sfont_id);
01347 return FLUID_FAILED;
01348 }
01349
01350
01351 fluid_channel_set_sfontnum(channel, sfont_id);
01352 fluid_channel_set_banknum(channel, bank_num);
01353 fluid_channel_set_prognum(channel, preset_num);
01354
01355 fluid_channel_set_preset(channel, preset);
01356
01357 return FLUID_OK;
01358 }
01359
01360
01361
01362
01363 int fluid_synth_program_select2(fluid_synth_t* synth,
01364 int chan,
01365 char* sfont_name,
01366 unsigned int bank_num,
01367 unsigned int preset_num)
01368 {
01369 fluid_preset_t* preset = NULL;
01370 fluid_channel_t* channel;
01371 fluid_sfont_t* sfont = NULL;
01372 int offset;
01373
01374 if ((chan < 0) || (chan >= synth->midi_channels)) {
01375 FLUID_LOG(FLUID_ERR, "Channel number out of range (chan=%d)", chan);
01376 return FLUID_FAILED;
01377 }
01378 channel = synth->channel[chan];
01379
01380 sfont = fluid_synth_get_sfont_by_name(synth, sfont_name);
01381 if (sfont == NULL) {
01382 FLUID_LOG(FLUID_ERR, "Could not find SoundFont %s", sfont_name);
01383 return FLUID_FAILED;
01384 }
01385
01386 offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont));
01387 preset = fluid_sfont_get_preset(sfont, bank_num - offset, preset_num);
01388 if (preset == NULL) {
01389 FLUID_LOG(FLUID_ERR,
01390 "There is no preset with bank number %d and preset number %d in SoundFont %s",
01391 bank_num, preset_num, sfont_name);
01392 return FLUID_FAILED;
01393 }
01394
01395
01396 fluid_channel_set_sfontnum(channel, fluid_sfont_get_id(sfont));
01397 fluid_channel_set_banknum(channel, bank_num);
01398 fluid_channel_set_prognum(channel, preset_num);
01399
01400 fluid_channel_set_preset(channel, preset);
01401
01402 return FLUID_OK;
01403 }
01404
01405
01406
01407
01408 void fluid_synth_update_presets(fluid_synth_t* synth)
01409 {
01410 int chan;
01411 fluid_channel_t* channel;
01412
01413 for (chan = 0; chan < synth->midi_channels; chan++) {
01414 channel = synth->channel[chan];
01415 fluid_channel_set_preset(channel,
01416 fluid_synth_get_preset(synth,
01417 fluid_channel_get_sfontnum(channel),
01418 fluid_channel_get_banknum(channel),
01419 fluid_channel_get_prognum(channel)));
01420 }
01421 }
01422
01423
01424
01425
01426
01427 int fluid_synth_update_gain(fluid_synth_t* synth, char* name, double value)
01428 {
01429 fluid_synth_set_gain(synth, (float) value);
01430 return 0;
01431 }
01432
01433
01434
01435
01436 void fluid_synth_set_gain(fluid_synth_t* synth, float gain)
01437 {
01438 int i;
01439
01440 fluid_clip(gain, 0.0f, 10.0f);
01441 synth->gain = gain;
01442
01443 for (i = 0; i < synth->polyphony; i++) {
01444 fluid_voice_t* voice = synth->voice[i];
01445 if (_PLAYING(voice)) {
01446 fluid_voice_set_gain(voice, gain);
01447 }
01448 }
01449 }
01450
01451
01452
01453
01454 float fluid_synth_get_gain(fluid_synth_t* synth)
01455 {
01456 return synth->gain;
01457 }
01458
01459
01460
01461
01462 int fluid_synth_update_polyphony(fluid_synth_t* synth, char* name, int value)
01463 {
01464 fluid_synth_set_polyphony(synth, value);
01465 return 0;
01466 }
01467
01468
01469
01470
01471 int fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony)
01472 {
01473 int i;
01474
01475 if (polyphony < 1 || polyphony > synth->nvoice) {
01476 return FLUID_FAILED;
01477 }
01478
01479
01480 for (i = polyphony; i < synth->nvoice; i++) {
01481 fluid_voice_t* voice = synth->voice[i];
01482 if (_PLAYING(voice)) {
01483 fluid_voice_off(voice);
01484 }
01485 }
01486
01487 synth->polyphony = polyphony;
01488
01489 return FLUID_OK;
01490 }
01491
01492
01493
01494
01495 int fluid_synth_get_polyphony(fluid_synth_t* synth)
01496 {
01497 return synth->polyphony;
01498 }
01499
01500
01501
01502
01503 int fluid_synth_get_internal_bufsize(fluid_synth_t* synth)
01504 {
01505 return FLUID_BUFSIZE;
01506 }
01507
01508
01509
01510
01511
01512
01513
01514 int
01515 fluid_synth_program_reset(fluid_synth_t* synth)
01516 {
01517 int i;
01518
01519 for (i = 0; i < synth->midi_channels; i++){
01520 fluid_synth_program_change(synth, i, fluid_channel_get_prognum(synth->channel[i]));
01521 }
01522 return FLUID_OK;
01523 }
01524
01525
01526
01527
01528 int fluid_synth_set_reverb_preset(fluid_synth_t* synth, int num)
01529 {
01530 int i = 0;
01531 while (revmodel_preset[i].name != NULL) {
01532 if (i == num) {
01533 fluid_revmodel_setroomsize(synth->reverb, revmodel_preset[i].roomsize);
01534 fluid_revmodel_setdamp(synth->reverb, revmodel_preset[i].damp);
01535 fluid_revmodel_setwidth(synth->reverb, revmodel_preset[i].width);
01536 fluid_revmodel_setlevel(synth->reverb, revmodel_preset[i].level);
01537 return FLUID_OK;
01538 }
01539 i++;
01540 }
01541 return FLUID_FAILED;
01542 }
01543
01544
01545
01546
01547 void fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, double damping,
01548 double width, double level)
01549 {
01550
01551
01552
01553 fluid_revmodel_setroomsize(synth->reverb, roomsize);
01554 fluid_revmodel_setdamp(synth->reverb, damping);
01555 fluid_revmodel_setwidth(synth->reverb, width);
01556 fluid_revmodel_setlevel(synth->reverb, level);
01557 }
01558
01559
01560
01561
01562 void fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level,
01563 double speed, double depth_ms, int type)
01564 {
01565
01566
01567
01568 fluid_chorus_set_nr(synth->chorus, nr);
01569 fluid_chorus_set_level(synth->chorus, (fluid_real_t)level);
01570 fluid_chorus_set_speed_Hz(synth->chorus, (fluid_real_t)speed);
01571 fluid_chorus_set_depth_ms(synth->chorus, (fluid_real_t)depth_ms);
01572 fluid_chorus_set_type(synth->chorus, type);
01573 fluid_chorus_update(synth->chorus);
01574 }
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628 int
01629 fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
01630 float** left, float** right,
01631 float** fx_left, float** fx_right)
01632 {
01633 fluid_real_t** left_in = synth->left_buf;
01634 fluid_real_t** right_in = synth->right_buf;
01635 double time = fluid_utime();
01636 int i, num, available, count, bytes;
01637
01638
01639 if (synth->state != FLUID_SYNTH_PLAYING) {
01640 return 0;
01641 }
01642
01643
01644 count = 0;
01645 num = synth->cur;
01646 if (synth->cur < FLUID_BUFSIZE) {
01647 available = FLUID_BUFSIZE - synth->cur;
01648
01649 num = (available > len)? len : available;
01650 bytes = num * sizeof(float);
01651
01652 for (i = 0; i < synth->audio_channels; i++) {
01653 FLUID_MEMCPY(left[i], left_in[i] + synth->cur, bytes);
01654 FLUID_MEMCPY(right[i], right_in[i] + synth->cur, bytes);
01655 }
01656 count += num;
01657 num += synth->cur;
01658 }
01659
01660
01661 while (count < len) {
01662 fluid_synth_one_block(synth, 1);
01663
01664 num = (FLUID_BUFSIZE > len - count)? len - count : FLUID_BUFSIZE;
01665 bytes = num * sizeof(float);
01666
01667 for (i = 0; i < synth->audio_channels; i++) {
01668 FLUID_MEMCPY(left[i] + count, left_in[i], bytes);
01669 FLUID_MEMCPY(right[i] + count, right_in[i], bytes);
01670 }
01671
01672 count += num;
01673 }
01674
01675 synth->cur = num;
01676
01677 time = fluid_utime() - time;
01678 synth->cpu_load = 0.5 * (synth->cpu_load +
01679 time * synth->sample_rate / len / 10000.0);
01680
01681
01682
01683 return 0;
01684 }
01685
01686
01687 int fluid_synth_process(fluid_synth_t* synth, int len,
01688 int nin, float** in,
01689 int nout, float** out)
01690 {
01691 if (nout==2) {
01692 return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1);
01693 }
01694 else {
01695 float **left, **right;
01696 int i;
01697 left = FLUID_ARRAY(float*, nout/2);
01698 right = FLUID_ARRAY(float*, nout/2);
01699 for(i=0; i<nout/2; i++) {
01700 left[i] = out[2*i];
01701 right[i] = out[2*i+1];
01702 }
01703 fluid_synth_nwrite_float(synth, len, left, right, NULL, NULL);
01704 FLUID_FREE(left);
01705 FLUID_FREE(right);
01706 return 0;
01707 }
01708 }
01709
01710
01711
01712
01713
01714 int
01715 fluid_synth_write_float(fluid_synth_t* synth, int len,
01716 void* lout, int loff, int lincr,
01717 void* rout, int roff, int rincr)
01718 {
01719 int i, j, k, l;
01720 float* left_out = (float*) lout;
01721 float* right_out = (float*) rout;
01722 fluid_real_t* left_in = synth->left_buf[0];
01723 fluid_real_t* right_in = synth->right_buf[0];
01724 double time = fluid_utime();
01725
01726
01727 if (synth->state != FLUID_SYNTH_PLAYING) {
01728 return 0;
01729 }
01730
01731 l = synth->cur;
01732
01733 for (i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr) {
01734
01735 if (l == FLUID_BUFSIZE) {
01736 fluid_synth_one_block(synth, 0);
01737 l = 0;
01738 }
01739
01740 left_out[j] = (float) left_in[l];
01741 right_out[k] = (float) right_in[l];
01742 }
01743
01744 synth->cur = l;
01745
01746 time = fluid_utime() - time;
01747 synth->cpu_load = 0.5 * (synth->cpu_load +
01748 time * synth->sample_rate / len / 10000.0);
01749
01750
01751
01752 return 0;
01753 }
01754
01755 #define DITHER_SIZE 48000
01756 #define DITHER_CHANNELS 2
01757
01758 static float rand_table[DITHER_CHANNELS][DITHER_SIZE];
01759
01760 static void init_dither(void)
01761 {
01762 float d, dp;
01763 int c, i;
01764
01765 for (c = 0; c < DITHER_CHANNELS; c++) {
01766 dp = 0;
01767 for (i = 0; i < DITHER_SIZE-1; i++) {
01768 d = rand() / (float)RAND_MAX - 0.5f;
01769 rand_table[c][i] = d - dp;
01770 dp = d;
01771 }
01772 rand_table[c][DITHER_SIZE-1] = 0 - dp;
01773 }
01774 }
01775
01776
01777 static inline int
01778 roundi (float x)
01779 {
01780 if (x >= 0.0f)
01781 return (int)(x+0.5f);
01782 else
01783 return (int)(x-0.5f);
01784 }
01785
01786
01787
01788
01789 int
01790 fluid_synth_write_s16(fluid_synth_t* synth, int len,
01791 void* lout, int loff, int lincr,
01792 void* rout, int roff, int rincr)
01793 {
01794 int i, j, k, cur;
01795 signed short* left_out = (signed short*) lout;
01796 signed short* right_out = (signed short*) rout;
01797 fluid_real_t* left_in = synth->left_buf[0];
01798 fluid_real_t* right_in = synth->right_buf[0];
01799 double prof_ref = fluid_profile_ref();
01800 fluid_real_t left_sample;
01801 fluid_real_t right_sample;
01802 double time = fluid_utime();
01803 int di = synth->dither_index;
01804 double prof_ref_on_block;
01805
01806
01807 if (synth->state != FLUID_SYNTH_PLAYING) {
01808 return 0;
01809 }
01810
01811 cur = synth->cur;
01812
01813 for (i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr) {
01814
01815
01816 if (cur == FLUID_BUFSIZE) {
01817 prof_ref_on_block = fluid_profile_ref();
01818
01819 fluid_synth_one_block(synth, 0);
01820 cur = 0;
01821
01822 fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref_on_block);
01823 }
01824
01825 left_sample = roundi (left_in[cur] * 32766.0f + rand_table[0][di]);
01826 right_sample = roundi (right_in[cur] * 32766.0f + rand_table[1][di]);
01827
01828 di++;
01829 if (di >= DITHER_SIZE) di = 0;
01830
01831
01832 if (left_sample > 32767.0f) left_sample = 32767.0f;
01833 if (left_sample < -32768.0f) left_sample = -32768.0f;
01834 if (right_sample > 32767.0f) right_sample = 32767.0f;
01835 if (right_sample < -32768.0f) right_sample = -32768.0f;
01836
01837 left_out[j] = (signed short) left_sample;
01838 right_out[k] = (signed short) right_sample;
01839 }
01840
01841 synth->cur = cur;
01842 synth->dither_index = di;
01843
01844 fluid_profile(FLUID_PROF_WRITE_S16, prof_ref);
01845
01846
01847 time = fluid_utime() - time;
01848 synth->cpu_load = 0.5 * (synth->cpu_load +
01849 time * synth->sample_rate / len / 10000.0);
01850
01851
01852
01853 return 0;
01854 }
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864 void
01865 fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
01866 void* lout, int loff, int lincr,
01867 void* rout, int roff, int rincr)
01868 {
01869 int i, j, k;
01870 signed short* left_out = (signed short*) lout;
01871 signed short* right_out = (signed short*) rout;
01872 double prof_ref = fluid_profile_ref();
01873 fluid_real_t left_sample;
01874 fluid_real_t right_sample;
01875 int di = *dither_index;
01876
01877 for (i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr) {
01878
01879 left_sample = roundi (lin[i] * 32766.0f + rand_table[0][di]);
01880 right_sample = roundi (rin[i] * 32766.0f + rand_table[1][di]);
01881
01882 di++;
01883 if (di >= DITHER_SIZE) di = 0;
01884
01885
01886 if (left_sample > 32767.0f) left_sample = 32767.0f;
01887 if (left_sample < -32768.0f) left_sample = -32768.0f;
01888 if (right_sample > 32767.0f) right_sample = 32767.0f;
01889 if (right_sample < -32768.0f) right_sample = -32768.0f;
01890
01891 left_out[j] = (signed short) left_sample;
01892 right_out[k] = (signed short) right_sample;
01893 }
01894
01895 *dither_index = di;
01896
01897 fluid_profile(FLUID_PROF_WRITE_S16, prof_ref);
01898 }
01899
01900
01901
01902
01903 int
01904 fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
01905 {
01906 int i, auchan;
01907 fluid_voice_t* voice;
01908 fluid_real_t* left_buf;
01909 fluid_real_t* right_buf;
01910 fluid_real_t* reverb_buf;
01911 fluid_real_t* chorus_buf;
01912 int byte_size = FLUID_BUFSIZE * sizeof(fluid_real_t);
01913 double prof_ref = fluid_profile_ref();
01914
01915
01916
01917 fluid_check_fpe("??? Just starting up ???");
01918
01919
01920 for (i = 0; i < synth->nbuf; i++) {
01921 FLUID_MEMSET(synth->left_buf[i], 0, byte_size);
01922 FLUID_MEMSET(synth->right_buf[i], 0, byte_size);
01923 }
01924
01925 for (i = 0; i < synth->effects_channels; i++) {
01926 FLUID_MEMSET(synth->fx_left_buf[i], 0, byte_size);
01927 FLUID_MEMSET(synth->fx_right_buf[i], 0, byte_size);
01928 }
01929
01930
01931
01932
01933
01934 reverb_buf = synth->with_reverb ? synth->fx_left_buf[0] : NULL;
01935 chorus_buf = synth->with_chorus ? synth->fx_left_buf[1] : NULL;
01936
01937 fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref);
01938
01939
01940 for (i = 0; i < synth->polyphony; i++) {
01941 voice = synth->voice[i];
01942
01943 if (_PLAYING(voice)) {
01944 double prof_ref_voice = fluid_profile_ref();
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958 auchan = fluid_channel_get_num(fluid_voice_get_channel(voice));
01959 auchan %= synth->audio_groups;
01960 left_buf = synth->left_buf[auchan];
01961 right_buf = synth->right_buf[auchan];
01962
01963 fluid_voice_write(voice, left_buf, right_buf, reverb_buf, chorus_buf);
01964
01965 fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref_voice);
01966 }
01967 }
01968
01969 fluid_check_fpe("Synthesis processes");
01970
01971 fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref);
01972
01973
01974
01975
01976
01977 if (do_not_mix_fx_to_out) {
01978
01979
01980 if (reverb_buf) {
01981 fluid_revmodel_processreplace(synth->reverb, reverb_buf,
01982 synth->fx_left_buf[0], synth->fx_right_buf[0]);
01983 fluid_check_fpe("Reverb");
01984 }
01985
01986 fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref);
01987
01988
01989 if (chorus_buf) {
01990 fluid_chorus_processreplace(synth->chorus, chorus_buf,
01991 synth->fx_left_buf[1], synth->fx_right_buf[1]);
01992 fluid_check_fpe("Chorus");
01993 }
01994
01995 } else {
01996
01997
01998 if (reverb_buf) {
01999 fluid_revmodel_processmix(synth->reverb, reverb_buf,
02000 synth->left_buf[0], synth->right_buf[0]);
02001 fluid_check_fpe("Reverb");
02002 }
02003
02004 fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref);
02005
02006
02007 if (chorus_buf) {
02008 fluid_chorus_processmix(synth->chorus, chorus_buf,
02009 synth->left_buf[0], synth->right_buf[0]);
02010 fluid_check_fpe("Chorus");
02011 }
02012 }
02013
02014 fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref);
02015
02016 #ifdef LADSPA
02017
02018 fluid_LADSPA_run(synth->LADSPA_FxUnit, synth->left_buf, synth->right_buf, synth->fx_left_buf, synth->fx_right_buf);
02019 fluid_check_fpe("LADSPA");
02020 #endif
02021
02022 synth->ticks += FLUID_BUFSIZE;
02023
02024
02025 #if 0
02026 {float num=1;while (num != 0){num*=0.5;};};
02027 #endif
02028 fluid_check_fpe("??? Remainder of synth_one_block ???");
02029
02030
02031
02032 return 0;
02033 }
02034
02035
02036
02037
02038
02039
02040
02041
02042 fluid_voice_t*
02043 fluid_synth_free_voice_by_kill(fluid_synth_t* synth)
02044 {
02045 int i;
02046 fluid_real_t best_prio = 999999.;
02047 fluid_real_t this_voice_prio;
02048 fluid_voice_t* voice;
02049 int best_voice_index=-1;
02050
02051
02052
02053
02054 for (i = 0; i < synth->polyphony; i++) {
02055
02056 voice = synth->voice[i];
02057
02058
02059 if (_AVAILABLE(voice)) {
02060 return voice;
02061 }
02062
02063
02064
02065 this_voice_prio = 10000.;
02066
02067
02068
02069
02070
02071
02072
02073 if (voice->chan == 9){
02074 this_voice_prio += 4000;
02075
02076 } else if (_RELEASED(voice)){
02077
02078
02079
02080 this_voice_prio -= 2000.;
02081 }
02082
02083 if (_SUSTAINED(voice)){
02084
02085
02086
02087
02088
02089
02090 this_voice_prio -= 1000;
02091 }
02092
02093
02094
02095
02096
02097
02098
02099 this_voice_prio -= (synth->noteid - fluid_voice_get_id(voice));
02100
02101
02102 if (voice->volenv_section != FLUID_VOICE_ENVATTACK){
02103 this_voice_prio += voice->volenv_val * 1000.;
02104 }
02105
02106
02107 if (this_voice_prio < best_prio)
02108 best_voice_index = i,
02109 best_prio = this_voice_prio;
02110 }
02111
02112 if (best_voice_index < 0) {
02113 return NULL;
02114 }
02115
02116 voice = synth->voice[best_voice_index];
02117 fluid_voice_off(voice);
02118
02119 return voice;
02120 }
02121
02122
02123
02124
02125 fluid_voice_t*
02126 fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int key, int vel)
02127 {
02128 int i, k;
02129 fluid_voice_t* voice = NULL;
02130 fluid_channel_t* channel = NULL;
02131
02132
02133
02134
02135
02136 for (i = 0; i < synth->polyphony; i++) {
02137 if (_AVAILABLE(synth->voice[i])) {
02138 voice = synth->voice[i];
02139 break;
02140 }
02141 }
02142
02143
02144 if (voice == NULL) {
02145 voice = fluid_synth_free_voice_by_kill(synth);
02146 }
02147
02148 if (voice == NULL) {
02149 FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key);
02150 return NULL;
02151 }
02152
02153 if (synth->verbose) {
02154 k = 0;
02155 for (i = 0; i < synth->polyphony; i++) {
02156 if (!_AVAILABLE(synth->voice[i])) {
02157 k++;
02158 }
02159 }
02160
02161 FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d",
02162 chan, key, vel, synth->storeid,
02163 (float) synth->ticks / 44100.0f,
02164 (fluid_curtime() - synth->start) / 1000.0f,
02165 0.0f,
02166 k);
02167 }
02168
02169 if (chan >= 0) {
02170 channel = synth->channel[chan];
02171 }
02172
02173 if (fluid_voice_init(voice, sample, channel, key, vel,
02174 synth->storeid, synth->ticks, synth->gain) != FLUID_OK) {
02175 FLUID_LOG(FLUID_WARN, "Failed to initialize voice");
02176 return NULL;
02177 }
02178
02179
02180 fluid_voice_add_mod(voice, &default_vel2att_mod, FLUID_VOICE_DEFAULT);
02181 fluid_voice_add_mod(voice, &default_vel2filter_mod, FLUID_VOICE_DEFAULT);
02182 fluid_voice_add_mod(voice, &default_at2viblfo_mod, FLUID_VOICE_DEFAULT);
02183 fluid_voice_add_mod(voice, &default_mod2viblfo_mod, FLUID_VOICE_DEFAULT);
02184 fluid_voice_add_mod(voice, &default_att_mod, FLUID_VOICE_DEFAULT);
02185 fluid_voice_add_mod(voice, &default_pan_mod, FLUID_VOICE_DEFAULT);
02186 fluid_voice_add_mod(voice, &default_expr_mod, FLUID_VOICE_DEFAULT);
02187 fluid_voice_add_mod(voice, &default_reverb_mod, FLUID_VOICE_DEFAULT);
02188 fluid_voice_add_mod(voice, &default_chorus_mod, FLUID_VOICE_DEFAULT);
02189 fluid_voice_add_mod(voice, &default_pitch_bend_mod, FLUID_VOICE_DEFAULT);
02190
02191 return voice;
02192 }
02193
02194
02195
02196
02197 void fluid_synth_kill_by_exclusive_class(fluid_synth_t* synth, fluid_voice_t* new_voice)
02198 {
02209 int i;
02210 int excl_class = _GEN(new_voice,GEN_EXCLUSIVECLASS);
02211
02212
02213
02214
02215
02216 if (excl_class == 0) {
02217 return;
02218 }
02219
02220
02221
02222
02223
02224 for (i = 0; i < synth->polyphony; i++) {
02225 fluid_voice_t* existing_voice = synth->voice[i];
02226
02227
02228 if (!_PLAYING(existing_voice)) {
02229 continue;
02230 }
02231
02232
02233
02234 if (existing_voice->chan != new_voice->chan) {
02235 continue;
02236 }
02237
02238
02239 if ((int)_GEN(existing_voice, GEN_EXCLUSIVECLASS) != excl_class) {
02240 continue;
02241 }
02242
02243
02244
02245 if (fluid_voice_get_id(existing_voice) == fluid_voice_get_id(new_voice)) {
02246 continue;
02247 }
02248
02249
02250
02251
02252 fluid_voice_kill_excl(existing_voice);
02253 };
02254 };
02255
02256
02257
02258
02259 void fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice)
02260 {
02261
02262
02263
02264
02265
02266
02267 fluid_synth_kill_by_exclusive_class(synth, voice);
02268
02269
02270
02271 fluid_voice_start(voice);
02272 }
02273
02274
02275
02276
02277 void fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader)
02278 {
02279 synth->loaders = fluid_list_prepend(synth->loaders, loader);
02280 }
02281
02282
02283
02284
02285
02286 int
02287 fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets)
02288 {
02289 fluid_sfont_t* sfont;
02290 fluid_list_t* list;
02291 fluid_sfloader_t* loader;
02292
02293 #if defined(MACOS9)
02294 fluid_synth_sfunload_macos9(synth);
02295 #endif
02296
02297 if (filename == NULL) {
02298 FLUID_LOG(FLUID_ERR, "Invalid filename");
02299 return FLUID_FAILED;
02300 }
02301
02302 for (list = synth->loaders; list; list = fluid_list_next(list)) {
02303 loader = (fluid_sfloader_t*) fluid_list_get(list);
02304
02305 sfont = fluid_sfloader_load(loader, filename);
02306
02307 if (sfont != NULL) {
02308
02309 sfont->id = ++synth->sfont_id;
02310
02311
02312 synth->sfont = fluid_list_prepend(synth->sfont, sfont);
02313
02314
02315 if (reset_presets) {
02316 fluid_synth_program_reset(synth);
02317 }
02318
02319 return (int) sfont->id;
02320 }
02321 }
02322
02323 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
02324 return -1;
02325 }
02326
02327
02328
02329
02330 static int fluid_synth_sfunload_callback(void* data, unsigned int msec)
02331 {
02332 fluid_sfont_t* sfont = (fluid_sfont_t*) data;
02333 int r = delete_fluid_sfont(sfont);
02334 if (r == 0) {
02335 FLUID_LOG(FLUID_DBG,"Unloaded SoundFont");
02336 }
02337 return r != 0;
02338 }
02339
02340
02341
02342
02343 void fluid_synth_sfunload_macos9(fluid_synth_t* synth)
02344 {
02345 #if defined(MACOS9)
02346 fluid_list_t *list, *next;
02347 fluid_sfont_t* sfont;
02348
02349 list = synth->unloading;
02350 while (list) {
02351 next = fluid_list_next(list);
02352 sfont = (fluid_sfont_t*) fluid_list_get(list);
02353 if (delete_fluid_sfont(sfont) == 0) {
02354 synth->unloading = fluid_list_remove(synth->unloading, sfont);
02355 }
02356 list = next;
02357 }
02358 #endif
02359 }
02360
02361
02362
02363
02364 int
02365 fluid_synth_sfunload(fluid_synth_t* synth, unsigned int id, int reset_presets)
02366 {
02367 fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth, id);
02368
02369 #if defined(MACOS9)
02370 fluid_synth_sfunload_macos9(synth);
02371 #endif
02372
02373 if (!sfont) {
02374 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
02375 return FLUID_FAILED;
02376 }
02377
02378
02379 synth->sfont = fluid_list_remove(synth->sfont, sfont);
02380
02381
02382 if (reset_presets) {
02383 fluid_synth_program_reset(synth);
02384 } else {
02385 fluid_synth_update_presets(synth);
02386 }
02387
02388 if (delete_fluid_sfont(sfont) != 0) {
02389 #if defined(MACOS9)
02390 synth->unloading = fluid_list_prepend(synth->unloading, sfont);
02391 #else
02392
02393 new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, 1, 1);
02394 #endif
02395 }
02396
02397 return FLUID_OK;
02398 }
02399
02400
02401
02402
02403 int fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id)
02404 {
02405 char filename[1024];
02406 fluid_sfont_t* sfont;
02407 int index = 0;
02408 fluid_list_t *list;
02409 fluid_sfloader_t* loader;
02410
02411
02412 sfont = fluid_synth_get_sfont_by_id(synth, id);
02413 if (!sfont) {
02414 FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
02415 return FLUID_FAILED;
02416 }
02417
02418
02419 list = synth->sfont;
02420 while (list) {
02421 if (sfont == (fluid_sfont_t*) fluid_list_get(list)) {
02422 break;
02423 }
02424 list = fluid_list_next(list);
02425 index++;
02426 }
02427
02428
02429 FLUID_STRCPY(filename, fluid_sfont_get_name(sfont));
02430
02431 if (fluid_synth_sfunload(synth, id, 0) != FLUID_OK) {
02432 return FLUID_FAILED;
02433 }
02434
02435 for (list = synth->loaders; list; list = fluid_list_next(list)) {
02436 loader = (fluid_sfloader_t*) fluid_list_get(list);
02437
02438 sfont = fluid_sfloader_load(loader, filename);
02439
02440 if (sfont != NULL) {
02441
02442 sfont->id = id;
02443
02444
02445 synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont);
02446
02447
02448 fluid_synth_update_presets(synth);
02449
02450 return sfont->id;
02451 }
02452 }
02453
02454 FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename);
02455 return -1;
02456 }
02457
02458
02459
02460
02461
02462 int fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
02463 {
02464 sfont->id = ++synth->sfont_id;
02465
02466
02467 synth->sfont = fluid_list_prepend(synth->sfont, sfont);
02468
02469
02470 fluid_synth_program_reset(synth);
02471
02472 return sfont->id;
02473 }
02474
02475
02476
02477
02478
02479 void fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
02480 {
02481 int sfont_id = fluid_sfont_get_id(sfont);
02482
02483 synth->sfont = fluid_list_remove(synth->sfont, sfont);
02484
02485
02486 fluid_synth_remove_bank_offset(synth, sfont_id);
02487
02488
02489 fluid_synth_program_reset(synth);
02490 }
02491
02492
02493
02494
02495
02496
02497 int
02498 fluid_synth_sfcount(fluid_synth_t* synth)
02499 {
02500 return fluid_list_size(synth->sfont);
02501 }
02502
02503
02504
02505
02506
02507 fluid_sfont_t*
02508 fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num)
02509 {
02510 return (fluid_sfont_t*) fluid_list_get(fluid_list_nth(synth->sfont, num));
02511 }
02512
02513
02514
02515
02516 fluid_sfont_t* fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id)
02517 {
02518 fluid_list_t* list = synth->sfont;
02519 fluid_sfont_t* sfont;
02520
02521 while (list) {
02522 sfont = (fluid_sfont_t*) fluid_list_get(list);
02523 if (fluid_sfont_get_id(sfont) == id) {
02524 return sfont;
02525 }
02526 list = fluid_list_next(list);
02527 }
02528 return NULL;
02529 }
02530
02531
02532
02533
02534 fluid_sfont_t* fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name)
02535 {
02536 fluid_list_t* list = synth->sfont;
02537 fluid_sfont_t* sfont;
02538
02539 while (list) {
02540 sfont = (fluid_sfont_t*) fluid_list_get(list);
02541 if (FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0) {
02542 return sfont;
02543 }
02544 list = fluid_list_next(list);
02545 }
02546 return NULL;
02547 }
02548
02549
02550
02551
02552 fluid_preset_t*
02553 fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan)
02554 {
02555 if ((chan >= 0) && (chan < synth->midi_channels)) {
02556 return fluid_channel_get_preset(synth->channel[chan]);
02557 }
02558
02559 return NULL;
02560 }
02561
02562
02563
02564
02565 void
02566 fluid_synth_get_voicelist(fluid_synth_t* synth, fluid_voice_t* buf[], int bufsize, int ID)
02567 {
02568 int i;
02569 int count = 0;
02570 for (i = 0; i < synth->polyphony; i++) {
02571 fluid_voice_t* voice = synth->voice[i];
02572 if (count >= bufsize) {
02573 return;
02574 }
02575
02576 if (_PLAYING(voice) && ((int)voice->id == ID || ID < 0)) {
02577 buf[count++] = voice;
02578 }
02579 }
02580 if (count >= bufsize) {
02581 return;
02582 }
02583 buf[count++] = NULL;
02584 }
02585
02586
02587
02588 void fluid_synth_set_reverb_on(fluid_synth_t* synth, int on)
02589 {
02590 synth->with_reverb = on;
02591 }
02592
02593
02594
02595 void fluid_synth_set_chorus_on(fluid_synth_t* synth, int on)
02596 {
02597 synth->with_chorus = on;
02598 }
02599
02600
02601
02602 int fluid_synth_get_chorus_nr(fluid_synth_t* synth)
02603 {
02604 return fluid_chorus_get_nr(synth->chorus);
02605 }
02606
02607 double fluid_synth_get_chorus_level(fluid_synth_t* synth)
02608 {
02609 return (double)fluid_chorus_get_level(synth->chorus);
02610 }
02611
02612 double fluid_synth_get_chorus_speed_Hz(fluid_synth_t* synth)
02613 {
02614 return (double)fluid_chorus_get_speed_Hz(synth->chorus);
02615 }
02616
02617 double fluid_synth_get_chorus_depth_ms(fluid_synth_t* synth)
02618 {
02619 return (double)fluid_chorus_get_depth_ms(synth->chorus);
02620 }
02621
02622 int fluid_synth_get_chorus_type(fluid_synth_t* synth)
02623 {
02624 return fluid_chorus_get_type(synth->chorus);
02625 }
02626
02627
02628
02629 double fluid_synth_get_reverb_roomsize(fluid_synth_t* synth)
02630 {
02631 return (double)fluid_revmodel_getroomsize(synth->reverb);
02632 }
02633
02634 double fluid_synth_get_reverb_damp(fluid_synth_t* synth)
02635 {
02636 return (double) fluid_revmodel_getdamp(synth->reverb);
02637 }
02638
02639 double fluid_synth_get_reverb_level(fluid_synth_t* synth)
02640 {
02641 return (double) fluid_revmodel_getlevel(synth->reverb);
02642 }
02643
02644 double fluid_synth_get_reverb_width(fluid_synth_t* synth)
02645 {
02646 return (double) fluid_revmodel_getwidth(synth->reverb);
02647 }
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659 void fluid_synth_release_voice_on_same_note(fluid_synth_t* synth, int chan, int key){
02660 int i;
02661 fluid_voice_t* voice;
02662
02663
02664
02665
02666 for (i = 0; i < synth->polyphony; i++) {
02667 voice = synth->voice[i];
02668 if (_PLAYING(voice)
02669 && (voice->chan == chan)
02670 && (voice->key == key)
02671 && (fluid_voice_get_id(voice) != synth->noteid)) {
02672 fluid_voice_noteoff(voice);
02673 }
02674 }
02675 }
02676
02677
02678
02679
02680
02681 int fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_method){
02682 int i;
02683 for (i = 0; i < synth->midi_channels; i++) {
02684 if (synth->channel[i] == NULL){
02685 FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!");
02686 return FLUID_FAILED;
02687 };
02688 if (chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan){
02689 fluid_channel_set_interp_method(synth->channel[i], interp_method);
02690 };
02691 };
02692 return FLUID_OK;
02693 };
02694
02695
02696
02697
02698 int
02699 fluid_synth_count_midi_channels(fluid_synth_t* synth)
02700 {
02701 return synth->midi_channels;
02702 }
02703
02704
02705
02706
02707 int
02708 fluid_synth_count_audio_channels(fluid_synth_t* synth)
02709 {
02710 return synth->audio_channels;
02711 }
02712
02713
02714
02715
02716 int
02717 fluid_synth_count_audio_groups(fluid_synth_t* synth)
02718 {
02719 return synth->audio_groups;
02720 }
02721
02722
02723
02724
02725 int
02726 fluid_synth_count_effects_channels(fluid_synth_t* synth)
02727 {
02728 return synth->effects_channels;
02729 }
02730
02731 double fluid_synth_get_cpu_load(fluid_synth_t* synth)
02732 {
02733 return synth->cpu_load;
02734 }
02735
02736 static fluid_tuning_t*
02737 fluid_synth_get_tuning(fluid_synth_t* synth, int bank, int prog)
02738 {
02739 if ((bank < 0) || (bank >= 128)) {
02740 FLUID_LOG(FLUID_WARN, "Bank number out of range");
02741 return NULL;
02742 }
02743 if ((prog < 0) || (prog >= 128)) {
02744 FLUID_LOG(FLUID_WARN, "Program number out of range");
02745 return NULL;
02746 }
02747 if ((synth->tuning == NULL) ||
02748 (synth->tuning[bank] == NULL) ||
02749 (synth->tuning[bank][prog] == NULL)) {
02750 FLUID_LOG(FLUID_WARN, "No tuning at bank %d, prog %d", bank, prog);
02751 return NULL;
02752 }
02753 return synth->tuning[bank][prog];
02754 }
02755
02756 static fluid_tuning_t*
02757 fluid_synth_create_tuning(fluid_synth_t* synth, int bank, int prog, char* name)
02758 {
02759 if ((bank < 0) || (bank >= 128)) {
02760 FLUID_LOG(FLUID_WARN, "Bank number out of range");
02761 return NULL;
02762 }
02763 if ((prog < 0) || (prog >= 128)) {
02764 FLUID_LOG(FLUID_WARN, "Program number out of range");
02765 return NULL;
02766 }
02767 if (synth->tuning == NULL) {
02768 synth->tuning = FLUID_ARRAY(fluid_tuning_t**, 128);
02769 if (synth->tuning == NULL) {
02770 FLUID_LOG(FLUID_PANIC, "Out of memory");
02771 return NULL;
02772 }
02773 FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t**));
02774 }
02775
02776 if (synth->tuning[bank] == NULL) {
02777 synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t*, 128);
02778 if (synth->tuning[bank] == NULL) {
02779 FLUID_LOG(FLUID_PANIC, "Out of memory");
02780 return NULL;
02781 }
02782 FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t*));
02783 }
02784
02785 if (synth->tuning[bank][prog] == NULL) {
02786 synth->tuning[bank][prog] = new_fluid_tuning(name, bank, prog);
02787 if (synth->tuning[bank][prog] == NULL) {
02788 return NULL;
02789 }
02790 }
02791
02792 if ((fluid_tuning_get_name(synth->tuning[bank][prog]) == NULL)
02793 || (FLUID_STRCMP(fluid_tuning_get_name(synth->tuning[bank][prog]), name) != 0)) {
02794 fluid_tuning_set_name(synth->tuning[bank][prog], name);
02795 }
02796
02797 return synth->tuning[bank][prog];
02798 }
02799
02800 int fluid_synth_create_key_tuning(fluid_synth_t* synth,
02801 int bank, int prog,
02802 char* name, double* pitch)
02803 {
02804 fluid_tuning_t* tuning = fluid_synth_create_tuning(synth, bank, prog, name);
02805 if (tuning == NULL) {
02806 return FLUID_FAILED;
02807 }
02808 if (pitch) {
02809 fluid_tuning_set_all(tuning, pitch);
02810 }
02811 return FLUID_OK;
02812 }
02813
02814
02815 int fluid_synth_create_octave_tuning(fluid_synth_t* synth,
02816 int bank, int prog,
02817 char* name, double* pitch)
02818 {
02819 fluid_tuning_t* tuning = fluid_synth_create_tuning(synth, bank, prog, name);
02820 if (tuning == NULL) {
02821 return FLUID_FAILED;
02822 }
02823 fluid_tuning_set_octave(tuning, pitch);
02824 return FLUID_OK;
02825 }
02826
02827 int fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
02828 int len, int *key, double* pitch, int apply)
02829 {
02830 fluid_tuning_t* tuning = fluid_synth_get_tuning(synth, bank, prog);
02831 int i;
02832
02833 if (tuning == NULL) {
02834 return FLUID_FAILED;
02835 }
02836
02837 for (i = 0; i < len; i++) {
02838 fluid_tuning_set_pitch(tuning, key[i], pitch[i]);
02839 }
02840
02841 return FLUID_OK;
02842 }
02843
02844 int fluid_synth_select_tuning(fluid_synth_t* synth, int chan,
02845 int bank, int prog)
02846 {
02847 fluid_tuning_t* tuning = fluid_synth_get_tuning(synth, bank, prog);
02848
02849 if (tuning == NULL) {
02850 return FLUID_FAILED;
02851 }
02852 if ((chan < 0) || (chan >= synth->midi_channels)) {
02853 FLUID_LOG(FLUID_WARN, "Channel out of range");
02854 return FLUID_FAILED;
02855 }
02856
02857 fluid_channel_set_tuning(synth->channel[chan], synth->tuning[bank][prog]);
02858
02859 return FLUID_OK;
02860 }
02861
02862 int fluid_synth_reset_tuning(fluid_synth_t* synth, int chan)
02863 {
02864 if ((chan < 0) || (chan >= synth->midi_channels)) {
02865 FLUID_LOG(FLUID_WARN, "Channel out of range");
02866 return FLUID_FAILED;
02867 }
02868
02869 fluid_channel_set_tuning(synth->channel[chan], NULL);
02870
02871 return FLUID_OK;
02872 }
02873
02874 void fluid_synth_tuning_iteration_start(fluid_synth_t* synth)
02875 {
02876 synth->cur_tuning = NULL;
02877 }
02878
02879 int fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog)
02880 {
02881 int b = 0, p = 0;
02882
02883 if (synth->tuning == NULL) {
02884 return 0;
02885 }
02886
02887 if (synth->cur_tuning != NULL) {
02888
02889 b = fluid_tuning_get_bank(synth->cur_tuning);
02890 p = 1 + fluid_tuning_get_prog(synth->cur_tuning);
02891 if (p >= 128) {
02892 p = 0;
02893 b++;
02894 }
02895 }
02896
02897 while (b < 128) {
02898 if (synth->tuning[b] != NULL) {
02899 while (p < 128) {
02900 if (synth->tuning[b][p] != NULL) {
02901 synth->cur_tuning = synth->tuning[b][p];
02902 *bank = b;
02903 *prog = p;
02904 return 1;
02905 }
02906 p++;
02907 }
02908 }
02909 p = 0;
02910 b++;
02911 }
02912
02913 return 0;
02914 }
02915
02916 int fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog,
02917 char* name, int len, double* pitch)
02918 {
02919 fluid_tuning_t* tuning = fluid_synth_get_tuning(synth, bank, prog);
02920
02921 if (tuning == NULL) {
02922 return FLUID_FAILED;
02923 }
02924
02925 if (name) {
02926 snprintf(name, len - 1, "%s", fluid_tuning_get_name(tuning));
02927 name[len - 1] = 0;
02928 }
02929 if (pitch) {
02930 FLUID_MEMCPY(pitch, fluid_tuning_get_all(tuning), 128 * sizeof(double));
02931 }
02932
02933 return FLUID_OK;
02934 }
02935
02936 fluid_settings_t* fluid_synth_get_settings(fluid_synth_t* synth)
02937 {
02938 return synth->settings;
02939 }
02940
02941 int fluid_synth_setstr(fluid_synth_t* synth, char* name, char* str)
02942 {
02943 return fluid_settings_setstr(synth->settings, name, str);
02944 }
02945
02946 int fluid_synth_getstr(fluid_synth_t* synth, char* name, char** str)
02947 {
02948 return fluid_settings_getstr(synth->settings, name, str);
02949 }
02950
02951 int fluid_synth_setnum(fluid_synth_t* synth, char* name, double val)
02952 {
02953 return fluid_settings_setnum(synth->settings, name, val);
02954 }
02955
02956 int fluid_synth_getnum(fluid_synth_t* synth, char* name, double* val)
02957 {
02958 return fluid_settings_getnum(synth->settings, name, val);
02959 }
02960
02961 int fluid_synth_setint(fluid_synth_t* synth, char* name, int val)
02962 {
02963 return fluid_settings_setint(synth->settings, name, val);
02964 }
02965
02966 int fluid_synth_getint(fluid_synth_t* synth, char* name, int* val)
02967 {
02968 return fluid_settings_getint(synth->settings, name, val);
02969 }
02970
02971 int
02972 fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value)
02973 {
02974 int i;
02975 fluid_voice_t* voice;
02976
02977 if ((chan < 0) || (chan >= synth->midi_channels)) {
02978 FLUID_LOG(FLUID_WARN, "Channel out of range");
02979 return FLUID_FAILED;
02980 }
02981
02982 if ((param < 0) || (param >= GEN_LAST)) {
02983 FLUID_LOG(FLUID_WARN, "Parameter number out of range");
02984 return FLUID_FAILED;
02985 }
02986
02987 fluid_channel_set_gen(synth->channel[chan], param, value, 0);
02988
02989 for (i = 0; i < synth->polyphony; i++) {
02990 voice = synth->voice[i];
02991 if (voice->chan == chan) {
02992 fluid_voice_set_param(voice, param, value, 0);
02993 }
02994 }
02995
02996 return FLUID_OK;
02997 }
02998
03022 int
03023 fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param,
03024 float value, int absolute, int normalized)
03025 {
03026 int i;
03027 fluid_voice_t* voice;
03028 float v;
03029
03030 if ((chan < 0) || (chan >= synth->midi_channels)) {
03031 FLUID_LOG(FLUID_WARN, "Channel out of range");
03032 return FLUID_FAILED;
03033 }
03034
03035 if ((param < 0) || (param >= GEN_LAST)) {
03036 FLUID_LOG(FLUID_WARN, "Parameter number out of range");
03037 return FLUID_FAILED;
03038 }
03039
03040 v = (normalized)? fluid_gen_scale(param, value) : value;
03041
03042 fluid_channel_set_gen(synth->channel[chan], param, v, absolute);
03043
03044 for (i = 0; i < synth->polyphony; i++) {
03045 voice = synth->voice[i];
03046 if (voice->chan == chan) {
03047 fluid_voice_set_param(voice, param, v, absolute);
03048 }
03049 }
03050
03051 return FLUID_OK;
03052 }
03053
03054 float fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param)
03055 {
03056 if ((chan < 0) || (chan >= synth->midi_channels)) {
03057 FLUID_LOG(FLUID_WARN, "Channel out of range");
03058 return 0.0;
03059 }
03060
03061 if ((param < 0) || (param >= GEN_LAST)) {
03062 FLUID_LOG(FLUID_WARN, "Parameter number out of range");
03063 return 0.0;
03064 }
03065
03066 return fluid_channel_get_gen(synth->channel[chan], param);
03067 }
03068
03069
03070
03071
03072 void fluid_synth_set_midi_router(fluid_synth_t* synth, fluid_midi_router_t* router){
03073 synth->midi_router=router;
03074 };
03075
03076
03077
03078
03079
03080 int fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event)
03081 {
03082 fluid_synth_t* synth = (fluid_synth_t*) data;
03083 int type = fluid_midi_event_get_type(event);
03084 int chan = fluid_midi_event_get_channel(event);
03085
03086 switch(type) {
03087 case NOTE_ON:
03088 return fluid_synth_noteon(synth, chan,
03089 fluid_midi_event_get_key(event),
03090 fluid_midi_event_get_velocity(event));
03091
03092 case NOTE_OFF:
03093 return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event));
03094
03095 case CONTROL_CHANGE:
03096 return fluid_synth_cc(synth, chan,
03097 fluid_midi_event_get_control(event),
03098 fluid_midi_event_get_value(event));
03099
03100 case PROGRAM_CHANGE:
03101 return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event));
03102
03103 case CHANNEL_PRESSURE:
03104 return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event));
03105
03106 case PITCH_BEND:
03107 return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event));
03108
03109 case MIDI_SYSTEM_RESET:
03110 return fluid_synth_system_reset(synth);
03111 }
03112 return FLUID_FAILED;
03113 }
03114
03115
03116 int fluid_synth_start(fluid_synth_t* synth, unsigned int id, fluid_preset_t* preset,
03117 int audio_chan, int midi_chan, int key, int vel)
03118 {
03119 int r;
03120
03121
03122 if ((midi_chan < 0) || (midi_chan >= synth->midi_channels)) {
03123 FLUID_LOG(FLUID_WARN, "Channel out of range");
03124 return FLUID_FAILED;
03125 }
03126
03127 if ((key < 0) || (key >= 128)) {
03128 FLUID_LOG(FLUID_WARN, "Key out of range");
03129 return FLUID_FAILED;
03130 }
03131
03132 if ((vel <= 0) || (vel >= 128)) {
03133 FLUID_LOG(FLUID_WARN, "Velocity out of range");
03134 return FLUID_FAILED;
03135 }
03136
03137 fluid_mutex_lock(synth->busy);
03138
03139 synth->storeid = id;
03140 r = fluid_preset_noteon(preset, synth, midi_chan, key, vel);
03141
03142 fluid_mutex_unlock(synth->busy);
03143
03144 return r;
03145 }
03146
03147 int fluid_synth_stop(fluid_synth_t* synth, unsigned int id)
03148 {
03149 int i;
03150 fluid_voice_t* voice;
03151 int status = FLUID_FAILED;
03152 int count = 0;
03153
03154 for (i = 0; i < synth->polyphony; i++) {
03155
03156 voice = synth->voice[i];
03157
03158 if (_ON(voice) && (fluid_voice_get_id(voice) == id)) {
03159 count++;
03160 fluid_voice_noteoff(voice);
03161 status = FLUID_OK;
03162 }
03163 }
03164
03165 return status;
03166 }
03167
03168 fluid_bank_offset_t*
03169 fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id)
03170 {
03171 fluid_list_t* list = synth->bank_offsets;
03172 fluid_bank_offset_t* offset;
03173
03174 while (list) {
03175
03176 offset = (fluid_bank_offset_t*) fluid_list_get(list);
03177 if (offset->sfont_id == sfont_id) {
03178 return offset;
03179 }
03180
03181 list = fluid_list_next(list);
03182 }
03183
03184 return NULL;
03185 }
03186
03187 int
03188 fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset)
03189 {
03190 fluid_bank_offset_t* bank_offset;
03191
03192 bank_offset = fluid_synth_get_bank_offset0(synth, sfont_id);
03193
03194 if (bank_offset == NULL) {
03195 bank_offset = FLUID_NEW(fluid_bank_offset_t);
03196 if (bank_offset == NULL) {
03197 return -1;
03198 }
03199 bank_offset->sfont_id = sfont_id;
03200 bank_offset->offset = offset;
03201 synth->bank_offsets = fluid_list_prepend(synth->bank_offsets, bank_offset);
03202 } else {
03203 bank_offset->offset = offset;
03204 }
03205
03206 return 0;
03207 }
03208
03209 int
03210 fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id)
03211 {
03212 fluid_bank_offset_t* bank_offset;
03213
03214 bank_offset = fluid_synth_get_bank_offset0(synth, sfont_id);
03215 return (bank_offset == NULL)? 0 : bank_offset->offset;
03216 }
03217
03218 void
03219 fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id)
03220 {
03221 fluid_bank_offset_t* bank_offset;
03222
03223 bank_offset = fluid_synth_get_bank_offset0(synth, sfont_id);
03224 if (bank_offset != NULL) {
03225 synth->bank_offsets = fluid_list_remove(synth->bank_offsets, bank_offset);
03226 }
03227 }