Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/rvoice/fluid_adsr_env.h
4396 views
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
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 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
fluid_real_t val; /* the current value of the envelope */
61
fluid_adsr_env_section_t section;
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)
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
// No, must apply to both, otherwise some voices may sound detuned. [TM] (https://github.com/FluidSynth/fluidsynth/issues/1059)
80
if(env->section == FLUID_VOICE_ENVDECAY)
81
{
82
env->val = env_data->min * env_data->coeff;
83
}
84
85
env_data = &env->data[++env->section];
86
env->count = 0;
87
}
88
89
/* calculate the envelope value and check for valid range */
90
x = env_data->coeff * env->val + env_data->increment;
91
92
if(x < env_data->min)
93
{
94
x = env_data->min;
95
env->section++;
96
env->count = 0;
97
}
98
else if(x > env_data->max)
99
{
100
x = env_data->max;
101
env->section++;
102
env->count = 0;
103
}
104
else
105
{
106
env->count++;
107
}
108
109
env->val = x;
110
}
111
112
/* This one cannot be inlined since it is referenced in
113
the event queue */
114
DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data);
115
116
static FLUID_INLINE void
117
fluid_adsr_env_reset(fluid_adsr_env_t *env)
118
{
119
env->count = 0;
120
env->section = FLUID_VOICE_ENVDELAY;
121
env->val = 0.0f;
122
}
123
124
static FLUID_INLINE fluid_real_t
125
fluid_adsr_env_get_val(fluid_adsr_env_t *env)
126
{
127
return env->val;
128
}
129
130
static FLUID_INLINE void
131
fluid_adsr_env_set_val(fluid_adsr_env_t *env, fluid_real_t val)
132
{
133
env->val = val;
134
}
135
136
static FLUID_INLINE fluid_adsr_env_section_t
137
fluid_adsr_env_get_section(fluid_adsr_env_t *env)
138
{
139
return env->section;
140
}
141
142
static FLUID_INLINE void
143
fluid_adsr_env_set_section(fluid_adsr_env_t *env,
144
fluid_adsr_env_section_t section)
145
{
146
env->section = section;
147
env->count = 0;
148
}
149
150
/* Used for determining which voice to kill.
151
Returns max amplitude from now, and forward in time.
152
*/
153
static FLUID_INLINE fluid_real_t
154
fluid_adsr_env_get_max_val(fluid_adsr_env_t *env)
155
{
156
if(env->section > FLUID_VOICE_ENVATTACK)
157
{
158
return env->val * 1000;
159
}
160
else
161
{
162
return env->data[FLUID_VOICE_ENVATTACK].max;
163
}
164
}
165
166
#endif
167
168