1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
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.
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.
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
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"
29 #undef ENABLE_MIXER_THREADS // Ardour does the multithreading -- synth.cpu-cores defaults to 1
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
35 typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t;
37 struct _fluid_mixer_buffers_t
39 fluid_rvoice_mixer_t *mixer; /**< Owner of object */
40 #if ENABLE_MIXER_THREADS
41 fluid_thread_t *thread; /**< Thread object */
44 fluid_rvoice_t **finished_voices; /* List of voices who have finished */
45 int finished_voice_count;
47 fluid_atomic_int_t ready; /**< Atomic: buffers are ready for mixing */
49 fluid_real_t *local_buf;
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()
63 fluid_real_t *left_buf;
65 /** dito, but for right part of a stereo channel */
66 fluid_real_t *right_buf;
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)
73 fluid_real_t *fx_left_buf;
74 fluid_real_t *fx_right_buf;
77 typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t;
79 struct _fluid_mixer_fx_t
81 fluid_revmodel_t *reverb; /**< Reverb unit */
82 fluid_chorus_t *chorus; /**< Chorus unit */
85 struct _fluid_rvoice_mixer_t
89 fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */
90 fluid_rvoice_eventhandler_t *eventhandler;
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 */
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? */
102 fluid_ladspa_fx_t *ladspa_fx; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */
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 */
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) */
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);
125 static FLUID_INLINE void
126 fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcount)
128 const int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
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);
134 fluid_real_t *out_rev_l, *out_rev_r, *out_ch_l, *out_ch_r;
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;
140 fluid_profile_ref_var(prof_ref);
143 if(mixer->mix_fx_to_out)
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);
149 reverb_process_func = fluid_revmodel_processmix;
150 chorus_process_func = fluid_chorus_processmix;
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);
159 reverb_process_func = fluid_revmodel_processreplace;
160 chorus_process_func = fluid_chorus_processreplace;
164 if(mixer->with_reverb)
166 for(f = 0; f < mixer->fx_units; f++)
168 int buf_idx = f * fx_channels_per_unit + SYNTH_REVERB_CHANNEL;
170 for(i = 0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
172 int samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + i;
174 reverb_process_func(mixer->fx[f].reverb,
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]);
181 fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref, 0,
182 current_blockcount * FLUID_BUFSIZE);
185 if(mixer->with_chorus)
187 for(f = 0; f < mixer->fx_units; f++)
189 int buf_idx = f * fx_channels_per_unit + SYNTH_CHORUS_CHANNEL;
191 for(i = 0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE)
193 int samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + i;
195 chorus_process_func(mixer->fx[f].chorus,
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]);
202 fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref, 0,
203 current_blockcount * FLUID_BUFSIZE);
208 /* Run the signal through the LADSPA Fx unit. The buffers have already been
209 * set up in fluid_rvoice_mixer_set_ladspa. */
212 fluid_ladspa_run(mixer->ladspa_fx, current_blockcount, FLUID_BUFSIZE);
213 fluid_check_fpe("LADSPA");
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
223 static FLUID_INLINE int
224 fluid_mixer_buffers_prepare(fluid_mixer_buffers_t *buffers, fluid_real_t **outbufs)
226 fluid_real_t *base_ptr;
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;
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. */
237 int with_ladspa = (buffers->mixer->ladspa_fx != NULL);
238 with_reverb = (with_reverb | with_ladspa);
239 with_chorus = (with_chorus | with_ladspa);
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);
245 for(i = 0; i < buffers->mixer->fx_units; i++)
247 int fx_idx = i * fx_channels_per_unit;
249 outbufs[offset + fx_idx + SYNTH_REVERB_CHANNEL] =
251 ? &base_ptr[(fx_idx + SYNTH_REVERB_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]
254 outbufs[offset + fx_idx + SYNTH_CHORUS_CHANNEL] =
256 ? &base_ptr[(fx_idx + SYNTH_CHORUS_CHANNEL) * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]
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.
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.
272 base_ptr = fluid_align_ptr(buffers->left_buf, FLUID_DEFAULT_ALIGNMENT);
274 for(i = 0; i < buffers->buf_count; i++)
276 outbufs[i * 2] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT];
279 base_ptr = fluid_align_ptr(buffers->right_buf, FLUID_DEFAULT_ALIGNMENT);
281 for(i = 0; i < buffers->buf_count; i++)
283 outbufs[i * 2 + 1] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT];
286 return offset + buffers->fx_buf_count;
290 static FLUID_INLINE void
291 fluid_finish_rvoice(fluid_mixer_buffers_t *buffers, fluid_rvoice_t *rvoice)
293 if(buffers->finished_voice_count < buffers->mixer->polyphony)
295 buffers->finished_voices[buffers->finished_voice_count++] = rvoice;
299 FLUID_LOG(FLUID_ERR, "Exceeded finished voices array, try increasing polyphony");
304 fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t *buffers)
308 for(i = 0; i < buffers->finished_voice_count; i++)
310 fluid_rvoice_t *v = buffers->finished_voices[i];
311 int av = buffers->mixer->active_voices;
313 for(j = 0; j < av; j++)
315 if(v == buffers->mixer->rvoices[j])
322 buffers->mixer->rvoices[j] = buffers->mixer->rvoices[av];
327 buffers->mixer->active_voices = av;
329 fluid_rvoice_eventhandler_finished_voice_callback(buffers->mixer->eventhandler, v);
332 buffers->finished_voice_count = 0;
335 static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice_mixer_t *mixer)
337 #if ENABLE_MIXER_THREADS
340 for(i = 0; i < mixer->thread_count; i++)
342 fluid_mixer_buffer_process_finished_voices(&mixer->threads[i]);
346 fluid_mixer_buffer_process_finished_voices(&mixer->buffers);
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)
354 int j = buffers->bufs[index].mapping;
356 if(j >= dest_bufcount || j < 0)
365 * Mix data down to buffers
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
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)
380 int bufcount = buffers->count;
383 if(sample_count <= 0 || dest_bufcount <= 0)
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);
391 for(i = 0; i < bufcount; i++)
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;
396 if(buf == NULL || amp == 0.0f)
401 FLUID_ASSERT((uintptr_t)buf % FLUID_DEFAULT_ALIGNMENT == 0);
403 #pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT)
405 for(dsp_i = (start_block * FLUID_BUFSIZE); dsp_i < sample_count; dsp_i++)
407 buf[dsp_i] += amp * dsp_buf[dsp_i];
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.
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)
422 int i, total_samples = 0, start_block = 0;
424 for(i = 0; i < blockcount; i++)
426 int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE * i]);
436 if(s < FLUID_BUFSIZE)
442 fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, -start_block, total_samples - ((-start_block)*FLUID_BUFSIZE), dest_bufs, dest_bufcount);
444 if(total_samples < blockcount * FLUID_BUFSIZE)
446 fluid_finish_rvoice(buffers, rvoice);
450 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice)
453 fluid_rvoice_mixer_t *mixer = obj;
454 fluid_rvoice_t *voice = param[0].ptr;
456 if(mixer->active_voices < mixer->polyphony)
458 mixer->rvoices[mixer->active_voices++] = voice;
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++)
466 if(mixer->rvoices[i] == voice)
468 FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!");
472 if(mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED)
474 fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]);
475 mixer->rvoices[i] = voice;
480 /* This should never happen */
481 FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice");
486 fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t *buffers, int value)
490 if(buffers->finished_voice_count > value)
495 newptr = FLUID_REALLOC(buffers->finished_voices, value * sizeof(fluid_rvoice_t *));
497 if(newptr == NULL && value > 0)
502 buffers->finished_voices = newptr;
507 * Update polyphony - max number of voices (NOTE: not hard real-time capable)
508 * @return FLUID_OK or FLUID_FAILED
510 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony)
513 fluid_rvoice_mixer_t *handler = obj;
514 int value = param[0].i;
516 if(handler->active_voices > value)
518 return /*FLUID_FAILED*/;
521 newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t *));
525 return /*FLUID_FAILED*/;
528 handler->rvoices = newptr;
530 if(fluid_mixer_buffers_update_polyphony(&handler->buffers, value)
533 return /*FLUID_FAILED*/;
536 #if ENABLE_MIXER_THREADS
540 for(i = 0; i < handler->thread_count; i++)
542 if(fluid_mixer_buffers_update_polyphony(&handler->threads[i], value)
545 return /*FLUID_FAILED*/;
551 handler->polyphony = value;
557 fluid_render_loop_singlethread(fluid_rvoice_mixer_t *mixer, int blockcount)
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);
564 fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT);
566 fluid_profile_ref_var(prof_ref);
568 for(i = 0; i < mixer->active_voices; i++)
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);
577 static FLUID_INLINE void
578 fluid_mixer_buffers_zero(fluid_mixer_buffers_t *buffers, int current_blockcount)
580 int i, size = current_blockcount * FLUID_BUFSIZE * sizeof(fluid_real_t);
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;
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);
588 for(i = 0; i < buf_count; i++)
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);
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);
597 for(i = 0; i < fx_buf_count; i++)
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);
605 fluid_mixer_buffers_init(fluid_mixer_buffers_t *buffers, fluid_rvoice_mixer_t *mixer)
607 const int samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT;
609 buffers->mixer = mixer;
610 buffers->buf_count = mixer->buffers.buf_count;
611 buffers->fx_buf_count = mixer->buffers.fx_buf_count;
613 /* Local mono voice buf */
614 buffers->local_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, samplecount, FLUID_DEFAULT_ALIGNMENT);
616 /* Left and right audio buffers */
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);
621 if((buffers->local_buf == NULL) || (buffers->left_buf == NULL) || (buffers->right_buf == NULL))
623 FLUID_LOG(FLUID_ERR, "Out of memory");
627 /* Effects audio buffers */
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);
632 if((buffers->fx_left_buf == NULL) || (buffers->fx_right_buf == NULL))
634 FLUID_LOG(FLUID_ERR, "Out of memory");
638 buffers->finished_voices = NULL;
640 if(fluid_mixer_buffers_update_polyphony(buffers, mixer->polyphony)
643 FLUID_LOG(FLUID_ERR, "Out of memory");
651 * Note: Not hard real-time capable (calls malloc)
653 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate)
655 fluid_rvoice_mixer_t *mixer = obj;
656 fluid_real_t samplerate = param[1].real; // becausee fluid_synth_update_mixer() puts real into arg2
659 for(i = 0; i < mixer->fx_units; i++)
661 if(mixer->fx[i].chorus)
663 delete_fluid_chorus(mixer->fx[i].chorus);
666 mixer->fx[i].chorus = new_fluid_chorus(samplerate);
668 if(mixer->fx[i].reverb)
670 fluid_revmodel_samplerate_change(mixer->fx[i].reverb, samplerate);
676 if(mixer->ladspa_fx != NULL)
678 fluid_ladspa_set_sample_rate(mixer->ladspa_fx, samplerate);
686 * @param buf_count number of primary stereo buffers
687 * @param fx_buf_count number of stereo effect buffers
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)
693 fluid_rvoice_mixer_t *mixer = FLUID_NEW(fluid_rvoice_mixer_t);
697 FLUID_LOG(FLUID_ERR, "Out of memory");
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;
707 /* allocate the reverb module */
708 mixer->fx = FLUID_ARRAY(fluid_mixer_fx_t, fx_units);
709 if(mixer->fx == NULL)
711 FLUID_LOG(FLUID_ERR, "Out of memory");
715 FLUID_MEMSET(mixer->fx, 0, fx_units * sizeof(*mixer->fx));
717 for(i = 0; i < fx_units; i++)
719 mixer->fx[i].reverb = new_fluid_revmodel(sample_rate);
720 mixer->fx[i].chorus = new_fluid_chorus(sample_rate);
722 if(mixer->fx[i].reverb == NULL || mixer->fx[i].chorus == NULL)
724 FLUID_LOG(FLUID_ERR, "Out of memory");
729 if(!fluid_mixer_buffers_init(&mixer->buffers, mixer))
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();
740 if(!mixer->thread_ready || !mixer->wakeup_threads ||
741 !mixer->thread_ready_m || !mixer->wakeup_threads_m)
746 if(fluid_rvoice_mixer_set_threads(mixer, extra_threads, prio) != FLUID_OK)
756 delete_fluid_rvoice_mixer(mixer);
761 fluid_mixer_buffers_free(fluid_mixer_buffers_t *buffers)
763 FLUID_FREE(buffers->finished_voices);
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);
773 void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *mixer)
777 fluid_return_if_fail(mixer != NULL);
779 #if ENABLE_MIXER_THREADS
780 delete_rvoice_mixer_threads(mixer);
782 if(mixer->thread_ready)
784 delete_fluid_cond(mixer->thread_ready);
787 if(mixer->wakeup_threads)
789 delete_fluid_cond(mixer->wakeup_threads);
792 if(mixer->thread_ready_m)
794 delete_fluid_cond_mutex(mixer->thread_ready_m);
797 if(mixer->wakeup_threads_m)
799 delete_fluid_cond_mutex(mixer->wakeup_threads_m);
803 fluid_mixer_buffers_free(&mixer->buffers);
806 for(i = 0; i < mixer->fx_units; i++)
808 if(mixer->fx[i].reverb)
810 delete_fluid_revmodel(mixer->fx[i].reverb);
813 if(mixer->fx[i].chorus)
815 delete_fluid_chorus(mixer->fx[i].chorus);
819 FLUID_FREE(mixer->fx);
820 FLUID_FREE(mixer->rvoices);
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)
832 mixer->ladspa_fx = ladspa_fx;
834 if(ladspa_fx == NULL)
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);
843 fluid_real_t *rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT);
844 fluid_real_t *chor = rev;
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];
849 fluid_ladspa_add_host_ports(ladspa_fx, "Main:L", audio_groups,
851 FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
853 fluid_ladspa_add_host_ports(ladspa_fx, "Main:R", audio_groups,
855 FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
857 fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:Send", 1,
859 FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
861 fluid_ladspa_add_host_ports(ladspa_fx, "Chorus:Send", 1,
863 FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT);
868 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled)
870 fluid_rvoice_mixer_t *mixer = obj;
873 mixer->with_reverb = on;
876 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled)
878 fluid_rvoice_mixer_t *mixer = obj;
880 mixer->with_chorus = on;
883 void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t *mixer, int on)
885 mixer->mix_fx_to_out = on;
888 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params)
890 fluid_rvoice_mixer_t *mixer = obj;
891 int set = param[0].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;
899 for(i = 0; i < mixer->fx_units; i++)
901 fluid_chorus_set(mixer->fx[i].chorus, set, nr, level, speed, depth_ms, type);
905 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params)
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;
915 for(i = 0; i < mixer->fx_units; i++)
917 fluid_revmodel_set(mixer->fx[i].reverb, set, roomsize, damping, width, level);
921 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_reverb)
923 fluid_rvoice_mixer_t *mixer = obj;
925 for(i = 0; i < mixer->fx_units; i++)
927 fluid_revmodel_reset(mixer->fx[i].reverb);
931 DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus)
933 fluid_rvoice_mixer_t *mixer = obj;
935 for(i = 0; i < mixer->fx_units; i++)
937 fluid_chorus_reset(mixer->fx[i].chorus);
941 int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t *mixer,
942 fluid_real_t **left, fluid_real_t **right)
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;
949 int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t *mixer,
950 fluid_real_t **fx_left, fluid_real_t **fx_right)
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;
957 int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t *mixer)
959 return FLUID_MIXER_MAX_BUFFERS_DEFAULT;
963 int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t *mixer)
965 return mixer->active_voices;
969 #if ENABLE_MIXER_THREADS
971 static FLUID_INLINE fluid_rvoice_t *
972 fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t *mixer)
974 int i = fluid_atomic_int_exchange_and_add(&mixer->current_rvoice, 1);
976 if(i >= mixer->active_voices)
981 return mixer->rvoices[i];
984 #define THREAD_BUF_PROCESSING 0
985 #define THREAD_BUF_VALID 1
986 #define THREAD_BUF_NODATA 2
987 #define THREAD_BUF_TERMINATE 3
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)
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);
998 int current_blockcount = 0;
999 fluid_real_t *local_buf = fluid_align_ptr(buffers->local_buf, FLUID_DEFAULT_ALIGNMENT);
1001 while(!fluid_atomic_int_get(&mixer->threads_should_terminate))
1003 fluid_rvoice_t *rvoice = fluid_mixer_get_mt_rvoice(mixer);
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);
1013 fluid_cond_mutex_lock(mixer->wakeup_threads_m);
1017 int j = fluid_atomic_int_get(&buffers->ready);
1019 if(j == THREAD_BUF_PROCESSING || j == THREAD_BUF_TERMINATE)
1024 fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m);
1027 fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
1033 // else: if buffer is not zeroed, zero buffers
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);
1043 // then render voice to buffers
1044 fluid_mixer_buffers_render_one(buffers, rvoice, bufs, bufcount, local_buf, current_blockcount);
1048 return FLUID_THREAD_RETURN_VALUE;
1052 fluid_mixer_buffers_mix(fluid_mixer_buffers_t *dst, fluid_mixer_buffers_t *src, int current_blockcount)
1055 int scount = current_blockcount * FLUID_BUFSIZE;
1057 fluid_real_t *FLUID_RESTRICT base_src;
1058 fluid_real_t *FLUID_RESTRICT base_dst;
1060 minbuf = dst->buf_count;
1062 if(minbuf > src->buf_count)
1064 minbuf = src->buf_count;
1067 base_src = fluid_align_ptr(src->left_buf, FLUID_DEFAULT_ALIGNMENT);
1068 base_dst = fluid_align_ptr(dst->left_buf, FLUID_DEFAULT_ALIGNMENT);
1070 for(i = 0; i < minbuf; i++)
1072 #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1074 for(j = 0; j < scount; j++)
1076 int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1077 base_dst[dsp_i] += base_src[dsp_i];
1081 base_src = fluid_align_ptr(src->right_buf, FLUID_DEFAULT_ALIGNMENT);
1082 base_dst = fluid_align_ptr(dst->right_buf, FLUID_DEFAULT_ALIGNMENT);
1084 for(i = 0; i < minbuf; i++)
1086 #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1088 for(j = 0; j < scount; j++)
1090 int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1091 base_dst[dsp_i] += base_src[dsp_i];
1095 minbuf = dst->fx_buf_count;
1097 if(minbuf > src->fx_buf_count)
1099 minbuf = src->fx_buf_count;
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);
1105 for(i = 0; i < minbuf; i++)
1107 #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1109 for(j = 0; j < scount; j++)
1111 int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1112 base_dst[dsp_i] += base_src[dsp_i];
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);
1119 for(i = 0; i < minbuf; i++)
1121 #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT)
1123 for(j = 0; j < scount; j++)
1125 int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j;
1126 base_dst[dsp_i] += base_src[dsp_i];
1133 * Go through all threads and see if someone is finished for mixing
1136 fluid_mixer_mix_in(fluid_rvoice_mixer_t *mixer, int extra_threads, int current_blockcount)
1138 int i, result, hasmixed;
1145 for(i = 0; i < extra_threads; i++)
1147 int j = fluid_atomic_int_get(&mixer->threads[i].ready);
1151 case THREAD_BUF_PROCESSING:
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);
1169 fluid_render_loop_multithread(fluid_rvoice_mixer_t *mixer, int current_blockcount)
1172 fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT);
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;
1179 if(extra_threads > mixer->thread_count)
1181 extra_threads = mixer->thread_count;
1184 if(extra_threads == 0)
1186 // No extra threads? No thread overhead!
1187 fluid_render_loop_singlethread(mixer, current_blockcount);
1191 bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs);
1193 // Prepare voice list
1194 fluid_cond_mutex_lock(mixer->wakeup_threads_m);
1195 fluid_atomic_int_set(&mixer->current_rvoice, 0);
1197 for(i = 0; i < extra_threads; i++)
1199 fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING);
1202 // Signal threads to wake up
1203 fluid_cond_broadcast(mixer->wakeup_threads);
1204 fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
1206 // If thread is finished, mix it in
1207 while(fluid_mixer_mix_in(mixer, extra_threads, current_blockcount))
1209 // Otherwise get a voice and render it
1210 fluid_rvoice_t *rvoice = fluid_mixer_get_mt_rvoice(mixer);
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);
1222 // If no voices, wait for mixes. Make sure one is still processing to avoid deadlock
1223 int is_processing = 0;
1225 fluid_cond_mutex_lock(mixer->thread_ready_m);
1227 for(i = 0; i < extra_threads; i++)
1229 if(fluid_atomic_int_get(&mixer->threads[i].ready) ==
1230 THREAD_BUF_PROCESSING)
1238 fluid_cond_wait(mixer->thread_ready, mixer->thread_ready_m);
1241 fluid_cond_mutex_unlock(mixer->thread_ready_m);
1245 //FLUID_LOG(FLUID_DBG, "Blockcount: %d, mixed %d of %d voices myself, waits = %d",
1246 // current_blockcount, test, mixer->active_voices, waits);
1249 static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer)
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);
1256 for(i = 0; i < mixer->thread_count; i++)
1258 fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE);
1261 fluid_cond_broadcast(mixer->wakeup_threads);
1262 fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
1264 for(i = 0; i < mixer->thread_count; i++)
1266 if(mixer->threads[i].thread)
1268 fluid_thread_join(mixer->threads[i].thread);
1269 delete_fluid_thread(mixer->threads[i].thread);
1272 fluid_mixer_buffers_free(&mixer->threads[i]);
1275 FLUID_FREE(mixer->threads);
1276 mixer->thread_count = 0;
1277 mixer->threads = NULL;
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
1285 static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level)
1290 // Kill all existing threads first
1291 if(mixer->thread_count)
1293 delete_rvoice_mixer_threads(mixer);
1296 if(thread_count == 0)
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);
1305 if(mixer->threads == NULL)
1307 FLUID_LOG(FLUID_ERR, "Out of memory");
1308 return FLUID_FAILED;
1311 FLUID_MEMSET(mixer->threads, 0, thread_count * sizeof(fluid_mixer_buffers_t));
1312 mixer->thread_count = thread_count;
1314 for(i = 0; i < thread_count; i++)
1316 fluid_mixer_buffers_t *b = &mixer->threads[i];
1318 if(!fluid_mixer_buffers_init(b, mixer))
1320 return FLUID_FAILED;
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);
1329 return FLUID_FAILED;
1338 * Synthesize audio into buffers
1339 * @param blockcount number of blocks to render, each having FLUID_BUFSIZE samples
1340 * @return number of blocks rendered
1343 fluid_rvoice_mixer_render(fluid_rvoice_mixer_t *mixer, int blockcount)
1345 fluid_profile_ref_var(prof_ref);
1347 mixer->current_blockcount = blockcount;
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);
1354 #if ENABLE_MIXER_THREADS
1356 if(mixer->thread_count > 0)
1358 fluid_render_loop_multithread(mixer, blockcount);
1363 fluid_render_loop_singlethread(mixer, blockcount);
1366 fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref, mixer->active_voices,
1367 blockcount * FLUID_BUFSIZE);
1370 // Process reverb & chorus
1371 fluid_rvoice_mixer_process_fx(mixer, blockcount);
1373 // Call the callback and pack active voice array
1374 fluid_rvoice_mixer_process_finished_voices(mixer);