comparison src/modplug/snd_flt.cxx @ 2216:3673c7ec4ea2

Sync with schism's modplug engine. Suggested by G¸«ärkan Seng¸«än.
author William Pitcock <nenolod@atheme.org>
date Fri, 07 Dec 2007 12:08:47 -0600
parents 6b5a52635b3b
children 6907fc39b53f
comparison
equal deleted inserted replaced
2198:32f9f1e4a9ec 2216:3673c7ec4ea2
7 #include "stdafx.h" 7 #include "stdafx.h"
8 #include "sndfile.h" 8 #include "sndfile.h"
9 9
10 // AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz] 10 // AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz]
11 // EMU10K1 docs: cutoff = reg[0-127]*62+100 11 // EMU10K1 docs: cutoff = reg[0-127]*62+100
12 #define FILTER_PRECISION 8192
13 12
14 #ifndef NO_FILTER 13 #ifndef NO_FILTER
15 14
16 #ifdef MSC_VER 15 static int filter_cutoff[] = {
17 #define _ASM_MATH 16 130, 132, 134, 136, 138, 140, 142, 144,
18 #endif 17 146, 148, 151, 153, 155, 157, 160, 162,
18 164, 167, 169, 172, 174, 177, 179, 182,
19 184, 187, 190, 193, 195, 198, 201, 204,
20 207, 210, 213, 216, 220, 223, 226, 229,
21 233, 236, 239, 243, 246, 250, 254, 257,
22 261, 265, 269, 273, 277, 281, 285, 289,
23 293, 297, 302, 306, 311, 315, 320, 324,
24 329, 334, 339, 344, 349, 354, 359, 364,
25 369, 375, 380, 386, 391, 397, 403, 409,
26 415, 421, 427, 433, 440, 446, 452, 459,
27 466, 472, 479, 486, 493, 501, 508, 515,
28 523, 530, 538, 546, 554, 562, 570, 578,
29 587, 595, 604, 613, 622, 631, 640, 649,
30 659, 668, 678, 688, 698, 708, 718, 729,
31 739, 750, 761, 772, 783, 795, 806, 818,
32 830, 842, 854, 867, 880, 892, 905, 918,
33 932, 945, 959, 973, 987, 1002, 1016, 1031,
34 1046, 1061, 1077, 1092, 1108, 1124, 1141, 1157,
35 1174, 1191, 1209, 1226, 1244, 1262, 1280, 1299,
36 1318, 1337, 1357, 1376, 1396, 1417, 1437, 1458,
37 1479, 1501, 1523, 1545, 1567, 1590, 1613, 1637,
38 1661, 1685, 1709, 1734, 1760, 1785, 1811, 1837,
39 1864, 1891, 1919, 1947, 1975, 2004, 2033, 2062,
40 2093, 2123, 2154, 2185, 2217, 2249, 2282, 2315,
41 2349, 2383, 2418, 2453, 2489, 2525, 2561, 2599,
42 2637, 2675, 2714, 2753, 2793, 2834, 2875, 2917,
43 2959, 3003, 3046, 3091, 3135, 3181, 3227, 3274,
44 3322, 3370, 3419, 3469, 3520, 3571, 3623, 3675,
45 3729, 3783, 3838, 3894, 3951, 4008, 4066, 4125,
46 4186, 4246, 4308, 4371, 4434, 4499, 4564, 4631,
47 4698, 4766, 4836, 4906, 4978, 5050, 5123, 5198
48 };
49 int dmpfac[] = {
50 131072, 128272, 125533, 122852, 120229, 117661, 115148, 112689,
51 110283, 107928, 105623, 103367, 101160, 98999, 96885, 94816,
52 92791, 90810, 88870, 86973, 85115, 83298, 81519, 79778,
53 78074, 76407, 74775, 73178, 71615, 70086, 68589, 67125,
54 65691, 64288, 62915, 61572, 60257, 58970, 57711, 56478,
55 55272, 54092, 52937, 51806, 50700, 49617, 48557, 47520,
56 46506, 45512, 44540, 43589, 42658, 41747, 40856, 39983,
57 39130, 38294, 37476, 36676, 35893, 35126, 34376, 33642,
58 32923, 32220, 31532, 30859, 30200, 29555, 28924, 28306,
59 27701, 27110, 26531, 25964, 25410, 24867, 24336, 23816,
60 23308, 22810, 22323, 21846, 21380, 20923, 20476, 20039,
61 19611, 19192, 18782, 18381, 17989, 17604, 17228, 16861,
62 16500, 16148, 15803, 15466, 15135, 14812, 14496, 14186,
63 13883, 13587, 13297, 13013, 12735, 12463, 12197, 11936,
64 11681, 11432, 11188, 10949, 10715, 10486, 10262, 10043,
65 9829, 9619, 9413, 9212, 9015, 8823, 8634, 8450,
66 8270, 8093, 7920, 7751, 7585, 7423, 7265, 7110,
67 6958, 6809, 6664, 6522, 6382, 6246, 6113, 5982,
68 5854, 5729, 5607, 5487, 5370, 5255, 5143, 5033,
69 4926, 4820, 4718, 4617, 4518, 4422, 4327, 4235,
70 4144, 4056, 3969, 3884, 3801, 3720, 3641, 3563,
71 3487, 3412, 3340, 3268, 3198, 3130, 3063, 2998,
72 2934, 2871, 2810, 2750, 2691, 2634, 2577, 2522,
73 2468, 2416, 2364, 2314, 2264, 2216, 2169, 2122,
74 2077, 2032, 1989, 1947, 1905, 1864, 1824, 1786,
75 1747, 1710, 1674, 1638, 1603, 1569, 1535, 1502,
76 1470, 1439, 1408, 1378, 1348, 1320, 1291, 1264,
77 1237, 1210, 1185, 1159, 1135, 1110, 1087, 1063,
78 1041, 1018, 997, 975, 955, 934, 914, 895,
79 876, 857, 838, 821, 803, 786, 769, 753,
80 737, 721, 705, 690, 676, 661, 647, 633,
81 620, 606, 593, 581, 568, 556, 544, 533
82 };
19 83
20 #ifdef _ASM_MATH
21
22 // pow(a,b) returns a^^b -> 2^^(b.log2(a))
23 static float pow(float a, float b)
24 {
25 long tmpint;
26 float result;
27 _asm {
28 fld b // Load b
29 fld a // Load a
30 fyl2x // ST(0) = b.log2(a)
31 fist tmpint // Store integer exponent
32 fisub tmpint // ST(0) = -1 <= (b*log2(a)) <= 1
33 f2xm1 // ST(0) = 2^(x)-1
34 fild tmpint // load integer exponent
35 fld1 // Load 1
36 fscale // ST(0) = 2^ST(1)
37 fstp ST(1) // Remove the integer from the stack
38 fmul ST(1), ST(0) // multiply with fractional part
39 faddp ST(1), ST(0) // add integer_part
40 fstp result // Store the result
41 }
42 return result;
43 }
44
45
46 #else
47 84
48 #include <math.h> 85 #include <math.h>
49 86
50 #endif // _ASM_MATH
51 87
52 88 #define PI ((double)3.14159265358979323846)
53 DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const
54 //-----------------------------------------------------------------------
55 {
56 float Fc;
57
58 if (m_dwSongFlags & SONG_EXFILTERRANGE)
59 Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f));
60 else
61 Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f));
62 LONG freq = (LONG)Fc;
63 if (freq < 120) return 120;
64 if (freq > 10000) return 10000;
65 if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1;
66 return (DWORD)freq;
67 }
68
69
70 // Simple 2-poles resonant filter 89 // Simple 2-poles resonant filter
71 void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const 90 void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier, int) const
72 //---------------------------------------------------------------------------------------- 91 //----------------------------------------------------------------------------------------
73 { 92 {
74 float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier); 93 int cutoff = pChn->nCutOff * 2;
75 float fs = (float)gdwMixingFreq; 94 cutoff *= (flt_modifier+256) / 2;
76 float fg, fb0, fb1; 95 cutoff /= 256;
96 if (cutoff>=255) cutoff=255;
77 97
78 fc *= (float)(2.0*3.14159265358/fs); 98 int resonance = pChn->nResonance;
79 float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f); 99 if (resonance>=255) resonance=255;
80 float d = (1.0f-2.0f*dmpfac)* fc;
81 if (d>2.0) d = 2.0;
82 d = (2.0f*dmpfac - d)/fc;
83 float e = pow(1.0f/fc,2.0);
84 100
85 fg=1/(1+d+e); 101 float fc = (float)filter_cutoff[cutoff];
86 fb0=(d+e+e)/(1+d+e); 102 float fs = (float)gdwMixingFreq;
87 fb1=-e/(1+d+e); 103 float fg, fb0, fb1;
104 float d2, d, e;
88 105
89 pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); 106 fc *= 3.14159265358979 * 2 / fs;
90 pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); 107 d2 = ((float)dmpfac[resonance]) / 65536.0;
91 pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); 108 d = (1.0 - d2) * fc;
92 109
93 if (bReset) 110 if (d > 2.0)
94 { 111 d = 2.0;
112
113 d = (d2 - d) / fc;
114 e = 1.0 / (fc * fc);
115
116 fg = 1.0 / (1 + d + e);
117 fb0 = (d + e + e) / (1 + d + e);
118 fb1 = -e / (1 + d + e);
119
120 pChn->nFilter_A0 = (double)fg;
121 pChn->nFilter_B0 = (double)fb0;
122 pChn->nFilter_B1 = (double)fb1;
123
124 if (bReset) {
95 pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0; 125 pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
96 pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0; 126 pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
97 } 127 }
98 pChn->dwFlags |= CHN_FILTER; 128 pChn->dwFlags |= CHN_FILTER;
99 } 129 }
100
101 #endif // NO_FILTER 130 #endif // NO_FILTER