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 

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