1a790cfbfbd3946170efc43d64781333652b54eb
[ardour.git] / libs / fluidsynth / src / fluid_conv.c
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 Library General Public License
7  * as published by the Free Software Foundation; either version 2 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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
23
24 /* conversion tables */
25 fluid_real_t fluid_ct2hz_tab[FLUID_CENTS_HZ_SIZE];
26 fluid_real_t fluid_cb2amp_tab[FLUID_CB_AMP_SIZE];
27 fluid_real_t fluid_atten2amp_tab[FLUID_ATTEN_AMP_SIZE];
28 fluid_real_t fluid_posbp_tab[128];
29 fluid_real_t fluid_concave_tab[128];
30 fluid_real_t fluid_convex_tab[128];
31 fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE];
32
33 /*
34  * void fluid_synth_init
35  *
36  * Does all the initialization for this module.
37  */
38 void
39 fluid_conversion_config(void)
40 {
41   int i;
42   double x;
43
44   for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) {
45     fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0);
46   }
47
48   /* centibels to amplitude conversion
49    * Note: SF2.01 section 8.1.3: Initial attenuation range is
50    * between 0 and 144 dB. Therefore a negative attenuation is
51    * not allowed.
52    */
53   for (i = 0; i < FLUID_CB_AMP_SIZE; i++) {
54     fluid_cb2amp_tab[i] = (fluid_real_t) pow(10.0, (double) i / -200.0);
55   }
56
57   /* NOTE: EMU8k and EMU10k devices don't conform to the SoundFont
58    * specification in regards to volume attenuation.  The below calculation
59    * is an approx. equation for generating a table equivelant to the
60    * cb_to_amp_table[] in tables.c of the TiMidity++ source, which I'm told
61    * was generated from device testing.  By the spec this should be centibels.
62    */
63   for (i = 0; i < FLUID_ATTEN_AMP_SIZE; i++) {
64     fluid_atten2amp_tab[i] = (fluid_real_t) pow(10.0, (double) i / FLUID_ATTEN_POWER_FACTOR);
65   }
66
67   /* initialize the conversion tables (see fluid_mod.c
68      fluid_mod_get_value cases 4 and 8) */
69
70   /* concave unipolar positive transform curve */
71   fluid_concave_tab[0] = 0.0;
72   fluid_concave_tab[127] = 1.0;
73
74   /* convex unipolar positive transform curve */
75   fluid_convex_tab[0] = 0;
76   fluid_convex_tab[127] = 1.0;
77   x = log10(128.0 / 127.0);
78
79   /* There seems to be an error in the specs. The equations are
80      implemented according to the pictures on SF2.01 page 73. */
81
82   for (i = 1; i < 127; i++) {
83     x = -20.0 / 96.0 * log((i * i) / (127.0 * 127.0)) / log(10.0);
84     fluid_convex_tab[i] = (fluid_real_t) (1.0 - x);
85     fluid_concave_tab[127 - i] = (fluid_real_t) x;
86   }
87
88   /* initialize the pan conversion table */
89   x = PI / 2.0 / (FLUID_PAN_SIZE - 1.0);
90   for (i = 0; i < FLUID_PAN_SIZE; i++) {
91     fluid_pan_tab[i] = (fluid_real_t) sin(i * x);
92   }
93 }
94
95 /*
96  * fluid_ct2hz
97  */
98 fluid_real_t
99 fluid_ct2hz_real(fluid_real_t cents)
100 {
101   if (cents < 0)
102     return (fluid_real_t) 1.0;
103   else if (cents < 900) {
104     return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)];
105   } else if (cents < 2100) {
106     return (fluid_real_t) 13.75 * fluid_ct2hz_tab[(int) (cents - 900)];
107   } else if (cents < 3300) {
108     return (fluid_real_t) 27.5 * fluid_ct2hz_tab[(int) (cents - 2100)];
109   } else if (cents < 4500) {
110     return (fluid_real_t) 55.0 * fluid_ct2hz_tab[(int) (cents - 3300)];
111   } else if (cents < 5700) {
112     return (fluid_real_t) 110.0 * fluid_ct2hz_tab[(int) (cents - 4500)];
113   } else if (cents < 6900) {
114     return (fluid_real_t) 220.0 * fluid_ct2hz_tab[(int) (cents - 5700)];
115   } else if (cents < 8100) {
116     return (fluid_real_t) 440.0 * fluid_ct2hz_tab[(int) (cents - 6900)];
117   } else if (cents < 9300) {
118     return (fluid_real_t) 880.0 * fluid_ct2hz_tab[(int) (cents - 8100)];
119   } else if (cents < 10500) {
120     return (fluid_real_t) 1760.0 * fluid_ct2hz_tab[(int) (cents - 9300)];
121   } else if (cents < 11700) {
122     return (fluid_real_t) 3520.0 * fluid_ct2hz_tab[(int) (cents - 10500)];
123   } else if (cents < 12900) {
124     return (fluid_real_t) 7040.0 * fluid_ct2hz_tab[(int) (cents - 11700)];
125   } else if (cents < 14100) {
126     return (fluid_real_t) 14080.0 * fluid_ct2hz_tab[(int) (cents - 12900)];
127   } else {
128     return (fluid_real_t) 1.0; /* some loony trying to make you deaf */
129   }
130 }
131
132 /*
133  * fluid_ct2hz
134  */
135 fluid_real_t
136 fluid_ct2hz(fluid_real_t cents)
137 {
138   /* Filter fc limit: SF2.01 page 48 # 8 */
139   if (cents >= 13500){
140     cents = 13500;             /* 20 kHz */
141   } else if (cents < 1500){
142     cents = 1500;              /* 20 Hz */
143   }
144   return fluid_ct2hz_real(cents);
145 }
146
147 /*
148  * fluid_cb2amp
149  *
150  * in: a value between 0 and 960, 0 is no attenuation
151  * out: a value between 1 and 0
152  */
153 fluid_real_t
154 fluid_cb2amp(fluid_real_t cb)
155 {
156   /*
157    * cb: an attenuation in 'centibels' (1/10 dB)
158    * SF2.01 page 49 # 48 limits it to 144 dB.
159    * 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit.
160    */
161
162   /* minimum attenuation: 0 dB */
163   if (cb < 0) {
164     return 1.0;
165   }
166   if (cb >= FLUID_CB_AMP_SIZE) {
167     return 0.0;
168   }
169   return fluid_cb2amp_tab[(int) cb];
170 }
171
172 /*
173  * fluid_atten2amp
174  *
175  * in: a value between 0 and 1440, 0 is no attenuation
176  * out: a value between 1 and 0
177  *
178  * Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't
179  * follow this.  Thats the reason for separate fluid_cb2amp and fluid_atten2amp.
180  */
181 fluid_real_t
182 fluid_atten2amp(fluid_real_t atten)
183 {
184   if (atten < 0) return 1.0;
185   else if (atten >= FLUID_ATTEN_AMP_SIZE) return 0.0;
186   else return fluid_atten2amp_tab[(int) atten];
187 }
188
189 /*
190  * fluid_tc2sec_delay
191  */
192 fluid_real_t
193 fluid_tc2sec_delay(fluid_real_t tc)
194 {
195   /* SF2.01 section 8.1.2 items 21, 23, 25, 33
196    * SF2.01 section 8.1.3 items 21, 23, 25, 33
197    *
198    * The most negative number indicates a delay of 0. Range is limited
199    * from -12000 to 5000 */
200   if (tc <= -32768.0f) {
201           return (fluid_real_t) 0.0f;
202   };
203   if (tc < -12000.) {
204           tc = (fluid_real_t) -12000.0f;
205   }
206   if (tc > 5000.0f) {
207           tc = (fluid_real_t) 5000.0f;
208   }
209   return (fluid_real_t) pow(2.0, (double) tc / 1200.0);
210 }
211
212 /*
213  * fluid_tc2sec_attack
214  */
215 fluid_real_t
216 fluid_tc2sec_attack(fluid_real_t tc)
217 {
218   /* SF2.01 section 8.1.2 items 26, 34
219    * SF2.01 section 8.1.3 items 26, 34
220    * The most negative number indicates a delay of 0
221    * Range is limited from -12000 to 8000 */
222   if (tc<=-32768.){return (fluid_real_t) 0.0;};
223   if (tc<-12000.){tc=(fluid_real_t) -12000.0;};
224   if (tc>8000.){tc=(fluid_real_t) 8000.0;};
225   return (fluid_real_t) pow(2.0, (double) tc / 1200.0);
226 }
227
228 /*
229  * fluid_tc2sec
230  */
231 fluid_real_t
232 fluid_tc2sec(fluid_real_t tc)
233 {
234   /* No range checking here! */
235   return (fluid_real_t) pow(2.0, (double) tc / 1200.0);
236 }
237
238 /*
239  * fluid_tc2sec_release
240  */
241 fluid_real_t
242 fluid_tc2sec_release(fluid_real_t tc)
243 {
244   /* SF2.01 section 8.1.2 items 30, 38
245    * SF2.01 section 8.1.3 items 30, 38
246    * No 'most negative number' rule here!
247    * Range is limited from -12000 to 8000 */
248   if (tc<=-32768.){return (fluid_real_t) 0.0;};
249   if (tc<-12000.){tc=(fluid_real_t) -12000.0;};
250   if (tc>8000.){tc=(fluid_real_t) 8000.0;};
251   return (fluid_real_t) pow(2.0, (double) tc / 1200.0);
252 }
253
254 /*
255  * fluid_act2hz
256  *
257  * Convert from absolute cents to Hertz
258  */
259 fluid_real_t
260 fluid_act2hz(fluid_real_t c)
261 {
262   return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0));
263 }
264
265 /*
266  * fluid_hz2ct
267  *
268  * Convert from Hertz to cents
269  */
270 fluid_real_t
271 fluid_hz2ct(fluid_real_t f)
272 {
273   return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / log(2.0));
274 }
275
276 /*
277  * fluid_pan
278  */
279 fluid_real_t
280 fluid_pan(fluid_real_t c, int left)
281 {
282   if (left) {
283     c = -c;
284   }
285   if (c < -500) {
286     return (fluid_real_t) 0.0;
287   } else if (c > 500) {
288     return (fluid_real_t) 1.0;
289   } else {
290     return fluid_pan_tab[(int) (c + 500)];
291   }
292 }
293
294 /*
295  * fluid_concave
296  */
297 fluid_real_t
298 fluid_concave(fluid_real_t val)
299 {
300   if (val < 0) {
301     return 0;
302   } else if (val > 127) {
303     return 1;
304   }
305   return fluid_concave_tab[(int) val];
306 }
307
308 /*
309  * fluid_convex
310  */
311 fluid_real_t
312 fluid_convex(fluid_real_t val)
313 {
314   if (val < 0) {
315     return 0;
316   } else if (val > 127) {
317     return 1;
318   }
319   return fluid_convex_tab[(int) val];
320 }