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 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 * 02111-1307, USA
19 */
20
21 #include "conv.h"
22
23 namespace FluidS {
24
25 /* conversion tables */
26 static float fluid_cb2amp_tab[FLUID_CB_AMP_SIZE];
27 static float fluid_atten2amp_tab[FLUID_ATTEN_AMP_SIZE];
28 static float fluid_concave_tab[128];
29 static float fluid_convex_tab[128];
30 static float fluid_pan_tab[FLUID_PAN_SIZE];
31
32 /*
33 * void fluid_synth_init
34 *
35 * Does all the initialization for this module.
36 */
fluid_conversion_config()37 void fluid_conversion_config()
38 {
39 /* centibels to amplitude conversion
40 * Note: SF2.01 section 8.1.3: Initial attenuation range is
41 * between 0 and 144 dB. Therefore a negative attenuation is
42 * not allowed.
43 */
44 for (int i = 0; i < FLUID_CB_AMP_SIZE; i++)
45 fluid_cb2amp_tab[i] = (float) pow(10.0, (double) i / -200.0);
46
47 /* NOTE: EMU8k and EMU10k devices don't conform to the SoundFont
48 * specification in regards to volume attenuation. The below calculation
49 * is an approx. equation for generating a table equivalent to the
50 * cb_to_amp_table[] in tables.c of the TiMidity++ source, which I'm told
51 * was generated from device testing. By the spec this should be centibels.
52 */
53 for (int i = 0; i < FLUID_ATTEN_AMP_SIZE; i++)
54 fluid_atten2amp_tab[i] = (float) pow(10.0, (double) i / FLUID_ATTEN_POWER_FACTOR);
55
56 /* initialize the conversion tables (see fluid_mod.c
57 fluid_mod_get_value cases 4 and 8) */
58
59 /* concave unipolar positive transform curve */
60 fluid_concave_tab[0] = 0.0;
61 fluid_concave_tab[127] = 1.0;
62
63 /* convex unipolar positive transform curve */
64 fluid_convex_tab[0] = 0;
65 fluid_convex_tab[127] = 1.0;
66
67 /* There seems to be an error in the specs. The equations are
68 implemented according to the pictures on SF2.01 page 73. */
69
70 for (int i = 1; i < 127; i++) {
71 double x = -20.0 / 96.0 * log((i * i) / (127.0 * 127.0)) / log(10.0);
72 fluid_convex_tab[i] = (float) (1.0 - x);
73 fluid_concave_tab[127 - i] = (float) x;
74 }
75
76 /* initialize the pan conversion table */
77 double x = M_PI / 2.0 / (FLUID_PAN_SIZE - 1.0);
78 for (int i = 0; i < FLUID_PAN_SIZE; i++)
79 fluid_pan_tab[i] = (float) sin(i * x);
80 }
81
82 /*
83 * fluid_cb2amp
84 *
85 * in: a value between 0 and 960, 0 is no attenuation
86 * out: a value between 1 and 0
87 */
fluid_cb2amp(float cb)88 float fluid_cb2amp(float cb)
89 {
90 /*
91 * cb: an attenuation in 'centibels' (1/10 dB)
92 * SF2.01 page 49 # 48 limits it to 144 dB.
93 * 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit.
94 */
95
96 /* minimum attenuation: 0 dB */
97 if (cb < 0)
98 return 1.0;
99 if (cb >= FLUID_CB_AMP_SIZE)
100 return 0.0;
101 return fluid_cb2amp_tab[(int) cb];
102 }
103
104 /*
105 * fluid_atten2amp
106 *
107 * in: a value between 0 and 1440, 0 is no attenuation
108 * out: a value between 1 and 0
109 *
110 * Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't
111 * follow this. That's the reason for separate fluid_cb2amp and fluid_atten2amp.
112 */
fluid_atten2amp(float atten)113 float fluid_atten2amp(float atten)
114 {
115 if (atten < 0)
116 return 1.0;
117 else if (atten >= FLUID_ATTEN_AMP_SIZE)
118 return 0.0;
119 else
120 return fluid_atten2amp_tab[(int) atten];
121 }
122
123 /*
124 * fluid_tc2sec_delay
125 */
fluid_tc2sec_delay(float tc)126 float fluid_tc2sec_delay(float tc)
127 {
128 /* SF2.01 section 8.1.2 items 21, 23, 25, 33
129 * SF2.01 section 8.1.3 items 21, 23, 25, 33
130 *
131 * The most negative number indicates a delay of 0. Range is limited
132 * from -12000 to 5000
133 */
134 if (tc <= -32768.0f)
135 return (float) 0.0f;
136 if (tc < -12000.)
137 tc = (float) -12000.0f;
138 if (tc > 5000.0f)
139 tc = (float) 5000.0f;
140 return (float) pow(2.0, (double) tc / 1200.0);
141 }
142
143 /*
144 * fluid_tc2sec_attack
145 */
fluid_tc2sec_attack(float tc)146 float fluid_tc2sec_attack(float tc)
147 {
148 /* SF2.01 section 8.1.2 items 26, 34
149 * SF2.01 section 8.1.3 items 26, 34
150 * The most negative number indicates a delay of 0
151 * Range is limited from -12000 to 8000 */
152 if (tc<=-32768.)
153 return (float) 0.0;
154 if (tc<-12000.)
155 tc=(float) -12000.0;
156 if (tc>8000.)
157 tc=(float) 8000.0;
158 return (float) pow(2.0, (double) tc / 1200.0);
159 }
160
161 /*
162 * fluid_tc2sec
163 */
fluid_tc2sec(float tc)164 float fluid_tc2sec(float tc)
165 {
166 /* No range checking here! */
167 return (float) pow(2.0, (double) tc / 1200.0);
168 }
169
170 /*
171 * fluid_tc2sec_release
172 */
fluid_tc2sec_release(float tc)173 float fluid_tc2sec_release(float tc)
174 {
175 /* SF2.01 section 8.1.2 items 30, 38
176 * SF2.01 section 8.1.3 items 30, 38
177 * No 'most negative number' rule here!
178 * Range is limited from -12000 to 8000
179 */
180 if (tc<=-32768.)
181 return (float) 0.0;
182 if (tc<-12000.)
183 tc=(float) -12000.0;
184 if (tc>8000.)
185 tc=(float) 8000.0;
186 return (float) pow(2.0, (double) tc / 1200.0);
187 }
188
189 /*
190 * fluid_act2hz
191 *
192 * Convert from absolute cents to Hertz
193 */
fluid_act2hz(float c)194 float fluid_act2hz(float c)
195 {
196 return (float) (8.176 * pow(2.0, (double) c / 1200.0));
197 }
198
199 /*
200 * fluid_pan
201 */
fluid_pan(float c,int left)202 float fluid_pan(float c, int left)
203 {
204 if (left)
205 c = -c;
206 if (c < -500)
207 return (float) 0.0;
208 else if (c > 500)
209 return (float) 1.0;
210 else
211 return fluid_pan_tab[(int) (c + 500)];
212 }
213
214 /*
215 * fluid_concave
216 */
fluid_concave(float val)217 float fluid_concave(float val)
218 {
219 if (val < 0)
220 return 0;
221 else if (val > 127)
222 return 1;
223 return fluid_concave_tab[(int) val];
224 }
225
226 /*
227 * fluid_convex
228 */
fluid_convex(float val)229 float fluid_convex(float val)
230 {
231 if (val < 0)
232 return 0;
233 else if (val > 127)
234 return 1;
235 return fluid_convex_tab[(int) val];
236 }
237 }
238
239