# src/fluid_mod.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 "fluid_mod.h"
    00022 #include "fluid_chan.h"
    00023 #include "fluid_voice.h"
    00024
    00025 /*
    00026  * fluid_mod_clone
    00027  */
    00028 void
    00029 fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
    00030 {
    00031   mod->dest = src->dest;
    00032   mod->src1 = src->src1;
    00033   mod->flags1 = src->flags1;
    00034   mod->src2 = src->src2;
    00035   mod->flags2 = src->flags2;
    00036   mod->amount = src->amount;
    00037 }
    00038
    00039 /*
    00040  * fluid_mod_set_source1
    00041  */
    00042 void
    00043 fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
    00044 {
    00045   mod->src1 = src;
    00046   mod->flags1 = flags;
    00047 }
    00048
    00049 /*
    00050  * fluid_mod_set_source2
    00051  */
    00052 void
    00053 fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
    00054 {
    00055   mod->src2 = src;
    00056   mod->flags2 = flags;
    00057 }
    00058
    00059 /*
    00060  * fluid_mod_set_dest
    00061  */
    00062 void
    00063 fluid_mod_set_dest(fluid_mod_t* mod, int dest)
    00064 {
    00065   mod->dest = dest;
    00066 }
    00067
    00068 /*
    00069  * fluid_mod_set_amount
    00070  */
    00071 void
    00072 fluid_mod_set_amount(fluid_mod_t* mod, double amount)
    00073 {
    00074   mod->amount = (double) amount;
    00075 }
    00076
    00077 int fluid_mod_get_source1(fluid_mod_t* mod)
    00078 {
    00079   return mod->src1;
    00080 }
    00081
    00082 int fluid_mod_get_flags1(fluid_mod_t* mod)
    00083 {
    00084   return mod->flags1;
    00085 }
    00086
    00087 int fluid_mod_get_source2(fluid_mod_t* mod)
    00088 {
    00089   return mod->src2;
    00090 }
    00091
    00092 int fluid_mod_get_flags2(fluid_mod_t* mod)
    00093 {
    00094   return mod->flags2;
    00095 }
    00096
    00097 int fluid_mod_get_dest(fluid_mod_t* mod)
    00098 {
    00099   return mod->dest;
    00100 }
    00101
    00102 double fluid_mod_get_amount(fluid_mod_t* mod)
    00103 {
    00104   return (fluid_real_t) mod->amount;
    00105 }
    00106
    00107
    00108 /*
    00109  * fluid_mod_get_value
    00110  */
    00111 fluid_real_t
    00112 fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
    00113 {
    00114   fluid_real_t v1 = 0.0, v2 = 1.0;
    00115   fluid_real_t range1 = 127.0, range2 = 127.0;
    00116
    00117   if (chan == NULL) {
    00118     return 0.0f;
    00119   }
    00120
    00121   /* 'special treatment' for default controller
    00122    *
    00123    *  Reference: SF2.01 section 8.4.2
    00124    *
    00125    * The GM default controller 'vel-to-filter cut off' is not clearly
    00126    * defined: If implemented according to the specs, the filter
    00127    * frequency jumps between vel=63 and vel=64.  To maintain
    00128    * compatibility with existing sound fonts, the implementation is
    00129    * 'hardcoded', it is impossible to implement using only one
    00130    * modulator otherwise.
    00131    *
    00132    * I assume here, that the 'intention' of the paragraph is one
    00133    * octave (1200 cents) filter frequency shift between vel=127 and
    00134    * vel=64.  'amount' is (-2400), at least as long as the controller
    00135    * is set to default.
    00136    *
    00137    * Further, the 'appearance' of the modulator (source enumerator,
    00138    * destination enumerator, flags etc) is different from that
    00139    * described in section 8.4.2, but it matches the definition used in
    00140    * several SF2.1 sound fonts (where it is used only to turn it off).
    00141    * */
    00142   if ((mod->src2 == FLUID_MOD_VELOCITY) &&
    00143       (mod->src1 == FLUID_MOD_VELOCITY) &&
    00144       (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
    00145                        | FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
    00146       (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
    00147                        | FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
    00148       (mod->dest == GEN_FILTERFC)) {
    00149     if (voice->vel < 64){
    00150       return (fluid_real_t) mod->amount / 2.0;
    00151     } else {
    00152       return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
    00153     }
    00154   }
    00155
    00156   /* get the initial value of the first source */
    00157   if (mod->src1 > 0) {
    00158     if (mod->flags1 & FLUID_MOD_CC) {
    00159       v1 = fluid_channel_get_cc(chan, mod->src1);
    00160     } else {  /* source 1 is one of the direct controllers */
    00161       switch (mod->src1) {
    00162       case FLUID_MOD_NONE:         /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
    00163         v1 = range1;
    00164         break;
    00165       case FLUID_MOD_VELOCITY:
    00166         v1 = voice->vel;
    00167         break;
    00168       case FLUID_MOD_KEY:
    00169         v1 = voice->key;
    00170         break;
    00171       case FLUID_MOD_KEYPRESSURE:
    00172         v1 = chan->key_pressure;
    00173         break;
    00174       case FLUID_MOD_CHANNELPRESSURE:
    00175         v1 = chan->channel_pressure;
    00176         break;
    00177       case FLUID_MOD_PITCHWHEEL:
    00178         v1 = chan->pitch_bend;
    00179         range1 = 0x4000;
    00180         break;
    00181       case FLUID_MOD_PITCHWHEELSENS:
    00182         v1 = chan->pitch_wheel_sensitivity;
    00183         break;
    00184       default:
    00185         v1 = 0.0;
    00186       }
    00187     }
    00188
    00189     /* transform the input value */
    00190     switch (mod->flags1 & 0x0f) {
    00191     case 0: /* linear, unipolar, positive */
    00192       v1 /= range1;
    00193       break;
    00194     case 1: /* linear, unipolar, negative */
    00195       v1 = 1.0f - v1 / range1;
    00196       break;
    00197     case 2: /* linear, bipolar, positive */
    00198       v1 = -1.0f + 2.0f * v1 / range1;
    00199       break;
    00200     case 3: /* linear, bipolar, negative */
    00201       v1 = -1.0f + 2.0f * v1 / range1;
    00202       break;
    00203     case 4: /* concave, unipolar, positive */
    00204       v1 = fluid_concave(v1);
    00205       break;
    00206     case 5: /* concave, unipolar, negative */
    00207       v1 = fluid_concave(127 - v1);
    00208       break;
    00209     case 6: /* concave, bipolar, positive */
    00210       v1 = (v1 > 64)? fluid_concave(2 * (v1 - 64)) : -fluid_concave(2 * (64 - v1));
    00211       break;
    00212     case 7: /* concave, bipolar, negative */
    00213       v1 = (v1 > 64)? -fluid_concave(2 * (v1 - 64)) : fluid_concave(2 * (64 - v1));
    00214       break;
    00215     case 8: /* convex, unipolar, positive */
    00216       v1 = fluid_convex(v1);
    00217       break;
    00218     case 9: /* convex, unipolar, negative */
    00219       v1 = fluid_convex(127 - v1);
    00220       break;
    00221     case 10: /* convex, bipolar, positive */
    00222       v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
    00223       break;
    00224     case 11: /* convex, bipolar, negative */
    00225       v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
    00226       break;
    00227     case 12: /* switch, unipolar, positive */
    00228       v1 = (v1 >= 64)? 1.0f : 0.0f;
    00229       break;
    00230     case 13: /* switch, unipolar, negative */
    00231       v1 = (v1 >= 64)? 0.0f : 1.0f;
    00232       break;
    00233     case 14: /* switch, bipolar, positive */
    00234       v1 = (v1 >= 64)? 1.0f : -1.0f;
    00235       break;
    00236     case 15: /* switch, bipolar, negative */
    00237       v1 = (v1 >= 64)? -1.0f : 1.0f;
    00238       break;
    00239     }
    00240   } else {
    00241     return 0.0;
    00242   }
    00243
    00244   /* no need to go further */
    00245   if (v1 == 0.0f) {
    00246     return 0.0f;
    00247   }
    00248
    00249   /* get the second input source */
    00250   if (mod->src2 > 0) {
    00251     if (mod->flags2 & FLUID_MOD_CC) {
    00252       v2 = fluid_channel_get_cc(chan, mod->src2);
    00253     } else {
    00254       switch (mod->src2) {
    00255       case FLUID_MOD_NONE:         /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
    00256         v2 = range2;
    00257         break;
    00258       case FLUID_MOD_VELOCITY:
    00259         v2 = voice->vel;
    00260         break;
    00261       case FLUID_MOD_KEY:
    00262         v2 = voice->key;
    00263         break;
    00264       case FLUID_MOD_KEYPRESSURE:
    00265         v2 = chan->key_pressure;
    00266         break;
    00267       case FLUID_MOD_CHANNELPRESSURE:
    00268         v2 = chan->channel_pressure;
    00269         break;
    00270       case FLUID_MOD_PITCHWHEEL:
    00271         v2 = chan->pitch_bend;
    00272         break;
    00273       case FLUID_MOD_PITCHWHEELSENS:
    00274         v2 = chan->pitch_wheel_sensitivity;
    00275         break;
    00276       default:
    00277         v1 = 0.0f;
    00278       }
    00279     }
    00280
    00281     /* transform the second input value */
    00282     switch (mod->flags2 & 0x0f) {
    00283     case 0: /* linear, unipolar, positive */
    00284       v2 /= range2;
    00285       break;
    00286     case 1: /* linear, unipolar, negative */
    00287       v2 = 1.0f - v2 / range2;
    00288       break;
    00289     case 2: /* linear, bipolar, positive */
    00290       v2 = -1.0f + 2.0f * v2 / range2;
    00291       break;
    00292     case 3: /* linear, bipolar, negative */
    00293       v2 = -1.0f + 2.0f * v2 / range2;
    00294       break;
    00295     case 4: /* concave, unipolar, positive */
    00296       v2 = fluid_concave(v2);
    00297       break;
    00298     case 5: /* concave, unipolar, negative */
    00299       v2 = fluid_concave(127 - v2);
    00300       break;
    00301     case 6: /* concave, bipolar, positive */
    00302       v2 = (v2 > 64)? fluid_concave(2 * (v2 - 64)) : -fluid_concave(2 * (64 - v2));
    00303       break;
    00304     case 7: /* concave, bipolar, negative */
    00305       v2 = (v2 > 64)? -fluid_concave(2 * (v2 - 64)) : fluid_concave(2 * (64 - v2));
    00306       break;
    00307     case 8: /* convex, unipolar, positive */
    00308       v2 = fluid_convex(v2);
    00309       break;
    00310     case 9: /* convex, unipolar, negative */
    00311       v2 = 1.0f - fluid_convex(v2);
    00312       break;
    00313     case 10: /* convex, bipolar, positive */
    00314       v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
    00315       break;
    00316     case 11: /* convex, bipolar, negative */
    00317       v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
    00318       break;
    00319     case 12: /* switch, unipolar, positive */
    00320       v2 = (v2 >= 64)? 1.0f : 0.0f;
    00321       break;
    00322     case 13: /* switch, unipolar, negative */
    00323       v2 = (v2 >= 64)? 0.0f : 1.0f;
    00324       break;
    00325     case 14: /* switch, bipolar, positive */
    00326       v2 = (v2 >= 64)? 1.0f : -1.0f;
    00327       break;
    00328     case 15: /* switch, bipolar, negative */
    00329       v2 = (v2 >= 64)? -1.0f : 1.0f;
    00330       break;
    00331     }
    00332   } else {
    00333     v2 = 1.0f;
    00334   }
    00335
    00336   /* it's as simple as that: */
    00337   return (fluid_real_t) mod->amount * v1 * v2;
    00338 }
    00339
    00340 /*
    00341  * fluid_mod_new
    00342  */
    00343 fluid_mod_t*
    00344 fluid_mod_new()
    00345 {
    00346   fluid_mod_t* mod = FLUID_NEW(fluid_mod_t);
    00347   if (mod == NULL) {
    00348     FLUID_LOG(FLUID_ERR, "Out of memory");
    00349     return NULL;
    00350   }
    00351   return mod;
    00352 };
    00353
    00354 /*
    00355  * fluid_mod_delete
    00356  */
    00357 void
    00358 fluid_mod_delete(fluid_mod_t * mod)
    00359 {
    00360   FLUID_FREE(mod);
    00361 };
    00362
    00363 /*
    00364  * fluid_mod_test_identity
    00365  */
    00366 /* Purpose:
    00367  * Checks, if two modulators are identical.
    00368  *  SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
    00369  */
    00370 int fluid_mod_test_identity(fluid_mod_t * mod1, fluid_mod_t * mod2){
    00371   if (mod1->dest != mod2->dest){return 0;};
    00372   if (mod1->src1 != mod2->src1){return 0;};
    00373   if (mod1->src2 != mod2->src2){return 0;};
    00374   if (mod1->flags1 != mod2->flags1){return 0;}
    00375   if (mod1->flags2 != mod2->flags2){return 0;}
    00376   return 1;
    00377 };
    00378
    00379 /* debug function: Prints the contents of a modulator */
    00380 void fluid_dump_modulator(fluid_mod_t * mod){
    00381   int src1=mod->src1;
    00382   int dest=mod->dest;
    00383   int src2=mod->src2;
    00384   int flags1=mod->flags1;
    00385   int flags2=mod->flags2;
    00386   fluid_real_t amount=(fluid_real_t)mod->amount;
    00387
    00388   printf("Src: ");
    00389   if (flags1 & FLUID_MOD_CC){
    00390     printf("MIDI CC=%i",src1);
    00391   } else {
    00392     switch(src1){
    00393         case FLUID_MOD_NONE:
    00394           printf("None"); break;
    00395         case FLUID_MOD_VELOCITY:
    00396           printf("note-on velocity"); break;
    00397         case FLUID_MOD_KEY:
    00398           printf("Key nr"); break;
    00399           case FLUID_MOD_KEYPRESSURE:
    00400             printf("Poly pressure"); break;
    00401         case FLUID_MOD_CHANNELPRESSURE:
    00402           printf("Chan pressure"); break;
    00403         case FLUID_MOD_PITCHWHEEL:
    00404           printf("Pitch Wheel"); break;
    00405         case FLUID_MOD_PITCHWHEELSENS:
    00406           printf("Pitch Wheel sens"); break;
    00407         default:
    00408           printf("(unknown: %i)", src1);
    00409     }; /* switch src1 */
    00410   }; /* if not CC */
    00411   if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
    00412   if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
    00413   printf("-> ");
    00414   switch(dest){
    00415       case GEN_FILTERQ: printf("Q"); break;
    00416       case GEN_FILTERFC: printf("fc"); break;
    00417       case GEN_VIBLFOTOPITCH: printf("VibLFO-to-pitch"); break;
    00418       case GEN_MODENVTOPITCH: printf("ModEnv-to-pitch"); break;
    00419       case GEN_MODLFOTOPITCH: printf("ModLFO-to-pitch"); break;
    00420       case GEN_CHORUSSEND: printf("Chorus send"); break;
    00421       case GEN_REVERBSEND: printf("Reverb send"); break;
    00422       case GEN_PAN: printf("pan"); break;
    00423       case GEN_ATTENUATION: printf("att"); break;
    00424       default: printf("dest %i",dest);
    00425   }; /* switch dest */
    00426   printf(", amount %f flags %i src2 %i flags2 %i\n",amount, flags1, src2, flags2);
    00427 };
    00428
    00429