From: <sag...@us...> - 2011-10-02 16:01:36
|
Revision: 1075 http://modplug.svn.sourceforge.net/modplug/?rev=1075&view=rev Author: saga-games Date: 2011-10-02 16:01:29 +0000 (Sun, 02 Oct 2011) Log Message: ----------- [Fix] IT Compatibility: The resonant filter doesn't do any filtering if cutoff is maximum and resonance is minimum. [Fix] IT Compatibility: New filter mode which pretty much sounds like XMPlay's resonant filter (http://bugs.openmpt.org/view.php?id=8). [Mod] IT Saving: Files with filter envlope use a different file version (2.16) now. [Mod] OpenMPT: Version is now 1.20.00.35 Modified Paths: -------------- trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Snd_flt.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Tables.cpp Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2011-10-02 13:31:42 UTC (rev 1074) +++ trunk/OpenMPT/mptrack/version.h 2011-10-02 16:01:29 UTC (rev 1075) @@ -15,12 +15,12 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 20 #define VER_MINOR 00 -#define VER_MINORMINOR 34 +#define VER_MINORMINOR 35 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of //version 1.17.02.28. -#define MAKE_VERSION_NUMERIC(v0,v1,v2,v3) ((0x##v0 << 24) + (0x##v1<<16) + (0x##v2<<8) + (0x##v3)) +#define MAKE_VERSION_NUMERIC(v0,v1,v2,v3) ((0x##v0 << 24) | (0x##v1<<16) | (0x##v2<<8) | (0x##v3)) //Version string. For example "1.17.02.28" #define MPT_VERSION_STR STRINGIZE(VER_MAJORMAJOR)"."STRINGIZE(VER_MAJOR)"."STRINGIZE(VER_MINOR)"."STRINGIZE(VER_MINORMINOR) @@ -39,7 +39,7 @@ { int v1, v2, v3, v4; sscanf(s, "%x.%x.%x.%x", &v1, &v2, &v3, &v4); - return ((v1 << 24) + (v2 << 16) + (v3 << 8) + v4); + return ((v1 << 24) | (v2 << 16) | (v3 << 8) | v4); }; // Returns version string from given numerical version value. @@ -49,7 +49,7 @@ if(v == 0) strVersion = "Unknown"; else - strVersion.Format("%X.%02X.%02X.%02X", (v>>24)&0xFF, (v>>16)&0xFF, (v>>8)&0xFF, (v)&0xFF); + strVersion.Format("%X.%02X.%02X.%02X", (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, (v) & 0xFF); return strVersion; }; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2011-10-02 13:31:42 UTC (rev 1074) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2011-10-02 16:01:29 UTC (rev 1075) @@ -1439,7 +1439,7 @@ { if(Instruments[nIns] && Instruments[nIns]->PitchEnv.dwFlags & ENV_FILTER) { - header.cmwt = LittleEndianW(0x0217); + header.cmwt = LittleEndianW(0x0216); break; } } Modified: trunk/OpenMPT/soundlib/Snd_flt.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_flt.cpp 2011-10-02 13:31:42 UTC (rev 1074) +++ trunk/OpenMPT/soundlib/Snd_flt.cpp 2011-10-02 16:01:29 UTC (rev 1075) @@ -16,55 +16,24 @@ #ifndef NO_FILTER -//#define _ASM_MATH - -#ifdef _ASM_MATH - -// pow(a,b) returns a^^b -> 2^^(b.log2(a)) - -static float pow(float a, float b) -{ - long tmpint; - float result; - _asm { - fld b // Load b - fld a // Load a - fyl2x // ST(0) = b.log2(a) - fist tmpint // Store integer exponent - fisub tmpint // ST(0) = -1 <= (b*log2(a)) <= 1 - f2xm1 // ST(0) = 2^(x)-1 - fild tmpint // load integer exponent - fld1 // Load 1 - fscale // ST(0) = 2^ST(1) - fstp ST(1) // Remove the integer from the stack - fmul ST(1), ST(0) // multiply with fractional part - faddp ST(1), ST(0) // add integer_part - fstp result // Store the result - } - return result; -} - - -#else - +#define _USE_MATH_DEFINES #include <math.h> -#endif // _ASM_MATH +extern float ITResonanceTable[128]; DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const //----------------------------------------------------------------------- { float Fc; - ASSERT(nCutOff<128); + ASSERT(nCutOff < 128); if (m_dwSongFlags & SONG_EXFILTERRANGE) Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff * (flt_modifier + 256))) / (20.0f * 512.0f)); else Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff * (flt_modifier + 256))) / (24.0f * 512.0f)); LONG freq = (LONG)Fc; - if (freq < 120) return 120; - if (freq > 20000) return 20000; - if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1; + Limit(freq, 120, 20000); + if (freq * 2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq >> 1; return (DWORD)freq; } @@ -73,67 +42,82 @@ void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, bool bReset, int flt_modifier) const //---------------------------------------------------------------------------------------- { - float fs = (float)gdwMixingFreq; - float fg, fb0, fb1, fc, dmpfac; - - int cutoff = 0; + int cutoff = (int)pChn->nCutOff + (int)pChn->nCutSwing; + int resonance = (int)(pChn->nResonance & 0x7F) + (int)pChn->nResSwing; + + Limit(cutoff, 0, 127); + Limit(resonance, 0, 127); + if(!GetModFlag(MSF_OLDVOLSWING)) { - if(pChn->nCutSwing) + pChn->nCutOff = (BYTE)cutoff; + pChn->nCutSwing = 0; + pChn->nResonance = (BYTE)resonance; + pChn->nResSwing = 0; + } + + float d, e; + + if(UseITFilterMode()) + { + + // flt_modifier is in [-256, 256], so cutoff is in [0, 127 * 2] after this calculation + cutoff = cutoff * (flt_modifier + 256) / 256; + + // Filtering is only ever done if either cutoff is not full or if resonance is set. + if (cutoff < 254 || resonance != 0) { - static_assert(sizeof(pChn->nCutOff) == 1, "check cast if this fails"); - pChn->nCutOff = static_cast<BYTE>(pChn->nCutOff + pChn->nCutSwing); - Limit(pChn->nCutOff, BYTE(0), BYTE(127)); - pChn->nCutSwing = 0; - } - if(pChn->nResSwing) + pChn->dwFlags |= CHN_FILTER; + } else { - static_assert(sizeof(pChn->nResonance) == 1, "check cast if this fails"); - pChn->nResonance = static_cast<BYTE>(pChn->nResonance + pChn->nResSwing); - Limit(pChn->nResonance, BYTE(0), BYTE(127)); - pChn->nResSwing = 0; + return; } - cutoff = CLAMP((int)pChn->nCutOff, 0, 127); // cap cutoff - fc = (float)CutOffToFrequency(cutoff, flt_modifier); - dmpfac = pow(10.0f, -((24.0f / 128.0f) * (float)((pChn->nResonance) & 0x7F)) / 20.0f); - } - else - { - cutoff = CLAMP((int)pChn->nCutOff + (int)pChn->nCutSwing, 0, 127); // cap cutoff - fc = (float)CutOffToFrequency(cutoff, flt_modifier); - dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)((pChn->nResonance + pChn->nResSwing) & 0x7F)) / 20.0f); - } - if(cutoff == 127 && IsCompatibleMode(TRK_IMPULSETRACKER)) + static const float freqMultiplier = 2.0f * (float)M_PI * 110.0f * pow(2.0f, 0.25f); + static const float freqParameterMultiplier = 128.0f / (24.0f * 256.0f); + + // 2 ^ (i / 24 * 256) + const float r = (float)gdwMixingFreq / (freqMultiplier * pow(2.0f, (float)cutoff * freqParameterMultiplier)); + + d = ITResonanceTable[resonance] * r + ITResonanceTable[resonance] - 1.0f; + e = r * r; + + } else { - // Z7F shouldn't actually enable the filter. - return; - } - fc *= (float)(2.0 * 3.14159265358 / fs); - - float d = (1.0f - 2.0f * dmpfac) * fc; - LimitMax(d, 2.0f); - d = (2.0f * dmpfac - d) / fc; - float e = pow(1.0f / fc, 2.0f); + pChn->dwFlags |= CHN_FILTER; - fg = 1 / (1 + d + e); - fb0 = (d + e + e ) / (1 + d + e); - fb1 = -e / (1 + d + e); + float fc = (float)CutOffToFrequency(cutoff, flt_modifier); + const float dmpfac = pow(10.0f, -((24.0f / 128.0f) * (float)resonance) / 20.0f); + fc *= (float)(2.0 * 3.14159265358 / (float)gdwMixingFreq); + + d = (1.0f - 2.0f * dmpfac) * fc; + LimitMax(d, 2.0f); + d = (2.0f * dmpfac - d) / fc; + e = pow(1.0f / fc, 2.0f); + + } + + float fg = 1 / (1 + d + e); + float fb0 = (d + e + e) / (1 + d + e); + float fb1 = -e / (1 + d + e); + switch(pChn->nFilterMode) { case FLTMODE_HIGHPASS: - pChn->nFilter_A0 = (int)((1.0f-fg) * FILTER_PRECISION); + pChn->nFilter_A0 = (int)((1.0f - fg) * FILTER_PRECISION); pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); pChn->nFilter_HP = -1; break; + default: pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); pChn->nFilter_HP = 0; + break; } if (bReset) @@ -142,7 +126,6 @@ pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0; } - pChn->dwFlags |= CHN_FILTER; } #endif // NO_FILTER Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-10-02 13:31:42 UTC (rev 1074) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-10-02 16:01:29 UTC (rev 1075) @@ -1013,7 +1013,7 @@ pChn->nCutSwing = pChn->nResSwing = 0; } #ifndef NO_FILTER - if ((pChn->nCutOff < 0x7F) && (bFlt)) SetupChannelFilter(pChn, true); + if ((pChn->nCutOff < 0x7F || UseITFilterMode()) && (bFlt)) SetupChannelFilter(pChn, true); #endif // NO_FILTER } // Special case for MPT @@ -2114,11 +2114,11 @@ // IMF Commands case CMD_NOTESLIDEUP: - NoteSlide(pChn, param, 1); + NoteSlide(pChn, param, true); break; case CMD_NOTESLIDEDOWN: - NoteSlide(pChn, param, -1); + NoteSlide(pChn, param, false); break; } @@ -2410,8 +2410,8 @@ // Implemented for IMF compatibility, can't actually save this in any formats // sign should be 1 (up) or -1 (down) -void CSoundFile::NoteSlide(MODCHANNEL *pChn, UINT param, int sign) -//---------------------------------------------------------------- +void CSoundFile::NoteSlide(MODCHANNEL *pChn, UINT param, bool slideUp) +//-------------------------------------------------------------------- { BYTE x, y; if (m_dwSongFlags & SONG_FIRSTTICK) @@ -2430,7 +2430,7 @@ pChn->nNoteSlideCounter = pChn->nNoteSlideSpeed; // update it pChn->nPeriod = GetPeriodFromNote - (sign * pChn->nNoteSlideStep + GetNoteFromPeriod(pChn->nPeriod), 8363, 0); + ((slideUp ? 1 : -1) * pChn->nNoteSlideStep + GetNoteFromPeriod(pChn->nPeriod), 8363, 0); } } } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-10-02 13:31:42 UTC (rev 1074) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-10-02 16:01:29 UTC (rev 1075) @@ -624,6 +624,9 @@ return true; // S3M and MOD format don't have compatibility flags, so we will always return true return ((GetType() & type) && GetModFlag(MSF_COMPATIBLE_PLAY)) ? true : false; } + + // Check whether a filter algorithm closer to IT's should be used. + bool UseITFilterMode() const { return IsCompatibleMode(TRK_IMPULSETRACKER) && !(m_dwSongFlags & SONG_EXFILTERRANGE); } //Tuning--> public: @@ -990,7 +993,7 @@ void FinePortamentoDown(MODCHANNEL *pChn, UINT param); void ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param); void ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param); - void NoteSlide(MODCHANNEL *pChn, UINT param, int sign); + void NoteSlide(MODCHANNEL *pChn, UINT param, bool slideUp); void TonePortamento(MODCHANNEL *pChn, UINT param); void Vibrato(MODCHANNEL *pChn, UINT param); void FineVibrato(MODCHANNEL *pChn, UINT param); Modified: trunk/OpenMPT/soundlib/Tables.cpp =================================================================== --- trunk/OpenMPT/soundlib/Tables.cpp 2011-10-02 13:31:42 UTC (rev 1074) +++ trunk/OpenMPT/soundlib/Tables.cpp 2011-10-02 16:01:29 UTC (rev 1075) @@ -461,6 +461,44 @@ }; +// LUT for 2 * damping factor +float ITResonanceTable[128] = +{ + 1.0000000000000000f, 0.9786446094512940f, 0.9577452540397644f, 0.9372922182083130f, + 0.9172759056091309f, 0.8976871371269226f, 0.8785166740417481f, 0.8597555756568909f, + 0.8413951396942139f, 0.8234267830848694f, 0.8058421611785889f, 0.7886331081390381f, + 0.7717915177345276f, 0.7553095817565918f, 0.7391796708106995f, 0.7233941555023193f, + 0.7079457640647888f, 0.6928272843360901f, 0.6780316829681397f, 0.6635520458221436f, + 0.6493816375732422f, 0.6355138421058655f, 0.6219421625137329f, 0.6086603403091431f, + 0.5956621170043945f, 0.5829415321350098f, 0.5704925656318665f, 0.5583094954490662f, + 0.5463865399360657f, 0.5347182154655457f, 0.5232990980148315f, 0.5121238231658936f, + 0.5011872053146362f, 0.4904841780662537f, 0.4800096750259399f, 0.4697588682174683f, + 0.4597269892692566f, 0.4499093294143677f, 0.4403013288974762f, 0.4308985173702240f, + 0.4216965138912201f, 0.4126909971237183f, 0.4038778245449066f, 0.3952528536319733f, + 0.3868120610713959f, 0.3785515129566193f, 0.3704673945903778f, 0.3625559210777283f, + 0.3548133969306946f, 0.3472362160682678f, 0.3398208320140839f, 0.3325638175010681f, + 0.3254617750644684f, 0.3185114264488220f, 0.3117094635963440f, 0.3050527870655060f, + 0.2985382676124573f, 0.2921628654003143f, 0.2859236001968384f, 0.2798175811767578f, + 0.2738419771194458f, 0.2679939568042755f, 0.2622708380222321f, 0.2566699385643005f, + 0.2511886358261108f, 0.2458244115114212f, 0.2405747324228287f, 0.2354371547698975f, + 0.2304092943668366f, 0.2254888117313385f, 0.2206734120845795f, 0.2159608304500580f, + 0.2113489061594009f, 0.2068354636430740f, 0.2024184018373489f, 0.1980956792831421f, + 0.1938652694225311f, 0.1897251904010773f, 0.1856735348701477f, 0.1817083954811096f, + 0.1778279393911362f, 0.1740303486585617f, 0.1703138649463654f, 0.1666767448186874f, + 0.1631172895431519f, 0.1596338599920273f, 0.1562248021364212f, 0.1528885662555695f, + 0.1496235728263855f, 0.1464282870292664f, 0.1433012634515762f, 0.1402409970760346f, + 0.1372461020946503f, 0.1343151479959488f, 0.1314467936754227f, 0.1286396980285645f, + 0.1258925348520279f, 0.1232040524482727f, 0.1205729842185974f, 0.1179980933666229f, + 0.1154781952500343f, 0.1130121126770973f, 0.1105986908078194f, 0.1082368120551109f, + 0.1059253737330437f, 0.1036632955074310f, 0.1014495193958283f, 0.0992830246686935f, + 0.0971627980470657f, 0.0950878411531448f, 0.0930572077631950f, 0.0910699293017387f, + 0.0891250967979431f, 0.0872217938303947f, 0.0853591337800026f, 0.0835362523794174f, + 0.0817523002624512f, 0.0800064504146576f, 0.0782978758215904f, 0.0766257941722870f, + 0.0749894231557846f, 0.0733879879117012f, 0.0718207582831383f, 0.0702869966626167f, + 0.0687859877943993f, 0.0673170387744904f, 0.0658794566988945f, 0.0644725710153580f, +}; + + int SpectrumSinusTable[256*2] = { 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |