1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public License
7  * as published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 #include "fluid_mod.h"
22 #include "fluid_chan.h"
23 #include "fluid_voice.h"
24 
25 /*
26  * fluid_mod_clone
27  */
28 void
fluid_mod_clone(fluid_mod_t * mod,fluid_mod_t * src)29 fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
30 {
31   mod->dest = src->dest;
32   mod->src1 = src->src1;
33   mod->flags1 = src->flags1;
34   mod->src2 = src->src2;
35   mod->flags2 = src->flags2;
36   mod->amount = src->amount;
37 }
38 
39 /**
40  * Set a modulator's primary source controller and flags.
41  * @param mod Modulator
42  * @param src Modulator source (#fluid_mod_src or a MIDI controller number)
43  * @param flags Flags determining mapping function and whether the source
44  *   controller is a general controller (#FLUID_MOD_GC) or a MIDI CC controller
45  *   (#FLUID_MOD_CC), see #fluid_mod_flags.
46  */
47 void
fluid_mod_set_source1(fluid_mod_t * mod,int src,int flags)48 fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
49 {
50   mod->src1 = src;
51   mod->flags1 = flags;
52 }
53 
54 /**
55  * Set a modulator's secondary source controller and flags.
56  * @param mod Modulator
57  * @param src Modulator source (#fluid_mod_src or a MIDI controller number)
58  * @param flags Flags determining mapping function and whether the source
59  *   controller is a general controller (#FLUID_MOD_GC) or a MIDI CC controller
60  *   (#FLUID_MOD_CC), see #fluid_mod_flags.
61  */
62 void
fluid_mod_set_source2(fluid_mod_t * mod,int src,int flags)63 fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
64 {
65   mod->src2 = src;
66   mod->flags2 = flags;
67 }
68 
69 /**
70  * Set the destination effect of a modulator.
71  * @param mod Modulator
72  * @param dest Destination generator (#fluid_gen_type)
73  */
74 void
fluid_mod_set_dest(fluid_mod_t * mod,int dest)75 fluid_mod_set_dest(fluid_mod_t* mod, int dest)
76 {
77   mod->dest = dest;
78 }
79 
80 /**
81  * Set the scale amount of a modulator.
82  * @param mod Modulator
83  * @param amount Scale amount to assign
84  */
85 void
fluid_mod_set_amount(fluid_mod_t * mod,double amount)86 fluid_mod_set_amount(fluid_mod_t* mod, double amount)
87 {
88   mod->amount = (double) amount;
89 }
90 
91 /**
92  * Get the primary source value from a modulator.
93  * @param mod Modulator
94  * @return The primary source value (#fluid_mod_src or a MIDI CC controller value).
95  */
96 int
fluid_mod_get_source1(fluid_mod_t * mod)97 fluid_mod_get_source1(fluid_mod_t* mod)
98 {
99   return mod->src1;
100 }
101 
102 /**
103  * Get primary source flags from a modulator.
104  * @param mod Modulator
105  * @return The primary source flags (#fluid_mod_flags).
106  */
107 int
fluid_mod_get_flags1(fluid_mod_t * mod)108 fluid_mod_get_flags1(fluid_mod_t* mod)
109 {
110   return mod->flags1;
111 }
112 
113 /**
114  * Get the secondary source value from a modulator.
115  * @param mod Modulator
116  * @return The secondary source value (#fluid_mod_src or a MIDI CC controller value).
117  */
118 int
fluid_mod_get_source2(fluid_mod_t * mod)119 fluid_mod_get_source2(fluid_mod_t* mod)
120 {
121   return mod->src2;
122 }
123 
124 /**
125  * Get secondary source flags from a modulator.
126  * @param mod Modulator
127  * @return The secondary source flags (#fluid_mod_flags).
128  */
129 int
fluid_mod_get_flags2(fluid_mod_t * mod)130 fluid_mod_get_flags2(fluid_mod_t* mod)
131 {
132   return mod->flags2;
133 }
134 
135 /**
136  * Get destination effect from a modulator.
137  * @param mod Modulator
138  * @return Destination generator (#fluid_gen_type)
139  */
140 int
fluid_mod_get_dest(fluid_mod_t * mod)141 fluid_mod_get_dest(fluid_mod_t* mod)
142 {
143   return mod->dest;
144 }
145 
146 /**
147  * Get the scale amount from a modulator.
148  * @param mod Modulator
149  * @return Scale amount
150  */
151 double
fluid_mod_get_amount(fluid_mod_t * mod)152 fluid_mod_get_amount(fluid_mod_t* mod)
153 {
154   return (fluid_real_t) mod->amount;
155 }
156 
157 
158 /*
159  * fluid_mod_get_value
160  */
161 fluid_real_t
fluid_mod_get_value(fluid_mod_t * mod,fluid_channel_t * chan,fluid_voice_t * voice)162 fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
163 {
164   fluid_real_t v1 = 0.0, v2 = 1.0;
165   fluid_real_t range1 = 127.0, range2 = 127.0;
166 
167   if (chan == NULL) {
168     return 0.0f;
169   }
170 
171   /* 'special treatment' for default controller
172    *
173    *  Reference: SF2.01 section 8.4.2
174    *
175    * The GM default controller 'vel-to-filter cut off' is not clearly
176    * defined: If implemented according to the specs, the filter
177    * frequency jumps between vel=63 and vel=64.  To maintain
178    * compatibility with existing sound fonts, the implementation is
179    * 'hardcoded', it is impossible to implement using only one
180    * modulator otherwise.
181    *
182    * I assume here, that the 'intention' of the paragraph is one
183    * octave (1200 cents) filter frequency shift between vel=127 and
184    * vel=64.  'amount' is (-2400), at least as long as the controller
185    * is set to default.
186    *
187    * Further, the 'appearance' of the modulator (source enumerator,
188    * destination enumerator, flags etc) is different from that
189    * described in section 8.4.2, but it matches the definition used in
190    * several SF2.1 sound fonts (where it is used only to turn it off).
191    * */
192   if ((mod->src2 == FLUID_MOD_VELOCITY) &&
193       (mod->src1 == FLUID_MOD_VELOCITY) &&
194       (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
195 		       | FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
196       (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
197 		       | FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
198       (mod->dest == GEN_FILTERFC)) {
199 // S. Christian Collins' mod, to stop forcing velocity based filtering
200 /*
201     if (voice->vel < 64){
202       return (fluid_real_t) mod->amount / 2.0;
203     } else {
204       return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
205     }
206 */
207      return 0; // (fluid_real_t) mod->amount / 2.0;
208   }
209 // end S. Christian Collins' mod
210 
211   /* get the initial value of the first source */
212   if (mod->src1 > 0) {
213     if (mod->flags1 & FLUID_MOD_CC) {
214       v1 = fluid_channel_get_cc(chan, mod->src1);
215     } else {  /* source 1 is one of the direct controllers */
216       switch (mod->src1) {
217       case FLUID_MOD_NONE:         /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
218 	v1 = range1;
219 	break;
220       case FLUID_MOD_VELOCITY:
221 	v1 = voice->vel;
222 	break;
223       case FLUID_MOD_KEY:
224 	v1 = voice->key;
225 	break;
226       case FLUID_MOD_KEYPRESSURE:
227 	v1 = fluid_channel_get_key_pressure (chan);
228 	break;
229       case FLUID_MOD_CHANNELPRESSURE:
230 	v1 = fluid_channel_get_channel_pressure (chan);
231 	break;
232       case FLUID_MOD_PITCHWHEEL:
233 	v1 = fluid_channel_get_pitch_bend (chan);
234 	range1 = 0x4000;
235 	break;
236       case FLUID_MOD_PITCHWHEELSENS:
237 	v1 = fluid_channel_get_pitch_wheel_sensitivity (chan);
238 	break;
239       default:
240 	v1 = 0.0;
241       }
242     }
243 
244     /* transform the input value */
245     switch (mod->flags1 & 0x0f) {
246     case 0: /* linear, unipolar, positive */
247       v1 /= range1;
248       break;
249     case 1: /* linear, unipolar, negative */
250       v1 = 1.0f - v1 / range1;
251       break;
252     case 2: /* linear, bipolar, positive */
253       v1 = -1.0f + 2.0f * v1 / range1;
254       break;
255     case 3: /* linear, bipolar, negative */
256       v1 = 1.0f - 2.0f * v1 / range1;
257       break;
258     case 4: /* concave, unipolar, positive */
259       v1 = fluid_concave(v1);
260       break;
261     case 5: /* concave, unipolar, negative */
262       v1 = fluid_concave(127 - v1);
263       break;
264     case 6: /* concave, bipolar, positive */
265       v1 = (v1 > 64)? fluid_concave(2 * (v1 - 64)) : -fluid_concave(2 * (64 - v1));
266       break;
267     case 7: /* concave, bipolar, negative */
268       v1 = (v1 > 64)? -fluid_concave(2 * (v1 - 64)) : fluid_concave(2 * (64 - v1));
269       break;
270     case 8: /* convex, unipolar, positive */
271       v1 = fluid_convex(v1);
272       break;
273     case 9: /* convex, unipolar, negative */
274       v1 = fluid_convex(127 - v1);
275       break;
276     case 10: /* convex, bipolar, positive */
277       v1 = (v1 > 64)? fluid_convex(2 * (v1 - 64)) : -fluid_convex(2 * (64 - v1));
278       break;
279     case 11: /* convex, bipolar, negative */
280       v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
281       break;
282     case 12: /* switch, unipolar, positive */
283       v1 = (v1 >= 64)? 1.0f : 0.0f;
284       break;
285     case 13: /* switch, unipolar, negative */
286       v1 = (v1 >= 64)? 0.0f : 1.0f;
287       break;
288     case 14: /* switch, bipolar, positive */
289       v1 = (v1 >= 64)? 1.0f : -1.0f;
290       break;
291     case 15: /* switch, bipolar, negative */
292       v1 = (v1 >= 64)? -1.0f : 1.0f;
293       break;
294     }
295   } else {
296     return 0.0;
297   }
298 
299   /* no need to go further */
300   if (v1 == 0.0f) {
301     return 0.0f;
302   }
303 
304   /* get the second input source */
305   if (mod->src2 > 0) {
306     if (mod->flags2 & FLUID_MOD_CC) {
307       v2 = fluid_channel_get_cc(chan, mod->src2);
308     } else {
309       switch (mod->src2) {
310       case FLUID_MOD_NONE:         /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
311 	v2 = range2;
312 	break;
313       case FLUID_MOD_VELOCITY:
314 	v2 = voice->vel;
315 	break;
316       case FLUID_MOD_KEY:
317 	v2 = voice->key;
318 	break;
319       case FLUID_MOD_KEYPRESSURE:
320 	v2 = fluid_channel_get_key_pressure (chan);
321 	break;
322       case FLUID_MOD_CHANNELPRESSURE:
323 	v2 = fluid_channel_get_channel_pressure (chan);
324 	break;
325       case FLUID_MOD_PITCHWHEEL:
326 	v2 = fluid_channel_get_pitch_bend (chan);
327 	break;
328       case FLUID_MOD_PITCHWHEELSENS:
329 	v2 = fluid_channel_get_pitch_wheel_sensitivity (chan);
330 	break;
331       default:
332 	v1 = 0.0f;
333       }
334     }
335 
336     /* transform the second input value */
337     switch (mod->flags2 & 0x0f) {
338     case 0: /* linear, unipolar, positive */
339       v2 /= range2;
340       break;
341     case 1: /* linear, unipolar, negative */
342       v2 = 1.0f - v2 / range2;
343       break;
344     case 2: /* linear, bipolar, positive */
345       v2 = -1.0f + 2.0f * v2 / range2;
346       break;
347     case 3: /* linear, bipolar, negative */
348       v2 = -1.0f + 2.0f * v2 / range2;
349       break;
350     case 4: /* concave, unipolar, positive */
351       v2 = fluid_concave(v2);
352       break;
353     case 5: /* concave, unipolar, negative */
354       v2 = fluid_concave(127 - v2);
355       break;
356     case 6: /* concave, bipolar, positive */
357       v2 = (v2 > 64)? fluid_concave(2 * (v2 - 64)) : -fluid_concave(2 * (64 - v2));
358       break;
359     case 7: /* concave, bipolar, negative */
360       v2 = (v2 > 64)? -fluid_concave(2 * (v2 - 64)) : fluid_concave(2 * (64 - v2));
361       break;
362     case 8: /* convex, unipolar, positive */
363       v2 = fluid_convex(v2);
364       break;
365     case 9: /* convex, unipolar, negative */
366       v2 = 1.0f - fluid_convex(v2);
367       break;
368     case 10: /* convex, bipolar, positive */
369       v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
370       break;
371     case 11: /* convex, bipolar, negative */
372       v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
373       break;
374     case 12: /* switch, unipolar, positive */
375       v2 = (v2 >= 64)? 1.0f : 0.0f;
376       break;
377     case 13: /* switch, unipolar, negative */
378       v2 = (v2 >= 64)? 0.0f : 1.0f;
379       break;
380     case 14: /* switch, bipolar, positive */
381       v2 = (v2 >= 64)? 1.0f : -1.0f;
382       break;
383     case 15: /* switch, bipolar, negative */
384       v2 = (v2 >= 64)? -1.0f : 1.0f;
385       break;
386     }
387   } else {
388     v2 = 1.0f;
389   }
390 
391   /* it's as simple as that: */
392   return (fluid_real_t) mod->amount * v1 * v2;
393 }
394 
395 /**
396  * Create a new uninitialized modulator structure.
397  * @return New allocated modulator or NULL if out of memory
398  */
399 fluid_mod_t*
fluid_mod_new()400 fluid_mod_new()
401 {
402   fluid_mod_t* mod = FLUID_NEW (fluid_mod_t);
403   if (mod == NULL) {
404     FLUID_LOG(FLUID_ERR, "Out of memory");
405     return NULL;
406   }
407   return mod;
408 }
409 
410 /**
411  * Free a modulator structure.
412  * @param mod Modulator to free
413  */
414 void
fluid_mod_delete(fluid_mod_t * mod)415 fluid_mod_delete (fluid_mod_t *mod)
416 {
417   FLUID_FREE(mod);
418 }
419 
420 /**
421  * Checks if two modulators are identical in sources, flags and destination.
422  * @param mod1 First modulator
423  * @param mod2 Second modulator
424  * @return TRUE if identical, FALSE otherwise
425  *
426  * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
427  */
428 int
fluid_mod_test_identity(fluid_mod_t * mod1,fluid_mod_t * mod2)429 fluid_mod_test_identity (fluid_mod_t *mod1, fluid_mod_t *mod2)
430 {
431   return mod1->dest == mod2->dest
432     && mod1->src1 == mod2->src1
433     && mod1->src2 == mod2->src2
434     && mod1->flags1 == mod2->flags1
435     && mod1->flags2 == mod2->flags2;
436 }
437 
438 /* debug function: Prints the contents of a modulator */
fluid_dump_modulator(fluid_mod_t * mod)439 void fluid_dump_modulator(fluid_mod_t * mod){
440   int src1=mod->src1;
441   int dest=mod->dest;
442   int src2=mod->src2;
443   int flags1=mod->flags1;
444   int flags2=mod->flags2;
445   fluid_real_t amount=(fluid_real_t)mod->amount;
446 
447   printf("Src: ");
448   if (flags1 & FLUID_MOD_CC){
449     printf("MIDI CC=%i",src1);
450   } else {
451     switch(src1){
452 	case FLUID_MOD_NONE:
453 	  printf("None"); break;
454 	case FLUID_MOD_VELOCITY:
455 	  printf("note-on velocity"); break;
456 	case FLUID_MOD_KEY:
457 	  printf("Key nr"); break;
458 	  case FLUID_MOD_KEYPRESSURE:
459 	    printf("Poly pressure"); break;
460 	case FLUID_MOD_CHANNELPRESSURE:
461 	  printf("Chan pressure"); break;
462 	case FLUID_MOD_PITCHWHEEL:
463 	  printf("Pitch Wheel"); break;
464 	case FLUID_MOD_PITCHWHEELSENS:
465 	  printf("Pitch Wheel sens"); break;
466 	default:
467 	  printf("(unknown: %i)", src1);
468     }; /* switch src1 */
469   }; /* if not CC */
470   if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
471   if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
472   printf("-> ");
473   switch(dest){
474       case GEN_FILTERQ: printf("Q"); break;
475       case GEN_FILTERFC: printf("fc"); break;
476       case GEN_VIBLFOTOPITCH: printf("VibLFO-to-pitch"); break;
477       case GEN_MODENVTOPITCH: printf("ModEnv-to-pitch"); break;
478       case GEN_MODLFOTOPITCH: printf("ModLFO-to-pitch"); break;
479       case GEN_CHORUSSEND: printf("Chorus send"); break;
480       case GEN_REVERBSEND: printf("Reverb send"); break;
481       case GEN_PAN: printf("pan"); break;
482       case GEN_ATTENUATION: printf("att"); break;
483       default: printf("dest %i",dest);
484   }; /* switch dest */
485   printf(", amount %f flags %i src2 %i flags2 %i\n",amount, flags1, src2, flags2);
486 };
487 
488 
489