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