Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/synth/fluid_chan.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_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 *
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
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
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
chan->override_gen_default[i].flags = GEN_UNUSED;
132
chan->override_gen_default[i].val = 0.0f;
133
}
134
// Not all MIDIs initialize the IIR filter coefficient, e.g. Uplift.mid.
135
// A default value is not documented, hence I'm assuming zero here.
136
chan->awe32_filter_coeff = 0;
137
138
if(is_all_ctrl_off)
139
{
140
for(i = 0; i < ALL_SOUND_OFF; i++)
141
{
142
if(i >= EFFECTS_DEPTH1 && i <= EFFECTS_DEPTH5)
143
{
144
continue;
145
}
146
147
if(i >= SOUND_CTRL1 && i <= SOUND_CTRL10)
148
{
149
continue;
150
}
151
152
if(i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB ||
153
i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB ||
154
i == BALANCE_MSB || i == BALANCE_LSB
155
)
156
{
157
continue;
158
}
159
160
fluid_channel_set_cc(chan, i, 0);
161
}
162
}
163
else
164
{
165
for(i = 0; i < 128; i++)
166
{
167
fluid_channel_set_cc(chan, i, 0);
168
}
169
170
chan->previous_cc_breath = 0;/* Reset previous breath */
171
}
172
/* Unconditionally clear PTC receive (issue #1050) */
173
fluid_channel_clear_portamento(chan);
174
175
/* Reset polyphonic key pressure on all voices */
176
for(i = 0; i < 128; i++)
177
{
178
fluid_channel_set_key_pressure(chan, i, 0);
179
}
180
181
/* Set RPN controllers to NULL state */
182
fluid_channel_set_cc(chan, RPN_LSB, 127);
183
fluid_channel_set_cc(chan, RPN_MSB, 127);
184
185
/* Set NRPN controllers to NULL state */
186
fluid_channel_set_cc(chan, NRPN_LSB, 127);
187
fluid_channel_set_cc(chan, NRPN_MSB, 127);
188
189
/* Expression (MSB & LSB) */
190
fluid_channel_set_cc(chan, EXPRESSION_MSB, 127);
191
fluid_channel_set_cc(chan, EXPRESSION_LSB, 127);
192
193
if(!is_all_ctrl_off)
194
{
195
196
chan->pitch_wheel_sensitivity = 2; /* two semi-tones */
197
198
/* Just like panning, a value of 64 indicates no change for sound ctrls */
199
for(i = SOUND_CTRL1; i <= SOUND_CTRL10; i++)
200
{
201
fluid_channel_set_cc(chan, i, 64);
202
}
203
204
/* Volume / initial attenuation (MSB & LSB) */
205
fluid_channel_set_cc(chan, VOLUME_MSB, 100);
206
fluid_channel_set_cc(chan, VOLUME_LSB, 0);
207
208
/* Pan (MSB & LSB) */
209
fluid_channel_set_cc(chan, PAN_MSB, 64);
210
fluid_channel_set_cc(chan, PAN_LSB, 0);
211
212
/* Balance (MSB & LSB) */
213
fluid_channel_set_cc(chan, BALANCE_MSB, 64);
214
fluid_channel_set_cc(chan, BALANCE_LSB, 0);
215
216
/* Reverb */
217
/* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */
218
/* Note: although XG standard specifies the default amount of reverb to
219
be 40, most people preferred having it at zero.
220
See https://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */
221
}
222
}
223
224
/* Only called by delete_fluid_synth(), so no need to queue a preset free event */
225
void
226
delete_fluid_channel(fluid_channel_t *chan)
227
{
228
fluid_return_if_fail(chan != NULL);
229
230
FLUID_FREE(chan);
231
}
232
233
void
234
fluid_channel_reset(fluid_channel_t *chan)
235
{
236
fluid_channel_init(chan);
237
fluid_channel_init_ctrl(chan, 0);
238
}
239
240
/* Should only be called from synthesis context */
241
int
242
fluid_channel_set_preset(fluid_channel_t *chan, fluid_preset_t *preset)
243
{
244
fluid_sfont_t *sfont;
245
246
if(chan->preset == preset)
247
{
248
return FLUID_OK;
249
}
250
251
if(chan->preset)
252
{
253
sfont = chan->preset->sfont;
254
sfont->refcount--;
255
}
256
257
fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum);
258
259
chan->preset = preset;
260
261
if(preset)
262
{
263
sfont = preset->sfont;
264
sfont->refcount++;
265
}
266
267
fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum);
268
269
return FLUID_OK;
270
}
271
272
/* Set SoundFont ID, MIDI bank and/or program. Use -1 to use current value. */
273
void
274
fluid_channel_set_sfont_bank_prog(fluid_channel_t *chan, int sfontnum,
275
int banknum, int prognum)
276
{
277
int oldval, newval, oldmask;
278
279
newval = ((sfontnum != -1) ? sfontnum << SFONT_SHIFTVAL : 0)
280
| ((banknum != -1) ? banknum << BANK_SHIFTVAL : 0)
281
| ((prognum != -1) ? prognum << PROG_SHIFTVAL : 0);
282
283
oldmask = ((sfontnum != -1) ? 0 : SFONT_MASKVAL)
284
| ((banknum != -1) ? 0 : BANK_MASKVAL)
285
| ((prognum != -1) ? 0 : PROG_MASKVAL);
286
287
oldval = chan->sfont_bank_prog;
288
newval = (newval & ~oldmask) | (oldval & oldmask);
289
chan->sfont_bank_prog = newval;
290
}
291
292
/* Set bank LSB 7 bits */
293
void
294
fluid_channel_set_bank_lsb(fluid_channel_t *chan, int banklsb)
295
{
296
int oldval, newval, style;
297
298
style = chan->synth->bank_select;
299
300
if(style == FLUID_BANK_STYLE_GM ||
301
style == FLUID_BANK_STYLE_GS)
302
{
303
return; /* ignored */
304
}
305
306
oldval = chan->sfont_bank_prog;
307
308
if(style == FLUID_BANK_STYLE_XG)
309
{
310
newval = (oldval & ~BANK_MASKVAL) | (banklsb << BANK_SHIFTVAL);
311
}
312
else /* style == FLUID_BANK_STYLE_MMA */
313
{
314
newval = (oldval & ~BANKLSB_MASKVAL) | (banklsb << BANK_SHIFTVAL);
315
}
316
317
chan->sfont_bank_prog = newval;
318
}
319
320
/* Set bank MSB 7 bits */
321
void
322
fluid_channel_set_bank_msb(fluid_channel_t *chan, int bankmsb)
323
{
324
int oldval, newval, style;
325
326
style = chan->synth->bank_select;
327
328
if(style == FLUID_BANK_STYLE_XG)
329
{
330
/* XG bank, do drum-channel auto-switch */
331
/* The number "120" was based on several keyboards having drums at 120 - 127,
332
reference: https://lists.nongnu.org/archive/html/fluid-dev/2011-02/msg00003.html */
333
chan->channel_type = (120 == bankmsb || 126 == bankmsb || 127 == bankmsb) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;
334
return;
335
}
336
337
if(style == FLUID_BANK_STYLE_GM ||
338
chan->channel_type == CHANNEL_TYPE_DRUM)
339
{
340
return; /* ignored */
341
}
342
343
oldval = chan->sfont_bank_prog;
344
345
if(style == FLUID_BANK_STYLE_GS)
346
{
347
newval = (oldval & ~BANK_MASKVAL) | (bankmsb << BANK_SHIFTVAL);
348
}
349
else /* style == FLUID_BANK_STYLE_MMA */
350
{
351
newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7));
352
}
353
354
chan->sfont_bank_prog = newval;
355
356
}
357
358
/* Get SoundFont ID, MIDI bank and/or program. Use NULL to ignore a value. */
359
void
360
fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont,
361
int *bank, int *prog)
362
{
363
int sfont_bank_prog;
364
365
sfont_bank_prog = chan->sfont_bank_prog;
366
367
if(sfont)
368
{
369
*sfont = (sfont_bank_prog & SFONT_MASKVAL) >> SFONT_SHIFTVAL;
370
}
371
372
if(bank)
373
{
374
*bank = (sfont_bank_prog & BANK_MASKVAL) >> BANK_SHIFTVAL;
375
}
376
377
if(prog)
378
{
379
*prog = (sfont_bank_prog & PROG_MASKVAL) >> PROG_SHIFTVAL;
380
}
381
}
382
383
/**
384
* Compute the pitch for a key after applying Fluidsynth's tuning functionality
385
* and channel coarse/fine tunings.
386
* @param chan fluid_channel_t
387
* @param key MIDI note number (0-127)
388
* @return the pitch of the key
389
*/
390
fluid_real_t fluid_channel_get_key_pitch(fluid_channel_t *chan, int key)
391
{
392
if(chan->tuning)
393
{
394
return fluid_tuning_get_pitch(chan->tuning, key)
395
+ 100.0f * fluid_channel_get_gen(chan, GEN_COARSETUNE)
396
+ fluid_channel_get_gen(chan, GEN_FINETUNE);
397
}
398
else
399
{
400
return key * 100.0f;
401
}
402
}
403
404
/**
405
* Updates legato/ staccato playing state
406
* The function is called:
407
* - on noteon before adding a note into the monolist.
408
* - on noteoff after removing a note out of the monolist.
409
* @param chan fluid_channel_t.
410
*/
411
static void
412
fluid_channel_update_legato_staccato_state(fluid_channel_t *chan)
413
{
414
/* Updates legato/ staccato playing state */
415
if(chan->n_notes)
416
{
417
chan->mode |= FLUID_CHANNEL_LEGATO_PLAYING; /* Legato state */
418
}
419
else
420
{
421
chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */
422
}
423
}
424
425
/**
426
* Adds a note into the monophonic list. The function is part of the legato
427
* detector. fluid_channel_add_monolist() is intended to be called by
428
* fluid_synth_noteon_mono_LOCAL().
429
*
430
* When a note is added at noteOn each element is use in the forward direction
431
* and indexed by i_last variable.
432
*
433
* @param chan fluid_channel_t.
434
* @param key MIDI note number (0-127).
435
* @param vel MIDI velocity (0-127, 0=noteoff).
436
* @param onenote. When 1 the function adds the note but the monophonic list
437
* keeps only one note (used on noteOn poly).
438
* Note: i_last index keeps a trace of the most recent note added.
439
* prev_note keeps a trace of the note prior i_last note.
440
* FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing state.
441
*
442
* More information in FluidPolyMono-0004.pdf chapter 4 (Appendices).
443
*/
444
void
445
fluid_channel_add_monolist(fluid_channel_t *chan, unsigned char key,
446
unsigned char vel, unsigned char onenote)
447
{
448
unsigned char i_last = chan->i_last;
449
/* Updates legato/ staccato playing state */
450
fluid_channel_update_legato_staccato_state(chan);
451
452
if(chan->n_notes)
453
{
454
/* keeps trace of the note prior last note */
455
chan->prev_note = chan->monolist[i_last].note;
456
}
457
458
/* moves i_last forward before writing new note */
459
i_last = chan->monolist[i_last].next;
460
chan->i_last = i_last; /* now ilast indexes the last note */
461
chan->monolist[i_last].note = key; /* we save note and velocity */
462
chan->monolist[i_last].vel = vel;
463
464
if(onenote)
465
{
466
/* clears monolist before one note addition */
467
chan->i_first = i_last;
468
chan->n_notes = 0;
469
}
470
471
if(chan->n_notes < FLUID_CHANNEL_SIZE_MONOLIST)
472
{
473
chan->n_notes++; /* updates n_notes */
474
}
475
else
476
{
477
/* The end of buffer is reach. So circular motion for i_first */
478
/* i_first index is moved forward */
479
chan->i_first = chan->monolist[i_last].next;
480
}
481
}
482
483
/**
484
* Searching a note in the monophonic list. The function is part of the legato
485
* detector. fluid_channel_search_monolist() is intended to be called by
486
* fluid_synth_noteoff_mono_LOCAL().
487
*
488
* The search starts from the first note in the list indexed by i_first
489
490
* @param chan fluid_channel_t.
491
* @param key MIDI note number (0-127) to search.
492
* @param i_prev pointer on returned index of the note prior the note to search.
493
* @return index of the note if find, FLUID_FAILED otherwise.
494
*
495
*/
496
int
497
fluid_channel_search_monolist(fluid_channel_t *chan, unsigned char key, int *i_prev)
498
{
499
short n = chan->n_notes; /* number of notes in monophonic list */
500
short j, i = chan->i_first; /* searching starts from i_first included */
501
502
for(j = 0 ; j < n ; j++)
503
{
504
if(chan->monolist[i].note == key)
505
{
506
if(i == chan->i_first)
507
{
508
/* tracking index of the previous note (i_prev) */
509
for(j = chan->i_last ; n < FLUID_CHANNEL_SIZE_MONOLIST; n++)
510
{
511
j = chan->monolist[j].next;
512
}
513
514
* i_prev = j; /* returns index of the previous note */
515
}
516
517
return i; /* returns index of the note to search */
518
}
519
520
* i_prev = i; /* tracking index of the previous note (i_prev) */
521
i = chan->monolist[i].next; /* next element */
522
}
523
524
return FLUID_FAILED; /* not found */
525
}
526
527
/**
528
* removes a note from the monophonic list. The function is part of
529
* the legato detector.
530
* fluid_channel_remove_monolist() is intended to be called by
531
* fluid_synth_noteoff_mono_LOCAL().
532
*
533
* When a note is removed at noteOff the element concerned is fast unlinked
534
* and relinked after the i_last element.
535
*
536
* @param chan fluid_channel_t.
537
* @param
538
* i, index of the note to remove. If i is invalid or the list is
539
* empty, the function do nothing and returns FLUID_FAILED.
540
* @param
541
* On input, i_prev is a pointer on index of the note previous i.
542
* On output i_prev is a pointer on index of the note previous i if i is the last note
543
* in the list,FLUID_FAILED otherwise. When the returned index is valid it means
544
* a legato detection on noteoff.
545
*
546
* Note: the following variables in Channel keeps trace of the situation.
547
* - i_last index keeps a trace of the most recent note played even if
548
* the list is empty.
549
* - prev_note keeps a trace of the note removed if it is i_last.
550
* - FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing state.
551
*
552
* More information in FluidPolyMono-0004.pdf chapter 4 (Appendices).
553
*/
554
void
555
fluid_channel_remove_monolist(fluid_channel_t *chan, int i, int *i_prev)
556
{
557
unsigned char i_last = chan->i_last;
558
559
/* checks if index is valid */
560
if(i < 0 || i >= FLUID_CHANNEL_SIZE_MONOLIST || !chan->n_notes)
561
{
562
* i_prev = FLUID_FAILED;
563
}
564
565
/* The element is about to be removed and inserted between i_last and next */
566
/* Note: when i is egal to i_last or egal to i_first, removing/inserting
567
isn't necessary */
568
if(i == i_last)
569
{
570
/* Removing/Inserting isn't necessary */
571
/* keeps trace of the note prior last note */
572
chan->prev_note = chan->monolist[i_last].note;
573
/* moves i_last backward to the previous */
574
chan->i_last = *i_prev; /* i_last index is moved backward */
575
}
576
else
577
{
578
/* i is before i_last */
579
if(i == chan->i_first)
580
{
581
/* Removing/inserting isn't necessary */
582
/* i_first index is moved forward to the next element*/
583
chan->i_first = chan->monolist[i].next;
584
}
585
else
586
{
587
/* i is between i_first and i_last */
588
/* Unlinks element i and inserts after i_last */
589
chan->monolist[* i_prev].next = chan->monolist[i].next; /* unlinks i */
590
/*inserts i after i_last */
591
chan->monolist[i].next = chan->monolist[i_last].next;
592
chan->monolist[i_last].next = i;
593
}
594
595
* i_prev = FLUID_FAILED;
596
}
597
598
chan->n_notes--; /* updates the number of note in the list */
599
/* Updates legato/ staccato playing state */
600
fluid_channel_update_legato_staccato_state(chan);
601
}
602
603
/**
604
* On noteOff on a polyphonic channel,the monophonic list is fully flushed.
605
*
606
* @param chan fluid_channel_t.
607
* Note: i_last index keeps a trace of the most recent note played even if
608
* the list is empty.
609
* prev_note keeps a trace of the note i_last .
610
* FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing.
611
*/
612
void fluid_channel_clear_monolist(fluid_channel_t *chan)
613
{
614
/* keeps trace off the most recent note played */
615
chan->prev_note = chan->monolist[chan->i_last].note;
616
617
/* flushes the monolist */
618
chan->i_first = chan->monolist[chan->i_last].next;
619
chan->n_notes = 0;
620
/* Update legato/ sataccato playing state */
621
chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */
622
}
623
624
/**
625
* On noteOn on a polyphonic channel,adds the note into the monophonic list
626
* keeping only this note.
627
* @param
628
* chan fluid_channel_t.
629
* key, vel, note and velocity added in the monolist
630
* Note: i_last index keeps a trace of the most recent note inserted.
631
* prev_note keeps a trace of the note prior i_last note.
632
* FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing.
633
*/
634
void fluid_channel_set_onenote_monolist(fluid_channel_t *chan, unsigned char key,
635
unsigned char vel)
636
{
637
fluid_channel_add_monolist(chan, key, vel, 1);
638
}
639
640
/**
641
* The function changes the state (Valid/Invalid) of the previous note played in
642
* a staccato manner (fluid_channel_prev_note()).
643
* When potamento mode 'each note' or 'staccato only' is selected, on next
644
* noteOn a portamento will be started from the most recent note played
645
* staccato.
646
* It will be possible that it isn't appropriate. To give the musician the
647
* possibility to choose a portamento from this note , prev_note will be forced
648
* to invalid state on noteOff if portamento pedal is Off.
649
*
650
* The function is intended to be called when the following event occurs:
651
* - On noteOff (in poly or mono mode), to mark prev_note invalid.
652
* - On Portamento Off(in poly or mono mode), to mark prev_note invalid.
653
* @param chan fluid_channel_t.
654
*/
655
void fluid_channel_invalid_prev_note_staccato(fluid_channel_t *chan)
656
{
657
/* checks if the playing is staccato */
658
if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
659
{
660
661
/* checks if portamento pedal is off */
662
if(! fluid_channel_portamento(chan))
663
{
664
/* forces prev_note invalid */
665
fluid_channel_clear_prev_note(chan);
666
}
667
}
668
669
/* else prev_note still remains valid for next fromkey portamento */
670
}
671
672
/**
673
* The function handles poly/mono commutation on legato pedal On/Off.
674
* @param chan fluid_channel_t.
675
* @param value, value of the CC legato.
676
*/
677
void fluid_channel_cc_legato(fluid_channel_t *chan, int value)
678
{
679
/* Special handling of the monophonic list */
680
if(!(chan->mode & FLUID_CHANNEL_POLY_OFF) && chan->n_notes) /* The monophonic list have notes */
681
{
682
if(value < 64) /* legato is released */
683
{
684
/* returns from monophonic to polyphonic with notes in the monophonic list */
685
686
/* The monophonic list is flushed keeping last note only
687
Note: i_last index keeps a trace of the most recent note played.
688
prev_note keeps a trace of the note i_last.
689
FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing.
690
*/
691
chan->i_first = chan->i_last;
692
chan->n_notes = 1;
693
}
694
else /* legato is depressed */
695
{
696
/* Inters in monophonic from polyphonic with note in monophonic list */
697
/* Stops the running note to remain coherent with Breath Sync mode */
698
if((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && !fluid_channel_breath_msb(chan))
699
{
700
fluid_synth_noteoff_monopoly(chan->synth, chan->channum,
701
fluid_channel_last_note(chan), 1);
702
}
703
}
704
}
705
}
706
707
/**
708
* The function handles CC Breath On/Off detection. When a channel is in
709
* Breath Sync mode and in monophonic playing, the breath controller allows
710
* to trigger noteon/noteoff note when the musician starts to breath (noteon) and
711
* stops to breath (noteoff).
712
* @param chan fluid_channel_t.
713
* @param value, value of the CC Breath..
714
*/
715
void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value)
716
{
717
if((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && fluid_channel_is_playing_mono(chan) &&
718
(chan->n_notes))
719
{
720
/* The monophonic list isn't empty */
721
if((value > 0) && (chan->previous_cc_breath == 0))
722
{
723
/* CC Breath On detection */
724
fluid_synth_noteon_mono_staccato(chan->synth, chan->channum,
725
fluid_channel_last_note(chan),
726
fluid_channel_last_vel(chan));
727
}
728
else if((value == 0) && (chan->previous_cc_breath > 0))
729
{
730
/* CC Breath Off detection */
731
fluid_synth_noteoff_monopoly(chan->synth, chan->channum,
732
fluid_channel_last_note(chan), 1);
733
}
734
}
735
736
chan->previous_cc_breath = value;
737
}
738
739
int fluid_channel_get_override_gen_default(fluid_channel_t *chan, int gen, fluid_real_t* val)
740
{
741
if(chan->override_gen_default[gen].flags != GEN_UNUSED)
742
{
743
*val = chan->override_gen_default[gen].val;
744
return TRUE;
745
}
746
747
return FALSE;
748
}
749
750
void fluid_channel_set_override_gen_default(fluid_channel_t *chan, int gen, fluid_real_t val)
751
{
752
chan->override_gen_default[gen].flags = GEN_SET;
753
chan->override_gen_default[gen].val = val;
754
}
755
756