Update Fluidsynth to 2.0.1
[ardour.git] / libs / fluidsynth / src / fluid_rvoice.c
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_rvoice.h"
22 #include "fluid_conv.h"
23 #include "fluid_sys.h"
24
25
26 static void fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t *voice, unsigned int min_ticks);
27
28 /**
29  * @return -1 if voice has finished, 0 if it's currently quiet, 1 otherwise
30  */
31 static FLUID_INLINE int
32 fluid_rvoice_calc_amp(fluid_rvoice_t *voice)
33 {
34     fluid_real_t target_amp;    /* target amplitude */
35
36     if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVDELAY)
37     {
38         return -1;    /* The volume amplitude is in hold phase. No sound is produced. */
39     }
40
41     if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVATTACK)
42     {
43         /* the envelope is in the attack section: ramp linearly to max value.
44          * A positive modlfo_to_vol should increase volume (negative attenuation).
45          */
46         target_amp = fluid_cb2amp(voice->dsp.attenuation)
47                      * fluid_cb2amp(fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol)
48                      * fluid_adsr_env_get_val(&voice->envlfo.volenv);
49     }
50     else
51     {
52         fluid_real_t amplitude_that_reaches_noise_floor;
53         fluid_real_t amp_max;
54
55         target_amp = fluid_cb2amp(voice->dsp.attenuation)
56                      * fluid_cb2amp(FLUID_PEAK_ATTENUATION * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv))
57                                     + fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol);
58
59         /* We turn off a voice, if the volume has dropped low enough. */
60
61         /* A voice can be turned off, when an estimate for the volume
62          * (upper bound) falls below that volume, that will drop the
63          * sample below the noise floor.
64          */
65
66         /* If the loop amplitude is known, we can use it if the voice loop is within
67          * the sample loop
68          */
69
70         /* Is the playing pointer already in the loop? */
71         if(voice->dsp.has_looped)
72         {
73             amplitude_that_reaches_noise_floor = voice->dsp.amplitude_that_reaches_noise_floor_loop;
74         }
75         else
76         {
77             amplitude_that_reaches_noise_floor = voice->dsp.amplitude_that_reaches_noise_floor_nonloop;
78         }
79
80         /* voice->attenuation_min is a lower boundary for the attenuation
81          * now and in the future (possibly 0 in the worst case).  Now the
82          * amplitude of sample and volenv cannot exceed amp_max (since
83          * volenv_val can only drop):
84          */
85
86         amp_max = fluid_cb2amp(voice->dsp.min_attenuation_cB) *
87                   fluid_adsr_env_get_val(&voice->envlfo.volenv);
88
89         /* And if amp_max is already smaller than the known amplitude,
90          * which will attenuate the sample below the noise floor, then we
91          * can safely turn off the voice. Duh. */
92         if(amp_max < amplitude_that_reaches_noise_floor)
93         {
94             return 0;
95         }
96     }
97
98     /* Volume increment to go from voice->amp to target_amp in FLUID_BUFSIZE steps */
99     voice->dsp.amp_incr = (target_amp - voice->dsp.amp) / FLUID_BUFSIZE;
100
101     fluid_check_fpe("voice_write amplitude calculation");
102
103     /* no volume and not changing? - No need to process */
104     if((voice->dsp.amp == 0.0f) && (voice->dsp.amp_incr == 0.0f))
105     {
106         return -1;
107     }
108
109     return 1;
110 }
111
112
113 /* these should be the absolute minimum that FluidSynth can deal with */
114 #define FLUID_MIN_LOOP_SIZE 2
115 #define FLUID_MIN_LOOP_PAD 0
116
117 #define FLUID_SAMPLESANITY_CHECK (1 << 0)
118 #define FLUID_SAMPLESANITY_STARTUP (1 << 1)
119
120 /* Purpose:
121  *
122  * Make sure, that sample start / end point and loop points are in
123  * proper order. When starting up, calculate the initial phase.
124  * TODO: Investigate whether this can be moved from rvoice to voice.
125  */
126 static void
127 fluid_rvoice_check_sample_sanity(fluid_rvoice_t *voice)
128 {
129     int min_index_nonloop = (int) voice->dsp.sample->start;
130     int max_index_nonloop = (int) voice->dsp.sample->end;
131
132     /* make sure we have enough samples surrounding the loop */
133     int min_index_loop = (int) voice->dsp.sample->start + FLUID_MIN_LOOP_PAD;
134     int max_index_loop = (int) voice->dsp.sample->end - FLUID_MIN_LOOP_PAD + 1; /* 'end' is last valid sample, loopend can be + 1 */
135     fluid_check_fpe("voice_check_sample_sanity start");
136
137 #if 0
138     printf("Sample from %i to %i\n", voice->dsp.sample->start, voice->dsp.sample->end);
139     printf("Sample loop from %i %i\n", voice->dsp.sample->loopstart, voice->dsp.sample->loopend);
140     printf("Playback from %i to %i\n", voice->dsp.start, voice->dsp.end);
141     printf("Playback loop from %i to %i\n", voice->dsp.loopstart, voice->dsp.loopend);
142 #endif
143
144     /* Keep the start point within the sample data */
145     if(voice->dsp.start < min_index_nonloop)
146     {
147         voice->dsp.start = min_index_nonloop;
148     }
149     else if(voice->dsp.start > max_index_nonloop)
150     {
151         voice->dsp.start = max_index_nonloop;
152     }
153
154     /* Keep the end point within the sample data */
155     if(voice->dsp.end < min_index_nonloop)
156     {
157         voice->dsp.end = min_index_nonloop;
158     }
159     else if(voice->dsp.end > max_index_nonloop)
160     {
161         voice->dsp.end = max_index_nonloop;
162     }
163
164     /* Keep start and end point in the right order */
165     if(voice->dsp.start > voice->dsp.end)
166     {
167         int temp = voice->dsp.start;
168         voice->dsp.start = voice->dsp.end;
169         voice->dsp.end = temp;
170         /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of start / end points!"); */
171     }
172
173     /* Zero length? */
174     if(voice->dsp.start == voice->dsp.end)
175     {
176         fluid_rvoice_voiceoff(voice, NULL);
177         return;
178     }
179
180     if((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE)
181             || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE))
182     {
183         /* Keep the loop start point within the sample data */
184         if(voice->dsp.loopstart < min_index_loop)
185         {
186             voice->dsp.loopstart = min_index_loop;
187         }
188         else if(voice->dsp.loopstart > max_index_loop)
189         {
190             voice->dsp.loopstart = max_index_loop;
191         }
192
193         /* Keep the loop end point within the sample data */
194         if(voice->dsp.loopend < min_index_loop)
195         {
196             voice->dsp.loopend = min_index_loop;
197         }
198         else if(voice->dsp.loopend > max_index_loop)
199         {
200             voice->dsp.loopend = max_index_loop;
201         }
202
203         /* Keep loop start and end point in the right order */
204         if(voice->dsp.loopstart > voice->dsp.loopend)
205         {
206             int temp = voice->dsp.loopstart;
207             voice->dsp.loopstart = voice->dsp.loopend;
208             voice->dsp.loopend = temp;
209             /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of loop points!"); */
210         }
211
212         /* Loop too short? Then don't loop. */
213         if(voice->dsp.loopend < voice->dsp.loopstart + FLUID_MIN_LOOP_SIZE)
214         {
215             voice->dsp.samplemode = FLUID_UNLOOPED;
216         }
217
218         /* The loop points may have changed. Obtain a new estimate for the loop volume. */
219         /* Is the voice loop within the sample loop? */
220         if((int)voice->dsp.loopstart >= (int)voice->dsp.sample->loopstart
221                 && (int)voice->dsp.loopend <= (int)voice->dsp.sample->loopend)
222         {
223             /* Is there a valid peak amplitude available for the loop, and can we use it? */
224             if(voice->dsp.sample->amplitude_that_reaches_noise_floor_is_valid && voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)
225             {
226                 voice->dsp.amplitude_that_reaches_noise_floor_loop = voice->dsp.sample->amplitude_that_reaches_noise_floor / voice->dsp.synth_gain;
227             }
228             else
229             {
230                 /* Worst case */
231                 voice->dsp.amplitude_that_reaches_noise_floor_loop = voice->dsp.amplitude_that_reaches_noise_floor_nonloop;
232             };
233         };
234
235     } /* if sample mode is looped */
236
237     /* Run startup specific code (only once, when the voice is started) */
238     if(voice->dsp.check_sample_sanity_flag & FLUID_SAMPLESANITY_STARTUP)
239     {
240         if(max_index_loop - min_index_loop < FLUID_MIN_LOOP_SIZE)
241         {
242             if((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE)
243                     || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE))
244             {
245                 voice->dsp.samplemode = FLUID_UNLOOPED;
246             }
247         }
248
249         /* Set the initial phase of the voice (using the result from the
250         start offset modulators). */
251         fluid_phase_set_int(voice->dsp.phase, voice->dsp.start);
252     } /* if startup */
253
254     /* Is this voice run in loop mode, or does it run straight to the
255        end of the waveform data? */
256     if(((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) &&
257             (fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE))
258             || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE))
259     {
260         /* Yes, it will loop as soon as it reaches the loop point.  In
261          * this case we must prevent, that the playback pointer (phase)
262          * happens to end up beyond the 2nd loop point, because the
263          * point has moved.  The DSP algorithm is unable to cope with
264          * that situation.  So if the phase is beyond the 2nd loop
265          * point, set it to the start of the loop. No way to avoid some
266          * noise here.  Note: If the sample pointer ends up -before the
267          * first loop point- instead, then the DSP loop will just play
268          * the sample, enter the loop and proceed as expected => no
269          * actions required.
270          */
271         int index_in_sample = fluid_phase_index(voice->dsp.phase);
272
273         if(index_in_sample >= voice->dsp.loopend)
274         {
275             /* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Phase after 2nd loop point!"); */
276             fluid_phase_set_int(voice->dsp.phase, voice->dsp.loopstart);
277         }
278     }
279
280     /*    FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Sample from %i to %i, loop from %i to %i", voice->dsp.start, voice->dsp.end, voice->dsp.loopstart, voice->dsp.loopend); */
281
282     /* Sample sanity has been assured. Don't check again, until some
283        sample parameter is changed by modulation. */
284     voice->dsp.check_sample_sanity_flag = 0;
285 #if 0
286     printf("Sane? playback loop from %i to %i\n", voice->dsp.loopstart, voice->dsp.loopend);
287 #endif
288     fluid_check_fpe("voice_check_sample_sanity");
289 }
290
291
292 /**
293  * Synthesize a voice to a buffer.
294  *
295  * @param voice rvoice to synthesize
296  * @param dsp_buf Audio buffer to synthesize to (#FLUID_BUFSIZE in length)
297  * @return Count of samples written to dsp_buf. (-1 means voice is currently
298  * quiet, 0 .. #FLUID_BUFSIZE-1 means voice finished.)
299  *
300  * Panning, reverb and chorus are processed separately. The dsp interpolation
301  * routine is in (fluid_rvoice_dsp.c).
302  */
303 int
304 fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf)
305 {
306     int ticks = voice->envlfo.ticks;
307     int count, is_looping;
308
309     /******************* sample sanity check **********/
310
311     if(!voice->dsp.sample)
312     {
313         return 0;
314     }
315
316     if(voice->dsp.check_sample_sanity_flag)
317     {
318         fluid_rvoice_check_sample_sanity(voice);
319     }
320
321     /******************* noteoff check ****************/
322
323     if(voice->envlfo.noteoff_ticks != 0 &&
324             voice->envlfo.ticks >= voice->envlfo.noteoff_ticks)
325     {
326         fluid_rvoice_noteoff_LOCAL(voice, 0);
327     }
328
329     voice->envlfo.ticks += FLUID_BUFSIZE;
330
331     /******************* vol env **********************/
332
333     fluid_adsr_env_calc(&voice->envlfo.volenv, 1);
334     fluid_check_fpe("voice_write vol env");
335
336     if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVFINISHED)
337     {
338         return 0;
339     }
340
341     /******************* mod env **********************/
342
343     fluid_adsr_env_calc(&voice->envlfo.modenv, 0);
344     fluid_check_fpe("voice_write mod env");
345
346     /******************* lfo **********************/
347
348     fluid_lfo_calc(&voice->envlfo.modlfo, ticks);
349     fluid_check_fpe("voice_write mod LFO");
350     fluid_lfo_calc(&voice->envlfo.viblfo, ticks);
351     fluid_check_fpe("voice_write vib LFO");
352
353     /******************* amplitude **********************/
354
355     count = fluid_rvoice_calc_amp(voice);
356
357     if(count <= 0)
358     {
359         return count;
360     }
361
362     /******************* phase **********************/
363
364     /* Calculate the number of samples, that the DSP loop advances
365      * through the original waveform with each step in the output
366      * buffer. It is the ratio between the frequencies of original
367      * waveform and output waveform.*/
368     voice->dsp.phase_incr = fluid_ct2hz_real(voice->dsp.pitch +
369                             voice->dsp.pitchoffset +
370                             fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_pitch
371                             + fluid_lfo_get_val(&voice->envlfo.viblfo) * voice->envlfo.viblfo_to_pitch
372                             + fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_pitch)
373                             / voice->dsp.root_pitch_hz;
374
375     /******************* portamento ****************/
376     /* pitchoffset is updated if enabled.
377        Pitchoffset will be added to dsp pitch at next phase calculation time */
378
379     /* In most cases portamento will be disabled. Thus first verify that portamento is
380      * enabled before updating pitchoffset and before disabling portamento when necessary,
381      * in order to keep the performance loss at minimum.
382      * If the algorithm would first update pitchoffset and then verify if portamento
383      * needs to be disabled, there would be a significant performance drop on a x87 FPU
384      */
385     if(voice->dsp.pitchinc > 0.0f)
386     {
387         /* portamento is enabled, so update pitchoffset */
388         voice->dsp.pitchoffset += voice->dsp.pitchinc;
389
390         /* when pitchoffset reaches 0.0f, portamento is disabled */
391         if(voice->dsp.pitchoffset > 0.0f)
392         {
393             voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f;
394         }
395     }
396     else if(voice->dsp.pitchinc < 0.0f)
397     {
398         /* portamento is enabled, so update pitchoffset */
399         voice->dsp.pitchoffset += voice->dsp.pitchinc;
400
401         /* when pitchoffset reaches 0.0f, portamento is disabled */
402         if(voice->dsp.pitchoffset < 0.0f)
403         {
404             voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f;
405         }
406     }
407
408     fluid_check_fpe("voice_write phase calculation");
409
410     /* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */
411     if(voice->dsp.phase_incr == 0)
412     {
413         voice->dsp.phase_incr = 1;
414     }
415
416     /* voice is currently looping? */
417     is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE
418                  || (voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE
419                      && fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE);
420
421     /*********************** run the dsp chain ************************
422      * The sample is mixed with the output buffer.
423      * The buffer has to be filled from 0 to FLUID_BUFSIZE-1.
424      * Depending on the position in the loop and the loop size, this
425      * may require several runs. */
426
427     switch(voice->dsp.interp_method)
428     {
429     case FLUID_INTERP_NONE:
430         count = fluid_rvoice_dsp_interpolate_none(&voice->dsp, dsp_buf, is_looping);
431         break;
432
433     case FLUID_INTERP_LINEAR:
434         count = fluid_rvoice_dsp_interpolate_linear(&voice->dsp, dsp_buf, is_looping);
435         break;
436
437     case FLUID_INTERP_4THORDER:
438     default:
439         count = fluid_rvoice_dsp_interpolate_4th_order(&voice->dsp, dsp_buf, is_looping);
440         break;
441
442     case FLUID_INTERP_7THORDER:
443         count = fluid_rvoice_dsp_interpolate_7th_order(&voice->dsp, dsp_buf, is_looping);
444         break;
445     }
446
447     fluid_check_fpe("voice_write interpolation");
448
449     if(count == 0)
450     {
451         return count;
452     }
453
454     /*************** resonant filter ******************/
455
456     fluid_iir_filter_calc(&voice->resonant_filter, voice->dsp.output_rate,
457                           fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_fc +
458                           fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_fc);
459
460     fluid_iir_filter_apply(&voice->resonant_filter, dsp_buf, count);
461
462     /* additional custom filter - only uses the fixed modulator, no lfos... */
463     fluid_iir_filter_calc(&voice->resonant_custom_filter, voice->dsp.output_rate, 0);
464     fluid_iir_filter_apply(&voice->resonant_custom_filter, dsp_buf, count);
465
466     return count;
467 }
468
469 /**
470  * Initialize buffers up to (and including) bufnum
471  */
472 static int
473 fluid_rvoice_buffers_check_bufnum(fluid_rvoice_buffers_t *buffers, unsigned int bufnum)
474 {
475     unsigned int i;
476
477     if(bufnum < buffers->count)
478     {
479         return FLUID_OK;
480     }
481
482     if(bufnum >= FLUID_RVOICE_MAX_BUFS)
483     {
484         return FLUID_FAILED;
485     }
486
487     for(i = buffers->count; i <= bufnum; i++)
488     {
489         buffers->bufs[i].amp = 0.0f;
490     }
491
492     buffers->count = bufnum + 1;
493     return FLUID_OK;
494 }
495
496
497 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp)
498 {
499     fluid_rvoice_buffers_t *buffers = obj;
500     unsigned int bufnum = param[0].i;
501     fluid_real_t value = param[1].real;
502
503     if(fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK)
504     {
505         return;
506     }
507
508     buffers->bufs[bufnum].amp = value;
509 }
510
511 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping)
512 {
513     fluid_rvoice_buffers_t *buffers = obj;
514     unsigned int bufnum = param[0].i;
515     int mapping = param[1].i;
516
517     if(fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK)
518     {
519         return;
520     }
521
522     buffers->bufs[bufnum].mapping = mapping;
523 }
524
525
526 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_reset)
527 {
528     fluid_rvoice_t *voice = obj;
529
530     voice->dsp.has_looped = 0;
531     voice->envlfo.ticks = 0;
532     voice->envlfo.noteoff_ticks = 0;
533     voice->dsp.amp = 0.0f; /* The last value of the volume envelope, used to
534                             calculate the volume increment during
535                             processing */
536
537     /* legato initialization */
538     voice->dsp.pitchoffset = 0.0;   /* portamento initialization */
539     voice->dsp.pitchinc = 0.0;
540
541     /* mod env initialization*/
542     fluid_adsr_env_reset(&voice->envlfo.modenv);
543
544     /* vol env initialization */
545     fluid_adsr_env_reset(&voice->envlfo.volenv);
546
547     /* Fixme: Retrieve from any other existing
548        voice on this channel to keep LFOs in
549        unison? */
550     fluid_lfo_reset(&voice->envlfo.viblfo);
551     fluid_lfo_reset(&voice->envlfo.modlfo);
552
553     /* Clear sample history in filter */
554     fluid_iir_filter_reset(&voice->resonant_filter);
555     fluid_iir_filter_reset(&voice->resonant_custom_filter);
556
557     /* Force setting of the phase at the first DSP loop run
558      * This cannot be done earlier, because it depends on modulators.
559        [DH] Is that comment really true? */
560     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP;
561 }
562
563 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_noteoff)
564 {
565     fluid_rvoice_t *rvoice = obj;
566     unsigned int min_ticks = param[0].i;
567
568     fluid_rvoice_noteoff_LOCAL(rvoice, min_ticks);
569 }
570
571 static void
572 fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t *voice, unsigned int min_ticks)
573 {
574     if(min_ticks > voice->envlfo.ticks)
575     {
576         /* Delay noteoff */
577         voice->envlfo.noteoff_ticks = min_ticks;
578         return;
579     }
580
581     voice->envlfo.noteoff_ticks = 0;
582
583     if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVATTACK)
584     {
585         /* A voice is turned off during the attack section of the volume
586          * envelope.  The attack section ramps up linearly with
587          * amplitude. The other sections use logarithmic scaling. Calculate new
588          * volenv_val to achieve equievalent amplitude during the release phase
589          * for seamless volume transition.
590          */
591         if(fluid_adsr_env_get_val(&voice->envlfo.volenv) > 0)
592         {
593             fluid_real_t lfo = fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol;
594             fluid_real_t amp = fluid_adsr_env_get_val(&voice->envlfo.volenv) * fluid_cb2amp(lfo);
595             fluid_real_t env_value = - ((-200 * log(amp) / log(10.0) - lfo) / FLUID_PEAK_ATTENUATION - 1);
596             fluid_clip(env_value, 0.0, 1.0);
597             fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value);
598         }
599     }
600
601     fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVRELEASE);
602     fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVRELEASE);
603 }
604
605 /**
606  * skips to Attack section
607  *
608  * Updates vol and attack data
609  * Correction on volume val to achieve equivalent amplitude at noteOn legato
610  *
611  * @param voice the synthesis voice to be updated
612 */
613 static FLUID_INLINE void fluid_rvoice_local_retrigger_attack(fluid_rvoice_t *voice)
614 {
615     /* skips to Attack section */
616     /* Once in Attack section, current count must be reset, to be sure
617     that the section will be not be prematurely finished. */
618     fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVATTACK);
619     {
620         /* Correction on volume val to achieve equivalent amplitude at noteOn legato */
621         fluid_env_data_t *env_data;
622         fluid_real_t peak = fluid_cb2amp(voice->dsp.attenuation);
623         fluid_real_t prev_peak = fluid_cb2amp(voice->dsp.prev_attenuation);
624         voice->envlfo.volenv.val = (voice->envlfo.volenv.val  * prev_peak) / peak;
625         /* Correction on slope direction for Attack section */
626         env_data = &voice->envlfo.volenv.data[FLUID_VOICE_ENVATTACK];
627
628         if(voice->envlfo.volenv.val <= 1.0f)
629         {
630             /* slope attack for legato note needs to be positive from val  up to 1 */
631             env_data->increment = 1.0f / env_data->count;
632             env_data->min = -1.0f;
633             env_data->max =  1.0f;
634         }
635         else
636         {
637             /* slope attack for legato note needs to be negative: from val  down to 1 */
638             env_data->increment = -voice->envlfo.volenv.val / env_data->count;
639             env_data->min = 1.0f;
640             env_data->max = voice->envlfo.volenv.val;
641         }
642     }
643 }
644
645 /**
646  * Used by legato Mode : multi_retrigger
647  *  see fluid_synth_noteon_mono_legato_multi_retrigger()
648  * @param voice the synthesis voice to be updated
649 */
650 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack)
651 {
652     fluid_rvoice_t *voice = obj;
653     int section = fluid_adsr_env_get_section(&voice->envlfo.volenv);
654
655     /*-------------------------------------------------------------------------
656      Section skip for volume envelope
657     --------------------------------------------------------------------------*/
658     if(section >= FLUID_VOICE_ENVHOLD)
659     {
660         /* DECAY, SUSTAIN,RELEASE section use logarithmic scaling. Calculates new
661         volenv_val to achieve equivalent amplitude during the attack phase
662         for seamless volume transition. */
663         fluid_real_t amp_cb, env_value;
664         amp_cb = FLUID_PEAK_ATTENUATION *
665                  (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv));
666         env_value = fluid_cb2amp(amp_cb); /* a bit of optimization */
667         fluid_clip(env_value, 0.0, 1.0);
668         fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value);
669         /* next, skips to Attack section */
670     }
671
672     /* skips to Attack section from any section */
673     /* Update vol and  attack data */
674     fluid_rvoice_local_retrigger_attack(voice);
675     /*-------------------------------------------------------------------------
676      Section skip for modulation envelope
677     --------------------------------------------------------------------------*/
678     /* Skips from any section to ATTACK section */
679     fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVATTACK);
680     /* Actually (v 1.1.6) all sections are linear, so there is no need to
681      correct val value. However soundfont 2.01/2.4 spec. says that Attack should
682      be convex (see issue #153  from Christian Collins). In the case Attack
683      section would be changed to a non linear shape it will be necessary to do
684      a correction for seamless val transition. Here is the place to do this */
685 }
686
687 /**
688  * sets the portamento dsp parameters: dsp.pitchoffset, dsp.pitchinc
689  * @param voice rvoice to set portamento.
690  * @param countinc increment count number.
691  * @param pitchoffset pitch offset to apply to voice dsp.pitch.
692  *
693  * Notes:
694  * 1) To get continuous portamento between consecutive noteOn (n1,n2,n3...),
695  *   pitchoffset is accumulated in current dsp pitchoffset.
696  * 2) And to get constant portamento duration, dsp pitch increment is updated.
697 */
698 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_portamento)
699 {
700     fluid_rvoice_t *voice = obj;
701     unsigned int countinc = param[0].i;
702     fluid_real_t pitchoffset = param[1].real;
703
704     if(countinc)
705     {
706         voice->dsp.pitchoffset += pitchoffset;
707         voice->dsp.pitchinc = - voice->dsp.pitchoffset / countinc;
708     }
709
710     /* Then during the voice processing (in fluid_rvoice_write()),
711     dsp.pitchoffset will be incremented by dsp pitchinc. */
712 }
713
714
715 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_output_rate)
716 {
717     fluid_rvoice_t *voice = obj;
718     fluid_real_t value = param[0].real;
719
720     voice->dsp.output_rate = value;
721 }
722
723 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_interp_method)
724 {
725     fluid_rvoice_t *voice = obj;
726     int value = param[0].i;
727
728     voice->dsp.interp_method = value;
729 }
730
731 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_root_pitch_hz)
732 {
733     fluid_rvoice_t *voice = obj;
734     fluid_real_t value = param[0].real;
735
736     voice->dsp.root_pitch_hz = value;
737 }
738
739 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_pitch)
740 {
741     fluid_rvoice_t *voice = obj;
742     fluid_real_t value = param[0].real;
743
744     voice->dsp.pitch = value;
745 }
746
747
748 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_attenuation)
749 {
750     fluid_rvoice_t *voice = obj;
751     fluid_real_t value = param[0].real;
752
753     voice->dsp.prev_attenuation = voice->dsp.attenuation;
754     voice->dsp.attenuation = value;
755 }
756
757 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_min_attenuation_cB)
758 {
759     fluid_rvoice_t *voice = obj;
760     fluid_real_t value = param[0].real;
761
762     voice->dsp.min_attenuation_cB = value;
763 }
764
765 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_viblfo_to_pitch)
766 {
767     fluid_rvoice_t *voice = obj;
768     fluid_real_t value = param[0].real;
769
770     voice->envlfo.viblfo_to_pitch = value;
771 }
772
773 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_pitch)
774 {
775     fluid_rvoice_t *voice = obj;
776     fluid_real_t value = param[0].real;
777
778     voice->envlfo.modlfo_to_pitch = value;
779 }
780
781 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_vol)
782 {
783     fluid_rvoice_t *voice = obj;
784     fluid_real_t value = param[0].real;
785
786     voice->envlfo.modlfo_to_vol = value;
787 }
788
789 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_fc)
790 {
791     fluid_rvoice_t *voice = obj;
792     fluid_real_t value = param[0].real;
793
794     voice->envlfo.modlfo_to_fc = value;
795 }
796
797 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_fc)
798 {
799     fluid_rvoice_t *voice = obj;
800     fluid_real_t value = param[0].real;
801
802     voice->envlfo.modenv_to_fc = value;
803 }
804
805 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_pitch)
806 {
807     fluid_rvoice_t *voice = obj;
808     fluid_real_t value = param[0].real;
809
810     voice->envlfo.modenv_to_pitch = value;
811 }
812
813 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_synth_gain)
814 {
815     fluid_rvoice_t *voice = obj;
816     fluid_real_t value = param[0].real;
817
818     voice->dsp.synth_gain = value;
819
820     /* For a looped sample, this value will be overwritten as soon as the
821      * loop parameters are initialized (they may depend on modulators).
822      * This value can be kept, it is a worst-case estimate.
823      */
824     voice->dsp.amplitude_that_reaches_noise_floor_nonloop = FLUID_NOISE_FLOOR / value;
825     voice->dsp.amplitude_that_reaches_noise_floor_loop = FLUID_NOISE_FLOOR / value;
826     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
827 }
828
829 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_start)
830 {
831     fluid_rvoice_t *voice = obj;
832     int value = param[0].i;
833
834     voice->dsp.start = value;
835     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
836 }
837
838 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_end)
839 {
840     fluid_rvoice_t *voice = obj;
841     int value = param[0].i;
842
843     voice->dsp.end = value;
844     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
845 }
846
847 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopstart)
848 {
849     fluid_rvoice_t *voice = obj;
850     int value = param[0].i;
851
852     voice->dsp.loopstart = value;
853     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
854 }
855
856 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopend)
857 {
858     fluid_rvoice_t *voice = obj;
859     int value = param[0].i;
860
861     voice->dsp.loopend = value;
862     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
863 }
864
865 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode)
866 {
867     fluid_rvoice_t *voice = obj;
868     enum fluid_loop value = param[0].i;
869
870     voice->dsp.samplemode = value;
871     voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
872 }
873
874
875 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample)
876 {
877     fluid_rvoice_t *voice = obj;
878     fluid_sample_t *value = param[0].ptr;
879
880     voice->dsp.sample = value;
881
882     if(value)
883     {
884         voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP;
885     }
886 }
887
888 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_voiceoff)
889 {
890     fluid_rvoice_t *voice = obj;
891
892     fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVFINISHED);
893     fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVFINISHED);
894 }
895
896