X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Ffluidsynth%2Fsrc%2Ffluid_rvoice.h;h=bae3ac9390c797dd926296e68ab8edd23313fb1b;hb=abf7905d5f82ad796544aa664cf3abaf20385cf7;hp=4566cb1de334e9f4a5a6a7100a5c19c0e85ab8c7;hpb=5b280463ce220ca27c067ce33cd9af2f457f240b;p=ardour.git diff --git a/libs/fluidsynth/src/fluid_rvoice.h b/libs/fluidsynth/src/fluid_rvoice.h index 4566cb1de3..bae3ac9390 100644 --- a/libs/fluidsynth/src/fluid_rvoice.h +++ b/libs/fluidsynth/src/fluid_rvoice.h @@ -3,16 +3,16 @@ * 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 + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA @@ -36,165 +36,190 @@ typedef struct _fluid_rvoice_t fluid_rvoice_t; /* Smallest amplitude that can be perceived (full scale is +/- 0.5) * 16 bits => 96+4=100 dB dynamic range => 0.00001 - * 0.00001 * 2 is approximately 0.00003 :) + * 24 bits => 144-4 = 140 dB dynamic range => 1.e-7 + * 1.e-7 * 2 == 2.e-7 :) */ -#define FLUID_NOISE_FLOOR 0.00003 +#define FLUID_NOISE_FLOOR 2.e-7 - -enum fluid_loop { - FLUID_UNLOOPED = 0, - FLUID_LOOP_DURING_RELEASE = 1, - FLUID_NOTUSED = 2, - FLUID_LOOP_UNTIL_RELEASE = 3 +enum fluid_loop +{ + FLUID_UNLOOPED = 0, + FLUID_LOOP_DURING_RELEASE = 1, + FLUID_NOTUSED = 2, + FLUID_LOOP_UNTIL_RELEASE = 3 }; -/** +/* * rvoice ticks-based parameters * These parameters must be updated even if the voice is currently quiet. */ struct _fluid_rvoice_envlfo_t { - /* Note-off minimum length */ - unsigned int ticks; - unsigned int noteoff_ticks; - - /* vol env */ - fluid_adsr_env_t volenv; - - /* mod env */ - fluid_adsr_env_t modenv; - fluid_real_t modenv_to_fc; - fluid_real_t modenv_to_pitch; - - /* mod lfo */ - 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_lfo_t viblfo; - fluid_real_t viblfo_to_pitch; + /* Note-off minimum length */ + unsigned int ticks; + unsigned int noteoff_ticks; + + /* vol env */ + fluid_adsr_env_t volenv; + + /* mod env */ + fluid_adsr_env_t modenv; + fluid_real_t modenv_to_fc; + fluid_real_t modenv_to_pitch; + + /* mod lfo */ + 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_lfo_t viblfo; + fluid_real_t viblfo_to_pitch; }; -/** +/* * rvoice parameters needed for dsp interpolation */ struct _fluid_rvoice_dsp_t { - /* interpolation method, as in fluid_interp in fluidsynth.h */ - int interp_method; - 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 phase calculations */ - - fluid_real_t pitch; /* the pitch in midicents */ - fluid_real_t root_pitch_hz; - fluid_real_t output_rate; - - /* 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 min_attenuation_cB; /* Estimate on the smallest possible attenuation - * during the lifetime of the voice */ - fluid_real_t amplitude_that_reaches_noise_floor_nonloop; - fluid_real_t amplitude_that_reaches_noise_floor_loop; - fluid_real_t synth_gain; /* master gain */ + /* interpolation method, as in fluid_interp in fluidsynth.h */ + 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; - /* Dynamic input to the interpolator below */ + fluid_sample_t *sample; - fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */ + /* 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) */ - fluid_real_t amp; /* current linear amplitude */ - fluid_real_t amp_incr; /* amplitude increment value for the next FLUID_BUFSIZE samples */ + /* Stuff needed for portamento calculations */ + fluid_real_t pitchoffset; /* the portamento range in midicents */ + fluid_real_t pitchinc; /* the portamento increment in midicents */ - 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; + /* Stuff needed for phase calculations */ + fluid_real_t pitch; /* the pitch in midicents */ + fluid_real_t root_pitch_hz; + fluid_real_t output_rate; + + /* Stuff needed for amplitude calculations */ + + 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() */ + fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation + * during the lifetime of the voice */ + fluid_real_t amplitude_that_reaches_noise_floor_nonloop; + 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 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 */ }; /* Currently left, right, reverb, chorus. To be changed if we ever add surround positioning, or stereo reverb/chorus */ #define FLUID_RVOICE_MAX_BUFS (4) -/** +/* * rvoice mixer-related parameters */ struct _fluid_rvoice_buffers_t { - unsigned int count; /* Number of records in "bufs" */ - struct { - fluid_real_t amp; - int mapping; /* Mapping to mixdown buffer index */ - } bufs[FLUID_RVOICE_MAX_BUFS]; + unsigned int count; /* Number of records in "bufs" */ + struct + { + fluid_real_t amp; + int mapping; /* Mapping to mixdown buffer index */ + } bufs[FLUID_RVOICE_MAX_BUFS]; }; -/** - * Parameters needed to synthesize a voice +/* + * Hard real-time parameters needed to synthesize a voice */ struct _fluid_rvoice_t { - fluid_rvoice_envlfo_t envlfo; - fluid_rvoice_dsp_t dsp; - fluid_iir_filter_t resonant_filter; /* IIR resonant dsp filter */ - fluid_rvoice_buffers_t buffers; + fluid_rvoice_envlfo_t envlfo; + fluid_rvoice_dsp_t dsp; + fluid_iir_filter_t resonant_filter; /* IIR resonant dsp filter */ + fluid_iir_filter_t resonant_custom_filter; /* optional custom/general-purpose IIR resonant filter */ + fluid_rvoice_buffers_t buffers; }; -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); -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 */ - -void fluid_rvoice_noteoff(fluid_rvoice_t* voice, unsigned int min_ticks); -void fluid_rvoice_voiceoff(fluid_rvoice_t* voice); -void fluid_rvoice_reset(fluid_rvoice_t* voice); -void fluid_rvoice_set_output_rate(fluid_rvoice_t* voice, fluid_real_t output_rate); -void fluid_rvoice_set_interp_method(fluid_rvoice_t* voice, int interp_method); -void fluid_rvoice_set_root_pitch_hz(fluid_rvoice_t* voice, fluid_real_t root_pitch_hz); -void fluid_rvoice_set_pitch(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_synth_gain(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_attenuation(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_min_attenuation_cB(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_viblfo_to_pitch(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_modlfo_to_pitch(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_modlfo_to_vol(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_modlfo_to_fc(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_modenv_to_fc(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_modenv_to_pitch(fluid_rvoice_t* voice, fluid_real_t value); -void fluid_rvoice_set_start(fluid_rvoice_t* voice, int value); -void fluid_rvoice_set_end(fluid_rvoice_t* voice, int value); -void fluid_rvoice_set_loopstart(fluid_rvoice_t* voice, int value); -void fluid_rvoice_set_loopend(fluid_rvoice_t* voice, int value); -void fluid_rvoice_set_sample(fluid_rvoice_t* voice, fluid_sample_t* value); -void fluid_rvoice_set_samplemode(fluid_rvoice_t* voice, enum fluid_loop value); +int fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf); + +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping); + +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_noteoff); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_voiceoff); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_reset); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_portamento); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_output_rate); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_interp_method); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_root_pitch_hz); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_pitch); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_attenuation); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_min_attenuation_cB); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_viblfo_to_pitch); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_pitch); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_vol); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_fc); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_fc); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_pitch); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_synth_gain); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_start); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_end); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopstart); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopend); +DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode); +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, 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); -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); + +/* + * Combines the most significant 16 bit part of a sample with a potentially present + * least sig. 8 bit part in order to create a 24 bit sample. + */ +static FLUID_INLINE int32_t +fluid_rvoice_get_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx) +{ + /* cast sample to unsigned type, so we can safely shift and bitwise or + * without relying on undefined behaviour (should never happen anyway ofc...) */ + uint32_t msb = (uint32_t)dsp_msb[idx]; + uint8_t lsb = 0U; + + /* most soundfonts have 16 bit samples, assume that it's unlikely we + * experience 24 bit samples here */ + if(FLUID_UNLIKELY(dsp_lsb != NULL)) + { + lsb = (uint8_t)dsp_lsb[idx]; + } + + return (int32_t)((msb << 8) | lsb); +} #endif