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 "fluid_conv.h" 22 23 24/* conversion tables */ 25fluid_real_t fluid_ct2hz_tab[FLUID_CENTS_HZ_SIZE]; 26fluid_real_t fluid_cb2amp_tab[FLUID_CB_AMP_SIZE]; 27fluid_real_t fluid_atten2amp_tab[FLUID_ATTEN_AMP_SIZE]; 28fluid_real_t fluid_posbp_tab[128]; 29fluid_real_t fluid_concave_tab[128]; 30fluid_real_t fluid_convex_tab[128]; 31fluid_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 */ 38void 39fluid_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 */ 98fluid_real_t 99fluid_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 */ 135fluid_real_t 136fluid_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 */ 153fluid_real_t 154fluid_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 */ 181fluid_real_t 182fluid_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 */ 192fluid_real_t 193fluid_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 */ 215fluid_real_t 216fluid_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 */ 231fluid_real_t 232fluid_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 */ 241fluid_real_t 242fluid_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 */ 259fluid_real_t 260fluid_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 */ 270fluid_real_t 271fluid_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 */ 279fluid_real_t 280fluid_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 */ 297fluid_real_t 298fluid_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 */ 311fluid_real_t 312fluid_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} 321