Skip to content

Commit

Permalink
Mix effects in parallel (#1158)
Browse files Browse the repository at this point in the history
  • Loading branch information
derselbst authored Sep 20, 2022
1 parent b1fbace commit 05c95c4
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 71 deletions.
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,9 @@ endif ( enable-threads )

unset ( HAVE_OPENMP CACHE )
find_package ( OpenMP QUIET )
if (enable-openmp AND ( OpenMP_FOUND OR OpenMP_C_FOUND ) )
if (enable-openmp AND ENABLE_UBSAN)
message(WARNING "OpenMP is not supported when UBSan is enabled. Disabling OpenMP.")
elseif (enable-openmp AND ( OpenMP_FOUND OR OpenMP_C_FOUND ) )
message(STATUS "Found OpenMP version: ${OpenMP_C_VERSION} date: ${OpenMP_C_SPEC_DATE}")
if ( TARGET OpenMP::OpenMP_C AND (( NOT OpenMP_C_SPEC_DATE LESS "201307" ) OR NOT ( OpenMP_C_VERSION VERSION_LESS "4.0" )) )
#[[ cmake_print_properties( TARGETS OpenMP::OpenMP_C
Expand All @@ -729,7 +731,7 @@ if (enable-openmp AND ( OpenMP_FOUND OR OpenMP_C_FOUND ) )
INTERFACE_INCLUDE_DIRECTORIES
INTERFACE_LINK_OPTIONS
INTERFACE_LINK_LIBRARIES ) ]]
set ( HAVE_OPENMP 1 )
set ( HAVE_OPENMP 1 )
else()
message(STATUS " OpenMP version is not supported. Feature disabled.")
endif()
Expand Down
152 changes: 83 additions & 69 deletions src/rvoice/fluid_rvoice_mixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,12 @@ static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int threa
static FLUID_INLINE void
fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcount)
{
const int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
int i, f;
int dry_count = mixer->buffers.buf_count; /* dry buffers count */
int mix_fx_to_out = mixer->mix_fx_to_out; /* get mix_fx_to_out mode */
int dry_idx = 0; /* dry buffer index */
int buf_idx; /* buffer index */
int samp_idx; /* sample index in buffer */
int sample_count; /* sample count to process */

// Making those variables const causes gcc to fail with "variable is predetermined ‘shared’ for ‘shared’".
// Not explicitly marking them shared makes it fail for clang and MSVC...
/*const*/ int fx_channels_per_unit = mixer->buffers.fx_buf_count / mixer->fx_units;
/*const*/ int dry_count = mixer->buffers.buf_count; /* dry buffers count */
/*const*/ int mix_fx_to_out = mixer->mix_fx_to_out; /* get mix_fx_to_out mode */

void (*reverb_process_func)(fluid_revmodel_t *rev, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);
void (*chorus_process_func)(fluid_chorus_t *chorus, const fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out);

Expand Down Expand Up @@ -170,7 +167,6 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun

reverb_process_func = fluid_revmodel_processmix;
chorus_process_func = fluid_chorus_processmix;

}
else
{
Expand All @@ -182,73 +178,92 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcoun
chorus_process_func = fluid_chorus_processreplace;
}


if(mixer->with_reverb)
if(mixer->with_reverb || mixer->with_chorus)
{
for(f = 0; f < mixer->fx_units; f++)
{
if(!mixer->fx[f].reverb_on)
{
continue; /* this reverb unit is disabled */
}

buf_idx = f * fx_channels_per_unit + SYNTH_REVERB_CHANNEL;
samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
sample_count = current_blockcount * FLUID_BUFSIZE;

/* in mix mode, map fx out_rev at index f to a dry buffer at index dry_idx */
if(mix_fx_to_out)
{
/* dry buffer mapping, should be done more flexible in the future */
dry_idx = (f % dry_count) * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
}

for(i = 0; i < sample_count; i += FLUID_BUFSIZE, samp_idx += FLUID_BUFSIZE)
{
reverb_process_func(mixer->fx[f].reverb,
&in_rev[samp_idx],
mix_fx_to_out ? &out_rev_l[dry_idx + i] : &out_rev_l[samp_idx],
mix_fx_to_out ? &out_rev_r[dry_idx + i] : &out_rev_r[samp_idx]);
}
}

fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref, 0,
current_blockcount * FLUID_BUFSIZE);
}

if(mixer->with_chorus)
{
for(f = 0; f < mixer->fx_units; f++)
#if ENABLE_MIXER_THREADS && !defined(WITH_PROFILING)
int fx_mixer_threads = mixer->fx_units;
fluid_clip(fx_mixer_threads, 1, mixer->thread_count + 1);
#pragma omp parallel default(none) shared(mixer, reverb_process_func, chorus_process_func, dry_count, current_blockcount, mix_fx_to_out, fx_channels_per_unit) firstprivate(in_rev, in_ch, out_rev_l, out_rev_r, out_ch_l, out_ch_r) num_threads(fx_mixer_threads)
#endif
{
if(!mixer->fx[f].chorus_on)
int i, f;
int buf_idx; /* buffer index */
int samp_idx; /* sample index in buffer */
int dry_idx = 0; /* dry buffer index */
int sample_count; /* sample count to process */
if(mixer->with_reverb)
{
continue; /* this chorus unit is disabled */
#if ENABLE_MIXER_THREADS && !defined(WITH_PROFILING)
#pragma omp for schedule(static)
#endif
for(f = 0; f < mixer->fx_units; f++)
{
if(!mixer->fx[f].reverb_on)
{
continue; /* this reverb unit is disabled */
}

buf_idx = f * fx_channels_per_unit + SYNTH_REVERB_CHANNEL;
samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
sample_count = current_blockcount * FLUID_BUFSIZE;

/* in mix mode, map fx out_rev at index f to a dry buffer at index dry_idx */
if(mix_fx_to_out)
{
/* dry buffer mapping, should be done more flexible in the future */
dry_idx = (f % dry_count) * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
}

for(i = 0; i < sample_count; i += FLUID_BUFSIZE, samp_idx += FLUID_BUFSIZE)
{
reverb_process_func(mixer->fx[f].reverb,
&in_rev[samp_idx],
mix_fx_to_out ? &out_rev_l[dry_idx + i] : &out_rev_l[samp_idx],
mix_fx_to_out ? &out_rev_r[dry_idx + i] : &out_rev_r[samp_idx]);
}
} // implicit omp barrier - required, because out_rev_l aliases with out_ch_l

fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref, 0,
current_blockcount * FLUID_BUFSIZE);
}

buf_idx = f * fx_channels_per_unit + SYNTH_CHORUS_CHANNEL;
samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
sample_count = current_blockcount * FLUID_BUFSIZE;

/* in mix mode, map fx out_ch at index f to a dry buffer at index dry_idx */
if(mix_fx_to_out)
if(mixer->with_chorus)
{
/* dry buffer mapping, should be done more flexible in the future */
dry_idx = (f % dry_count) * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
}
#if ENABLE_MIXER_THREADS && !defined(WITH_PROFILING)
#pragma omp for schedule(static)
#endif
for(f = 0; f < mixer->fx_units; f++)
{
if(!mixer->fx[f].chorus_on)
{
continue; /* this chorus unit is disabled */
}

buf_idx = f * fx_channels_per_unit + SYNTH_CHORUS_CHANNEL;
samp_idx = buf_idx * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
sample_count = current_blockcount * FLUID_BUFSIZE;

/* in mix mode, map fx out_ch at index f to a dry buffer at index dry_idx */
if(mix_fx_to_out)
{
/* dry buffer mapping, should be done more flexible in the future */
dry_idx = (f % dry_count) * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE;
}

for(i = 0; i < sample_count; i += FLUID_BUFSIZE, samp_idx += FLUID_BUFSIZE)
{
chorus_process_func(mixer->fx[f].chorus,
&in_ch [samp_idx],
mix_fx_to_out ? &out_ch_l[dry_idx + i] : &out_ch_l[samp_idx],
mix_fx_to_out ? &out_ch_r[dry_idx + i] : &out_ch_r[samp_idx]);
}
}

for(i = 0; i < sample_count; i += FLUID_BUFSIZE, samp_idx += FLUID_BUFSIZE)
{
chorus_process_func(mixer->fx[f].chorus,
&in_ch [samp_idx],
mix_fx_to_out ? &out_ch_l[dry_idx + i] : &out_ch_l[samp_idx],
mix_fx_to_out ? &out_ch_r[dry_idx + i] : &out_ch_r[samp_idx]);
fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref, 0,
current_blockcount * FLUID_BUFSIZE);
}
}

fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref, 0,
current_blockcount * FLUID_BUFSIZE);
}

}

/**
Expand Down Expand Up @@ -575,7 +590,6 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice)

/* This should never happen */
FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice");
return;
}

static int
Expand Down Expand Up @@ -645,7 +659,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony)
#endif

handler->polyphony = value;
return /*FLUID_OK*/;
/*return FLUID_OK*/;
}


Expand Down

0 comments on commit 05c95c4

Please sign in to comment.