Update Fluidsynth to v2.0.4
[ardour.git] / libs / fluidsynth / src / fluid_rvoice_mixer.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_mixer.h"
22 #include "fluid_rvoice.h"
23 #include "fluid_sys.h"
24 #include "fluid_rev.h"
25 #include "fluid_chorus.h"
26 #include "fluid_synth.h"
27
28
29 // If less than x voices, the thread overhead is larger than the gain,
30 // so don't activate the thread(s).
31 #define VOICES_PER_THREAD 8
32
33 typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t;
34
35 struct _fluid_mixer_buffers_t
36 {
37     fluid_rvoice_mixer_t *mixer; /**< Owner of object */
38 #if ENABLE_MIXER_THREADS
39     fluid_thread_t *thread;     /**< Thread object */
40     fluid_atomic_int_t ready;   /**< Atomic: buffers are ready for mixing */
41 #endif
42
43     fluid_rvoice_t **finished_voices; /* List of voices who have finished */
44     int finished_voice_count;
45
46     fluid_real_t *local_buf;
47
48     int buf_count;
49     int fx_buf_count;
50
51     /** buffer to store the left part of a stereo channel to.
52      * Specifically a two dimensional array, containing \c buf_count sample buffers
53      * (i.e. for each synth.audio-channels), of which each contains
54      * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples)
55      * @note Each sample buffer is aligned to the FLUID_DEFAULT_ALIGNMENT
56      * boundary provided that this pointer points to an aligned buffer.
57      * So make sure to access the sample buffer by first aligning this
58      * pointer using fluid_align_ptr()
59      */
60     fluid_real_t *left_buf;
61
62     /** dito, but for right part of a stereo channel */
63     fluid_real_t *right_buf;
64
65     /** buffer to store the left part of a stereo effects channel to.
66      * Specifically a two dimensional array, containing \c fx_buf_count buffers
67      * (i.e. for each synth.effects-channels), of which each buffer contains
68      * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples)
69      */
70     fluid_real_t *fx_left_buf;
71     fluid_real_t *fx_right_buf;
72 };
73
74 typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t;
75
76 struct _fluid_mixer_fx_t
77 {
78     fluid_revmodel_t *reverb; /**< Reverb unit */
79     fluid_chorus_t *chorus; /**< Chorus unit */
80 };
81
82 struct _fluid_rvoice_mixer_t
83 {
84     fluid_mixer_fx_t *fx;
85
86     fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */
87     fluid_rvoice_eventhandler_t *eventhandler;
88
89     fluid_rvoice_t **rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */
90     int polyphony; /**< Read-only: Length of voices array */
91     int active_voices; /**< Read-only: Number of non-null voices */
92     int current_blockcount;      /**< Read-only: how many blocks to process this time */
93     int fx_units;
94     int with_reverb;        /**< Should the synth use the built-in reverb unit? */
95     int with_chorus;        /**< Should the synth use the built-in chorus unit? */
96     int mix_fx_to_out;      /**< Should the effects be mixed in with the primary output? */
97
98 #ifdef LADSPA
99     fluid_ladspa_fx_t *ladspa_fx; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */
100 #endif
101
102 #if ENABLE_MIXER_THREADS
103 //  int sleeping_threads;        /**< Atomic: number of threads currently asleep */
104 //  int active_threads;          /**< Atomic: number of threads in the thread loop */
105     fluid_atomic_int_t threads_should_terminate; /**< Atomic: Set to TRUE when threads should terminate */
106     fluid_atomic_int_t current_rvoice;           /**< Atomic: for the threads to know next voice to  */
107     fluid_cond_t *wakeup_threads; /**< Signalled when the threads should wake up */
108     fluid_cond_mutex_t *wakeup_threads_m; /**< wakeup_threads mutex companion */
109     fluid_cond_t *thread_ready; /**< Signalled from thread, when the thread has a buffer ready for mixing */
110     fluid_cond_mutex_t *thread_ready_m; /**< thread_ready mutex companion */
111
112     int thread_count;            /**< Number of extra mixer threads for multi-core rendering */
113     fluid_mixer_buffers_t *threads;    /**< Array of mixer threads (thread_count in length) */
114 #endif
115 };
116
117 #if ENABLE_MIXER_THREADS
118 static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer);
119 static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level);
120 #endif
121
122 static FLUID_INLINE void
123 fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcount)
124 {
125     const int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
126     int i, f;
127
128     void (*reverb_process_func)(fluid_revmodel_t *rev, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
129     void (*chorus_process_func)(fluid_chorus_t *chorus, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
130
131     fluid_real_t *out_rev_l, *out_rev_r, *out_ch_l, *out_ch_r;
132
133     // all dry unprocessed mono input is stored in the left channel
134     fluid_real_t *in_rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
135     fluid_real_t *in_ch = in_rev;
136
137     fluid_profile_ref_var(prof_ref);
138
139
140     if(mixer->mix_fx_to_out)
141     {
142         // mix effects to first stereo channel
143         out_ch_l = out_rev_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT);
144         out_ch_r = out_rev_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT);
145
146         reverb_process_func = fluid_revmodel_processmix;
147         chorus_process_func = fluid_chorus_processmix;
148
149     }
150     else
151     {
152         // replace effects into respective stereo effects channel
153         out_ch_l = out_rev_l = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
154         out_ch_r = out_rev_r = fluid_align_ptr(mixer->buffers.fx_right_buf, FLUID_DEFAULT_ALIGNMENT);
155
156         reverb_process_func = fluid_revmodel_processreplace;
157         chorus_process_func = fluid_chorus_processreplace;
158     }
159
160
161     if(mixer->with_reverb)
162     {
163         for(f = 0; f < mixer->fx_units; f++)
164         {
165             int buf_idx = f * fx_channels_per_unit + SYNTH_REVERB_CHANNEL;
166             
167             for(i = 0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
168             {
169                 int samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + i;
170                 
171                 reverb_process_func(mixer->fx[f].reverb,
172                                     &in_rev[samp_idx],
173                                     mixer->mix_fx_to_out ? &out_rev_l[i] : &out_rev_l[samp_idx],
174                                     mixer->mix_fx_to_out ? &out_rev_r[i] : &out_rev_r[samp_idx]);
175             }
176         }
177
178         fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref, 0,
179                       current_blockcount * FLUID_BUFSIZE);
180     }
181
182     if(mixer->with_chorus)
183     {
184         for(f = 0; f < mixer->fx_units; f++)
185         {
186             int buf_idx = f * fx_channels_per_unit + SYNTH_CHORUS_CHANNEL;
187             
188             for(i = 0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
189             {
190                 int samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + i;
191                 
192                 chorus_process_func(mixer->fx[f].chorus,
193                                     &in_ch [samp_idx],
194                                     mixer->mix_fx_to_out ? &out_ch_l[i] : &out_ch_l[samp_idx],
195                                     mixer->mix_fx_to_out ? &out_ch_r[i] : &out_ch_r[samp_idx]);
196             }
197         }
198
199         fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref, 0,
200                       current_blockcount * FLUID_BUFSIZE);
201     }
202
203 #ifdef LADSPA
204
205     /* Run the signal through the LADSPA Fx unit. The buffers have already been
206      * set up in fluid_rvoice_mixer_set_ladspa. */
207     if(mixer->ladspa_fx)
208     {
209         fluid_ladspa_run(mixer->ladspa_fx, current_blockcount, FLUID_BUFSIZE);
210         fluid_check_fpe("LADSPA");
211     }
212
213 #endif
214 }
215
216 /**
217  * Glue to get fluid_rvoice_buffers_mix what it wants
218  * Note: Make sure outbufs has 2 * (buf_count + fx_buf_count) elements before calling
219  */
220 static FLUID_INLINE int
221 fluid_mixer_buffers_prepare(fluid_mixer_buffers_t *buffers, fluid_real_t **outbufs)
222 {
223     fluid_real_t *base_ptr;
224     int i;
225     const int fx_channels_per_unit = buffers->fx_buf_count / buffers->mixer->fx_units;
226     const int offset = buffers->buf_count * 2;
227     int with_reverb = buffers->mixer->with_reverb;
228     int with_chorus = buffers->mixer->with_chorus;
229
230     /* Set up the reverb and chorus buffers only when the effect is enabled or
231      * when LADSPA is active. Nonexisting buffers are detected in the DSP loop.
232      * Not sending the effect signals saves some time in that case. */
233 #ifdef LADSPA
234     int with_ladspa = (buffers->mixer->ladspa_fx != NULL);
235     with_reverb = (with_reverb | with_ladspa);
236     with_chorus = (with_chorus | with_ladspa);
237 #endif
238
239     // all the dry, non-processed mono audio for effects is to be stored in the left buffers
240     base_ptr = fluid_align_ptr(buffers->fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
241
242     for(i = 0; i < buffers->mixer->fx_units; i++)
243     {
244         int fx_idx = i * fx_channels_per_unit;
245         
246         outbufs[offset + fx_idx + SYNTH_REVERB_CHANNEL] =
247             (with_reverb)
248             ? &base_ptr[(fx_idx + SYNTH_REVERB_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]
249             : NULL;
250             
251         outbufs[offset + fx_idx + SYNTH_CHORUS_CHANNEL] =
252             (with_chorus)
253             ? &base_ptr[(fx_idx + SYNTH_CHORUS_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]
254             : NULL;
255     }
256     
257     /* The output associated with a MIDI channel is wrapped around
258      * using the number of audio groups as modulo divider.  This is
259      * typically the number of output channels on the 'sound card',
260      * as long as the LADSPA Fx unit is not used. In case of LADSPA
261      * unit, think of it as subgroups on a mixer.
262      *
263      * For example: Assume that the number of groups is set to 2.
264      * Then MIDI channel 1, 3, 5, 7 etc. go to output 1, channels 2,
265      * 4, 6, 8 etc to output 2.  Or assume 3 groups: Then MIDI
266      * channels 1, 4, 7, 10 etc go to output 1; 2, 5, 8, 11 etc to
267      * output 2, 3, 6, 9, 12 etc to output 3.
268      */
269     base_ptr = fluid_align_ptr(buffers->left_buf, FLUID_DEFAULT_ALIGNMENT);
270
271     for(i = 0; i < buffers->buf_count; i++)
272     {
273         outbufs[i * 2] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT];
274     }
275
276     base_ptr = fluid_align_ptr(buffers->right_buf, FLUID_DEFAULT_ALIGNMENT);
277
278     for(i = 0; i < buffers->buf_count; i++)
279     {
280         outbufs[i * 2 + 1] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT];
281     }
282
283     return offset + buffers->fx_buf_count;
284 }
285
286
287 static FLUID_INLINE void
288 fluid_finish_rvoice(fluid_mixer_buffers_t *buffers, fluid_rvoice_t *rvoice)
289 {
290     if(buffers->finished_voice_count < buffers->mixer->polyphony)
291     {
292         buffers->finished_voices[buffers->finished_voice_count++] = rvoice;
293     }
294     else
295     {
296         FLUID_LOG(FLUID_ERR, "Exceeded finished voices array, try increasing polyphony");
297     }
298 }
299
300 static void
301 fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t *buffers)
302 {
303     int i, j;
304
305     for(i = 0; i < buffers->finished_voice_count; i++)
306     {
307         fluid_rvoice_t *v = buffers->finished_voices[i];
308         int av = buffers->mixer->active_voices;
309
310         for(j = 0; j < av; j++)
311         {
312             if(v == buffers->mixer->rvoices[j])
313             {
314                 av--;
315
316                 /* Pack the array */
317                 if(j < av)
318                 {
319                     buffers->mixer->rvoices[j] = buffers->mixer->rvoices[av];
320                 }
321             }
322         }
323
324         buffers->mixer->active_voices = av;
325
326         fluid_rvoice_eventhandler_finished_voice_callback(buffers->mixer->eventhandler, v);
327     }
328
329     buffers->finished_voice_count = 0;
330 }
331
332 static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice_mixer_t *mixer)
333 {
334 #if ENABLE_MIXER_THREADS
335     int i;
336
337     for(i = 0; i < mixer->thread_count; i++)
338     {
339         fluid_mixer_buffer_process_finished_voices(&mixer->threads[i]);
340     }
341
342 #endif
343     fluid_mixer_buffer_process_finished_voices(&mixer->buffers);
344 }
345
346
347 static FLUID_INLINE fluid_real_t *
348 get_dest_buf(fluid_rvoice_buffers_t *buffers, int index,
349              fluid_real_t **dest_bufs, int dest_bufcount)
350 {
351     int j = buffers->bufs[index].mapping;
352
353     if(j >= dest_bufcount || j < 0)
354     {
355         return NULL;
356     }
357
358     return dest_bufs[j];
359 }
360
361 /**
362  * Mix data down to buffers
363  *
364  * @param buffers Destination buffer(s)
365  * @param dsp_buf Mono sample source
366  * @param start_block Block to start mixing at
367  * @param sample_count number of samples to mix following \c start_block
368  * @param dest_bufs Array of buffers to mixdown to
369  * @param dest_bufcount Length of dest_bufs
370  */
371 static void
372 fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
373                          const fluid_real_t *FLUID_RESTRICT dsp_buf,
374                          int start_block, int sample_count,
375                          fluid_real_t **dest_bufs, int dest_bufcount)
376 {
377     int bufcount = buffers->count;
378     int i, dsp_i;
379
380     if(sample_count <= 0 || dest_bufcount <= 0)
381     {
382         return;
383     }
384
385     FLUID_ASSERT((uintptr_t)dsp_buf % FLUID_DEFAULT_ALIGNMENT == 0);
386     FLUID_ASSERT((uintptr_t)(&dsp_buf[start_block * FLUID_BUFSIZE]) % FLUID_DEFAULT_ALIGNMENT == 0);
387
388     for(i = 0; i < bufcount; i++)
389     {
390         fluid_real_t *FLUID_RESTRICT buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount);
391         fluid_real_t amp = buffers->bufs[i].amp;
392
393         if(buf == NULL || amp == 0.0f)
394         {
395             continue;
396         }
397
398         FLUID_ASSERT((uintptr_t)buf % FLUID_DEFAULT_ALIGNMENT == 0);
399
400         #pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT)
401
402         for(dsp_i = (start_block * FLUID_BUFSIZE); dsp_i < sample_count; dsp_i++)
403         {
404             buf[dsp_i] += amp * dsp_buf[dsp_i];
405         }
406     }
407 }
408
409 /**
410  * Synthesize one voice and add to buffer.
411  * NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means
412  * voice has been finished, removed and possibly replaced with another voice.
413  */
414 static FLUID_INLINE void
415 fluid_mixer_buffers_render_one(fluid_mixer_buffers_t *buffers,
416                                fluid_rvoice_t *rvoice, fluid_real_t **dest_bufs,
417                                unsigned int dest_bufcount, fluid_real_t *src_buf, int blockcount)
418 {
419     int i, total_samples = 0, start_block = 0;
420
421     for(i = 0; i < blockcount; i++)
422     {
423         int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE * i]);
424
425         if(s == -1)
426         {
427             start_block += s;
428             s = FLUID_BUFSIZE;
429         }
430
431         total_samples += s;
432
433         if(s < FLUID_BUFSIZE)
434         {
435             break;
436         }
437     }
438
439     fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, -start_block, total_samples - ((-start_block)*FLUID_BUFSIZE), dest_bufs, dest_bufcount);
440
441     if(total_samples < blockcount * FLUID_BUFSIZE)
442     {
443         fluid_finish_rvoice(buffers, rvoice);
444     }
445 }
446
447 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice)
448 {
449     int i;
450     fluid_rvoice_mixer_t *mixer = obj;
451     fluid_rvoice_t *voice = param[0].ptr;
452
453     if(mixer->active_voices < mixer->polyphony)
454     {
455         mixer->rvoices[mixer->active_voices++] = voice;
456         return; // success
457     }
458
459     /* See if any voices just finished, if so, take its place.
460        This can happen in voice overflow conditions. */
461     for(i = 0; i < mixer->active_voices; i++)
462     {
463         if(mixer->rvoices[i] == voice)
464         {
465             FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!");
466             return;
467         }
468
469         if(mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED)
470         {
471             fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]);
472             mixer->rvoices[i] = voice;
473             return; // success
474         }
475     }
476
477     /* This should never happen */
478     FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice");
479     return;
480 }
481
482 static int
483 fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t *buffers, int value)
484 {
485     void *newptr;
486
487     if(buffers->finished_voice_count > value)
488     {
489         return FLUID_FAILED;
490     }
491
492     newptr = FLUID_REALLOC(buffers->finished_voices, value * sizeof(fluid_rvoice_t *));
493
494     if(newptr == NULL && value > 0)
495     {
496         return FLUID_FAILED;
497     }
498
499     buffers->finished_voices = newptr;
500     return FLUID_OK;
501 }
502
503 /**
504  * Update polyphony - max number of voices (NOTE: not hard real-time capable)
505  * @return FLUID_OK or FLUID_FAILED
506  */
507 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony)
508 {
509     void *newptr;
510     fluid_rvoice_mixer_t *handler = obj;
511     int value = param[0].i;
512
513     if(handler->active_voices > value)
514     {
515         return /*FLUID_FAILED*/;
516     }
517
518     newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t *));
519
520     if(newptr == NULL)
521     {
522         return /*FLUID_FAILED*/;
523     }
524
525     handler->rvoices = newptr;
526
527     if(fluid_mixer_buffers_update_polyphony(&handler->buffers, value)
528             == FLUID_FAILED)
529     {
530         return /*FLUID_FAILED*/;
531     }
532
533 #if ENABLE_MIXER_THREADS
534     {
535         int i;
536
537         for(i = 0; i < handler->thread_count; i++)
538         {
539             if(fluid_mixer_buffers_update_polyphony(&handler->threads[i], value)
540                     == FLUID_FAILED)
541             {
542                 return /*FLUID_FAILED*/;
543             }
544         }
545     }
546 #endif
547
548     handler->polyphony = value;
549     return /*FLUID_OK*/;
550 }
551
552
553 static void
554 fluid_render_loop_singlethread(fluid_rvoice_mixer_t *mixer, int blockcount)
555 {
556     int i;
557     FLUID_DECLARE_VLA(fluid_real_t *, bufs,
558                       mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2);
559     int bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs);
560
561     fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT);
562
563     fluid_profile_ref_var(prof_ref);
564
565     for(i = 0; i < mixer->active_voices; i++)
566     {
567         fluid_mixer_buffers_render_one(&mixer->buffers, mixer->rvoices[i], bufs,
568                                        bufcount, local_buf, blockcount);
569         fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref, 1,
570                       blockcount * FLUID_BUFSIZE);
571     }
572 }
573
574 static FLUID_INLINE void
575 fluid_mixer_buffers_zero(fluid_mixer_buffers_t *buffers, int current_blockcount)
576 {
577     int i, size = current_blockcount * FLUID_BUFSIZE * sizeof(fluid_real_t);
578
579     /* TODO: Optimize by only zero out the buffers we actually use later on. */
580     int buf_count = buffers->buf_count, fx_buf_count = buffers->fx_buf_count;
581
582     fluid_real_t *FLUID_RESTRICT buf_l = fluid_align_ptr(buffers->left_buf, FLUID_DEFAULT_ALIGNMENT);
583     fluid_real_t *FLUID_RESTRICT buf_r = fluid_align_ptr(buffers->right_buf, FLUID_DEFAULT_ALIGNMENT);
584
585     for(i = 0; i < buf_count; i++)
586     {
587         FLUID_MEMSET(&buf_l[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size);
588         FLUID_MEMSET(&buf_r[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size);
589     }
590
591     buf_l = fluid_align_ptr(buffers->fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
592     buf_r = fluid_align_ptr(buffers->fx_right_buf, FLUID_DEFAULT_ALIGNMENT);
593
594     for(i = 0; i < fx_buf_count; i++)
595     {
596         FLUID_MEMSET(&buf_l[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size);
597         FLUID_MEMSET(&buf_r[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size);
598     }
599 }
600
601 static int
602 fluid_mixer_buffers_init(fluid_mixer_buffers_t *buffers, fluid_rvoice_mixer_t *mixer)
603 {
604     const int samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT;
605
606     buffers->mixer = mixer;
607     buffers->buf_count = mixer->buffers.buf_count;
608     buffers->fx_buf_count = mixer->buffers.fx_buf_count;
609
610     /* Local mono voice buf */
611     buffers->local_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, samplecount, FLUID_DEFAULT_ALIGNMENT);
612
613     /* Left and right audio buffers */
614
615     buffers->left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT);
616     buffers->right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT);
617
618     if((buffers->local_buf == NULL) || (buffers->left_buf == NULL) || (buffers->right_buf == NULL))
619     {
620         FLUID_LOG(FLUID_ERR, "Out of memory");
621         return 0;
622     }
623
624     /* Effects audio buffers */
625
626     buffers->fx_left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT);
627     buffers->fx_right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT);
628
629     if((buffers->fx_left_buf == NULL) || (buffers->fx_right_buf == NULL))
630     {
631         FLUID_LOG(FLUID_ERR, "Out of memory");
632         return 0;
633     }
634
635     buffers->finished_voices = NULL;
636
637     if(fluid_mixer_buffers_update_polyphony(buffers, mixer->polyphony)
638             == FLUID_FAILED)
639     {
640         FLUID_LOG(FLUID_ERR, "Out of memory");
641         return 0;
642     }
643
644     return 1;
645 }
646
647 /**
648  * Note: Not hard real-time capable (calls malloc)
649  */
650 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate)
651 {
652     fluid_rvoice_mixer_t *mixer = obj;
653     fluid_real_t samplerate = param[1].real; // becausee fluid_synth_update_mixer() puts real into arg2
654
655     int i;
656     for(i = 0; i < mixer->fx_units; i++)
657     {
658         if(mixer->fx[i].chorus)
659         {
660             delete_fluid_chorus(mixer->fx[i].chorus);
661         }
662
663         mixer->fx[i].chorus = new_fluid_chorus(samplerate);
664
665         if(mixer->fx[i].reverb)
666         {
667             fluid_revmodel_samplerate_change(mixer->fx[i].reverb, samplerate);
668         }
669     }
670
671 #if LADSPA
672
673     if(mixer->ladspa_fx != NULL)
674     {
675         fluid_ladspa_set_sample_rate(mixer->ladspa_fx, samplerate);
676     }
677
678 #endif
679 }
680
681
682 /**
683  * @param buf_count number of primary stereo buffers
684  * @param fx_buf_count number of stereo effect buffers
685  */
686 fluid_rvoice_mixer_t *
687 new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, int fx_units, fluid_real_t sample_rate, fluid_rvoice_eventhandler_t *evthandler, int extra_threads, int prio)
688 {
689     int i;
690     fluid_rvoice_mixer_t *mixer = FLUID_NEW(fluid_rvoice_mixer_t);
691
692     if(mixer == NULL)
693     {
694         FLUID_LOG(FLUID_ERR, "Out of memory");
695         return NULL;
696     }
697
698     FLUID_MEMSET(mixer, 0, sizeof(fluid_rvoice_mixer_t));
699     mixer->eventhandler = evthandler;
700     mixer->fx_units = fx_units;
701     mixer->buffers.buf_count = buf_count;
702     mixer->buffers.fx_buf_count = fx_buf_count * fx_units;
703
704     /* allocate the reverb module */
705     mixer->fx = FLUID_ARRAY(fluid_mixer_fx_t, fx_units);
706     if(mixer->fx == NULL)
707     {
708         FLUID_LOG(FLUID_ERR, "Out of memory");
709         goto error_recovery;
710     }
711     
712     FLUID_MEMSET(mixer->fx, 0, fx_units * sizeof(*mixer->fx));
713     
714     for(i = 0; i < fx_units; i++)
715     {
716         mixer->fx[i].reverb = new_fluid_revmodel(sample_rate);
717         mixer->fx[i].chorus = new_fluid_chorus(sample_rate);
718
719         if(mixer->fx[i].reverb == NULL || mixer->fx[i].chorus == NULL)
720         {
721             FLUID_LOG(FLUID_ERR, "Out of memory");
722             goto error_recovery;
723         }
724     }
725
726     if(!fluid_mixer_buffers_init(&mixer->buffers, mixer))
727     {
728         goto error_recovery;
729     }
730
731 #if ENABLE_MIXER_THREADS
732     mixer->thread_ready = new_fluid_cond();
733     mixer->wakeup_threads = new_fluid_cond();
734     mixer->thread_ready_m = new_fluid_cond_mutex();
735     mixer->wakeup_threads_m = new_fluid_cond_mutex();
736
737     if(!mixer->thread_ready || !mixer->wakeup_threads ||
738             !mixer->thread_ready_m || !mixer->wakeup_threads_m)
739     {
740         goto error_recovery;
741     }
742
743     if(fluid_rvoice_mixer_set_threads(mixer, extra_threads, prio) != FLUID_OK)
744     {
745         goto error_recovery;
746     }
747
748 #endif
749
750     return mixer;
751     
752 error_recovery:
753     delete_fluid_rvoice_mixer(mixer);
754     return NULL;
755 }
756
757 static void
758 fluid_mixer_buffers_free(fluid_mixer_buffers_t *buffers)
759 {
760     FLUID_FREE(buffers->finished_voices);
761
762     /* free all the sample buffers */
763     FLUID_FREE(buffers->local_buf);
764     FLUID_FREE(buffers->left_buf);
765     FLUID_FREE(buffers->right_buf);
766     FLUID_FREE(buffers->fx_left_buf);
767     FLUID_FREE(buffers->fx_right_buf);
768 }
769
770 void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *mixer)
771 {
772     int i;
773     
774     fluid_return_if_fail(mixer != NULL);
775
776 #if ENABLE_MIXER_THREADS
777     delete_rvoice_mixer_threads(mixer);
778
779     if(mixer->thread_ready)
780     {
781         delete_fluid_cond(mixer->thread_ready);
782     }
783
784     if(mixer->wakeup_threads)
785     {
786         delete_fluid_cond(mixer->wakeup_threads);
787     }
788
789     if(mixer->thread_ready_m)
790     {
791         delete_fluid_cond_mutex(mixer->thread_ready_m);
792     }
793
794     if(mixer->wakeup_threads_m)
795     {
796         delete_fluid_cond_mutex(mixer->wakeup_threads_m);
797     }
798
799 #endif
800     fluid_mixer_buffers_free(&mixer->buffers);
801
802     
803     for(i = 0; i < mixer->fx_units; i++)
804     {
805         if(mixer->fx[i].reverb)
806         {
807             delete_fluid_revmodel(mixer->fx[i].reverb);
808         }
809
810         if(mixer->fx[i].chorus)
811         {
812             delete_fluid_chorus(mixer->fx[i].chorus);
813         }
814     }
815
816     FLUID_FREE(mixer->fx);
817     FLUID_FREE(mixer->rvoices);
818     FLUID_FREE(mixer);
819 }
820
821
822 #ifdef LADSPA
823 /**
824  * Set a LADSPS fx instance to be used by the mixer and assign the mixer buffers
825  * as LADSPA host buffers with sensible names */
826 void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t *mixer,
827                                    fluid_ladspa_fx_t *ladspa_fx, int audio_groups)
828 {
829     mixer->ladspa_fx = ladspa_fx;
830
831     if(ladspa_fx == NULL)
832     {
833         return;
834     }
835     else
836     {
837         fluid_real_t *main_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT);
838         fluid_real_t *main_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT);
839
840         fluid_real_t *rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
841         fluid_real_t *chor = rev;
842
843         rev = &rev[SYNTH_REVERB_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT];
844         chor = &chor[SYNTH_CHORUS_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT];
845
846         fluid_ladspa_add_host_ports(ladspa_fx, "Main:L", audio_groups,
847                                     main_l,
848                                     FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
849
850         fluid_ladspa_add_host_ports(ladspa_fx, "Main:R", audio_groups,
851                                     main_r,
852                                     FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
853
854         fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:Send", 1,
855                                     rev,
856                                     FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
857
858         fluid_ladspa_add_host_ports(ladspa_fx, "Chorus:Send", 1,
859                                     chor,
860                                     FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
861     }
862 }
863 #endif
864
865 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled)
866 {
867     fluid_rvoice_mixer_t *mixer = obj;
868     int on = param[0].i;
869
870     mixer->with_reverb = on;
871 }
872
873 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled)
874 {
875     fluid_rvoice_mixer_t *mixer = obj;
876     int on = param[0].i;
877     mixer->with_chorus = on;
878 }
879
880 void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t *mixer, int on)
881 {
882     mixer->mix_fx_to_out = on;
883 }
884
885 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params)
886 {
887     fluid_rvoice_mixer_t *mixer = obj;
888     int set = param[0].i;
889     int nr = param[1].i;
890     fluid_real_t level = param[2].real;
891     fluid_real_t speed = param[3].real;
892     fluid_real_t depth_ms = param[4].real;
893     int type = param[5].i;
894
895     int i;
896     for(i = 0; i < mixer->fx_units; i++)
897     {
898         fluid_chorus_set(mixer->fx[i].chorus, set, nr, level, speed, depth_ms, type);
899     }
900 }
901
902 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params)
903 {
904     fluid_rvoice_mixer_t *mixer = obj;
905     int set = param[0].i;
906     fluid_real_t roomsize = param[1].real;
907     fluid_real_t damping = param[2].real;
908     fluid_real_t width = param[3].real;
909     fluid_real_t level = param[4].real;
910
911     int i;
912     for(i = 0; i < mixer->fx_units; i++)
913     {
914         fluid_revmodel_set(mixer->fx[i].reverb, set, roomsize, damping, width, level);
915     }
916 }
917
918 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_reverb)
919 {
920     fluid_rvoice_mixer_t *mixer = obj;
921     int i;
922     for(i = 0; i < mixer->fx_units; i++)
923     {
924         fluid_revmodel_reset(mixer->fx[i].reverb);
925     }
926 }
927
928 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus)
929 {
930     fluid_rvoice_mixer_t *mixer = obj;
931     int i;
932     for(i = 0; i < mixer->fx_units; i++)
933     {
934         fluid_chorus_reset(mixer->fx[i].chorus);
935     }
936 }
937
938 int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t *mixer,
939                                 fluid_real_t **left, fluid_real_t **right)
940 {
941     *left = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT);
942     *right = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT);
943     return mixer->buffers.buf_count;
944 }
945
946 int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t *mixer,
947                                    fluid_real_t **fx_left, fluid_real_t **fx_right)
948 {
949     *fx_left = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
950     *fx_right = fluid_align_ptr(mixer->buffers.fx_right_buf, FLUID_DEFAULT_ALIGNMENT);
951     return mixer->buffers.fx_buf_count;
952 }
953
954 int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t *mixer)
955 {
956     return FLUID_MIXER_MAX_BUFFERS_DEFAULT;
957 }
958
959 #if WITH_PROFILING
960 int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t *mixer)
961 {
962     return mixer->active_voices;
963 }
964 #endif
965
966 #if ENABLE_MIXER_THREADS
967
968 static FLUID_INLINE fluid_rvoice_t *
969 fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t *mixer)
970 {
971     int i = fluid_atomic_int_exchange_and_add(&mixer->current_rvoice, 1);
972
973     if(i >= mixer->active_voices)
974     {
975         return NULL;
976     }
977
978     return mixer->rvoices[i];
979 }
980
981 #define THREAD_BUF_PROCESSING 0
982 #define THREAD_BUF_VALID 1
983 #define THREAD_BUF_NODATA 2
984 #define THREAD_BUF_TERMINATE 3
985
986 /* Core thread function (processes voices in parallel to primary synthesis thread) */
987 static fluid_thread_return_t
988 fluid_mixer_thread_func(void *data)
989 {
990     fluid_mixer_buffers_t *buffers = data;
991     fluid_rvoice_mixer_t *mixer = buffers->mixer;
992     int hasValidData = 0;
993     FLUID_DECLARE_VLA(fluid_real_t *, bufs, buffers->buf_count * 2 + buffers->fx_buf_count * 2);
994     int bufcount = 0;
995     int current_blockcount = 0;
996     fluid_real_t *local_buf = fluid_align_ptr(buffers->local_buf, FLUID_DEFAULT_ALIGNMENT);
997
998     while(!fluid_atomic_int_get(&mixer->threads_should_terminate))
999     {
1000         fluid_rvoice_t *rvoice = fluid_mixer_get_mt_rvoice(mixer);
1001
1002         if(rvoice == NULL)
1003         {
1004             // if no voices: signal rendered buffers, sleep
1005             fluid_atomic_int_set(&buffers->ready, hasValidData ? THREAD_BUF_VALID : THREAD_BUF_NODATA);
1006             fluid_cond_mutex_lock(mixer->thread_ready_m);
1007             fluid_cond_signal(mixer->thread_ready);
1008             fluid_cond_mutex_unlock(mixer->thread_ready_m);
1009
1010             fluid_cond_mutex_lock(mixer->wakeup_threads_m);
1011
1012             while(1)
1013             {
1014                 int j = fluid_atomic_int_get(&buffers->ready);
1015
1016                 if(j == THREAD_BUF_PROCESSING || j == THREAD_BUF_TERMINATE)
1017                 {
1018                     break;
1019                 }
1020
1021                 fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m);
1022             }
1023
1024             fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
1025
1026             hasValidData = 0;
1027         }
1028         else
1029         {
1030             // else: if buffer is not zeroed, zero buffers
1031             if(!hasValidData)
1032             {
1033                 // blockcount may have changed, since thread was put to sleep
1034                 current_blockcount = mixer->current_blockcount;
1035                 fluid_mixer_buffers_zero(buffers, current_blockcount);
1036                 bufcount = fluid_mixer_buffers_prepare(buffers, bufs);
1037                 hasValidData = 1;
1038             }
1039
1040             // then render voice to buffers
1041             fluid_mixer_buffers_render_one(buffers, rvoice, bufs, bufcount, local_buf, current_blockcount);
1042         }
1043     }
1044
1045     return FLUID_THREAD_RETURN_VALUE;
1046 }
1047
1048 static void
1049 fluid_mixer_buffers_mix(fluid_mixer_buffers_t *dst, fluid_mixer_buffers_t *src, int current_blockcount)
1050 {
1051     int i, j;
1052     int scount = current_blockcount * FLUID_BUFSIZE;
1053     int minbuf;
1054     fluid_real_t *FLUID_RESTRICT base_src;
1055     fluid_real_t *FLUID_RESTRICT base_dst;
1056
1057     minbuf = dst->buf_count;
1058
1059     if(minbuf > src->buf_count)
1060     {
1061         minbuf = src->buf_count;
1062     }
1063
1064     base_src = fluid_align_ptr(src->left_buf, FLUID_DEFAULT_ALIGNMENT);
1065     base_dst = fluid_align_ptr(dst->left_buf, FLUID_DEFAULT_ALIGNMENT);
1066
1067     for(i = 0; i < minbuf; i++)
1068     {
1069         #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1070
1071         for(j = 0; j < scount; j++)
1072         {
1073             int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1074             base_dst[dsp_i] += base_src[dsp_i];
1075         }
1076     }
1077
1078     base_src = fluid_align_ptr(src->right_buf, FLUID_DEFAULT_ALIGNMENT);
1079     base_dst = fluid_align_ptr(dst->right_buf, FLUID_DEFAULT_ALIGNMENT);
1080
1081     for(i = 0; i < minbuf; i++)
1082     {
1083         #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1084
1085         for(j = 0; j < scount; j++)
1086         {
1087             int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1088             base_dst[dsp_i] += base_src[dsp_i];
1089         }
1090     }
1091
1092     minbuf = dst->fx_buf_count;
1093
1094     if(minbuf > src->fx_buf_count)
1095     {
1096         minbuf = src->fx_buf_count;
1097     }
1098
1099     base_src = fluid_align_ptr(src->fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
1100     base_dst = fluid_align_ptr(dst->fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
1101
1102     for(i = 0; i < minbuf; i++)
1103     {
1104         #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1105
1106         for(j = 0; j < scount; j++)
1107         {
1108             int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1109             base_dst[dsp_i] += base_src[dsp_i];
1110         }
1111     }
1112
1113     base_src = fluid_align_ptr(src->fx_right_buf, FLUID_DEFAULT_ALIGNMENT);
1114     base_dst = fluid_align_ptr(dst->fx_right_buf, FLUID_DEFAULT_ALIGNMENT);
1115
1116     for(i = 0; i < minbuf; i++)
1117     {
1118         #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1119
1120         for(j = 0; j < scount; j++)
1121         {
1122             int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1123             base_dst[dsp_i] += base_src[dsp_i];
1124         }
1125     }
1126 }
1127
1128
1129 /**
1130  * Go through all threads and see if someone is finished for mixing
1131  */
1132 static int
1133 fluid_mixer_mix_in(fluid_rvoice_mixer_t *mixer, int extra_threads, int current_blockcount)
1134 {
1135     int i, result, hasmixed;
1136
1137     do
1138     {
1139         hasmixed = 0;
1140         result = 0;
1141
1142         for(i = 0; i < extra_threads; i++)
1143         {
1144             int j = fluid_atomic_int_get(&mixer->threads[i].ready);
1145
1146             switch(j)
1147             {
1148             case THREAD_BUF_PROCESSING:
1149                 result = 1;
1150                 break;
1151
1152             case THREAD_BUF_VALID:
1153                 fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_NODATA);
1154                 fluid_mixer_buffers_mix(&mixer->buffers, &mixer->threads[i], current_blockcount);
1155                 hasmixed = 1;
1156                 break;
1157             }
1158         }
1159     }
1160     while(hasmixed);
1161
1162     return result;
1163 }
1164
1165 static void
1166 fluid_render_loop_multithread(fluid_rvoice_mixer_t *mixer, int current_blockcount)
1167 {
1168     int i, bufcount;
1169     fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT);
1170
1171     FLUID_DECLARE_VLA(fluid_real_t *, bufs,
1172                       mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2);
1173     // How many threads should we start this time?
1174     int extra_threads = mixer->active_voices / VOICES_PER_THREAD;
1175
1176     if(extra_threads > mixer->thread_count)
1177     {
1178         extra_threads = mixer->thread_count;
1179     }
1180
1181     if(extra_threads == 0)
1182     {
1183         // No extra threads? No thread overhead!
1184         fluid_render_loop_singlethread(mixer, current_blockcount);
1185         return;
1186     }
1187
1188     bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs);
1189
1190     // Prepare voice list
1191     fluid_cond_mutex_lock(mixer->wakeup_threads_m);
1192     fluid_atomic_int_set(&mixer->current_rvoice, 0);
1193
1194     for(i = 0; i < extra_threads; i++)
1195     {
1196         fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING);
1197     }
1198
1199     // Signal threads to wake up
1200     fluid_cond_broadcast(mixer->wakeup_threads);
1201     fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
1202
1203     // If thread is finished, mix it in
1204     while(fluid_mixer_mix_in(mixer, extra_threads, current_blockcount))
1205     {
1206         // Otherwise get a voice and render it
1207         fluid_rvoice_t *rvoice = fluid_mixer_get_mt_rvoice(mixer);
1208
1209         if(rvoice != NULL)
1210         {
1211             fluid_profile_ref_var(prof_ref);
1212             fluid_mixer_buffers_render_one(&mixer->buffers, rvoice, bufs, bufcount, local_buf, current_blockcount);
1213             fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref, 1,
1214                           current_blockcount * FLUID_BUFSIZE);
1215             //test++;
1216         }
1217         else
1218         {
1219             // If no voices, wait for mixes. Make sure one is still processing to avoid deadlock
1220             int is_processing = 0;
1221             //waits++;
1222             fluid_cond_mutex_lock(mixer->thread_ready_m);
1223
1224             for(i = 0; i < extra_threads; i++)
1225             {
1226                 if(fluid_atomic_int_get(&mixer->threads[i].ready) ==
1227                         THREAD_BUF_PROCESSING)
1228                 {
1229                     is_processing = 1;
1230                 }
1231             }
1232
1233             if(is_processing)
1234             {
1235                 fluid_cond_wait(mixer->thread_ready, mixer->thread_ready_m);
1236             }
1237
1238             fluid_cond_mutex_unlock(mixer->thread_ready_m);
1239         }
1240     }
1241
1242     //FLUID_LOG(FLUID_DBG, "Blockcount: %d, mixed %d of %d voices myself, waits = %d",
1243     //      current_blockcount, test, mixer->active_voices, waits);
1244 }
1245
1246 static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer)
1247 {
1248     int i;
1249     fluid_atomic_int_set(&mixer->threads_should_terminate, 1);
1250     // Signal threads to wake up
1251     fluid_cond_mutex_lock(mixer->wakeup_threads_m);
1252
1253     for(i = 0; i < mixer->thread_count; i++)
1254     {
1255         fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE);
1256     }
1257
1258     fluid_cond_broadcast(mixer->wakeup_threads);
1259     fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
1260
1261     for(i = 0; i < mixer->thread_count; i++)
1262     {
1263         if(mixer->threads[i].thread)
1264         {
1265             fluid_thread_join(mixer->threads[i].thread);
1266             delete_fluid_thread(mixer->threads[i].thread);
1267         }
1268
1269         fluid_mixer_buffers_free(&mixer->threads[i]);
1270     }
1271
1272     FLUID_FREE(mixer->threads);
1273     mixer->thread_count = 0;
1274     mixer->threads = NULL;
1275 }
1276
1277 /**
1278  * Update amount of extra mixer threads.
1279  * @param thread_count Number of extra mixer threads for multi-core rendering
1280  * @param prio_level real-time prio level for the extra mixer threads
1281  */
1282 static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level)
1283 {
1284     char name[16];
1285     int i;
1286
1287     // Kill all existing threads first
1288     if(mixer->thread_count)
1289     {
1290         delete_rvoice_mixer_threads(mixer);
1291     }
1292
1293     if(thread_count == 0)
1294     {
1295         return FLUID_OK;
1296     }
1297
1298     // Now prepare the new threads
1299     fluid_atomic_int_set(&mixer->threads_should_terminate, 0);
1300     mixer->threads = FLUID_ARRAY(fluid_mixer_buffers_t, thread_count);
1301
1302     if(mixer->threads == NULL)
1303     {
1304         FLUID_LOG(FLUID_ERR, "Out of memory");
1305         return FLUID_FAILED;
1306     }
1307
1308     FLUID_MEMSET(mixer->threads, 0, thread_count * sizeof(fluid_mixer_buffers_t));
1309     mixer->thread_count = thread_count;
1310
1311     for(i = 0; i < thread_count; i++)
1312     {
1313         fluid_mixer_buffers_t *b = &mixer->threads[i];
1314
1315         if(!fluid_mixer_buffers_init(b, mixer))
1316         {
1317             return FLUID_FAILED;
1318         }
1319
1320         fluid_atomic_int_set(&b->ready, THREAD_BUF_NODATA);
1321         FLUID_SNPRINTF(name, sizeof(name), "mixer%d", i);
1322         b->thread = new_fluid_thread(name, fluid_mixer_thread_func, b, prio_level, 0);
1323
1324         if(!b->thread)
1325         {
1326             return FLUID_FAILED;
1327         }
1328     }
1329
1330     return FLUID_OK;
1331 }
1332 #endif
1333
1334 /**
1335  * Synthesize audio into buffers
1336  * @param blockcount number of blocks to render, each having FLUID_BUFSIZE samples
1337  * @return number of blocks rendered
1338  */
1339 int
1340 fluid_rvoice_mixer_render(fluid_rvoice_mixer_t *mixer, int blockcount)
1341 {
1342     fluid_profile_ref_var(prof_ref);
1343
1344     mixer->current_blockcount = blockcount;
1345
1346     // Zero buffers
1347     fluid_mixer_buffers_zero(&mixer->buffers, blockcount);
1348     fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref, mixer->active_voices,
1349                   blockcount * FLUID_BUFSIZE);
1350
1351 #if ENABLE_MIXER_THREADS
1352
1353     if(mixer->thread_count > 0)
1354     {
1355         fluid_render_loop_multithread(mixer, blockcount);
1356     }
1357     else
1358 #endif
1359     {
1360         fluid_render_loop_singlethread(mixer, blockcount);
1361     }
1362
1363     fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref, mixer->active_voices,
1364                   blockcount * FLUID_BUFSIZE);
1365
1366
1367     // Process reverb & chorus
1368     fluid_rvoice_mixer_process_fx(mixer, blockcount);
1369
1370     // Call the callback and pack active voice array
1371     fluid_rvoice_mixer_process_finished_voices(mixer);
1372
1373     return blockcount;
1374 }