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_chan.h"
22 #include "fluid_mod.h"
23 #include "fluid_synth.h"
24 #include "fluid_sfont.h"
25
26 /* Field shift amounts for sfont_bank_prog bit field integer */
27 #define PROG_SHIFTVAL 0
28 #define BANK_SHIFTVAL 8
29 #define SFONT_SHIFTVAL 22
30
31 /* Field mask values for sfont_bank_prog bit field integer */
32 #define PROG_MASKVAL 0x000000FF /* Bit 7 is used to indicate unset state */
33 #define BANK_MASKVAL 0x003FFF00
34 #define BANKLSB_MASKVAL 0x00007F00
35 #define BANKMSB_MASKVAL 0x003F8000
36 #define SFONT_MASKVAL 0xFFC00000
37
38
39 static void fluid_channel_init(fluid_channel_t *chan);
40
41
42 fluid_channel_t *
new_fluid_channel(fluid_synth_t * synth,int num)43 new_fluid_channel(fluid_synth_t *synth, int num)
44 {
45 fluid_channel_t *chan;
46
47 chan = FLUID_NEW(fluid_channel_t);
48
49 if(chan == NULL)
50 {
51 FLUID_LOG(FLUID_ERR, "Out of memory");
52 return NULL;
53 }
54
55 chan->synth = synth;
56 chan->channum = num;
57 chan->preset = NULL;
58 chan->tuning = NULL;
59
60 fluid_channel_init(chan);
61 fluid_channel_init_ctrl(chan, 0);
62
63 return chan;
64 }
65
66 static void
fluid_channel_init(fluid_channel_t * chan)67 fluid_channel_init(fluid_channel_t *chan)
68 {
69 fluid_preset_t *newpreset;
70 int i, prognum, banknum;
71
72 chan->sostenuto_orderid = 0;
73 /*--- Init poly/mono modes variables --------------------------------------*/
74 chan->mode = 0;
75 chan->mode_val = 0;
76
77 /* monophonic list initialization */
78 for(i = 0; i < FLUID_CHANNEL_SIZE_MONOLIST; i++)
79 {
80 chan->monolist[i].next = i + 1;
81 }
82
83 chan->monolist[FLUID_CHANNEL_SIZE_MONOLIST - 1].next = 0; /* ending element chained to the 1st */
84 chan->i_last = chan->n_notes = 0; /* clears the list */
85 chan->i_first = chan->monolist[chan->i_last].next; /* first note index in the list */
86 fluid_channel_clear_prev_note(chan); /* Mark previous note invalid */
87 /*---*/
88 chan->key_mono_sustained = INVALID_NOTE; /* No previous mono note sustained */
89 chan->legatomode = FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER; /* Default mode */
90 chan->portamentomode = FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY; /* Default mode */
91 /*--- End of poly/mono initialization --------------------------------------*/
92
93 chan->channel_type = (chan->channum == 9) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;
94 prognum = 0;
95 banknum = (chan->channel_type == CHANNEL_TYPE_DRUM) ? DRUM_INST_BANK : 0;
96
97 chan->sfont_bank_prog = 0 << SFONT_SHIFTVAL | banknum << BANK_SHIFTVAL
98 | prognum << PROG_SHIFTVAL;
99
100 newpreset = fluid_synth_find_preset(chan->synth, banknum, prognum);
101 fluid_channel_set_preset(chan, newpreset);
102
103 chan->interp_method = FLUID_INTERP_DEFAULT;
104 chan->tuning_bank = 0;
105 chan->tuning_prog = 0;
106 chan->nrpn_select = 0;
107 chan->nrpn_active = 0;
108
109 if(chan->tuning)
110 {
111 fluid_tuning_unref(chan->tuning, 1);
112 chan->tuning = NULL;
113 }
114 }
115
116 /*
117 @param is_all_ctrl_off if nonzero, only resets some controllers, according to
118 https://www.midi.org/techspecs/rp15.php
119 */
120 void
fluid_channel_init_ctrl(fluid_channel_t * chan,int is_all_ctrl_off)121 fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off)
122 {
123 int i;
124
125 chan->channel_pressure = 0;
126 chan->pitch_bend = 0x2000; /* Range is 0x4000, pitch bend wheel starts in centered position */
127
128 for(i = 0; i < GEN_LAST; i++)
129 {
130 chan->gen[i] = 0.0f;
131 }
132
133 if(is_all_ctrl_off)
134 {
135 for(i = 0; i < ALL_SOUND_OFF; i++)
136 {
137 if(i >= EFFECTS_DEPTH1 && i <= EFFECTS_DEPTH5)
138 {
139 continue;
140 }
141
142 if(i >= SOUND_CTRL1 && i <= SOUND_CTRL10)
143 {
144 continue;
145 }
146
147 if(i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB ||
148 i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB ||
149 i == BALANCE_MSB || i == BALANCE_LSB
150 )
151 {
152 continue;
153 }
154
155 fluid_channel_set_cc(chan, i, 0);
156 }
157 }
158 else
159 {
160 for(i = 0; i < 128; i++)
161 {
162 fluid_channel_set_cc(chan, i, 0);
163 }
164
165 fluid_channel_clear_portamento(chan); /* Clear PTC receive */
166 chan->previous_cc_breath = 0;/* Reset previous breath */
167 }
168
169 /* Reset polyphonic key pressure on all voices */
170 for(i = 0; i < 128; i++)
171 {
172 fluid_channel_set_key_pressure(chan, i, 0);
173 }
174
175 /* Set RPN controllers to NULL state */
176 fluid_channel_set_cc(chan, RPN_LSB, 127);
177 fluid_channel_set_cc(chan, RPN_MSB, 127);
178
179 /* Set NRPN controllers to NULL state */
180 fluid_channel_set_cc(chan, NRPN_LSB, 127);
181 fluid_channel_set_cc(chan, NRPN_MSB, 127);
182
183 /* Expression (MSB & LSB) */
184 fluid_channel_set_cc(chan, EXPRESSION_MSB, 127);
185 fluid_channel_set_cc(chan, EXPRESSION_LSB, 127);
186
187 if(!is_all_ctrl_off)
188 {
189
190 chan->pitch_wheel_sensitivity = 2; /* two semi-tones */
191
192 /* Just like panning, a value of 64 indicates no change for sound ctrls */
193 for(i = SOUND_CTRL1; i <= SOUND_CTRL10; i++)
194 {
195 fluid_channel_set_cc(chan, i, 64);
196 }
197
198 /* Volume / initial attenuation (MSB & LSB) */
199 fluid_channel_set_cc(chan, VOLUME_MSB, 100);
200 fluid_channel_set_cc(chan, VOLUME_LSB, 0);
201
202 /* Pan (MSB & LSB) */
203 fluid_channel_set_cc(chan, PAN_MSB, 64);
204 fluid_channel_set_cc(chan, PAN_LSB, 0);
205
206 /* Balance (MSB & LSB) */
207 fluid_channel_set_cc(chan, BALANCE_MSB, 64);
208 fluid_channel_set_cc(chan, BALANCE_LSB, 0);
209
210 /* Reverb */
211 /* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
212 /* Note: although XG standard specifies the default amount of reverb to
213 be 40, most people preferred having it at zero.
214 See https://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */
215 }
216 }
217
218 /* Only called by delete_fluid_synth(), so no need to queue a preset free event */
219 void
delete_fluid_channel(fluid_channel_t * chan)220 delete_fluid_channel(fluid_channel_t *chan)
221 {
222 fluid_return_if_fail(chan != NULL);
223
224 FLUID_FREE(chan);
225 }
226
227 void
fluid_channel_reset(fluid_channel_t * chan)228 fluid_channel_reset(fluid_channel_t *chan)
229 {
230 fluid_channel_init(chan);
231 fluid_channel_init_ctrl(chan, 0);
232 }
233
234 /* Should only be called from synthesis context */
235 int
fluid_channel_set_preset(fluid_channel_t * chan,fluid_preset_t * preset)236 fluid_channel_set_preset(fluid_channel_t *chan, fluid_preset_t *preset)
237 {
238 fluid_sfont_t *sfont;
239
240 if(chan->preset == preset)
241 {
242 return FLUID_OK;
243 }
244
245 if(chan->preset)
246 {
247 sfont = chan->preset->sfont;
248 sfont->refcount--;
249 }
250
251 fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
252
253 chan->preset = preset;
254
255 if(preset)
256 {
257 sfont = preset->sfont;
258 sfont->refcount++;
259 }
260
261 fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum);
262
263 return FLUID_OK;
264 }
265
266 /* Set SoundFont ID, MIDI bank and/or program. Use -1 to use current value. */
267 void
fluid_channel_set_sfont_bank_prog(fluid_channel_t * chan,int sfontnum,int banknum,int prognum)268 fluid_channel_set_sfont_bank_prog(fluid_channel_t *chan, int sfontnum,
269 int banknum, int prognum)
270 {
271 int oldval, newval, oldmask;
272
273 newval = ((sfontnum != -1) ? sfontnum << SFONT_SHIFTVAL : 0)
274 | ((banknum != -1) ? banknum << BANK_SHIFTVAL : 0)
275 | ((prognum != -1) ? prognum << PROG_SHIFTVAL : 0);
276
277 oldmask = ((sfontnum != -1) ? 0 : SFONT_MASKVAL)
278 | ((banknum != -1) ? 0 : BANK_MASKVAL)
279 | ((prognum != -1) ? 0 : PROG_MASKVAL);
280
281 oldval = chan->sfont_bank_prog;
282 newval = (newval & ~oldmask) | (oldval & oldmask);
283 chan->sfont_bank_prog = newval;
284 }
285
286 /* Set bank LSB 7 bits */
287 void
fluid_channel_set_bank_lsb(fluid_channel_t * chan,int banklsb)288 fluid_channel_set_bank_lsb(fluid_channel_t *chan, int banklsb)
289 {
290 int oldval, newval, style;
291
292 style = chan->synth->bank_select;
293
294 if(style == FLUID_BANK_STYLE_GM ||
295 style == FLUID_BANK_STYLE_GS)
296 {
297 return; /* ignored */
298 }
299
300 oldval = chan->sfont_bank_prog;
301
302 if(style == FLUID_BANK_STYLE_XG)
303 {
304 newval = (oldval & ~BANK_MASKVAL) | (banklsb << BANK_SHIFTVAL);
305 }
306 else /* style == FLUID_BANK_STYLE_MMA */
307 {
308 newval = (oldval & ~BANKLSB_MASKVAL) | (banklsb << BANK_SHIFTVAL);
309 }
310
311 chan->sfont_bank_prog = newval;
312 }
313
314 /* Set bank MSB 7 bits */
315 void
fluid_channel_set_bank_msb(fluid_channel_t * chan,int bankmsb)316 fluid_channel_set_bank_msb(fluid_channel_t *chan, int bankmsb)
317 {
318 int oldval, newval, style;
319
320 style = chan->synth->bank_select;
321
322 if(style == FLUID_BANK_STYLE_XG)
323 {
324 /* XG bank, do drum-channel auto-switch */
325 /* The number "120" was based on several keyboards having drums at 120 - 127,
326 reference: https://lists.nongnu.org/archive/html/fluid-dev/2011-02/msg00003.html */
327 chan->channel_type = (120 <= bankmsb) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;
328 return;
329 }
330
331 if(style == FLUID_BANK_STYLE_GM ||
332 chan->channel_type == CHANNEL_TYPE_DRUM)
333 {
334 return; /* ignored */
335 }
336
337 oldval = chan->sfont_bank_prog;
338
339 if(style == FLUID_BANK_STYLE_GS)
340 {
341 newval = (oldval & ~BANK_MASKVAL) | (bankmsb << BANK_SHIFTVAL);
342 }
343 else /* style == FLUID_BANK_STYLE_MMA */
344 {
345 newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7));
346 }
347
348 chan->sfont_bank_prog = newval;
349
350 }
351
352 /* Get SoundFont ID, MIDI bank and/or program. Use NULL to ignore a value. */
353 void
fluid_channel_get_sfont_bank_prog(fluid_channel_t * chan,int * sfont,int * bank,int * prog)354 fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont,
355 int *bank, int *prog)
356 {
357 int sfont_bank_prog;
358
359 sfont_bank_prog = chan->sfont_bank_prog;
360
361 if(sfont)
362 {
363 *sfont = (sfont_bank_prog & SFONT_MASKVAL) >> SFONT_SHIFTVAL;
364 }
365
366 if(bank)
367 {
368 *bank = (sfont_bank_prog & BANK_MASKVAL) >> BANK_SHIFTVAL;
369 }
370
371 if(prog)
372 {
373 *prog = (sfont_bank_prog & PROG_MASKVAL) >> PROG_SHIFTVAL;
374 }
375 }
376
377 /**
378 * Updates legato/ staccato playing state
379 * The function is called:
380 * - on noteon before adding a note into the monolist.
381 * - on noteoff after removing a note out of the monolist.
382 * @param chan fluid_channel_t.
383 */
384 static void
fluid_channel_update_legato_staccato_state(fluid_channel_t * chan)385 fluid_channel_update_legato_staccato_state(fluid_channel_t *chan)
386 {
387 /* Updates legato/ staccato playing state */
388 if(chan->n_notes)
389 {
390 chan->mode |= FLUID_CHANNEL_LEGATO_PLAYING; /* Legato state */
391 }
392 else
393 {
394 chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */
395 }
396 }
397
398 /**
399 * Adds a note into the monophonic list. The function is part of the legato
400 * detector. fluid_channel_add_monolist() is intended to be called by
401 * fluid_synth_noteon_mono_LOCAL().
402 *
403 * When a note is added at noteOn each element is use in the forward direction
404 * and indexed by i_last variable.
405 *
406 * @param chan fluid_channel_t.
407 * @param key MIDI note number (0-127).
408 * @param vel MIDI velocity (0-127, 0=noteoff).
409 * @param onenote. When 1 the function adds the note but the monophonic list
410 * keeps only one note (used on noteOn poly).
411 * Note: i_last index keeps a trace of the most recent note added.
412 * prev_note keeps a trace of the note prior i_last note.
413 * FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing state.
414 *
415 * More information in FluidPolyMono-0004.pdf chapter 4 (Appendices).
416 */
417 void
fluid_channel_add_monolist(fluid_channel_t * chan,unsigned char key,unsigned char vel,unsigned char onenote)418 fluid_channel_add_monolist(fluid_channel_t *chan, unsigned char key,
419 unsigned char vel, unsigned char onenote)
420 {
421 unsigned char i_last = chan->i_last;
422 /* Updates legato/ staccato playing state */
423 fluid_channel_update_legato_staccato_state(chan);
424
425 if(chan->n_notes)
426 {
427 /* keeps trace of the note prior last note */
428 chan->prev_note = chan->monolist[i_last].note;
429 }
430
431 /* moves i_last forward before writing new note */
432 i_last = chan->monolist[i_last].next;
433 chan->i_last = i_last; /* now ilast indexes the last note */
434 chan->monolist[i_last].note = key; /* we save note and velocity */
435 chan->monolist[i_last].vel = vel;
436
437 if(onenote)
438 {
439 /* clears monolist before one note addition */
440 chan->i_first = i_last;
441 chan->n_notes = 0;
442 }
443
444 if(chan->n_notes < FLUID_CHANNEL_SIZE_MONOLIST)
445 {
446 chan->n_notes++; /* updates n_notes */
447 }
448 else
449 {
450 /* The end of buffer is reach. So circular motion for i_first */
451 /* i_first index is moved forward */
452 chan->i_first = chan->monolist[i_last].next;
453 }
454 }
455
456 /**
457 * Searching a note in the monophonic list. The function is part of the legato
458 * detector. fluid_channel_search_monolist() is intended to be called by
459 * fluid_synth_noteoff_mono_LOCAL().
460 *
461 * The search starts from the first note in the list indexed by i_first
462
463 * @param chan fluid_channel_t.
464 * @param key MIDI note number (0-127) to search.
465 * @param i_prev pointer on returned index of the note prior the note to search.
466 * @return index of the note if find, FLUID_FAILED otherwise.
467 *
468 */
469 int
fluid_channel_search_monolist(fluid_channel_t * chan,unsigned char key,int * i_prev)470 fluid_channel_search_monolist(fluid_channel_t *chan, unsigned char key, int *i_prev)
471 {
472 short n = chan->n_notes; /* number of notes in monophonic list */
473 short j, i = chan->i_first; /* searching starts from i_first included */
474
475 for(j = 0 ; j < n ; j++)
476 {
477 if(chan->monolist[i].note == key)
478 {
479 if(i == chan->i_first)
480 {
481 /* tracking index of the previous note (i_prev) */
482 for(j = chan->i_last ; n < FLUID_CHANNEL_SIZE_MONOLIST; n++)
483 {
484 j = chan->monolist[j].next;
485 }
486
487 * i_prev = j; /* returns index of the previous note */
488 }
489
490 return i; /* returns index of the note to search */
491 }
492
493 * i_prev = i; /* tracking index of the previous note (i_prev) */
494 i = chan->monolist[i].next; /* next element */
495 }
496
497 return FLUID_FAILED; /* not found */
498 }
499
500 /**
501 * removes a note from the monophonic list. The function is part of
502 * the legato detector.
503 * fluid_channel_remove_monolist() is intended to be called by
504 * fluid_synth_noteoff_mono_LOCAL().
505 *
506 * When a note is removed at noteOff the element concerned is fast unlinked
507 * and relinked after the i_last element.
508 *
509 * @param chan fluid_channel_t.
510 * @param
511 * i, index of the note to remove. If i is invalid or the list is
512 * empty, the function do nothing and returns FLUID_FAILED.
513 * @param
514 * On input, i_prev is a pointer on index of the note previous i.
515 * On output i_prev is a pointer on index of the note previous i if i is the last note
516 * in the list,FLUID_FAILED otherwise. When the returned index is valid it means
517 * a legato detection on noteoff.
518 *
519 * Note: the following variables in Channel keeps trace of the situation.
520 * - i_last index keeps a trace of the most recent note played even if
521 * the list is empty.
522 * - prev_note keeps a trace of the note removed if it is i_last.
523 * - FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing state.
524 *
525 * More information in FluidPolyMono-0004.pdf chapter 4 (Appendices).
526 */
527 void
fluid_channel_remove_monolist(fluid_channel_t * chan,int i,int * i_prev)528 fluid_channel_remove_monolist(fluid_channel_t *chan, int i, int *i_prev)
529 {
530 unsigned char i_last = chan->i_last;
531
532 /* checks if index is valid */
533 if(i < 0 || i >= FLUID_CHANNEL_SIZE_MONOLIST || !chan->n_notes)
534 {
535 * i_prev = FLUID_FAILED;
536 }
537
538 /* The element is about to be removed and inserted between i_last and next */
539 /* Note: when i is egal to i_last or egal to i_first, removing/inserting
540 isn't necessary */
541 if(i == i_last)
542 {
543 /* Removing/Inserting isn't necessary */
544 /* keeps trace of the note prior last note */
545 chan->prev_note = chan->monolist[i_last].note;
546 /* moves i_last backward to the previous */
547 chan->i_last = *i_prev; /* i_last index is moved backward */
548 }
549 else
550 {
551 /* i is before i_last */
552 if(i == chan->i_first)
553 {
554 /* Removing/inserting isn't necessary */
555 /* i_first index is moved forward to the next element*/
556 chan->i_first = chan->monolist[i].next;
557 }
558 else
559 {
560 /* i is between i_first and i_last */
561 /* Unlinks element i and inserts after i_last */
562 chan->monolist[* i_prev].next = chan->monolist[i].next; /* unlinks i */
563 /*inserts i after i_last */
564 chan->monolist[i].next = chan->monolist[i_last].next;
565 chan->monolist[i_last].next = i;
566 }
567
568 * i_prev = FLUID_FAILED;
569 }
570
571 chan->n_notes--; /* updates the number of note in the list */
572 /* Updates legato/ staccato playing state */
573 fluid_channel_update_legato_staccato_state(chan);
574 }
575
576 /**
577 * On noteOff on a polyphonic channel,the monophonic list is fully flushed.
578 *
579 * @param chan fluid_channel_t.
580 * Note: i_last index keeps a trace of the most recent note played even if
581 * the list is empty.
582 * prev_note keeps a trace of the note i_last .
583 * FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing.
584 */
fluid_channel_clear_monolist(fluid_channel_t * chan)585 void fluid_channel_clear_monolist(fluid_channel_t *chan)
586 {
587 /* keeps trace off the most recent note played */
588 chan->prev_note = chan->monolist[chan->i_last].note;
589
590 /* flushes the monolist */
591 chan->i_first = chan->monolist[chan->i_last].next;
592 chan->n_notes = 0;
593 /* Update legato/ sataccato playing state */
594 chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */
595 }
596
597 /**
598 * On noteOn on a polyphonic channel,adds the note into the monophonic list
599 * keeping only this note.
600 * @param
601 * chan fluid_channel_t.
602 * key, vel, note and velocity added in the monolist
603 * Note: i_last index keeps a trace of the most recent note inserted.
604 * prev_note keeps a trace of the note prior i_last note.
605 * FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing.
606 */
fluid_channel_set_onenote_monolist(fluid_channel_t * chan,unsigned char key,unsigned char vel)607 void fluid_channel_set_onenote_monolist(fluid_channel_t *chan, unsigned char key,
608 unsigned char vel)
609 {
610 fluid_channel_add_monolist(chan, key, vel, 1);
611 }
612
613 /**
614 * The function changes the state (Valid/Invalid) of the previous note played in
615 * a staccato manner (fluid_channel_prev_note()).
616 * When potamento mode 'each note' or 'staccato only' is selected, on next
617 * noteOn a portamento will be started from the most recent note played
618 * staccato.
619 * It will be possible that it isn't appropriate. To give the musician the
620 * possibility to choose a portamento from this note , prev_note will be forced
621 * to invalid state on noteOff if portamento pedal is Off.
622 *
623 * The function is intended to be called when the following event occurs:
624 * - On noteOff (in poly or mono mode), to mark prev_note invalid.
625 * - On Portamento Off(in poly or mono mode), to mark prev_note invalid.
626 * @param chan fluid_channel_t.
627 */
fluid_channel_invalid_prev_note_staccato(fluid_channel_t * chan)628 void fluid_channel_invalid_prev_note_staccato(fluid_channel_t *chan)
629 {
630 /* checks if the playing is staccato */
631 if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
632 {
633
634 /* checks if portamento pedal is off */
635 if(! fluid_channel_portamento(chan))
636 {
637 /* forces prev_note invalid */
638 fluid_channel_clear_prev_note(chan);
639 }
640 }
641
642 /* else prev_note still remains valid for next fromkey portamento */
643 }
644
645 /**
646 * The function handles poly/mono commutation on legato pedal On/Off.
647 * @param chan fluid_channel_t.
648 * @param value, value of the CC legato.
649 */
fluid_channel_cc_legato(fluid_channel_t * chan,int value)650 void fluid_channel_cc_legato(fluid_channel_t *chan, int value)
651 {
652 /* Special handling of the monophonic list */
653 if(!(chan->mode & FLUID_CHANNEL_POLY_OFF) && chan->n_notes) /* The monophonic list have notes */
654 {
655 if(value < 64) /* legato is released */
656 {
657 /* returns from monophonic to polyphonic with notes in the monophonic list */
658
659 /* The monophonic list is flushed keeping last note only
660 Note: i_last index keeps a trace of the most recent note played.
661 prev_note keeps a trace of the note i_last.
662 FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing.
663 */
664 chan->i_first = chan->i_last;
665 chan->n_notes = 1;
666 }
667 else /* legato is depressed */
668 {
669 /* Inters in monophonic from polyphonic with note in monophonic list */
670 /* Stops the running note to remain coherent with Breath Sync mode */
671 if((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && !fluid_channel_breath_msb(chan))
672 {
673 fluid_synth_noteoff_monopoly(chan->synth, chan->channum,
674 fluid_channel_last_note(chan), 1);
675 }
676 }
677 }
678 }
679
680 /**
681 * The function handles CC Breath On/Off detection. When a channel is in
682 * Breath Sync mode and in monophonic playing, the breath controller allows
683 * to trigger noteon/noteoff note when the musician starts to breath (noteon) and
684 * stops to breath (noteoff).
685 * @param chan fluid_channel_t.
686 * @param value, value of the CC Breath..
687 */
fluid_channel_cc_breath_note_on_off(fluid_channel_t * chan,int value)688 void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value)
689 {
690 if((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && fluid_channel_is_playing_mono(chan) &&
691 (chan->n_notes))
692 {
693 /* The monophonic list isn't empty */
694 if((value > 0) && (chan->previous_cc_breath == 0))
695 {
696 /* CC Breath On detection */
697 fluid_synth_noteon_mono_staccato(chan->synth, chan->channum,
698 fluid_channel_last_note(chan),
699 fluid_channel_last_vel(chan));
700 }
701 else if((value == 0) && (chan->previous_cc_breath > 0))
702 {
703 /* CC Breath Off detection */
704 fluid_synth_noteoff_monopoly(chan->synth, chan->channum,
705 fluid_channel_last_note(chan), 1);
706 }
707 }
708
709 chan->previous_cc_breath = value;
710 }
711