Merge pull request #364 from FluidSynth/197

Unify calling conventions for rvoice update functions
This commit is contained in:
Tom M 2018-04-11 19:42:19 +02:00 committed by GitHub
commit d3e6781abd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 486 additions and 476 deletions

View file

@ -20,15 +20,16 @@
#include "fluid_adsr_env.h" #include "fluid_adsr_env.h"
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data)
fluid_adsr_env_set_data(fluid_adsr_env_t* env,
fluid_adsr_env_section_t section,
unsigned int count,
fluid_real_t coeff,
fluid_real_t increment,
fluid_real_t min,
fluid_real_t max)
{ {
fluid_adsr_env_t* env = obj;
fluid_adsr_env_section_t section = param[0].i;
unsigned int count = param[1].i;
fluid_real_t coeff = param[2].real;
fluid_real_t increment = param[3].real;
fluid_real_t min = param[4].real;
fluid_real_t max = param[5].real;
env->data[section].count = count; env->data[section].count = count;
env->data[section].coeff = coeff; env->data[section].coeff = coeff;
env->data[section].increment = increment; env->data[section].increment = increment;

View file

@ -104,14 +104,7 @@ fluid_adsr_env_calc(fluid_adsr_env_t* env, int is_volenv)
/* This one cannot be inlined since it is referenced in /* This one cannot be inlined since it is referenced in
the event queue */ the event queue */
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data);
fluid_adsr_env_set_data(fluid_adsr_env_t* env,
fluid_adsr_env_section_t section,
unsigned int count,
fluid_real_t coeff,
fluid_real_t increment,
fluid_real_t min,
fluid_real_t max);
static FLUID_INLINE void static FLUID_INLINE void
fluid_adsr_env_reset(fluid_adsr_env_t* env) fluid_adsr_env_reset(fluid_adsr_env_t* env)

View file

@ -138,8 +138,12 @@ fluid_iir_filter_apply(fluid_iir_filter_t* iir_filter,
} }
void fluid_iir_filter_init(fluid_iir_filter_t* iir_filter, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags) DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_init)
{ {
fluid_iir_filter_t* iir_filter = obj;
enum fluid_iir_filter_type type = param[0].i;
enum fluid_iir_filter_flags flags = param[1].i;
iir_filter->type = type; iir_filter->type = type;
iir_filter->flags = flags; iir_filter->flags = flags;
if(type != FLUID_IIR_DISABLED) if(type != FLUID_IIR_DISABLED)
@ -158,10 +162,11 @@ fluid_iir_filter_reset(fluid_iir_filter_t* iir_filter)
iir_filter->filter_startup = 1; iir_filter->filter_startup = 1;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_fres)
fluid_iir_filter_set_fres(fluid_iir_filter_t* iir_filter,
fluid_real_t fres)
{ {
fluid_iir_filter_t* iir_filter = obj;
fluid_real_t fres = param[0].real;
iir_filter->fres = fres; iir_filter->fres = fres;
iir_filter->last_fres = -1.; iir_filter->last_fres = -1.;
} }
@ -197,9 +202,10 @@ static fluid_real_t fluid_iir_filter_q_from_dB(fluid_real_t q_dB)
return pow(10.0f, q_dB / 20.0f); return pow(10.0f, q_dB / 20.0f);
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q)
fluid_iir_filter_set_q(fluid_iir_filter_t* iir_filter, fluid_real_t q)
{ {
fluid_iir_filter_t* iir_filter = obj;
fluid_real_t q = param[0].real;
int flags = iir_filter->flags; int flags = iir_filter->flags;
if(flags & FLUID_IIR_Q_ZERO_OFF && q<=0.0) if(flags & FLUID_IIR_Q_ZERO_OFF && q<=0.0)

View file

@ -25,19 +25,15 @@
typedef struct _fluid_iir_filter_t fluid_iir_filter_t; typedef struct _fluid_iir_filter_t fluid_iir_filter_t;
DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_init);
void fluid_iir_filter_init(fluid_iir_filter_t* iir_filter, enum fluid_iir_filter_type, enum fluid_iir_filter_flags flags); DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_fres);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q);
void fluid_iir_filter_apply(fluid_iir_filter_t* iir_filter, void fluid_iir_filter_apply(fluid_iir_filter_t* iir_filter,
fluid_real_t *dsp_buf, int dsp_buf_count); fluid_real_t *dsp_buf, int dsp_buf_count);
void fluid_iir_filter_reset(fluid_iir_filter_t* iir_filter); void fluid_iir_filter_reset(fluid_iir_filter_t* iir_filter);
void fluid_iir_filter_set_q(fluid_iir_filter_t* iir_filter, fluid_real_t q);
void fluid_iir_filter_set_fres(fluid_iir_filter_t* iir_filter,
fluid_real_t fres);
void fluid_iir_filter_calc(fluid_iir_filter_t* iir_filter, void fluid_iir_filter_calc(fluid_iir_filter_t* iir_filter,
fluid_real_t output_rate, fluid_real_t output_rate,
fluid_real_t fres_mod); fluid_real_t fres_mod);

View file

@ -1,13 +1,17 @@
#include "fluid_lfo.h" #include "fluid_lfo.h"
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_incr)
fluid_lfo_set_incr(fluid_lfo_t* lfo, fluid_real_t increment)
{ {
lfo->increment = increment; fluid_lfo_t* lfo = obj;
fluid_real_t increment = param[0].real;
lfo->increment = increment;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_delay)
fluid_lfo_set_delay(fluid_lfo_t* lfo, unsigned int delay)
{ {
lfo->delay = delay; fluid_lfo_t* lfo = obj;
unsigned int delay = param[0].i;
lfo->delay = delay;
} }

View file

@ -38,8 +38,8 @@ fluid_lfo_reset(fluid_lfo_t* lfo)
} }
// These two cannot be inlined since they're used by event_dispatch // These two cannot be inlined since they're used by event_dispatch
void fluid_lfo_set_incr(fluid_lfo_t* lfo, fluid_real_t increment); DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_incr);
void fluid_lfo_set_delay(fluid_lfo_t* lfo, unsigned int delay); DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_delay);
static FLUID_INLINE fluid_real_t static FLUID_INLINE fluid_real_t
fluid_lfo_get_val(fluid_lfo_t* lfo) fluid_lfo_get_val(fluid_lfo_t* lfo)

View file

@ -22,6 +22,9 @@
#include "fluid_conv.h" #include "fluid_conv.h"
#include "fluid_sys.h" #include "fluid_sys.h"
static void fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t* voice, unsigned int min_ticks);
/** /**
* @return -1 if voice has finished, 0 if it's currently quiet, 1 otherwise * @return -1 if voice has finished, 0 if it's currently quiet, 1 otherwise
*/ */
@ -158,7 +161,7 @@ fluid_rvoice_check_sample_sanity(fluid_rvoice_t* voice)
/* Zero length? */ /* Zero length? */
if (voice->dsp.start == voice->dsp.end){ if (voice->dsp.start == voice->dsp.end){
fluid_rvoice_voiceoff(voice); fluid_rvoice_voiceoff(voice, NULL);
return; return;
} }
@ -282,7 +285,7 @@ fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
if (voice->envlfo.noteoff_ticks != 0 && if (voice->envlfo.noteoff_ticks != 0 &&
voice->envlfo.ticks >= voice->envlfo.noteoff_ticks) { voice->envlfo.ticks >= voice->envlfo.noteoff_ticks) {
fluid_rvoice_noteoff(voice, 0); fluid_rvoice_noteoff_LOCAL(voice, 0);
} }
voice->envlfo.ticks += FLUID_BUFSIZE; voice->envlfo.ticks += FLUID_BUFSIZE;
@ -475,28 +478,33 @@ fluid_rvoice_buffers_check_bufnum(fluid_rvoice_buffers_t* buffers, unsigned int
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp)
fluid_rvoice_buffers_set_amp(fluid_rvoice_buffers_t* buffers,
unsigned int bufnum, fluid_real_t value)
{ {
fluid_rvoice_buffers_t* buffers = obj;
unsigned int bufnum = param[0].i;
fluid_real_t value = param[1].real;
if (fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK) if (fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK)
return; return;
buffers->bufs[bufnum].amp = value; buffers->bufs[bufnum].amp = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping)
fluid_rvoice_buffers_set_mapping(fluid_rvoice_buffers_t* buffers,
unsigned int bufnum, int mapping)
{ {
fluid_rvoice_buffers_t* buffers = obj;
unsigned int bufnum = param[0].i;
int mapping = param[1].i;
if (fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK) if (fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK)
return; return;
buffers->bufs[bufnum].mapping = mapping; buffers->bufs[bufnum].mapping = mapping;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_reset)
fluid_rvoice_reset(fluid_rvoice_t* voice)
{ {
fluid_rvoice_t* voice = obj;
voice->dsp.has_looped = 0; voice->dsp.has_looped = 0;
voice->envlfo.ticks = 0; voice->envlfo.ticks = 0;
voice->envlfo.noteoff_ticks = 0; voice->envlfo.noteoff_ticks = 0;
@ -530,9 +538,16 @@ fluid_rvoice_reset(fluid_rvoice_t* voice)
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP;
} }
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_noteoff)
{
fluid_rvoice_t* rvoice = obj;
unsigned int min_ticks = param[0].i;
fluid_rvoice_noteoff_LOCAL(rvoice, min_ticks);
}
void static void
fluid_rvoice_noteoff(fluid_rvoice_t* voice, unsigned int min_ticks) fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t* voice, unsigned int min_ticks)
{ {
if (min_ticks > voice->envlfo.ticks) { if (min_ticks > voice->envlfo.ticks) {
/* Delay noteoff */ /* Delay noteoff */
@ -600,9 +615,9 @@ static FLUID_INLINE void fluid_rvoice_local_retrigger_attack (fluid_rvoice_t* vo
* see fluid_synth_noteon_mono_legato_multi_retrigger() * see fluid_synth_noteon_mono_legato_multi_retrigger()
* @param voice the synthesis voice to be updated * @param voice the synthesis voice to be updated
*/ */
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack)
fluid_rvoice_multi_retrigger_attack (fluid_rvoice_t* voice)
{ {
fluid_rvoice_t* voice = obj;
int section = fluid_adsr_env_get_section(&voice->envlfo.volenv); int section = fluid_adsr_env_get_section(&voice->envlfo.volenv);
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
Section skip for volume envelope Section skip for volume envelope
@ -645,9 +660,12 @@ fluid_rvoice_multi_retrigger_attack (fluid_rvoice_t* voice)
* pitchoffset is accumulated in current dsp pitchoffset. * pitchoffset is accumulated in current dsp pitchoffset.
* 2) And to get constant portamento duration, dsp pitch increment is updated. * 2) And to get constant portamento duration, dsp pitch increment is updated.
*/ */
void fluid_rvoice_set_portamento(fluid_rvoice_t * voice, unsigned int countinc, DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_portamento)
fluid_real_t pitchoffset)
{ {
fluid_rvoice_t * voice = obj;
unsigned int countinc = param[0].i;
fluid_real_t pitchoffset = param[1].real;
if (countinc) if (countinc)
{ {
voice->dsp.pitchoffset += pitchoffset; voice->dsp.pitchoffset += pitchoffset;
@ -657,82 +675,110 @@ void fluid_rvoice_set_portamento(fluid_rvoice_t * voice, unsigned int countinc,
dsp.pitchoffset will be incremented by dsp pitchinc. */ dsp.pitchoffset will be incremented by dsp pitchinc. */
} }
void
fluid_rvoice_set_output_rate(fluid_rvoice_t* voice, fluid_real_t value) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_output_rate)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->dsp.output_rate = value; voice->dsp.output_rate = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_interp_method)
fluid_rvoice_set_interp_method(fluid_rvoice_t* voice, int value)
{ {
fluid_rvoice_t* voice = obj;
int value = param[0].i;
voice->dsp.interp_method = value; voice->dsp.interp_method = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_root_pitch_hz)
fluid_rvoice_set_root_pitch_hz(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->dsp.root_pitch_hz = value; voice->dsp.root_pitch_hz = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_pitch)
fluid_rvoice_set_pitch(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->dsp.pitch = value; voice->dsp.pitch = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_attenuation)
fluid_rvoice_set_attenuation(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->dsp.prev_attenuation = voice->dsp.attenuation; voice->dsp.prev_attenuation = voice->dsp.attenuation;
voice->dsp.attenuation = value; voice->dsp.attenuation = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_min_attenuation_cB)
fluid_rvoice_set_min_attenuation_cB(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->dsp.min_attenuation_cB = value; voice->dsp.min_attenuation_cB = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_viblfo_to_pitch)
fluid_rvoice_set_viblfo_to_pitch(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->envlfo.viblfo_to_pitch = value; voice->envlfo.viblfo_to_pitch = value;
} }
void fluid_rvoice_set_modlfo_to_pitch(fluid_rvoice_t* voice, fluid_real_t value) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_pitch)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->envlfo.modlfo_to_pitch = value; voice->envlfo.modlfo_to_pitch = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_vol)
fluid_rvoice_set_modlfo_to_vol(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->envlfo.modlfo_to_vol = value; voice->envlfo.modlfo_to_vol = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_fc)
fluid_rvoice_set_modlfo_to_fc(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->envlfo.modlfo_to_fc = value; voice->envlfo.modlfo_to_fc = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_fc)
fluid_rvoice_set_modenv_to_fc(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->envlfo.modenv_to_fc = value; voice->envlfo.modenv_to_fc = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_pitch)
fluid_rvoice_set_modenv_to_pitch(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->envlfo.modenv_to_pitch = value; voice->envlfo.modenv_to_pitch = value;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_synth_gain)
fluid_rvoice_set_synth_gain(fluid_rvoice_t* voice, fluid_real_t value)
{ {
fluid_rvoice_t* voice = obj;
fluid_real_t value = param[0].real;
voice->dsp.synth_gain = value; voice->dsp.synth_gain = value;
/* For a looped sample, this value will be overwritten as soon as the /* For a looped sample, this value will be overwritten as soon as the
@ -744,52 +790,67 @@ fluid_rvoice_set_synth_gain(fluid_rvoice_t* voice, fluid_real_t value)
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_start)
fluid_rvoice_set_start(fluid_rvoice_t* voice, int value)
{ {
fluid_rvoice_t* voice = obj;
int value = param[0].i;
voice->dsp.start = value; voice->dsp.start = value;
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_end)
fluid_rvoice_set_end(fluid_rvoice_t* voice, int value)
{ {
fluid_rvoice_t* voice = obj;
int value = param[0].i;
voice->dsp.end = value; voice->dsp.end = value;
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopstart)
fluid_rvoice_set_loopstart(fluid_rvoice_t* voice, int value)
{ {
fluid_rvoice_t* voice = obj;
int value = param[0].i;
voice->dsp.loopstart = value; voice->dsp.loopstart = value;
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
} }
void fluid_rvoice_set_loopend(fluid_rvoice_t* voice, int value) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopend)
{ {
fluid_rvoice_t* voice = obj;
int value = param[0].i;
voice->dsp.loopend = value; voice->dsp.loopend = value;
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
} }
void fluid_rvoice_set_samplemode(fluid_rvoice_t* voice, enum fluid_loop value) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode)
{ {
fluid_rvoice_t* voice = obj;
enum fluid_loop value = param[0].i;
voice->dsp.samplemode = value; voice->dsp.samplemode = value;
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK;
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample)
fluid_rvoice_set_sample(fluid_rvoice_t* voice, fluid_sample_t* value)
{ {
fluid_rvoice_t* voice = obj;
fluid_sample_t* value = param[0].ptr;
voice->dsp.sample = value; voice->dsp.sample = value;
if (value) { if (value) {
voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP; voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP;
} }
} }
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_voiceoff)
fluid_rvoice_voiceoff(fluid_rvoice_t* voice)
{ {
fluid_rvoice_t* voice = obj;
fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVFINISHED); fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVFINISHED);
fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVFINISHED); fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVFINISHED);
} }

View file

@ -167,40 +167,36 @@ int fluid_rvoice_write(fluid_rvoice_t* voice, fluid_real_t *dsp_buf);
void fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers, void fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers,
fluid_real_t* dsp_buf, int samplecount, fluid_real_t* dsp_buf, int samplecount,
fluid_real_t** dest_bufs, int dest_bufcount); fluid_real_t** dest_bufs, int dest_bufcount);
void fluid_rvoice_buffers_set_amp(fluid_rvoice_buffers_t* buffers,
unsigned int bufnum, fluid_real_t value);
void fluid_rvoice_buffers_set_mapping(fluid_rvoice_buffers_t* buffers,
unsigned int bufnum, int mapping);
/* Dynamic update functions */ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp);
void fluid_rvoice_set_portamento(fluid_rvoice_t * voice, unsigned int countinc, DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping);
fluid_real_t pitchoffset);
void fluid_rvoice_multi_retrigger_attack(fluid_rvoice_t* voice); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_noteoff);
void fluid_rvoice_noteoff(fluid_rvoice_t* voice, unsigned int min_ticks); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_voiceoff);
void fluid_rvoice_voiceoff(fluid_rvoice_t* voice); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_reset);
void fluid_rvoice_reset(fluid_rvoice_t* voice); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack);
void fluid_rvoice_set_output_rate(fluid_rvoice_t* voice, fluid_real_t output_rate); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_portamento);
void fluid_rvoice_set_interp_method(fluid_rvoice_t* voice, int interp_method); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_output_rate);
void fluid_rvoice_set_root_pitch_hz(fluid_rvoice_t* voice, fluid_real_t root_pitch_hz); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_interp_method);
void fluid_rvoice_set_pitch(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_root_pitch_hz);
void fluid_rvoice_set_synth_gain(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_pitch);
void fluid_rvoice_set_attenuation(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_attenuation);
void fluid_rvoice_set_min_attenuation_cB(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_min_attenuation_cB);
void fluid_rvoice_set_viblfo_to_pitch(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_viblfo_to_pitch);
void fluid_rvoice_set_modlfo_to_pitch(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_pitch);
void fluid_rvoice_set_modlfo_to_vol(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_vol);
void fluid_rvoice_set_modlfo_to_fc(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_fc);
void fluid_rvoice_set_modenv_to_fc(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_fc);
void fluid_rvoice_set_modenv_to_pitch(fluid_rvoice_t* voice, fluid_real_t value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_pitch);
void fluid_rvoice_set_start(fluid_rvoice_t* voice, int value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_synth_gain);
void fluid_rvoice_set_end(fluid_rvoice_t* voice, int value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_start);
void fluid_rvoice_set_loopstart(fluid_rvoice_t* voice, int value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_end);
void fluid_rvoice_set_loopend(fluid_rvoice_t* voice, int value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopstart);
void fluid_rvoice_set_sample(fluid_rvoice_t* voice, fluid_sample_t* value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopend);
void fluid_rvoice_set_samplemode(fluid_rvoice_t* voice, enum fluid_loop value); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample);
/* defined in fluid_rvoice_dsp.c */ /* defined in fluid_rvoice_dsp.c */
void fluid_rvoice_dsp_config (void); void fluid_rvoice_dsp_config (void);
int fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice); 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_linear (fluid_rvoice_dsp_t *voice);

View file

@ -24,136 +24,13 @@
#include "fluid_iir_filter.h" #include "fluid_iir_filter.h"
#include "fluid_lfo.h" #include "fluid_lfo.h"
#include "fluid_adsr_env.h" #include "fluid_adsr_env.h"
/* Calling proc without data parameters */
#define EVENTFUNC_0(proc, type) \
if (event->method == proc) { \
proc((type) event->object); \
return; }
/* Calling proc passing only one real data parameter */
#define EVENTFUNC_R1(proc, type) \
if (event->method == proc) { \
if(event->intparam != 0) { FLUID_LOG(FLUID_DBG, "IR-mismatch"); } \
proc((type) event->object, event->realparams[0]); \
return; }
/* Calling proc passing pointer parameter */
#define EVENTFUNC_PTR(proc, type, type2) \
if (event->method == proc) { \
proc((type) event->object, (type2) event->ptr); \
return; }
/* Calling proc passing only int parameter */
#define EVENTFUNC_I1(proc, type) \
if (event->method == proc) { \
if(event->realparams[0] != 0.0f) { FLUID_LOG(FLUID_DBG, "IR-mismatch"); } \
proc((type) event->object, event->intparam); \
return; }
/* Calling proc passing: int,int data parameters */
#define EVENTFUNC_II(proc, type) \
if (event->method == proc) { \
proc((type) event->object, event->intparam, (int) event->realparams[0]); \
return; }
/* Calling proc passing: int,real data parameters */
#define EVENTFUNC_IR(proc, type) \
if (event->method == proc) { \
proc((type) event->object, event->intparam, event->realparams[0]); \
return; }
/* Calling proc passing: int,real,real,real,real,real data parameters */
#define EVENTFUNC_ALL(proc, type) \
if (event->method == proc) { \
proc((type) event->object, event->intparam, event->realparams[0], \
event->realparams[1], event->realparams[2], event->realparams[3], \
event->realparams[4]); \
return; }
/* Calling proc passing: int,int,real,real,real,int data parameters */
#define EVENTFUNC_IIR3I(proc, type) \
if (event->method == proc) { \
proc((type) event->object, event->intparam, (int)event->realparams[0], \
event->realparams[1], event->realparams[2], event->realparams[3], \
(int)event->realparams[4]); \
return; }
/* Calling proc passing: int,int,real,real,real,real data parameters */
#define EVENTFUNC_IIR4(proc, type) \
if (event->method == proc) { \
proc((type) event->object, event->intparam, (int)event->realparams[0], \
event->realparams[1], event->realparams[2], event->realparams[3], \
event->realparams[4]); \
return; }
/* Calling proc passing: int,real,real,real,real data parameters */
#define EVENTFUNC_R4(proc, type) \
if (event->method == proc) { \
proc((type) event->object, event->intparam, event->realparams[0], \
event->realparams[1], event->realparams[2], event->realparams[3]); \
return; }
static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event); static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event);
void static FLUID_INLINE void
fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event) fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event)
{ {
EVENTFUNC_PTR(fluid_rvoice_mixer_add_voice, fluid_rvoice_mixer_t*, fluid_rvoice_t*); event->method(event->object, event->param);
EVENTFUNC_I1(fluid_rvoice_noteoff, fluid_rvoice_t*);
EVENTFUNC_0(fluid_rvoice_voiceoff, fluid_rvoice_t*);
EVENTFUNC_0(fluid_rvoice_reset, fluid_rvoice_t*);
EVENTFUNC_0(fluid_rvoice_multi_retrigger_attack, fluid_rvoice_t*);
EVENTFUNC_IR(fluid_rvoice_set_portamento, fluid_rvoice_t*);
EVENTFUNC_IIR4(fluid_adsr_env_set_data, fluid_adsr_env_t*);
EVENTFUNC_I1(fluid_lfo_set_delay, fluid_lfo_t*);
EVENTFUNC_R1(fluid_lfo_set_incr, fluid_lfo_t*);
EVENTFUNC_II(fluid_iir_filter_init, fluid_iir_filter_t*);
EVENTFUNC_R1(fluid_iir_filter_set_fres, fluid_iir_filter_t*);
EVENTFUNC_R1(fluid_iir_filter_set_q, fluid_iir_filter_t*);
EVENTFUNC_II(fluid_rvoice_buffers_set_mapping, fluid_rvoice_buffers_t*);
EVENTFUNC_IR(fluid_rvoice_buffers_set_amp, fluid_rvoice_buffers_t*);
EVENTFUNC_R1(fluid_rvoice_set_modenv_to_pitch, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_output_rate, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_root_pitch_hz, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_synth_gain, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_pitch, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_attenuation, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_min_attenuation_cB, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_viblfo_to_pitch, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_modlfo_to_pitch, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_modlfo_to_vol, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_modlfo_to_fc, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_modenv_to_fc, fluid_rvoice_t*);
EVENTFUNC_R1(fluid_rvoice_set_modenv_to_pitch, fluid_rvoice_t*);
EVENTFUNC_I1(fluid_rvoice_set_interp_method, fluid_rvoice_t*);
EVENTFUNC_I1(fluid_rvoice_set_start, fluid_rvoice_t*);
EVENTFUNC_I1(fluid_rvoice_set_end, fluid_rvoice_t*);
EVENTFUNC_I1(fluid_rvoice_set_loopstart, fluid_rvoice_t*);
EVENTFUNC_I1(fluid_rvoice_set_loopend, fluid_rvoice_t*);
EVENTFUNC_I1(fluid_rvoice_set_samplemode, fluid_rvoice_t*);
EVENTFUNC_PTR(fluid_rvoice_set_sample, fluid_rvoice_t*, fluid_sample_t*);
EVENTFUNC_R1(fluid_rvoice_mixer_set_samplerate, fluid_rvoice_mixer_t*);
EVENTFUNC_I1(fluid_rvoice_mixer_set_polyphony, fluid_rvoice_mixer_t*);
EVENTFUNC_I1(fluid_rvoice_mixer_set_reverb_enabled, fluid_rvoice_mixer_t*);
EVENTFUNC_I1(fluid_rvoice_mixer_set_chorus_enabled, fluid_rvoice_mixer_t*);
EVENTFUNC_I1(fluid_rvoice_mixer_set_mix_fx, fluid_rvoice_mixer_t*);
EVENTFUNC_0(fluid_rvoice_mixer_reset_fx, fluid_rvoice_mixer_t*);
EVENTFUNC_0(fluid_rvoice_mixer_reset_reverb, fluid_rvoice_mixer_t*);
EVENTFUNC_0(fluid_rvoice_mixer_reset_chorus, fluid_rvoice_mixer_t*);
EVENTFUNC_II(fluid_rvoice_mixer_set_threads, fluid_rvoice_mixer_t*);
EVENTFUNC_IIR3I(fluid_rvoice_mixer_set_chorus_params, fluid_rvoice_mixer_t*);
EVENTFUNC_R4(fluid_rvoice_mixer_set_reverb_params, fluid_rvoice_mixer_t*);
FLUID_LOG(FLUID_ERR, "fluid_rvoice_event_dispatch: Unknown method %p to dispatch!", event->method);
} }
@ -162,56 +39,45 @@ fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event)
* use push for all events, then use flush to commit them to the * use push for all events, then use flush to commit them to the
* queue. If threadsafe is false, all events are processed immediately. */ * queue. If threadsafe is false, all events are processed immediately. */
int int
fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler, fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t* handler,
void* method, void* object, int intparam, fluid_rvoice_function_t method, void* object, int intparam,
fluid_real_t realparam) fluid_real_t realparam)
{ {
fluid_rvoice_event_t local_event; fluid_rvoice_event_t local_event;
local_event.method = method; local_event.method = method;
local_event.object = object; local_event.object = object;
local_event.intparam = intparam; local_event.param[0].i = intparam;
local_event.realparams[0] = realparam; local_event.param[1].real = realparam;
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
} }
int
fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler, fluid_rvoice_function_t method, void* object, fluid_rvoice_param_t param[MAX_EVENT_PARAMS])
{
fluid_rvoice_event_t local_event;
local_event.method = method;
local_event.object = object;
FLUID_MEMCPY(&local_event.param, param, sizeof(*param) * MAX_EVENT_PARAMS);
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
}
int int
fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler, fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler,
void* method, void* object, void* ptr) fluid_rvoice_function_t method, void* object, void* ptr)
{ {
fluid_rvoice_event_t local_event; fluid_rvoice_event_t local_event;
local_event.method = method; local_event.method = method;
local_event.object = object; local_event.object = object;
local_event.ptr = ptr; local_event.param[0].ptr = ptr;
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
} }
int
fluid_rvoice_eventhandler_push5(fluid_rvoice_eventhandler_t* handler,
void* method, void* object, int intparam,
fluid_real_t r1, fluid_real_t r2,
fluid_real_t r3, fluid_real_t r4, fluid_real_t r5)
{
fluid_rvoice_event_t local_event;
local_event.method = method;
local_event.object = object;
local_event.intparam = intparam;
local_event.realparams[0] = r1;
local_event.realparams[1] = r2;
local_event.realparams[2] = r3;
local_event.realparams[3] = r4;
local_event.realparams[4] = r5;
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
}
static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event) static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event)
{ {
fluid_rvoice_event_t* event; fluid_rvoice_event_t* event;
@ -225,7 +91,7 @@ static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* han
return FLUID_FAILED; // Buffer full... return FLUID_FAILED; // Buffer full...
} }
memcpy(event, src_event, sizeof(*event)); FLUID_MEMCPY(event, src_event, sizeof(*event));
return FLUID_OK; return FLUID_OK;
} }

View file

@ -26,22 +26,15 @@
#include "fluid_rvoice_mixer.h" #include "fluid_rvoice_mixer.h"
#include "fluid_ringbuffer.h" #include "fluid_ringbuffer.h"
#define EVENT_REAL_PARAMS (5)
typedef struct _fluid_rvoice_event_t fluid_rvoice_event_t; typedef struct _fluid_rvoice_event_t fluid_rvoice_event_t;
typedef struct _fluid_rvoice_eventhandler_t fluid_rvoice_eventhandler_t; typedef struct _fluid_rvoice_eventhandler_t fluid_rvoice_eventhandler_t;
struct _fluid_rvoice_event_t { struct _fluid_rvoice_event_t {
void* method; fluid_rvoice_function_t method;
void* object; void* object;
void* ptr; fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
int intparam;
fluid_real_t realparams[EVENT_REAL_PARAMS];
}; };
void fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event);
/* /*
* Bridge between the renderer thread and the midi state thread. * Bridge between the renderer thread and the midi state thread.
* fluid_rvoice_eventhandler_fetch_all() can be called in parallell * fluid_rvoice_eventhandler_fetch_all() can be called in parallell
@ -88,17 +81,16 @@ fluid_rvoice_eventhandler_get_finished_voice(fluid_rvoice_eventhandler_t* handle
} }
int fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler, int fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t* handler,
void* method, void* object, int intparam, fluid_rvoice_function_t method, void* object, int intparam,
fluid_real_t realparam); fluid_real_t realparam);
int fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler, int fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler,
void* method, void* object, void* ptr); fluid_rvoice_function_t method, void* object, void* ptr);
int fluid_rvoice_eventhandler_push5(fluid_rvoice_eventhandler_t* handler, int fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler,
void* method, void* object, int intparam, fluid_rvoice_function_t method, void* object,
fluid_real_t r1, fluid_real_t r2, fluid_rvoice_param_t param[MAX_EVENT_PARAMS]);
fluid_real_t r3, fluid_real_t r4, fluid_real_t r5);
static FLUID_INLINE void static FLUID_INLINE void
fluid_rvoice_eventhandler_add_rvoice(fluid_rvoice_eventhandler_t* handler, fluid_rvoice_eventhandler_add_rvoice(fluid_rvoice_eventhandler_t* handler,

View file

@ -311,14 +311,15 @@ static int fluid_mixer_buffers_replace_voice(fluid_mixer_buffers_t* buffers,
} }
*/ */
int DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice)
fluid_rvoice_mixer_add_voice(fluid_rvoice_mixer_t* mixer, fluid_rvoice_t* voice)
{ {
int i; int i;
fluid_rvoice_mixer_t* mixer = obj;
fluid_rvoice_t* voice = param[0].ptr;
if (mixer->active_voices < mixer->polyphony) { if (mixer->active_voices < mixer->polyphony) {
mixer->rvoices[mixer->active_voices++] = voice; mixer->rvoices[mixer->active_voices++] = voice;
return FLUID_OK; return; // success
} }
/* See if any voices just finished, if so, take its place. /* See if any voices just finished, if so, take its place.
@ -326,18 +327,18 @@ fluid_rvoice_mixer_add_voice(fluid_rvoice_mixer_t* mixer, fluid_rvoice_t* voice)
for (i=0; i < mixer->active_voices; i++) { for (i=0; i < mixer->active_voices; i++) {
if (mixer->rvoices[i] == voice) { if (mixer->rvoices[i] == voice) {
FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!"); FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!");
return FLUID_FAILED; return;
} }
if (mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED) { if (mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED) {
fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]); fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]);
mixer->rvoices[i] = voice; mixer->rvoices[i] = voice;
return FLUID_OK; return; // success
} }
} }
/* This should never happen */ /* This should never happen */
FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice"); FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice");
return FLUID_FAILED; return;
} }
static int static int
@ -359,21 +360,23 @@ fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t* buffers, int value)
* Update polyphony - max number of voices (NOTE: not hard real-time capable) * Update polyphony - max number of voices (NOTE: not hard real-time capable)
* @return FLUID_OK or FLUID_FAILED * @return FLUID_OK or FLUID_FAILED
*/ */
int DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony)
fluid_rvoice_mixer_set_polyphony(fluid_rvoice_mixer_t* handler, int value)
{ {
void* newptr; void* newptr;
fluid_rvoice_mixer_t* handler = obj;
int value = param[0].i;
if (handler->active_voices > value) if (handler->active_voices > value)
return FLUID_FAILED; return /*FLUID_FAILED*/;
newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t*)); newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t*));
if (newptr == NULL) if (newptr == NULL)
return FLUID_FAILED; return /*FLUID_FAILED*/;
handler->rvoices = newptr; handler->rvoices = newptr;
if (fluid_mixer_buffers_update_polyphony(&handler->buffers, value) if (fluid_mixer_buffers_update_polyphony(&handler->buffers, value)
== FLUID_FAILED) == FLUID_FAILED)
return FLUID_FAILED; return /*FLUID_FAILED*/;
#ifdef ENABLE_MIXER_THREADS #ifdef ENABLE_MIXER_THREADS
{ {
@ -381,12 +384,12 @@ fluid_rvoice_mixer_set_polyphony(fluid_rvoice_mixer_t* handler, int value)
for (i=0; i < handler->thread_count; i++) for (i=0; i < handler->thread_count; i++)
if (fluid_mixer_buffers_update_polyphony(&handler->threads[i], value) if (fluid_mixer_buffers_update_polyphony(&handler->threads[i], value)
== FLUID_FAILED) == FLUID_FAILED)
return FLUID_FAILED; return /*FLUID_FAILED*/;
} }
#endif #endif
handler->polyphony = value; handler->polyphony = value;
return FLUID_OK; return /*FLUID_OK*/;
} }
@ -497,17 +500,18 @@ fluid_mixer_buffers_init(fluid_mixer_buffers_t* buffers, fluid_rvoice_mixer_t* m
/** /**
* Note: Not hard real-time capable (calls malloc) * Note: Not hard real-time capable (calls malloc)
*/ */
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate)
fluid_rvoice_mixer_set_samplerate(fluid_rvoice_mixer_t* mixer, fluid_real_t samplerate)
{ {
int i; fluid_rvoice_mixer_t* mixer = obj;
fluid_real_t samplerate = param[1].real; // becausee fluid_synth_update_mixer() puts real into arg2
if (mixer->fx.chorus) if (mixer->fx.chorus)
delete_fluid_chorus(mixer->fx.chorus); delete_fluid_chorus(mixer->fx.chorus);
mixer->fx.chorus = new_fluid_chorus(samplerate); mixer->fx.chorus = new_fluid_chorus(samplerate);
if (mixer->fx.reverb) if (mixer->fx.reverb)
fluid_revmodel_samplerate_change(mixer->fx.reverb, samplerate); fluid_revmodel_samplerate_change(mixer->fx.reverb, samplerate);
for (i=0; i < mixer->active_voices; i++)
fluid_rvoice_set_output_rate(mixer->rvoices[i], samplerate);
#if LADSPA #if LADSPA
if (mixer->ladspa_fx != NULL) if (mixer->ladspa_fx != NULL)
{ {
@ -612,7 +616,6 @@ void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t* mixer)
{ {
fluid_return_if_fail(mixer != NULL); fluid_return_if_fail(mixer != NULL);
fluid_rvoice_mixer_set_threads(mixer, 0, 0);
#ifdef ENABLE_MIXER_THREADS #ifdef ENABLE_MIXER_THREADS
if (mixer->thread_ready) if (mixer->thread_ready)
delete_fluid_cond(mixer->thread_ready); delete_fluid_cond(mixer->thread_ready);
@ -660,13 +663,18 @@ void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer,
} }
#endif #endif
void fluid_rvoice_mixer_set_reverb_enabled(fluid_rvoice_mixer_t* mixer, int on) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled)
{ {
fluid_rvoice_mixer_t* mixer = obj;
int on = param[0].i;
mixer->fx.with_reverb = on; mixer->fx.with_reverb = on;
} }
void fluid_rvoice_mixer_set_chorus_enabled(fluid_rvoice_mixer_t* mixer, int on) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled)
{ {
fluid_rvoice_mixer_t* mixer = obj;
int on = param[0].i;
mixer->fx.with_chorus = on; mixer->fx.with_chorus = on;
} }
@ -675,32 +683,40 @@ void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t* mixer, int on)
mixer->fx.mix_fx_to_out = on; mixer->fx.mix_fx_to_out = on;
} }
void fluid_rvoice_mixer_set_chorus_params(fluid_rvoice_mixer_t* mixer, int set, DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params)
int nr, fluid_real_t level, fluid_real_t speed,
fluid_real_t depth_ms, int type)
{ {
fluid_rvoice_mixer_t* mixer = obj;
int set = param[0].i;
int nr = param[1].i;
fluid_real_t level = param[2].real;
fluid_real_t speed = param[3].real;
fluid_real_t depth_ms = param[4].real;
int type = param[5].i;
fluid_chorus_set(mixer->fx.chorus, set, nr, level, speed, depth_ms, type); fluid_chorus_set(mixer->fx.chorus, set, nr, level, speed, depth_ms, type);
} }
void fluid_rvoice_mixer_set_reverb_params(fluid_rvoice_mixer_t* mixer, int set,
fluid_real_t roomsize, fluid_real_t damping, DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params)
fluid_real_t width, fluid_real_t level)
{ {
fluid_rvoice_mixer_t* mixer = obj;
int set = param[0].i;
fluid_real_t roomsize = param[1].real;
fluid_real_t damping = param[2].real;
fluid_real_t width = param[3].real;
fluid_real_t level = param[4].real;
fluid_revmodel_set(mixer->fx.reverb, set, roomsize, damping, width, level); fluid_revmodel_set(mixer->fx.reverb, set, roomsize, damping, width, level);
} }
void fluid_rvoice_mixer_reset_fx(fluid_rvoice_mixer_t* mixer) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_reverb)
{
fluid_revmodel_reset(mixer->fx.reverb);
fluid_chorus_reset(mixer->fx.chorus);
}
void fluid_rvoice_mixer_reset_reverb(fluid_rvoice_mixer_t* mixer)
{ {
fluid_rvoice_mixer_t* mixer = obj;
fluid_revmodel_reset(mixer->fx.reverb); fluid_revmodel_reset(mixer->fx.reverb);
} }
void fluid_rvoice_mixer_reset_chorus(fluid_rvoice_mixer_t* mixer) DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus)
{ {
fluid_rvoice_mixer_t* mixer = obj;
fluid_chorus_reset(mixer->fx.chorus); fluid_chorus_reset(mixer->fx.chorus);
} }
@ -913,13 +929,14 @@ fluid_render_loop_multithread(fluid_rvoice_mixer_t* mixer)
* @param thread_count Number of extra mixer threads for multi-core rendering * @param thread_count Number of extra mixer threads for multi-core rendering
* @param prio_level real-time prio level for the extra mixer threads * @param prio_level real-time prio level for the extra mixer threads
*/ */
void DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_threads)
fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_count,
int prio_level)
{ {
#ifdef ENABLE_MIXER_THREADS #ifdef ENABLE_MIXER_THREADS
char name[16]; char name[16];
int i; int i;
fluid_rvoice_mixer_t* mixer = obj;
int thread_count = param[0].i;
int prio_level = param[1].real;
// Kill all existing threads first // Kill all existing threads first
if (mixer->thread_count) { if (mixer->thread_count) {

View file

@ -51,26 +51,23 @@ fluid_rvoice_mixer_t* new_fluid_rvoice_mixer(int buf_count, int fx_buf_count,
void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t*); void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t*);
void fluid_rvoice_mixer_set_samplerate(fluid_rvoice_mixer_t* mixer, fluid_real_t samplerate);
void fluid_rvoice_mixer_set_reverb_enabled(fluid_rvoice_mixer_t* mixer, int on);
void fluid_rvoice_mixer_set_chorus_enabled(fluid_rvoice_mixer_t* mixer, int on);
void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t* mixer, int on);
int fluid_rvoice_mixer_set_polyphony(fluid_rvoice_mixer_t* handler, int value);
int fluid_rvoice_mixer_add_voice(fluid_rvoice_mixer_t* mixer, fluid_rvoice_t* voice);
void fluid_rvoice_mixer_set_chorus_params(fluid_rvoice_mixer_t* mixer, int set,
int nr, fluid_real_t level, fluid_real_t speed,
fluid_real_t depth_ms, int type);
void fluid_rvoice_mixer_set_reverb_params(fluid_rvoice_mixer_t* mixer, int set,
fluid_real_t roomsize, fluid_real_t damping,
fluid_real_t width, fluid_real_t level);
void fluid_rvoice_mixer_reset_fx(fluid_rvoice_mixer_t* mixer);
void fluid_rvoice_mixer_reset_reverb(fluid_rvoice_mixer_t* mixer);
void fluid_rvoice_mixer_reset_chorus(fluid_rvoice_mixer_t* mixer);
void fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_count, DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice);
int prio_level); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony);
#ifdef LADSPA DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_reverb);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus);
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_threads);
void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t* mixer, int on);
#ifdef LADSPA
void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer,
fluid_ladspa_fx_t *ladspa_fx, int audio_groups); fluid_ladspa_fx_t *ladspa_fx, int audio_groups);
#endif #endif

View file

@ -131,6 +131,9 @@ static void fluid_synth_handle_important_channels(void *data, const char *name,
static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t* synth, int chan, int nbr_chan); static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t* synth, int chan, int nbr_chan);
static int fluid_synth_check_next_basic_channel(fluid_synth_t* synth, int basicchan, int mode, int val); static int fluid_synth_check_next_basic_channel(fluid_synth_t* synth, int basicchan, int mode, int val);
static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t* synth, int basicchan, int mode, int val); static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t* synth, int basicchan, int mode, int val);
static int fluid_synth_set_reverb_full_LOCAL(fluid_synth_t* synth, int set, double roomsize,
double damping, double width, double level);
/*************************************************************** /***************************************************************
* *
@ -536,16 +539,23 @@ void delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t* timer
*/ */
static FLUID_INLINE void static FLUID_INLINE void
fluid_synth_update_mixer(fluid_synth_t* synth, void* method, int intparam, fluid_synth_update_mixer(fluid_synth_t* synth, fluid_rvoice_function_t method, int intparam,
fluid_real_t realparam) fluid_real_t realparam)
{ {
fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL); fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL);
fluid_return_if_fail(synth->eventhandler->mixer != NULL); fluid_return_if_fail(synth->eventhandler->mixer != NULL);
fluid_rvoice_eventhandler_push(synth->eventhandler, method, fluid_rvoice_eventhandler_push_int_real(synth->eventhandler, method,
synth->eventhandler->mixer, synth->eventhandler->mixer,
intparam, realparam); intparam, realparam);
} }
static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_synth_t* synth)
{
int i;
fluid_settings_getint(synth->settings, "synth.min-note-length", &i);
return (unsigned int) (i*synth->sample_rate/1000.0f);
}
/** /**
* Create new FluidSynth instance. * Create new FluidSynth instance.
* @param settings Configuration parameters to use (used directly). * @param settings Configuration parameters to use (used directly).
@ -760,7 +770,7 @@ new_fluid_synth(fluid_settings_t *settings)
goto error_recovery; goto error_recovery;
} }
for (i = 0; i < synth->nvoice; i++) { for (i = 0; i < synth->nvoice; i++) {
synth->voice[i] = new_fluid_voice(synth->sample_rate); synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
if (synth->voice[i] == NULL) { if (synth->voice[i] == NULL) {
goto error_recovery; goto error_recovery;
} }
@ -773,7 +783,9 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
synth->midi_channels); synth->midi_channels);
fluid_synth_set_sample_rate(synth, synth->sample_rate); synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
synth->polyphony, 0.0f); synth->polyphony, 0.0f);
fluid_synth_set_reverb_on(synth, synth->with_reverb); fluid_synth_set_reverb_on(synth, synth->with_reverb);
@ -783,18 +795,13 @@ new_fluid_synth(fluid_settings_t *settings)
synth->curmax = 0; synth->curmax = 0;
synth->dither_index = 0; synth->dither_index = 0;
synth->reverb_roomsize = FLUID_REVERB_DEFAULT_ROOMSIZE; fluid_synth_set_reverb_full_LOCAL(synth,
synth->reverb_damping = FLUID_REVERB_DEFAULT_DAMP; FLUID_REVMODEL_SET_ALL,
synth->reverb_width = FLUID_REVERB_DEFAULT_WIDTH; FLUID_REVERB_DEFAULT_ROOMSIZE,
synth->reverb_level = FLUID_REVERB_DEFAULT_LEVEL; FLUID_REVERB_DEFAULT_DAMP,
FLUID_REVERB_DEFAULT_WIDTH,
fluid_rvoice_eventhandler_push5(synth->eventhandler, FLUID_REVERB_DEFAULT_LEVEL);
fluid_rvoice_mixer_set_reverb_params,
synth->eventhandler->mixer,
FLUID_REVMODEL_SET_ALL, synth->reverb_roomsize,
synth->reverb_damping, synth->reverb_width,
synth->reverb_level, 0.0f);
/* Initialize multi-core variables if multiple cores enabled */ /* Initialize multi-core variables if multiple cores enabled */
if (synth->cores > 1) if (synth->cores > 1)
{ {
@ -1940,7 +1947,8 @@ fluid_synth_system_reset_LOCAL(fluid_synth_t* synth)
fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,
synth->midi_channels); synth->midi_channels);
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_fx, 0, 0.0f); fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f);
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f);
return FLUID_OK; return FLUID_OK;
} }
@ -2583,6 +2591,7 @@ fluid_synth_handle_sample_rate(void *data, const char* name, double value)
fluid_synth_set_sample_rate(synth, (float) value); fluid_synth_set_sample_rate(synth, (float) value);
} }
/** /**
* Set sample rate of the synth. * Set sample rate of the synth.
* @note This function is currently experimental and should only be * @note This function is currently experimental and should only be
@ -2600,8 +2609,7 @@ fluid_synth_set_sample_rate(fluid_synth_t* synth, float sample_rate)
fluid_clip (sample_rate, 8000.0f, 96000.0f); fluid_clip (sample_rate, 8000.0f, 96000.0f);
synth->sample_rate = sample_rate; synth->sample_rate = sample_rate;
fluid_settings_getint(synth->settings, "synth.min-note-length", &i); synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth);
synth->min_note_length_ticks = (unsigned int) (i*synth->sample_rate/1000.0f);
for (i=0; i < synth->polyphony; i++) for (i=0; i < synth->polyphony; i++)
fluid_voice_set_output_rate(synth->voice[i], sample_rate); fluid_voice_set_output_rate(synth->voice[i], sample_rate);
@ -2715,7 +2723,7 @@ fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony)
return FLUID_FAILED; return FLUID_FAILED;
synth->voice = new_voices; synth->voice = new_voices;
for (i = synth->nvoice; i < new_polyphony; i++) { for (i = synth->nvoice; i < new_polyphony; i++) {
synth->voice[i] = new_fluid_voice(synth->sample_rate); synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate);
if (synth->voice[i] == NULL) if (synth->voice[i] == NULL)
return FLUID_FAILED; return FLUID_FAILED;
@ -4141,6 +4149,7 @@ fluid_synth_set_reverb_full(fluid_synth_t* synth, int set, double roomsize,
double damping, double width, double level) double damping, double width, double level)
{ {
int ret; int ret;
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
/* if non of the flags is set, fail */ /* if non of the flags is set, fail */
fluid_return_val_if_fail (set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED); fluid_return_val_if_fail (set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED);
@ -4148,7 +4157,17 @@ fluid_synth_set_reverb_full(fluid_synth_t* synth, int set, double roomsize,
/* Synth shadow values are set here so that they will be returned if querried */ /* Synth shadow values are set here so that they will be returned if querried */
fluid_synth_api_enter(synth); fluid_synth_api_enter(synth);
ret = fluid_synth_set_reverb_full_LOCAL(synth, set, roomsize, damping, width, level);
FLUID_API_RETURN(ret);
}
static int
fluid_synth_set_reverb_full_LOCAL(fluid_synth_t* synth, int set, double roomsize,
double damping, double width, double level)
{
int ret;
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
if (set & FLUID_REVMODEL_SET_ROOMSIZE) if (set & FLUID_REVMODEL_SET_ROOMSIZE)
synth->reverb_roomsize = roomsize; synth->reverb_roomsize = roomsize;
@ -4161,13 +4180,17 @@ fluid_synth_set_reverb_full(fluid_synth_t* synth, int set, double roomsize,
if (set & FLUID_REVMODEL_SET_LEVEL) if (set & FLUID_REVMODEL_SET_LEVEL)
synth->reverb_level = level; synth->reverb_level = level;
param[0].i = set;
param[1].real = roomsize;
param[2].real = damping;
param[3].real = width;
param[4].real = level;
/* finally enqueue an rvoice event to the mixer to actual update reverb */ /* finally enqueue an rvoice event to the mixer to actual update reverb */
ret = fluid_rvoice_eventhandler_push5(synth->eventhandler, ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
fluid_rvoice_mixer_set_reverb_params, fluid_rvoice_mixer_set_reverb_params,
synth->eventhandler->mixer, set, synth->eventhandler->mixer,
roomsize, damping, width, level, 0.0f); param);
return ret;
FLUID_API_RETURN(ret);
} }
/** /**
@ -4333,6 +4356,8 @@ fluid_synth_set_chorus_full(fluid_synth_t* synth, int set, int nr, double level,
double speed, double depth_ms, int type) double speed, double depth_ms, int type)
{ {
int ret; int ret;
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
/* if non of the flags is set, fail */ /* if non of the flags is set, fail */
fluid_return_val_if_fail (set & FLUID_CHORUS_SET_ALL, FLUID_FAILED); fluid_return_val_if_fail (set & FLUID_CHORUS_SET_ALL, FLUID_FAILED);
@ -4355,10 +4380,16 @@ fluid_synth_set_chorus_full(fluid_synth_t* synth, int set, int nr, double level,
if (set & FLUID_CHORUS_SET_TYPE) if (set & FLUID_CHORUS_SET_TYPE)
synth->chorus_type = type; synth->chorus_type = type;
ret = fluid_rvoice_eventhandler_push5(synth->eventhandler, param[0].i = set;
fluid_rvoice_mixer_set_chorus_params, param[1].i = nr;
synth->eventhandler->mixer, set, param[2].real = level;
nr, level, speed, depth_ms, type); param[3].real = speed;
param[4].real = depth_ms;
param[5].i = type;
ret = fluid_rvoice_eventhandler_push(synth->eventhandler,
fluid_rvoice_mixer_set_chorus_params,
synth->eventhandler->mixer,
param);
FLUID_API_RETURN(ret); FLUID_API_RETURN(ret);
} }

View file

@ -48,85 +48,110 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice);
#define UPDATE_RVOICE0(proc) \ #define UPDATE_RVOICE0(proc) \
do { \ do { \
if (voice->can_access_rvoice) proc(voice->rvoice); \ fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \
else fluid_rvoice_eventhandler_push(voice->channel->synth->eventhandler, \ fluid_rvoice_eventhandler_push(voice->eventhandler, proc, voice->rvoice, param); \
proc, voice->rvoice, 0, 0.0f); \
} while (0) } while (0)
#define UPDATE_RVOICE_PTR(proc, obj) \
do { \
if (voice->can_access_rvoice) proc(voice->rvoice, obj); \
else fluid_rvoice_eventhandler_push_ptr(voice->channel->synth->eventhandler, \
proc, voice->rvoice, obj); \
} while (0)
#define UPDATE_RVOICE_GENERIC_R1(proc, obj, rarg) \ #define UPDATE_RVOICE_GENERIC_R1(proc, obj, rarg) \
do { \ do { \
if (voice->can_access_rvoice) proc(obj, rarg); \ fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \
else fluid_rvoice_eventhandler_push(voice->channel->synth->eventhandler, \ param[0].real = rarg; \
proc, obj, 0, rarg); \ fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \
} while (0) } while (0)
#define UPDATE_RVOICE_GENERIC_I1(proc, obj, iarg) \ #define UPDATE_RVOICE_GENERIC_I1(proc, obj, iarg) \
do { \ do { \
if (voice->can_access_rvoice) proc(obj, iarg); \ fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \
else fluid_rvoice_eventhandler_push(voice->channel->synth->eventhandler, \ param[0].i = iarg; \
proc, obj, iarg, 0.0f); \ fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \
} while (0)
#define UPDATE_RVOICE_GENERIC_I2(proc, obj, iarg1, iarg2) \
do { \
fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \
param[0].i = iarg1; \
param[1].i = iarg2; \
fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \
} while (0) } while (0)
#define UPDATE_RVOICE_GENERIC_IR(proc, obj, iarg, rarg) \ #define UPDATE_RVOICE_GENERIC_IR(proc, obj, iarg, rarg) \
do { \ do { \
if (voice->can_access_rvoice) proc(obj, iarg, rarg); \ fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \
else fluid_rvoice_eventhandler_push(voice->channel->synth->eventhandler, \ param[0].i = iarg; \
proc, obj, iarg, rarg); \ param[1].real = rarg; \
} while (0) fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \
#define UPDATE_RVOICE_GENERIC_ALL(proc, obj, iarg, r1, r2, r3, r4, r5) \
do { \
if (voice->can_access_rvoice) proc(obj, iarg, r1, r2, r3, r4, r5); \
else fluid_rvoice_eventhandler_push5(voice->channel->synth->eventhandler, \
proc, obj, iarg, r1, r2, r3, r4, r5); \
} while (0) } while (0)
#define UPDATE_RVOICE_R1(proc, arg1) UPDATE_RVOICE_GENERIC_R1(proc, voice->rvoice, arg1) #define UPDATE_RVOICE_R1(proc, arg1) UPDATE_RVOICE_GENERIC_R1(proc, voice->rvoice, arg1)
#define UPDATE_RVOICE_I1(proc, arg1) UPDATE_RVOICE_GENERIC_I1(proc, voice->rvoice, arg1) #define UPDATE_RVOICE_I1(proc, arg1) UPDATE_RVOICE_GENERIC_I1(proc, voice->rvoice, arg1)
#define UPDATE_RVOICE_FILTER1(proc, arg1) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->resonant_filter, arg1)
#define UPDATE_RVOICE_CUSTOM_FILTER1(proc, arg1) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->resonant_custom_filter, arg1)
#define UPDATE_RVOICE_CUSTOM_FILTER_I2(proc, arg1, arg2) UPDATE_RVOICE_GENERIC_IR(proc, &voice->rvoice->resonant_custom_filter, arg1, arg2)
#define UPDATE_RVOICE2(proc, iarg, rarg) UPDATE_RVOICE_GENERIC_IR(proc, voice->rvoice, iarg, rarg) #define UPDATE_RVOICE_BUFFERS_AMP(proc, iarg, rarg) UPDATE_RVOICE_GENERIC_IR(proc, &voice->rvoice->buffers, iarg, rarg)
#define UPDATE_RVOICE_BUFFERS2(proc, iarg, rarg) UPDATE_RVOICE_GENERIC_IR(proc, &voice->rvoice->buffers, iarg, rarg)
#define UPDATE_RVOICE_ENVLFO_R1(proc, envp, rarg) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->envlfo.envp, rarg) #define UPDATE_RVOICE_ENVLFO_R1(proc, envp, rarg) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->envlfo.envp, rarg)
#define UPDATE_RVOICE_ENVLFO_I1(proc, envp, iarg) UPDATE_RVOICE_GENERIC_I1(proc, &voice->rvoice->envlfo.envp, iarg) #define UPDATE_RVOICE_ENVLFO_I1(proc, envp, iarg) UPDATE_RVOICE_GENERIC_I1(proc, &voice->rvoice->envlfo.envp, iarg)
static FLUID_INLINE void static FLUID_INLINE void
fluid_voice_update_volenv(fluid_voice_t* voice, fluid_voice_update_volenv(fluid_voice_t* voice,
fluid_adsr_env_section_t section, int enqueue,
fluid_adsr_env_section_t section,
unsigned int count, unsigned int count,
fluid_real_t coeff, fluid_real_t coeff,
fluid_real_t increment, fluid_real_t increment,
fluid_real_t min, fluid_real_t min,
fluid_real_t max) fluid_real_t max)
{ {
UPDATE_RVOICE_GENERIC_ALL(fluid_adsr_env_set_data, fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
&voice->rvoice->envlfo.volenv, section, count,
coeff, increment, min, max); param[0].i = section;
param[1].i = count;
param[2].real = coeff;
param[3].real = increment;
param[4].real = min;
param[5].real = max;
if(enqueue)
{
fluid_rvoice_eventhandler_push(voice->eventhandler,
fluid_adsr_env_set_data,
&voice->rvoice->envlfo.volenv,
param);
}
else
{
fluid_adsr_env_set_data(&voice->rvoice->envlfo.volenv, param);
}
} }
static FLUID_INLINE void static FLUID_INLINE void
fluid_voice_update_modenv(fluid_voice_t* voice, fluid_voice_update_modenv(fluid_voice_t* voice,
fluid_adsr_env_section_t section, int enqueue,
fluid_adsr_env_section_t section,
unsigned int count, unsigned int count,
fluid_real_t coeff, fluid_real_t coeff,
fluid_real_t increment, fluid_real_t increment,
fluid_real_t min, fluid_real_t min,
fluid_real_t max) fluid_real_t max)
{ {
UPDATE_RVOICE_GENERIC_ALL(fluid_adsr_env_set_data, fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
&voice->rvoice->envlfo.modenv, section, count,
coeff, increment, min, max); param[0].i = section;
param[1].i = count;
param[2].real = coeff;
param[3].real = increment;
param[4].real = min;
param[5].real = max;
if(enqueue)
{
fluid_rvoice_eventhandler_push(voice->eventhandler,
fluid_adsr_env_set_data,
&voice->rvoice->envlfo.modenv,
param);
}
else
{
fluid_adsr_env_set_data(&voice->rvoice->envlfo.modenv, param);
}
} }
static FLUID_INLINE void fluid_voice_sample_unref(fluid_sample_t** sample) static FLUID_INLINE void fluid_voice_sample_unref(fluid_sample_t** sample)
@ -150,8 +175,10 @@ static void fluid_voice_swap_rvoice(fluid_voice_t* voice)
voice->can_access_overflow_rvoice = ctemp; voice->can_access_overflow_rvoice = ctemp;
} }
static void fluid_voice_initialize_rvoice(fluid_voice_t* voice) static void fluid_voice_initialize_rvoice(fluid_voice_t* voice, fluid_real_t output_rate)
{ {
fluid_rvoice_param_t param[MAX_EVENT_PARAMS];
FLUID_MEMSET(voice->rvoice, 0, sizeof(fluid_rvoice_t)); FLUID_MEMSET(voice->rvoice, 0, sizeof(fluid_rvoice_t));
/* The 'sustain' and 'finished' segments of the volume / modulation /* The 'sustain' and 'finished' segments of the volume / modulation
@ -159,24 +186,31 @@ static void fluid_voice_initialize_rvoice(fluid_voice_t* voice)
* or generator. Therefore it is enough to initialize them once * or generator. Therefore it is enough to initialize them once
* during the lifetime of the synth. * during the lifetime of the synth.
*/ */
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVSUSTAIN, fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN,
0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f); 0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVFINISHED, fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVFINISHED,
0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f); 0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVSUSTAIN, fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN,
0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f); 0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVFINISHED, fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVFINISHED,
0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f); 0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f);
fluid_iir_filter_init(&voice->rvoice->resonant_filter, FLUID_IIR_LOWPASS, 0); param[0].i = FLUID_IIR_LOWPASS;
fluid_iir_filter_init(&voice->rvoice->resonant_custom_filter, FLUID_IIR_DISABLED, 0); param[1].i = 0;
fluid_iir_filter_init(&voice->rvoice->resonant_filter, param);
param[0].i = FLUID_IIR_DISABLED;
fluid_iir_filter_init(&voice->rvoice->resonant_custom_filter, param);
param[0].real = output_rate;
fluid_rvoice_set_output_rate(voice->rvoice, param);
} }
/* /*
* new_fluid_voice * new_fluid_voice
*/ */
fluid_voice_t* fluid_voice_t*
new_fluid_voice(fluid_real_t output_rate) new_fluid_voice(fluid_rvoice_eventhandler_t* handler, fluid_real_t output_rate)
{ {
fluid_voice_t* voice; fluid_voice_t* voice;
voice = FLUID_NEW(fluid_voice_t); voice = FLUID_NEW(fluid_voice_t);
@ -184,12 +218,15 @@ new_fluid_voice(fluid_real_t output_rate)
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL; return NULL;
} }
voice->can_access_rvoice = TRUE;
voice->can_access_overflow_rvoice = TRUE;
voice->rvoice = FLUID_NEW(fluid_rvoice_t); voice->rvoice = FLUID_NEW(fluid_rvoice_t);
voice->overflow_rvoice = FLUID_NEW(fluid_rvoice_t); voice->overflow_rvoice = FLUID_NEW(fluid_rvoice_t);
if (voice->rvoice == NULL || voice->overflow_rvoice == NULL) { if (voice->rvoice == NULL || voice->overflow_rvoice == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_LOG(FLUID_ERR, "Out of memory");
FLUID_FREE(voice->rvoice); delete_fluid_voice(voice);
FLUID_FREE(voice);
return NULL; return NULL;
} }
@ -197,17 +234,15 @@ new_fluid_voice(fluid_real_t output_rate)
voice->chan = NO_CHANNEL; voice->chan = NO_CHANNEL;
voice->key = 0; voice->key = 0;
voice->vel = 0; voice->vel = 0;
voice->eventhandler = handler;
voice->channel = NULL; voice->channel = NULL;
voice->sample = NULL; voice->sample = NULL;
voice->output_rate = output_rate;
/* Initialize both the rvoice and overflow_rvoice */ /* Initialize both the rvoice and overflow_rvoice */
voice->can_access_rvoice = TRUE; fluid_voice_initialize_rvoice(voice, output_rate);
voice->can_access_overflow_rvoice = TRUE;
fluid_voice_initialize_rvoice(voice);
fluid_voice_swap_rvoice(voice); fluid_voice_swap_rvoice(voice);
fluid_voice_initialize_rvoice(voice); fluid_voice_initialize_rvoice(voice, output_rate);
fluid_voice_set_output_rate(voice, output_rate);
return voice; return voice;
} }
@ -276,7 +311,7 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
unloading of the soundfont while this voice is playing, unloading of the soundfont while this voice is playing,
once for us and once for the rvoice. */ once for us and once for the rvoice. */
fluid_sample_incr_ref(sample); fluid_sample_incr_ref(sample);
UPDATE_RVOICE_PTR(fluid_rvoice_set_sample, sample); fluid_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample);
fluid_sample_incr_ref(sample); fluid_sample_incr_ref(sample);
voice->sample = sample; voice->sample = sample;
@ -301,11 +336,12 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
/* Set up buffer mapping, should be done more flexible in the future. */ /* Set up buffer mapping, should be done more flexible in the future. */
i = channel->synth->audio_groups; i = channel->synth->audio_groups;
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_mapping, 2, i*2 + SYNTH_REVERB_CHANNEL); UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 2, i*2 + SYNTH_REVERB_CHANNEL);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_mapping, 3, i*2 + SYNTH_CHORUS_CHANNEL); UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 3, i*2 + SYNTH_CHORUS_CHANNEL);
i = 2 * (voice->chan % i); i = 2 * (voice->chan % i);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_mapping, 0, i); UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 0, i);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_mapping, 1, i+1); UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 1, i+1);
return FLUID_OK; return FLUID_OK;
} }
@ -315,20 +351,15 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
* Update sample rate. * Update sample rate.
* @note If the voice is active, it will be turned off. * @note If the voice is active, it will be turned off.
*/ */
int void
fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value) fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value)
{ {
if (fluid_voice_is_playing(voice)) if (fluid_voice_is_playing(voice))
fluid_voice_off(voice); fluid_voice_off(voice);
voice->output_rate = value; voice->output_rate = value;
UPDATE_RVOICE_R1(fluid_rvoice_set_output_rate, value); UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->rvoice, value);
/* Update the other rvoice as well */ UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->overflow_rvoice, value);
fluid_voice_swap_rvoice(voice);
UPDATE_RVOICE_R1(fluid_rvoice_set_output_rate, value);
fluid_voice_swap_rvoice(voice);
return FLUID_FAILED;
} }
@ -692,12 +723,12 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE); voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE);
/* left amp */ /* left amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0,
fluid_voice_calculate_gain_amplitude(voice, fluid_voice_calculate_gain_amplitude(voice,
fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1))); fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)));
/* right amp */ /* right amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1,
fluid_voice_calculate_gain_amplitude(voice, fluid_voice_calculate_gain_amplitude(voice,
fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0))); fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)));
break; break;
@ -729,14 +760,14 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
/* The generator unit is 'tenths of a percent'. */ /* The generator unit is 'tenths of a percent'. */
voice->reverb_send = x / 1000.0f; voice->reverb_send = x / 1000.0f;
fluid_clip(voice->reverb_send, 0.0, 1.0); fluid_clip(voice->reverb_send, 0.0, 1.0);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send)); UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send));
break; break;
case GEN_CHORUSSEND: case GEN_CHORUSSEND:
/* The generator unit is 'tenths of a percent'. */ /* The generator unit is 'tenths of a percent'. */
voice->chorus_send = x / 1000.0f; voice->chorus_send = x / 1000.0f;
fluid_clip(voice->chorus_send, 0.0, 1.0); fluid_clip(voice->chorus_send, 0.0, 1.0);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send)); UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send));
break; break;
case GEN_OVERRIDEROOTKEY: case GEN_OVERRIDEROOTKEY:
@ -772,20 +803,20 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
* modulation. The allowed range is tested in the 'fluid_ct2hz' * modulation. The allowed range is tested in the 'fluid_ct2hz'
* function [PH,20021214] * function [PH,20021214]
*/ */
UPDATE_RVOICE_FILTER1(fluid_iir_filter_set_fres, x); UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_filter, x);
break; break;
case GEN_FILTERQ: case GEN_FILTERQ:
UPDATE_RVOICE_FILTER1(fluid_iir_filter_set_q, x); UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_filter, x);
break; break;
/* same as the two above, only for the custom filter */ /* same as the two above, only for the custom filter */
case GEN_CUSTOM_FILTERFC: case GEN_CUSTOM_FILTERFC:
UPDATE_RVOICE_CUSTOM_FILTER1(fluid_iir_filter_set_fres, x); UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_custom_filter, x);
break; break;
case GEN_CUSTOM_FILTERQ: case GEN_CUSTOM_FILTERQ:
UPDATE_RVOICE_CUSTOM_FILTER1(fluid_iir_filter_set_q, x); UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_custom_filter, x);
break; break;
case GEN_MODLFOTOPITCH: case GEN_MODLFOTOPITCH:
@ -968,21 +999,21 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */ case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */
fluid_clip(x, -12000.0f, 5000.0f); fluid_clip(x, -12000.0f, 5000.0f);
count = NUM_BUFFERS_DELAY(x); count = NUM_BUFFERS_DELAY(x);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVDELAY, fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDELAY,
count, 0.0f, 0.0f, -1.0f, 1.0f); count, 0.0f, 0.0f, -1.0f, 1.0f);
break; break;
case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */ case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */
fluid_clip(x, -12000.0f, 8000.0f); fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_BUFFERS_ATTACK(x); count = 1 + NUM_BUFFERS_ATTACK(x);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVATTACK, fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVATTACK,
count, 1.0f, 1.0f / count, -1.0f, 1.0f); count, 1.0f, 1.0f / count, -1.0f, 1.0f);
break; break;
case GEN_VOLENVHOLD: /* SF2.01 section 8.1.3 # 35 */ case GEN_VOLENVHOLD: /* SF2.01 section 8.1.3 # 35 */
case GEN_KEYTOVOLENVHOLD: /* SF2.01 section 8.1.3 # 39 */ case GEN_KEYTOVOLENVHOLD: /* SF2.01 section 8.1.3 # 39 */
count = calculate_hold_decay_buffers(voice, GEN_VOLENVHOLD, GEN_KEYTOVOLENVHOLD, 0); /* 0 means: hold */ count = calculate_hold_decay_buffers(voice, GEN_VOLENVHOLD, GEN_KEYTOVOLENVHOLD, 0); /* 0 means: hold */
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVHOLD, fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVHOLD,
count, 1.0f, 0.0f, -1.0f, 2.0f); count, 1.0f, 0.0f, -1.0f, 2.0f);
break; break;
@ -992,35 +1023,35 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_VOLENVSUSTAIN); x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_VOLENVSUSTAIN);
fluid_clip(x , 0.0f, 1.0f); fluid_clip(x , 0.0f, 1.0f);
count = calculate_hold_decay_buffers(voice, GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */ count = calculate_hold_decay_buffers(voice, GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVDECAY, fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDECAY,
count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f); count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f);
break; break;
case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */ case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */
fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f); fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f);
count = 1 + NUM_BUFFERS_RELEASE(x); count = 1 + NUM_BUFFERS_RELEASE(x);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVRELEASE, fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVRELEASE,
count, 1.0f, -1.0f / count, 0.0f, 1.0f); count, 1.0f, -1.0f / count, 0.0f, 1.0f);
break; break;
/* Modulation envelope */ /* Modulation envelope */
case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */ case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */
fluid_clip(x, -12000.0f, 5000.0f); fluid_clip(x, -12000.0f, 5000.0f);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVDELAY, fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDELAY,
NUM_BUFFERS_DELAY(x), 0.0f, 0.0f, -1.0f, 1.0f); NUM_BUFFERS_DELAY(x), 0.0f, 0.0f, -1.0f, 1.0f);
break; break;
case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */ case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */
fluid_clip(x, -12000.0f, 8000.0f); fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_BUFFERS_ATTACK(x); count = 1 + NUM_BUFFERS_ATTACK(x);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVATTACK, fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVATTACK,
count, 1.0f, 1.0f / count, -1.0f, 1.0f); count, 1.0f, 1.0f / count, -1.0f, 1.0f);
break; break;
case GEN_MODENVHOLD: /* SF2.01 section 8.1.3 # 27 */ case GEN_MODENVHOLD: /* SF2.01 section 8.1.3 # 27 */
case GEN_KEYTOMODENVHOLD: /* SF2.01 section 8.1.3 # 31 */ case GEN_KEYTOMODENVHOLD: /* SF2.01 section 8.1.3 # 31 */
count = calculate_hold_decay_buffers(voice, GEN_MODENVHOLD, GEN_KEYTOMODENVHOLD, 0); /* 1 means: hold */ count = calculate_hold_decay_buffers(voice, GEN_MODENVHOLD, GEN_KEYTOMODENVHOLD, 0); /* 1 means: hold */
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVHOLD, fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVHOLD,
count, 1.0f, 0.0f, -1.0f, 2.0f); count, 1.0f, 0.0f, -1.0f, 2.0f);
break; break;
@ -1030,14 +1061,14 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
count = calculate_hold_decay_buffers(voice, GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */ count = calculate_hold_decay_buffers(voice, GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */
x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_MODENVSUSTAIN); x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_MODENVSUSTAIN);
fluid_clip(x, 0.0f, 1.0f); fluid_clip(x, 0.0f, 1.0f);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVDECAY, fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDECAY,
count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f); count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f);
break; break;
case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */ case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */
fluid_clip(x, -12000.0f, 8000.0f); fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_BUFFERS_RELEASE(x); count = 1 + NUM_BUFFERS_RELEASE(x);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVRELEASE, fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVRELEASE,
count, 1.0f, -1.0f / count, 0.0f, 2.0f); count, 1.0f, -1.0f / count, 0.0f, 2.0f);
break; break;
@ -1180,8 +1211,8 @@ void fluid_voice_update_portamento (fluid_voice_t* voice, int fromkey,int tokey)
(fluid_real_t)fluid_channel_portamentotime(channel)) / (fluid_real_t)fluid_channel_portamentotime(channel)) /
(fluid_real_t)FLUID_BUFSIZE +0.5); (fluid_real_t)FLUID_BUFSIZE +0.5);
/* Sends portamento parameters to the voice dsp */ /* Send portamento parameters to the voice dsp */
UPDATE_RVOICE2(fluid_rvoice_set_portamento, countinc, pitchoffset); UPDATE_RVOICE_GENERIC_IR(fluid_rvoice_set_portamento, voice->rvoice, countinc, pitchoffset);
} }
/*---------------------------------------------------------------*/ /*---------------------------------------------------------------*/
@ -1663,10 +1694,10 @@ int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain)
chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send); chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send);
UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain); UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, left); UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, left);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, right); UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, right);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 2, reverb); UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, reverb);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 3, chorus); UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, chorus);
return FLUID_OK; return FLUID_OK;
} }
@ -1812,6 +1843,6 @@ fluid_voice_get_overflow_prio(fluid_voice_t* voice,
void fluid_voice_set_custom_filter(fluid_voice_t* voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags) void fluid_voice_set_custom_filter(fluid_voice_t* voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags)
{ {
UPDATE_RVOICE_CUSTOM_FILTER_I2(fluid_iir_filter_init, type, flags); UPDATE_RVOICE_GENERIC_I2(fluid_iir_filter_init, &voice->rvoice->resonant_custom_filter, type, flags);
} }

View file

@ -29,6 +29,7 @@
#include "fluid_adsr_env.h" #include "fluid_adsr_env.h"
#include "fluid_lfo.h" #include "fluid_lfo.h"
#include "fluid_rvoice.h" #include "fluid_rvoice.h"
#include "fluid_rvoice_event.h"
#include "fluid_sys.h" #include "fluid_sys.h"
#define NO_CHANNEL 0xff #define NO_CHANNEL 0xff
@ -69,6 +70,7 @@ struct _fluid_voice_t
unsigned char key; /* the key of the noteon event, quick access for noteoff */ unsigned char key; /* the key of the noteon event, quick access for noteoff */
unsigned char vel; /* the velocity of the noteon event */ unsigned char vel; /* the velocity of the noteon event */
fluid_channel_t* channel; fluid_channel_t* channel;
fluid_rvoice_eventhandler_t* eventhandler;
fluid_gen_t gen[GEN_LAST]; fluid_gen_t gen[GEN_LAST];
fluid_mod_t mod[FLUID_NUM_MOD]; fluid_mod_t mod[FLUID_NUM_MOD];
int mod_count; int mod_count;
@ -114,7 +116,7 @@ struct _fluid_voice_t
}; };
fluid_voice_t* new_fluid_voice(fluid_real_t output_rate); fluid_voice_t* new_fluid_voice(fluid_rvoice_eventhandler_t* handler, fluid_real_t output_rate);
void delete_fluid_voice(fluid_voice_t* voice); void delete_fluid_voice(fluid_voice_t* voice);
void fluid_voice_start(fluid_voice_t* voice); void fluid_voice_start(fluid_voice_t* voice);
@ -135,7 +137,7 @@ int fluid_voice_set_param(fluid_voice_t* voice, int gen, fluid_real_t value, int
/** Set the gain. */ /** Set the gain. */
int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain); int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain);
int fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value); void fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value);
/** Update all the synthesis parameters, which depend on generator /** Update all the synthesis parameters, which depend on generator

View file

@ -205,6 +205,23 @@ typedef struct _fluid_server_socket_t fluid_server_socket_t;
typedef struct _fluid_sample_timer_t fluid_sample_timer_t; typedef struct _fluid_sample_timer_t fluid_sample_timer_t;
typedef struct _fluid_zone_range_t fluid_zone_range_t; typedef struct _fluid_zone_range_t fluid_zone_range_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 */
typedef union _fluid_rvoice_param_t
{
void* ptr;
int i;
fluid_real_t real;
} fluid_rvoice_param_t;
enum { MAX_EVENT_PARAMS = 6 }; /**< Maximum number of #fluid_rvoice_param_t to be passed to an #fluid_rvoice_function_t */
typedef void (*fluid_rvoice_function_t)(void* obj, const fluid_rvoice_param_t param[MAX_EVENT_PARAMS]);
/* Macro for declaring an rvoice event function (#fluid_rvoice_function_t). The functions may only access
* those params that were previously set in fluid_voice.c
*/
#define DECLARE_FLUID_RVOICE_FUNCTION(name) void name(void* obj, const fluid_rvoice_param_t param[MAX_EVENT_PARAMS])
/*************************************************************** /***************************************************************
* *
* CONSTANTS * CONSTANTS