1/* FluidSynth - A Software Synthesizer 2 * 3 * Copyright (C) 2003 Peter Hanappe and others. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public License 7 * as published by the Free Software Foundation; either version 2 of 8 * the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public 16 * License along with this library; if not, write to the Free 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 * 02111-1307, USA 19 */ 20 21 22#ifndef _FLUID_VOICE_H 23#define _FLUID_VOICE_H 24 25#include "fluid_phase.h" 26#include "fluid_gen.h" 27#include "fluid_mod.h" 28 29#define NO_CHANNEL 0xff 30 31enum fluid_voice_status 32{ 33 FLUID_VOICE_CLEAN, 34 FLUID_VOICE_ON, 35 FLUID_VOICE_SUSTAINED, 36 FLUID_VOICE_OFF 37}; 38 39 40/* 41 * envelope data 42 */ 43struct _fluid_env_data_t { 44 unsigned int count; 45 fluid_real_t coeff; 46 fluid_real_t incr; 47 fluid_real_t min; 48 fluid_real_t max; 49}; 50 51/* Indices for envelope tables */ 52enum fluid_voice_envelope_index_t{ 53 FLUID_VOICE_ENVDELAY, 54 FLUID_VOICE_ENVATTACK, 55 FLUID_VOICE_ENVHOLD, 56 FLUID_VOICE_ENVDECAY, 57 FLUID_VOICE_ENVSUSTAIN, 58 FLUID_VOICE_ENVRELEASE, 59 FLUID_VOICE_ENVFINISHED, 60 FLUID_VOICE_ENVLAST 61}; 62 63/* 64 * fluid_voice_t 65 */ 66struct _fluid_voice_t 67{ 68 unsigned int id; /* the id is incremented for every new noteon. 69 it's used for noteoff's */ 70 unsigned char status; 71 unsigned char chan; /* the channel number, quick access for channel messages */ 72 unsigned char key; /* the key, quick acces for noteoff */ 73 unsigned char vel; /* the velocity */ 74 fluid_channel_t* channel; 75 fluid_gen_t gen[GEN_LAST]; 76 fluid_mod_t mod[FLUID_NUM_MOD]; 77 int mod_count; 78 int has_looped; /* Flag that is set as soon as the first loop is completed. */ 79 fluid_sample_t* sample; 80 int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters 81 have to be checked. */ 82#if 0 83 /* Instead of keeping a pointer to a fluid_sample_t structure, 84 * I think it would be better to copy the sample data in the 85 * voice structure. SoundFont loader then do not have to 86 * allocate and maintain the fluid_sample_t structure. [PH] 87 * 88 * The notify callback may be used also for streaming samples. 89 */ 90 short* sample_data; /* pointer to the sample data */ 91 int sample_data_offset; /* the offset of data[0] in the whole sample */ 92 int sample_data_length; /* the length of the data array */ 93 unsigned int sample_start; 94 unsigned int sample_end; 95 unsigned int sample_loopstart; 96 unsigned int sample_loopend; 97 unsigned int sample_rate; 98 int sample_origpitch; 99 int sample_pitchadj; 100 int sample_type; 101 int (*sample_notify)(fluid_voice_t* voice, int reason); 102 void* sample_userdata; 103#endif 104 105 /* basic parameters */ 106 fluid_real_t output_rate; /* the sample rate of the synthesizer */ 107 108 unsigned int start_time; 109 unsigned int ticks; 110 111 fluid_real_t amp; /* current linear amplitude */ 112 fluid_phase_t phase; /* the phase of the sample wave */ 113 114 /* Temporary variables used in fluid_voice_write() */ 115 116 fluid_real_t phase_incr; /* the phase increment for the next 64 samples */ 117 fluid_real_t amp_incr; /* amplitude increment value */ 118 fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */ 119 120 /* End temporary variables */ 121 122 /* basic parameters */ 123 fluid_real_t pitch; /* the pitch in midicents */ 124 fluid_real_t attenuation; /* the attenuation in centibels */ 125 fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation 126 * during the lifetime of the voice */ 127 fluid_real_t root_pitch; 128 129 /* sample and loop start and end points (offset in sample memory). */ 130 int start; 131 int end; 132 int loopstart; 133 int loopend; /* Note: first point following the loop (superimposed on loopstart) */ 134 135 /* master gain */ 136 fluid_real_t synth_gain; 137 138 /* vol env */ 139 fluid_env_data_t volenv_data[FLUID_VOICE_ENVLAST]; 140 unsigned int volenv_count; 141 int volenv_section; 142 fluid_real_t volenv_val; 143 fluid_real_t amplitude_that_reaches_noise_floor_nonloop; 144 fluid_real_t amplitude_that_reaches_noise_floor_loop; 145 146 /* mod env */ 147 fluid_env_data_t modenv_data[FLUID_VOICE_ENVLAST]; 148 unsigned int modenv_count; 149 int modenv_section; 150 fluid_real_t modenv_val; /* the value of the modulation envelope */ 151 fluid_real_t modenv_to_fc; 152 fluid_real_t modenv_to_pitch; 153 154 /* mod lfo */ 155 fluid_real_t modlfo_val; /* the value of the modulation LFO */ 156 unsigned int modlfo_delay; /* the delay of the lfo in samples */ 157 fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */ 158 fluid_real_t modlfo_to_fc; 159 fluid_real_t modlfo_to_pitch; 160 fluid_real_t modlfo_to_vol; 161 162 /* vib lfo */ 163 fluid_real_t viblfo_val; /* the value of the vibrato LFO */ 164 unsigned int viblfo_delay; /* the delay of the lfo in samples */ 165 fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */ 166 fluid_real_t viblfo_to_pitch; 167 168 /* resonant filter */ 169 fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */ 170 fluid_real_t last_fres; /* Current resonance frequency of the IIR filter */ 171 /* Serves as a flag: A deviation between fres and last_fres */ 172 /* indicates, that the filter has to be recalculated. */ 173 fluid_real_t q_lin; /* the q-factor on a linear scale */ 174 fluid_real_t filter_gain; /* Gain correction factor, depends on q */ 175 fluid_real_t hist1, hist2; /* Sample history for the IIR filter */ 176 int filter_startup; /* Flag: If set, the filter will be set directly. 177 Else it changes smoothly. */ 178 179 /* filter coefficients */ 180 /* The coefficients are normalized to a0. */ 181 /* b0 and b2 are identical => b02 */ 182 fluid_real_t b02; /* b0 / a0 */ 183 fluid_real_t b1; /* b1 / a0 */ 184 fluid_real_t a1; /* a0 / a0 */ 185 fluid_real_t a2; /* a1 / a0 */ 186 187 fluid_real_t b02_incr; 188 fluid_real_t b1_incr; 189 fluid_real_t a1_incr; 190 fluid_real_t a2_incr; 191 int filter_coeff_incr_count; 192 193 /* pan */ 194 fluid_real_t pan; 195 fluid_real_t amp_left; 196 fluid_real_t amp_right; 197 198 /* reverb */ 199 fluid_real_t reverb_send; 200 fluid_real_t amp_reverb; 201 202 /* chorus */ 203 fluid_real_t chorus_send; 204 fluid_real_t amp_chorus; 205 206 /* interpolation method, as in fluid_interp in fluidsynth.h */ 207 int interp_method; 208 209 /* for debugging */ 210 int debug; 211 double ref; 212}; 213 214 215fluid_voice_t* new_fluid_voice(fluid_real_t output_rate); 216int delete_fluid_voice(fluid_voice_t* voice); 217 218void fluid_voice_start(fluid_voice_t* voice); 219 220int fluid_voice_write(fluid_voice_t* voice, 221 fluid_real_t* left, fluid_real_t* right, 222 fluid_real_t* reverb_buf, fluid_real_t* chorus_buf); 223 224int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, 225 fluid_channel_t* channel, int key, int vel, 226 unsigned int id, unsigned int time, fluid_real_t gain); 227 228int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl); 229int fluid_voice_modulate_all(fluid_voice_t* voice); 230 231/** Set the NRPN value of a generator. */ 232int fluid_voice_set_param(fluid_voice_t* voice, int gen, fluid_real_t value, int abs); 233 234 235/** Set the gain. */ 236int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain); 237 238 239/** Update all the synthesis parameters, which depend on generator 240 'gen'. This is only necessary after changing a generator of an 241 already operating voice. Most applications will not need this 242 function.*/ 243void fluid_voice_update_param(fluid_voice_t* voice, int gen); 244 245int fluid_voice_noteoff(fluid_voice_t* voice); 246int fluid_voice_off(fluid_voice_t* voice); 247int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice); 248fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice); 249int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, 250 int gen_key2base, int is_decay); 251int fluid_voice_kill_excl(fluid_voice_t* voice); 252fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice); 253fluid_real_t fluid_voice_determine_amplitude_that_reaches_noise_floor_for_sample(fluid_voice_t* voice); 254void fluid_voice_check_sample_sanity(fluid_voice_t* voice); 255 256#define fluid_voice_set_id(_voice, _id) { (_voice)->id = (_id); } 257#define fluid_voice_get_chan(_voice) (_voice)->chan 258 259 260#define _PLAYING(voice) (((voice)->status == FLUID_VOICE_ON) || ((voice)->status == FLUID_VOICE_SUSTAINED)) 261 262/* A voice is 'ON', if it has not yet received a noteoff 263 * event. Sending a noteoff event will advance the envelopes to 264 * section 5 (release). */ 265#define _ON(voice) ((voice)->status == FLUID_VOICE_ON && (voice)->volenv_section < FLUID_VOICE_ENVRELEASE) 266#define _SUSTAINED(voice) ((voice)->status == FLUID_VOICE_SUSTAINED) 267#define _AVAILABLE(voice) (((voice)->status == FLUID_VOICE_CLEAN) || ((voice)->status == FLUID_VOICE_OFF)) 268#define _RELEASED(voice) ((voice)->chan == NO_CHANNEL) 269#define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val) 270 271 272fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num); 273 274#define _GEN(_voice, _n) \ 275 ((fluid_real_t)(_voice)->gen[_n].val \ 276 + (fluid_real_t)(_voice)->gen[_n].mod \ 277 + (fluid_real_t)(_voice)->gen[_n].nrpn) 278 279#define FLUID_SAMPLESANITY_CHECK (1 << 0) 280#define FLUID_SAMPLESANITY_STARTUP (1 << 1) 281 282 283/* defined in fluid_dsp_float.c */ 284 285void fluid_dsp_float_config (void); 286int fluid_dsp_float_interpolate_none (fluid_voice_t *voice); 287int fluid_dsp_float_interpolate_linear (fluid_voice_t *voice); 288int fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice); 289int fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice); 290 291#endif /* _FLUID_VOICE_H */ 292