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