2003-03-11 16:56:45 +00:00
|
|
|
/* FluidSynth - A Software Synthesizer
|
|
|
|
*
|
|
|
|
* Copyright (C) 2003 Peter Hanappe and others.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2017-07-12 15:45:23 +00:00
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
2017-07-12 15:53:03 +00:00
|
|
|
* as published by the Free Software Foundation; either version 2.1 of
|
2003-03-11 16:56:45 +00:00
|
|
|
* 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
|
2017-07-12 15:45:23 +00:00
|
|
|
* Lesser General Public License for more details.
|
2007-03-04 16:45:05 +00:00
|
|
|
*
|
2017-07-12 15:54:54 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2003-03-11 16:56:45 +00:00
|
|
|
* License along with this library; if not, write to the Free
|
2011-08-15 12:57:10 +00:00
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301, USA
|
2003-03-11 16:56:45 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _FLUID_VOICE_H
|
|
|
|
#define _FLUID_VOICE_H
|
|
|
|
|
|
|
|
#include "fluid_phase.h"
|
|
|
|
#include "fluid_gen.h"
|
|
|
|
#include "fluid_mod.h"
|
2010-06-20 06:52:37 +00:00
|
|
|
#include "fluid_iir_filter.h"
|
2010-06-20 06:53:00 +00:00
|
|
|
#include "fluid_adsr_env.h"
|
2010-06-20 06:53:20 +00:00
|
|
|
#include "fluid_lfo.h"
|
2010-06-26 15:02:58 +00:00
|
|
|
#include "fluid_rvoice.h"
|
2010-06-28 20:03:12 +00:00
|
|
|
#include "fluid_sys.h"
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
#define NO_CHANNEL 0xff
|
|
|
|
|
2010-07-31 20:50:47 +00:00
|
|
|
typedef struct _fluid_overflow_prio_t fluid_overflow_prio_t;
|
|
|
|
|
|
|
|
struct _fluid_overflow_prio_t
|
|
|
|
{
|
2010-08-01 18:16:54 +00:00
|
|
|
fluid_real_t percussion; /**< Is this voice on the drum channel? Then add this score */
|
2010-07-31 20:50:47 +00:00
|
|
|
fluid_real_t released; /**< Is this voice in release stage? Then add this score (usually negative) */
|
|
|
|
fluid_real_t sustained; /**< Is this voice sustained? Then add this score (usually negative) */
|
|
|
|
fluid_real_t volume; /**< Multiply current (or future) volume (a value between 0 and 1) */
|
|
|
|
fluid_real_t age; /**< This score will be divided by the number of seconds the voice has lasted */
|
|
|
|
};
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
enum fluid_voice_status
|
|
|
|
{
|
2004-03-29 10:05:18 +00:00
|
|
|
FLUID_VOICE_CLEAN,
|
|
|
|
FLUID_VOICE_ON,
|
2015-04-07 11:48:04 +00:00
|
|
|
FLUID_VOICE_SUSTAINED, /* Sustained by Sustain pedal */
|
|
|
|
FLUID_VOICE_HELD_BY_SOSTENUTO, /* Sustained by Sostenuto pedal */
|
2004-03-29 10:05:18 +00:00
|
|
|
FLUID_VOICE_OFF
|
2003-03-11 16:56:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* fluid_voice_t
|
|
|
|
*/
|
|
|
|
struct _fluid_voice_t
|
|
|
|
{
|
2007-03-04 16:45:05 +00:00
|
|
|
unsigned int id; /* the id is incremented for every new noteon.
|
2004-03-29 10:05:18 +00:00
|
|
|
it's used for noteoff's */
|
|
|
|
unsigned char status;
|
|
|
|
unsigned char chan; /* the channel number, quick access for channel messages */
|
2017-09-02 22:01:45 +00:00
|
|
|
unsigned char key; /* the key of the noteon event, quick access for noteoff */
|
|
|
|
unsigned char vel; /* the velocity of the noteon event */
|
2004-03-29 10:05:18 +00:00
|
|
|
fluid_channel_t* channel;
|
|
|
|
fluid_gen_t gen[GEN_LAST];
|
|
|
|
fluid_mod_t mod[FLUID_NUM_MOD];
|
|
|
|
int mod_count;
|
2010-06-26 15:02:58 +00:00
|
|
|
fluid_sample_t* sample; /* Pointer to sample (dupe in rvoice) */
|
|
|
|
|
2004-03-29 10:05:18 +00:00
|
|
|
/* basic parameters */
|
2010-06-26 15:02:58 +00:00
|
|
|
fluid_real_t output_rate; /* the sample rate of the synthesizer (dupe in rvoice) */
|
2004-03-29 10:05:18 +00:00
|
|
|
|
|
|
|
unsigned int start_time;
|
2010-07-31 20:50:47 +00:00
|
|
|
fluid_adsr_env_t volenv; /* Volume envelope (dupe in rvoice) */
|
2004-03-29 10:05:18 +00:00
|
|
|
|
|
|
|
/* basic parameters */
|
2010-06-26 15:02:58 +00:00
|
|
|
fluid_real_t pitch; /* the pitch in midicents (dupe in rvoice) */
|
|
|
|
fluid_real_t attenuation; /* the attenuation in centibels (dupe in rvoice) */
|
|
|
|
fluid_real_t root_pitch;
|
2004-03-29 10:05:18 +00:00
|
|
|
|
2010-06-26 15:02:58 +00:00
|
|
|
/* master gain (dupe in rvoice) */
|
|
|
|
fluid_real_t synth_gain;
|
2004-03-29 10:05:18 +00:00
|
|
|
|
|
|
|
/* pan */
|
|
|
|
fluid_real_t pan;
|
|
|
|
fluid_real_t amp_left;
|
|
|
|
fluid_real_t amp_right;
|
|
|
|
|
|
|
|
/* reverb */
|
|
|
|
fluid_real_t reverb_send;
|
|
|
|
fluid_real_t amp_reverb;
|
|
|
|
|
|
|
|
/* chorus */
|
|
|
|
fluid_real_t chorus_send;
|
|
|
|
fluid_real_t amp_chorus;
|
|
|
|
|
2010-06-26 15:02:58 +00:00
|
|
|
/* rvoice control */
|
|
|
|
fluid_rvoice_t* rvoice;
|
2011-03-27 13:54:52 +00:00
|
|
|
fluid_rvoice_t* overflow_rvoice; /* Used temporarily and only in overflow situations */
|
2017-10-19 21:52:46 +00:00
|
|
|
char can_access_rvoice; /* False if rvoice is being rendered in separate thread */
|
|
|
|
char can_access_overflow_rvoice; /* False if overflow_rvoice is being rendered in separate thread */
|
|
|
|
char has_noteoff; /* Flag set when noteoff has been sent */
|
2017-10-20 10:25:45 +00:00
|
|
|
|
|
|
|
/* for debugging */
|
|
|
|
double ref;
|
2003-03-11 16:56:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-03-29 10:05:18 +00:00
|
|
|
fluid_voice_t* new_fluid_voice(fluid_real_t output_rate);
|
2003-03-11 16:56:45 +00:00
|
|
|
int delete_fluid_voice(fluid_voice_t* voice);
|
|
|
|
|
2007-03-04 16:45:05 +00:00
|
|
|
void fluid_voice_start(fluid_voice_t* voice);
|
2009-09-25 00:56:48 +00:00
|
|
|
void fluid_voice_calculate_gen_pitch(fluid_voice_t* voice);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
Added public API functions: fluid_synth_sysex, fluid_synth_activate_key_tuning, fluid_synth_activate_octave_tuning, fluid_synth_tune_notes, fluid_synth_activate_tuning and fluid_synth_deactivate_tuning.
Added audio.realtime, audio.realtime-prio, midi.realtime and midi.realtime-prio (only ALSA updated to use them at this point).
Fixed bug in new_fluid_channel() where tuning field was not initialized.
fluid_settings.h had wrong field order in prototypes for fluid_settings_register_num and fluid_settings_register_int.
Added multi core support: "synth.cpu-cores" setting, fluid_synth_core_thread_func() and many core_ variables to fluid_synth_t.
Switched fluid_mutex_t back to a normal non-recursive mutex and added fluid_rec_mutex_t.
Added fluid_cond_t thread synchronization stuff.
Added fluid_cond_mutex_t which is a dynamically allocated regular mutex for use with fluid_cond_t.
fluid_settings_t and fluid_synth_t are now using fluid_rec_mutex_t (same as before, just name change).
Added platform specific fluid_thread_self_set_prio() functions to fluid_sys.c for activating high priority for the calling thread.
Modified new_fluid_thread() to take a prio and prio_level parameters.
Added missing fluid_atomic_pointer_set().
fluid_voice_write() changed to only take a voice audio buffer to render to, mixing is done separately with new fluid_voice_mix().
fluid_voice_write() now returns the count of samples rendered.
fluid_voice_effects() split into fluid_voice_filter() and fluid_voice_mix().
Added dsp_buf_count field to fluid_voice_t to keep track of last count of samples rendered to dsp_buf.
fluid_voice_get_channel() converted to a macro.
Added FLUID_DEFAULT_AUDIO_RT_PRIO and FLUID_DEFAULT_MIDI_RT_PRIO in fluidsynth_priv.h, set to 90 and 80 respectively which get used for audio.realtime-prio and midi.realtime-prio (was 90 and 90 before).
2009-09-29 21:40:28 +00:00
|
|
|
int fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
2007-03-04 16:45:05 +00:00
|
|
|
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
|
|
|
|
fluid_channel_t* channel, int key, int vel,
|
2004-03-29 10:05:18 +00:00
|
|
|
unsigned int id, unsigned int time, fluid_real_t gain);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl);
|
|
|
|
int fluid_voice_modulate_all(fluid_voice_t* voice);
|
|
|
|
|
|
|
|
/** Set the NRPN value of a generator. */
|
2004-03-03 11:14:25 +00:00
|
|
|
int fluid_voice_set_param(fluid_voice_t* voice, int gen, fluid_real_t value, int abs);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
/** Set the gain. */
|
|
|
|
int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain);
|
|
|
|
|
2010-07-14 08:46:03 +00:00
|
|
|
int fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value);
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
|
|
|
|
/** Update all the synthesis parameters, which depend on generator
|
|
|
|
'gen'. This is only necessary after changing a generator of an
|
|
|
|
already operating voice. Most applications will not need this
|
|
|
|
function.*/
|
|
|
|
void fluid_voice_update_param(fluid_voice_t* voice, int gen);
|
|
|
|
|
2015-04-07 11:48:04 +00:00
|
|
|
void fluid_voice_release(fluid_voice_t* voice);
|
2009-10-14 07:27:30 +00:00
|
|
|
int fluid_voice_noteoff(fluid_voice_t* voice);
|
2017-07-01 15:57:43 +00:00
|
|
|
void fluid_voice_off(fluid_voice_t* voice);
|
|
|
|
void fluid_voice_stop(fluid_voice_t* voice);
|
2011-03-27 13:54:52 +00:00
|
|
|
void fluid_voice_overflow_rvoice_finished(fluid_voice_t* voice);
|
2010-06-26 15:02:58 +00:00
|
|
|
void fluid_voice_mix (fluid_voice_t *voice, int count, fluid_real_t* dsp_buf,
|
|
|
|
fluid_real_t* left_buf, fluid_real_t* right_buf,
|
|
|
|
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf);
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
int fluid_voice_kill_excl(fluid_voice_t* voice);
|
2010-07-31 20:50:47 +00:00
|
|
|
fluid_real_t fluid_voice_get_overflow_prio(fluid_voice_t* voice,
|
|
|
|
fluid_overflow_prio_t* score,
|
|
|
|
unsigned int cur_time);
|
2003-03-11 16:56:45 +00:00
|
|
|
|
2011-03-27 13:54:52 +00:00
|
|
|
#define OVERFLOW_PRIO_CANNOT_KILL 999999.
|
|
|
|
|
2010-06-28 20:03:12 +00:00
|
|
|
/**
|
|
|
|
* Locks the rvoice for rendering, so it can't be modified directly
|
|
|
|
*/
|
|
|
|
static FLUID_INLINE fluid_rvoice_t*
|
|
|
|
fluid_voice_lock_rvoice(fluid_voice_t* voice)
|
|
|
|
{
|
|
|
|
voice->can_access_rvoice = 0;
|
|
|
|
return voice->rvoice;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-07-31 20:50:47 +00:00
|
|
|
* Unlocks the rvoice for rendering, so it can be modified directly
|
2010-06-28 20:03:12 +00:00
|
|
|
*/
|
|
|
|
static FLUID_INLINE void
|
|
|
|
fluid_voice_unlock_rvoice(fluid_voice_t* voice)
|
|
|
|
{
|
|
|
|
voice->can_access_rvoice = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define _AVAILABLE(voice) ((voice)->can_access_rvoice && \
|
|
|
|
(((voice)->status == FLUID_VOICE_CLEAN) || ((voice)->status == FLUID_VOICE_OFF)))
|
2010-07-31 20:50:47 +00:00
|
|
|
//#define _RELEASED(voice) ((voice)->chan == NO_CHANNEL)
|
2003-03-11 16:56:45 +00:00
|
|
|
#define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val)
|
|
|
|
|
2004-03-03 11:14:25 +00:00
|
|
|
|
Added public API functions: fluid_synth_sysex, fluid_synth_activate_key_tuning, fluid_synth_activate_octave_tuning, fluid_synth_tune_notes, fluid_synth_activate_tuning and fluid_synth_deactivate_tuning.
Added audio.realtime, audio.realtime-prio, midi.realtime and midi.realtime-prio (only ALSA updated to use them at this point).
Fixed bug in new_fluid_channel() where tuning field was not initialized.
fluid_settings.h had wrong field order in prototypes for fluid_settings_register_num and fluid_settings_register_int.
Added multi core support: "synth.cpu-cores" setting, fluid_synth_core_thread_func() and many core_ variables to fluid_synth_t.
Switched fluid_mutex_t back to a normal non-recursive mutex and added fluid_rec_mutex_t.
Added fluid_cond_t thread synchronization stuff.
Added fluid_cond_mutex_t which is a dynamically allocated regular mutex for use with fluid_cond_t.
fluid_settings_t and fluid_synth_t are now using fluid_rec_mutex_t (same as before, just name change).
Added platform specific fluid_thread_self_set_prio() functions to fluid_sys.c for activating high priority for the calling thread.
Modified new_fluid_thread() to take a prio and prio_level parameters.
Added missing fluid_atomic_pointer_set().
fluid_voice_write() changed to only take a voice audio buffer to render to, mixing is done separately with new fluid_voice_mix().
fluid_voice_write() now returns the count of samples rendered.
fluid_voice_effects() split into fluid_voice_filter() and fluid_voice_mix().
Added dsp_buf_count field to fluid_voice_t to keep track of last count of samples rendered to dsp_buf.
fluid_voice_get_channel() converted to a macro.
Added FLUID_DEFAULT_AUDIO_RT_PRIO and FLUID_DEFAULT_MIDI_RT_PRIO in fluidsynth_priv.h, set to 90 and 80 respectively which get used for audio.realtime-prio and midi.realtime-prio (was 90 and 90 before).
2009-09-29 21:40:28 +00:00
|
|
|
/* FIXME - This doesn't seem to be used anywhere - JG */
|
2004-03-03 11:14:25 +00:00
|
|
|
fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num);
|
|
|
|
|
2010-06-20 06:53:00 +00:00
|
|
|
#define fluid_voice_get_loudness(voice) (fluid_adsr_env_get_max_val(&voice->volenv))
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
#define _GEN(_voice, _n) \
|
|
|
|
((fluid_real_t)(_voice)->gen[_n].val \
|
|
|
|
+ (fluid_real_t)(_voice)->gen[_n].mod \
|
|
|
|
+ (fluid_real_t)(_voice)->gen[_n].nrpn)
|
|
|
|
|
2007-09-02 23:23:47 +00:00
|
|
|
/* defined in fluid_dsp_float.c */
|
|
|
|
|
|
|
|
void fluid_dsp_float_config (void);
|
|
|
|
int fluid_dsp_float_interpolate_none (fluid_voice_t *voice);
|
|
|
|
int fluid_dsp_float_interpolate_linear (fluid_voice_t *voice);
|
|
|
|
int fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice);
|
|
|
|
int fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice);
|
|
|
|
|
2003-03-11 16:56:45 +00:00
|
|
|
#endif /* _FLUID_VOICE_H */
|