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
4396 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
280
/* we could also only switch case the lower nibble of mod_flags, however
281
* this would keep us from adding further mod types in the future
282
*
283
* instead just remove the flag(s) we already took care of
284
*/
285
mod_flags &= ~FLUID_MOD_CC;
286
287
switch(mod_flags/* & 0x0f*/)
288
{
289
case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =0 */
290
val = val_norm;
291
break;
292
293
case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =1 */
294
val = 1.0f - val_norm;
295
break;
296
297
case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =2 */
298
val = -1.0f + 2.0f * val_norm;
299
break;
300
301
case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =3 */
302
val = 1.0f - 2.0f * val_norm;
303
break;
304
305
case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =4 */
306
val = fluid_concave(127 * (val_norm));
307
break;
308
309
case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =5 */
310
val = fluid_concave(127 * (1.0f - val_norm));
311
break;
312
313
case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =6 */
314
val = (val_norm > 0.5f) ? fluid_concave(127 * 2 * (val_norm - 0.5f))
315
: -fluid_concave(127 * 2 * (0.5f - val_norm));
316
break;
317
318
case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =7 */
319
val = (val_norm > 0.5f) ? -fluid_concave(127 * 2 * (val_norm - 0.5f))
320
: fluid_concave(127 * 2 * (0.5f - val_norm));
321
break;
322
323
case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =8 */
324
val = fluid_convex(127 * (val_norm));
325
break;
326
327
case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =9 */
328
val = fluid_convex(127 * (1.0f - val_norm));
329
break;
330
331
case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =10 */
332
val = (val_norm > 0.5f) ? fluid_convex(127 * 2 * (val_norm - 0.5f))
333
: -fluid_convex(127 * 2 * (0.5f - val_norm));
334
break;
335
336
case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =11 */
337
val = (val_norm > 0.5f) ? -fluid_convex(127 * 2 * (val_norm - 0.5f))
338
: fluid_convex(127 * 2 * (0.5f - val_norm));
339
break;
340
341
case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =12 */
342
val = (val_norm >= 0.5f) ? 1.0f : 0.0f;
343
break;
344
345
case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =13 */
346
val = (val_norm >= 0.5f) ? 0.0f : 1.0f;
347
break;
348
349
case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =14 */
350
val = (val_norm >= 0.5f) ? 1.0f : -1.0f;
351
break;
352
353
case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =15 */
354
val = (val_norm >= 0.5f) ? -1.0f : 1.0f;
355
break;
356
357
/*
358
* MIDI CCs only have a resolution of 7 bits. The closer val_norm gets to 1,
359
* the less will be the resulting change of the sinus. When using this sin()
360
* for scaling the cutoff frequency, there will be no audible difference between
361
* MIDI CCs 118 to 127. To avoid this waste of CCs multiply with 0.87
362
* (at least for unipolar) which makes sin() never get to 1.0 but to 0.98 which
363
* is close enough.
364
*/
365
case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* custom sin(x) */
366
val = FLUID_SIN((FLUID_M_PI / 2.0f * 0.87f) * val_norm);
367
break;
368
369
case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* custom */
370
val = FLUID_SIN((FLUID_M_PI / 2.0f * 0.87f) * (1.0f - val_norm));
371
break;
372
373
case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* custom */
374
val = (val_norm > 0.5f) ? FLUID_SIN(FLUID_M_PI * (val_norm - 0.5f))
375
: -FLUID_SIN(FLUID_M_PI * (0.5f - val_norm));
376
break;
377
378
case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* custom */
379
val = (val_norm > 0.5f) ? -FLUID_SIN(FLUID_M_PI * (val_norm - 0.5f))
380
: FLUID_SIN(FLUID_M_PI * (0.5f - val_norm));
381
break;
382
383
default:
384
FLUID_LOG(FLUID_ERR, "Unknown modulator type '%d', disabling modulator.", mod_flags);
385
val = 0.0f;
386
break;
387
}
388
389
return val;
390
}
391
392
/*
393
* fluid_mod_get_value.
394
* Computes and return modulator output following SF2.01
395
* (See SoundFont Modulator Controller Model Chapter 9.5).
396
*
397
* Output = Transform(Amount * Map(primary source input) * Map(secondary source input))
398
*
399
* Note:
400
* fluid_mod_get_value ignores the Transform operator. The result is:
401
*
402
* Output = Amount * Map(primary source input) * Map(secondary source input)
403
*/
404
fluid_real_t
405
fluid_mod_get_value(fluid_mod_t *mod, fluid_voice_t *voice)
406
{
407
extern fluid_mod_t default_vel2filter_mod;
408
409
fluid_real_t v1, v2;
410
fluid_real_t final_value;
411
/* The wording of the default modulators refers to a range of 127/128.
412
* And the table in section 9.5.3 suggests, that this mapping should be applied
413
* to all unipolar and bipolar mappings respectively.
414
*
415
* Thinking about this further, this is actually pretty clever, as this is properly
416
* addresses MIDI Recommended Practice (RP-036) Default Pan Formula
417
* "Since MIDI controller values range from 0 to 127, the exact center
418
* of the range, 63.5, cannot be represented."
419
*
420
* When changing the overall range to 127/128 however, the "middle pan" value of 64
421
* can be correctly represented.
422
*/
423
fluid_real_t range1 = 128.0, range2 = 128.0;
424
425
/* 'special treatment' for default controller
426
*
427
* Reference: SF2.01 section 8.4.2
428
*
429
* The GM default controller 'vel-to-filter cut off' is not clearly
430
* defined: If implemented according to the specs, the filter
431
* frequency jumps between vel=63 and vel=64. To maintain
432
* compatibility with existing sound fonts, the implementation is
433
* 'hardcoded', it is impossible to implement using only one
434
* modulator otherwise.
435
*
436
* I assume here, that the 'intention' of the paragraph is one
437
* octave (1200 cents) filter frequency shift between vel=127 and
438
* vel=64. 'amount' is (-2400), at least as long as the controller
439
* is set to default.
440
*
441
* Further, the 'appearance' of the modulator (source enumerator,
442
* destination enumerator, flags etc) is different from that
443
* described in section 8.4.2, but it matches the definition used in
444
* several SF2.1 sound fonts (where it is used only to turn it off).
445
* */
446
if(fluid_mod_test_identity(mod, &default_vel2filter_mod))
447
{
448
/*
449
if (voice->vel < 64){
450
return (fluid_real_t) mod->amount / 2.0;
451
} else {
452
return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
453
}
454
return (fluid_real_t) mod->amount / 2.0;
455
*/
456
// S. Christian Collins' mod, to stop forcing velocity based filtering
457
return 0;
458
}
459
460
/* Get the initial value of the first source.
461
*
462
* Even if the src is FLUID_MOD_NONE, the value has to be transformed, see #1389
463
*/
464
v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, voice);
465
466
/* transform the input value */
467
v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1);
468
469
/* get the second input source */
470
v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, voice);
471
472
/* transform the second input value */
473
v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2);
474
475
/* it indeed is as simple as that: */
476
final_value = (fluid_real_t) mod->amount * v1 * v2;
477
478
/* check for absolute value transform */
479
if(mod->trans == FLUID_MOD_TRANSFORM_ABS)
480
{
481
final_value = FLUID_FABS(final_value);
482
}
483
return final_value;
484
}
485
486
/**
487
* Create a new uninitialized modulator structure.
488
*
489
* @return New allocated modulator or NULL if out of memory
490
*/
491
fluid_mod_t *
492
new_fluid_mod(void)
493
{
494
fluid_mod_t *mod = FLUID_NEW(fluid_mod_t);
495
496
if(mod == NULL)
497
{
498
FLUID_LOG(FLUID_ERR, "Out of memory");
499
return NULL;
500
}
501
// for the sake of backward compatibility
502
mod->trans = FLUID_MOD_TRANSFORM_LINEAR;
503
return mod;
504
}
505
506
/**
507
* Free a modulator structure.
508
*
509
* @param mod Modulator to free
510
*/
511
void
512
delete_fluid_mod(fluid_mod_t *mod)
513
{
514
FLUID_FREE(mod);
515
}
516
517
/**
518
* Returns the size of the fluid_mod_t structure.
519
*
520
* @return Size of fluid_mod_t in bytes
521
*
522
* Useful in low latency scenarios e.g. to allocate a modulator on the stack.
523
*/
524
size_t fluid_mod_sizeof(void)
525
{
526
return sizeof(fluid_mod_t);
527
}
528
529
/**
530
* Checks if modulator with source 1 other than CC is FLUID_MOD_NONE.
531
*
532
* @param mod, modulator.
533
* @return TRUE if modulator source 1 other than cc is FLUID_MOD_NONE, FALSE otherwise.
534
*/
535
static int
536
fluid_mod_is_src1_none(const fluid_mod_t *mod)
537
{
538
return(((mod->flags1 & FLUID_MOD_CC) == 0) && (mod->src1 == FLUID_MOD_NONE));
539
}
540
541
/**
542
* Checks if modulators source other than CC source is invalid.
543
*
544
* @param mod, modulator.
545
* @param src1_select, source input selection to check.
546
* 1 to check src1 source.
547
* 0 to check src2 source.
548
* @return FALSE if selected modulator source other than cc is invalid, TRUE otherwise.
549
*
550
* (specs SF 2.01 7.4, 7.8, 8.2.1)
551
*/
552
static int
553
fluid_mod_check_non_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
554
{
555
unsigned char flags, src;
556
557
if(src1_select)
558
{
559
flags = mod->flags1;
560
src = mod->src1;
561
}
562
else
563
{
564
flags = mod->flags2;
565
src = mod->src2;
566
}
567
568
return(((flags & FLUID_MOD_CC) != 0) /* src is a CC */
569
/* SF2.01 section 8.2.1: Constant value */
570
|| ((src == FLUID_MOD_NONE)
571
|| (src == FLUID_MOD_VELOCITY) /* Note-on velocity */
572
|| (src == FLUID_MOD_KEY) /* Note-on key number */
573
|| (src == FLUID_MOD_KEYPRESSURE) /* Poly pressure */
574
|| (src == FLUID_MOD_CHANNELPRESSURE) /* Channel pressure */
575
|| (src == FLUID_MOD_PITCHWHEEL) /* Pitch wheel */
576
|| (src == FLUID_MOD_PITCHWHEELSENS) /* Pitch wheel sensitivity */
577
));
578
}
579
580
/**
581
* Checks if modulator CC source is invalid (specs SF 2.01 7.4, 7.8, 8.2.1).
582
*
583
* @param mod, modulator.
584
* @src1_select, source input selection:
585
* 1 to check src1 source or
586
* 0 to check src2 source.
587
* @return FALSE if selected modulator's source CC is invalid, TRUE otherwise.
588
*/
589
static int
590
fluid_mod_check_cc_source(const fluid_mod_t *mod, unsigned char src1_select)
591
{
592
unsigned char flags, src;
593
594
if(src1_select)
595
{
596
flags = mod->flags1;
597
src = mod->src1;
598
}
599
else
600
{
601
flags = mod->flags2;
602
src = mod->src2;
603
}
604
605
return(((flags & FLUID_MOD_CC) == 0) /* src is non CC */
606
|| ((src != BANK_SELECT_MSB)
607
&& (src != BANK_SELECT_LSB)
608
&& (src != DATA_ENTRY_MSB)
609
&& (src != DATA_ENTRY_LSB)
610
/* is src not NRPN_LSB, NRPN_MSB, RPN_LSB, RPN_MSB */
611
&& ((src < NRPN_LSB) || (RPN_MSB < src))
612
/* is src not ALL_SOUND_OFF, ALL_CTRL_OFF, LOCAL_CONTROL, ALL_NOTES_OFF ? */
613
/* is src not OMNI_OFF, OMNI_ON, POLY_OFF, POLY_ON ? */
614
&& (src < ALL_SOUND_OFF)
615
/* CC lsb shouldn't allowed to modulate (spec SF 2.01 - 8.2.1)
616
However, as long fluidsynth will use only CC 7 bits resolution,
617
it is safe to ignore these SF recommendations on CC receive.
618
See explanations in fluid_synth_cc_LOCAL() */
619
/* uncomment next line to forbid CC lsb */
620
/* && ((src < 32) || (63 < src)) */
621
));
622
}
623
624
/**
625
* Checks valid modulator sources (specs SF 2.01 7.4, 7.8, 8.2.1)
626
*
627
* @param mod, modulator.
628
* @param name,if not NULL, pointer on a string displayed as a warning.
629
* @return TRUE if modulator sources src1, src2 are valid, FALSE otherwise.
630
*/
631
int fluid_mod_check_sources(const fluid_mod_t *mod, char *name)
632
{
633
static const char invalid_non_cc_src[] =
634
"Invalid modulator, using non-CC source %s.src%d=%d";
635
static const char invalid_cc_src[] =
636
"Invalid modulator, using CC source %s.src%d=%d";
637
static const char src1_is_none[] =
638
"Modulator with source 1 none %s.src1=%d";
639
640
/* checks valid non cc sources */
641
if(!fluid_mod_check_non_cc_source(mod, 1)) /* check src1 */
642
{
643
if(name)
644
{
645
FLUID_LOG(FLUID_WARN, invalid_non_cc_src, name, 1, mod->src1);
646
}
647
648
return FALSE;
649
}
650
651
/*
652
When src1 is non CC source FLUID_MOD_NONE, the modulator is valid but
653
the output of this modulator will be forced to 0 at synthesis time.
654
Also this modulator cannot be used to overwrite a default modulator (as
655
there is no default modulator with src1 source equal to FLUID_MOD_NONE).
656
Consequently it is useful to return FALSE to indicate this modulator
657
being useless. It will be removed later with others invalid modulators.
658
*/
659
if(fluid_mod_is_src1_none(mod))
660
{
661
if(name)
662
{
663
FLUID_LOG(FLUID_WARN, src1_is_none, name, mod->src1);
664
}
665
666
return FALSE;
667
}
668
669
if(!fluid_mod_check_non_cc_source(mod, 0)) /* check src2 */
670
{
671
if(name)
672
{
673
FLUID_LOG(FLUID_WARN, invalid_non_cc_src, name, 2, mod->src2);
674
}
675
676
return FALSE;
677
}
678
679
/* checks valid cc sources */
680
if(!fluid_mod_check_cc_source(mod, 1)) /* check src1 */
681
{
682
if(name)
683
{
684
FLUID_LOG(FLUID_WARN, invalid_cc_src, name, 1, mod->src1);
685
}
686
687
return FALSE;
688
}
689
690
if(!fluid_mod_check_cc_source(mod, 0)) /* check src2 */
691
{
692
if(name)
693
{
694
FLUID_LOG(FLUID_WARN, invalid_cc_src, name, 2, mod->src2);
695
}
696
697
return FALSE;
698
}
699
700
return TRUE;
701
}
702
703
/**
704
* Checks if two modulators are identical in sources, flags and destination.
705
*
706
* @param mod1 First modulator
707
* @param mod2 Second modulator
708
* @return TRUE if identical, FALSE otherwise
709
*
710
* SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
711
*/
712
int
713
fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2)
714
{
715
return mod1->dest == mod2->dest
716
&& mod1->src1 == mod2->src1
717
&& mod1->src2 == mod2->src2
718
&& mod1->flags1 == mod2->flags1
719
&& mod1->flags2 == mod2->flags2;
720
}
721
722
/**
723
* Check if the modulator has the given source.
724
*
725
* @param mod The modulator instance
726
* @param cc Boolean value indicating if ctrl is a CC controller or not
727
* @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)
728
*
729
* @return TRUE if the modulator has the given source, FALSE otherwise.
730
*/
731
int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl)
732
{
733
return
734
(
735
(
736
((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) != 0) && (cc != 0))
737
|| ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) == 0) && (cc == 0))
738
)
739
||
740
(
741
((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) != 0) && (cc != 0))
742
|| ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) == 0) && (cc == 0))
743
)
744
);
745
}
746
747
/**
748
* Check if the modulator has the given destination.
749
*
750
* @param mod The modulator instance
751
* @param gen The destination generator of type #fluid_gen_type to check for
752
* @return TRUE if the modulator has the given destination, FALSE otherwise.
753
*/
754
int fluid_mod_has_dest(const fluid_mod_t *mod, int gen)
755
{
756
return mod->dest == gen;
757
}
758
759
760
/* debug function: Prints the contents of a modulator */
761
#ifdef DEBUG
762
void fluid_dump_modulator(fluid_mod_t *mod)
763
{
764
int src1 = mod->src1;
765
int dest = mod->dest;
766
int src2 = mod->src2;
767
int flags1 = mod->flags1;
768
int flags2 = mod->flags2;
769
fluid_real_t amount = (fluid_real_t)mod->amount;
770
771
printf("Src: ");
772
773
if(flags1 & FLUID_MOD_CC)
774
{
775
printf("MIDI CC=%i", src1);
776
}
777
else
778
{
779
switch(src1)
780
{
781
case FLUID_MOD_NONE:
782
printf("None");
783
break;
784
785
case FLUID_MOD_VELOCITY:
786
printf("note-on velocity");
787
break;
788
789
case FLUID_MOD_KEY:
790
printf("Key nr");
791
break;
792
793
case FLUID_MOD_KEYPRESSURE:
794
printf("Poly pressure");
795
break;
796
797
case FLUID_MOD_CHANNELPRESSURE:
798
printf("Chan pressure");
799
break;
800
801
case FLUID_MOD_PITCHWHEEL:
802
printf("Pitch Wheel");
803
break;
804
805
case FLUID_MOD_PITCHWHEELSENS:
806
printf("Pitch Wheel sens");
807
break;
808
809
default:
810
printf("(unknown: %i)", src1);
811
}; /* switch src1 */
812
}; /* if not CC */
813
814
if(flags1 & FLUID_MOD_NEGATIVE)
815
{
816
printf("- ");
817
}
818
else
819
{
820
printf("+ ");
821
};
822
823
if(flags1 & FLUID_MOD_BIPOLAR)
824
{
825
printf("bip ");
826
}
827
else
828
{
829
printf("unip ");
830
};
831
832
printf("-> ");
833
834
switch(dest)
835
{
836
case GEN_FILTERQ:
837
printf("Q");
838
break;
839
840
case GEN_FILTERFC:
841
printf("fc");
842
break;
843
844
case GEN_CUSTOM_FILTERQ:
845
printf("custom-Q");
846
break;
847
848
case GEN_CUSTOM_FILTERFC:
849
printf("custom-fc");
850
break;
851
852
case GEN_VIBLFOTOPITCH:
853
printf("VibLFO-to-pitch");
854
break;
855
856
case GEN_MODENVTOPITCH:
857
printf("ModEnv-to-pitch");
858
break;
859
860
case GEN_MODLFOTOPITCH:
861
printf("ModLFO-to-pitch");
862
break;
863
864
case GEN_CHORUSSEND:
865
printf("Chorus send");
866
break;
867
868
case GEN_REVERBSEND:
869
printf("Reverb send");
870
break;
871
872
case GEN_PAN:
873
printf("pan");
874
break;
875
876
case GEN_CUSTOM_BALANCE:
877
printf("balance");
878
break;
879
880
case GEN_ATTENUATION:
881
printf("att");
882
break;
883
884
default:
885
printf("dest %i", dest);
886
}; /* switch dest */
887
888
printf(", amount %f flags %i src2 %i flags2 %i\n", amount, flags1, src2, flags2);
889
};
890
#endif
891
892