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 Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 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  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser 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  * Clone the modulators destination, sources, flags and amount.
27  * @param mod the modulator to store the copy to
28  * @param src the source modulator to retrieve the information from
29  * @note The \c next member of \c mod will be left unchanged.
30  */
31 void
fluid_mod_clone(fluid_mod_t * mod,const fluid_mod_t * src)32 fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src)
33 {
34     mod->dest = src->dest;
35     mod->src1 = src->src1;
36     mod->flags1 = src->flags1;
37     mod->src2 = src->src2;
38     mod->flags2 = src->flags2;
39     mod->amount = src->amount;
40 }
41 
42 /**
43  * Set a modulator's primary source controller and flags.
44  * @param mod The modulator instance
45  * @param src Modulator source (#fluid_mod_src or a MIDI controller number)
46  * @param flags Flags determining mapping function and whether the source
47  *   controller is a general controller (#FLUID_MOD_GC) or a MIDI CC controller
48  *   (#FLUID_MOD_CC), see #fluid_mod_flags.
49  */
50 void
fluid_mod_set_source1(fluid_mod_t * mod,int src,int flags)51 fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags)
52 {
53     mod->src1 = src;
54     mod->flags1 = flags;
55 }
56 
57 /**
58  * Set a modulator's secondary source controller and flags.
59  * @param mod The modulator instance
60  * @param src Modulator source (#fluid_mod_src or a MIDI controller number)
61  * @param flags Flags determining mapping function and whether the source
62  *   controller is a general controller (#FLUID_MOD_GC) or a MIDI CC controller
63  *   (#FLUID_MOD_CC), see #fluid_mod_flags.
64  */
65 void
fluid_mod_set_source2(fluid_mod_t * mod,int src,int flags)66 fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags)
67 {
68     mod->src2 = src;
69     mod->flags2 = flags;
70 }
71 
72 /**
73  * Set the destination effect of a modulator.
74  * @param mod The modulator instance
75  * @param dest Destination generator (#fluid_gen_type)
76  */
77 void
fluid_mod_set_dest(fluid_mod_t * mod,int dest)78 fluid_mod_set_dest(fluid_mod_t *mod, int dest)
79 {
80     mod->dest = dest;
81 }
82 
83 /**
84  * Set the scale amount of a modulator.
85  * @param mod The modulator instance
86  * @param amount Scale amount to assign
87  */
88 void
fluid_mod_set_amount(fluid_mod_t * mod,double amount)89 fluid_mod_set_amount(fluid_mod_t *mod, double amount)
90 {
91     mod->amount = (double) amount;
92 }
93 
94 /**
95  * Get the primary source value from a modulator.
96  * @param mod The modulator instance
97  * @return The primary source value (#fluid_mod_src or a MIDI CC controller value).
98  */
99 int
fluid_mod_get_source1(const fluid_mod_t * mod)100 fluid_mod_get_source1(const fluid_mod_t *mod)
101 {
102     return mod->src1;
103 }
104 
105 /**
106  * Get primary source flags from a modulator.
107  * @param mod The modulator instance
108  * @return The primary source flags (#fluid_mod_flags).
109  */
110 int
fluid_mod_get_flags1(const fluid_mod_t * mod)111 fluid_mod_get_flags1(const fluid_mod_t *mod)
112 {
113     return mod->flags1;
114 }
115 
116 /**
117  * Get the secondary source value from a modulator.
118  * @param mod The modulator instance
119  * @return The secondary source value (#fluid_mod_src or a MIDI CC controller value).
120  */
121 int
fluid_mod_get_source2(const fluid_mod_t * mod)122 fluid_mod_get_source2(const fluid_mod_t *mod)
123 {
124     return mod->src2;
125 }
126 
127 /**
128  * Get secondary source flags from a modulator.
129  * @param mod The modulator instance
130  * @return The secondary source flags (#fluid_mod_flags).
131  */
132 int
fluid_mod_get_flags2(const fluid_mod_t * mod)133 fluid_mod_get_flags2(const fluid_mod_t *mod)
134 {
135     return mod->flags2;
136 }
137 
138 /**
139  * Get destination effect from a modulator.
140  * @param mod The modulator instance
141  * @return Destination generator (#fluid_gen_type)
142  */
143 int
fluid_mod_get_dest(const fluid_mod_t * mod)144 fluid_mod_get_dest(const fluid_mod_t *mod)
145 {
146     return mod->dest;
147 }
148 
149 /**
150  * Get the scale amount from a modulator.
151  * @param mod The modulator instance
152  * @return Scale amount
153  */
154 double
fluid_mod_get_amount(const fluid_mod_t * mod)155 fluid_mod_get_amount(const fluid_mod_t *mod)
156 {
157     return (double) mod->amount;
158 }
159 
160 /*
161  * retrieves the initial value from the given source of the modulator
162  */
163 static fluid_real_t
fluid_mod_get_source_value(const unsigned char mod_src,const unsigned char mod_flags,fluid_real_t * range,const fluid_voice_t * voice)164 fluid_mod_get_source_value(const unsigned char mod_src,
165                            const unsigned char mod_flags,
166                            fluid_real_t *range,
167                            const fluid_voice_t *voice
168                           )
169 {
170     const fluid_channel_t *chan = voice->channel;
171     fluid_real_t val;
172 
173     if(mod_flags & FLUID_MOD_CC)
174     {
175         /* From MIDI Recommended Practice (RP-036) Default Pan Formula:
176          * "Since MIDI controller values range from 0 to 127, the exact center
177          * of the range, 63.5, cannot be represented. Therefore, the effective
178          * range for CC#10 is modified to be 1 to 127, and values 0 and 1 both
179          * pan hard left. The recommended method is to subtract 1 from the
180          * value of CC#10, and saturate the result to be non-negative."
181          *
182          * We treat the balance control in exactly the same way, as the same
183          * problem applies here as well.
184          */
185         if(mod_src == PAN_MSB || mod_src == BALANCE_MSB)
186         {
187             *range = 126;
188             val = fluid_channel_get_cc(chan, mod_src) - 1;
189 
190             if(val < 0)
191             {
192                 val = 0;
193             }
194         }
195         else
196         {
197             val = fluid_channel_get_cc(chan, mod_src);
198         }
199     }
200     else
201     {
202         switch(mod_src)
203         {
204         case FLUID_MOD_NONE:         /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
205             val = *range;
206             break;
207 
208         case FLUID_MOD_VELOCITY:
209             val = fluid_voice_get_actual_velocity(voice);
210             break;
211 
212         case FLUID_MOD_KEY:
213             val = fluid_voice_get_actual_key(voice);
214             break;
215 
216         case FLUID_MOD_KEYPRESSURE:
217             val = fluid_channel_get_key_pressure(chan, voice->key);
218             break;
219 
220         case FLUID_MOD_CHANNELPRESSURE:
221             val = fluid_channel_get_channel_pressure(chan);
222             break;
223 
224         case FLUID_MOD_PITCHWHEEL:
225             val = fluid_channel_get_pitch_bend(chan);
226             *range = 0x4000;
227             break;
228 
229         case FLUID_MOD_PITCHWHEELSENS:
230             val = fluid_channel_get_pitch_wheel_sensitivity(chan);
231             break;
232 
233         default:
234             FLUID_LOG(FLUID_ERR, "Unknown modulator source '%d', disabling modulator.", mod_src);
235             val = 0.0;
236         }
237     }
238 
239     return val;
240 }
241 
242 /**
243  * transforms the initial value retrieved by \c fluid_mod_get_source_value into [0.0;1.0]
244  */
245 static fluid_real_t
fluid_mod_transform_source_value(fluid_real_t val,unsigned char mod_flags,const fluid_real_t range)246 fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, const fluid_real_t range)
247 {
248     /* normalized value, i.e. usually in the range [0;1] */
249     const fluid_real_t val_norm = val / range;
250 
251     /* we could also only switch case the lower nibble of mod_flags, however
252      * this would keep us from adding further mod types in the future
253      *
254      * instead just remove the flag(s) we already took care of
255      */
256     mod_flags &= ~FLUID_MOD_CC;
257 
258     switch(mod_flags/* & 0x0f*/)
259     {
260     case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =0 */
261         val = val_norm;
262         break;
263 
264     case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =1 */
265         val = 1.0f - val_norm;
266         break;
267 
268     case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =2 */
269         val = -1.0f + 2.0f * val_norm;
270         break;
271 
272     case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =3 */
273         val = 1.0f - 2.0f * val_norm;
274         break;
275 
276     case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =4 */
277         val = fluid_concave(127 * (val_norm));
278         break;
279 
280     case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =5 */
281         val = fluid_concave(127 * (1.0f - val_norm));
282         break;
283 
284     case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =6 */
285         val = (val_norm > 0.5f) ?  fluid_concave(127 * 2 * (val_norm - 0.5f))
286               : -fluid_concave(127 * 2 * (0.5f - val_norm));
287         break;
288 
289     case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =7 */
290         val = (val_norm > 0.5f) ? -fluid_concave(127 * 2 * (val_norm - 0.5f))
291               :  fluid_concave(127 * 2 * (0.5f - val_norm));
292         break;
293 
294     case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =8 */
295         val = fluid_convex(127 * (val_norm));
296         break;
297 
298     case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =9 */
299         val = fluid_convex(127 * (1.0f - val_norm));
300         break;
301 
302     case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =10 */
303         val = (val_norm > 0.5f) ?  fluid_convex(127 * 2 * (val_norm - 0.5f))
304               : -fluid_convex(127 * 2 * (0.5f - val_norm));
305         break;
306 
307     case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =11 */
308         val = (val_norm > 0.5f) ? -fluid_convex(127 * 2 * (val_norm - 0.5f))
309               :  fluid_convex(127 * 2 * (0.5f - val_norm));
310         break;
311 
312     case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =12 */
313         val = (val_norm >= 0.5f) ? 1.0f : 0.0f;
314         break;
315 
316     case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =13 */
317         val = (val_norm >= 0.5f) ? 0.0f : 1.0f;
318         break;
319 
320     case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =14 */
321         val = (val_norm >= 0.5f) ? 1.0f : -1.0f;
322         break;
323 
324     case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =15 */
325         val = (val_norm >= 0.5f) ? -1.0f : 1.0f;
326         break;
327 
328     /*
329      * MIDI CCs only have a resolution of 7 bits. The closer val_norm gets to 1,
330      * the less will be the resulting change of the sinus. When using this sin()
331      * for scaling the cutoff frequency, there will be no audible difference between
332      * MIDI CCs 118 to 127. To avoid this waste of CCs multiply with 0.87
333      * (at least for unipolar) which makes sin() never get to 1.0 but to 0.98 which
334      * is close enough.
335      */
336     case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* custom sin(x) */
337         val = FLUID_SIN((FLUID_M_PI / 2.0f * 0.87f) * val_norm);
338         break;
339 
340     case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* custom */
341         val = FLUID_SIN((FLUID_M_PI / 2.0f * 0.87f) * (1.0f - val_norm));
342         break;
343 
344     case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* custom */
345         val = (val_norm > 0.5f) ?  FLUID_SIN(FLUID_M_PI * (val_norm - 0.5f))
346               : -FLUID_SIN(FLUID_M_PI * (0.5f - val_norm));
347         break;
348 
349     case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* custom */
350         val = (val_norm > 0.5f) ? -FLUID_SIN(FLUID_M_PI * (val_norm - 0.5f))
351               :  FLUID_SIN(FLUID_M_PI * (0.5f - val_norm));
352         break;
353 
354     default:
355         FLUID_LOG(FLUID_ERR, "Unknown modulator type '%d', disabling modulator.", mod_flags);
356         val = 0.0f;
357         break;
358     }
359 
360     return val;
361 }
362 
363 /*
364  * fluid_mod_get_value.
365  * Computes and return modulator output following SF2.01
366  * (See SoundFont Modulator Controller Model Chapter 9.5).
367  *
368  * Output = Transform(Amount * Map(primary source input) * Map(secondary source input))
369  *
370  * Notes:
371  * 1)fluid_mod_get_value, ignores the Transform operator. The result is:
372  *
373  *   Output = Amount * Map(primary source input) * Map(secondary source input)
374  *
375  * 2)When primary source input (src1) is set to General Controller 'No Controller',
376  *   output is forced to 0.
377  *
378  * 3)When secondary source input (src2) is set to General Controller 'No Controller',
379  *   output is forced to +1.0
380  */
381 fluid_real_t
fluid_mod_get_value(fluid_mod_t * mod,fluid_voice_t * voice)382 fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
383 {
384     extern fluid_mod_t default_vel2filter_mod;
385 
386     fluid_real_t v1 = 0.0, v2 = 1.0;
387     fluid_real_t range1 = 127.0, range2 = 127.0;
388 
389     /* 'special treatment' for default controller
390      *
391      *  Reference: SF2.01 section 8.4.2
392      *
393      * The GM default controller 'vel-to-filter cut off' is not clearly
394      * defined: If implemented according to the specs, the filter
395      * frequency jumps between vel=63 and vel=64.  To maintain
396      * compatibility with existing sound fonts, the implementation is
397      * 'hardcoded', it is impossible to implement using only one
398      * modulator otherwise.
399      *
400      * I assume here, that the 'intention' of the paragraph is one
401      * octave (1200 cents) filter frequency shift between vel=127 and
402      * vel=64.  'amount' is (-2400), at least as long as the controller
403      * is set to default.
404      *
405      * Further, the 'appearance' of the modulator (source enumerator,
406      * destination enumerator, flags etc) is different from that
407      * described in section 8.4.2, but it matches the definition used in
408      * several SF2.1 sound fonts (where it is used only to turn it off).
409      * */
410     if(fluid_mod_test_identity(mod, &default_vel2filter_mod))
411     {
412 // S. Christian Collins' mod, to stop forcing velocity based filtering
413 
414             if (voice->vel < 64){
415               return (fluid_real_t) mod->amount / 2.0;
416             } else {
417               return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
418             }
419 
420         return 0; // (fluid_real_t) mod->amount / 2.0;
421     }
422 
423 // end S. Christian Collins' mod
424 
425     /* get the initial value of the first source */
426     if(mod->src1 > 0)
427     {
428         v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, voice);
429 
430         /* transform the input value */
431         v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1);
432     }
433     /* When primary source input (src1) is set to General Controller 'No Controller',
434        output is forced to 0.0
435     */
436     else
437     {
438         return 0.0;
439     }
440 
441     /* no need to go further */
442     if(v1 == 0.0f)
443     {
444         return 0.0f;
445     }
446 
447     /* get the second input source */
448     if(mod->src2 > 0)
449     {
450         v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, voice);
451 
452         /* transform the second input value */
453         v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2);
454     }
455     /* When secondary source input (src2) is set to General Controller 'No Controller',
456        output is forced to +1.0
457     */
458     else
459     {
460         v2 = 1.0f;
461     }
462 
463     /* it's as simple as that: */
464     return (fluid_real_t) mod->amount * v1 * v2;
465 }
466 
467 /**
468  * Create a new uninitialized modulator structure.
469  * @return New allocated modulator or NULL if out of memory
470  */
471 fluid_mod_t *
new_fluid_mod()472 new_fluid_mod()
473 {
474     fluid_mod_t *mod = FLUID_NEW(fluid_mod_t);
475 
476     if(mod == NULL)
477     {
478         FLUID_LOG(FLUID_ERR, "Out of memory");
479         return NULL;
480     }
481 
482     return mod;
483 }
484 
485 /**
486  * Free a modulator structure.
487  * @param mod Modulator to free
488  */
489 void
delete_fluid_mod(fluid_mod_t * mod)490 delete_fluid_mod(fluid_mod_t *mod)
491 {
492     FLUID_FREE(mod);
493 }
494 
495 /**
496  * Returns the size of the fluid_mod_t structure.
497  *
498  * Useful in low latency scenarios e.g. to allocate a modulator on the stack.
499  *
500  * @return Size of fluid_mod_t in bytes
501  */
fluid_mod_sizeof()502 size_t fluid_mod_sizeof()
503 {
504     return sizeof(fluid_mod_t);
505 }
506 
507 /**
508  * Checks if modulator with source 1 other than CC is FLUID_MOD_NONE.
509  *
510  * @param mod, modulator.
511  * @return TRUE if modulator source 1 other than cc is FLUID_MOD_NONE, FALSE otherwise.
512  */
513 static int
fluid_mod_is_src1_none(const fluid_mod_t * mod)514 fluid_mod_is_src1_none(const fluid_mod_t *mod)
515 {
516     return(((mod->flags1 & FLUID_MOD_CC) == 0) && (mod->src1 == FLUID_MOD_NONE));
517 }
518 
519 /**
520  * Checks if modulators source other than CC source is invalid.
521  * (specs SF 2.01  7.4, 7.8, 8.2.1)
522  *
523  * @param mod, modulator.
524  * @param src1_select, source input selection to check.
525  *   1 to check src1 source.
526  *   0 to check src2 source.
527  * @return FALSE if selected modulator source other than cc is invalid, TRUE otherwise.
528  */
529 static int
fluid_mod_check_non_cc_source(const fluid_mod_t * mod,unsigned char src1_select)530 fluid_mod_check_non_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
531 {
532     unsigned char flags, src;
533 
534     if(src1_select)
535     {
536         flags = mod->flags1;
537         src = mod->src1;
538     }
539     else
540     {
541         flags = mod->flags2;
542         src = mod->src2;
543     }
544 
545     return(((flags & FLUID_MOD_CC) != 0)  /* src is a CC */
546            /* SF2.01 section 8.2.1: Constant value */
547            || ((src == FLUID_MOD_NONE)
548                || (src == FLUID_MOD_VELOCITY)        /* Note-on velocity */
549                || (src == FLUID_MOD_KEY)             /* Note-on key number */
550                || (src == FLUID_MOD_KEYPRESSURE)     /* Poly pressure */
551                || (src == FLUID_MOD_CHANNELPRESSURE) /* Channel pressure */
552                || (src == FLUID_MOD_PITCHWHEEL)      /* Pitch wheel */
553                || (src == FLUID_MOD_PITCHWHEELSENS)  /* Pitch wheel sensitivity */
554               ));
555 }
556 
557 /**
558  * Checks if modulator CC source is invalid (specs SF 2.01  7.4, 7.8, 8.2.1).
559  * @param mod, modulator.
560  * @src1_select, source input selection:
561  *   1 to check src1 source or
562  *   0 to check src2 source.
563  * @return FALSE if selected modulator's source CC is invalid, TRUE otherwise.
564  */
565 static int
fluid_mod_check_cc_source(const fluid_mod_t * mod,unsigned char src1_select)566 fluid_mod_check_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
567 {
568     unsigned char flags, src;
569 
570     if(src1_select)
571     {
572         flags = mod->flags1;
573         src = mod->src1;
574     }
575     else
576     {
577         flags = mod->flags2;
578         src = mod->src2;
579     }
580 
581     return(((flags & FLUID_MOD_CC) == 0)  /* src is non CC */
582            || ((src != BANK_SELECT_MSB)
583                && (src != BANK_SELECT_LSB)
584                && (src != DATA_ENTRY_MSB)
585                && (src != DATA_ENTRY_LSB)
586                /* is src not NRPN_LSB, NRPN_MSB, RPN_LSB, RPN_MSB */
587                && ((src < NRPN_LSB) || (RPN_MSB < src))
588                /* is src not ALL_SOUND_OFF, ALL_CTRL_OFF, LOCAL_CONTROL, ALL_NOTES_OFF ? */
589                /* is src not OMNI_OFF, OMNI_ON, POLY_OFF, POLY_ON ? */
590                && (src < ALL_SOUND_OFF)
591                /* CC lsb shouldn't allowed to modulate (spec SF 2.01 - 8.2.1)
592                   However, as long fluidsynth will use only CC 7 bits resolution,
593                   it is safe to ignore these SF recommendations on CC receive.
594                   See explanations in fluid_synth_cc_LOCAL() */
595                /* uncomment next line to forbid CC lsb  */
596                /* && ((src < 32) || (63 < src)) */
597               ));
598 }
599 
600 /**
601  * Checks valid modulator sources (specs SF 2.01  7.4, 7.8, 8.2.1)
602  * @param mod, modulator.
603  * @param name,if not NULL, pointer on a string displayed as a warning.
604  * @return TRUE if modulator sources src1, src2 are valid, FALSE otherwise.
605  */
fluid_mod_check_sources(const fluid_mod_t * mod,const char * name)606 int fluid_mod_check_sources(const fluid_mod_t *mod, const char *name)
607 {
608     static const char invalid_non_cc_src[] =
609         "Invalid modulator, using non-CC source %s.src%d=%d";
610     static const char invalid_cc_src[] =
611         "Invalid modulator, using CC source %s.src%d=%d";
612     static const char src1_is_none[] =
613         "Modulator with source 1 none %s.src1=%d";
614 
615     /* checks valid non cc sources */
616     if(!fluid_mod_check_non_cc_source(mod, 1)) /* check src1 */
617     {
618         if(name)
619         {
620             FLUID_LOG(FLUID_WARN, invalid_non_cc_src, name, 1, mod->src1);
621         }
622 
623         return FALSE;
624     }
625 
626     /*
627       When src1 is non CC source FLUID_MOD_NONE, the modulator is valid but
628       the output of this modulator will be forced to 0 at synthesis time.
629       Also this modulator cannot be used to overwrite a default modulator (as
630       there is no default modulator with src1 source equal to FLUID_MOD_NONE).
631       Consequently it is useful to return FALSE to indicate this modulator
632       being useless. It will be removed later with others invalid modulators.
633     */
634     if(fluid_mod_is_src1_none(mod))
635     {
636         if(name)
637         {
638             FLUID_LOG(FLUID_WARN, src1_is_none, name, mod->src1);
639         }
640 
641         return FALSE;
642     }
643 
644     if(!fluid_mod_check_non_cc_source(mod, 0)) /* check src2 */
645     {
646         if(name)
647         {
648             FLUID_LOG(FLUID_WARN, invalid_non_cc_src, name, 2, mod->src2);
649         }
650 
651         return FALSE;
652     }
653 
654     /* checks valid cc sources */
655     if(!fluid_mod_check_cc_source(mod, 1)) /* check src1 */
656     {
657         if(name)
658         {
659             FLUID_LOG(FLUID_WARN, invalid_cc_src, name, 1, mod->src1);
660         }
661 
662         return FALSE;
663     }
664 
665     if(!fluid_mod_check_cc_source(mod, 0)) /* check src2 */
666     {
667         if(name)
668         {
669             FLUID_LOG(FLUID_WARN, invalid_cc_src, name, 2, mod->src2);
670         }
671 
672         return FALSE;
673     }
674 
675     return TRUE;
676 }
677 
678 /**
679  * Checks if two modulators are identical in sources, flags and destination.
680  * @param mod1 First modulator
681  * @param mod2 Second modulator
682  * @return TRUE if identical, FALSE otherwise
683  *
684  * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
685  */
686 int
fluid_mod_test_identity(const fluid_mod_t * mod1,const fluid_mod_t * mod2)687 fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2)
688 {
689     return mod1->dest == mod2->dest
690            && mod1->src1 == mod2->src1
691            && mod1->src2 == mod2->src2
692            && mod1->flags1 == mod2->flags1
693            && mod1->flags2 == mod2->flags2;
694 }
695 
696 /**
697  * Check if the modulator has the given source.
698  *
699  * @param mod The modulator instance
700  * @param cc Boolean value indicating if ctrl is a CC controller or not
701  * @param ctrl The source to check for (if \c cc == FALSE : a value of type #fluid_mod_src, else the value of the MIDI CC to check for)
702  *
703  * @return TRUE if the modulator has the given source, FALSE otherwise.
704  */
fluid_mod_has_source(const fluid_mod_t * mod,int cc,int ctrl)705 int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl)
706 {
707     return
708         (
709             (
710                 ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) != 0) && (cc != 0))
711                 || ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) == 0) && (cc == 0))
712             )
713             ||
714             (
715                 ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) != 0) && (cc != 0))
716                 || ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) == 0) && (cc == 0))
717             )
718         );
719 }
720 
721 /**
722  * Check if the modulator has the given destination.
723  * @param mod The modulator instance
724  * @param gen The destination generator of type #fluid_gen_type to check for
725  * @return TRUE if the modulator has the given destination, FALSE otherwise.
726  */
fluid_mod_has_dest(const fluid_mod_t * mod,int gen)727 int fluid_mod_has_dest(const fluid_mod_t *mod, int gen)
728 {
729     return mod->dest == gen;
730 }
731 
732 
733 /* debug function: Prints the contents of a modulator */
734 #ifdef DEBUG
fluid_dump_modulator(fluid_mod_t * mod)735 void fluid_dump_modulator(fluid_mod_t *mod)
736 {
737     int src1 = mod->src1;
738     int dest = mod->dest;
739     int src2 = mod->src2;
740     int flags1 = mod->flags1;
741     int flags2 = mod->flags2;
742     fluid_real_t amount = (fluid_real_t)mod->amount;
743 
744     printf("Src: ");
745 
746     if(flags1 & FLUID_MOD_CC)
747     {
748         printf("MIDI CC=%i", src1);
749     }
750     else
751     {
752         switch(src1)
753         {
754         case FLUID_MOD_NONE:
755             printf("None");
756             break;
757 
758         case FLUID_MOD_VELOCITY:
759             printf("note-on velocity");
760             break;
761 
762         case FLUID_MOD_KEY:
763             printf("Key nr");
764             break;
765 
766         case FLUID_MOD_KEYPRESSURE:
767             printf("Poly pressure");
768             break;
769 
770         case FLUID_MOD_CHANNELPRESSURE:
771             printf("Chan pressure");
772             break;
773 
774         case FLUID_MOD_PITCHWHEEL:
775             printf("Pitch Wheel");
776             break;
777 
778         case FLUID_MOD_PITCHWHEELSENS:
779             printf("Pitch Wheel sens");
780             break;
781 
782         default:
783             printf("(unknown: %i)", src1);
784         }; /* switch src1 */
785     }; /* if not CC */
786 
787     if(flags1 & FLUID_MOD_NEGATIVE)
788     {
789         printf("- ");
790     }
791     else
792     {
793         printf("+ ");
794     };
795 
796     if(flags1 & FLUID_MOD_BIPOLAR)
797     {
798         printf("bip ");
799     }
800     else
801     {
802         printf("unip ");
803     };
804 
805     printf("-> ");
806 
807     switch(dest)
808     {
809     case GEN_FILTERQ:
810         printf("Q");
811         break;
812 
813     case GEN_FILTERFC:
814         printf("fc");
815         break;
816 
817     case GEN_CUSTOM_FILTERQ:
818         printf("custom-Q");
819         break;
820 
821     case GEN_CUSTOM_FILTERFC:
822         printf("custom-fc");
823         break;
824 
825     case GEN_VIBLFOTOPITCH:
826         printf("VibLFO-to-pitch");
827         break;
828 
829     case GEN_MODENVTOPITCH:
830         printf("ModEnv-to-pitch");
831         break;
832 
833     case GEN_MODLFOTOPITCH:
834         printf("ModLFO-to-pitch");
835         break;
836 
837     case GEN_CHORUSSEND:
838         printf("Chorus send");
839         break;
840 
841     case GEN_REVERBSEND:
842         printf("Reverb send");
843         break;
844 
845     case GEN_PAN:
846         printf("pan");
847         break;
848 
849     case GEN_CUSTOM_BALANCE:
850         printf("balance");
851         break;
852 
853     case GEN_ATTENUATION:
854         printf("att");
855         break;
856 
857     default:
858         printf("dest %i", dest);
859     }; /* switch dest */
860 
861     printf(", amount %f flags %i src2 %i flags2 %i\n", amount, flags1, src2, flags2);
862 };
863 #endif
864 
865