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 Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1 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  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, 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 #include "fluid_iir_filter.h"
29 #include "fluid_adsr_env.h"
30 #include "fluid_lfo.h"
31 #include "fluid_rvoice.h"
32 #include "fluid_rvoice_event.h"
33 
34 #define NO_CHANNEL             0xff
35 
36 typedef struct _fluid_overflow_prio_t fluid_overflow_prio_t;
37 
38 struct _fluid_overflow_prio_t
39 {
40     float percussion; /**< Is this voice on the drum channel? Then add this score */
41     float released; /**< Is this voice in release stage? Then add this score (usually negative) */
42     float sustained; /**< Is this voice sustained? Then add this score (usually negative) */
43     float volume; /**< Multiply current (or future) volume (a value between 0 and 1) */
44     float age; /**< This score will be divided by the number of seconds the voice has lasted */
45     float important; /**< This score will be added to all important channels */
46     char *important_channels; /**< "important" flags indexed by MIDI channel number */
47     int num_important_channels; /**< Number of elements in the important_channels array */
48 };
49 
50 enum fluid_voice_status
51 {
52     FLUID_VOICE_CLEAN,
53     FLUID_VOICE_ON,
54     FLUID_VOICE_SUSTAINED,         /* Sustained by Sustain pedal */
55     FLUID_VOICE_HELD_BY_SOSTENUTO, /* Sustained by Sostenuto pedal */
56     FLUID_VOICE_OFF
57 };
58 
59 
60 /*
61  * fluid_voice_t
62  */
63 struct _fluid_voice_t
64 {
65     unsigned int id;                /* the id is incremented for every new noteon.
66 					   it's used for noteoff's  */
67     unsigned char status;
68     unsigned char chan;             /* the channel number, quick access for channel messages */
69     unsigned char key;              /* the key of the noteon event, quick access for noteoff */
70     unsigned char vel;              /* the velocity of the noteon event */
71     fluid_channel_t *channel;
72     fluid_rvoice_eventhandler_t *eventhandler;
73     fluid_zone_range_t *zone_range;  /* instrument zone range*/
74     fluid_sample_t *sample;          /* Pointer to sample (dupe in rvoice) */
75     fluid_sample_t *overflow_sample; /* Pointer to sample (dupe in overflow_rvoice) */
76 
77     unsigned int start_time;
78     int mod_count;
79     fluid_mod_t mod[FLUID_NUM_MOD];
80     fluid_gen_t gen[GEN_LAST];
81 
82     /* basic parameters */
83     fluid_real_t output_rate;        /* the sample rate of the synthesizer (dupe in rvoice) */
84 
85     /* basic parameters */
86     fluid_real_t pitch;              /* the pitch in midicents (dupe in rvoice) */
87     fluid_real_t attenuation;        /* the attenuation in centibels (dupe in rvoice) */
88     fluid_real_t root_pitch;
89 
90     /* master gain (dupe in rvoice) */
91     fluid_real_t synth_gain;
92 
93     /* pan */
94     fluid_real_t pan;
95 
96     /* balance */
97     fluid_real_t balance;
98 
99     /* reverb */
100     fluid_real_t reverb_send;
101 
102     /* chorus */
103     fluid_real_t chorus_send;
104 
105     /* rvoice control */
106     fluid_rvoice_t *rvoice;
107     fluid_rvoice_t *overflow_rvoice; /* Used temporarily and only in overflow situations */
108     char can_access_rvoice; /* False if rvoice is being rendered in separate thread */
109     char can_access_overflow_rvoice; /* False if overflow_rvoice is being rendered in separate thread */
110     char has_noteoff; /* Flag set when noteoff has been sent */
111 
112 #ifdef WITH_PROFILING
113     /* for debugging */
114     double ref;
115 #endif
116 };
117 
118 
119 fluid_voice_t *new_fluid_voice(fluid_rvoice_eventhandler_t *handler, fluid_real_t output_rate);
120 void delete_fluid_voice(fluid_voice_t *voice);
121 
122 void fluid_voice_start(fluid_voice_t *voice);
123 void  fluid_voice_calculate_gen_pitch(fluid_voice_t *voice);
124 
125 int fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample,
126                      fluid_zone_range_t *inst_zone_range,
127                      fluid_channel_t *channel, int key, int vel,
128                      unsigned int id, unsigned int time, fluid_real_t gain);
129 
130 int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl);
131 int fluid_voice_modulate_all(fluid_voice_t *voice);
132 
133 /** Set the NRPN value of a generator. */
134 int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t value);
135 
136 
137 /** Set the gain. */
138 int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain);
139 
140 void fluid_voice_set_output_rate(fluid_voice_t *voice, fluid_real_t value);
141 
142 
143 /** Update all the synthesis parameters, which depend on generator
144     'gen'. This is only necessary after changing a generator of an
145     already operating voice.  Most applications will not need this
146     function.*/
147 void fluid_voice_update_param(fluid_voice_t *voice, int gen);
148 
149 /** legato modes */
150 /* force in the attack section for legato mode multi_retrigger: 1 */
151 void fluid_voice_update_multi_retrigger_attack(fluid_voice_t *voice, int tokey, int vel);
152 /* Update portamento parameter */
153 void fluid_voice_update_portamento(fluid_voice_t *voice, int fromkey, int tokey);
154 
155 
156 void fluid_voice_release(fluid_voice_t *voice);
157 void fluid_voice_noteoff(fluid_voice_t *voice);
158 void fluid_voice_off(fluid_voice_t *voice);
159 void fluid_voice_stop(fluid_voice_t *voice);
160 void fluid_voice_add_mod_local(fluid_voice_t *voice, fluid_mod_t *mod, int mode, int check_limit_count);
161 void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice);
162 
163 int fluid_voice_kill_excl(fluid_voice_t *voice);
164 float fluid_voice_get_overflow_prio(fluid_voice_t *voice,
165                                     fluid_overflow_prio_t *score,
166                                     unsigned int cur_time);
167 
168 #define OVERFLOW_PRIO_CANNOT_KILL 999999.
169 
170 /**
171  * Locks the rvoice for rendering, so it can't be modified directly
172  */
173 static FLUID_INLINE void
fluid_voice_lock_rvoice(fluid_voice_t * voice)174 fluid_voice_lock_rvoice(fluid_voice_t *voice)
175 {
176     voice->can_access_rvoice = 0;
177 }
178 
179 /**
180  * Unlocks the rvoice for rendering, so it can be modified directly
181  */
182 static FLUID_INLINE void
fluid_voice_unlock_rvoice(fluid_voice_t * voice)183 fluid_voice_unlock_rvoice(fluid_voice_t *voice)
184 {
185     voice->can_access_rvoice = 1;
186 }
187 
188 #define _AVAILABLE(voice)  ((voice)->can_access_rvoice && \
189  (((voice)->status == FLUID_VOICE_CLEAN) || ((voice)->status == FLUID_VOICE_OFF)))
190 //#define _RELEASED(voice)  ((voice)->chan == NO_CHANNEL)
191 #define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val)
192 
193 
194 fluid_real_t fluid_voice_gen_value(const fluid_voice_t *voice, int num);
195 void fluid_voice_set_custom_filter(fluid_voice_t *voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags);
196 
197 
198 #endif /* _FLUID_VOICE_H */
199