Merge pull request #372 from FluidSynth/rvoice-refactor3

rvoice_mixer refactorings + cleanups
This commit is contained in:
Tom M 2018-05-02 20:51:53 +02:00 committed by GitHub
commit 05c2d57e65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 184 additions and 250 deletions

View File

@ -271,11 +271,11 @@ unset ( WITH_PROFILING CACHE )
if ( enable-profiling )
set ( WITH_PROFILING 1 )
if ( CMAKE_C_COMPILER_ID STREQUAL "Clang" )
set ( OPT_FLAGS "-Rpass=loop-vectorize -Rpass-analysis=loop-vectorize -Wpadded" )
set ( OPT_FLAGS "-Rpass=loop-vectorize -Rpass-analysis=loop-vectorize" )
elseif ( CMAKE_C_COMPILER_ID STREQUAL "Intel" )
set ( OPT_FLAGS "-qopt-report=3" )
elseif ( CMAKE_C_COMPILER_ID STREQUAL "GNU" )
set ( OPT_FLAGS "-Wpadded" )
set ( OPT_FLAGS "" )
endif ( )
set ( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${OPT_FLAGS}" )

View File

@ -272,7 +272,7 @@ int
fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
{
int ticks = voice->envlfo.ticks;
int count;
int count, is_looping;
/******************* sample sanity check **********/
@ -358,7 +358,8 @@ fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
/* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */
if (voice->dsp.phase_incr == 0) voice->dsp.phase_incr = 1;
voice->dsp.is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE
/* voice is currently looping? */
is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE
|| (voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE
&& fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE);
@ -367,22 +368,21 @@ fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
* The buffer has to be filled from 0 to FLUID_BUFSIZE-1.
* Depending on the position in the loop and the loop size, this
* may require several runs. */
voice->dsp.dsp_buf = dsp_buf;
switch (voice->dsp.interp_method)
{
case FLUID_INTERP_NONE:
count = fluid_rvoice_dsp_interpolate_none (&voice->dsp);
count = fluid_rvoice_dsp_interpolate_none (&voice->dsp, dsp_buf, is_looping);
break;
case FLUID_INTERP_LINEAR:
count = fluid_rvoice_dsp_interpolate_linear (&voice->dsp);
count = fluid_rvoice_dsp_interpolate_linear (&voice->dsp, dsp_buf, is_looping);
break;
case FLUID_INTERP_4THORDER:
default:
count = fluid_rvoice_dsp_interpolate_4th_order (&voice->dsp);
count = fluid_rvoice_dsp_interpolate_4th_order (&voice->dsp, dsp_buf, is_looping);
break;
case FLUID_INTERP_7THORDER:
count = fluid_rvoice_dsp_interpolate_7th_order (&voice->dsp);
count = fluid_rvoice_dsp_interpolate_7th_order (&voice->dsp, dsp_buf, is_looping);
break;
}
fluid_check_fpe ("voice_write interpolation");
@ -404,60 +404,6 @@ fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
return count;
}
static FLUID_INLINE fluid_real_t*
get_dest_buf(fluid_rvoice_buffers_t* buffers, int index,
fluid_real_t** dest_bufs, int dest_bufcount)
{
int j = buffers->bufs[index].mapping;
if (j >= dest_bufcount || j < 0) return NULL;
return dest_bufs[j];
}
/**
* Mix data down to buffers
*
* @param buffers Destination buffer(s)
* @param dsp_buf Mono sample source
* @param samplecount Number of samples to process (no FLUID_BUFSIZE restriction)
* @param dest_bufs Array of buffers to mixdown to
* @param dest_bufcount Length of dest_bufs
*/
void
fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers,
fluid_real_t* dsp_buf, int samplecount,
fluid_real_t** dest_bufs, int dest_bufcount)
{
int bufcount = buffers->count;
int i, dsp_i;
if (!samplecount || !bufcount || !dest_bufcount)
return;
for (i=0; i < bufcount; i++) {
fluid_real_t* buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount);
fluid_real_t* next_buf;
fluid_real_t amp = buffers->bufs[i].amp;
if (buf == NULL || amp == 0.0f)
continue;
/* Optimization for centered stereo samples - we can save one
multiplication per sample */
next_buf = (i+1 >= bufcount ? NULL : get_dest_buf(buffers, i+1, dest_bufs, dest_bufcount));
if (next_buf && buffers->bufs[i+1].amp == amp) {
for (dsp_i = 0; dsp_i < samplecount; dsp_i++) {
fluid_real_t samp = amp * dsp_buf[dsp_i];
buf[dsp_i] += samp;
next_buf[dsp_i] += samp;
}
i++;
}
else {
for (dsp_i = 0; dsp_i < samplecount; dsp_i++)
buf[dsp_i] += amp * dsp_buf[dsp_i];
}
}
}
/**
* Initialize buffers up to (and including) bufnum
*/
@ -470,8 +416,7 @@ fluid_rvoice_buffers_check_bufnum(fluid_rvoice_buffers_t* buffers, unsigned int
if (bufnum >= FLUID_RVOICE_MAX_BUFS) return FLUID_FAILED;
for (i = buffers->count; i <= bufnum; i++) {
buffers->bufs[bufnum].amp = 0.0f;
buffers->bufs[bufnum].mapping = i;
buffers->bufs[i].amp = 0.0f;
}
buffers->count = bufnum+1;
return FLUID_OK;

View File

@ -84,17 +84,22 @@ struct _fluid_rvoice_envlfo_t
struct _fluid_rvoice_dsp_t
{
/* interpolation method, as in fluid_interp in fluidsynth.h */
int interp_method;
enum fluid_interp interp_method;
enum fluid_loop samplemode;
/* Flag that is set as soon as the first loop is completed. */
char has_looped;
/* Flag that initiates, that sample-related parameters have to be checked. */
char check_sample_sanity_flag;
fluid_sample_t* sample;
int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters
have to be checked. */
/* sample and loop start and end points (offset in sample memory). */
int start;
int end;
int loopstart;
int loopend; /* Note: first point following the loop (superimposed on loopstart) */
enum fluid_loop samplemode;
/* Stuff needed for portamento calculations */
fluid_real_t pitchoffset; /* the portamento range in midicents */
@ -108,7 +113,6 @@ struct _fluid_rvoice_dsp_t
/* Stuff needed for amplitude calculations */
int has_looped; /* Flag that is set as soon as the first loop is completed. */
fluid_real_t attenuation; /* the attenuation in centibels */
fluid_real_t prev_attenuation; /* the previous attenuation in centibels
used by fluid_rvoice_multi_retrigger_attack() */
@ -118,18 +122,13 @@ struct _fluid_rvoice_dsp_t
fluid_real_t amplitude_that_reaches_noise_floor_loop;
fluid_real_t synth_gain; /* master gain */
/* Dynamic input to the interpolator below */
fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */
fluid_real_t amp; /* current linear amplitude */
fluid_real_t amp_incr; /* amplitude increment value for the next FLUID_BUFSIZE samples */
fluid_phase_t phase; /* the phase (current sample offset) of the sample wave */
fluid_real_t phase_incr; /* the phase increment for the next FLUID_BUFSIZE samples */
int is_looping;
};
/* Currently left, right, reverb, chorus. To be changed if we
@ -164,10 +163,6 @@ struct _fluid_rvoice_t
int fluid_rvoice_write(fluid_rvoice_t* voice, fluid_real_t *dsp_buf);
void fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers,
fluid_real_t* dsp_buf, int samplecount,
fluid_real_t** dest_bufs, int dest_bufcount);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping);
@ -198,10 +193,10 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample);
/* defined in fluid_rvoice_dsp.c */
void fluid_rvoice_dsp_config (void);
int fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice);
int fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice);
int fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice);
int fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice);
int fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
int fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
int fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
int fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping);
/*

View File

@ -130,25 +130,20 @@ fluid_rvoice_get_float_sample(const short int* dsp_msb, const char* dsp_lsb, uns
* the playback pointer. Questionable quality, but very
* efficient. */
int
fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice)
fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
int looping;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* voice is currently looping? */
looping = voice->is_looping;
end_index = looping ? voice->loopend - 1 : voice->end;
@ -192,28 +187,23 @@ fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice)
* smaller if end of sample occurs).
*/
int
fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int end_index;
fluid_real_t point;
fluid_real_t *coeffs;
int looping;
const fluid_real_t *FLUID_RESTRICT coeffs;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* voice is currently looping? */
looping = voice->is_looping;
/* last index before 2nd interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 1;
@ -282,28 +272,23 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice)
* smaller if end of sample occurs).
*/
int
fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
fluid_real_t start_point, end_point1, end_point2;
fluid_real_t *coeffs;
int looping;
const fluid_real_t *FLUID_RESTRICT coeffs;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
/* voice is currently looping? */
looping = voice->is_looping;
/* last index before 4th interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 2;
@ -437,21 +422,19 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice)
* smaller if end of sample occurs).
*/
int
fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping)
{
fluid_phase_t dsp_phase = voice->phase;
fluid_phase_t dsp_phase_incr;
short int *dsp_data = voice->sample->data;
char *dsp_data24 = voice->sample->data24;
fluid_real_t *dsp_buf = voice->dsp_buf;
fluid_real_t dsp_amp = voice->amp;
fluid_real_t dsp_amp_incr = voice->amp_incr;
unsigned int dsp_i = 0;
unsigned int dsp_phase_index;
unsigned int start_index, end_index;
fluid_real_t start_points[3], end_points[3];
fluid_real_t *coeffs;
int looping;
const fluid_real_t *FLUID_RESTRICT coeffs;
/* Convert playback "speed" floating point value to phase index/fract */
fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
@ -460,9 +443,6 @@ fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice)
* the 4th sample point */
fluid_phase_incr (dsp_phase, (fluid_phase_t)0x80000000);
/* voice is currently looping? */
looping = voice->is_looping;
/* last index before 7th interpolation point must be specially handled */
end_index = (looping ? voice->loopend - 1 : voice->end) - 3;

View File

@ -97,10 +97,9 @@ static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* han
}
static void
finished_voice_callback(void* userdata, fluid_rvoice_t* rvoice)
void
fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t* eventhandler, fluid_rvoice_t* rvoice)
{
fluid_rvoice_eventhandler_t* eventhandler = userdata;
fluid_rvoice_t** vptr = fluid_ringbuffer_get_inptr(eventhandler->finished_voices, 0);
if (vptr == NULL)
return; // Buffer full
@ -132,11 +131,10 @@ new_fluid_rvoice_eventhandler(int queuesize,
if (eventhandler->queue == NULL)
goto error_recovery;
eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, sample_rate);
eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, sample_rate, eventhandler);
if (eventhandler->mixer == NULL)
goto error_recovery;
fluid_rvoice_mixer_set_finished_voices_callback(eventhandler->mixer,
finished_voice_callback, eventhandler);
return eventhandler;
error_recovery:

View File

@ -27,7 +27,6 @@
#include "fluid_ringbuffer.h"
typedef struct _fluid_rvoice_event_t fluid_rvoice_event_t;
typedef struct _fluid_rvoice_eventhandler_t fluid_rvoice_eventhandler_t;
struct _fluid_rvoice_event_t {
fluid_rvoice_function_t method;
@ -55,6 +54,8 @@ void delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t*);
int fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t*);
int fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t*);
void fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t* eventhandler,
fluid_rvoice_t* rvoice);
static FLUID_INLINE void
fluid_rvoice_eventhandler_flush(fluid_rvoice_eventhandler_t* handler)

View File

@ -46,9 +46,7 @@ struct _fluid_mixer_buffers_t {
int finished_voice_count;
fluid_atomic_int_t ready; /**< Atomic: buffers are ready for mixing */
int buf_blocks; /**< Number of blocks allocated in the buffers */
int buf_count;
fluid_real_t** left_buf;
fluid_real_t** right_buf;
@ -72,8 +70,7 @@ struct _fluid_rvoice_mixer_t {
fluid_mixer_fx_t fx;
fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */
void (*remove_voice_callback)(void*, fluid_rvoice_t*); /**< Used by mixer only: Receive this callback every time a voice is removed */
void* remove_voice_callback_userdata;
fluid_rvoice_eventhandler_t* eventhandler;
fluid_rvoice_t** rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */
int polyphony; /**< Read-only: Length of voices array */
@ -156,50 +153,6 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t* mixer)
#endif
}
/**
* During rendering, rvoices might be finished. Set this callback
* for getting a callback any time the rvoice is finished.
*/
void fluid_rvoice_mixer_set_finished_voices_callback(
fluid_rvoice_mixer_t* mixer,
void (*func)(void*, fluid_rvoice_t*),
void* userdata)
{
mixer->remove_voice_callback_userdata = userdata;
mixer->remove_voice_callback = func;
}
/**
* Synthesize one voice and add to buffer.
* NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means
* voice has been finished, removed and possibly replaced with another voice.
* @return Number of samples written
*/
static int
fluid_mix_one(fluid_rvoice_t* rvoice, fluid_real_t** bufs, unsigned int bufcount, int blockcount)
{
int i, result = 0;
FLUID_DECLARE_VLA(fluid_real_t, local_buf, FLUID_BUFSIZE*blockcount);
for (i=0; i < blockcount; i++) {
int s = fluid_rvoice_write(rvoice, &local_buf[FLUID_BUFSIZE*i]);
if (s == -1) {
s = FLUID_BUFSIZE; /* Voice is quiet, TODO: optimize away memset/mix */
FLUID_MEMSET(&local_buf[FLUID_BUFSIZE*i], 0, FLUID_BUFSIZE*sizeof(fluid_real_t));
}
result += s;
if (s < FLUID_BUFSIZE) {
break;
}
}
fluid_rvoice_buffers_mix(&rvoice->buffers, local_buf, result, bufs, bufcount);
return result;
}
/**
* Glue to get fluid_rvoice_buffers_mix what it wants
* Note: Make sure outbufs has 2 * (buf_count + fx_buf_count) elements before calling
@ -261,18 +214,18 @@ fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t* buffers)
int i,j;
for (i=0; i < buffers->finished_voice_count; i++) {
fluid_rvoice_t* v = buffers->finished_voices[i];
int* av = &buffers->mixer->active_voices;
for (j=0; j < *av; j++) {
int av = buffers->mixer->active_voices;
for (j=0; j < av; j++) {
if (v == buffers->mixer->rvoices[j]) {
(*av)--;
av--;
/* Pack the array */
if (j < *av)
buffers->mixer->rvoices[j] = buffers->mixer->rvoices[*av];
if (j < av)
buffers->mixer->rvoices[j] = buffers->mixer->rvoices[av];
}
}
if (buffers->mixer->remove_voice_callback)
buffers->mixer->remove_voice_callback(
buffers->mixer->remove_voice_callback_userdata, v);
buffers->mixer->active_voices = av;
fluid_rvoice_eventhandler_finished_voice_callback(buffers->mixer->eventhandler, v);
}
buffers->finished_voice_count = 0;
}
@ -287,33 +240,92 @@ static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice
fluid_mixer_buffer_process_finished_voices(&mixer->buffers);
}
static FLUID_INLINE void
fluid_mixer_buffers_render_one(fluid_mixer_buffers_t* buffers,
fluid_rvoice_t* voice, fluid_real_t** bufs,
unsigned int bufcount)
static FLUID_INLINE fluid_real_t*
get_dest_buf(fluid_rvoice_buffers_t* buffers, int index,
fluid_real_t** dest_bufs, int dest_bufcount)
{
int s = fluid_mix_one(voice, bufs, bufcount, buffers->mixer->current_blockcount);
if (s < buffers->mixer->current_blockcount * FLUID_BUFSIZE) {
fluid_finish_rvoice(buffers, voice);
int j = buffers->bufs[index].mapping;
if (j >= dest_bufcount || j < 0) return NULL;
return dest_bufs[j];
}
/**
* Mix data down to buffers
*
* @param buffers Destination buffer(s)
* @param dsp_buf Mono sample source
* @param samplecount Number of samples to process (no FLUID_BUFSIZE restriction)
* @param dest_bufs Array of buffers to mixdown to
* @param dest_bufcount Length of dest_bufs
*/
static void
fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers,
fluid_real_t* dsp_buf, int start, int samplecount,
fluid_real_t** dest_bufs, int dest_bufcount)
{
int bufcount = buffers->count;
int i, dsp_i;
if (!samplecount || !bufcount || !dest_bufcount)
return;
for (i=0; i < bufcount; i++) {
fluid_real_t* buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount);
fluid_real_t* next_buf;
fluid_real_t amp = buffers->bufs[i].amp;
if (buf == NULL || amp == 0.0f)
continue;
/* Optimization for centered stereo samples - we can save one
multiplication per sample */
next_buf = (i+1 >= bufcount ? NULL : get_dest_buf(buffers, i+1, dest_bufs, dest_bufcount));
if (next_buf && buffers->bufs[i+1].amp == amp) {
for (dsp_i = start; dsp_i < samplecount; dsp_i++) {
fluid_real_t samp = amp * dsp_buf[dsp_i];
buf[dsp_i] += samp;
next_buf[dsp_i] += samp;
}
i++;
}
else {
for (dsp_i = start; dsp_i < samplecount; dsp_i++)
buf[dsp_i] += amp * dsp_buf[dsp_i];
}
}
}
/*
static int fluid_mixer_buffers_replace_voice(fluid_mixer_buffers_t* buffers,
fluid_rvoice_t* voice)
/**
* Synthesize one voice and add to buffer.
* NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means
* voice has been finished, removed and possibly replaced with another voice.
*/
static FLUID_INLINE void
fluid_mixer_buffers_render_one(fluid_mixer_buffers_t* buffers,
fluid_rvoice_t* rvoice, fluid_real_t** dest_bufs,
unsigned int dest_bufcount)
{
int i, retval=0;
int fvc = buffers->finished_voice_count;
for (i=0; i < fvc; i++)
if (buffers->finished_voices[i] == voice) {
fvc--;
if (i < fvc)
buffers->finished_voices[i] = buffers->finished_voices[fvc];
retval++;
int blockcount = buffers->mixer->current_blockcount;
int i, result = 0, start = 0;
FLUID_DECLARE_VLA(fluid_real_t, local_buf, FLUID_BUFSIZE*blockcount);
for (i=0; i < blockcount; i++) {
int s = fluid_rvoice_write(rvoice, &local_buf[FLUID_BUFSIZE*i]);
if (s == -1) {
start += FLUID_BUFSIZE;
s = FLUID_BUFSIZE;
}
fvc = buffers->finished_voice_count;
return retval;
result += s;
if (s < FLUID_BUFSIZE) {
break;
}
}
fluid_rvoice_buffers_mix(&rvoice->buffers, local_buf, start, result-start, dest_bufs, dest_bufcount);
if (result < buffers->mixer->current_blockcount * FLUID_BUFSIZE) {
fluid_finish_rvoice(buffers, rvoice);
}
}
*/
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice)
{
@ -440,8 +452,7 @@ fluid_mixer_buffers_init(fluid_mixer_buffers_t* buffers, fluid_rvoice_mixer_t* m
buffers->mixer = mixer;
buffers->buf_count = buffers->mixer->buffers.buf_count;
buffers->fx_buf_count = buffers->mixer->buffers.fx_buf_count;
buffers->buf_blocks = buffers->mixer->buffers.buf_blocks;
samplecount = FLUID_BUFSIZE * buffers->buf_blocks;
samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT;
/* Left and right audio buffers */
@ -530,7 +541,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate)
* @param fx_buf_count number of stereo effect buffers
*/
fluid_rvoice_mixer_t*
new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, fluid_real_t sample_rate)
new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, fluid_real_t sample_rate, fluid_rvoice_eventhandler_t* evthandler)
{
fluid_rvoice_mixer_t* mixer = FLUID_NEW(fluid_rvoice_mixer_t);
if (mixer == NULL) {
@ -538,9 +549,9 @@ new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, fluid_real_t sample_rate
return NULL;
}
FLUID_MEMSET(mixer, 0, sizeof(fluid_rvoice_mixer_t));
mixer->eventhandler = evthandler;
mixer->buffers.buf_count = buf_count;
mixer->buffers.fx_buf_count = fx_buf_count;
mixer->buffers.buf_blocks = FLUID_MIXER_MAX_BUFFERS_DEFAULT;
/* allocate the reverb module */
mixer->fx.reverb = new_fluid_revmodel(sample_rate);
@ -744,7 +755,7 @@ int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t* mixer,
int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t* mixer)
{
return mixer->buffers.buf_blocks;
return FLUID_MIXER_MAX_BUFFERS_DEFAULT;
}
#if WITH_PROFILING
@ -1008,8 +1019,7 @@ fluid_rvoice_mixer_render(fluid_rvoice_mixer_t* mixer, int blockcount)
{
fluid_profile_ref_var(prof_ref);
mixer->current_blockcount = blockcount > mixer->buffers.buf_blocks ?
mixer->buffers.buf_blocks : blockcount;
mixer->current_blockcount = blockcount;
// Zero buffers
fluid_mixer_buffers_zero(&mixer->buffers);

View File

@ -31,12 +31,6 @@ typedef struct _fluid_rvoice_mixer_t fluid_rvoice_mixer_t;
#define FLUID_MIXER_MAX_BUFFERS_DEFAULT (8192/FLUID_BUFSIZE)
void fluid_rvoice_mixer_set_finished_voices_callback(
fluid_rvoice_mixer_t* mixer,
void (*func)(void*, fluid_rvoice_t*),
void* userdata);
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);
@ -47,7 +41,7 @@ int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t* mixer);
int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t* mixer);
#endif
fluid_rvoice_mixer_t* new_fluid_rvoice_mixer(int buf_count, int fx_buf_count,
fluid_real_t sample_rate);
fluid_real_t sample_rate, fluid_rvoice_eventhandler_t*);
void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t*);

View File

@ -65,8 +65,8 @@
struct mononote
{
unsigned char next; /* next note */
unsigned char note; /* note */
unsigned char vel; /* velocity */
char note; /* note */
char vel; /* velocity */
};
/*
@ -83,42 +83,46 @@ struct _fluid_channel_t
/* Poly Mono variables see macro access description */
int mode; /**< Poly Mono mode */
int mode_val; /**< number of channel in basic channel group */
/* monophonic list - legato detector */
struct mononote monolist[FLUID_CHANNEL_SIZE_MONOLIST]; /**< monophonic list */
unsigned char i_first; /**< First note index */
unsigned char i_last; /**< most recent note index since the most recent add */
unsigned char prev_note; /**< previous note of the most recent add/remove */
char prev_note; /**< previous note of the most recent add/remove */
unsigned char n_notes; /**< actual number of notes in the list */
/*--*/
int key_mono_sustained; /**< previous sustained monophonic note */
struct mononote monolist[FLUID_CHANNEL_SIZE_MONOLIST]; /**< monophonic list */
char key_mono_sustained; /**< previous sustained monophonic note */
char previous_cc_breath; /**< Previous Breath */
enum fluid_channel_legato_mode legatomode; /**< legato mode */
enum fluid_channel_portamento_mode portamentomode; /**< portamento mode */
int previous_cc_breath; /**< Previous Breath */
/*- End of Poly/mono variables description */
int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */
fluid_preset_t* preset; /**< Selected preset */
char cc[128]; /**< MIDI controller values */
char key_pressure[128]; /**< MIDI polyphonic key pressure */
int channel_pressure; /**< MIDI channel pressure */
int pitch_bend; /**< Current pitch bend value */
int pitch_wheel_sensitivity; /**< Current pitch wheel sensitivity */
int cc[128]; /**< MIDI controller values */
/* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */
enum fluid_midi_channel_type channel_type;
enum fluid_interp interp_method; /**< Interpolation method (enum fluid_interp) */
char channel_pressure; /**< MIDI channel pressure */
char pitch_wheel_sensitivity; /**< Current pitch wheel sensitivity */
short pitch_bend; /**< Current pitch bend value */
/* Sostenuto order id gives the order of SostenutoOn event.
This value is useful to known when the sostenuto pedal is depressed
(before or after a key note). We need to compare SostenutoOrderId with voice id.
* This value is useful to known when the sostenuto pedal is depressed
* (before or after a key note). We need to compare SostenutoOrderId with voice id.
*/
unsigned int sostenuto_orderid;
int interp_method; /**< Interpolation method (enum fluid_interp) */
fluid_tuning_t* tuning; /**< Micro tuning */
int tuning_bank; /**< Current tuning bank number */
int tuning_prog; /**< Current tuning program number */
fluid_tuning_t* tuning; /**< Micro tuning */
fluid_preset_t* preset; /**< Selected preset */
int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */
/* NRPN system */
int nrpn_select; /* Generator ID of SoundFont NRPN message */
int nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */
enum fluid_gen_type nrpn_select; /* Generator ID of SoundFont NRPN message */
char nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */
/* The values of the generators, set by NRPN messages, or by
* fluid_synth_set_gen(), are cached in the channel so they can be
@ -137,10 +141,6 @@ struct _fluid_channel_t
* flag indicating whether the NRPN value is absolute or not.
*/
char gen_abs[GEN_LAST];
/* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */
int channel_type;
};
fluid_channel_t* new_fluid_channel(fluid_synth_t* synth, int num);
@ -231,7 +231,7 @@ int fluid_channel_get_interp_method(fluid_channel_t* chan);
fluid_channel_legato(chan))
/* Macros interface to monophonic list variables */
#define INVALID_NOTE 255
#define INVALID_NOTE (-1)
/* Returns true when a note is a valid note */
#define fluid_channel_is_valid_note(n) (n != INVALID_NOTE)
/* Marks prev_note as invalid. */

View File

@ -162,10 +162,10 @@
* - In mono staccato playing,default_fromkey must be INVALID_NOTE.
* - In mono legato playing,default_fromkey must be valid.
*/
static unsigned char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan,
unsigned char default_fromkey)
static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan,
char default_fromkey)
{
unsigned char ptc = fluid_channel_get_cc(chan, PORTAMENTO_CTRL);
char ptc = fluid_channel_get_cc(chan, PORTAMENTO_CTRL);
if(fluid_channel_is_valid_note(ptc))
{ /* CC PTC has been received */
fluid_channel_clear_portamento(chan); /* clears the CC PTC receive */
@ -178,12 +178,12 @@ static unsigned char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t*
}
else
{ /* determines and returns fromkey portamento */
unsigned char fromkey_portamento = INVALID_NOTE;
char fromkey_portamento = INVALID_NOTE;
if(fluid_channel_portamento(chan))
{ /* Portamento when Portamento pedal is On */
/* 'fromkey portamento'is determined from the portamento mode
and the most recent note played (prev_note)*/
unsigned char portamentomode = chan->portamentomode;
enum fluid_channel_portamento_mode portamentomode = chan->portamentomode;
if(fluid_channel_is_valid_note(default_fromkey))
{
fromkey_portamento = default_fromkey; /* on each note */
@ -319,7 +319,7 @@ int fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan,
fluid_channel_t* channel = synth->channel[chan];
/* Adds the note into the monophonic list */
fluid_channel_add_monolist(channel,(unsigned char)key,(unsigned char)vel,0);
fluid_channel_add_monolist(channel, key, vel, 0);
/* in Breath Sync mode, the noteon triggering is postponed
until the musician starts blowing in the breath controller */
@ -381,7 +381,7 @@ int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key)
int i,i_prev;
fluid_channel_t* channel = synth->channel[chan];
/* searching the note in the monophonic list */
i=fluid_channel_search_monolist(channel, (unsigned char)key , &i_prev);
i=fluid_channel_search_monolist(channel, key , &i_prev);
if (i >= 0)
{ /* the note is in the monophonic list */
@ -624,11 +624,11 @@ int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan,
int fromkey, int tokey, int vel)
{
fluid_channel_t* channel = synth->channel[chan];
unsigned char legatomode = channel->legatomode;
enum fluid_channel_legato_mode legatomode = channel->legatomode;
fluid_voice_t* voice;
int i ;
/* Gets possible 'fromkey portamento' and possible 'fromkey legato' note */
fromkey = fluid_synth_get_fromkey_portamento_legato( channel, (unsigned char)fromkey);
fromkey = fluid_synth_get_fromkey_portamento_legato( channel, fromkey);
if (fluid_channel_is_valid_note(fromkey)) for (i = 0; i < synth->polyphony; i++)
{

View File

@ -71,17 +71,17 @@ struct _fluid_voice_t
unsigned char vel; /* the velocity of the noteon event */
fluid_channel_t* channel;
fluid_rvoice_eventhandler_t* eventhandler;
fluid_gen_t gen[GEN_LAST];
fluid_mod_t mod[FLUID_NUM_MOD];
int mod_count;
fluid_zone_range_t * zone_range; /* instrument zone range*/
fluid_sample_t* sample; /* Pointer to sample (dupe in rvoice) */
unsigned int start_time;
int mod_count;
fluid_mod_t mod[FLUID_NUM_MOD];
fluid_gen_t gen[GEN_LAST];
/* basic parameters */
fluid_real_t output_rate; /* the sample rate of the synthesizer (dupe in rvoice) */
unsigned int start_time;
/* basic parameters */
fluid_real_t pitch; /* the pitch in midicents (dupe in rvoice) */
fluid_real_t attenuation; /* the attenuation in centibels (dupe in rvoice) */

View File

@ -59,6 +59,16 @@ void fluid_time_config(void);
/* Misc */
#if defined(__INTEL_COMPILER)
#define FLUID_RESTRICT restrict
#elif defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#define FLUID_RESTRICT __restrict__
#elif defined(_MSC_VER)
#define FLUID_RESTRICT __restrict
#else
#warning "Dont know how this compiler handles restrict pointers, refuse to use them."
#define FLUID_RESTRICT
#endif
#define FLUID_INLINE inline
#define FLUID_POINTER_TO_UINT GPOINTER_TO_UINT

View File

@ -204,6 +204,7 @@ typedef struct _fluid_client_t fluid_client_t;
typedef struct _fluid_server_socket_t fluid_server_socket_t;
typedef struct _fluid_sample_timer_t fluid_sample_timer_t;
typedef struct _fluid_zone_range_t fluid_zone_range_t;
typedef struct _fluid_rvoice_eventhandler_t fluid_rvoice_eventhandler_t;
/* Declare rvoice related typedefs here instead of fluid_rvoice.h, as it's needed
* in fluid_lfo.c and fluid_adsr.c as well */