Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/synth/fluid_synth_monopoly.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_synth.h"
22
#include "fluid_chan.h"
23
#include "fluid_defsfont.h"
24
25
26
/******************************************************************************
27
The legato detector is composed as this,
28
variables:
29
- monolist: monophonic list variable.
30
- prev_note: to store the most recent note before adding on noteon or before
31
removing on noteoff.
32
- FLUID_CHANNEL_LEGATO_PLAYING: legato/staccato state bit that informs on
33
legato or staccato playing.
34
functions:
35
- fluid_channel_add_monolist(), for inserting a new note.
36
- fluid_channel_search_monolist(), for searching the position of a note
37
into the list.
38
- fluid_channel_remove_monolist(), for removing a note from the list.
39
40
The monophonic list
41
+------------------------------------------------+
42
| +----+ +----+ +----+ +----+ |
43
| |note| |note| |note| |note| |
44
+--->|vel |-->|vel |-->....-->|vel |-->|vel |----+
45
+----+ +----+ +----+ +----+
46
/|\ /|\
47
| |
48
i_first i_last
49
50
The list allows an easy automatic detection of a legato passage when it is
51
played on a MIDI keyboard input device.
52
It is useful also when the input device is an ewi (electronic wind instrument)
53
or evi (electronic valve instrument) and these instruments are unable to send
54
MIDI CC legato on/off.
55
56
The list memorizes the notes in playing order.
57
- (a) On noteOn n2, if a previous note n1 exists, there is a legato
58
detection with n1 (with or without portamento from n1 to n2 See note below).
59
- (b) On noteOff of the running note n2, if a previous note n1 exists,
60
there is a legato detection from n2 to n1, allowing fast trills playing
61
(with or without portamento from n2 to n1. See note below).
62
63
Notes in the list are inserted to the end of the list that works like a
64
circular buffer.The features are:
65
66
1) It is always possible to play an infinite legato passage in
67
direct order (n1_On,n2_On,n3_On,....).
68
69
2) Playing legato in the reverse order (n10_Off, n9_Off,,...) helps in
70
fast trills playing as the list memorizes 10 most recent notes.
71
72
3) Playing an infinite lagato passage in ascendant or descendant order,
73
without playing trills is always possible using the usual way like this:
74
First we begin with an ascendant passage,
75
n1On, (n2On,n1Off), (n3On,n2Off) , (n4On,n3Off), then
76
we continue with a descendant passage
77
(n3On,n4off), (n2On,n3off), (n1On,n2off), n1Off...and so on
78
79
Each MIDI channel have a legato detector.
80
81
Note:
82
Portamento is a feature independent of the legato detector. So
83
portamento isn't part of the lagato detector. However portamento
84
(when enabled) is triggered at noteOn (like legato). Like in legato
85
situation it is usual to have a portamento from a note 'fromkey' to another
86
note 'tokey'. Portamento fromkey note choice is determined at noteOn by
87
fluid_synth_get_fromkey_portamento_legato() (see below).
88
89
More information in FluidPolyMono-0004.pdf chapter 4 (Appendices).
90
******************************************************************************/
91
92
93
/*****************************************************************************
94
Portamento related functions in Poly or Mono mode
95
******************************************************************************/
96
97
/**
98
* fluid_synth_get_fromkey_portamento_legato returns two information:
99
* - fromkey note for portamento.
100
* - fromkey note for legato.
101
* +-----> fromkey_portamento
102
* ______|________
103
* portamento modes >------->| |
104
* | get_fromkey |
105
* Porta.on/off >------------------------->|_______________|
106
* (PTC) |
107
* +-----> fromkey_legato
108
*
109
* The functions is intended to be call on noteOn mono
110
* see fluid_synth_noteon_mono_staccato(), fluid_synth_noteon_monopoly_legato()
111
* -------
112
* 1)The function determines if a portamento must occur on next noteOn.
113
* The value returned is 'fromkey portamento' which is the pitchstart key
114
* of a portamento, as function of PTC or (default_fromkey, prev_note) both
115
* if Portamento On. By order of precedence the result is:
116
* 1.1) PTC have precedence over Portamento On.
117
* If CC PTC has been received, its value supersedes and any
118
* portamento pedal On, default_fromkey,prev_note or portamento mode.
119
* 1.2) Otherwise ,when Portamento On the function takes the following value:
120
* - default_fromkey if valid
121
* - otherwise prev_note(prev_note is the note prior the most recent
122
* note played).
123
* Then portamento mode is applied to validate the value chosen.
124
* Where portamento mode is:
125
* - each note, a portamento occurs on each note.
126
* - legato only, portamento only on notes played legato.
127
* - staccato only, portamento only on notes played staccato.
128
* 1.3) Otherwise, portamento is off,INVALID_NOTE is returned (portamento is disabled).
129
* ------
130
* 2)The function determines if a legato playing must occur on next noteOn.
131
* 'fromkey legato note' is returned as a function of default_fromkey, PTC,
132
* current mono/poly mode,actual 'staccato/legato' playing state and prev_note.
133
* By order of precedence the result is:
134
* 2.1) If valid, default_fromkey have precedence over any others values.
135
* 2.2) Otherwise if CC PTC has been received its value is returned.
136
* 2.3) Otherwise fromkey legato is determined from the mono/poly mode,
137
* the actual 'staccato/legato' playing state (FLUID_CHANNEL_LEGATO_PLAYING) and prev_note
138
* as this:
139
* - in (poly/Mono) staccato , INVALID_NOTE is returned.
140
* - in poly legato , actually we don't want playing legato. So
141
* INVALID_NOTE is returned.
142
* - in mono legato , prev_note is returned.
143
*
144
* On input
145
* @param chan fluid_channel_t.
146
* @param defaultFromkey, the default 'fromkey portamento' note or 'fromkey legato'
147
* note (see description above).
148
*
149
* @return
150
* 1)'fromkey portamento' is returned in fluid_synth_t.fromkey_portamento.
151
* If valid,it means that portamento is enabled .
152
*
153
* 2)The 'fromkey legato' note is returned.
154
*
155
* Notes about usage:
156
* The function is intended to be called when the following event occurs:
157
* - On noteOn (Poly or Mono) after insertion in the monophonic list.
158
* - On noteOff(mono legato playing). In this case, default_fromkey must be valid.
159
*
160
* Typical calling usage:
161
* - In poly, default_fromkey must be INVALID_NOTE.
162
* - In mono staccato playing,default_fromkey must be INVALID_NOTE.
163
* - In mono legato playing,default_fromkey must be valid.
164
*/
165
static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t *chan,
166
int default_fromkey)
167
{
168
unsigned char ptc = fluid_channel_get_cc(chan, PORTAMENTO_CTRL);
169
170
if(fluid_channel_is_valid_note(ptc))
171
{
172
/* CC PTC has been received */
173
fluid_channel_clear_portamento(chan); /* clears the CC PTC receive */
174
chan->synth->fromkey_portamento = ptc;/* returns fromkey portamento */
175
176
/* returns fromkey legato */
177
if(!fluid_channel_is_valid_note(default_fromkey))
178
{
179
default_fromkey = ptc;
180
}
181
}
182
else
183
{
184
/* determines and returns fromkey portamento */
185
unsigned char fromkey_portamento = INVALID_NOTE;
186
187
if(fluid_channel_portamento(chan))
188
{
189
/* Portamento when Portamento pedal is On */
190
/* 'fromkey portamento'is determined from the portamento mode
191
and the most recent note played (prev_note)*/
192
enum fluid_channel_portamento_mode portamentomode = chan->portamentomode;
193
194
if(fluid_channel_is_valid_note(default_fromkey))
195
{
196
fromkey_portamento = default_fromkey; /* on each note */
197
}
198
else
199
{
200
fromkey_portamento = fluid_channel_prev_note(chan); /* on each note */
201
}
202
203
if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY)
204
{
205
/* Mode portamento:legato only */
206
if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
207
{
208
fromkey_portamento = INVALID_NOTE;
209
}
210
}
211
else if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY)
212
{
213
/* Mode portamento:staccato only */
214
if(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)
215
{
216
fromkey_portamento = INVALID_NOTE;
217
}
218
}
219
220
/* else Mode portamento: on each note (staccato/legato) */
221
}
222
223
/* Returns fromkey portamento */
224
chan->synth->fromkey_portamento = fromkey_portamento;
225
226
/* Determines and returns fromkey legato */
227
if(!fluid_channel_is_valid_note(default_fromkey))
228
{
229
/* in staccato (poly/Mono) returns INVALID_NOTE */
230
/* In mono mode legato playing returns the note prior most
231
recent note played */
232
if(fluid_channel_is_playing_mono(chan) && (chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
233
{
234
default_fromkey = fluid_channel_prev_note(chan); /* note prior last note */
235
}
236
237
/* In poly mode legato playing, actually we don't want playing legato.
238
So returns INVALID_NOTE */
239
}
240
}
241
242
return default_fromkey; /* Returns legato fromkey */
243
}
244
245
/*****************************************************************************
246
noteon - noteoff functions in Mono mode
247
******************************************************************************/
248
/*
249
* noteon - noteoff on a channel in "monophonic playing".
250
*
251
* A channel needs to be played monophonic if this channel has been set in
252
* monophonic mode by basic channel API.(see fluid_synth_polymono.c).
253
* A channel needs also to be played monophonic if it has been set in
254
* polyphonic mode and legato pedal is On during the playing.
255
* When a channel is in "monophonic playing" state, only one note at a time can be
256
* played in a staccato or legato manner (with or without portamento).
257
* More information in FluidPolyMono-0004.pdf chapter 4 (Appendices).
258
* _______________
259
* ________________ | noteon |
260
* | legato detector| O-->| mono_staccato |--*-> preset_noteon
261
* noteon_mono ->| (add_monolist) |--O-- |_______________| | (with or without)
262
* LOCAL |________________| O /|\ | (portamento)
263
* /|\ set_onenote | | fromkey |
264
* | | | portamento|
265
* noteOn poly >---*------------------* | |
266
* | | |
267
* | _____ |________ |
268
* portamento modes >--- | ->| | |
269
* | | get_fromkey | |
270
* Porta.on/off >--------------------- | ->|_______________| |
271
* (PTC) | | |
272
* | fromkey | fromkey |
273
* | legato | portamento|
274
* | _____\|/_______ |
275
* *-->| noteon |--/
276
* | | monopoly |
277
* | | legato |----> voices
278
* legato modes >------- | ->|_______________| triggering
279
* | (with or without)
280
* | (portamento)
281
* |
282
* |
283
* noteOff poly >---*----------------- | ---------+
284
* | clear | |
285
* _\|/_____________ | |
286
* | legato detector | O |
287
* noteoff_mono->|(search_monolist)|-O-- _____\|/_______
288
* LOCAL |(remove_monolist)| O-->| noteoff |
289
* |_________________| | monopoly |----> noteoff
290
* Sust.on/off >------------------------->|_______________|
291
* Sost.on/off
292
------------------------------------------------------------------------------*/
293
294
/**
295
* Plays a noteon event for a Synth instance in "monophonic playing" state.
296
* Please see the description above about "monophonic playing".
297
* _______________
298
* ________________ | noteon |
299
* | legato detector| O-->| mono_staccato |--->preset_noteon
300
* noteon_mono ->| (add_monolist) |--O-- |_______________|
301
* LOCAL |________________| O
302
* |
303
* |
304
* |
305
* |
306
* |
307
* |
308
* |
309
* |
310
* |
311
* | _______________
312
* | | noteon |
313
* +-->| monopoly |
314
* | legato |---> voices
315
* |_______________| triggering
316
*
317
* The function uses the legato detector (see above) to determine if the note must
318
* be played staccato or legato.
319
*
320
* @param synth instance.
321
* @param chan MIDI channel number (0 to MIDI channel count - 1).
322
* @param key MIDI note number (0-127).
323
* @param vel MIDI velocity (0-127).
324
* @return FLUID_OK on success, FLUID_FAILED otherwise.
325
*/
326
int fluid_synth_noteon_mono_LOCAL(fluid_synth_t *synth, int chan,
327
int key, int vel)
328
{
329
fluid_channel_t *channel = synth->channel[chan];
330
331
/* Adds the note into the monophonic list */
332
fluid_channel_add_monolist(channel, key, vel, 0);
333
334
/* in Breath Sync mode, the noteon triggering is postponed
335
until the musician starts blowing in the breath controller */
336
if(!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) ||
337
fluid_channel_breath_msb(channel))
338
{
339
/* legato/staccato playing detection */
340
if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING)
341
{
342
/* legato playing */
343
/* legato from prev_note to key */
344
/* the voices from prev_note key number are to be used to play key number */
345
/* fromkey must be valid */
346
return fluid_synth_noteon_monopoly_legato(synth, chan,
347
fluid_channel_prev_note(channel), key, vel);
348
}
349
else
350
{
351
/* staccato playing */
352
return fluid_synth_noteon_mono_staccato(synth, chan, key, vel);
353
}
354
}
355
else
356
{
357
return FLUID_OK;
358
}
359
}
360
361
/**
362
* Plays a noteoff event for a Synth instance in "monophonic playing" state.
363
* Please see the description above about "monophonic playing"
364
*
365
* _______________
366
* | noteon |
367
* +-->| monopoly |
368
* | | legato |----> voices
369
* | |_______________| triggering
370
* | (with or without)
371
* | (portamento)
372
* |
373
* |
374
* |
375
* |
376
* |
377
* |
378
* _________________ |
379
* | legato detector | O
380
* noteoff_mono->|(search_monolist)|-O-- _______________
381
* LOCAL |(remove_monolist)| O-->| noteoff |
382
* |_________________| | monopoly |----> noteoff
383
* |_______________|
384
*
385
* The function uses the legato detector (see above) to determine if the noteoff must
386
* be played staccato or legato.
387
*
388
* @param synth instance.
389
* @param chan MIDI channel number (0 to MIDI channel count - 1).
390
* @param key MIDI note number (0-127).
391
* @return FLUID_OK on success, FLUID_FAILED otherwise.
392
*/
393
int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t *synth, int chan, int key)
394
{
395
int status;
396
int i, i_prev;
397
fluid_channel_t *channel = synth->channel[chan];
398
/* searching the note in the monophonic list */
399
i = fluid_channel_search_monolist(channel, key, &i_prev);
400
401
if(i >= 0)
402
{
403
/* the note is in the monophonic list */
404
/* Removes the note from the monophonic list */
405
fluid_channel_remove_monolist(channel, i, &i_prev);
406
407
/* in Breath Sync mode, the noteoff triggering is done
408
if the musician is blowing in the breath controller */
409
if(!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) ||
410
fluid_channel_breath_msb(channel))
411
{
412
/* legato playing detection */
413
if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING)
414
{
415
/* the list contains others notes */
416
if(i_prev >= 0)
417
{
418
/* legato playing detection on noteoff */
419
/* legato from key to i_prev key */
420
/* the voices from key number are to be used to
421
play i_prev key number. */
422
status = fluid_synth_noteon_monopoly_legato(synth, chan,
423
key, channel->monolist[i_prev].note,
424
channel->monolist[i_prev].vel);
425
}
426
/* else the note doesn't need to be played off */
427
else
428
{
429
status = FLUID_OK;
430
}
431
}
432
else
433
{
434
/* the monophonic list is empty */
435
/* plays the monophonic note noteoff and eventually held
436
by sustain/sostenuto */
437
status = fluid_synth_noteoff_monopoly(synth, chan, key, 1);
438
}
439
}
440
else
441
{
442
status = FLUID_OK;
443
}
444
}
445
else
446
{
447
/* the note is not found in the list so the note was
448
played On when the channel was in polyphonic playing */
449
/* plays the noteoff as for polyphonic */
450
status = fluid_synth_noteoff_monopoly(synth, chan, key, 0);
451
}
452
453
return status;
454
}
455
456
/*----------------------------------------------------------------------------
457
staccato playing
458
-----------------------------------------------------------------------------*/
459
/**
460
* Plays noteon for a monophonic note in staccato manner.
461
* Please see the description above about "monophonic playing".
462
* _______________
463
* | noteon |
464
* noteon_mono >------------------------>| mono_staccato |----> preset_noteon
465
* |_______________| (with or without)
466
* LOCAL /|\ (portamento)
467
* | fromkey
468
* | portamento
469
* |
470
* |
471
* ______|________
472
* portamento modes >----->| |
473
* | get_fromkey |
474
* Porta.on/off >----------------------->|_______________|
475
* Portamento
476
* (PTC)
477
*
478
* We are in staccato situation (where no previous note have been depressed).
479
* Before the note been passed to fluid_preset_noteon(), the function must determine
480
* the from_key_portamento parameter used by fluid_preset_noteon().
481
*
482
* from_key_portamento is returned by fluid_synth_get_fromkey_portamento_legato() function.
483
* fromkey_portamento is set to valid/invalid key value depending of the portamento
484
* modes (see portamento mode API) , CC portamento On/Off , and CC portamento control
485
* (PTC).
486
*
487
* @param synth instance.
488
* @param chan MIDI channel number (0 to MIDI channel count - 1).
489
* @param key MIDI note number (0-127).
490
* @param vel MIDI velocity (0-127).
491
* @return FLUID_OK on success, FLUID_FAILED otherwise.
492
*/
493
int
494
fluid_synth_noteon_mono_staccato(fluid_synth_t *synth, int chan, int key, int vel)
495
{
496
fluid_channel_t *channel = synth->channel[chan];
497
498
/* Before playing a new note, if a previous monophonic note is currently
499
sustained it needs to be released */
500
fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, channel->key_mono_sustained);
501
/* Get possible 'fromkey portamento' */
502
fluid_synth_get_fromkey_portamento_legato(channel, INVALID_NOTE);
503
/* The note needs to be played by voices allocation */
504
return fluid_preset_noteon(channel->preset, synth, chan, key, vel);
505
}
506
507
/**
508
* Plays noteoff for a polyphonic or monophonic note
509
* Please see the description above about "monophonic playing".
510
*
511
*
512
* noteOff poly >---------------------------------+
513
* |
514
* |
515
* |
516
* noteoff_mono _____\|/_______
517
* LOCAL >------------------------->| noteoff |
518
* | monopoly |----> noteoff
519
* Sust.on/off >------------------------->|_______________|
520
* Sost.on/off
521
*
522
* The function has the same behaviour when the noteoff is poly of mono, except
523
* that for mono noteoff, if any pedal (sustain or sostenuto ) is depressed, the
524
* key is memorized. This is necessary when the next mono note will be played
525
* staccato, as any current mono note currently sustained will need to be released
526
* (see fluid_synth_noteon_mono_staccato()).
527
* Note also that for a monophonic legato passage, the function is called only when
528
* the last noteoff of the passage occurs. That means that if sustain or sostenuto
529
* is depressed, only the last note of a legato passage will be sustained.
530
*
531
* @param synth instance.
532
* @param chan MIDI channel number (0 to MIDI channel count - 1).
533
* @param key MIDI note number (0-127).
534
* @param Mono, 1 noteoff on monophonic note.
535
* 0 noteoff on polyphonic note.
536
* @return FLUID_OK on success, FLUID_FAILED otherwise.
537
*
538
* Note: On return, on monophonic, possible sustained note is memorized in
539
* key_mono_sustained. Memorization is done here on noteOff.
540
*/
541
int fluid_synth_noteoff_monopoly(fluid_synth_t *synth, int chan, int key,
542
char Mono)
543
{
544
int status = FLUID_FAILED;
545
fluid_voice_t *voice;
546
int i;
547
fluid_channel_t *channel = synth->channel[chan];
548
549
/* Key_sustained is prepared to return no note sustained (INVALID_NOTE) */
550
if(Mono)
551
{
552
channel->key_mono_sustained = INVALID_NOTE; /* no mono note sustained */
553
}
554
555
/* noteoff for all voices with same chan and same key */
556
for(i = 0; i < synth->polyphony; i++)
557
{
558
voice = synth->voice[i];
559
560
if(fluid_voice_is_on(voice) &&
561
fluid_voice_get_channel(voice) == chan &&
562
fluid_voice_get_key(voice) == key)
563
{
564
if(synth->verbose)
565
{
566
int used_voices = 0;
567
int k;
568
569
for(k = 0; k < synth->polyphony; k++)
570
{
571
if(!_AVAILABLE(synth->voice[k]))
572
{
573
used_voices++;
574
}
575
}
576
577
FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%d",
578
fluid_voice_get_channel(voice), fluid_voice_get_key(voice), 0,
579
fluid_voice_get_id(voice),
580
(fluid_curtime() - synth->start) / 1000.0f,
581
used_voices);
582
} /* if verbose */
583
584
fluid_voice_noteoff(voice);
585
586
/* noteoff on monophonic note */
587
/* Key memorization if the note is sustained */
588
if(Mono &&
589
(fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice)))
590
{
591
channel->key_mono_sustained = key;
592
}
593
594
status = FLUID_OK;
595
} /* if voice on */
596
} /* for all voices */
597
598
return status;
599
}
600
601
/*----------------------------------------------------------------------------
602
legato playing
603
-----------------------------------------------------------------------------*/
604
/**
605
* Plays noteon for a monophonic note played legato.
606
* Please see the description above about "monophonic playing".
607
*
608
*
609
* _______________
610
* portamento modes >----->| |
611
* | get_fromkey |
612
* Porta.on/off >----------------------->|_______________|
613
* Portamento |
614
* (PTC) | +-->preset_noteon
615
* fromkey | fromkey | (with or without)
616
* legato | portamento| (portamento)
617
* _____\|/_______ |
618
* | noteon |--+
619
* noteon_mono >------------------------>| monopoly |
620
* LOCAL | legato |----->voices
621
* |_______________| triggering
622
* /|\ (with or without)
623
* | (portamento)
624
* legato modes >-----------------+
625
*
626
* We are in legato situation (where a previous note has been depressed).
627
* The function must determine the from_key_portamento and from_key_legato parameters
628
* used respectively by fluid_preset_noteon() function and voices triggering functions.
629
*
630
* from_key_portamento and from_key_legato are returned by
631
* fluid_synth_get_fromkey_portamento_legato() function.
632
* fromkey_portamento is set to valid/invalid key value depending of the portamento
633
* modes (see portamento mode API), CC portamento On/Off, and CC portamento control
634
* (PTC).
635
* Then, depending of the legato modes (see legato mode API), the function will call
636
* the appropriate triggering functions.
637
* @param synth instance.
638
* @param chan MIDI channel number (0 to MIDI channel count - 1).
639
* @param fromkey MIDI note number (0-127).
640
* @param tokey MIDI note number (0-127).
641
* @param vel MIDI velocity (0-127).
642
* @return FLUID_OK on success, FLUID_FAILED otherwise.
643
*
644
* Note: The voices with key 'fromkey' are to be used to play key 'tokey'.
645
* The function is able to play legato through Preset Zone(s) (PZ) and
646
* Instrument Zone(s) (IZ) as far as possible.
647
* When key tokey is outside the current Instrument Zone, Preset Zone,
648
* current 'fromkey' voices are released. If necessary new voices
649
* are restarted when tokey enters inside new Instrument(s) Zones,Preset Zone(s).
650
* More information in FluidPolyMono-0004.pdf chapter 4.7 (Appendices).
651
*/
652
int fluid_synth_noteon_monopoly_legato(fluid_synth_t *synth, int chan,
653
int fromkey, int tokey, int vel)
654
{
655
fluid_channel_t *channel = synth->channel[chan];
656
enum fluid_channel_legato_mode legatomode = channel->legatomode;
657
fluid_voice_t *voice;
658
int i ;
659
/* Gets possible 'fromkey portamento' and possible 'fromkey legato' note */
660
fromkey = fluid_synth_get_fromkey_portamento_legato(channel, fromkey);
661
662
if(fluid_channel_is_valid_note(fromkey))
663
{
664
for(i = 0; i < synth->polyphony; i++)
665
{
666
/* searching fromkey voices: only those who don't have 'note off' */
667
voice = synth->voice[i];
668
669
if(fluid_voice_is_on(voice) &&
670
fluid_voice_get_channel(voice) == chan &&
671
fluid_voice_get_key(voice) == fromkey)
672
{
673
fluid_zone_range_t *zone_range = voice->zone_range;
674
675
/* Ignores voice when there is no instrument zone (i.e no zone_range). Otherwise
676
checks if tokey is inside the range of the running voice */
677
if(zone_range && fluid_zone_inside_range(zone_range, tokey, vel))
678
{
679
switch(legatomode)
680
{
681
case FLUID_CHANNEL_LEGATO_MODE_RETRIGGER: /* mode 0 */
682
fluid_voice_release(voice); /* normal release */
683
break;
684
685
case FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER: /* mode 1 */
686
/* Skip in attack section */
687
fluid_voice_update_multi_retrigger_attack(voice, tokey, vel);
688
689
/* Starts portamento if enabled */
690
if(fluid_channel_is_valid_note(synth->fromkey_portamento))
691
{
692
/* Sends portamento parameters to the voice dsp */
693
fluid_voice_update_portamento(voice,
694
synth->fromkey_portamento,
695
tokey);
696
}
697
698
/* The voice is now used to play tokey in legato manner */
699
/* Marks this Instrument Zone to be ignored during next
700
fluid_preset_noteon() */
701
zone_range->ignore = TRUE;
702
break;
703
704
default: /* Invalid mode: this should never happen */
705
FLUID_LOG(FLUID_WARN, "Failed to execute legato mode: %d",
706
legatomode);
707
return FLUID_FAILED;
708
}
709
}
710
else
711
{
712
/* tokey note is outside the voice range, so the voice is released */
713
fluid_voice_release(voice);
714
}
715
}
716
}
717
}
718
719
/* May be,tokey will enter in new others Insrument Zone(s),Preset Zone(s), in
720
this case it needs to be played by voices allocation */
721
return fluid_preset_noteon(channel->preset, synth, chan, tokey, vel);
722
}
723
724