Speech bubbles can point down right.
[scummvm-innocent.git] / sound / softsynth / mt32 / tables.cpp
blob571750ee99557be7d37cff5103859d9b4ca7c925
1 /* Copyright (c) 2003-2005 Various contributors
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
26 #include "mt32emu.h"
28 #if defined(MACOSX) || defined(SOLARIS) || defined(__MINGW32__)
29 // Older versions of Mac OS X didn't supply a powf function, so using it
30 // will cause a binary incompatibility when trying to run a binary built
31 // on a newer OS X release on an olderr one. And Solaris 8 doesn't provide
32 // powf, floorf, fabsf etc. at all.
33 // Cross-compiled MinGW32 toolchains suffer from a cross-compile bug in
34 // libstdc++. math/stubs.o should be empty, but it comes with a symbol for
35 // powf, resulting in a linker error because of multiple definitions.
36 // Hence we re-define them here. The only potential drawback is that it
37 // might be a little bit slower this way.
38 #define powf(x,y) ((float)pow(x,y))
39 #define floorf(x) ((float)floor(x))
40 #define fabsf(x) ((float)fabs(x))
41 #endif
43 #define FIXEDPOINT_MAKE(x, point) ((Bit32u)((1 << point) * x))
45 namespace MT32Emu {
47 //Amplitude time velocity follow exponential coefficients
48 static const double tvcatconst[5] = {0.0, 0.002791309, 0.005942882, 0.012652792, 0.026938637};
49 static const double tvcatmult[5] = {1.0, 1.072662811, 1.169129367, 1.288579123, 1.229630539};
51 // These are division constants for the TVF depth key follow
52 static const Bit32u depexp[5] = {3000, 950, 485, 255, 138};
54 //Envelope time keyfollow exponential coefficients
55 static const double tkcatconst[5] = {0.0, 0.005853144, 0.011148054, 0.019086143, 0.043333215};
56 static const double tkcatmult[5] = {1.0, 1.058245688, 1.048488989, 1.016049301, 1.097538067};
58 // Begin filter stuff
60 // Pre-warp the coefficients of a numerator or denominator.
61 // Note that a0 is assumed to be 1, so there is no wrapping
62 // of it.
63 static void prewarp(double *a1, double *a2, double fc, double fs) {
64 double wp;
66 wp = 2.0 * fs * tan(DOUBLE_PI * fc / fs);
68 *a2 = *a2 / (wp * wp);
69 *a1 = *a1 / wp;
72 // Transform the numerator and denominator coefficients
73 // of s-domain biquad section into corresponding
74 // z-domain coefficients.
76 // Store the 4 IIR coefficients in array pointed by coef
77 // in following order:
78 // beta1, beta2 (denominator)
79 // alpha1, alpha2 (numerator)
81 // Arguments:
82 // a0-a2 - s-domain numerator coefficients
83 // b0-b2 - s-domain denominator coefficients
84 // k - filter gain factor. initially set to 1
85 // and modified by each biquad section in such
86 // a way, as to make it the coefficient by
87 // which to multiply the overall filter gain
88 // in order to achieve a desired overall filter gain,
89 // specified in initial value of k.
90 // fs - sampling rate (Hz)
91 // coef - array of z-domain coefficients to be filled in.
93 // Return:
94 // On return, set coef z-domain coefficients
95 static void bilinear(double a0, double a1, double a2, double b0, double b1, double b2, double *k, double fs, float *coef) {
96 double ad, bd;
98 // alpha (Numerator in s-domain)
99 ad = 4. * a2 * fs * fs + 2. * a1 * fs + a0;
100 // beta (Denominator in s-domain)
101 bd = 4. * b2 * fs * fs + 2. * b1* fs + b0;
103 // update gain constant for this section
104 *k *= ad/bd;
106 // Denominator
107 *coef++ = (float)((2. * b0 - 8. * b2 * fs * fs) / bd); // beta1
108 *coef++ = (float)((4. * b2 * fs * fs - 2. * b1 * fs + b0) / bd); // beta2
110 // Nominator
111 *coef++ = (float)((2. * a0 - 8. * a2 * fs * fs) / ad); // alpha1
112 *coef = (float)((4. * a2 * fs * fs - 2. * a1 * fs + a0) / ad); // alpha2
115 // a0-a2: numerator coefficients
116 // b0-b2: denominator coefficients
117 // fc: Filter cutoff frequency
118 // fs: sampling rate
119 // k: overall gain factor
120 // coef: pointer to 4 iir coefficients
121 static void szxform(double *a0, double *a1, double *a2, double *b0, double *b1, double *b2, double fc, double fs, double *k, float *coef) {
122 // Calculate a1 and a2 and overwrite the original values
123 prewarp(a1, a2, fc, fs);
124 prewarp(b1, b2, fc, fs);
125 bilinear(*a0, *a1, *a2, *b0, *b1, *b2, k, fs, coef);
128 static void initFilter(float fs, float fc, float *icoeff, float Q) {
129 float *coef;
130 double a0, a1, a2, b0, b1, b2;
132 double k = 1.5; // Set overall filter gain factor
133 coef = icoeff + 1; // Skip k, or gain
135 // Section 1
136 a0 = 1.0;
137 a1 = 0;
138 a2 = 0;
139 b0 = 1.0;
140 b1 = 0.765367 / Q; // Divide by resonance or Q
141 b2 = 1.0;
142 szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef);
143 coef += 4; // Point to next filter section
145 // Section 2
146 a0 = 1.0;
147 a1 = 0;
148 a2 = 0;
149 b0 = 1.0;
150 b1 = 1.847759 / Q;
151 b2 = 1.0;
152 szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef);
154 icoeff[0] = (float)k;
157 void Tables::initFiltCoeff(float samplerate) {
158 for (int j = 0; j < FILTERGRAN; j++) {
159 for (int res = 0; res < 31; res++) {
160 float tres = resonanceFactor[res];
161 initFilter((float)samplerate, (((float)(j+1.0)/FILTERGRAN)) * ((float)samplerate/2), filtCoeff[j][res], tres);
166 void Tables::initEnvelopes(float samplerate) {
167 for (int lf = 0; lf <= 100; lf++) {
168 float elf = (float)lf;
170 // General envelope
171 // This formula fits observation of the CM-32L by +/- 0.03s or so for the second time value in the filter,
172 // when all other times were 0 and all levels were 100. Note that variations occur depending on the level
173 // delta of the section, which we're not fully emulating.
174 float seconds = powf(2.0f, (elf / 8.0f) + 7.0f) / 32768.0f;
175 int samples = (int)(seconds * samplerate);
176 envTime[lf] = samples;
178 // Cap on envelope times depending on the level delta
179 if (elf == 0) {
180 envDeltaMaxTime[lf] = 63;
181 } else {
182 float cap = 11.0f * (float)log(elf) + 64;
183 if (cap > 100.0f) {
184 cap = 100.0f;
186 envDeltaMaxTime[lf] = (int)cap;
190 // This (approximately) represents the time durations when the target level is 0.
191 // Not sure why this is a special case, but it's seen to be from the real thing.
192 seconds = powf(2, (elf / 8.0f) + 6) / 32768.0f;
193 envDecayTime[lf] = (int)(seconds * samplerate);
195 // I am certain of this: Verified by hand LFO log
196 lfoPeriod[lf] = (Bit32u)(((float)samplerate) / (powf(1.088883372f, (float)lf) * 0.021236044f));
200 void Tables::initMT32ConstantTables(Synth *synth) {
201 int lf;
202 synth->printDebug("Initialising Pitch Tables");
203 for (lf = -108; lf <= 108; lf++) {
204 tvfKeyfollowMult[lf + 108] = (int)(256 * powf(2.0f, (float)(lf / 24.0f)));
205 //synth->printDebug("KT %d = %d", f, keytable[f+108]);
208 for (int res = 0; res < 31; res++) {
209 resonanceFactor[res] = powf((float)res / 30.0f, 5.0f) + 1.0f;
212 int period = 65536;
214 for (int ang = 0; ang < period; ang++) {
215 int halfang = (period / 2);
216 int angval = ang % halfang;
217 float tval = (((float)angval / (float)halfang) - 0.5f) * 2;
218 if (ang >= halfang)
219 tval = -tval;
220 sintable[ang] = (Bit16s)(tval * 50.0f) + 50;
223 int velt, dep;
224 float tempdep;
225 for (velt = 0; velt < 128; velt++) {
226 for (dep = 0; dep < 5; dep++) {
227 if (dep > 0) {
228 float ff = (float)(exp(3.5f * tvcatconst[dep] * (59.0f - (float)velt)) * tvcatmult[dep]);
229 tempdep = 256.0f * ff;
230 envTimeVelfollowMult[dep][velt] = (int)tempdep;
231 //if ((velt % 16) == 0) {
232 // synth->printDebug("Key %d, depth %d, factor %d", velt, dep, (int)tempdep);
234 } else
235 envTimeVelfollowMult[dep][velt] = 256;
238 for (dep = -7; dep < 8; dep++) {
239 float fldep = (float)abs(dep) / 7.0f;
240 fldep = powf(fldep,2.5f);
241 if (dep < 0)
242 fldep = fldep * -1.0f;
243 pwVelfollowAdd[dep+7][velt] = Bit32s((fldep * (float)velt * 100) / 128.0);
247 for (dep = 0; dep <= 100; dep++) {
248 for (velt = 0; velt < 128; velt++) {
249 float fdep = (float)dep * 0.000347013f; // Another MT-32 constant
250 float fv = ((float)velt - 64.0f)/7.26f;
251 float flogdep = powf(10, fdep * fv);
252 float fbase;
254 if (velt > 64)
255 synth->tables.tvfVelfollowMult[velt][dep] = (int)(flogdep * 256.0);
256 else {
257 //lff = 1 - (pow(((128.0 - (float)lf) / 64.0),.25) * ((float)velt / 96));
258 fbase = 1 - (powf(((float)dep / 100.0f),.25f) * ((float)(64-velt) / 96.0f));
259 synth->tables.tvfVelfollowMult[velt][dep] = (int)(fbase * 256.0);
261 //synth->printDebug("Filvel dep %d velt %d = %x", dep, velt, filveltable[velt][dep]);
265 for (lf = 0; lf < 128; lf++) {
266 float veloFract = lf / 127.0f;
267 for (int velsens = 0; velsens <= 100; velsens++) {
268 float sensFract = (velsens - 50) / 50.0f;
269 if (velsens < 50) {
270 tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, veloFract * -sensFract * 127.0f / 20.0f), 8);
271 } else {
272 tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, (1.0f - veloFract) * sensFract * 127.0f / 20.0f), 8);
277 for (lf = 0; lf <= 100; lf++) {
278 // Converts the 0-100 range used by the MT-32 to volume multiplier
279 volumeMult[lf] = FIXEDPOINT_MAKE(powf((float)lf / 100.0f, FLOAT_LN), 7);
282 for (lf = 0; lf <= 100; lf++) {
283 float mv = lf / 100.0f;
284 float pt = mv - 0.5f;
285 if (pt < 0)
286 pt = 0;
288 // Original (CC version)
289 //pwFactor[lf] = (int)(pt * 210.04f) + 128;
291 // Approximation from sample comparison
292 pwFactor[lf] = (int)(pt * 179.0f) + 128;
295 for (unsigned int i = 0; i < MAX_SAMPLE_OUTPUT; i++) {
296 int myRand;
297 myRand = rand();
298 //myRand = ((myRand - 16383) * 7168) >> 16;
299 // This one is slower but works with all values of RAND_MAX
300 myRand = (int)((myRand - RAND_MAX / 2) / (float)RAND_MAX * (7168 / 2));
301 //FIXME:KG: Original ultimately set the lowest two bits to 0, for no obvious reason
302 noiseBuf[i] = (Bit16s)myRand;
305 float tdist;
306 float padjtable[51];
307 for (lf = 0; lf <= 50; lf++) {
308 if (lf == 0)
309 padjtable[lf] = 7;
310 else if (lf == 1)
311 padjtable[lf] = 6;
312 else if (lf == 2)
313 padjtable[lf] = 5;
314 else if (lf == 3)
315 padjtable[lf] = 4;
316 else if (lf == 4)
317 padjtable[lf] = 4 - (0.333333f);
318 else if (lf == 5)
319 padjtable[lf] = 4 - (0.333333f * 2);
320 else if (lf == 6)
321 padjtable[lf] = 3;
322 else if ((lf > 6) && (lf <= 12)) {
323 tdist = (lf-6.0f) / 6.0f;
324 padjtable[lf] = 3.0f - tdist;
325 } else if ((lf > 12) && (lf <= 25)) {
326 tdist = (lf - 12.0f) / 13.0f;
327 padjtable[lf] = 2.0f - tdist;
328 } else {
329 tdist = (lf - 25.0f) / 25.0f;
330 padjtable[lf] = 1.0f - tdist;
332 //synth->printDebug("lf %d = padj %f", lf, padjtable[lf]);
335 float lfp, depf, finalval, tlf;
336 int depat, pval, depti;
337 for (lf = 0; lf <= 10; lf++) {
338 // I believe the depth is cubed or something
340 for (depat = 0; depat <= 100; depat++) {
341 if (lf > 0) {
342 depti = abs(depat - 50);
343 tlf = (float)lf - padjtable[depti];
344 if (tlf < 0)
345 tlf = 0;
346 lfp = (float)exp(0.713619942f * tlf) / 407.4945111f;
348 if (depat < 50)
349 finalval = 4096.0f * powf(2, -lfp);
350 else
351 finalval = 4096.0f * powf(2, lfp);
352 pval = (int)finalval;
354 pitchEnvVal[lf][depat] = pval;
355 //synth->printDebug("lf %d depat %d pval %d tlf %f lfp %f", lf,depat,pval, tlf, lfp);
356 } else {
357 pitchEnvVal[lf][depat] = 4096;
358 //synth->printDebug("lf %d depat %d pval 4096", lf, depat);
362 for (lf = 0; lf <= 100; lf++) {
363 // It's linear - verified on MT-32 - one of the few things linear
364 lfp = ((float)lf * 0.1904f) / 310.55f;
366 for (depat = 0; depat <= 100; depat++) {
367 depf = ((float)depat - 50.0f) / 50.0f;
368 //finalval = pow(2, lfp * depf * .5);
369 finalval = 4096.0f + (4096.0f * lfp * depf);
371 pval = (int)finalval;
373 lfoShift[lf][depat] = pval;
375 //synth->printDebug("lf %d depat %d pval %x", lf,depat,pval);
379 for (lf = 0; lf <= 12; lf++) {
380 for (int distval = 0; distval < 128; distval++) {
381 float amplog, dval;
382 if (lf == 0) {
383 amplog = 0;
384 dval = 1;
385 tvaBiasMult[lf][distval] = 256;
386 } else {
388 amplog = powf(1.431817011f, (float)lf) / FLOAT_PI;
389 dval = ((128.0f - (float)distval) / 128.0f);
390 amplog = exp(amplog);
391 dval = powf(amplog, dval) / amplog;
392 tvaBiasMult[lf][distval] = (int)(dval * 256.0);
394 // Lets assume for a second it's linear
396 // Distance of full volume reduction
397 amplog = (float)(12.0f / (float)lf) * 24.0f;
398 if (distval > amplog) {
399 tvaBiasMult[lf][distval] = 0;
400 } else {
401 dval = (amplog - (float)distval) / amplog;
402 tvaBiasMult[lf][distval] = (int)(dval * 256.0f);
405 //synth->printDebug("Ampbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvaBiasMult[lf][distval],amplog);
409 for (lf = 0; lf <= 14; lf++) {
410 for (int distval = 0; distval < 128; distval++) {
411 float filval = fabsf((float)((lf - 7) * 12) / 7.0f);
412 float amplog, dval;
413 if (lf == 7) {
414 amplog = 0;
415 dval = 1;
416 tvfBiasMult[lf][distval] = 256;
417 } else {
418 //amplog = pow(1.431817011, filval) / FLOAT_PI;
419 amplog = powf(1.531817011f, filval) / FLOAT_PI;
420 dval = (128.0f - (float)distval) / 128.0f;
421 amplog = (float)exp(amplog);
422 dval = powf(amplog,dval)/amplog;
423 if (lf < 8) {
424 tvfBiasMult[lf][distval] = (int)(dval * 256.0f);
425 } else {
426 dval = powf(dval, 0.3333333f);
427 if (dval < 0.01f)
428 dval = 0.01f;
429 dval = 1 / dval;
430 tvfBiasMult[lf][distval] = (int)(dval * 256.0f);
433 //synth->printDebug("Fbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvfBiasMult[lf][distval],amplog);
438 // Per-note table initialisation follows
440 static void initSaw(NoteLookup *noteLookup, Bit32s div2) {
441 int tmpdiv = div2 << 16;
442 for (int rsaw = 0; rsaw <= 100; rsaw++) {
443 float fsaw;
444 if (rsaw < 50)
445 fsaw = 50.0f;
446 else
447 fsaw = (float)rsaw;
449 //(66 - (((A8 - 50) / 50) ^ 0.63) * 50) / 132
450 float sawfact = (66.0f - (powf((fsaw - 50.0f) / 50.0f, 0.63f) * 50.0f)) / 132.0f;
451 noteLookup->sawTable[rsaw] = (int)(sawfact * (float)tmpdiv) >> 16;
452 //synth->printDebug("F %d divtable %d saw %d sawtable %d", f, div, rsaw, sawtable[f][rsaw]);
456 static void initDep(KeyLookup *keyLookup, float f) {
457 for (int dep = 0; dep < 5; dep++) {
458 if (dep == 0) {
459 keyLookup->envDepthMult[dep] = 256;
460 keyLookup->envTimeMult[dep] = 256;
461 } else {
462 float depfac = 3000.0f;
463 float ff, tempdep;
464 depfac = (float)depexp[dep];
466 ff = (f - (float)MIDDLEC) / depfac;
467 tempdep = powf(2, ff) * 256.0f;
468 keyLookup->envDepthMult[dep] = (int)tempdep;
470 ff = (float)(exp(tkcatconst[dep] * ((float)MIDDLEC - f)) * tkcatmult[dep]);
471 keyLookup->envTimeMult[dep] = (int)(ff * 256.0f);
474 //synth->printDebug("F %f d1 %x d2 %x d3 %x d4 %x d5 %x", f, noteLookup->fildepTable[0], noteLookup->fildepTable[1], noteLookup->fildepTable[2], noteLookup->fildepTable[3], noteLookup->fildepTable[4]);
477 Bit16s Tables::clampWF(Synth *synth, const char *n, float ampVal, double input) {
478 Bit32s x = (Bit32s)(input * ampVal);
479 if (x < -ampVal - 1) {
480 synth->printDebug("%s==%d<-WGAMP-1!", n, x);
481 x = (Bit32s)(-ampVal - 1);
482 } else if (x > ampVal) {
483 synth->printDebug("%s==%d>WGAMP!", n, x);
484 x = (Bit32s)ampVal;
486 return (Bit16s)x;
489 File *Tables::initWave(Synth *synth, NoteLookup *noteLookup, float ampVal, float div2, File *file) {
490 int iDiv2 = (int)div2;
491 noteLookup->waveformSize[0] = iDiv2 << 1;
492 noteLookup->waveformSize[1] = iDiv2 << 1;
493 noteLookup->waveformSize[2] = iDiv2 << 2;
494 for (int i = 0; i < 3; i++) {
495 if (noteLookup->waveforms[i] == NULL) {
496 noteLookup->waveforms[i] = new Bit16s[noteLookup->waveformSize[i]];
499 if (file != NULL) {
500 for (int i = 0; i < 3 && file != NULL; i++) {
501 size_t len = noteLookup->waveformSize[i];
502 for (unsigned int j = 0; j < len; j++) {
503 if (!file->readBit16u((Bit16u *)&noteLookup->waveforms[i][j])) {
504 synth->printDebug("Error reading wave file cache!");
505 file->close();
506 file = NULL;
507 break;
512 if (file == NULL) {
513 double sd = DOUBLE_PI / div2;
515 for (int fa = 0; fa < (iDiv2 << 1); fa++) {
516 // sa ranges from 0 to 2PI
517 double sa = fa * sd;
519 // Calculate a sample for the bandlimited sawtooth wave
520 double saw = 0.0;
521 int sincs = iDiv2 >> 1;
522 double sinus = 1.0;
523 for (int sincNum = 1; sincNum <= sincs; sincNum++) {
524 saw += sin(sinus * sa) / sinus;
525 sinus++;
528 // This works pretty well
529 // Multiplied by 0.84 so that the spikes caused by bandlimiting don't overdrive the amplitude
530 noteLookup->waveforms[0][fa] = clampWF(synth, "saw", ampVal, -saw / (0.5 * DOUBLE_PI) * 0.84);
531 noteLookup->waveforms[1][fa] = clampWF(synth, "cos", ampVal, -cos(sa / 2.0));
532 noteLookup->waveforms[2][fa * 2] = clampWF(synth, "cosoff_0", ampVal, -cos(sa - DOUBLE_PI));
533 noteLookup->waveforms[2][fa * 2 + 1] = clampWF(synth, "cosoff_1", ampVal, -cos((sa + (sd / 2)) - DOUBLE_PI));
536 return file;
539 static void initFiltTable(NoteLookup *noteLookup, float freq, float rate) {
540 for (int tr = 0; tr <= 200; tr++) {
541 float ftr = (float)tr;
543 // Verified exact on MT-32
544 if (tr > 100)
545 ftr = 100.0f + (powf((ftr - 100.0f) / 100.0f, 3.0f) * 100.0f);
547 // I think this is the one
548 float brsq = powf(10.0f, (tr / 50.0f) - 1.0f);
549 noteLookup->filtTable[0][tr] = (int)((freq * brsq) / (rate / 2) * FILTERGRAN);
550 if (noteLookup->filtTable[0][tr]>=((FILTERGRAN*15)/16))
551 noteLookup->filtTable[0][tr] = ((FILTERGRAN*15)/16);
553 float brsa = powf(10.0f, ((tr / 55.0f) - 1.0f)) / 2.0f;
554 noteLookup->filtTable[1][tr] = (int)((freq * brsa) / (rate / 2) * FILTERGRAN);
555 if (noteLookup->filtTable[1][tr]>=((FILTERGRAN*15)/16))
556 noteLookup->filtTable[1][tr] = ((FILTERGRAN*15)/16);
560 static void initNFiltTable(NoteLookup *noteLookup, float freq, float rate) {
561 for (int cf = 0; cf <= 100; cf++) {
562 float cfmult = (float)cf;
564 for (int tf = 0;tf <= 100; tf++) {
565 float tfadd = (float)tf;
567 //float freqsum = exp((cfmult + tfadd) / 30.0f) / 4.0f;
568 //float freqsum = 0.15f * exp(0.45f * ((cfmult + tfadd) / 10.0f));
570 float freqsum = powf(2.0f, ((cfmult + tfadd) - 40.0f) / 16.0f);
572 noteLookup->nfiltTable[cf][tf] = (int)((freq * freqsum) / (rate / 2) * FILTERGRAN);
573 if (noteLookup->nfiltTable[cf][tf] >= ((FILTERGRAN * 15) / 16))
574 noteLookup->nfiltTable[cf][tf] = ((FILTERGRAN * 15) / 16);
579 File *Tables::initNote(Synth *synth, NoteLookup *noteLookup, float note, float rate, float masterTune, PCMWaveEntry *pcmWaves, File *file) {
580 float freq = (float)(masterTune * pow(2.0, ((double)note - MIDDLEA) / 12.0));
581 float div2 = rate * 2.0f / freq;
582 noteLookup->div2 = (int)div2;
584 if (noteLookup->div2 == 0)
585 noteLookup->div2 = 1;
587 initSaw(noteLookup, noteLookup->div2);
589 //synth->printDebug("Note %f; freq=%f, div=%f", note, freq, rate / freq);
590 file = initWave(synth, noteLookup, (const float)WGAMP, div2, file);
592 // Create the pitch tables
593 if (noteLookup->wavTable == NULL)
594 noteLookup->wavTable = new Bit32u[synth->controlROMMap->pcmCount];
595 double rateMult = 32000.0 / rate;
596 double tuner = freq * 65536.0f;
597 for (int pc = 0; pc < synth->controlROMMap->pcmCount; pc++) {
598 noteLookup->wavTable[pc] = (int)(tuner / pcmWaves[pc].tune * rateMult);
601 initFiltTable(noteLookup, freq, rate);
602 initNFiltTable(noteLookup, freq, rate);
603 return file;
606 bool Tables::initNotes(Synth *synth, PCMWaveEntry *pcmWaves, float rate, float masterTune) {
607 const char *NoteNames[12] = {
608 "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B "
610 char filename[64];
611 int intRate = (int)rate;
612 char version[4] = {0, 0, 0, 5};
613 sprintf(filename, "waveformcache-%d-%.2f.raw", intRate, (double)masterTune);
615 File *file = NULL;
616 char header[20];
617 strncpy(header, "MT32WAVE", 8);
618 int pos = 8;
619 // Version...
620 for (int i = 0; i < 4; i++)
621 header[pos++] = version[i];
622 header[pos++] = (char)((intRate >> 24) & 0xFF);
623 header[pos++] = (char)((intRate >> 16) & 0xFF);
624 header[pos++] = (char)((intRate >> 8) & 0xFF);
625 header[pos++] = (char)(intRate & 0xFF);
626 int intTuning = (int)masterTune;
627 header[pos++] = (char)((intTuning >> 8) & 0xFF);
628 header[pos++] = (char)(intTuning & 0xFF);
629 header[pos++] = 0;
630 header[pos] = (char)((masterTune - intTuning) * 10);
631 #if MT32EMU_WAVECACHEMODE < 2
632 bool reading = false;
633 file = synth->openFile(filename, File::OpenMode_read);
634 if (file != NULL) {
635 char fileHeader[20];
636 if (file->read(fileHeader, 20) == 20) {
637 if (memcmp(fileHeader, header, 20) == 0) {
638 Bit16u endianCheck;
639 if (file->readBit16u(&endianCheck)) {
640 if (endianCheck == 1) {
641 reading = true;
642 } else {
643 synth->printDebug("Endian check in %s does not match expected", filename);
645 } else {
646 synth->printDebug("Unable to read endian check in %s", filename);
648 } else {
649 synth->printDebug("Header of %s does not match expected", filename);
651 } else {
652 synth->printDebug("Error reading 16 bytes of %s", filename);
654 if (!reading) {
655 file->close();
656 file = NULL;
658 } else {
659 synth->printDebug("Unable to open %s for reading", filename);
661 #endif
663 float progress = 0.0f;
664 bool abort = false;
665 synth->report(ReportType_progressInit, &progress);
666 for (int f = LOWEST_NOTE; f <= HIGHEST_NOTE; f++) {
667 synth->printDebug("Initialising note %s%d", NoteNames[f % 12], (f / 12) - 2);
668 NoteLookup *noteLookup = &noteLookups[f - LOWEST_NOTE];
669 file = initNote(synth, noteLookup, (float)f, rate, masterTune, pcmWaves, file);
670 progress = (f - LOWEST_NOTE + 1) / (float)NUM_NOTES;
671 abort = synth->report(ReportType_progressInit, &progress) != 0;
672 if (abort)
673 break;
676 #if MT32EMU_WAVECACHEMODE == 0 || MT32EMU_WAVECACHEMODE == 2
677 if (file == NULL) {
678 file = synth->openFile(filename, File::OpenMode_write);
679 if (file != NULL) {
680 if (file->write(header, 20) == 20 && file->writeBit16u(1)) {
681 for (int f = 0; f < NUM_NOTES; f++) {
682 for (int i = 0; i < 3 && file != NULL; i++) {
683 int len = noteLookups[f].waveformSize[i];
684 for (int j = 0; j < len; j++) {
685 if (!file->writeBit16u(noteLookups[f].waveforms[i][j])) {
686 synth->printDebug("Error writing waveform cache file");
687 file->close();
688 file = NULL;
689 break;
694 } else {
695 synth->printDebug("Error writing 16-byte header to %s - won't continue saving", filename);
697 } else {
698 synth->printDebug("Unable to open %s for writing - won't be created", filename);
701 #endif
703 if (file != NULL)
704 synth->closeFile(file);
705 return !abort;
708 void Tables::freeNotes() {
709 for (int t = 0; t < 3; t++) {
710 for (int m = 0; m < NUM_NOTES; m++) {
711 if (noteLookups[m].waveforms[t] != NULL) {
712 delete[] noteLookups[m].waveforms[t];
713 noteLookups[m].waveforms[t] = NULL;
714 noteLookups[m].waveformSize[t] = 0;
716 if (noteLookups[m].wavTable != NULL) {
717 delete[] noteLookups[m].wavTable;
718 noteLookups[m].wavTable = NULL;
722 initialisedMasterTune = 0.0f;
725 Tables::Tables() {
726 initialisedSampleRate = 0.0f;
727 initialisedMasterTune = 0.0f;
728 memset(&noteLookups, 0, sizeof(noteLookups));
731 bool Tables::init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune) {
732 if (sampleRate <= 0.0f) {
733 synth->printDebug("Bad sampleRate (%f <= 0.0f)", sampleRate);
734 return false;
736 if (initialisedSampleRate == 0.0f) {
737 initMT32ConstantTables(synth);
739 if (initialisedSampleRate != sampleRate) {
740 initFiltCoeff(sampleRate);
741 initEnvelopes(sampleRate);
742 for (int key = 12; key <= 108; key++) {
743 initDep(&keyLookups[key - 12], (float)key);
746 if (initialisedSampleRate != sampleRate || initialisedMasterTune != masterTune) {
747 freeNotes();
748 if (!initNotes(synth, pcmWaves, sampleRate, masterTune)) {
749 return false;
751 initialisedSampleRate = sampleRate;
752 initialisedMasterTune = masterTune;
754 return true;