src/fluid_synth.c

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

Generated on Sat Nov 17 13:40:23 2007 for libfluidsynth by  doxygen 1.5.3