00506d4af0c46d049bec394c96a4075dd9c2e8e4
[platform/upstream/gstreamer.git] / gst / modplug / libmodplug / snd_flt.cpp
1 /*
2  * This source code is public domain.
3  *
4  * Authors: Olivier Lapicque <olivierl@jps.net>
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "stdafx.h"
12 #include "sndfile.h"
13
14 // AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz]
15 // EMU10K1 docs: cutoff = reg[0-127]*62+100
16 #define FILTER_PRECISION        8192
17
18 #ifndef NO_FILTER
19
20 #ifdef MSC_VER
21 #define _ASM_MATH
22 #endif
23
24 #ifdef _ASM_MATH
25
26 // pow(a,b) returns a^^b -> 2^^(b.log2(a))
27 static float pow(float a, float b)
28 {
29         long tmpint;
30         float result;
31         _asm {
32         fld b                           // Load b
33         fld a                           // Load a
34         fyl2x                           // ST(0) = b.log2(a)
35         fist tmpint                     // Store integer exponent
36         fisub tmpint            // ST(0) = -1 <= (b*log2(a)) <= 1
37         f2xm1                           // ST(0) = 2^(x)-1
38         fild tmpint                     // load integer exponent
39         fld1                            // Load 1
40         fscale                          // ST(0) = 2^ST(1)
41         fstp ST(1)                      // Remove the integer from the stack
42         fmul ST(1), ST(0)       // multiply with fractional part
43         faddp ST(1), ST(0)      // add integer_part
44         fstp result                     // Store the result
45         }
46         return result;
47 }
48
49
50 #else
51
52 #include <math.h>
53
54 #endif // _ASM_MATH
55
56
57 DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const
58 //-----------------------------------------------------------------------
59 {
60         float Fc;
61
62         if (m_dwSongFlags & SONG_EXFILTERRANGE)
63                 Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f));
64         else
65                 Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f));
66         LONG freq = (LONG)Fc;
67         if (freq < 120) return 120;
68         if (freq > 10000) return 10000;
69         if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1;
70         return (DWORD)freq;
71 }
72
73
74 // Simple 2-poles resonant filter
75 void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const
76 //----------------------------------------------------------------------------------------
77 {
78         float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier);
79         float fs = (float)gdwMixingFreq;
80         float fg, fb0, fb1;
81
82         fc *= (float)(2.0*3.14159265358/fs);
83         float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f);
84         float d = (1.0f-2.0f*dmpfac)* fc;
85         if (d>2.0) d = 2.0;
86         d = (2.0f*dmpfac - d)/fc;
87         float e = pow(1.0f/fc, 2);
88
89         fg=1/(1+d+e);
90         fb0=(d+e+e)/(1+d+e);
91         fb1=-e/(1+d+e);
92
93         pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION);
94         pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION);
95         pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION);
96
97         if (bReset)
98         {
99                 pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
100                 pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
101         }
102         pChn->dwFlags |= CHN_FILTER;
103 }
104
105 #endif // NO_FILTER