Path: blob/master/libs/fluidsynth/src/synth/fluid_voice.c
4396 views
/* FluidSynth - A Software Synthesizer1*2* Copyright (C) 2003 Peter Hanappe and others.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public License6* as published by the Free Software Foundation; either version 2.1 of7* the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful, but10* WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* You should have received a copy of the GNU Lesser General Public15* License along with this library; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA17* 02110-1301, USA18*/1920#include "fluid_sys.h"21#include "fluid_voice.h"22#include "fluid_mod.h"23#include "fluid_chan.h"24#include "fluid_conv.h"25#include "fluid_synth.h"26#include "fluid_sys.h"27#include "fluid_sfont.h"28#include "fluid_rvoice_event.h"29#include "fluid_defsfont.h"3031/* used for filter turn off optimization - if filter cutoff is above the32specified value and filter q is below the other value, turn filter off */33#define FLUID_MAX_AUDIBLE_FILTER_FC 19000.0f34#define FLUID_MIN_AUDIBLE_FILTER_Q 1.2f3536/* min vol envelope release (to stop clicks) in SoundFont timecents */37#define FLUID_MIN_VOLENVRELEASE -7200.0f /* ~16ms */383940static const int32_t INT24_MAX = (1 << (16 + 8 - 1));4142static int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t *voice);43static int calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base,44int gen_key2base, int is_decay);45static fluid_real_t46fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice);4748#define UPDATE_RVOICE0(proc) \49do { \50fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \51fluid_rvoice_eventhandler_push(voice->eventhandler, proc, voice->rvoice, param); \52} while (0)5354#define UPDATE_RVOICE_GENERIC_R1(proc, obj, rarg) \55do { \56fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \57param[0].real = rarg; \58fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \59} while (0)6061#define UPDATE_RVOICE_GENERIC_I1(proc, obj, iarg) \62do { \63fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \64param[0].i = iarg; \65fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \66} while (0)6768#define UPDATE_RVOICE_GENERIC_I2(proc, obj, iarg1, iarg2) \69do { \70fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \71param[0].i = iarg1; \72param[1].i = iarg2; \73fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \74} while (0)7576#define UPDATE_RVOICE_GENERIC_IR(proc, obj, iarg, rarg) \77do { \78fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \79param[0].i = iarg; \80param[1].real = rarg; \81fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \82} while (0)838485#define UPDATE_RVOICE_R1(proc, arg1) UPDATE_RVOICE_GENERIC_R1(proc, voice->rvoice, arg1)86#define UPDATE_RVOICE_I1(proc, arg1) UPDATE_RVOICE_GENERIC_I1(proc, voice->rvoice, arg1)8788#define UPDATE_RVOICE_BUFFERS_AMP(proc, iarg, rarg) UPDATE_RVOICE_GENERIC_IR(proc, &voice->rvoice->buffers, iarg, rarg)89#define UPDATE_RVOICE_ENVLFO_R1(proc, envp, rarg) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->envlfo.envp, rarg)90#define UPDATE_RVOICE_ENVLFO_I1(proc, envp, iarg) UPDATE_RVOICE_GENERIC_I1(proc, &voice->rvoice->envlfo.envp, iarg)9192static FLUID_INLINE void93fluid_voice_update_volenv(fluid_voice_t *voice,94int enqueue,95fluid_adsr_env_section_t section,96unsigned int count,97fluid_real_t coeff,98fluid_real_t increment,99fluid_real_t min,100fluid_real_t max)101{102fluid_rvoice_param_t param[MAX_EVENT_PARAMS];103104param[0].i = section;105param[1].i = count;106param[2].real = coeff;107param[3].real = increment;108param[4].real = min;109param[5].real = max;110111if(enqueue)112{113fluid_rvoice_eventhandler_push(voice->eventhandler,114fluid_adsr_env_set_data,115&voice->rvoice->envlfo.volenv,116param);117}118else119{120fluid_adsr_env_set_data(&voice->rvoice->envlfo.volenv, param);121}122}123124static FLUID_INLINE void125fluid_voice_update_modenv(fluid_voice_t *voice,126int enqueue,127fluid_adsr_env_section_t section,128unsigned int count,129fluid_real_t coeff,130fluid_real_t increment,131fluid_real_t min,132fluid_real_t max)133{134fluid_rvoice_param_t param[MAX_EVENT_PARAMS];135136param[0].i = section;137param[1].i = count;138param[2].real = coeff;139param[3].real = increment;140param[4].real = min;141param[5].real = max;142143if(enqueue)144{145fluid_rvoice_eventhandler_push(voice->eventhandler,146fluid_adsr_env_set_data,147&voice->rvoice->envlfo.modenv,148param);149}150else151{152fluid_adsr_env_set_data(&voice->rvoice->envlfo.modenv, param);153}154}155156static FLUID_INLINE void fluid_voice_sample_unref(fluid_sample_t **sample)157{158if(*sample != NULL)159{160fluid_sample_decr_ref(*sample);161*sample = NULL;162}163}164165/*166* Swaps the current rvoice with the current overflow_rvoice167*/168static void fluid_voice_swap_rvoice(fluid_voice_t *voice)169{170fluid_rvoice_t *rtemp = voice->rvoice;171int ctemp = voice->can_access_rvoice;172voice->rvoice = voice->overflow_rvoice;173voice->can_access_rvoice = voice->can_access_overflow_rvoice;174voice->overflow_rvoice = rtemp;175voice->can_access_overflow_rvoice = ctemp;176voice->overflow_sample = voice->sample;177}178179static void fluid_voice_initialize_rvoice(fluid_voice_t *voice, fluid_real_t output_rate)180{181fluid_rvoice_param_t param[MAX_EVENT_PARAMS];182183FLUID_MEMSET(voice->rvoice, 0, sizeof(fluid_rvoice_t));184185/* The 'sustain' and 'finished' segments of the volume / modulation186* envelope are constant. They are never affected by any modulator187* or generator. Therefore it is enough to initialize them once188* during the lifetime of the synth.189*/190fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN,1910xffffffff, 1.0f, 0.0f, -1.0f, 2.0f);192fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVFINISHED,1930xffffffff, 0.0f, 0.0f, -1.0f, 1.0f);194fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN,1950xffffffff, 1.0f, 0.0f, -1.0f, 2.0f);196fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVFINISHED,1970xffffffff, 0.0f, 0.0f, -1.0f, 1.0f);198199param[0].i = FLUID_IIR_LOWPASS;200param[1].i = 0;201fluid_iir_filter_init(&voice->rvoice->resonant_filter, param);202203param[0].i = FLUID_IIR_DISABLED;204fluid_iir_filter_init(&voice->rvoice->resonant_custom_filter, param);205206param[0].real = output_rate;207fluid_rvoice_set_output_rate(voice->rvoice, param);208}209210/*211* new_fluid_voice212*/213fluid_voice_t *214new_fluid_voice(fluid_rvoice_eventhandler_t *handler, fluid_real_t output_rate)215{216fluid_voice_t *voice;217voice = FLUID_NEW(fluid_voice_t);218219if(voice == NULL)220{221FLUID_LOG(FLUID_ERR, "Out of memory");222return NULL;223}224225voice->can_access_rvoice = TRUE;226voice->can_access_overflow_rvoice = TRUE;227228voice->rvoice = FLUID_NEW(fluid_rvoice_t);229voice->overflow_rvoice = FLUID_NEW(fluid_rvoice_t);230231if(voice->rvoice == NULL || voice->overflow_rvoice == NULL)232{233FLUID_LOG(FLUID_ERR, "Out of memory");234delete_fluid_voice(voice);235return NULL;236}237238voice->status = FLUID_VOICE_CLEAN;239voice->chan = NO_CHANNEL;240voice->key = 0;241voice->vel = 0;242voice->eventhandler = handler;243voice->channel = NULL;244voice->sample = NULL;245voice->overflow_sample = NULL;246voice->output_rate = output_rate;247248/* Initialize both the rvoice and overflow_rvoice */249fluid_voice_initialize_rvoice(voice, output_rate);250fluid_voice_swap_rvoice(voice);251fluid_voice_initialize_rvoice(voice, output_rate);252253return voice;254}255256/*257* delete_fluid_voice258*/259void260delete_fluid_voice(fluid_voice_t *voice)261{262fluid_return_if_fail(voice != NULL);263264if(!voice->can_access_rvoice || !voice->can_access_overflow_rvoice)265{266FLUID_LOG(FLUID_WARN, "Deleting voice %u which has locked rvoices!", voice->id);267}268269FLUID_FREE(voice->overflow_rvoice);270FLUID_FREE(voice->rvoice);271FLUID_FREE(voice);272}273274/* fluid_voice_init275*276* Initialize the synthesis process277* inst_zone, the Instrument Zone contains the sample, Keyrange,Velrange278* of the voice.279* When playing legato (n1,n2) in mono mode, n2 will use n1 voices280* as far as n2 still enters in Keyrange,Velrange of n1.281*/282int283fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample,284fluid_zone_range_t *inst_zone_range,285fluid_channel_t *channel, int key, int vel, unsigned int id,286unsigned int start_time, fluid_real_t gain)287{288/* Note: The voice parameters will be initialized later, when the289* generators have been retrieved from the sound font. Here, only290* the 'working memory' of the voice (position in envelopes, history291* of IIR filters, position in sample etc) is initialized. */292int i;293294if(!voice->can_access_rvoice)295{296if(voice->can_access_overflow_rvoice)297{298fluid_voice_swap_rvoice(voice);299}300else301{302FLUID_LOG(FLUID_ERR, "Internal error: Cannot access an rvoice in fluid_voice_init!");303return FLUID_FAILED;304}305}306307/* We are now guaranteed to have access to the rvoice */308309if(voice->sample)310{311fluid_voice_off(voice);312}313314voice->zone_range = inst_zone_range; /* Instrument zone range for legato */315voice->id = id;316voice->chan = fluid_channel_get_num(channel);317voice->key = (unsigned char) key;318voice->vel = (unsigned char) vel;319voice->channel = channel;320voice->mod_count = 0;321voice->start_time = start_time;322voice->has_noteoff = 0;323UPDATE_RVOICE0(fluid_rvoice_reset);324325/*326We increment the reference count of the sample to indicate that this327sample is about to be owned by the rvoice. This will prevent the328unloading of the soundfont while this rvoice is playing.329*/330fluid_sample_incr_ref(sample);331fluid_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample);332voice->sample = sample;333334i = fluid_channel_get_interp_method(channel);335UPDATE_RVOICE_I1(fluid_rvoice_set_interp_method, i);336337/* Set all the generators to their default value, according to SF338* 2.01 section 8.1.3 (page 48). The value of NRPN messages are339* copied from the channel to the voice's generators. The sound font340* loader overwrites them. The generator values are later converted341* into voice parameters in342* fluid_voice_calculate_runtime_synthesis_parameters. */343fluid_gen_init(&voice->gen[0], channel);344UPDATE_RVOICE_I1(fluid_rvoice_set_samplemode, _SAMPLEMODE(voice));345346voice->synth_gain = gain;347348/* avoid division by zero later*/349if(voice->synth_gain < 0.0000001f)350{351voice->synth_gain = 0.0000001f;352}353354UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, voice->synth_gain);355356/* Set up buffer mapping, should be done more flexible in the future. */357i = 2 * channel->synth->audio_groups;358i += (voice->chan % channel->synth->effects_groups) * channel->synth->effects_channels;359UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 2, i + SYNTH_REVERB_CHANNEL);360UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 3, i + SYNTH_CHORUS_CHANNEL);361362i = 2 * (voice->chan % channel->synth->audio_groups);363UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 0, i);364UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 1, i + 1);365366return FLUID_OK;367}368369370/**371* Update sample rate.372*373* @note If the voice is active, it will be turned off.374*/375void376fluid_voice_set_output_rate(fluid_voice_t *voice, fluid_real_t value)377{378if(fluid_voice_is_playing(voice))379{380fluid_voice_off(voice);381}382383voice->output_rate = value;384UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->rvoice, value);385UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->overflow_rvoice, value);386}387388389/**390* Set the value of a generator.391*392* @param voice Voice instance393* @param i Generator ID (#fluid_gen_type)394* @param val Generator value395*/396void397fluid_voice_gen_set(fluid_voice_t *voice, int i, float val)398{399voice->gen[i].val = val;400voice->gen[i].flags = GEN_SET;401402if(i == GEN_SAMPLEMODE)403{404UPDATE_RVOICE_I1(fluid_rvoice_set_samplemode, (int) val);405}406}407408/**409* Offset the value of a generator.410*411* @param voice Voice instance412* @param i Generator ID (#fluid_gen_type)413* @param val Value to add to the existing value414*/415void416fluid_voice_gen_incr(fluid_voice_t *voice, int i, float val)417{418voice->gen[i].val += val;419voice->gen[i].flags = GEN_SET;420}421422/**423* Get the value of a generator.424*425* @param voice Voice instance426* @param gen Generator ID (#fluid_gen_type)427* @return Current generator value428*/429float430fluid_voice_gen_get(fluid_voice_t *voice, int gen)431{432return voice->gen[gen].val;433}434435fluid_real_t fluid_voice_gen_value(const fluid_voice_t *voice, int num)436{437return (fluid_real_t)(voice->gen[num].val + voice->gen[num].mod + voice->gen[num].nrpn);438}439440/*441* fluid_voice_start442*/443void fluid_voice_start(fluid_voice_t *voice)444{445/* The maximum volume of the loop is calculated and cached once for each446* sample with its nominal loop settings. This happens, when the sample is used447* for the first time.*/448449fluid_voice_calculate_runtime_synthesis_parameters(voice);450451#ifdef WITH_PROFILING452voice->ref = fluid_profile_ref();453#endif454455voice->status = FLUID_VOICE_ON;456457/* Increment voice count */458voice->channel->synth->active_voice_count++;459}460461/**462* Calculate the amplitude of a voice.463*464* @param gain The gain value in the range [0.0 ; 1.0]465* @return An amplitude used by rvoice_mixer's buffers466*/467static FLUID_INLINE fluid_real_t468fluid_voice_calculate_gain_amplitude(const fluid_voice_t *voice, fluid_real_t gain)469{470/* we use 24bit samples in fluid_rvoice_dsp. in order to normalize float471* samples to [0.0;1.0] divide samples by the max. value of an int24 and472* amplify them with the gain */473return gain * voice->synth_gain / (INT24_MAX * 1.0f);474}475476/* Useful to return the nominal pitch of a key */477/* The nominal pitch is dependent of voice->root_pitch,tuning, and478GEN_SCALETUNE generator.479This is useful to set the value of GEN_PITCH generator on noteOn.480This is useful to get the beginning/ending pitch for portamento.481*/482fluid_real_t fluid_voice_calculate_pitch(fluid_voice_t *voice, int key)483{484fluid_tuning_t *tuning;485fluid_real_t x, pitch;486487/* Now the nominal pitch of the key is returned.488* Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a489* non-realtime parameter. So we don't allow modulation (as opposed490* to fluid_voice_gen_value(voice, GEN_SCALETUNE) When the scale tuning is varied,491* one key remains fixed. Here C3 (MIDI number 60) is used.492*/493if(fluid_channel_has_tuning(voice->channel))494{495tuning = fluid_channel_get_tuning(voice->channel);496x = fluid_tuning_get_pitch(tuning, (int)(voice->root_pitch / 100.0f));497pitch = voice->gen[GEN_SCALETUNE].val / 100.0f *498(fluid_tuning_get_pitch(tuning, key) - x) + x;499}500else501{502pitch = voice->gen[GEN_SCALETUNE].val503* (key - voice->root_pitch / 100.0f) + voice->root_pitch;504}505506return pitch;507}508509void510fluid_voice_calculate_gen_pitch(fluid_voice_t *voice)511{512voice->gen[GEN_PITCH].val = fluid_voice_calculate_pitch(voice, fluid_voice_get_actual_key(voice));513}514515/*516* fluid_voice_calculate_runtime_synthesis_parameters517*518* in this function we calculate the values of all the parameters. the519* parameters are converted to their most useful unit for the DSP520* algorithm, for example, number of samples instead of521* timecents. Some parameters keep their "perceptual" unit and522* conversion will be done in the DSP function. This is the case, for523* example, for the pitch since it is modulated by the controllers in524* cents. */525static int526fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t *voice)527{528int i;529unsigned int n;530531static int const list_of_generators_to_initialize[] =532{533GEN_STARTADDROFS, /* SF2.01 page 48 #0 */534GEN_ENDADDROFS, /* #1 */535GEN_STARTLOOPADDROFS, /* #2 */536GEN_ENDLOOPADDROFS, /* #3 */537/* GEN_STARTADDRCOARSEOFS see comment below [1] #4 */538GEN_MODLFOTOPITCH, /* #5 */539GEN_VIBLFOTOPITCH, /* #6 */540GEN_MODENVTOPITCH, /* #7 */541GEN_FILTERFC, /* #8 */542GEN_FILTERQ, /* #9 */543GEN_MODLFOTOFILTERFC, /* #10 */544GEN_MODENVTOFILTERFC, /* #11 */545/* GEN_ENDADDRCOARSEOFS [1] #12 */546GEN_MODLFOTOVOL, /* #13 */547/* not defined #14 */548GEN_CHORUSSEND, /* #15 */549GEN_REVERBSEND, /* #16 */550GEN_PAN, /* #17 */551/* not defined #18 */552/* not defined #19 */553/* not defined #20 */554GEN_MODLFODELAY, /* #21 */555GEN_MODLFOFREQ, /* #22 */556GEN_VIBLFODELAY, /* #23 */557GEN_VIBLFOFREQ, /* #24 */558GEN_MODENVDELAY, /* #25 */559GEN_MODENVATTACK, /* #26 */560GEN_MODENVHOLD, /* #27 */561GEN_MODENVDECAY, /* #28 */562/* GEN_MODENVSUSTAIN [1] #29 */563GEN_MODENVRELEASE, /* #30 */564/* GEN_KEYTOMODENVHOLD [1] #31 */565/* GEN_KEYTOMODENVDECAY [1] #32 */566GEN_VOLENVDELAY, /* #33 */567GEN_VOLENVATTACK, /* #34 */568GEN_VOLENVHOLD, /* #35 */569GEN_VOLENVDECAY, /* #36 */570/* GEN_VOLENVSUSTAIN [1] #37 */571GEN_VOLENVRELEASE, /* #38 */572/* GEN_KEYTOVOLENVHOLD [1] #39 */573/* GEN_KEYTOVOLENVDECAY [1] #40 */574/* GEN_STARTLOOPADDRCOARSEOFS [1] #45 */575GEN_KEYNUM, /* #46 */576GEN_VELOCITY, /* #47 */577GEN_ATTENUATION, /* #48 */578/* GEN_ENDLOOPADDRCOARSEOFS [1] #50 */579/* GEN_COARSETUNE [1] #51 */580/* GEN_FINETUNE [1] #52 */581GEN_OVERRIDEROOTKEY, /* #58 */582GEN_PITCH, /* --- */583GEN_CUSTOM_BALANCE, /* --- */584GEN_CUSTOM_FILTERFC, /* --- */585GEN_CUSTOM_FILTERQ /* --- */586};587588/* When the voice is made ready for the synthesis process, a lot of589* voice-internal parameters have to be calculated.590*591* At this point, the sound font has already set the -nominal- value592* for all generators (excluding GEN_PITCH). Most generators can be593* modulated - they include a nominal value and an offset (which594* changes with velocity, note number, channel parameters like595* aftertouch, mod wheel...) Now this offset will be calculated as596* follows:597*598* - Process each modulator once.599* - Calculate its output value.600* - Find the target generator.601* - Add the output value to the modulation value of the generator.602*603* Note: The generators have been initialized with604* fluid_gen_init().605*/606607for(i = 0; i < voice->mod_count; i++)608{609fluid_mod_t *mod = &voice->mod[i];610fluid_real_t modval = fluid_mod_get_value(mod, voice);611int dest_gen_index = mod->dest;612fluid_gen_t *dest_gen = &voice->gen[dest_gen_index];613dest_gen->mod += modval;614/* fluid_dump_modulator(mod); */615}616617/* Now the generators are initialized, nominal and modulation value.618* The voice parameters (which depend on generators) are calculated619* with fluid_voice_update_param. Processing the list of generator620* changes will calculate each voice parameter once.621*622* Note [1]: Some voice parameters depend on several generators. For623* example, the pitch depends on GEN_COARSETUNE, GEN_FINETUNE and624* GEN_PITCH. voice->pitch. Unnecessary recalculation is avoided625* by removing all but one generator from the list of voice626* parameters. Same with GEN_XXX and GEN_XXXCOARSE: the627* initialisation list contains only GEN_XXX.628*/629630/* Calculate the voice parameter(s) dependent on each generator. */631for(n = 0; n < FLUID_N_ELEMENTS(list_of_generators_to_initialize); n++)632{633fluid_voice_update_param(voice, list_of_generators_to_initialize[n]);634}635636/* Start portamento if enabled */637{638/* fromkey note comes from "GetFromKeyPortamentoLegato()" detector.639When fromkey is set to ValidNote , portamento is started */640/* Return fromkey portamento */641int fromkey = voice->channel->synth->fromkey_portamento;642643if(fluid_channel_is_valid_note(fromkey))644{645/* Send portamento parameters to the voice dsp */646fluid_voice_update_portamento(voice, fromkey, fluid_voice_get_actual_key(voice));647}648}649650/* Make an estimate on how loud this voice can get at any time (attenuation). */651UPDATE_RVOICE_R1(fluid_rvoice_set_min_attenuation_cB,652fluid_voice_get_lower_boundary_for_attenuation(voice));653return FLUID_OK;654}655656/*657* calculate_hold_decay_buffers658*/659static int660calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base,661int gen_key2base, int is_decay)662{663/* Purpose:664*665* Returns the number of DSP loops, that correspond to the hold666* (is_decay=0) or decay (is_decay=1) time.667* gen_base=GEN_VOLENVHOLD, GEN_VOLENVDECAY, GEN_MODENVHOLD,668* GEN_MODENVDECAY gen_key2base=GEN_KEYTOVOLENVHOLD,669* GEN_KEYTOVOLENVDECAY, GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVDECAY670*/671672fluid_real_t keysteps;673fluid_real_t timecents;674fluid_real_t seconds;675int buffers;676677/* SF2.01 section 8.4.3 # 31, 32, 39, 40678* GEN_KEYTOxxxENVxxx uses key 60 as 'origin'.679* The unit of the generator is timecents per key number.680* If KEYTOxxxENVxxx is 100, a key one octave over key 60 (72)681* will cause (60-72)*100=-1200 timecents of time variation.682* The time is cut in half.683*/684685keysteps = 60.0f - fluid_channel_get_key_pitch(voice->channel, fluid_voice_get_actual_key(voice)) / 100.0f;686timecents = fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * keysteps;687688/* Range checking */689if(is_decay)690{691/* SF 2.01 section 8.1.3 # 28, 36 */692if(timecents > 8000.f)693{694timecents = 8000.f;695}696}697else698{699/* SF 2.01 section 8.1.3 # 27, 35 */700if(timecents > 5000.f)701{702timecents = 5000.f;703}704705/* SF 2.01 section 8.1.2 # 27, 35:706* The most negative number indicates no hold time707*/708if(timecents <= -32768.f)709{710return 0;711}712}713714/* SF 2.01 section 8.1.3 # 27, 28, 35, 36 */715if(timecents < -12000.f)716{717timecents = -12000.f;718}719720seconds = fluid_tc2sec(timecents);721/* Each DSP loop processes FLUID_BUFSIZE samples. */722723/* round to next full number of buffers */724buffers = (int)(((fluid_real_t)voice->output_rate * seconds)725/ (fluid_real_t)FLUID_BUFSIZE726+ 0.5f);727728return buffers;729}730731/*732* The value of a generator (gen) has changed. (The different733* generators are listed in fluidsynth.h, or in SF2.01 page 48-49)734* Now the dependent 'voice' parameters are calculated.735*736* fluid_voice_update_param can be called during the setup of the737* voice (to calculate the initial value for a voice parameter), or738* during its operation (a generator has been changed due to739* real-time parameter modifications like pitch-bend).740*741* Note: The generator holds three values: The base value .val, an742* offset caused by modulators .mod, and an offset caused by the743* NRPN system. fluid_voice_gen_value(voice, generator_enumerator) returns the sum744* of all three.745*/746747/**748* Update all the synthesis parameters which depend on generator \a gen.749*750* @param voice Voice instance751* @param gen Generator id (#fluid_gen_type)752*753* Calling this function is only necessary after changing a generator of an already playing voice.754*/755void756fluid_voice_update_param(fluid_voice_t *voice, int gen)757{758unsigned int count, z;759fluid_real_t x = fluid_voice_gen_value(voice, gen);760761switch(gen)762{763764case GEN_PAN:765case GEN_CUSTOM_BALANCE:766/* range checking is done in the fluid_pan and fluid_balance functions */767voice->pan = fluid_voice_gen_value(voice, GEN_PAN);768voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE);769770/* left amp */771UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0,772fluid_voice_calculate_gain_amplitude(voice,773fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)));774775/* right amp */776UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1,777fluid_voice_calculate_gain_amplitude(voice,778fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)));779break;780781case GEN_ATTENUATION:782voice->attenuation = x;783784/* Range: SF2.01 section 8.1.3 # 48785* Motivation for range checking:786* OHPiano.SF2 sets initial attenuation to a whooping -96 dB */787fluid_clip(voice->attenuation, 0.f, 1440.f);788UPDATE_RVOICE_R1(fluid_rvoice_set_attenuation, voice->attenuation);789break;790791/* The pitch is calculated from three different generators.792* Read comment in fluidsynth.h about GEN_PITCH.793*/794case GEN_PITCH:795case GEN_COARSETUNE:796case GEN_FINETUNE:797/* The testing for allowed range is done in 'fluid_ct2hz' */798voice->pitch = (fluid_voice_gen_value(voice, GEN_PITCH)799+ 100.0f * fluid_voice_gen_value(voice, GEN_COARSETUNE)800+ fluid_voice_gen_value(voice, GEN_FINETUNE));801UPDATE_RVOICE_R1(fluid_rvoice_set_pitch, voice->pitch);802break;803804case GEN_REVERBSEND:805/* The generator unit is 'tenths of a percent'. */806voice->reverb_send = x / 1000.0f;807fluid_clip(voice->reverb_send, 0.f, 1.f);808UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send));809break;810811case GEN_CHORUSSEND:812/* The generator unit is 'tenths of a percent'. */813voice->chorus_send = x / 1000.0f;814fluid_clip(voice->chorus_send, 0.f, 1.f);815UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send));816break;817818case GEN_OVERRIDEROOTKEY:819820/* This is a non-realtime parameter. Therefore the .mod part of the generator821* can be neglected.822* NOTE: origpitch sets MIDI root note while pitchadj is a fine tuning amount823* which offsets the original rate. This means that the fine tuning is824* inverted with respect to the root note (so subtract it, not add).825*/826if(voice->sample != NULL)827{828if(voice->gen[GEN_OVERRIDEROOTKEY].val > -1) //FIXME: use flag instead of -1829{830voice->root_pitch = voice->gen[GEN_OVERRIDEROOTKEY].val * 100.0f831- voice->sample->pitchadj;832}833else834{835voice->root_pitch = voice->sample->origpitch * 100.0f - voice->sample->pitchadj;836}837838x = (fluid_ct2hz_real(voice->root_pitch) * ((fluid_real_t) voice->output_rate / voice->sample->samplerate));839}840else841{842if(voice->gen[GEN_OVERRIDEROOTKEY].val > -1) //FIXME: use flag instead of -1843{844voice->root_pitch = voice->gen[GEN_OVERRIDEROOTKEY].val * 100.0f;845}846else847{848voice->root_pitch = 0;849}850851x = fluid_ct2hz_real(voice->root_pitch);852}853854/* voice->pitch depends on voice->root_pitch, so calculate voice->pitch now */855fluid_voice_calculate_gen_pitch(voice);856UPDATE_RVOICE_R1(fluid_rvoice_set_root_pitch_hz, x);857858break;859860case GEN_FILTERFC:861/* The resonance frequency is converted from absolute cents to862* midicents .val and .mod are both used, this permits real-time863* modulation. The allowed range is tested in the 'fluid_ct2hz'864* function [PH,20021214]865*/866UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_filter, x);867break;868869case GEN_FILTERQ:870UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_filter, x);871break;872873/* same as the two above, only for the custom filter */874case GEN_CUSTOM_FILTERFC:875UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_custom_filter, x);876break;877878case GEN_CUSTOM_FILTERQ:879UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_custom_filter, x);880break;881882case GEN_MODLFOTOPITCH:883fluid_clip(x, -12000.f, 12000.f);884UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_pitch, x);885break;886887case GEN_MODLFOTOVOL:888fluid_clip(x, -960.f, 960.f);889UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_vol, x);890break;891892case GEN_MODLFOTOFILTERFC:893fluid_clip(x, -12000.f, 12000.f);894UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_fc, x);895break;896897case GEN_MODLFODELAY:898fluid_clip(x, -12000.0f, 5000.0f);899z = (unsigned int)(voice->output_rate * fluid_tc2sec_delay(x));900UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, modlfo, z);901break;902903case GEN_MODLFOFREQ:904/* - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples905* - the delay into a sample delay906*/907fluid_clip(x, -16000.0f, 4500.0f);908x = (4.0f * FLUID_BUFSIZE * fluid_ct2hz_real(x) / voice->output_rate);909UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, modlfo, x);910break;911912case GEN_VIBLFOFREQ:913/* vib lfo914*915* - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples916* - the delay into a sample delay917*/918fluid_clip(x, -16000.0f, 4500.0f);919x = 4.0f * FLUID_BUFSIZE * fluid_ct2hz_real(x) / voice->output_rate;920UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, viblfo, x);921break;922923case GEN_VIBLFODELAY:924fluid_clip(x, -12000.0f, 5000.0f);925z = (unsigned int)(voice->output_rate * fluid_tc2sec_delay(x));926UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, viblfo, z);927break;928929case GEN_VIBLFOTOPITCH:930fluid_clip(x, -12000.f, 12000.f);931UPDATE_RVOICE_R1(fluid_rvoice_set_viblfo_to_pitch, x);932break;933934case GEN_KEYNUM:935/* GEN_KEYNUM: SF2.01 page 46, item 46936*937* If this generator is active, it forces the key number to its938* value. Non-realtime controller.939*940* There is a flag, which should indicate, whether a generator is941* enabled or not. But here we rely on the default value of -1.942*/943944/* 2017-09-02: do not change the voice's key here, otherwise it will945* never be released on a noteoff event946*/947#if 0948x = fluid_voice_gen_value(voice, GEN_KEYNUM);949950if(x >= 0)951{952voice->key = x;953}954955#endif956break;957958case GEN_VELOCITY:959/* GEN_VELOCITY: SF2.01 page 46, item 47960*961* If this generator is active, it forces the velocity to its962* value. Non-realtime controller.963*964* There is a flag, which should indicate, whether a generator is965* enabled or not. But here we rely on the default value of -1.966*/967/* 2017-09-02: do not change the voice's velocity here, use968* fluid_voice_get_actual_velocity() to get the value of this generator969* if active.970*/971#if 0972x = fluid_voice_gen_value(voice, GEN_VELOCITY);973974if(x > 0)975{976voice->vel = x;977}978979#endif980break;981982case GEN_MODENVTOPITCH:983fluid_clip(x, -12000.f, 12000.f);984UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_pitch, x);985break;986987case GEN_MODENVTOFILTERFC:988/* Range: SF2.01 section 8.1.3 # 1989* Motivation for range checking:990* Filter is reported to make funny noises now and then991*/992fluid_clip(x, -12000.f, 12000.f);993UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_fc, x);994break;995996997/* sample start and ends points998*999* Range checking is initiated via the1000* voice->check_sample_sanity flag,1001* because it is impossible to check here:1002* During the voice setup, all modulators are processed, while1003* the voice is inactive. Therefore, illegal settings may1004* occur during the setup (for example: First move the loop1005* end point ahead of the loop start point => invalid, then1006* move the loop start point forward => valid again.1007*/1008case GEN_STARTADDROFS: /* SF2.01 section 8.1.3 # 0 */1009case GEN_STARTADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 4 */1010if(voice->sample != NULL)1011{1012fluid_real_t start_fine = fluid_voice_gen_value(voice, GEN_STARTADDROFS);1013fluid_real_t start_coar = fluid_voice_gen_value(voice, GEN_STARTADDRCOARSEOFS);10141015z = voice->sample->start + (int)start_fine + 32768 * (int)start_coar;1016UPDATE_RVOICE_I1(fluid_rvoice_set_start, z);1017}10181019break;10201021case GEN_ENDADDROFS: /* SF2.01 section 8.1.3 # 1 */1022case GEN_ENDADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 12 */1023if(voice->sample != NULL)1024{1025fluid_real_t end_fine = fluid_voice_gen_value(voice, GEN_ENDADDROFS);1026fluid_real_t end_coar = fluid_voice_gen_value(voice, GEN_ENDADDRCOARSEOFS);10271028z = voice->sample->end + (int)end_fine + 32768 * (int)end_coar;1029UPDATE_RVOICE_I1(fluid_rvoice_set_end, z);1030}10311032break;10331034case GEN_STARTLOOPADDROFS: /* SF2.01 section 8.1.3 # 2 */1035case GEN_STARTLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 45 */1036if(voice->sample != NULL)1037{1038fluid_real_t lstart_fine = fluid_voice_gen_value(voice, GEN_STARTLOOPADDROFS);1039fluid_real_t lstart_coar = fluid_voice_gen_value(voice, GEN_STARTLOOPADDRCOARSEOFS);10401041z = voice->sample->loopstart + (int)lstart_fine + 32768 * (int)lstart_coar;1042UPDATE_RVOICE_I1(fluid_rvoice_set_loopstart, z);1043}10441045break;10461047case GEN_ENDLOOPADDROFS: /* SF2.01 section 8.1.3 # 3 */1048case GEN_ENDLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 50 */1049if(voice->sample != NULL)1050{1051fluid_real_t lend_fine = fluid_voice_gen_value(voice, GEN_ENDLOOPADDROFS);1052fluid_real_t lend_coar = fluid_voice_gen_value(voice, GEN_ENDLOOPADDRCOARSEOFS);10531054z = voice->sample->loopend + (int)lend_fine + 32768 * (int)lend_coar;1055UPDATE_RVOICE_I1(fluid_rvoice_set_loopend, z);1056}10571058break;10591060/* Conversion functions differ in range limit */1061#define NUM_BUFFERS_DELAY(_v) (unsigned int) (voice->output_rate * fluid_tc2sec_delay(_v) / FLUID_BUFSIZE)1062#define NUM_BUFFERS_ATTACK(_v) (unsigned int) (voice->output_rate * fluid_tc2sec_attack(_v) / FLUID_BUFSIZE)1063#define NUM_BUFFERS_RELEASE(_v) (unsigned int) (voice->output_rate * fluid_tc2sec_release(_v) / FLUID_BUFSIZE)10641065/* volume envelope1066*1067* - delay and hold times are converted to absolute number of samples1068* - sustain is converted to its absolute value1069* - attack, decay and release are converted to their increment per sample1070*/1071case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */1072fluid_clip(x, -12000.0f, 5000.0f);1073count = NUM_BUFFERS_DELAY(x);1074fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDELAY,1075count, 0.0f, 0.0f, -1.0f, 1.0f);1076break;10771078case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */1079fluid_clip(x, -12000.0f, 8000.0f);1080count = 1 + NUM_BUFFERS_ATTACK(x);1081fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVATTACK,1082count, 1.0f, 1.0f / count, -1.0f, 1.0f);1083break;10841085case GEN_VOLENVHOLD: /* SF2.01 section 8.1.3 # 35 */1086case GEN_KEYTOVOLENVHOLD: /* SF2.01 section 8.1.3 # 39 */1087count = calculate_hold_decay_buffers(voice, GEN_VOLENVHOLD, GEN_KEYTOVOLENVHOLD, 0); /* 0 means: hold */1088fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVHOLD,1089count, 1.0f, 0.0f, -1.0f, 2.0f);1090break;10911092case GEN_VOLENVDECAY: /* SF2.01 section 8.1.3 # 36 */1093case GEN_VOLENVSUSTAIN: /* SF2.01 section 8.1.3 # 37 */1094case GEN_KEYTOVOLENVDECAY: /* SF2.01 section 8.1.3 # 40 */1095x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_VOLENVSUSTAIN);1096fluid_clip(x, 0.0f, 1.0f);1097count = calculate_hold_decay_buffers(voice, GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */1098fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDECAY,1099count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f);1100break;11011102case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */1103fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f);1104count = 1 + NUM_BUFFERS_RELEASE(x);1105fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVRELEASE,1106count, 1.0f, -1.0f / count, 0.0f, 1.0f);1107break;11081109/* Modulation envelope */1110case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */1111fluid_clip(x, -12000.0f, 5000.0f);1112count = NUM_BUFFERS_DELAY(x);1113fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDELAY,1114count, 0.0f, 0.0f, -1.0f, 1.0f);1115break;11161117case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */1118fluid_clip(x, -12000.0f, 8000.0f);1119count = 1 + NUM_BUFFERS_ATTACK(x);1120fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVATTACK,1121count, 1.0f, 1.0f / count, -1.0f, 1.0f);1122break;11231124case GEN_MODENVHOLD: /* SF2.01 section 8.1.3 # 27 */1125case GEN_KEYTOMODENVHOLD: /* SF2.01 section 8.1.3 # 31 */1126count = calculate_hold_decay_buffers(voice, GEN_MODENVHOLD, GEN_KEYTOMODENVHOLD, 0); /* 1 means: hold */1127fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVHOLD,1128count, 1.0f, 0.0f, -1.0f, 2.0f);1129break;11301131case GEN_MODENVDECAY: /* SF 2.01 section 8.1.3 # 28 */1132case GEN_MODENVSUSTAIN: /* SF 2.01 section 8.1.3 # 29 */1133case GEN_KEYTOMODENVDECAY: /* SF 2.01 section 8.1.3 # 32 */1134count = calculate_hold_decay_buffers(voice, GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */1135x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_MODENVSUSTAIN);1136fluid_clip(x, 0.0f, 1.0f);1137fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDECAY,1138count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f);1139break;11401141case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */1142fluid_clip(x, -12000.0f, 8000.0f);1143count = 1 + NUM_BUFFERS_RELEASE(x);1144fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVRELEASE,1145count, 1.0f, -1.0f / count, 0.0f, 2.0f);11461147break;11481149} /* switch gen */1150}11511152/**1153* Recalculate voice parameters for a given control.1154*1155* @param voice the synthesis voice1156* @param cc flag to distinguish between a continuous control and a channel control (pitch bend, ...)1157* @param ctrl the control number:1158* when >=0, only modulators's destination having ctrl as source are updated.1159* when -1, all modulators's destination are updated (regardless of ctrl).1160*1161* In this implementation, I want to make sure that all controllers1162* are event based: the parameter values of the DSP algorithm should1163* only be updates when a controller event arrived and not at every1164* iteration of the audio cycle (which would probably be feasible if1165* the synth was made in silicon).1166*1167* The update is done in two steps:1168*1169* - step 1: first, we look for all the modulators that have the changed1170* controller as a source. This will yield a generator that will be changed1171* because of the controller event.1172*1173* - step 2: For this generator, calculate its new value. This is the1174* sum of its original value plus the values of all the attached modulators.1175* The generator flag is set to indicate the parameters must be updated.1176* This avoid the risk to call 'fluid_voice_update_param' several1177* times for the same generator if several modulators have that generator as1178* destination. So every changed generators are updated only once.1179*/11801181/* bit table for each generator being updated. The bits are packed in variables1182Each variable have NBR_BIT_BY_VAR bits represented by NBR_BIT_BY_VAR_LN2.1183The size of the table is the number of variables: SIZE_UPDATED_GEN_BIT.11841185Note: In this implementation NBR_BIT_BY_VAR_LN2 is set to 5 (convenient for 32 bits cpu)1186but this could be set to 6 for 64 bits cpu.1187*/11881189#define NBR_BIT_BY_VAR_LN2 5 /* for 32 bits variables */1190#define NBR_BIT_BY_VAR (1 << NBR_BIT_BY_VAR_LN2)1191#define NBR_BIT_BY_VAR_ANDMASK (NBR_BIT_BY_VAR - 1)1192#define SIZE_UPDATED_GEN_BIT ((GEN_LAST + NBR_BIT_BY_VAR_ANDMASK) / NBR_BIT_BY_VAR)11931194#define is_gen_updated(bit,gen) (bit[gen >> NBR_BIT_BY_VAR_LN2] & (1 << (gen & NBR_BIT_BY_VAR_ANDMASK)))1195#define set_gen_updated(bit,gen) (bit[gen >> NBR_BIT_BY_VAR_LN2] |= (1 << (gen & NBR_BIT_BY_VAR_ANDMASK)))11961197int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl)1198{1199int i, k;1200fluid_mod_t *mod;1201uint32_t gen;1202fluid_real_t modval;12031204/* Clears registered bits table of updated generators */1205uint32_t updated_gen_bit[SIZE_UPDATED_GEN_BIT] = {0};12061207/* printf("Chan=%d, CC=%d, Src=%d, Val=%d\n", voice->channel->channum, cc, ctrl, val); */12081209for(i = 0; i < voice->mod_count; i++)1210{1211mod = &voice->mod[i];12121213/* step 1: find all the modulators that have the changed controller1214as input source. When ctrl is -1 all modulators destination1215are updated */1216if(ctrl < 0 || fluid_mod_has_source(mod, cc, ctrl))1217{1218gen = fluid_mod_get_dest(mod);12191220/* Skip if this generator has already been updated */1221if(!is_gen_updated(updated_gen_bit, gen))1222{1223modval = 0.0;12241225/* step 2: for every attached modulator, calculate the modulation1226* value for the generator gen */1227for(k = 0; k < voice->mod_count; k++)1228{1229if(fluid_mod_has_dest(&voice->mod[k], gen))1230{1231modval += fluid_mod_get_value(&voice->mod[k], voice);1232}1233}12341235fluid_gen_set_mod(&voice->gen[gen], modval);12361237/* now recalculate the parameter values that are derived from the1238generator */1239fluid_voice_update_param(voice, gen);12401241/* set the bit that indicates this generator is updated */1242set_gen_updated(updated_gen_bit, gen);1243}1244}1245}12461247return FLUID_OK;1248}12491250/**1251* Update all the modulators.1252*1253* This function is called after a ALL_CTRL_OFF MIDI message has been received (CC 121).1254* All destinations of all modulators will be updated.1255*/1256int fluid_voice_modulate_all(fluid_voice_t *voice)1257{1258return fluid_voice_modulate(voice, 0, -1);1259}12601261/* legato update functions --------------------------------------------------*/12621263/* Updates voice portamento parameters1264*1265* @voice voice the synthesis voice1266* @fromkey the beginning pitch of portamento.1267* @tokey the ending pitch of portamento.1268*1269* The function calculates pitch offset and increment, then these parameters1270* are send to the dsp.1271*/1272void fluid_voice_update_portamento(fluid_voice_t *voice, int fromkey, int tokey)12731274{1275fluid_channel_t *channel = voice->channel;12761277/* calculates pitch offset */1278fluid_real_t PitchBeg = fluid_voice_calculate_pitch(voice, fromkey);1279fluid_real_t PitchEnd = fluid_voice_calculate_pitch(voice, tokey);1280fluid_real_t pitchoffset = PitchBeg - PitchEnd;12811282/* Calculates increment countinc */1283/* Increment is function of PortamentoTime (ms)*/1284unsigned int countinc = (unsigned int)(((fluid_real_t)voice->output_rate *12850.001f *1286(fluid_real_t)fluid_channel_portamentotime(channel)) /1287(fluid_real_t)FLUID_BUFSIZE + 0.5f);12881289/* Send portamento parameters to the voice dsp */1290UPDATE_RVOICE_GENERIC_IR(fluid_rvoice_set_portamento, voice->rvoice, countinc, pitchoffset);1291}12921293/*---------------------------------------------------------------*/1294/*legato mode 1: multi_retrigger1295*1296* Modulates all generators dependent of key,vel.1297* Forces the voice envelopes in the attack section (legato mode 1).1298*1299* @voice voice the synthesis voice1300* @tokey the new key to be applied to this voice.1301* @vel the new velocity to be applied to this voice.1302*/1303void fluid_voice_update_multi_retrigger_attack(fluid_voice_t *voice,1304int tokey, int vel)1305{1306voice->key = tokey; /* new note */1307voice->vel = vel; /* new velocity */1308/* Updates generators dependent of velocity */1309/* Modulates GEN_ATTENUATION (and others ) before calling1310fluid_rvoice_multi_retrigger_attack().*/1311fluid_voice_modulate(voice, FALSE, FLUID_MOD_VELOCITY);13121313/* Updates generator dependent of voice->key */1314fluid_voice_update_param(voice, GEN_KEYTOMODENVHOLD);1315fluid_voice_update_param(voice, GEN_KEYTOMODENVDECAY);1316fluid_voice_update_param(voice, GEN_KEYTOVOLENVHOLD);1317fluid_voice_update_param(voice, GEN_KEYTOVOLENVDECAY);13181319/* Updates pitch generator */1320fluid_voice_calculate_gen_pitch(voice);1321fluid_voice_update_param(voice, GEN_PITCH);13221323/* updates adsr generator */1324UPDATE_RVOICE0(fluid_rvoice_multi_retrigger_attack);1325}1326/** end of legato update functions */13271328/*1329Force the voice into release stage. Useful anywhere a voice1330needs to be damped even if pedals (sustain sostenuto) are depressed.1331See fluid_synth_damp_voices_by_sustain_LOCAL(),1332fluid_synth_damp_voices_by_sostenuto_LOCAL,1333fluid_voice_noteoff().1334*/1335void1336fluid_voice_release(fluid_voice_t *voice)1337{1338unsigned int at_tick = fluid_channel_get_min_note_length_ticks(voice->channel);1339UPDATE_RVOICE_I1(fluid_rvoice_noteoff, at_tick);1340voice->has_noteoff = 1; // voice is marked as noteoff occurred1341}13421343/*1344* fluid_voice_noteoff1345*1346* Sending a noteoff event will advance the envelopes to section 5 (release).1347* The function is convenient for polyphonic or monophonic note1348*/1349void1350fluid_voice_noteoff(fluid_voice_t *voice)1351{1352fluid_channel_t *channel;13531354fluid_profile(FLUID_PROF_VOICE_NOTE, voice->ref, 0, 0);13551356channel = voice->channel;13571358/* Sustain a note under Sostenuto pedal */1359if(fluid_channel_sostenuto(channel) &&1360channel->sostenuto_orderid > voice->id)1361{1362// Sostenuto depressed after note1363voice->status = FLUID_VOICE_HELD_BY_SOSTENUTO;1364}1365/* Or sustain a note under Sustain pedal */1366else if(fluid_channel_sustained(channel))1367{1368voice->status = FLUID_VOICE_SUSTAINED;1369}1370/* Or force the voice to release stage */1371else1372{1373fluid_voice_release(voice);1374}1375}13761377/*1378* fluid_voice_kill_excl1379*1380* Percussion sounds can be mutually exclusive: for example, a 'closed1381* hihat' sound will terminate an 'open hihat' sound ringing at the1382* same time. This behaviour is modeled using 'exclusive classes',1383* turning on a voice with an exclusive class other than 0 will kill1384* all other voices having that exclusive class within the same preset1385* or channel. fluid_voice_kill_excl gets called, when 'voice' is to1386* be killed for that reason.1387*/13881389int1390fluid_voice_kill_excl(fluid_voice_t *voice)1391{13921393unsigned int at_tick;13941395if(!fluid_voice_is_playing(voice))1396{1397return FLUID_OK;1398}13991400/* Turn off the exclusive class information for this voice,1401so that it doesn't get killed twice1402*/1403fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, 0);14041405/* Speed up the volume envelope */1406/* The value was found through listening tests with hi-hat samples. */1407fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, -200);1408fluid_voice_update_param(voice, GEN_VOLENVRELEASE);14091410/* Speed up the modulation envelope */1411fluid_voice_gen_set(voice, GEN_MODENVRELEASE, -200);1412fluid_voice_update_param(voice, GEN_MODENVRELEASE);14131414at_tick = fluid_channel_get_min_note_length_ticks(voice->channel);1415UPDATE_RVOICE_I1(fluid_rvoice_noteoff, at_tick);141614171418return FLUID_OK;1419}14201421/*1422* Unlock the overflow rvoice of the voice.1423* Decrement the reference count of the sample owned by this rvoice.1424*1425* Called by fluid_synth when the overflow rvoice has finished by itself.1426* Must be called also explicitly at synth destruction to ensure that1427* the soundfont be unloaded successfully.1428*/1429void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice)1430{1431voice->can_access_overflow_rvoice = 1;14321433/* Decrement the reference count of the sample to indicate1434that this sample isn't owned by the rvoice anymore */1435fluid_voice_sample_unref(&voice->overflow_sample);1436}14371438/*1439* fluid_voice_off1440*1441* Force the voice into finished stage. Useful anywhere a voice1442* needs to be cancelled from MIDI API.1443*/1444void fluid_voice_off(fluid_voice_t *voice)1445{1446UPDATE_RVOICE0(fluid_rvoice_voiceoff); /* request to finish the voice */1447}14481449/*1450* fluid_voice_stop1451*1452* Purpose:1453* Turns off a voice, meaning that it is not processed anymore by the1454* DSP loop, i.e. contrary part to fluid_voice_start().1455*/1456void1457fluid_voice_stop(fluid_voice_t *voice)1458{1459fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref, 0, 0);14601461voice->chan = NO_CHANNEL;14621463/* Decrement the reference count of the sample, to indicate1464that this sample isn't owned by the rvoice anymore.1465*/1466fluid_voice_sample_unref(&voice->sample);14671468voice->status = FLUID_VOICE_OFF;1469voice->has_noteoff = 1;14701471/* Decrement voice count */1472voice->channel->synth->active_voice_count--;1473}14741475/**1476* Adds a modulator to the voice if the modulator has valid sources.1477*1478* @param voice Voice instance.1479* @param mod Modulator info (copied).1480* @param mode Determines how to handle an existing identical modulator.1481* #FLUID_VOICE_ADD to add (offset) the modulator amounts,1482* #FLUID_VOICE_OVERWRITE to replace the modulator,1483* #FLUID_VOICE_DEFAULT when adding a default modulator - no duplicate should1484* exist so don't check.1485*/1486void1487fluid_voice_add_mod(fluid_voice_t *voice, fluid_mod_t *mod, int mode)1488{1489/* Ignore the modulator if its sources inputs are invalid */1490if(fluid_mod_check_sources(mod, "api fluid_voice_add_mod mod"))1491{1492fluid_voice_add_mod_local(voice, mod, mode, FLUID_NUM_MOD);1493}1494}14951496/**1497* Adds a modulator to the voice.1498* local version of fluid_voice_add_mod function. Called at noteon time.1499* @param voice, mod, mode, same as for fluid_voice_add_mod() (see above).1500* @param check_limit_count is the modulator number limit to handle with existing1501* identical modulator(i.e mode FLUID_VOICE_OVERWRITE, FLUID_VOICE_ADD).1502* - When FLUID_NUM_MOD, all the voices modulators (since the previous call)1503* are checked for identity.1504* - When check_count_limit is below the actual number of voices modulators1505* (voice->mod_count), this will restrict identity check to this number,1506* This is useful when we know by advance that there is no duplicate with1507* modulators at index above this limit. This avoid wasting cpu cycles at noteon.1508*/1509void1510fluid_voice_add_mod_local(fluid_voice_t *voice, fluid_mod_t *mod, int mode, int check_limit_count)1511{1512int i;15131514/* check_limit_count cannot be above voice->mod_count */1515if(check_limit_count > voice->mod_count)1516{1517check_limit_count = voice->mod_count;1518}15191520if(mode == FLUID_VOICE_ADD)1521{15221523/* if identical modulator exists, add them */1524for(i = 0; i < check_limit_count; i++)1525{1526if(fluid_mod_test_identity(&voice->mod[i], mod))1527{1528// printf("Adding modulator...\n");1529voice->mod[i].amount += mod->amount;1530return;1531}1532}15331534}1535else if(mode == FLUID_VOICE_OVERWRITE)1536{15371538/* if identical modulator exists, replace it (only the amount has to be changed) */1539for(i = 0; i < check_limit_count; i++)1540{1541if(fluid_mod_test_identity(&voice->mod[i], mod))1542{1543// printf("Replacing modulator...amount is %f\n",mod->amount);1544voice->mod[i].amount = mod->amount;1545return;1546}1547}1548}15491550/* Add a new modulator (No existing modulator to add / overwrite).1551Also, default modulators (FLUID_VOICE_DEFAULT) are added without1552checking, if the same modulator already exists. */1553if(voice->mod_count < FLUID_NUM_MOD)1554{1555fluid_mod_clone(&voice->mod[voice->mod_count++], mod);1556}1557else1558{1559FLUID_LOG(FLUID_WARN, "Voice %i has more modulators than supported, ignoring.", voice->id);1560}1561}15621563/**1564* Get the unique ID of the noteon-event.1565*1566* @param voice Voice instance1567* @return Note on unique ID1568*1569* A SoundFont loader may store pointers to voices it has created for1570* real-time control during the operation of a voice (for example: parameter1571* changes in SoundFont editor). The synth uses a pool of voices internally which are1572* 'recycled' and never deallocated.1573*1574* However, before modifying an existing voice, check1575* - that its state is still 'playing'1576* - that the ID is still the same1577*1578* Otherwise the voice has finished playing.1579*/1580unsigned int fluid_voice_get_id(const fluid_voice_t *voice)1581{1582return voice->id;1583}15841585/**1586* Check if a voice is producing sound.1587*1588* Like fluid_voice_is_on() this will return TRUE once a call to1589* fluid_synth_start_voice() has been made. Contrary to fluid_voice_is_on(),1590* this might also return TRUE after the voice received a noteoff event, as it may1591* still be playing in release phase, or because it has been sustained or1592* sostenuto'ed.1593*1594* @param voice Voice instance1595* @return TRUE if playing, FALSE otherwise1596*/1597int fluid_voice_is_playing(const fluid_voice_t *voice)1598{1599return (voice->status == FLUID_VOICE_ON)1600|| fluid_voice_is_sustained(voice)1601|| fluid_voice_is_sostenuto(voice);16021603}16041605/**1606* Check if a voice is ON.1607*1608* A voice is in ON state as soon as a call to fluid_synth_start_voice() has been made1609* (which is typically done in a fluid_preset_t's noteon function).1610* A voice stays ON as long as it has not received a noteoff event.1611*1612* @param voice Voice instance1613* @return TRUE if on, FALSE otherwise1614*1615* @since 1.1.71616*/1617int fluid_voice_is_on(const fluid_voice_t *voice)1618{1619return (voice->status == FLUID_VOICE_ON && !voice->has_noteoff);1620}16211622/**1623* Check if a voice keeps playing after it has received a noteoff due to being held by sustain.1624*1625* @param voice Voice instance1626* @return TRUE if sustained, FALSE otherwise1627*1628* @since 1.1.71629*/1630int fluid_voice_is_sustained(const fluid_voice_t *voice)1631{1632return (voice->status == FLUID_VOICE_SUSTAINED);1633}16341635/**1636* Check if a voice keeps playing after it has received a noteoff due to being held by sostenuto.1637*1638* @param voice Voice instance1639* @return TRUE if sostenuto, FALSE otherwise1640*1641* @since 1.1.71642*/1643int fluid_voice_is_sostenuto(const fluid_voice_t *voice)1644{1645return (voice->status == FLUID_VOICE_HELD_BY_SOSTENUTO);1646}16471648/**1649* Return the MIDI channel the voice is playing on.1650*1651* @param voice Voice instance1652* @return The channel assigned to this voice1653*1654* @note The result of this function is only valid if the voice is playing.1655*1656* @since 1.1.71657*/1658int fluid_voice_get_channel(const fluid_voice_t *voice)1659{1660return voice->chan;1661}16621663/**1664* Return the effective MIDI key of the playing voice.1665*1666* @param voice Voice instance1667* @return The MIDI key this voice is playing at1668*1669* If the voice was started from an instrument which uses a fixed key generator, it returns that.1670* Otherwise returns the same value as \c fluid_voice_get_key.1671*1672* @note The result of this function is only valid if the voice is playing.1673*1674* @since 1.1.71675*/1676int fluid_voice_get_actual_key(const fluid_voice_t *voice)1677{1678fluid_real_t x = fluid_voice_gen_value(voice, GEN_KEYNUM);16791680if(x >= 0)1681{1682return (int)x;1683}1684else1685{1686return fluid_voice_get_key(voice);1687}1688}16891690/**1691* Return the MIDI key from the starting noteon event.1692*1693* @param voice Voice instance1694* @return The MIDI key of the noteon event that originally turned on this voice1695*1696* @note The result of this function is only valid if the voice is playing.1697*1698* @since 1.1.71699*/1700int fluid_voice_get_key(const fluid_voice_t *voice)1701{1702return voice->key;1703}17041705/**1706* Return the effective MIDI velocity of the playing voice.1707*1708* @param voice Voice instance1709* @return The MIDI velocity this voice is playing at1710*1711* If the voice was started from an instrument which uses a fixed velocity generator, it returns that.1712* Otherwise it returns the same value as \c fluid_voice_get_velocity.1713*1714* @note The result of this function is only valid if the voice is playing.1715*1716* @since 1.1.71717*/1718int fluid_voice_get_actual_velocity(const fluid_voice_t *voice)1719{1720fluid_real_t x = fluid_voice_gen_value(voice, GEN_VELOCITY);17211722if(x > 0)1723{1724return (int)x;1725}1726else1727{1728return fluid_voice_get_velocity(voice);1729}1730}17311732/**1733* Return the MIDI velocity from the starting noteon event.1734*1735* @param voice Voice instance1736* @return The MIDI velocity which originally turned on this voice1737*1738* @note The result of this function is only valid if the voice is playing.1739*1740* @since 1.1.71741*/1742int fluid_voice_get_velocity(const fluid_voice_t *voice)1743{1744return voice->vel;1745}17461747/*1748* fluid_voice_get_lower_boundary_for_attenuation1749*1750* Purpose:1751*1752* A lower boundary for the attenuation (as in 'the minimum1753* attenuation of this voice, with volume pedals, modulators1754* etc. resulting in minimum attenuation, cannot fall below x cB) is1755* calculated. This has to be called during fluid_voice_start, after1756* all modulators have been run on the voice once. Also,1757* voice->attenuation has to be initialized.1758* (see fluid_voice_calculate_runtime_synthesis_parameters())1759*/1760static fluid_real_t1761fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice)1762{1763int i;1764fluid_mod_t *mod;1765fluid_real_t possible_att_reduction_cB = 0;1766fluid_real_t lower_bound;17671768for(i = 0; i < voice->mod_count; i++)1769{1770mod = &voice->mod[i];17711772/* Modulator has attenuation as target and can change over time? */1773if((mod->dest == GEN_ATTENUATION)1774&& ((mod->flags1 & FLUID_MOD_CC)1775|| (mod->flags2 & FLUID_MOD_CC)1776|| (mod->src1 == FLUID_MOD_CHANNELPRESSURE)1777|| (mod->src1 == FLUID_MOD_KEYPRESSURE)1778|| (mod->src1 == FLUID_MOD_PITCHWHEEL)1779|| (mod->src2 == FLUID_MOD_CHANNELPRESSURE)1780|| (mod->src2 == FLUID_MOD_KEYPRESSURE)1781|| (mod->src2 == FLUID_MOD_PITCHWHEEL)))1782{17831784fluid_real_t current_val = fluid_mod_get_value(mod, voice);1785/* min_val is the possible minimum value for this modulator.1786it depends of 3 things :17871)the minimum values of src1,src2 (i.e -1 if mapping is bipolar1788or 0 if mapping is unipolar).17892)the sign of amount.17903)absolute value of amount.17911792When at least one source mapping is bipolar:1793min_val is -|amount| regardless the sign of amount.1794When both sources mapping are unipolar:1795min_val is -|amount|, if amount is negative.1796min_val is 0, if amount is positive1797*/1798fluid_real_t min_val = fabs(mod->amount);17991800/* Can this modulator produce a negative contribution? */1801if((mod->flags1 & FLUID_MOD_BIPOLAR)1802|| (mod->flags2 & FLUID_MOD_BIPOLAR)1803|| (mod->amount < 0))1804{1805min_val = -min_val; /* min_val = - |amount|*/1806}1807else1808{1809/* No negative value possible. But still, the minimum contribution is 0. */1810min_val = 0;1811}18121813/* For example:1814* - current_val=1001815* - min_val=-40001816* - possible reduction contribution of this modulator = current_val - min_val = 41001817*/1818if(current_val > min_val)1819{1820possible_att_reduction_cB += (current_val - min_val);1821}1822}1823}18241825lower_bound = voice->attenuation - possible_att_reduction_cB;18261827/* SF2.01 specs do not allow negative attenuation */1828if(lower_bound < 0)1829{1830lower_bound = 0;1831}18321833return lower_bound;1834}18351836int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t nrpn_value)1837{1838voice->gen[gen].nrpn = nrpn_value;1839voice->gen[gen].flags = GEN_SET;1840fluid_voice_update_param(voice, gen);1841return FLUID_OK;1842}18431844int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain)1845{1846fluid_real_t left, right, reverb, chorus;18471848/* avoid division by zero*/1849if(gain < 0.0000001f)1850{1851gain = 0.0000001f;1852}18531854voice->synth_gain = gain;1855left = fluid_voice_calculate_gain_amplitude(voice,1856fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1));1857right = fluid_voice_calculate_gain_amplitude(voice,1858fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0));1859reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send);1860chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send);18611862UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain);1863UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, left);1864UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, right);1865UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, reverb);1866UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, chorus);18671868return FLUID_OK;1869}18701871/* - Scan the loop1872* - determine the peak level1873* - Calculate, what factor will make the loop inaudible1874* - Store in sample1875*/18761877/**1878* Calculate the peak volume of a sample for voice off optimization.1879*1880* @param s Sample to optimize1881* @return #FLUID_OK on success, #FLUID_FAILED otherwise1882*1883* If the peak volume during the loop is known, then the voice can1884* be released earlier during the release phase. Otherwise, the1885* voice will operate (inaudibly), until the envelope is at the1886* nominal turnoff point. So it's a good idea to call1887* fluid_voice_optimize_sample() on each sample once.1888*/1889int1890fluid_voice_optimize_sample(fluid_sample_t *s)1891{1892int32_t peak_max = 0;1893int32_t peak_min = 0;1894int32_t peak;1895fluid_real_t normalized_amplitude_during_loop;1896double result;1897unsigned int i;18981899/* ignore disabled samples */1900if(s->start == s->end)1901{1902return (FLUID_OK);1903}19041905if(!s->amplitude_that_reaches_noise_floor_is_valid) /* Only once */1906{1907/* Scan the loop */1908for(i = s->loopstart; i < s->loopend; i++)1909{1910int32_t val = fluid_rvoice_get_sample(s->data, s->data24, i);19111912if(val > peak_max)1913{1914peak_max = val;1915}1916else if(val < peak_min)1917{1918peak_min = val;1919}1920}19211922/* Determine the peak level */1923if(peak_max > -peak_min)1924{1925peak = peak_max;1926}1927else1928{1929peak = -peak_min;1930}19311932if(peak == 0)1933{1934/* Avoid division by zero */1935peak = 1;1936}19371938/* Calculate what factor will make the loop inaudible1939* For example: Take a peak of 3277 (10 % of 32768). The1940* normalized amplitude is 0.1 (10 % of 32768). An amplitude1941* factor of 0.0001 (as opposed to the default 0.00001) will1942* drop this sample to the noise floor.1943*/19441945/* 16 bits => 96+4=100 dB dynamic range => 0.00001 */1946normalized_amplitude_during_loop = ((fluid_real_t)peak) / (INT24_MAX * 1.0f);1947result = FLUID_NOISE_FLOOR / normalized_amplitude_during_loop;19481949/* Store in sample */1950s->amplitude_that_reaches_noise_floor = (double)result;1951s->amplitude_that_reaches_noise_floor_is_valid = 1;1952#if 01953printf("Sample peak detection: factor %f\n", (double)result);1954#endif1955}19561957return FLUID_OK;1958}19591960float1961fluid_voice_get_overflow_prio(fluid_voice_t *voice,1962fluid_overflow_prio_t *score,1963unsigned int cur_time)1964{1965float this_voice_prio = 0;1966int channel;19671968/* Are we already overflowing? */1969if(!voice->can_access_overflow_rvoice)1970{1971return OVERFLOW_PRIO_CANNOT_KILL;1972}19731974/* Is this voice on the drum channel?1975* Then it is very important.1976* Also skip the released and sustained scores.1977*/1978if(voice->channel->channel_type == CHANNEL_TYPE_DRUM)1979{1980this_voice_prio += score->percussion;1981}1982else if(voice->has_noteoff)1983{1984/* Noteoff has */1985this_voice_prio += score->released;1986}1987else if(fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice))1988{1989/* This voice is still active, since the sustain pedal is held down.1990* Consider it less important than non-sustained channels.1991* This decision is somehow subjective. But usually the sustain pedal1992* is used to play 'more-voices-than-fingers', so it shouldn't hurt1993* if we kill one voice.1994*/1995this_voice_prio += score->sustained;1996}19971998/* We are not enthusiastic about releasing voices, which have just been started.1999* Otherwise hitting a chord may result in killing notes belonging to that very same2000* chord. So give newer voices a higher score. */2001if(score->age)2002{2003cur_time -= voice->start_time;20042005if(cur_time < 1)2006{2007cur_time = 1; // Avoid div by zero2008}20092010this_voice_prio += (score->age * voice->output_rate) / cur_time;2011}20122013/* take a rough estimate of loudness into account. Louder voices are more important. */2014if(score->volume)2015{2016fluid_real_t a = voice->attenuation;20172018if(voice->has_noteoff)2019{2020// FIXME: Should take into account where on the envelope we are...?2021}20222023if(a < 0.1f)2024{2025a = 0.1f; // Avoid div by zero2026}20272028this_voice_prio += score->volume / a;2029}20302031/* Check if this voice is on an important channel. If so, then add the2032* score for important channels */2033channel = fluid_voice_get_channel(voice);20342035if(channel < score->num_important_channels && score->important_channels[channel])2036{2037this_voice_prio += score->important;2038}20392040return this_voice_prio;2041}204220432044void fluid_voice_set_custom_filter(fluid_voice_t *voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags)2045{2046UPDATE_RVOICE_GENERIC_I2(fluid_iir_filter_init, &voice->rvoice->resonant_custom_filter, type, flags);2047}204820492050