Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…
Cannot retrieve contributors at this time
243 lines (202 sloc) 7.81 KB
/* 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
* 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_VOICE_H
#define _FLUID_VOICE_H
#include "fluid.h"
#include "gen.h"
namespace FluidS {
#define NO_CHANNEL 0xff
enum fluid_voice_status {
* envelope data
struct fluid_env_data_t {
unsigned int count; // sample count
float coeff;
float incr;
float min;
float max;
/* Indices for envelope tables */
enum fluid_voice_envelope_index_t {
// Voice
class Voice
static float interp_coeff_linear[FLUID_INTERP_MAX][2];
static float interp_coeff[FLUID_INTERP_MAX][4];
static float sinc_table7[FLUID_INTERP_MAX][7];
Fluid* _fluid;
double _noteTuning; // +/- in midicent
void effects(int count, float* left, float* right, float* reverb, float* chorus);
unsigned int id; // the id is incremented for every new noteon.
// it's used for noteoff's
unsigned char status;
unsigned char chan; // the channel number, quick access for channel messages
unsigned char key; // the key, quick acces for noteoff
unsigned char vel; // the velocity
Channel* channel;
Generator gen[GEN_LAST];
int mod_count;
bool has_looped; /* Flag that is set as soon as the first loop is completed. */
Sample* sample;
int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters
have to be checked. */
unsigned int ticks;
float amp; /* the linear amplitude */
Phase phase; // the phase of the sample wave
// Temporary variables used in write()
float phase_incr; /* the phase increment for the next 64 samples */
float amp_incr; /* amplitude increment value */
float* dsp_buf; /* buffer to store interpolated sample data to */
/* basic parameters */
float pitch; /* the pitch in midicents */
float attenuation; /* the attenuation in centibels */
float min_attenuation_cB; /* Estimate on the smallest possible attenuation
* during the lifetime of the voice */
float root_pitch;
/* sample and loop start and end points (offset in sample memory). */
int start;
int end;
int loopstart;
int loopend;
/* vol env */
fluid_env_data_t volenv_data[FLUID_VOICE_ENVLAST];
unsigned int volenv_count;
int volenv_section;
float volenv_val;
float amplitude_that_reaches_noise_floor_nonloop;
float amplitude_that_reaches_noise_floor_loop;
/* mod env */
fluid_env_data_t modenv_data[FLUID_VOICE_ENVLAST];
unsigned int modenv_count;
int modenv_section;
float modenv_val; /* the value of the modulation envelope */
float modenv_to_fc;
float modenv_to_pitch;
/* mod lfo */
float modlfo_val; /* the value of the modulation LFO */
unsigned int modlfo_delay; /* the delay of the lfo in samples */
float modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */
float modlfo_to_fc;
float modlfo_to_pitch;
float modlfo_to_vol;
/* vib lfo */
float viblfo_val; /* the value of the vibrato LFO */
unsigned int viblfo_delay; /* the delay of the lfo in samples */
float viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */
float viblfo_to_pitch;
/* resonant filter */
float fres; /* the resonance frequency, in cents (not absolute cents) */
float last_fres; /* Current resonance frequency of the IIR filter */
/* Serves as a flag: A deviation between fres and last_fres */
/* indicates, that the filter has to be recalculated. */
float q_lin; /* the q-factor on a linear scale */
float filter_gain; /* Gain correction factor, depends on q */
float hist1, hist2; /* Sample history for the IIR filter */
int filter_startup; /* Flag: If set, the filter will be set directly.
Else it changes smoothly. */
/* filter coefficients */
/* The coefficients are normalized to a0. */
/* b0 and b2 are identical => b02 */
float b02; /* b0 / a0 */
float b1; /* b1 / a0 */
float a1; /* a0 / a0 */
float a2; /* a1 / a0 */
float b02_incr;
float b1_incr;
float a1_incr;
float a2_incr;
int filter_coeff_incr_count;
/* pan */
float pan;
float amp_left;
float amp_right;
/* reverb */
float reverb_send;
float amp_reverb;
/* chorus */
float chorus_send;
float amp_chorus;
/* interpolation method, as in fluid_interp in fluidsynth.h */
int interp_method;
/* for debugging */
int debug;
double ref;
Channel* get_channel() const { return channel; }
void voice_start();
void off();
void init(Sample*, Channel*, int key, int vel, unsigned id, double tuning);
void gen_incr(int i, float val);
void gen_set(int i, float val);
float gen_get(int gen);
unsigned int get_id() const { return id; }
bool isPlaying() { return ((status == FLUID_VOICE_ON) || (status == FLUID_VOICE_SUSTAINED)); }
void set_param(int gen, float nrpn_value, int abs);
// 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 update_param(int gen);
double GEN(int n) { return gen[n].val + gen[n].mod + gen[n].nrpn; }
void modulate_all();
void modulate(bool _cc, int _ctrl);
float get_lower_boundary_for_attenuation();
void check_sample_sanity();
void noteoff();
void kill_excl();
int calculate_hold_decay_frames(int gen_base, int gen_key2base, int is_decay);
/* A voice is 'ON', if it has not yet received a noteoff
* event. Sending a noteoff event will advance the envelopes to
* section 5 (release).
bool RELEASED() const { return chan == NO_CHANNEL; }
bool SUSTAINED() const { return status == FLUID_VOICE_SUSTAINED; }
bool PLAYING() const { return (status == FLUID_VOICE_ON) || (status == FLUID_VOICE_SUSTAINED); }
bool ON() const { return (status == FLUID_VOICE_ON) && (volenv_section < FLUID_VOICE_ENVRELEASE); }
int SAMPLEMODE() const { return ((int)gen[GEN_SAMPLEMODE].val); }
void write(unsigned n, float* l, float* r, float* reverb_buf, float* chorus_buf);
void add_mod(const Mod* mod, int mode);
static void dsp_float_config();
int dsp_float_interpolate_none(unsigned);
int dsp_float_interpolate_linear(unsigned);
int dsp_float_interpolate_4th_order(unsigned);
int dsp_float_interpolate_7th_order(unsigned);
#endif /* _FLUID_VOICE_H */
Jump to Line
Something went wrong with that request. Please try again.