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 Library General Public License
7 * as published by the Free Software Foundation; either version 2 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 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library 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 * fluid_mod_clone
27 */
28 void
fluid_mod_clone(fluid_mod_t * mod,fluid_mod_t * src)29 fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src)
30 {
31 mod->dest = src->dest;
32 mod->src1 = src->src1;
33 mod->flags1 = src->flags1;
34 mod->src2 = src->src2;
35 mod->flags2 = src->flags2;
36 mod->amount = src->amount;
37 }
38
39 /**
40 * Set a modulator's primary source controller and flags.
41 * @param mod Modulator
42 * @param src Modulator source (#fluid_mod_src or a MIDI controller number)
43 * @param flags Flags determining mapping function and whether the source
44 * controller is a general controller (#FLUID_MOD_GC) or a MIDI CC controller
45 * (#FLUID_MOD_CC), see #fluid_mod_flags.
46 */
47 void
fluid_mod_set_source1(fluid_mod_t * mod,int src,int flags)48 fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags)
49 {
50 mod->src1 = src;
51 mod->flags1 = flags;
52 }
53
54 /**
55 * Set a modulator's secondary source controller and flags.
56 * @param mod Modulator
57 * @param src Modulator source (#fluid_mod_src or a MIDI controller number)
58 * @param flags Flags determining mapping function and whether the source
59 * controller is a general controller (#FLUID_MOD_GC) or a MIDI CC controller
60 * (#FLUID_MOD_CC), see #fluid_mod_flags.
61 */
62 void
fluid_mod_set_source2(fluid_mod_t * mod,int src,int flags)63 fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags)
64 {
65 mod->src2 = src;
66 mod->flags2 = flags;
67 }
68
69 /**
70 * Set the destination effect of a modulator.
71 * @param mod Modulator
72 * @param dest Destination generator (#fluid_gen_type)
73 */
74 void
fluid_mod_set_dest(fluid_mod_t * mod,int dest)75 fluid_mod_set_dest(fluid_mod_t* mod, int dest)
76 {
77 mod->dest = dest;
78 }
79
80 /**
81 * Set the scale amount of a modulator.
82 * @param mod Modulator
83 * @param amount Scale amount to assign
84 */
85 void
fluid_mod_set_amount(fluid_mod_t * mod,double amount)86 fluid_mod_set_amount(fluid_mod_t* mod, double amount)
87 {
88 mod->amount = (double) amount;
89 }
90
91 /**
92 * Get the primary source value from a modulator.
93 * @param mod Modulator
94 * @return The primary source value (#fluid_mod_src or a MIDI CC controller value).
95 */
96 int
fluid_mod_get_source1(fluid_mod_t * mod)97 fluid_mod_get_source1(fluid_mod_t* mod)
98 {
99 return mod->src1;
100 }
101
102 /**
103 * Get primary source flags from a modulator.
104 * @param mod Modulator
105 * @return The primary source flags (#fluid_mod_flags).
106 */
107 int
fluid_mod_get_flags1(fluid_mod_t * mod)108 fluid_mod_get_flags1(fluid_mod_t* mod)
109 {
110 return mod->flags1;
111 }
112
113 /**
114 * Get the secondary source value from a modulator.
115 * @param mod Modulator
116 * @return The secondary source value (#fluid_mod_src or a MIDI CC controller value).
117 */
118 int
fluid_mod_get_source2(fluid_mod_t * mod)119 fluid_mod_get_source2(fluid_mod_t* mod)
120 {
121 return mod->src2;
122 }
123
124 /**
125 * Get secondary source flags from a modulator.
126 * @param mod Modulator
127 * @return The secondary source flags (#fluid_mod_flags).
128 */
129 int
fluid_mod_get_flags2(fluid_mod_t * mod)130 fluid_mod_get_flags2(fluid_mod_t* mod)
131 {
132 return mod->flags2;
133 }
134
135 /**
136 * Get destination effect from a modulator.
137 * @param mod Modulator
138 * @return Destination generator (#fluid_gen_type)
139 */
140 int
fluid_mod_get_dest(fluid_mod_t * mod)141 fluid_mod_get_dest(fluid_mod_t* mod)
142 {
143 return mod->dest;
144 }
145
146 /**
147 * Get the scale amount from a modulator.
148 * @param mod Modulator
149 * @return Scale amount
150 */
151 double
fluid_mod_get_amount(fluid_mod_t * mod)152 fluid_mod_get_amount(fluid_mod_t* mod)
153 {
154 return (fluid_real_t) mod->amount;
155 }
156
157
158 /*
159 * fluid_mod_get_value
160 */
161 fluid_real_t
fluid_mod_get_value(fluid_mod_t * mod,fluid_channel_t * chan,fluid_voice_t * voice)162 fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice)
163 {
164 fluid_real_t v1 = 0.0, v2 = 1.0;
165 fluid_real_t range1 = 127.0, range2 = 127.0;
166
167 if (chan == NULL) {
168 return 0.0f;
169 }
170
171 /* 'special treatment' for default controller
172 *
173 * Reference: SF2.01 section 8.4.2
174 *
175 * The GM default controller 'vel-to-filter cut off' is not clearly
176 * defined: If implemented according to the specs, the filter
177 * frequency jumps between vel=63 and vel=64. To maintain
178 * compatibility with existing sound fonts, the implementation is
179 * 'hardcoded', it is impossible to implement using only one
180 * modulator otherwise.
181 *
182 * I assume here, that the 'intention' of the paragraph is one
183 * octave (1200 cents) filter frequency shift between vel=127 and
184 * vel=64. 'amount' is (-2400), at least as long as the controller
185 * is set to default.
186 *
187 * Further, the 'appearance' of the modulator (source enumerator,
188 * destination enumerator, flags etc) is different from that
189 * described in section 8.4.2, but it matches the definition used in
190 * several SF2.1 sound fonts (where it is used only to turn it off).
191 * */
192 if ((mod->src2 == FLUID_MOD_VELOCITY) &&
193 (mod->src1 == FLUID_MOD_VELOCITY) &&
194 (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
195 | FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
196 (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
197 | FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
198 (mod->dest == GEN_FILTERFC)) {
199 // S. Christian Collins' mod, to stop forcing velocity based filtering
200 /*
201 if (voice->vel < 64){
202 return (fluid_real_t) mod->amount / 2.0;
203 } else {
204 return (fluid_real_t) mod->amount * (127 - voice->vel) / 127;
205 }
206 */
207 return 0; // (fluid_real_t) mod->amount / 2.0;
208 }
209 // end S. Christian Collins' mod
210
211 /* get the initial value of the first source */
212 if (mod->src1 > 0) {
213 if (mod->flags1 & FLUID_MOD_CC) {
214 v1 = fluid_channel_get_cc(chan, mod->src1);
215 } else { /* source 1 is one of the direct controllers */
216 switch (mod->src1) {
217 case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
218 v1 = range1;
219 break;
220 case FLUID_MOD_VELOCITY:
221 v1 = voice->vel;
222 break;
223 case FLUID_MOD_KEY:
224 v1 = voice->key;
225 break;
226 case FLUID_MOD_KEYPRESSURE:
227 v1 = fluid_channel_get_key_pressure (chan);
228 break;
229 case FLUID_MOD_CHANNELPRESSURE:
230 v1 = fluid_channel_get_channel_pressure (chan);
231 break;
232 case FLUID_MOD_PITCHWHEEL:
233 v1 = fluid_channel_get_pitch_bend (chan);
234 range1 = 0x4000;
235 break;
236 case FLUID_MOD_PITCHWHEELSENS:
237 v1 = fluid_channel_get_pitch_wheel_sensitivity (chan);
238 break;
239 default:
240 v1 = 0.0;
241 }
242 }
243
244 /* transform the input value */
245 switch (mod->flags1 & 0x0f) {
246 case 0: /* linear, unipolar, positive */
247 v1 /= range1;
248 break;
249 case 1: /* linear, unipolar, negative */
250 v1 = 1.0f - v1 / range1;
251 break;
252 case 2: /* linear, bipolar, positive */
253 v1 = -1.0f + 2.0f * v1 / range1;
254 break;
255 case 3: /* linear, bipolar, negative */
256 v1 = 1.0f - 2.0f * v1 / range1;
257 break;
258 case 4: /* concave, unipolar, positive */
259 v1 = fluid_concave(v1);
260 break;
261 case 5: /* concave, unipolar, negative */
262 v1 = fluid_concave(127 - v1);
263 break;
264 case 6: /* concave, bipolar, positive */
265 v1 = (v1 > 64)? fluid_concave(2 * (v1 - 64)) : -fluid_concave(2 * (64 - v1));
266 break;
267 case 7: /* concave, bipolar, negative */
268 v1 = (v1 > 64)? -fluid_concave(2 * (v1 - 64)) : fluid_concave(2 * (64 - v1));
269 break;
270 case 8: /* convex, unipolar, positive */
271 v1 = fluid_convex(v1);
272 break;
273 case 9: /* convex, unipolar, negative */
274 v1 = fluid_convex(127 - v1);
275 break;
276 case 10: /* convex, bipolar, positive */
277 v1 = (v1 > 64)? fluid_convex(2 * (v1 - 64)) : -fluid_convex(2 * (64 - v1));
278 break;
279 case 11: /* convex, bipolar, negative */
280 v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
281 break;
282 case 12: /* switch, unipolar, positive */
283 v1 = (v1 >= 64)? 1.0f : 0.0f;
284 break;
285 case 13: /* switch, unipolar, negative */
286 v1 = (v1 >= 64)? 0.0f : 1.0f;
287 break;
288 case 14: /* switch, bipolar, positive */
289 v1 = (v1 >= 64)? 1.0f : -1.0f;
290 break;
291 case 15: /* switch, bipolar, negative */
292 v1 = (v1 >= 64)? -1.0f : 1.0f;
293 break;
294 }
295 } else {
296 return 0.0;
297 }
298
299 /* no need to go further */
300 if (v1 == 0.0f) {
301 return 0.0f;
302 }
303
304 /* get the second input source */
305 if (mod->src2 > 0) {
306 if (mod->flags2 & FLUID_MOD_CC) {
307 v2 = fluid_channel_get_cc(chan, mod->src2);
308 } else {
309 switch (mod->src2) {
310 case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
311 v2 = range2;
312 break;
313 case FLUID_MOD_VELOCITY:
314 v2 = voice->vel;
315 break;
316 case FLUID_MOD_KEY:
317 v2 = voice->key;
318 break;
319 case FLUID_MOD_KEYPRESSURE:
320 v2 = fluid_channel_get_key_pressure (chan);
321 break;
322 case FLUID_MOD_CHANNELPRESSURE:
323 v2 = fluid_channel_get_channel_pressure (chan);
324 break;
325 case FLUID_MOD_PITCHWHEEL:
326 v2 = fluid_channel_get_pitch_bend (chan);
327 break;
328 case FLUID_MOD_PITCHWHEELSENS:
329 v2 = fluid_channel_get_pitch_wheel_sensitivity (chan);
330 break;
331 default:
332 v1 = 0.0f;
333 }
334 }
335
336 /* transform the second input value */
337 switch (mod->flags2 & 0x0f) {
338 case 0: /* linear, unipolar, positive */
339 v2 /= range2;
340 break;
341 case 1: /* linear, unipolar, negative */
342 v2 = 1.0f - v2 / range2;
343 break;
344 case 2: /* linear, bipolar, positive */
345 v2 = -1.0f + 2.0f * v2 / range2;
346 break;
347 case 3: /* linear, bipolar, negative */
348 v2 = -1.0f + 2.0f * v2 / range2;
349 break;
350 case 4: /* concave, unipolar, positive */
351 v2 = fluid_concave(v2);
352 break;
353 case 5: /* concave, unipolar, negative */
354 v2 = fluid_concave(127 - v2);
355 break;
356 case 6: /* concave, bipolar, positive */
357 v2 = (v2 > 64)? fluid_concave(2 * (v2 - 64)) : -fluid_concave(2 * (64 - v2));
358 break;
359 case 7: /* concave, bipolar, negative */
360 v2 = (v2 > 64)? -fluid_concave(2 * (v2 - 64)) : fluid_concave(2 * (64 - v2));
361 break;
362 case 8: /* convex, unipolar, positive */
363 v2 = fluid_convex(v2);
364 break;
365 case 9: /* convex, unipolar, negative */
366 v2 = 1.0f - fluid_convex(v2);
367 break;
368 case 10: /* convex, bipolar, positive */
369 v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
370 break;
371 case 11: /* convex, bipolar, negative */
372 v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
373 break;
374 case 12: /* switch, unipolar, positive */
375 v2 = (v2 >= 64)? 1.0f : 0.0f;
376 break;
377 case 13: /* switch, unipolar, negative */
378 v2 = (v2 >= 64)? 0.0f : 1.0f;
379 break;
380 case 14: /* switch, bipolar, positive */
381 v2 = (v2 >= 64)? 1.0f : -1.0f;
382 break;
383 case 15: /* switch, bipolar, negative */
384 v2 = (v2 >= 64)? -1.0f : 1.0f;
385 break;
386 }
387 } else {
388 v2 = 1.0f;
389 }
390
391 /* it's as simple as that: */
392 return (fluid_real_t) mod->amount * v1 * v2;
393 }
394
395 /**
396 * Create a new uninitialized modulator structure.
397 * @return New allocated modulator or NULL if out of memory
398 */
399 fluid_mod_t*
fluid_mod_new()400 fluid_mod_new()
401 {
402 fluid_mod_t* mod = FLUID_NEW (fluid_mod_t);
403 if (mod == NULL) {
404 FLUID_LOG(FLUID_ERR, "Out of memory");
405 return NULL;
406 }
407 return mod;
408 }
409
410 /**
411 * Free a modulator structure.
412 * @param mod Modulator to free
413 */
414 void
fluid_mod_delete(fluid_mod_t * mod)415 fluid_mod_delete (fluid_mod_t *mod)
416 {
417 FLUID_FREE(mod);
418 }
419
420 /**
421 * Checks if two modulators are identical in sources, flags and destination.
422 * @param mod1 First modulator
423 * @param mod2 Second modulator
424 * @return TRUE if identical, FALSE otherwise
425 *
426 * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
427 */
428 int
fluid_mod_test_identity(fluid_mod_t * mod1,fluid_mod_t * mod2)429 fluid_mod_test_identity (fluid_mod_t *mod1, fluid_mod_t *mod2)
430 {
431 return mod1->dest == mod2->dest
432 && mod1->src1 == mod2->src1
433 && mod1->src2 == mod2->src2
434 && mod1->flags1 == mod2->flags1
435 && mod1->flags2 == mod2->flags2;
436 }
437
438 /* debug function: Prints the contents of a modulator */
fluid_dump_modulator(fluid_mod_t * mod)439 void fluid_dump_modulator(fluid_mod_t * mod){
440 int src1=mod->src1;
441 int dest=mod->dest;
442 int src2=mod->src2;
443 int flags1=mod->flags1;
444 int flags2=mod->flags2;
445 fluid_real_t amount=(fluid_real_t)mod->amount;
446
447 printf("Src: ");
448 if (flags1 & FLUID_MOD_CC){
449 printf("MIDI CC=%i",src1);
450 } else {
451 switch(src1){
452 case FLUID_MOD_NONE:
453 printf("None"); break;
454 case FLUID_MOD_VELOCITY:
455 printf("note-on velocity"); break;
456 case FLUID_MOD_KEY:
457 printf("Key nr"); break;
458 case FLUID_MOD_KEYPRESSURE:
459 printf("Poly pressure"); break;
460 case FLUID_MOD_CHANNELPRESSURE:
461 printf("Chan pressure"); break;
462 case FLUID_MOD_PITCHWHEEL:
463 printf("Pitch Wheel"); break;
464 case FLUID_MOD_PITCHWHEELSENS:
465 printf("Pitch Wheel sens"); break;
466 default:
467 printf("(unknown: %i)", src1);
468 }; /* switch src1 */
469 }; /* if not CC */
470 if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");};
471 if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");};
472 printf("-> ");
473 switch(dest){
474 case GEN_FILTERQ: printf("Q"); break;
475 case GEN_FILTERFC: printf("fc"); break;
476 case GEN_VIBLFOTOPITCH: printf("VibLFO-to-pitch"); break;
477 case GEN_MODENVTOPITCH: printf("ModEnv-to-pitch"); break;
478 case GEN_MODLFOTOPITCH: printf("ModLFO-to-pitch"); break;
479 case GEN_CHORUSSEND: printf("Chorus send"); break;
480 case GEN_REVERBSEND: printf("Reverb send"); break;
481 case GEN_PAN: printf("pan"); break;
482 case GEN_ATTENUATION: printf("att"); break;
483 default: printf("dest %i",dest);
484 }; /* switch dest */
485 printf(", amount %f flags %i src2 %i flags2 %i\n",amount, flags1, src2, flags2);
486 };
487
488
489