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