Update Fluidsynth to 2.0.1
[ardour.git] / libs / fluidsynth / src / fluid_adsr_env.h
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 #ifndef _FLUID_ADSR_ENVELOPE_H
22 #define _FLUID_ADSR_ENVELOPE_H
23
24 #include "fluidsynth_priv.h"
25 #include "fluid_sys.h"
26
27 /*
28  * envelope data
29  */
30 struct _fluid_env_data_t
31 {
32     unsigned int count;
33     fluid_real_t coeff;
34     fluid_real_t increment;
35     fluid_real_t min;
36     fluid_real_t max;
37 };
38
39 /* Indices for envelope tables */
40 enum fluid_voice_envelope_index_t
41 {
42     FLUID_VOICE_ENVDELAY,
43     FLUID_VOICE_ENVATTACK,
44     FLUID_VOICE_ENVHOLD,
45     FLUID_VOICE_ENVDECAY,
46     FLUID_VOICE_ENVSUSTAIN,
47     FLUID_VOICE_ENVRELEASE,
48     FLUID_VOICE_ENVFINISHED,
49     FLUID_VOICE_ENVLAST
50 };
51
52 typedef enum fluid_voice_envelope_index_t fluid_adsr_env_section_t;
53
54 typedef struct _fluid_adsr_env_t fluid_adsr_env_t;
55
56 struct _fluid_adsr_env_t
57 {
58     fluid_env_data_t data[FLUID_VOICE_ENVLAST];
59     unsigned int count;
60     int section;
61     fluid_real_t val;         /* the current value of the envelope */
62 };
63
64 /* For performance, all functions are inlined */
65
66 static FLUID_INLINE void
67 fluid_adsr_env_calc(fluid_adsr_env_t *env, int is_volenv)
68 {
69     fluid_env_data_t *env_data;
70     fluid_real_t x;
71
72     env_data = &env->data[env->section];
73
74     /* skip to the next section of the envelope if necessary */
75     while(env->count >= env_data->count)
76     {
77         // If we're switching envelope stages from decay to sustain, force the value to be the end value of the previous stage
78         // Hmm, should this only apply to volenv? It was so before refactoring, so keep it for now. [DH]
79         if(env->section == FLUID_VOICE_ENVDECAY && is_volenv)
80         {
81             env->val = env_data->min * env_data->coeff;
82         }
83
84         env_data = &env->data[++env->section];
85         env->count = 0;
86     }
87
88     /* calculate the envelope value and check for valid range */
89     x = env_data->coeff * env->val + env_data->increment;
90
91     if(x < env_data->min)
92     {
93         x = env_data->min;
94         env->section++;
95         env->count = 0;
96     }
97     else if(x > env_data->max)
98     {
99         x = env_data->max;
100         env->section++;
101         env->count = 0;
102     }
103     else
104     {
105         env->count++;
106     }
107
108     env->val = x;
109
110
111 }
112
113 /* This one cannot be inlined since it is referenced in
114    the event queue */
115 DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data);
116
117 static FLUID_INLINE void
118 fluid_adsr_env_reset(fluid_adsr_env_t *env)
119 {
120     env->count = 0;
121     env->section = 0;
122     env->val = 0.0f;
123 }
124
125 static FLUID_INLINE fluid_real_t
126 fluid_adsr_env_get_val(fluid_adsr_env_t *env)
127 {
128     return env->val;
129 }
130
131 static FLUID_INLINE void
132 fluid_adsr_env_set_val(fluid_adsr_env_t *env, fluid_real_t val)
133 {
134     env->val = val;
135 }
136
137 static FLUID_INLINE fluid_adsr_env_section_t
138 fluid_adsr_env_get_section(fluid_adsr_env_t *env)
139 {
140     return env->section;
141 }
142
143 static FLUID_INLINE void
144 fluid_adsr_env_set_section(fluid_adsr_env_t *env,
145                            fluid_adsr_env_section_t section)
146 {
147     env->section = section;
148     env->count = 0;
149 }
150
151 /* Used for determining which voice to kill.
152    Returns max amplitude from now, and forward in time.
153 */
154 static FLUID_INLINE fluid_real_t
155 fluid_adsr_env_get_max_val(fluid_adsr_env_t *env)
156 {
157     if(env->section > FLUID_VOICE_ENVATTACK)
158     {
159         return env->val * 1000;
160     }
161     else
162     {
163         return env->data[FLUID_VOICE_ENVATTACK].max;
164     }
165 }
166
167 #endif
168