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 #include "fluid_conv.h"
22 #include "fluid_sys.h"
23 #include "fluid_conv_tables.c"
24
25 /*
26 * Converts absolute cents to Hertz
27 *
28 * As per sfspec section 9.3:
29 *
30 * ABSOLUTE CENTS - An absolute logarithmic measure of frequency based on a
31 * reference of MIDI key number scaled by 100.
32 * A cent is 1/1200 of an octave [which is the twelve hundredth root of two],
33 * and value 6900 is 440 Hz (A-440).
34 *
35 * Implemented below basically is the following:
36 * 440 * 2^((cents-6900)/1200)
37 * = 440 * 2^((int)((cents-6900)/1200)) * 2^(((int)cents-6900)%1200))
38 * = 2^((int)((cents-6900)/1200)) * (440 * 2^(((int)cents-6900)%1200)))
39 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40 * This second factor is stored in the lookup table.
41 *
42 * The first factor can be implemented with a fast shift when the exponent
43 * is always an int. This is the case when using 440/2^6 Hz rather than 440Hz
44 * reference.
45 */
46 fluid_real_t
fluid_ct2hz_real(fluid_real_t cents)47 fluid_ct2hz_real(fluid_real_t cents)
48 {
49 if(FLUID_UNLIKELY(cents < 0))
50 {
51 return (fluid_real_t) 1.0;
52 }
53 else
54 {
55 unsigned int mult, fac, rem;
56 unsigned int icents = (unsigned int)cents;
57 icents += 300u;
58
59 // don't use stdlib div() here, it turned out have poor performance
60 fac = icents / 1200u;
61 rem = icents % 1200u;
62
63 // Think of "mult" as the factor that we multiply (440/2^6)Hz with,
64 // or in other words mult is the "first factor" of the above
65 // functions comment.
66 //
67 // Assuming sizeof(uint)==4 this will give us a maximum range of
68 // 32 * 1200cents - 300cents == 38100 cents == 29,527,900,160 Hz
69 // which is much more than ever needed. For bigger values, just
70 // safely wrap around (the & is just a replacement for the quick
71 // modulo operation % 32).
72 mult = 1u << (fac & (sizeof(mult)*8u - 1u));
73
74 // don't use ldexp() either (poor performance)
75 return mult * fluid_ct2hz_tab[rem];
76 }
77 }
78
79 /*
80 * fluid_ct2hz
81 */
82 fluid_real_t
fluid_ct2hz(fluid_real_t cents)83 fluid_ct2hz(fluid_real_t cents)
84 {
85 /* Filter fc limit: SF2.01 page 48 # 8 */
86 if(cents >= 13500)
87 {
88 cents = 13500; /* 20 kHz */
89 }
90 else if(cents < 1500)
91 {
92 cents = 1500; /* 20 Hz */
93 }
94
95 return fluid_ct2hz_real(cents);
96 }
97
98 /*
99 * fluid_cb2amp
100 *
101 * in: a value between 0 and 1440, 0 is no attenuation
102 * out: a value between 1 and 0
103 */
104 fluid_real_t
fluid_cb2amp(fluid_real_t cb)105 fluid_cb2amp(fluid_real_t cb)
106 {
107 /*
108 * cb: an attenuation in 'centibels' (1/10 dB)
109 * SF2.01 page 49 # 48 limits it to 144 dB.
110 * 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit.
111 */
112
113 /* minimum attenuation: 0 dB */
114 if(cb < 0)
115 {
116 return 1.0;
117 }
118
119 if(cb >= FLUID_CB_AMP_SIZE)
120 {
121 return 0.0;
122 }
123
124 return fluid_cb2amp_tab[(int) cb];
125 }
126
127 /*
128 * fluid_tc2sec_delay
129 */
130 fluid_real_t
fluid_tc2sec_delay(fluid_real_t tc)131 fluid_tc2sec_delay(fluid_real_t tc)
132 {
133 /* SF2.01 section 8.1.2 items 21, 23, 25, 33
134 * SF2.01 section 8.1.3 items 21, 23, 25, 33
135 *
136 * The most negative number indicates a delay of 0. Range is limited
137 * from -12000 to 5000 */
138 if(tc <= -32768.0f)
139 {
140 return (fluid_real_t) 0.0f;
141 };
142
143 if(tc < -12000.f)
144 {
145 tc = (fluid_real_t) -12000.0f;
146 }
147
148 if(tc > 5000.0f)
149 {
150 tc = (fluid_real_t) 5000.0f;
151 }
152
153 return FLUID_POW(2.f, tc / 1200.f);
154 }
155
156 /*
157 * fluid_tc2sec_attack
158 */
159 fluid_real_t
fluid_tc2sec_attack(fluid_real_t tc)160 fluid_tc2sec_attack(fluid_real_t tc)
161 {
162 /* SF2.01 section 8.1.2 items 26, 34
163 * SF2.01 section 8.1.3 items 26, 34
164 * The most negative number indicates a delay of 0
165 * Range is limited from -12000 to 8000 */
166 if(tc <= -32768.f)
167 {
168 return (fluid_real_t) 0.f;
169 };
170
171 if(tc < -12000.f)
172 {
173 tc = (fluid_real_t) -12000.f;
174 };
175
176 if(tc > 8000.f)
177 {
178 tc = (fluid_real_t) 8000.f;
179 };
180
181 return FLUID_POW(2.f, tc / 1200.f);
182 }
183
184 /*
185 * fluid_tc2sec
186 */
187 fluid_real_t
fluid_tc2sec(fluid_real_t tc)188 fluid_tc2sec(fluid_real_t tc)
189 {
190 /* No range checking here! */
191 return FLUID_POW(2.f, tc / 1200.f);
192 }
193
194 /*
195 * fluid_tc2sec_release
196 */
197 fluid_real_t
fluid_tc2sec_release(fluid_real_t tc)198 fluid_tc2sec_release(fluid_real_t tc)
199 {
200 /* SF2.01 section 8.1.2 items 30, 38
201 * SF2.01 section 8.1.3 items 30, 38
202 * No 'most negative number' rule here!
203 * Range is limited from -12000 to 8000 */
204 if(tc <= -32768.f)
205 {
206 return (fluid_real_t) 0.f;
207 };
208
209 if(tc < -12000.f)
210 {
211 tc = (fluid_real_t) -12000.f;
212 };
213
214 if(tc > 8000.f)
215 {
216 tc = (fluid_real_t) 8000.f;
217 };
218
219 return FLUID_POW(2.f, tc / 1200.f);
220 }
221
222 /*
223 * fluid_act2hz
224 *
225 * Convert from absolute cents to Hertz
226 *
227 * The inverse operation, converting from Hertz to cents, was unused and implemented as
228 *
229 fluid_hz2ct(fluid_real_t f)
230 {
231 return 6900.f + (1200.f / FLUID_M_LN2) * FLUID_LOGF(f / 440.0f));
232 }
233 */
234 fluid_real_t
fluid_act2hz(fluid_real_t c)235 fluid_act2hz(fluid_real_t c)
236 {
237 return 8.176f * FLUID_POW(2.f, c / 1200.f);
238 }
239
240 /*
241 * fluid_pan
242 */
243 fluid_real_t
fluid_pan(fluid_real_t c,int left)244 fluid_pan(fluid_real_t c, int left)
245 {
246 if(left)
247 {
248 c = -c;
249 }
250
251 if(c <= -500.f)
252 {
253 return (fluid_real_t) 0.f;
254 }
255 else if(c >= 500.f)
256 {
257 return (fluid_real_t) 1.f;
258 }
259 else
260 {
261 return fluid_pan_tab[(int)(c) + 500];
262 }
263 }
264
265 /*
266 * Return the amount of attenuation based on the balance for the specified
267 * channel. If balance is negative (turned toward left channel, only the right
268 * channel is attenuated. If balance is positive, only the left channel is
269 * attenuated.
270 *
271 * @params balance left/right balance, range [-960;960] in absolute centibels
272 * @return amount of attenuation [0.0;1.0]
273 */
fluid_balance(fluid_real_t balance,int left)274 fluid_real_t fluid_balance(fluid_real_t balance, int left)
275 {
276 /* This is the most common case */
277 if(balance == 0.f)
278 {
279 return 1.0f;
280 }
281
282 if((left && balance < 0.f) || (!left && balance > 0.f))
283 {
284 return 1.0f;
285 }
286
287 if(balance < 0.f)
288 {
289 balance = -balance;
290 }
291
292 return fluid_cb2amp(balance);
293 }
294
295 /*
296 * fluid_concave
297 */
298 fluid_real_t
fluid_concave(fluid_real_t val)299 fluid_concave(fluid_real_t val)
300 {
301 if(val < 0.f)
302 {
303 return 0.f;
304 }
305 else if(val >= (fluid_real_t)FLUID_VEL_CB_SIZE)
306 {
307 return 1.f;
308 }
309
310 return fluid_concave_tab[(int) val];
311 }
312
313 /*
314 * fluid_convex
315 */
316 fluid_real_t
fluid_convex(fluid_real_t val)317 fluid_convex(fluid_real_t val)
318 {
319 if(val < 0.f)
320 {
321 return 0.f;
322 }
323 else if(val >= (fluid_real_t)FLUID_VEL_CB_SIZE)
324 {
325 return 1.f;
326 }
327
328 return fluid_convex_tab[(int) val];
329 }
330
331