Give the Windows MMTimer test a better chance of passing
[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 Library General Public License
7  * as published by the Free Software Foundation; either version 2 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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_ladspa.h"
28
29 #define SYNTH_REVERB_CHANNEL 0
30 #define SYNTH_CHORUS_CHANNEL 1
31
32 #undef ENABLE_MIXER_THREADS // Ardour does the multithreading -- synth.cpu-cores defaults to 1
33
34 // If less than x voices, the thread overhead is larger than the gain,
35 // so don't activate the thread(s).
36 #define VOICES_PER_THREAD 8
37
38 typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t;
39
40 struct _fluid_mixer_buffers_t {
41   fluid_rvoice_mixer_t* mixer; /**< Owner of object */
42 #ifdef ENABLE_MIXER_THREADS
43   fluid_thread_t* thread;     /**< Thread object */
44 #endif
45
46   fluid_rvoice_t** finished_voices; /* List of voices who have finished */
47   int finished_voice_count;
48
49   int ready;             /**< Atomic: buffers are ready for mixing */
50
51   int buf_blocks;             /**< Number of blocks allocated in the buffers */
52
53   int buf_count;
54   fluid_real_t** left_buf;
55   fluid_real_t** right_buf;
56
57   int fx_buf_count;
58   fluid_real_t** fx_left_buf;
59   fluid_real_t** fx_right_buf;
60 };
61
62 typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t;
63
64 struct _fluid_mixer_fx_t {
65   fluid_revmodel_t* reverb; /**< Reverb unit */
66   fluid_chorus_t* chorus; /**< Chorus unit */
67   int with_reverb;        /**< Should the synth use the built-in reverb unit? */
68   int with_chorus;        /**< Should the synth use the built-in chorus unit? */
69   int mix_fx_to_out;      /**< Should the effects be mixed in with the primary output? */
70 };
71
72 struct _fluid_rvoice_mixer_t {
73   fluid_mixer_fx_t fx;
74
75   fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */
76   void (*remove_voice_callback)(void*, fluid_rvoice_t*); /**< Used by mixer only: Receive this callback every time a voice is removed */
77   void* remove_voice_callback_userdata;
78
79   fluid_rvoice_t** rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */
80   int polyphony; /**< Read-only: Length of voices array */
81   int active_voices; /**< Read-only: Number of non-null voices */
82   int current_blockcount;      /**< Read-only: how many blocks to process this time */
83
84 #ifdef LADSPA
85   fluid_LADSPA_FxUnit_t* LADSPA_FxUnit; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */
86 #endif
87
88 #ifdef ENABLE_MIXER_THREADS
89 //  int sleeping_threads;        /**< Atomic: number of threads currently asleep */
90 //  int active_threads;          /**< Atomic: number of threads in the thread loop */
91   int threads_should_terminate; /**< Atomic: Set to TRUE when threads should terminate */
92   int current_rvoice;           /**< Atomic: for the threads to know next voice to  */
93   fluid_cond_t* wakeup_threads; /**< Signalled when the threads should wake up */
94   fluid_cond_mutex_t* wakeup_threads_m; /**< wakeup_threads mutex companion */
95   fluid_cond_t* thread_ready; /**< Signalled from thread, when the thread has a buffer ready for mixing */
96   fluid_cond_mutex_t* thread_ready_m; /**< thread_ready mutex companion */
97
98   int thread_count;            /**< Number of extra mixer threads for multi-core rendering */
99   fluid_mixer_buffers_t* threads;    /**< Array of mixer threads (thread_count in length) */
100 #endif
101 };
102
103 static FLUID_INLINE void 
104 fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t* mixer)
105 {
106   int i;
107   fluid_profile_ref_var(prof_ref);
108   if (mixer->fx.with_reverb) {
109     if (mixer->fx.mix_fx_to_out) {
110       for (i=0; i < mixer->current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
111         fluid_revmodel_processmix(mixer->fx.reverb, 
112                                   &mixer->buffers.fx_left_buf[SYNTH_REVERB_CHANNEL][i],
113                                   &mixer->buffers.left_buf[0][i],
114                                   &mixer->buffers.right_buf[0][i]);
115     } 
116     else {
117       for (i=0; i < mixer->current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
118         fluid_revmodel_processreplace(mixer->fx.reverb, 
119                                   &mixer->buffers.fx_left_buf[SYNTH_REVERB_CHANNEL][i],
120                                   &mixer->buffers.fx_left_buf[SYNTH_REVERB_CHANNEL][i],
121                                   &mixer->buffers.fx_right_buf[SYNTH_REVERB_CHANNEL][i]);
122     }
123     fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref);
124   }
125   
126   if (mixer->fx.with_chorus) {
127     if (mixer->fx.mix_fx_to_out) {
128       for (i=0; i < mixer->current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
129         fluid_chorus_processmix(mixer->fx.chorus, 
130                                 &mixer->buffers.fx_left_buf[SYNTH_CHORUS_CHANNEL][i],
131                                 &mixer->buffers.left_buf[0][i],
132                                 &mixer->buffers.right_buf[0][i]);
133     } 
134     else {
135       for (i=0; i < mixer->current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
136         fluid_chorus_processreplace(mixer->fx.chorus, 
137                                 &mixer->buffers.fx_left_buf[SYNTH_CHORUS_CHANNEL][i],
138                                 &mixer->buffers.fx_left_buf[SYNTH_CHORUS_CHANNEL][i],
139                                 &mixer->buffers.fx_right_buf[SYNTH_CHORUS_CHANNEL][i]);
140     }
141     fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref);
142   }
143   
144 #ifdef LADSPA
145   /* Run the signal through the LADSPA Fx unit */
146   if (mixer->LADSPA_FxUnit) {
147     int j;
148     FLUID_DECLARE_VLA(fluid_real_t*, left_buf, mixer->buffers.buf_count);
149     FLUID_DECLARE_VLA(fluid_real_t*, right_buf, mixer->buffers.buf_count);
150     FLUID_DECLARE_VLA(fluid_real_t*, fx_left_buf, mixer->buffers.fx_buf_count);
151     FLUID_DECLARE_VLA(fluid_real_t*, fx_right_buf, mixer->buffers.fx_buf_count);
152     for (j=0; j < mixer->buffers.buf_count; j++) {
153       left_buf[j] = mixer->buffers.left_buf[j];
154       right_buf[j] = mixer->buffers.right_buf[j];
155     }
156     for (j=0; j < mixer->buffers.fx_buf_count; j++) {
157       fx_left_buf[j] = mixer->buffers.fx_left_buf[j];
158       fx_right_buf[j] = mixer->buffers.fx_right_buf[j];
159     }
160     for (i=0; i < mixer->current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE) {
161       fluid_LADSPA_run(mixer->LADSPA_FxUnit, left_buf, right_buf, fx_left_buf, 
162                        fx_right_buf);
163       for (j=0; j < mixer->buffers.buf_count; j++) {
164         left_buf[j] += FLUID_BUFSIZE;
165         right_buf[j] += FLUID_BUFSIZE;
166       }
167       for (j=0; j < mixer->buffers.fx_buf_count; j++) {
168         fx_left_buf[j] += FLUID_BUFSIZE;
169         fx_right_buf[j] += FLUID_BUFSIZE;
170       }
171     }
172     fluid_check_fpe("LADSPA");
173   }
174 #endif
175 }
176
177 /**
178  * During rendering, rvoices might be finished. Set this callback
179  * for getting a callback any time the rvoice is finished.
180  */
181 void fluid_rvoice_mixer_set_finished_voices_callback(
182   fluid_rvoice_mixer_t* mixer,
183   void (*func)(void*, fluid_rvoice_t*),
184   void* userdata)
185 {
186   mixer->remove_voice_callback_userdata = userdata;
187   mixer->remove_voice_callback = func;
188 }
189
190
191
192 /**
193  * Synthesize one voice and add to buffer.
194  * NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means 
195  * voice has been finished, removed and possibly replaced with another voice.
196  * @return Number of samples written 
197  */
198 static int
199 fluid_mix_one(fluid_rvoice_t* rvoice, fluid_real_t** bufs, unsigned int bufcount, int blockcount)
200 {
201   int i, result = 0;
202
203   FLUID_DECLARE_VLA(fluid_real_t, local_buf, FLUID_BUFSIZE*blockcount);
204
205   for (i=0; i < blockcount; i++) {
206     int s = fluid_rvoice_write(rvoice, &local_buf[FLUID_BUFSIZE*i]);
207     if (s == -1) {
208       s = FLUID_BUFSIZE; /* Voice is quiet, TODO: optimize away memset/mix */
209       FLUID_MEMSET(&local_buf[FLUID_BUFSIZE*i], 0, FLUID_BUFSIZE*sizeof(fluid_real_t));
210     } 
211     result += s;
212     if (s < FLUID_BUFSIZE) {
213       break;
214     }
215   }
216   fluid_rvoice_buffers_mix(&rvoice->buffers, local_buf, result, bufs, bufcount);
217
218   return result;
219 }
220
221 /**
222  * Glue to get fluid_rvoice_buffers_mix what it wants
223  * Note: Make sure outbufs has 2 * (buf_count + fx_buf_count) elements before calling
224  */
225 static FLUID_INLINE int 
226 fluid_mixer_buffers_prepare(fluid_mixer_buffers_t* buffers, fluid_real_t** outbufs)
227 {
228   fluid_real_t* reverb_buf, *chorus_buf;
229   int i;
230
231   /* Set up the reverb / chorus buffers only, when the effect is
232    * enabled on synth level.  Nonexisting buffers are detected in the
233    * DSP loop. Not sending the reverb / chorus signal saves some time
234    * in that case. */
235   reverb_buf = buffers->mixer->fx.with_reverb ? buffers->fx_left_buf[SYNTH_REVERB_CHANNEL] : NULL;
236   chorus_buf = buffers->mixer->fx.with_chorus ? buffers->fx_left_buf[SYNTH_CHORUS_CHANNEL] : NULL;
237   outbufs[buffers->buf_count*2 + SYNTH_REVERB_CHANNEL] = reverb_buf;
238   outbufs[buffers->buf_count*2 + SYNTH_CHORUS_CHANNEL] = chorus_buf;
239
240       /* The output associated with a MIDI channel is wrapped around
241        * using the number of audio groups as modulo divider.  This is
242        * typically the number of output channels on the 'sound card',
243        * as long as the LADSPA Fx unit is not used. In case of LADSPA
244        * unit, think of it as subgroups on a mixer.
245        *
246        * For example: Assume that the number of groups is set to 2.
247        * Then MIDI channel 1, 3, 5, 7 etc. go to output 1, channels 2,
248        * 4, 6, 8 etc to output 2.  Or assume 3 groups: Then MIDI
249        * channels 1, 4, 7, 10 etc go to output 1; 2, 5, 8, 11 etc to
250        * output 2, 3, 6, 9, 12 etc to output 3.
251        */
252
253   for (i = 0; i < buffers->buf_count; i++) {
254     outbufs[i*2] = buffers->left_buf[i];
255     outbufs[i*2+1] = buffers->right_buf[i];
256   }
257   return buffers->buf_count*2 + 2;
258 }
259
260
261 static FLUID_INLINE void
262 fluid_finish_rvoice(fluid_mixer_buffers_t* buffers, fluid_rvoice_t* rvoice)
263 {
264   if (buffers->finished_voice_count < buffers->mixer->polyphony)
265     buffers->finished_voices[buffers->finished_voice_count++] = rvoice;
266   else
267     FLUID_LOG(FLUID_ERR, "Exceeded finished voices array, try increasing polyphony");
268 }
269
270 static void   
271 fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t* buffers)
272 {
273   int i,j;
274   for (i=0; i < buffers->finished_voice_count; i++) {
275     fluid_rvoice_t* v = buffers->finished_voices[i];
276     int* av = &buffers->mixer->active_voices; 
277     for (j=0; j < *av; j++) {
278       if (v == buffers->mixer->rvoices[j]) {
279         (*av)--;
280         /* Pack the array */
281         if (j < *av) 
282           buffers->mixer->rvoices[j] = buffers->mixer->rvoices[*av];
283       }
284     }
285     if (buffers->mixer->remove_voice_callback)
286       buffers->mixer->remove_voice_callback(
287         buffers->mixer->remove_voice_callback_userdata, v);
288   }
289   buffers->finished_voice_count = 0;
290 }
291
292 static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice_mixer_t* mixer)
293 {
294 #ifdef ENABLE_MIXER_THREADS  
295   int i;
296   for (i=0; i < mixer->thread_count; i++)
297     fluid_mixer_buffer_process_finished_voices(&mixer->threads[i]);
298 #endif
299   fluid_mixer_buffer_process_finished_voices(&mixer->buffers);
300 }
301
302 static FLUID_INLINE void
303 fluid_mixer_buffers_render_one(fluid_mixer_buffers_t* buffers, 
304                                fluid_rvoice_t* voice, fluid_real_t** bufs, 
305                                unsigned int bufcount)
306 {
307   int s = fluid_mix_one(voice, bufs, bufcount, buffers->mixer->current_blockcount);
308   if (s < buffers->mixer->current_blockcount * FLUID_BUFSIZE) {
309     fluid_finish_rvoice(buffers, voice);
310   }
311 }
312 /*
313 static int fluid_mixer_buffers_replace_voice(fluid_mixer_buffers_t* buffers, 
314                                               fluid_rvoice_t* voice)
315 {
316   int i, retval=0;
317   int fvc = buffers->finished_voice_count;
318   for (i=0; i < fvc; i++)
319     if (buffers->finished_voices[i] == voice) {
320       fvc--;
321       if (i < fvc)
322         buffers->finished_voices[i] =  buffers->finished_voices[fvc];
323       retval++;
324     }
325   fvc = buffers->finished_voice_count;
326   return retval;  
327 }
328 */
329
330 int 
331 fluid_rvoice_mixer_add_voice(fluid_rvoice_mixer_t* mixer, fluid_rvoice_t* voice)
332 {
333   int i;
334
335   if (mixer->active_voices < mixer->polyphony) {
336     mixer->rvoices[mixer->active_voices++] = voice;
337     return FLUID_OK;
338   }
339   
340   /* See if any voices just finished, if so, take its place.
341      This can happen in voice overflow conditions. */
342   for (i=0; i < mixer->active_voices; i++) {
343     if (mixer->rvoices[i] == voice) {
344       FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!");
345       return FLUID_FAILED;
346     }
347     if (mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED) {
348       fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]);
349       mixer->rvoices[i] = voice;
350       return FLUID_OK;
351     }
352   }
353
354   /* This should never happen */
355   FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice");
356   return FLUID_FAILED;
357 }
358
359 static int 
360 fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t* buffers, int value)
361 {
362   void* newptr;
363
364   if (buffers->finished_voice_count > value) 
365     return FLUID_FAILED;
366   
367   newptr = FLUID_REALLOC(buffers->finished_voices, value * sizeof(fluid_rvoice_t*));
368   if (newptr == NULL && value > 0) 
369     return FLUID_FAILED;
370   buffers->finished_voices = newptr;  
371   return FLUID_OK;
372 }
373
374 /**
375  * Update polyphony - max number of voices (NOTE: not hard real-time capable)
376  * @return FLUID_OK or FLUID_FAILED
377  */
378 int 
379 fluid_rvoice_mixer_set_polyphony(fluid_rvoice_mixer_t* handler, int value)
380 {
381   void* newptr;
382   if (handler->active_voices > value) 
383     return FLUID_FAILED;
384
385   newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t*));
386   if (newptr == NULL) 
387     return FLUID_FAILED;
388   handler->rvoices = newptr;
389
390   if (fluid_mixer_buffers_update_polyphony(&handler->buffers, value) 
391       == FLUID_FAILED)
392     return FLUID_FAILED;
393
394 #ifdef ENABLE_MIXER_THREADS
395   {
396     int i;
397     for (i=0; i < handler->thread_count; i++)
398       if (fluid_mixer_buffers_update_polyphony(&handler->threads[i], value) 
399           == FLUID_FAILED)
400         return FLUID_FAILED;
401   }
402 #endif
403
404   handler->polyphony = value;
405   return FLUID_OK;
406 }
407
408
409 static void 
410 fluid_render_loop_singlethread(fluid_rvoice_mixer_t* mixer)
411 {
412   int i;
413   FLUID_DECLARE_VLA(fluid_real_t*, bufs, 
414                     mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2);
415   int bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs);
416   fluid_profile_ref_var(prof_ref);
417   for (i=0; i < mixer->active_voices; i++) {
418     fluid_mixer_buffers_render_one(&mixer->buffers, mixer->rvoices[i], bufs, 
419                                    bufcount);
420     fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref);
421   }
422 }
423
424
425 static FLUID_INLINE void
426 fluid_mixer_buffers_zero(fluid_mixer_buffers_t* buffers)
427 {
428   int i;
429   int size = buffers->mixer->current_blockcount * FLUID_BUFSIZE * sizeof(fluid_real_t);
430   /* TODO: Optimize by only zero out the buffers we actually use later on. */
431   for (i=0; i < buffers->buf_count; i++) {
432     FLUID_MEMSET(buffers->left_buf[i], 0, size);
433     FLUID_MEMSET(buffers->right_buf[i], 0, size);
434   }
435   for (i=0; i < buffers->fx_buf_count; i++) {
436     FLUID_MEMSET(buffers->fx_left_buf[i], 0, size);
437     FLUID_MEMSET(buffers->fx_right_buf[i], 0, size);
438   }
439 }
440
441
442
443 static int 
444 fluid_mixer_buffers_init(fluid_mixer_buffers_t* buffers, fluid_rvoice_mixer_t* mixer)
445 {
446   int i, samplecount;
447   
448   buffers->mixer = mixer;
449   buffers->buf_count = buffers->mixer->buffers.buf_count;
450   buffers->fx_buf_count = buffers->mixer->buffers.fx_buf_count;
451   buffers->buf_blocks = buffers->mixer->buffers.buf_blocks;
452   samplecount = FLUID_BUFSIZE * buffers->buf_blocks;
453   
454  
455   /* Left and right audio buffers */
456
457   buffers->left_buf = FLUID_ARRAY(fluid_real_t*, buffers->buf_count);
458   buffers->right_buf = FLUID_ARRAY(fluid_real_t*, buffers->buf_count);
459
460   if ((buffers->left_buf == NULL) || (buffers->right_buf == NULL)) {
461     FLUID_LOG(FLUID_ERR, "Out of memory");
462     return 0;
463   }
464
465   FLUID_MEMSET(buffers->left_buf, 0, buffers->buf_count * sizeof(fluid_real_t*));
466   FLUID_MEMSET(buffers->right_buf, 0, buffers->buf_count * sizeof(fluid_real_t*));
467
468   for (i = 0; i < buffers->buf_count; i++) {
469
470     buffers->left_buf[i] = FLUID_ARRAY(fluid_real_t, samplecount);
471     buffers->right_buf[i] = FLUID_ARRAY(fluid_real_t, samplecount);
472
473     if ((buffers->left_buf[i] == NULL) || (buffers->right_buf[i] == NULL)) {
474       FLUID_LOG(FLUID_ERR, "Out of memory");
475       return 0;
476     }
477   }
478
479   /* Effects audio buffers */
480
481   buffers->fx_left_buf = FLUID_ARRAY(fluid_real_t*, buffers->fx_buf_count);
482   buffers->fx_right_buf = FLUID_ARRAY(fluid_real_t*, buffers->fx_buf_count);
483
484   if ((buffers->fx_left_buf == NULL) || (buffers->fx_right_buf == NULL)) {
485     FLUID_LOG(FLUID_ERR, "Out of memory");
486     return 0;
487   }
488
489   FLUID_MEMSET(buffers->fx_left_buf, 0, buffers->fx_buf_count * sizeof(fluid_real_t*));
490   FLUID_MEMSET(buffers->fx_right_buf, 0, buffers->fx_buf_count * sizeof(fluid_real_t*));
491
492   for (i = 0; i < buffers->fx_buf_count; i++) {
493     buffers->fx_left_buf[i] = FLUID_ARRAY(fluid_real_t, samplecount);
494     buffers->fx_right_buf[i] = FLUID_ARRAY(fluid_real_t, samplecount);
495
496     if ((buffers->fx_left_buf[i] == NULL) || (buffers->fx_right_buf[i] == NULL)) {
497       FLUID_LOG(FLUID_ERR, "Out of memory");
498       return 0;
499     }
500   }
501   
502   buffers->finished_voices = NULL;
503   if (fluid_mixer_buffers_update_polyphony(buffers, mixer->polyphony) 
504       == FLUID_FAILED) {
505     FLUID_LOG(FLUID_ERR, "Out of memory");
506     return 0;
507   }
508   
509   return 1;
510 }
511
512 /**
513  * Note: Not hard real-time capable (calls malloc)
514  */
515 void 
516 fluid_rvoice_mixer_set_samplerate(fluid_rvoice_mixer_t* mixer, fluid_real_t samplerate)
517 {
518   int i;
519   if (mixer->fx.chorus)
520     delete_fluid_chorus(mixer->fx.chorus);
521   mixer->fx.chorus = new_fluid_chorus(samplerate);
522   if (mixer->fx.reverb)
523           fluid_revmodel_samplerate_change(mixer->fx.reverb, samplerate);
524   for (i=0; i < mixer->active_voices; i++)
525     fluid_rvoice_set_output_rate(mixer->rvoices[i], samplerate);
526 }
527
528
529 /**
530  * @param buf_count number of primary stereo buffers
531  * @param fx_buf_count number of stereo effect buffers
532  */
533 fluid_rvoice_mixer_t* 
534 new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, fluid_real_t sample_rate)
535 {
536   fluid_rvoice_mixer_t* mixer = FLUID_NEW(fluid_rvoice_mixer_t);
537   if (mixer == NULL) {
538     FLUID_LOG(FLUID_ERR, "Out of memory");
539     return NULL;
540   }
541   FLUID_MEMSET(mixer, 0, sizeof(fluid_rvoice_mixer_t));
542   mixer->buffers.buf_count = buf_count;
543   mixer->buffers.fx_buf_count = fx_buf_count;
544   mixer->buffers.buf_blocks = FLUID_MIXER_MAX_BUFFERS_DEFAULT;
545   
546   /* allocate the reverb module */
547   mixer->fx.reverb = new_fluid_revmodel(sample_rate);
548   mixer->fx.chorus = new_fluid_chorus(sample_rate);
549   if (mixer->fx.reverb == NULL) {
550     FLUID_LOG(FLUID_ERR, "Out of memory");
551     delete_fluid_rvoice_mixer(mixer);
552     return NULL;
553   }
554   
555   if (!fluid_mixer_buffers_init(&mixer->buffers, mixer)) {
556     delete_fluid_rvoice_mixer(mixer);
557     return NULL;
558   }
559   
560 #ifdef ENABLE_MIXER_THREADS
561   mixer->thread_ready = new_fluid_cond();
562   mixer->wakeup_threads = new_fluid_cond();
563   mixer->thread_ready_m = new_fluid_cond_mutex();
564   mixer->wakeup_threads_m = new_fluid_cond_mutex();
565   if (!mixer->thread_ready || !mixer->wakeup_threads || 
566       !mixer->thread_ready_m || !mixer->wakeup_threads_m) {
567     delete_fluid_rvoice_mixer(mixer);
568     return NULL;
569   }
570 #endif
571   
572   return mixer;
573 }
574
575 static void
576 fluid_mixer_buffers_free(fluid_mixer_buffers_t* buffers)
577 {
578   int i;
579   
580   FLUID_FREE(buffers->finished_voices);
581   
582   /* free all the sample buffers */
583   if (buffers->left_buf != NULL) {
584     for (i = 0; i < buffers->buf_count; i++) {
585       if (buffers->left_buf[i] != NULL) {
586         FLUID_FREE(buffers->left_buf[i]);
587       }
588     }
589     FLUID_FREE(buffers->left_buf);
590   }
591
592   if (buffers->right_buf != NULL) {
593     for (i = 0; i < buffers->buf_count; i++) {
594       if (buffers->right_buf[i] != NULL) {
595         FLUID_FREE(buffers->right_buf[i]);
596       }
597     }
598     FLUID_FREE(buffers->right_buf);
599   }
600
601   if (buffers->fx_left_buf != NULL) {
602     for (i = 0; i < buffers->fx_buf_count; i++) {
603       if (buffers->fx_left_buf[i] != NULL) {
604         FLUID_FREE(buffers->fx_left_buf[i]);
605       }
606     }
607     FLUID_FREE(buffers->fx_left_buf);
608   }
609
610   if (buffers->fx_right_buf != NULL) {
611     for (i = 0; i < buffers->fx_buf_count; i++) {
612       if (buffers->fx_right_buf[i] != NULL) {
613         FLUID_FREE(buffers->fx_right_buf[i]);
614       }
615     }
616     FLUID_FREE(buffers->fx_right_buf);
617   }  
618 }
619
620 void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t* mixer)
621 {
622   if (!mixer)
623     return;
624   fluid_rvoice_mixer_set_threads(mixer, 0, 0);
625 #ifdef ENABLE_MIXER_THREADS
626   if (mixer->thread_ready)
627     delete_fluid_cond(mixer->thread_ready);
628   if (mixer->wakeup_threads)
629     delete_fluid_cond(mixer->wakeup_threads);
630   if (mixer->thread_ready_m)
631     delete_fluid_cond_mutex(mixer->thread_ready_m);
632   if (mixer->wakeup_threads_m)
633     delete_fluid_cond_mutex(mixer->wakeup_threads_m);
634 #endif
635   fluid_mixer_buffers_free(&mixer->buffers);
636   if (mixer->fx.reverb)
637     delete_fluid_revmodel(mixer->fx.reverb);
638   if (mixer->fx.chorus)
639     delete_fluid_chorus(mixer->fx.chorus);
640   FLUID_FREE(mixer->rvoices);
641   FLUID_FREE(mixer);
642 }
643
644
645 #ifdef LADSPA                               
646 void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, 
647                                    fluid_LADSPA_FxUnit_t* ladspa)
648 {
649   mixer->LADSPA_FxUnit = ladspa;
650 }
651 #endif
652
653 void fluid_rvoice_mixer_set_reverb_enabled(fluid_rvoice_mixer_t* mixer, int on)
654 {
655   mixer->fx.with_reverb = on;
656 }
657
658 void fluid_rvoice_mixer_set_chorus_enabled(fluid_rvoice_mixer_t* mixer, int on)
659 {
660   mixer->fx.with_chorus = on;
661 }
662
663 void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t* mixer, int on)
664 {
665   mixer->fx.mix_fx_to_out = on;
666 }
667
668 void fluid_rvoice_mixer_set_chorus_params(fluid_rvoice_mixer_t* mixer, int set, 
669                                          int nr, double level, double speed, 
670                                          double depth_ms, int type)
671 {
672   fluid_chorus_set(mixer->fx.chorus, set, nr, level, speed, depth_ms, type);
673 }
674 void fluid_rvoice_mixer_set_reverb_params(fluid_rvoice_mixer_t* mixer, int set, 
675                                          double roomsize, double damping, 
676                                          double width, double level)
677 {
678   fluid_revmodel_set(mixer->fx.reverb, set, roomsize, damping, width, level); 
679 }
680
681 void fluid_rvoice_mixer_reset_fx(fluid_rvoice_mixer_t* mixer)
682 {
683   fluid_revmodel_reset(mixer->fx.reverb);
684   fluid_chorus_reset(mixer->fx.chorus);
685 }
686
687 void fluid_rvoice_mixer_reset_reverb(fluid_rvoice_mixer_t* mixer)
688 {
689   fluid_revmodel_reset(mixer->fx.reverb);
690 }
691
692 void fluid_rvoice_mixer_reset_chorus(fluid_rvoice_mixer_t* mixer)
693 {
694   fluid_chorus_reset(mixer->fx.chorus);
695 }
696
697 int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t* mixer, 
698                                   fluid_real_t*** left, fluid_real_t*** right)
699 {
700   *left = mixer->buffers.left_buf;
701   *right = mixer->buffers.right_buf;
702   return mixer->buffers.buf_count;
703 }
704
705
706 #ifdef ENABLE_MIXER_THREADS
707
708 static FLUID_INLINE fluid_rvoice_t* 
709 fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t* mixer)
710 {
711   int i = fluid_atomic_int_exchange_and_add(&mixer->current_rvoice, 1);
712   if (i >= mixer->active_voices) 
713     return NULL;
714   return mixer->rvoices[i];
715 }
716
717 #define THREAD_BUF_PROCESSING 0
718 #define THREAD_BUF_VALID 1
719 #define THREAD_BUF_NODATA 2
720 #define THREAD_BUF_TERMINATE 3
721
722 /* Core thread function (processes voices in parallel to primary synthesis thread) */
723 static void
724 fluid_mixer_thread_func (void* data)
725 {
726   fluid_mixer_buffers_t* buffers = data;  
727   fluid_rvoice_mixer_t* mixer = buffers->mixer;
728   int hasValidData = 0;
729   FLUID_DECLARE_VLA(fluid_real_t*, bufs, buffers->buf_count*2 + buffers->fx_buf_count*2);
730   int bufcount = 0;
731   
732   while (!fluid_atomic_int_get(&mixer->threads_should_terminate)) {
733     fluid_rvoice_t* rvoice = fluid_mixer_get_mt_rvoice(mixer);
734     if (rvoice == NULL) {
735       // if no voices: signal rendered buffers, sleep
736       fluid_atomic_int_set(&buffers->ready, hasValidData ? THREAD_BUF_VALID : THREAD_BUF_NODATA);
737       fluid_cond_mutex_lock(mixer->thread_ready_m);
738       fluid_cond_signal(mixer->thread_ready);
739       fluid_cond_mutex_unlock(mixer->thread_ready_m);
740       
741       fluid_cond_mutex_lock(mixer->wakeup_threads_m);
742       while (1) {
743         int j = fluid_atomic_int_get(&buffers->ready); 
744         if (j == THREAD_BUF_PROCESSING || j == THREAD_BUF_TERMINATE)
745           break;
746         fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m);
747       }
748       fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
749       
750       hasValidData = 0;
751     }
752     else {
753       // else: if buffer is not zeroed, zero buffers
754       if (!hasValidData) {
755         fluid_mixer_buffers_zero(buffers);
756         bufcount = fluid_mixer_buffers_prepare(buffers, bufs);
757         hasValidData = 1;
758       }
759       // then render voice to buffers
760       fluid_mixer_buffers_render_one(buffers, rvoice, bufs, bufcount);
761     }
762   }
763
764 }
765
766 static void
767 fluid_mixer_buffers_mix(fluid_mixer_buffers_t* dest, fluid_mixer_buffers_t* src)
768 {
769   int i,j;
770   int scount = dest->mixer->current_blockcount * FLUID_BUFSIZE;
771   int minbuf;
772   
773   minbuf = dest->buf_count;
774   if (minbuf > src->buf_count)
775     minbuf = src->buf_count;
776   for (i=0; i < minbuf; i++) {
777     for (j=0; j < scount; j++) {
778       dest->left_buf[i][j] += src->left_buf[i][j];
779       dest->right_buf[i][j] += src->right_buf[i][j];
780     }
781   }
782
783   minbuf = dest->fx_buf_count;
784   if (minbuf > src->fx_buf_count)
785     minbuf = src->fx_buf_count;
786   for (i=0; i < minbuf; i++) {
787     for (j=0; j < scount; j++) {
788       dest->fx_left_buf[i][j] += src->fx_left_buf[i][j];
789       dest->fx_right_buf[i][j] += src->fx_right_buf[i][j];
790     }
791   }
792 }
793
794
795 /**
796  * Go through all threads and see if someone is finished for mixing 
797  */
798 static FLUID_INLINE int
799 fluid_mixer_mix_in(fluid_rvoice_mixer_t* mixer, int extra_threads)
800 {
801   int i, result, hasmixed;
802   do {
803     hasmixed = 0;
804     result = 0;
805     for (i=0; i < extra_threads; i++) {
806       int j = fluid_atomic_int_get(&mixer->threads[i].ready);
807       switch (j) {
808         case THREAD_BUF_PROCESSING: 
809           result = 1;
810           break;
811         case THREAD_BUF_VALID:
812           fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_NODATA);
813           fluid_mixer_buffers_mix(&mixer->buffers, &mixer->threads[i]);
814           hasmixed = 1;
815           break;
816       }
817     }
818   } while (hasmixed);
819   return result;
820 }
821
822 static void 
823 fluid_render_loop_multithread(fluid_rvoice_mixer_t* mixer)
824 {
825   int i, bufcount;
826   //int scount = mixer->current_blockcount * FLUID_BUFSIZE;
827   FLUID_DECLARE_VLA(fluid_real_t*, bufs, 
828                     mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2);
829   // How many threads should we start this time?
830   int extra_threads = mixer->active_voices / VOICES_PER_THREAD;
831   if (extra_threads > mixer->thread_count)
832     extra_threads = mixer->thread_count;
833   if (extra_threads == 0) {
834     // No extra threads? No thread overhead!
835     fluid_render_loop_singlethread(mixer);
836     return;
837   }
838
839   bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs);
840   
841   // Prepare voice list
842   fluid_cond_mutex_lock(mixer->wakeup_threads_m);
843   fluid_atomic_int_set(&mixer->current_rvoice, 0);
844   for (i=0; i < extra_threads; i++)
845     fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING);
846   // Signal threads to wake up
847   fluid_cond_broadcast(mixer->wakeup_threads);
848   fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
849   
850   // If thread is finished, mix it in
851   while (fluid_mixer_mix_in(mixer, extra_threads)) {
852     // Otherwise get a voice and render it
853     fluid_rvoice_t* rvoice = fluid_mixer_get_mt_rvoice(mixer);
854     if (rvoice != NULL) {
855       fluid_profile_ref_var(prof_ref);
856       fluid_mixer_buffers_render_one(&mixer->buffers, rvoice, bufs, bufcount);
857       fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref);
858       //test++;
859     }
860     else {
861       // If no voices, wait for mixes. Make sure one is still processing to avoid deadlock
862       int is_processing = 0;
863       //waits++;
864       fluid_cond_mutex_lock(mixer->thread_ready_m);
865       for (i=0; i < extra_threads; i++) 
866         if (fluid_atomic_int_get(&mixer->threads[i].ready) == 
867             THREAD_BUF_PROCESSING)
868           is_processing = 1;
869       if (is_processing) 
870         fluid_cond_wait(mixer->thread_ready, mixer->thread_ready_m);
871       fluid_cond_mutex_unlock(mixer->thread_ready_m);
872     }
873   }
874   //FLUID_LOG(FLUID_DBG, "Blockcount: %d, mixed %d of %d voices myself, waits = %d", 
875   //        mixer->current_blockcount, test, mixer->active_voices, waits);
876 }
877
878 #endif
879
880 /**
881  * Update amount of extra mixer threads. 
882  * @param thread_count Number of extra mixer threads for multi-core rendering
883  * @param prio_level real-time prio level for the extra mixer threads
884  */
885 void 
886 fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_count, 
887                                int prio_level)
888 {
889 #ifdef ENABLE_MIXER_THREADS
890   char name[16];
891   int i;
892  
893   // Kill all existing threads first
894   if (mixer->thread_count) {
895     fluid_atomic_int_set(&mixer->threads_should_terminate, 1);
896     // Signal threads to wake up
897     fluid_cond_mutex_lock(mixer->wakeup_threads_m);
898     for (i=0; i < mixer->thread_count; i++)
899       fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE);
900     fluid_cond_broadcast(mixer->wakeup_threads);
901     fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
902   
903     for (i=0; i < mixer->thread_count; i++) {
904       if (mixer->threads[i].thread) {
905         fluid_thread_join(mixer->threads[i].thread);
906         delete_fluid_thread(mixer->threads[i].thread);
907       }
908       fluid_mixer_buffers_free(&mixer->threads[i]);
909     }
910     FLUID_FREE(mixer->threads);
911     mixer->thread_count = 0;
912     mixer->threads = NULL;
913   }
914   
915   if (thread_count == 0) 
916     return;
917   
918   // Now prepare the new threads
919   fluid_atomic_int_set(&mixer->threads_should_terminate, 0);
920   mixer->threads = FLUID_ARRAY(fluid_mixer_buffers_t, thread_count);
921   if (mixer->threads == NULL) {
922     FLUID_LOG(FLUID_ERR, "Out of memory");
923     return;
924   }
925   FLUID_MEMSET(mixer->threads, 0, thread_count*sizeof(fluid_mixer_buffers_t));
926   mixer->thread_count = thread_count;
927   for (i=0; i < thread_count; i++) {
928     fluid_mixer_buffers_t* b = &mixer->threads[i]; 
929     if (!fluid_mixer_buffers_init(b, mixer))
930       return;
931     fluid_atomic_int_set(&b->ready, THREAD_BUF_NODATA);
932     g_snprintf (name, sizeof (name), "mixer%d", i);
933     b->thread = new_fluid_thread(name, fluid_mixer_thread_func, b, prio_level, 0);
934     if (!b->thread)
935       return;
936   }
937
938 #endif
939 }
940
941 /**
942  * Synthesize audio into buffers
943  * @param blockcount number of blocks to render, each having FLUID_BUFSIZE samples 
944  * @return number of blocks rendered
945  */
946 int 
947 fluid_rvoice_mixer_render(fluid_rvoice_mixer_t* mixer, int blockcount)
948 {
949   fluid_profile_ref_var(prof_ref);
950   
951   mixer->current_blockcount = blockcount > mixer->buffers.buf_blocks ? 
952       mixer->buffers.buf_blocks : blockcount;
953
954   // Zero buffers
955   fluid_mixer_buffers_zero(&mixer->buffers);
956   fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref);
957   
958 #ifdef ENABLE_MIXER_THREADS
959   if (mixer->thread_count > 0)
960     fluid_render_loop_multithread(mixer);
961   else
962 #endif
963     fluid_render_loop_singlethread(mixer);
964   fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref);
965     
966
967   // Process reverb & chorus
968   fluid_rvoice_mixer_process_fx(mixer);
969
970   // Call the callback and pack active voice array
971   fluid_rvoice_mixer_process_finished_voices(mixer);
972
973   return mixer->current_blockcount;
974 }