summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/snd_flt.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/snd_flt.cpp') (more/less context) (show whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/snd_flt.cpp104
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))
26static 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
56DWORD 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
74void 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