00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "stdafx.h"
00011 #include "sndfile.h"
00012
00013
00014
00015 #define FILTER_PRECISION 8192
00016
00017 #ifndef NO_FILTER
00018
00019 #ifdef WIN32
00020 #define _ASM_MATH
00021 #endif
00022
00023 #ifdef _ASM_MATH
00024
00025
00026 static float pow(float a, float b)
00027 {
00028 long tmpint;
00029 float result;
00030 _asm {
00031 fld b
00032 fld a
00033 fyl2x
00034 fist tmpint
00035 fisub tmpint
00036 f2xm1
00037 fild tmpint
00038 fld1
00039 fscale
00040 fstp ST(1)
00041 fmul ST(1), ST(0)
00042 faddp ST(1), ST(0)
00043 fstp result
00044 }
00045 return result;
00046 }
00047
00048
00049 #else
00050
00051 #include <math.h>
00052
00053 #endif // _ASM_MATH
00054
00055
00056 DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const
00057
00058 {
00059 float Fc;
00060
00061 if (m_dwSongFlags & SONG_EXFILTERRANGE)
00062 Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f));
00063 else
00064 Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f));
00065 LONG freq = (LONG)Fc;
00066 if (freq < 120) return 120;
00067 if (freq > 10000) return 10000;
00068 if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1;
00069 return (DWORD)freq;
00070 }
00071
00072
00073
00074 void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const
00075
00076 {
00077 float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier);
00078 float fs = (float)gdwMixingFreq;
00079 float fg, fb0, fb1;
00080
00081 fc *= (float)(2.0*3.14159265358/fs);
00082 float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f);
00083 float d = (1.0f-2.0f*dmpfac)* fc;
00084 if (d>2.0) d = 2.0;
00085 d = (2.0f*dmpfac - d)/fc;
00086 float e = pow(1.0f/fc,2.0);
00087
00088 fg=1/(1+d+e);
00089 fb0=(d+e+e)/(1+d+e);
00090 fb1=-e/(1+d+e);
00091
00092 pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION);
00093 pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION);
00094 pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION);
00095
00096 if (bReset)
00097 {
00098 pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
00099 pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
00100 }
00101 pChn->dwFlags |= CHN_FILTER;
00102 }
00103
00104 #endif // NO_FILTER