diff --git a/fluidsynth/src/Makefile.am b/fluidsynth/src/Makefile.am index 3c71b28e..72b2d68c 100644 --- a/fluidsynth/src/Makefile.am +++ b/fluidsynth/src/Makefile.am @@ -129,6 +129,7 @@ libfluidsynth_la_SOURCES = \ fluid_iir_filter.c \ fluid_iir_filter.h \ fluid_adsr_env.h \ + fluid_lfo.h \ fluid_filerenderer.c \ fluid_aufile.c diff --git a/fluidsynth/src/fluid_lfo.h b/fluidsynth/src/fluid_lfo.h new file mode 100644 index 00000000..a3368b47 --- /dev/null +++ b/fluidsynth/src/fluid_lfo.h @@ -0,0 +1,80 @@ +/* FluidSynth - A Software Synthesizer + * + * Copyright (C) 2003 Peter Hanappe and others. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#ifndef _FLUID_LFO_H +#define _FLUID_LFO_H + +#include "fluidsynth_priv.h" + +typedef struct _fluid_lfo_t fluid_lfo_t; + +struct _fluid_lfo_t { + fluid_real_t val; /* the current value of the LFO */ + unsigned int delay; /* the delay of the lfo in samples */ + fluid_real_t incr; /* the lfo frequency is converted to a per-buffer increment */ +}; + +static inline void +fluid_lfo_reset(fluid_lfo_t* lfo) +{ + lfo->val = 0.0f; +} + +static inline void +fluid_lfo_set_incr(fluid_lfo_t* lfo, fluid_real_t incr) +{ + lfo->incr = incr; +} + +static inline void +fluid_lfo_set_delay(fluid_lfo_t* lfo, unsigned int delay) +{ + lfo->delay = delay; +} + +static inline fluid_real_t +fluid_lfo_get_val(fluid_lfo_t* lfo) +{ + return lfo->val; +} + +static inline void +fluid_lfo_calc(fluid_lfo_t* lfo, unsigned int cur_delay) +{ + if (cur_delay < lfo->delay) + return; + + lfo->val += lfo->incr; + + if (lfo->val > (fluid_real_t) 1.0) + { + lfo->incr = -lfo->incr; + lfo->val = (fluid_real_t) 2.0 - lfo->val; + } + else if (lfo->val < (fluid_real_t) -1.0) + { + lfo->incr = -lfo->incr; + lfo->val = (fluid_real_t) -2.0 - lfo->val; + } + +} + +#endif + diff --git a/fluidsynth/src/fluid_voice.c b/fluidsynth/src/fluid_voice.c index 7bc7bd85..3a2cfce8 100644 --- a/fluidsynth/src/fluid_voice.c +++ b/fluidsynth/src/fluid_voice.c @@ -140,14 +140,14 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, /* mod env initialization*/ fluid_adsr_env_reset(&voice->modenv); - /* mod lfo */ - voice->modlfo_val = 0.0;/* Fixme: Retrieve from any other existing - voice on this channel to keep LFOs in - unison? */ - - /* vib lfo */ - voice->viblfo_val = 0.0f; /* Fixme: See mod lfo */ + /* lfo init */ + /* Fixme: Retrieve from any other existing + voice on this channel to keep LFOs in + unison? */ + fluid_lfo_reset(&voice->modlfo); + fluid_lfo_reset(&voice->viblfo); + /* Clear sample history in filter */ fluid_iir_filter_reset(&voice->resonant_filter); @@ -289,45 +289,12 @@ fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf) fluid_adsr_env_calc(&voice->modenv, 0); fluid_check_fpe ("voice_write mod env"); - /******************* mod lfo **********************/ + /******************* lfo **********************/ - if (voice->ticks >= voice->modlfo_delay) - { - voice->modlfo_val += voice->modlfo_incr; - - if (voice->modlfo_val > 1.0) - { - voice->modlfo_incr = -voice->modlfo_incr; - voice->modlfo_val = (fluid_real_t) 2.0 - voice->modlfo_val; - } - else if (voice->modlfo_val < -1.0) - { - voice->modlfo_incr = -voice->modlfo_incr; - voice->modlfo_val = (fluid_real_t) -2.0 - voice->modlfo_val; - } - } - + fluid_lfo_calc(&voice->modlfo, voice->ticks); fluid_check_fpe ("voice_write mod LFO"); - - /******************* vib lfo **********************/ - - if (voice->ticks >= voice->viblfo_delay) - { - voice->viblfo_val += voice->viblfo_incr; - - if (voice->viblfo_val > (fluid_real_t) 1.0) - { - voice->viblfo_incr = -voice->viblfo_incr; - voice->viblfo_val = (fluid_real_t) 2.0 - voice->viblfo_val; - } - else if (voice->viblfo_val < -1.0) - { - voice->viblfo_incr = -voice->viblfo_incr; - voice->viblfo_val = (fluid_real_t) -2.0 - voice->viblfo_val; - } - } - - fluid_check_fpe ("voice_write Vib LFO"); + fluid_lfo_calc(&voice->viblfo, voice->ticks); + fluid_check_fpe ("voice_write vib LFO"); /******************* amplitude **********************/ @@ -345,7 +312,7 @@ fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf) * A positive modlfo_to_vol should increase volume (negative attenuation). */ target_amp = fluid_atten2amp (voice->attenuation) - * fluid_cb2amp (voice->modlfo_val * -voice->modlfo_to_vol) + * fluid_cb2amp (fluid_lfo_get_val(&voice->modlfo) * -voice->modlfo_to_vol) * fluid_adsr_env_get_val(&voice->volenv); } else @@ -355,7 +322,7 @@ fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf) target_amp = fluid_atten2amp (voice->attenuation) * fluid_cb2amp (960.0f * (1.0f - fluid_adsr_env_get_val(&voice->volenv)) - + voice->modlfo_val * -voice->modlfo_to_vol); + + fluid_lfo_get_val(&voice->modlfo) * -voice->modlfo_to_vol); /* We turn off a voice, if the volume has dropped low enough. */ @@ -408,8 +375,8 @@ fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf) * buffer. It is the ratio between the frequencies of original * waveform and output waveform.*/ voice->phase_incr = fluid_ct2hz_real - (voice->pitch + voice->modlfo_val * voice->modlfo_to_pitch - + voice->viblfo_val * voice->viblfo_to_pitch + (voice->pitch + fluid_lfo_get_val(&voice->modlfo) * voice->modlfo_to_pitch + + fluid_lfo_get_val(&voice->viblfo) * voice->viblfo_to_pitch + fluid_adsr_env_get_val(&voice->modenv) * voice->modenv_to_pitch) / voice->root_pitch_hz; fluid_check_fpe ("voice_write phase calculation"); @@ -419,7 +386,7 @@ fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf) /*************** resonant filter ******************/ fluid_iir_filter_calc(&voice->resonant_filter, voice->output_rate, - voice->modlfo_val * voice->modlfo_to_fc + + fluid_lfo_get_val(&voice->modlfo) * voice->modlfo_to_fc + fluid_adsr_env_get_val(&voice->modenv) * voice->modenv_to_fc); /*********************** run the dsp chain ************************ @@ -920,7 +887,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) case GEN_MODLFODELAY: x = _GEN(voice, GEN_MODLFODELAY); fluid_clip(x, -12000.0f, 5000.0f); - voice->modlfo_delay = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x)); + fluid_lfo_set_delay(&voice->modlfo, (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x))); break; case GEN_MODLFOFREQ: @@ -929,7 +896,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) */ x = _GEN(voice, GEN_MODLFOFREQ); fluid_clip(x, -16000.0f, 4500.0f); - voice->modlfo_incr = (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate); + fluid_lfo_set_incr(&voice->modlfo, (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate)); break; case GEN_VIBLFOFREQ: @@ -940,13 +907,13 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) */ x = _GEN(voice, GEN_VIBLFOFREQ); fluid_clip(x, -16000.0f, 4500.0f); - voice->viblfo_incr = (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate); + fluid_lfo_set_incr(&voice->viblfo, (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate)); break; case GEN_VIBLFODELAY: x = _GEN(voice,GEN_VIBLFODELAY); fluid_clip(x, -12000.0f, 5000.0f); - voice->viblfo_delay = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x)); + fluid_lfo_set_delay(&voice->viblfo, (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x))); break; case GEN_VIBLFOTOPITCH: @@ -1283,7 +1250,7 @@ fluid_voice_noteoff(fluid_voice_t* voice) * for seamless volume transition. */ if (fluid_adsr_env_get_val(&voice->volenv) > 0){ - fluid_real_t lfo = voice->modlfo_val * -voice->modlfo_to_vol; + fluid_real_t lfo = fluid_lfo_get_val(&voice->modlfo) * -voice->modlfo_to_vol; fluid_real_t amp = fluid_adsr_env_get_val(&voice->volenv) * pow (10.0, lfo / -200); fluid_real_t env_value = - ((-200 * log (amp) / log (10.0) - lfo) / 960.0 - 1); fluid_clip (env_value, 0.0, 1.0); @@ -1767,5 +1734,3 @@ fluid_voice_optimize_sample(fluid_sample_t* s) return FLUID_OK; } - - diff --git a/fluidsynth/src/fluid_voice.h b/fluidsynth/src/fluid_voice.h index 06d4c258..ba2757ac 100644 --- a/fluidsynth/src/fluid_voice.h +++ b/fluidsynth/src/fluid_voice.h @@ -27,6 +27,7 @@ #include "fluid_mod.h" #include "fluid_iir_filter.h" #include "fluid_adsr_env.h" +#include "fluid_lfo.h" #define NO_CHANNEL 0xff @@ -128,17 +129,13 @@ struct _fluid_voice_t fluid_real_t modenv_to_pitch; /* mod lfo */ - fluid_real_t modlfo_val; /* the value of the modulation LFO */ - unsigned int modlfo_delay; /* the delay of the lfo in samples */ - fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */ + fluid_lfo_t modlfo; fluid_real_t modlfo_to_fc; fluid_real_t modlfo_to_pitch; fluid_real_t modlfo_to_vol; /* vib lfo */ - fluid_real_t viblfo_val; /* the value of the vibrato LFO */ - unsigned int viblfo_delay; /* the delay of the lfo in samples */ - fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */ + fluid_lfo_t viblfo; fluid_real_t viblfo_to_pitch; fluid_iir_filter_t resonant_filter; /* IIR resonance dsp filter */