implement reading effect buffers from fluid_synth_nwrite_float()

This commit is contained in:
derselbst 2017-07-13 12:02:58 +02:00
parent 54a7f5cae8
commit 1ff2002ab5
3 changed files with 89 additions and 10 deletions

View file

@ -705,8 +705,8 @@ int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t* mixer,
int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t* mixer,
fluid_real_t*** fx_left, fluid_real_t*** fx_right)
{
*left = mixer->buffers.fx_left_buf;
*right = mixer->buffers.fx_right_buf;
*fx_left = mixer->buffers.fx_left_buf;
*fx_right = mixer->buffers.fx_right_buf;
return mixer->buffers.fx_buf_count;
}

View file

@ -39,7 +39,9 @@ void fluid_rvoice_mixer_set_finished_voices_callback(
int fluid_rvoice_mixer_render(fluid_rvoice_mixer_t* mixer, int blockcount);
int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t* mixer,
fluid_real_t*** left, fluid_real_t*** right);
fluid_real_t*** left, fluid_real_t*** right);
int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t* mixer,
fluid_real_t*** fx_left, fluid_real_t*** fx_right);
fluid_rvoice_mixer_t* new_fluid_rvoice_mixer(int buf_count, int fx_buf_count,
fluid_real_t sample_rate);

View file

@ -2421,24 +2421,60 @@ fluid_synth_program_reset(fluid_synth_t* synth)
}
/**
* Synthesize a block of floating point audio to audio buffers.
* Synthesize a block of floating point audio to separate audio buffers (multichannel rendering).
* @param synth FluidSynth instance
* @param len Count of audio frames to synthesize
* @param left Array of floats to store left channel of audio (\c len in size)
* @param right Array of floats to store right channel of audio (\c len in size)
* @param fx_left since 1.1.7: Array of floats to store left effect channel (reverb and chrous, \c len in size)
* @param fx_right since 1.1.7: Array of floats to store right effect channel (reverb and chorus, \c len in size)
* @param left Array of arrays of floats to store left channel of planar audio (\c len in size)
* @param right Array of arrays of floats to store right channel of planar audio (\c len in size)
* @param fx_left Since 1.1.7: If not \c NULL, array of arrays of floats to store left effect channel (reverb and chrous, \c len in size)
* @param fx_right Since 1.1.7: If not \c NULL, array of arrays of floats to store right effect channel (reverb and chorus, \c len in size)
* @return FLUID_OK on success, FLUID_FAIL otherwise
*
* @note Should only be called from synthesis thread.
*
* Usage example:
* @code
const int FramesToRender = 64;
int channels;
// retrieve number of stereo audio channels
fluid_settings_getint(settings, "synth.audio-channels", &channels);
// we need twice as many (mono-)buffers
channels *= 2;
// fluid_synth_process renders planar audio, i.e. each midi channel gets render to its own stereo buffer, rather than having one buffer and interleaving PCM
float** mix_buf = new float*[channels];
for(int i = 0; i < channels; i++)
{
mix_buf[i] = new float[FramesToRender];
}
// retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan) and chrous (second chan))
fluid_settings_getint(settings, "synth.effects-channels", &channels);
channels *= 2;
float** fx_buf = new float*[channels];
for(int i = 0; i < channels; i++)
{
fx_buf[i] = new float[FramesToRender];
}
float** mix_buf_l = mix_buf;
float** mix_buf_r = &mix_buf[channels/2];
float** fx_buf_l = fx_buf;
float** fx_buf_r = &fx_buf[channels/2];
fluid_synth_nwrite_float(synth, FramesToRender, mix_buf_l, mix_buf_r, fx_buf_l, fx_buf_r)
* @endcode
*/
int
fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
float** left, float** right,
float** fx_left, float** fx_right)
{
fluid_real_t** left_in;
fluid_real_t** right_in;
fluid_real_t** left_in, **fx_left_in;
fluid_real_t** right_in, **fx_right_in;
double time = fluid_utime();
int i, num, available, count;
#ifdef WITH_FLOAT
@ -2455,6 +2491,7 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
if (synth->cur < FLUID_BUFSIZE) {
available = FLUID_BUFSIZE - synth->cur;
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
num = (available > len)? len : available;
#ifdef WITH_FLOAT
@ -2473,6 +2510,26 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
}
#endif //WITH_FLOAT
}
for (i = 0; i < synth->effects_channels; i++)
{
#ifdef WITH_FLOAT
if(fx_left != NULL)
FLUID_MEMCPY(fx_left[i], fx_left_in[i] + synth->cur, bytes);
if(fx_right != NULL)
FLUID_MEMCPY(fx_right[i], fx_right_in[i] + synth->cur, bytes);
#else //WITH_FLOAT
int j;
for (j = 0; (fx_left != NULL) && (j < num); j++)
fx_left[i][j] = (float) fx_left_in[i][j + synth->cur];
for (j = 0; (fx_right != NULL) && (j < num); j++)
fx_right[i][j] = (float) fx_right_in[i][j + synth->cur];
#endif //WITH_FLOAT
}
count += num;
num += synth->cur; /* if we're now done, num becomes the new synth->cur below */
}
@ -2482,6 +2539,7 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0);
fluid_synth_render_blocks(synth, 1); // TODO:
fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in);
fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in);
num = (FLUID_BUFSIZE > len - count)? len - count : FLUID_BUFSIZE;
#ifdef WITH_FLOAT
@ -2501,6 +2559,25 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len,
#endif //WITH_FLOAT
}
for (i = 0; i < synth->effects_channels; i++)
{
#ifdef WITH_FLOAT
if(fx_left != NULL)
FLUID_MEMCPY(fx_left[i + count], fx_left_in[i], bytes);
if(fx_right != NULL)
FLUID_MEMCPY(fx_right[i + count], fx_right_in[i], bytes);
#else //WITH_FLOAT
int j;
for (j = 0; (fx_left != NULL) && (j < num); j++)
fx_left[i][j + count] = (float) fx_left_in[i][j];
for (j = 0; (fx_right != NULL) && (j < num); j++)
fx_right[i][j + count] = (float) fx_right_in[i][j];
#endif //WITH_FLOAT
}
count += num;
}