1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
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.
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.
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
21 #include "fluid_mod.h"
22 #include "fluid_chan.h"
23 #include "fluid_voice.h"
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.
32 fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src)
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;
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.
51 fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags)
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.
66 fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags)
73 * Set the destination effect of a modulator.
74 * @param mod The modulator instance
75 * @param dest Destination generator (#fluid_gen_type)
78 fluid_mod_set_dest(fluid_mod_t *mod, int dest)
84 * Set the scale amount of a modulator.
85 * @param mod The modulator instance
86 * @param amount Scale amount to assign
89 fluid_mod_set_amount(fluid_mod_t *mod, double amount)
91 mod->amount = (double) amount;
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).
100 fluid_mod_get_source1(const fluid_mod_t *mod)
106 * Get primary source flags from a modulator.
107 * @param mod The modulator instance
108 * @return The primary source flags (#fluid_mod_flags).
111 fluid_mod_get_flags1(const fluid_mod_t *mod)
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).
122 fluid_mod_get_source2(const fluid_mod_t *mod)
128 * Get secondary source flags from a modulator.
129 * @param mod The modulator instance
130 * @return The secondary source flags (#fluid_mod_flags).
133 fluid_mod_get_flags2(const fluid_mod_t *mod)
139 * Get destination effect from a modulator.
140 * @param mod The modulator instance
141 * @return Destination generator (#fluid_gen_type)
144 fluid_mod_get_dest(const fluid_mod_t *mod)
150 * Get the scale amount from a modulator.
151 * @param mod The modulator instance
152 * @return Scale amount
155 fluid_mod_get_amount(const fluid_mod_t *mod)
157 return (double) mod->amount;
161 * retrieves the initial value from the given source of the modulator
164 fluid_mod_get_source_value(const unsigned char mod_src,
165 const unsigned char mod_flags,
167 const fluid_voice_t *voice
170 const fluid_channel_t *chan = voice->channel;
173 if(mod_flags & FLUID_MOD_CC)
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."
182 * We treat the balance control in exactly the same way, as the same
183 * problem applies here as well.
185 if(mod_src == PAN_MSB || mod_src == BALANCE_MSB)
188 val = fluid_channel_get_cc(chan, mod_src) - 1;
197 val = fluid_channel_get_cc(chan, mod_src);
204 case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
208 case FLUID_MOD_VELOCITY:
209 val = fluid_voice_get_actual_velocity(voice);
213 val = fluid_voice_get_actual_key(voice);
216 case FLUID_MOD_KEYPRESSURE:
217 val = fluid_channel_get_key_pressure(chan, voice->key);
220 case FLUID_MOD_CHANNELPRESSURE:
221 val = fluid_channel_get_channel_pressure(chan);
224 case FLUID_MOD_PITCHWHEEL:
225 val = fluid_channel_get_pitch_bend(chan);
229 case FLUID_MOD_PITCHWHEELSENS:
230 val = fluid_channel_get_pitch_wheel_sensitivity(chan);
234 FLUID_LOG(FLUID_ERR, "Unknown modulator source '%d', disabling modulator.", mod_src);
243 * transforms the initial value retrieved by \c fluid_mod_get_source_value into [0.0;1.0]
246 fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, const fluid_real_t range)
248 /* normalized value, i.e. usually in the range [0;1]
250 * if val was retrieved from pitch_bend then [-0.5;0.5]
252 const fluid_real_t val_norm = val / range;
254 /* we could also only switch case the lower nibble of mod_flags, however
255 * this would keep us from adding further mod types in the future
257 * instead just remove the flag(s) we already took care of
259 mod_flags &= ~FLUID_MOD_CC;
261 switch(mod_flags/* & 0x0f*/)
263 case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =0 */
267 case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =1 */
268 val = 1.0f - val_norm;
271 case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =2 */
272 val = -1.0f + 2.0f * val_norm;
275 case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =3 */
276 val = 1.0f - 2.0f * val_norm;
279 case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =4 */
280 val = fluid_concave(127 * (val_norm));
283 case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =5 */
284 val = fluid_concave(127 * (1.0f - val_norm));
287 case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =6 */
288 val = (val_norm > 0.5f) ? fluid_concave(127 * 2 * (val_norm - 0.5f))
289 : -fluid_concave(127 * 2 * (0.5f - val_norm));
292 case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =7 */
293 val = (val_norm > 0.5f) ? -fluid_concave(127 * 2 * (val_norm - 0.5f))
294 : fluid_concave(127 * 2 * (0.5f - val_norm));
297 case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =8 */
298 val = fluid_convex(127 * (val_norm));
301 case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =9 */
302 val = fluid_convex(127 * (1.0f - val_norm));
305 case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =10 */
306 val = (val_norm > 0.5f) ? fluid_convex(127 * 2 * (val_norm - 0.5f))
307 : -fluid_convex(127 * 2 * (0.5f - val_norm));
310 case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =11 */
311 val = (val_norm > 0.5f) ? -fluid_convex(127 * 2 * (val_norm - 0.5f))
312 : fluid_convex(127 * 2 * (0.5f - val_norm));
315 case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =12 */
316 val = (val_norm >= 0.5f) ? 1.0f : 0.0f;
319 case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =13 */
320 val = (val_norm >= 0.5f) ? 0.0f : 1.0f;
323 case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =14 */
324 val = (val_norm >= 0.5f) ? 1.0f : -1.0f;
327 case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =15 */
328 val = (val_norm >= 0.5f) ? -1.0f : 1.0f;
332 * MIDI CCs only have a resolution of 7 bits. The closer val_norm gets to 1,
333 * the less will be the resulting change of the sinus. When using this sin()
334 * for scaling the cutoff frequency, there will be no audible difference between
335 * MIDI CCs 118 to 127. To avoid this waste of CCs multiply with 0.87
336 * (at least for unipolar) which makes sin() never get to 1.0 but to 0.98 which
339 case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* custom sin(x) */
340 val = sin(M_PI / 2 * val_norm * 0.87);
343 case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* custom */
344 val = sin(M_PI / 2 * (1.0f - val_norm) * 0.87);
347 case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* custom */
348 val = (val_norm > 0.5f) ? sin(M_PI / 2 * 2 * (val_norm - 0.5f))
349 : -sin(M_PI / 2 * 2 * (0.5f - val_norm));
352 case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* custom */
353 val = (val_norm > 0.5f) ? -sin(M_PI / 2 * 2 * (val_norm - 0.5f))
354 : sin(M_PI / 2 * 2 * (0.5f - val_norm));
358 FLUID_LOG(FLUID_ERR, "Unknown modulator type '%d', disabling modulator.", mod_flags);
367 * fluid_mod_get_value
370 fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
372 extern fluid_mod_t default_vel2filter_mod;
374 fluid_real_t v1 = 0.0, v2 = 1.0;
375 fluid_real_t range1 = 127.0, range2 = 127.0;
377 /* 'special treatment' for default controller
379 * Reference: SF2.01 section 8.4.2
381 * The GM default controller 'vel-to-filter cut off' is not clearly
382 * defined: If implemented according to the specs, the filter
383 * frequency jumps between vel=63 and vel=64. To maintain
384 * compatibility with existing sound fonts, the implementation is
385 * 'hardcoded', it is impossible to implement using only one
386 * modulator otherwise.
388 * I assume here, that the 'intention' of the paragraph is one
389 * octave (1200 cents) filter frequency shift between vel=127 and
390 * vel=64. 'amount' is (-2400), at least as long as the controller
393 * Further, the 'appearance' of the modulator (source enumerator,
394 * destination enumerator, flags etc) is different from that
395 * described in section 8.4.2, but it matches the definition used in
396 * several SF2.1 sound fonts (where it is used only to turn it off).
398 if(fluid_mod_test_identity(mod, &default_vel2filter_mod))
400 // S. Christian Collins' mod, to stop forcing velocity based filtering
402 if (voice->vel < 64){
403 return (fluid_real_t) mod->amount / 2.0;
405 return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
408 return 0; // (fluid_real_t) mod->amount / 2.0;
411 // end S. Christian Collins' mod
413 /* get the initial value of the first source */
416 v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, voice);
418 /* transform the input value */
419 v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1);
426 /* no need to go further */
432 /* get the second input source */
435 v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, voice);
437 /* transform the second input value */
438 v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2);
445 /* it's as simple as that: */
446 return (fluid_real_t) mod->amount * v1 * v2;
450 * Create a new uninitialized modulator structure.
451 * @return New allocated modulator or NULL if out of memory
456 fluid_mod_t *mod = FLUID_NEW(fluid_mod_t);
460 FLUID_LOG(FLUID_ERR, "Out of memory");
468 * Free a modulator structure.
469 * @param mod Modulator to free
472 delete_fluid_mod(fluid_mod_t *mod)
478 * Returns the size of the fluid_mod_t structure.
480 * Useful in low latency scenarios e.g. to allocate a modulator on the stack.
482 * @return Size of fluid_mod_t in bytes
484 size_t fluid_mod_sizeof()
486 return sizeof(fluid_mod_t);
490 * Checks if two modulators are identical in sources, flags and destination.
491 * @param mod1 First modulator
492 * @param mod2 Second modulator
493 * @return TRUE if identical, FALSE otherwise
495 * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
498 fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2)
500 return mod1->dest == mod2->dest
501 && mod1->src1 == mod2->src1
502 && mod1->src2 == mod2->src2
503 && mod1->flags1 == mod2->flags1
504 && mod1->flags2 == mod2->flags2;
508 * Check if the modulator has the given source.
510 * @param mod The modulator instance
511 * @param cc Boolean value indicating if ctrl is a CC controller or not
512 * @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)
514 * @return TRUE if the modulator has the given source, FALSE otherwise.
516 int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl)
521 ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) != 0) && (cc != 0))
522 || ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) == 0) && (cc == 0))
526 ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) != 0) && (cc != 0))
527 || ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) == 0) && (cc == 0))
533 * Check if the modulator has the given destination.
534 * @param mod The modulator instance
535 * @param gen The destination generator of type #fluid_gen_type to check for
536 * @return TRUE if the modulator has the given destination, FALSE otherwise.
538 int fluid_mod_has_dest(const fluid_mod_t *mod, int gen)
540 return mod->dest == gen;
544 /* debug function: Prints the contents of a modulator */
546 void fluid_dump_modulator(fluid_mod_t *mod)
548 int src1 = mod->src1;
549 int dest = mod->dest;
550 int src2 = mod->src2;
551 int flags1 = mod->flags1;
552 int flags2 = mod->flags2;
553 fluid_real_t amount = (fluid_real_t)mod->amount;
557 if(flags1 & FLUID_MOD_CC)
559 printf("MIDI CC=%i", src1);
569 case FLUID_MOD_VELOCITY:
570 printf("note-on velocity");
577 case FLUID_MOD_KEYPRESSURE:
578 printf("Poly pressure");
581 case FLUID_MOD_CHANNELPRESSURE:
582 printf("Chan pressure");
585 case FLUID_MOD_PITCHWHEEL:
586 printf("Pitch Wheel");
589 case FLUID_MOD_PITCHWHEELSENS:
590 printf("Pitch Wheel sens");
594 printf("(unknown: %i)", src1);
598 if(flags1 & FLUID_MOD_NEGATIVE)
607 if(flags1 & FLUID_MOD_BIPOLAR)
628 case GEN_CUSTOM_FILTERQ:
632 case GEN_CUSTOM_FILTERFC:
636 case GEN_VIBLFOTOPITCH:
637 printf("VibLFO-to-pitch");
640 case GEN_MODENVTOPITCH:
641 printf("ModEnv-to-pitch");
644 case GEN_MODLFOTOPITCH:
645 printf("ModLFO-to-pitch");
649 printf("Chorus send");
653 printf("Reverb send");
660 case GEN_CUSTOM_BALANCE:
664 case GEN_ATTENUATION:
669 printf("dest %i", dest);
672 printf(", amount %f flags %i src2 %i flags2 %i\n", amount, flags1, src2, flags2);