libfluidsynth  2.3.5
Audio Rendering

The functions in this section can be used to render audio directly to memory buffers. More...

Functions

int fluid_synth_nwrite_float (fluid_synth_t *synth, int len, float **left, float **right, float **fx_left, float **fx_right)
 Synthesize a block of floating point audio to separate audio buffers (multi-channel rendering). More...
 
int fluid_synth_process (fluid_synth_t *synth, int len, int nfx, float *fx[], int nout, float *out[])
 Synthesize floating point audio to stereo audio channels (implements the default interface fluid_audio_func_t). More...
 
int fluid_synth_write_float (fluid_synth_t *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr)
 Synthesize a block of floating point audio samples to audio buffers. More...
 
int fluid_synth_write_s16 (fluid_synth_t *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr)
 Synthesize a block of 16 bit audio samples to audio buffers. More...
 

Detailed Description

The functions in this section can be used to render audio directly to memory buffers.

They are used internally by the Audio Driver and File Renderer, but can also be used manually for custom processing of the rendered audio.

Note
Please note that all following functions block during rendering. If your goal is to render real-time audio, ensure that you call these functions from a high-priority thread with little to no other duties other than calling the rendering functions.
Warning
If a concurrently running thread calls any other sound affecting synth function (e.g. fluid_synth_noteon(), fluid_synth_cc(), etc.) it is unspecified whether the event triggered by such a call will be effective in the recently synthesized audio. While this is inaudible when only requesting small chunks from the synth with every call (cf. fluid_synth_get_internal_bufsize()), it will become evident when requesting larger sample chunks: With larger sample chunks it will get harder for the synth to react on those spontaneously occurring events in time (like events received from a MIDI driver, or directly made synth API calls). In those real-time scenarios, prefer requesting smaller sample chunks from the synth with each call, to avoid poor quantization of your events in the synthesized audio. This issue is not applicable when using the MIDI player or sequencer for event dispatching. Also refer to the documentation of audio.period-size.

Function Documentation

◆ fluid_synth_nwrite_float()

int fluid_synth_nwrite_float ( fluid_synth_t synth,
int  len,
float **  left,
float **  right,
float **  fx_left,
float **  fx_right 
)

Synthesize a block of floating point audio to separate audio buffers (multi-channel rendering).

Parameters
synthFluidSynth instance
lenCount of audio frames to synthesize
leftArray of float buffers to store left channel of planar audio (as many as synth.audio-channels buffers, each of len in size)
rightArray of float buffers to store right channel of planar audio (size: dito)
fx_leftSince 1.1.7: If not NULL, array of float buffers to store left effect channels (as many as synth.effects-channels buffers, each of len in size)
fx_rightSince 1.1.7: If not NULL, array of float buffers to store right effect channels (size: dito)
Returns
FLUID_OK on success, FLUID_FAILED otherwise

First effect channel used by reverb, second for chorus.

Note
Should only be called from synthesis thread.
Deprecated:
fluid_synth_nwrite_float() is deprecated and will be removed in a future release. It may continue to work or it may return FLUID_FAILED in the future. Consider using the more powerful and flexible fluid_synth_process().

Usage example:

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_nwrite_float renders planar audio, e.g. if synth.audio-channels==16:
// each midi channel gets rendered to its own stereo buffer, rather than having
// one buffer and interleaved 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)
int fluid_synth_nwrite_float(fluid_synth_t *synth, int len, float **left, float **right, float **fx_left, float **fx_right)
Synthesize a block of floating point audio to separate audio buffers (multi-channel rendering).
Definition: fluid_synth.c:3830
int fluid_settings_getint(fluid_settings_t *settings, const char *name, int *val)
Get an integer value setting.
Definition: fluid_settings.c:1592

◆ fluid_synth_process()

int fluid_synth_process ( fluid_synth_t synth,
int  len,
int  nfx,
float *  fx[],
int  nout,
float *  out[] 
)

Synthesize floating point audio to stereo audio channels (implements the default interface fluid_audio_func_t).

Parameters
synthFluidSynth instance
lenCount of audio frames to synthesize and store in every single buffer provided by out and fx. Zero value is permitted, the function does nothing and return FLUID_OK.
nfxCount of arrays in fx. Must be a multiple of 2 (because of stereo) and in the range 0 <= nfx/2 <= (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups()). Note that zero value is valid and allows to skip mixing effects in all fx output buffers.
fxArray of buffers to store effects audio to. Buffers may alias with buffers of out. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
noutCount of arrays in out. Must be a multiple of 2 (because of stereo) and in the range 0 <= nout/2 <= fluid_synth_count_audio_channels(). Note that zero value is valid and allows to skip mixing dry audio in all out output buffers.
outArray of buffers to store (dry) audio to. Buffers may alias with buffers of fx. Individual NULL buffers are permitted and will cause to skip mixing any audio into that buffer.
Returns
FLUID_OK on success, FLUID_FAILED otherwise,
  • fx == NULL while nfx > 0, or out == NULL while nout > 0.
  • nfx or nout not multiple of 2.
  • len < 0.
  • nfx or nout exceed the range explained above.

Synthesize and mix audio to a given number of planar audio buffers. Therefore pass nout = N*2 float buffers to out in order to render the synthesized audio to N stereo channels. Each float buffer must be able to hold len elements.

out contains an array of planar buffers for normal, dry, stereo audio (alternating left and right). Like:

out[0] = left_buffer_audio_channel_0
out[1] = right_buffer_audio_channel_0
out[2] = left_buffer_audio_channel_1
out[3] = right_buffer_audio_channel_1
...
out[ (i * 2 + 0) % nout ] = left_buffer_audio_channel_i
out[ (i * 2 + 1) % nout ] = right_buffer_audio_channel_i

for zero-based channel index i. The buffer layout of fx used for storing effects like reverb and chorus looks similar:

fx[0] = left_buffer_channel_of_reverb_unit_0
fx[1] = right_buffer_channel_of_reverb_unit_0
fx[2] = left_buffer_channel_of_chorus_unit_0
fx[3] = right_buffer_channel_of_chorus_unit_0
fx[4] = left_buffer_channel_of_reverb_unit_1
fx[5] = right_buffer_channel_of_reverb_unit_1
fx[6] = left_buffer_channel_of_chorus_unit_1
fx[7] = right_buffer_channel_of_chorus_unit_1
fx[8] = left_buffer_channel_of_reverb_unit_2
...
fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 0) % nfx ] = left_buffer_for_effect_channel_j_of_unit_k
fx[ ((k * fluid_synth_count_effects_channels() + j) * 2 + 1) % nfx ] = right_buffer_for_effect_channel_j_of_unit_k
int fluid_synth_count_effects_channels(fluid_synth_t *synth)
Get the total number of allocated effects channels.
Definition: fluid_synth.c:6970

where 0 <= k < fluid_synth_count_effects_groups() is a zero-based index denoting the effects unit and 0 <= j < fluid_synth_count_effects_channels() is a zero-based index denoting the effect channel within unit k.

Any playing voice is assigned to audio channels based on the MIDI channel it's playing on: Let chan be the zero-based MIDI channel index an arbitrary voice is playing on. To determine the audio channel and effects unit it is going to be rendered to use:

i = chan % fluid_synth_count_audio_groups()

k = chan % fluid_synth_count_effects_groups()

Note
The owner of the sample buffers must zero them out before calling this function, because any synthesized audio is mixed (i.e. added) to the buffers. E.g. if fluid_synth_process() is called from a custom audio driver process function (see new_fluid_audio_driver2()), the audio driver takes care of zeroing the buffers.
Note
No matter how many buffers you pass in, fluid_synth_process() will always render all audio channels to the buffers in out and all effects channels to the buffers in fx, provided that nout > 0 and nfx > 0 respectively. If nout/2 < fluid_synth_count_audio_channels() it will wrap around. Same is true for effects audio if nfx/2 < (fluid_synth_count_effects_channels() * fluid_synth_count_effects_groups()). See usage examples below.
Note
Should only be called from synthesis thread.
Examples
fluidsynth_fx.c, and fluidsynth_process.c.

◆ fluid_synth_write_float()

int fluid_synth_write_float ( fluid_synth_t synth,
int  len,
void *  lout,
int  loff,
int  lincr,
void *  rout,
int  roff,
int  rincr 
)

Synthesize a block of floating point audio samples to audio buffers.

Parameters
synthFluidSynth instance
lenCount of audio frames to synthesize
loutArray of floats to store left channel of audio
loffOffset index in 'lout' for first sample
lincrIncrement between samples stored to 'lout'
routArray of floats to store right channel of audio
roffOffset index in 'rout' for first sample
rincrIncrement between samples stored to 'rout'
Returns
FLUID_OK on success, FLUID_FAILED otherwise

Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1, lincr = 2, rincr = 2).

Note
Should only be called from synthesis thread.
Reverb and Chorus are mixed to lout resp. rout.

◆ fluid_synth_write_s16()

int fluid_synth_write_s16 ( fluid_synth_t synth,
int  len,
void *  lout,
int  loff,
int  lincr,
void *  rout,
int  roff,
int  rincr 
)

Synthesize a block of 16 bit audio samples to audio buffers.

Parameters
synthFluidSynth instance
lenCount of audio frames to synthesize
loutArray of 16 bit words to store left channel of audio
loffOffset index in 'lout' for first sample
lincrIncrement between samples stored to 'lout'
routArray of 16 bit words to store right channel of audio
roffOffset index in 'rout' for first sample
rincrIncrement between samples stored to 'rout'
Returns
FLUID_OK on success, FLUID_FAILED otherwise

Useful for storing interleaved stereo (lout = rout, loff = 0, roff = 1, lincr = 2, rincr = 2).

Note
Should only be called from synthesis thread.
Reverb and Chorus are mixed to lout resp. rout.
Dithering is performed when converting from internal floating point to 16 bit audio.