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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21 #include "fluid.h"
22 #include "conv.h"
23 #include "voice.h"
24
25 namespace FluidS {
26
27 #undef FLUID_LOG
28 #define FLUID_LOG(a, ...)
29
30 //---------------------------------------------------------
31 // clone
32 //---------------------------------------------------------
33
clone(Mod * mod) const34 void Mod::clone(Mod* mod) const
35 {
36 mod->dest = dest;
37 mod->src1 = src1;
38 mod->flags1 = flags1;
39 mod->src2 = src2;
40 mod->flags2 = flags2;
41 mod->amount = amount;
42 }
43
44 /*
45 * fluid_mod_set_source1
46 */
set_source1(int src,int flags)47 void Mod::set_source1(int src, int flags)
48 {
49 src1 = src;
50 flags1 = flags;
51 }
52
53 /*
54 * fluid_mod_set_source2
55 */
set_source2(int src,int flags)56 void Mod::set_source2(int src, int flags)
57 {
58 src2 = src;
59 flags2 = flags;
60 }
61
62 /*
63 * fluid_mod_get_value
64 */
get_value(Channel * chan,Voice * voice)65 float Mod::get_value(Channel* chan, Voice* voice)
66 {
67 Mod* mod = this;
68 float v1 = 0.0, v2 = 1.0;
69 float range1 = 127.0, range2 = 127.0;
70
71 if (chan == 0)
72 return 0.0f;
73
74 /* 'special treatment' for default controller
75 *
76 * Reference: SF2.01 section 8.4.2
77 *
78 * The GM default controller 'vel-to-filter cut off' is not clearly
79 * defined: If implemented according to the specs, the filter
80 * frequency jumps between vel=63 and vel=64. To maintain
81 * compatibility with existing sound fonts, the implementation is
82 * 'hardcoded', it is impossible to implement using only one
83 * modulator otherwise.
84 *
85 * I assume here, that the 'intention' of the paragraph is one
86 * octave (1200 cents) filter frequency shift between vel=127 and
87 * vel=64. 'amount' is (-2400), at least as long as the controller
88 * is set to default.
89 *
90 * Further, the 'appearance' of the modulator (source enumerator,
91 * destination enumerator, flags etc) is different from that
92 * described in section 8.4.2, but it matches the definition used in
93 * several SF2.1 sound fonts (where it is used only to turn it off).
94 */
95
96 if ((mod->src2 == FLUID_MOD_VELOCITY) &&
97 (mod->src1 == FLUID_MOD_VELOCITY) &&
98 (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
99 | FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) &&
100 (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR
101 | FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) &&
102 (mod->dest == GEN_FILTERFC)) {
103 // Disable default vel-to-filter cutoff modulator per upstream FluidSynth
104 /*
105 if (voice->vel < 64)
106 return (float) mod->amount / 2.0;
107 else
108 return (float) mod->amount * (127 - voice->vel) / 127;
109 }
110 */
111 return 0; // (float) mod->amount / 2.0;
112 }
113 // end vel-to-filter cutoff mod
114
115 /* get the initial value of the first source */
116 if (mod->src1 > 0) {
117 if (mod->flags1 & FLUID_MOD_CC) {
118 v1 = chan->getCC(mod->src1);
119 }
120 else { /* source 1 is one of the direct controllers */
121 switch (mod->src1) {
122 case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
123 v1 = range1;
124 break;
125 case FLUID_MOD_VELOCITY:
126 v1 = voice->vel;
127 break;
128 case FLUID_MOD_KEY:
129 v1 = voice->key;
130 break;
131 case FLUID_MOD_KEYPRESSURE:
132 v1 = chan->keyPressure(voice->key);
133 break;
134 case FLUID_MOD_CHANNELPRESSURE:
135 v1 = chan->channel_pressure;
136 break;
137 case FLUID_MOD_PITCHWHEEL:
138 v1 = chan->pitch_bend;
139 range1 = 0x4000;
140 break;
141 case FLUID_MOD_PITCHWHEELSENS:
142 v1 = chan->pitch_wheel_sensitivity;
143 break;
144 default:
145 v1 = 0.0;
146 }
147 }
148
149 /* transform the input value */
150 switch (mod->flags1 & 0x0f) {
151 case 0: /* linear, unipolar, positive */
152 v1 /= range1;
153 break;
154 case 1: /* linear, unipolar, negative */
155 v1 = 1.0f - v1 / range1;
156 break;
157 case 2: /* linear, bipolar, positive */
158 v1 = -1.0f + 2.0f * v1 / range1;
159 break;
160 case 3: /* linear, bipolar, negative */
161 v1 = 1.0f - 2.0f * v1 / range1;
162 break;
163 case 4: /* concave, unipolar, positive */
164 v1 = fluid_concave(v1);
165 break;
166 case 5: /* concave, unipolar, negative */
167 v1 = fluid_concave(127 - v1);
168 break;
169 case 6: /* concave, bipolar, positive */
170 v1 = (v1 > 64)? fluid_concave(2 * (v1 - 64)) : -fluid_concave(2 * (64 - v1));
171 break;
172 case 7: /* concave, bipolar, negative */
173 v1 = (v1 > 64)? -fluid_concave(2 * (v1 - 64)) : fluid_concave(2 * (64 - v1));
174 break;
175 case 8: /* convex, unipolar, positive */
176 v1 = fluid_convex(v1);
177 break;
178 case 9: /* convex, unipolar, negative */
179 v1 = fluid_convex(127 - v1);
180 break;
181 case 10: /* convex, bipolar, positive */
182 v1 = (v1 > 64) ? fluid_convex(2 * (v1 - 64)) : -fluid_convex(2 * (64 - v1));
183 break;
184 case 11: /* convex, bipolar, negative */
185 v1 = (v1 > 64)? -fluid_convex(2 * (v1 - 64)) : fluid_convex(2 * (64 - v1));
186 break;
187 case 12: /* switch, unipolar, positive */
188 v1 = (v1 >= 64)? 1.0f : 0.0f;
189 break;
190 case 13: /* switch, unipolar, negative */
191 v1 = (v1 >= 64)? 0.0f : 1.0f;
192 break;
193 case 14: /* switch, bipolar, positive */
194 v1 = (v1 >= 64)? 1.0f : -1.0f;
195 break;
196 case 15: /* switch, bipolar, negative */
197 v1 = (v1 >= 64)? -1.0f : 1.0f;
198 break;
199 }
200 }
201 else
202 return 0.0;
203
204 /* no need to go further */
205 if (v1 == 0.0f)
206 return 0.0f;
207
208 /* get the second input source */
209 if (mod->src2 > 0) {
210 if (mod->flags2 & FLUID_MOD_CC) {
211 v2 = chan->getCC(mod->src2);
212 }
213 else {
214 switch (mod->src2) {
215 case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
216 v2 = range2;
217 break;
218 case FLUID_MOD_VELOCITY:
219 v2 = voice->vel;
220 break;
221 case FLUID_MOD_KEY:
222 v2 = voice->key;
223 break;
224 case FLUID_MOD_KEYPRESSURE:
225 v2 = chan->keyPressure(voice->key);
226 break;
227 case FLUID_MOD_CHANNELPRESSURE:
228 v2 = chan->channel_pressure;
229 break;
230 case FLUID_MOD_PITCHWHEEL:
231 v2 = chan->pitch_bend;
232 break;
233 case FLUID_MOD_PITCHWHEELSENS:
234 v2 = chan->pitch_wheel_sensitivity;
235 break;
236 default:
237 v1 = 0.0f;
238 }
239 }
240
241 /* transform the second input value */
242 switch (mod->flags2 & 0x0f) {
243 case 0: /* linear, unipolar, positive */
244 v2 /= range2;
245 break;
246 case 1: /* linear, unipolar, negative */
247 v2 = 1.0f - v2 / range2;
248 break;
249 case 2: /* linear, bipolar, positive */
250 v2 = -1.0f + 2.0f * v2 / range2;
251 break;
252 case 3: /* linear, bipolar, negative */
253 v2 = -1.0f + 2.0f * v2 / range2;
254 break;
255 case 4: /* concave, unipolar, positive */
256 v2 = fluid_concave(v2);
257 break;
258 case 5: /* concave, unipolar, negative */
259 v2 = fluid_concave(127 - v2);
260 break;
261 case 6: /* concave, bipolar, positive */
262 v2 = (v2 > 64)? fluid_concave(2 * (v2 - 64)) : -fluid_concave(2 * (64 - v2));
263 break;
264 case 7: /* concave, bipolar, negative */
265 v2 = (v2 > 64)? -fluid_concave(2 * (v2 - 64)) : fluid_concave(2 * (64 - v2));
266 break;
267 case 8: /* convex, unipolar, positive */
268 v2 = fluid_convex(v2);
269 break;
270 case 9: /* convex, unipolar, negative */
271 v2 = 1.0f - fluid_convex(v2);
272 break;
273 case 10: /* convex, bipolar, positive */
274 v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
275 break;
276 case 11: /* convex, bipolar, negative */
277 v2 = (v2 > 64)? -fluid_convex(2 * (v2 - 64)) : fluid_convex(2 * (64 - v2));
278 break;
279 case 12: /* switch, unipolar, positive */
280 v2 = (v2 >= 64)? 1.0f : 0.0f;
281 break;
282 case 13: /* switch, unipolar, negative */
283 v2 = (v2 >= 64)? 0.0f : 1.0f;
284 break;
285 case 14: /* switch, bipolar, positive */
286 v2 = (v2 >= 64)? 1.0f : -1.0f;
287 break;
288 case 15: /* switch, bipolar, negative */
289 v2 = (v2 >= 64)? -1.0f : 1.0f;
290 break;
291 }
292 }
293 else
294 v2 = 1.0f;
295
296 /* it's as simple as that: */
297 return mod->amount * v1 * v2;
298 }
299
300 /*
301 * test_identity
302 */
303 /* Purpose:
304 * Checks, if two modulators are identical.
305 * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'.
306 */
test_identity(const Mod * mod1,const Mod * mod2)307 bool test_identity(const Mod * mod1, const Mod * mod2)
308 {
309 return (mod1->dest == mod2->dest)
310 && (mod1->src1 == mod2->src1)
311 && (mod1->src2 == mod2->src2)
312 && (mod1->flags1 == mod2->flags1)
313 && (mod1->flags2 == mod2->flags2);
314 }
315
316 //---------------------------------------------------------
317 // dump
318 // debug function: Prints the contents of a modulator
319 //---------------------------------------------------------
320
dump() const321 void Mod::dump() const
322 {
323 const Mod* mod = this;
324
325 int lsrc1 = mod->src1;
326 int ldest = mod->dest;
327 int lsrc2 = mod->src2;
328 int lflags1 = mod->flags1;
329 int lflags2 = mod->flags2;
330 float lamount = (float)mod->amount;
331
332 printf("Src: ");
333 if (flags1 & FLUID_MOD_CC){
334 printf("MIDI CC=%i",lsrc1);
335 }
336 else {
337 switch(lsrc1){
338 case FLUID_MOD_NONE:
339 printf("None");
340 break;
341 case FLUID_MOD_VELOCITY:
342 printf("note-on velocity");
343 break;
344 case FLUID_MOD_KEY:
345 printf("Key nr");
346 break;
347 case FLUID_MOD_KEYPRESSURE:
348 printf("Poly pressure");
349 break;
350 case FLUID_MOD_CHANNELPRESSURE:
351 printf("Chan pressure");
352 break;
353 case FLUID_MOD_PITCHWHEEL:
354 printf("Pitch Wheel");
355 break;
356 case FLUID_MOD_PITCHWHEELSENS:
357 printf("Pitch Wheel sens");
358 break;
359 default:
360 printf("(unknown: %i)", lsrc1);
361 } /* switch src1 */
362 } /* if not CC */
363 if (lflags1 & FLUID_MOD_NEGATIVE)
364 printf("- ");
365 else
366 printf("+ ");
367 if (lflags1 & FLUID_MOD_BIPOLAR)
368 printf("bip ");
369 else
370 printf("unip ");
371 printf("-> ");
372 switch(ldest){
373 case GEN_FILTERQ:
374 printf("Q");
375 break;
376 case GEN_FILTERFC:
377 printf("fc");
378 break;
379 case GEN_VIBLFOTOPITCH:
380 printf("VibLFO-to-pitch");
381 break;
382 case GEN_MODENVTOPITCH:
383 printf("ModEnv-to-pitch");
384 break;
385 case GEN_MODLFOTOPITCH:
386 printf("ModLFO-to-pitch");
387 break;
388 case GEN_CHORUSSEND:
389 printf("Chorus send");
390 break;
391 case GEN_REVERBSEND:
392 printf("Reverb send");
393 break;
394 case GEN_PAN:
395 printf("pan");
396 break;
397 case GEN_ATTENUATION:
398 printf("att");
399 break;
400 default:
401 printf("dest %i", ldest);
402 break;
403 } /* switch dest */
404 printf(", amount %f flags %i src2 %i flags2 %i\n",lamount, lflags1, lsrc2, lflags2);
405 }
406
407 }
408