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,char * name)623 int fluid_mod_check_sources(const fluid_mod_t *mod, 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