Diffstat (limited to 'core/multimedia/opieplayer/modplug/snd_flt.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/snd_flt.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/snd_flt.cpp b/core/multimedia/opieplayer/modplug/snd_flt.cpp new file mode 100644 index 0000000..5ac241e --- a/dev/null +++ b/core/multimedia/opieplayer/modplug/snd_flt.cpp | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2 of the license or (at your | ||
5 | * option) any later version. | ||
6 | * | ||
7 | * Authors: Olivier Lapicque <olivierl@jps.net> | ||
8 | */ | ||
9 | |||
10 | #include "stdafx.h" | ||
11 | #include "sndfile.h" | ||
12 | |||
13 | // AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz] | ||
14 | // EMU10K1 docs: cutoff = reg[0-127]*62+100 | ||
15 | #define FILTER_PRECISION8192 | ||
16 | |||
17 | #ifndef NO_FILTER | ||
18 | |||
19 | #ifdef WIN32 | ||
20 | #define _ASM_MATH | ||
21 | #endif | ||
22 | |||
23 | #ifdef _ASM_MATH | ||
24 | |||
25 | // pow(a,b) returns a^^b -> 2^^(b.log2(a)) | ||
26 | static float pow(float a, float b) | ||
27 | { | ||
28 | long tmpint; | ||
29 | float result; | ||
30 | _asm { | ||
31 | fld b // Load b | ||
32 | fld a // Load a | ||
33 | fyl2x // ST(0) = b.log2(a) | ||
34 | fist tmpint // Store integer exponent | ||
35 | fisub tmpint // ST(0) = -1 <= (b*log2(a)) <= 1 | ||
36 | f2xm1 // ST(0) = 2^(x)-1 | ||
37 | fild tmpint // load integer exponent | ||
38 | fld1 // Load 1 | ||
39 | fscale // ST(0) = 2^ST(1) | ||
40 | fstp ST(1) // Remove the integer from the stack | ||
41 | fmul ST(1), ST(0)// multiply with fractional part | ||
42 | faddp ST(1), ST(0)// add integer_part | ||
43 | fstp result // Store the result | ||
44 | } | ||
45 | return result; | ||
46 | } | ||
47 | |||
48 | |||
49 | #else | ||
50 | |||
51 | #include <math.h> | ||
52 | |||
53 | #endif // _ASM_MATH | ||
54 | |||
55 | |||
56 | DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const | ||
57 | //----------------------------------------------------------------------- | ||
58 | { | ||
59 | float Fc; | ||
60 | |||
61 | if (m_dwSongFlags & SONG_EXFILTERRANGE) | ||
62 | Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f)); | ||
63 | else | ||
64 | Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f)); | ||
65 | LONG freq = (LONG)Fc; | ||
66 | if (freq < 120) return 120; | ||
67 | if (freq > 10000) return 10000; | ||
68 | if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1; | ||
69 | return (DWORD)freq; | ||
70 | } | ||
71 | |||
72 | |||
73 | // Simple 2-poles resonant filter | ||
74 | void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const | ||
75 | //---------------------------------------------------------------------------------------- | ||
76 | { | ||
77 | float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier); | ||
78 | float fs = (float)gdwMixingFreq; | ||
79 | float fg, fb0, fb1; | ||
80 | |||
81 | fc *= (float)(2.0*3.14159265358/fs); | ||
82 | float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f); | ||
83 | float d = (1.0f-2.0f*dmpfac)* fc; | ||
84 | if (d>2.0) d = 2.0; | ||
85 | d = (2.0f*dmpfac - d)/fc; | ||
86 | float e = pow(1.0f/fc,2.0); | ||
87 | |||
88 | fg=1/(1+d+e); | ||
89 | fb0=(d+e+e)/(1+d+e); | ||
90 | fb1=-e/(1+d+e); | ||
91 | |||
92 | pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); | ||
93 | pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); | ||
94 | pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); | ||
95 | |||
96 | if (bReset) | ||
97 | { | ||
98 | pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0; | ||
99 | pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0; | ||
100 | } | ||
101 | pChn->dwFlags |= CHN_FILTER; | ||
102 | } | ||
103 | |||
104 | #endif // NO_FILTER | ||