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