# HG changeset patch # User William Pitcock # Date 1197051217 21600 # Node ID 6907fc39b53f0810d59c781c84e63eb41afdda69 # Parent 6a4d667a9183f9910a3ff88ab8a8fe5c44ae6857 That didn't merge properly. I'll try again at some other point. diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/fastmix.cxx --- a/src/modplug/fastmix.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/fastmix.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -1,5 +1,8 @@ /* - * This source code is public domain. + * This program is free software; you can redistribute it and modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the license or (at your + * option) any later version. * * Authors: Olivier Lapicque * Markus Fick spline + fir-resampler @@ -9,6 +12,10 @@ #include "sndfile.h" #include +#ifdef MSC_VER +#pragma bss_seg(".modplug") +#endif + // Front Mix Buffer (Also room for interleaved rear mix) int MixSoundBuffer[MIXBUFFERSIZE*4]; @@ -18,8 +25,14 @@ extern UINT gnReverbSend; #endif +#ifndef MODPLUG_FASTSOUNDLIB int MixRearBuffer[MIXBUFFERSIZE*2]; float MixFloatBuffer[MIXBUFFERSIZE*2]; +#endif + +#ifdef MSC_VER +#pragma bss_seg() +#endif extern LONG gnDryROfsVol; @@ -517,39 +530,37 @@ // Resonant Filters // Mono -#define MIX_BEGIN_FILTER \ - double fy1 = pChannel->nFilter_Y1;\ - double fy2 = pChannel->nFilter_Y2;\ - double ta; +#define MIX_BEGIN_FILTER\ + int fy1 = pChannel->nFilter_Y1;\ + int fy2 = pChannel->nFilter_Y2;\ -#define MIX_END_FILTER \ +#define MIX_END_FILTER\ pChannel->nFilter_Y1 = fy1;\ pChannel->nFilter_Y2 = fy2; -#define SNDMIX_PROCESSFILTER \ -ta = ((double)vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\ -fy2 = fy1;\ -fy1 = ta;vol=(int)ta; +#define SNDMIX_PROCESSFILTER\ + vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ + fy2 = fy1;\ + fy1 = vol;\ // Stereo -#define MIX_BEGIN_STEREO_FILTER \ -double fy1 = pChannel->nFilter_Y1;\ -double fy2 = pChannel->nFilter_Y2;\ -double fy3 = pChannel->nFilter_Y3;\ -double fy4 = pChannel->nFilter_Y4;\ -double ta, tb; +#define MIX_BEGIN_STEREO_FILTER\ + int fy1 = pChannel->nFilter_Y1;\ + int fy2 = pChannel->nFilter_Y2;\ + int fy3 = pChannel->nFilter_Y3;\ + int fy4 = pChannel->nFilter_Y4;\ -#define MIX_END_STEREO_FILTER \ -pChannel->nFilter_Y1 = fy1;\ -pChannel->nFilter_Y2 = fy2;\ -pChannel->nFilter_Y3 = fy3;\ -pChannel->nFilter_Y4 = fy4;\ +#define MIX_END_STEREO_FILTER\ + pChannel->nFilter_Y1 = fy1;\ + pChannel->nFilter_Y2 = fy2;\ + pChannel->nFilter_Y3 = fy3;\ + pChannel->nFilter_Y4 = fy4;\ -#define SNDMIX_PROCESSSTEREOFILTER \ -ta = ((double)vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\ -tb = ((double)vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1);\ -fy2 = fy1; fy1 = ta;vol_l=(int)ta;\ -fy4 = fy3; fy3 = tb;vol_r=(int)tb; +#define SNDMIX_PROCESSSTEREOFILTER\ + vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ + vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\ + fy2 = fy1; fy1 = vol_l;\ + fy4 = fy3; fy3 = vol_r;\ ////////////////////////////////////////////////////////// // Interfaces @@ -648,17 +659,11 @@ ///////////////////////////////////////////////////// // -extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount, const float _i2fc); -extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount, const float _f2ic); -extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount, const float _i2fc); -extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount, const float _f2ic); - -void InitMixBuffer(int *pBuffer, UINT nSamples); -void EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples); -void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); - -void StereoMixToFloat(const int *, float *, float *, UINT nCount); -void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount); +void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples); +void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples); +void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); +void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount); +void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount); ///////////////////////////////////////////////////// // Mono samples functions @@ -1461,7 +1466,9 @@ DWORD nchused, nchmixed; if (!count) return 0; - if (gnChannels > 2) InitMixBuffer(MixRearBuffer, count*2); +#ifndef MODPLUG_FASTSOUNDLIB + if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2); +#endif nchused = nchmixed = 0; for (UINT nChn=0; nChndwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER; #endif - if (!(pChannel->dwFlags & CHN_NOIDO) - && !(gdwSoundSetup & SNDMIX_NORESAMPLING)) + if (!(pChannel->dwFlags & CHN_NOIDO)) { // use hq-fir mixer? if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) ) - nFlags |= MIXNDX_FIRSRC; - else if( (gdwSoundSetup & SNDMIX_HQRESAMPLER)) - nFlags |= MIXNDX_SPLINESRC; + nFlags += MIXNDX_FIRSRC; + else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER ) + nFlags += MIXNDX_SPLINESRC; else - nFlags |= MIXNDX_LINEARSRC; // use + nFlags += MIXNDX_LINEARSRC; // use } if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol) && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp))) @@ -1530,7 +1536,7 @@ pChannel->nPos = 0; pChannel->nPosLo = 0; pChannel->nRampLength = 0; - EndChannelOfs(pChannel, pbuffer, nsamples); + X86_EndChannelOfs(pChannel, pbuffer, nsamples); *pOfsR += pChannel->nROfs; *pOfsL += pChannel->nLOfs; pChannel->nROfs = pChannel->nLOfs = 0; @@ -1551,10 +1557,6 @@ } else // Do mixing { - if (pChannel->nLength) { - pChannel->topnote_offset = ((pChannel->nPos << 16) | pChannel->nPosLo) % pChannel->nLength; - } - // Choose function for mixing LPMIXINTERFACE pMixFunc; pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags]; @@ -1591,59 +1593,81 @@ return nchused; } -static float f2ic = (float)(1 << 28); -static float i2fc = (float)(1.0 / (1 << 28)); -VOID CSoundFile::StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount) -//----------------------------------------------------------------------------------------- -{ - for (UINT i = 0; i < nCount; i++) { - *pOut1++ = *pSrc * i2fc; /*!*/ - pSrc++; +#ifdef MSC_VER +#pragma warning (disable:4100) +#endif - *pOut2++ = *pSrc * i2fc; /*!*/ - pSrc++; - } -} - - -VOID CSoundFile::FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount) -//--------------------------------------------------------------------------------------------- +// Clip and convert to 8 bit +#ifdef MSC_VER +__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +//---------------------------------------------------------------------------------------------------------------------------- { - for (UINT i = 0; i < nCount; i++) { - *pOut++ = (int)(*pIn1 * f2ic); - *pOut++ = (int)(*pIn2 * f2ic); - pIn1++; - pIn2++; + _asm { + push ebx + push esi + push edi + mov ebx, 16[esp] // ebx = 8-bit buffer + mov esi, 20[esp] // esi = pBuffer + mov edi, 24[esp] // edi = lSampleCount + mov eax, 28[esp] + mov ecx, dword ptr [eax] // ecx = clipmin + mov eax, 32[esp] + mov edx, dword ptr [eax] // edx = clipmax +cliploop: + mov eax, dword ptr [esi] + inc ebx + cdq + and edx, (1 << (24-MIXING_ATTENUATION)) - 1 + add eax, edx + cmp eax, MIXING_CLIPMIN + jl cliplow + cmp eax, MIXING_CLIPMAX + jg cliphigh + cmp eax, ecx + jl updatemin + cmp eax, edx + jg updatemax +cliprecover: + add esi, 4 + sar eax, 24-MIXING_ATTENUATION + xor eax, 0x80 + dec edi + mov byte ptr [ebx-1], al + jnz cliploop + mov eax, 28[esp] + mov dword ptr [eax], ecx + mov eax, 32[esp] + mov dword ptr [eax], edx + mov eax, 24[esp] + pop edi + pop esi + pop ebx + ret +updatemin: + mov ecx, eax + jmp cliprecover +updatemax: + mov edx, eax + jmp cliprecover +cliplow: + mov ecx, MIXING_CLIPMIN + mov edx, MIXING_CLIPMAX + mov eax, MIXING_CLIPMIN + jmp cliprecover +cliphigh: + mov ecx, MIXING_CLIPMIN + mov edx, MIXING_CLIPMAX + mov eax, MIXING_CLIPMAX + jmp cliprecover } } - - -VOID CSoundFile::MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount) -//------------------------------------------------------------------------ -{ - for (UINT i = 0; i < nCount; i++) { - *pOut++ = *pSrc * i2fc; /*!*/ - pSrc++; - } -} - - -VOID CSoundFile::FloatToMonoMix(const float *pIn, int *pOut, UINT nCount) -//----------------------------------------------------------------------- -{ - for (UINT i = 0; i < nCount; i++) { - *pOut++ = (int)(*pIn * f2ic); /*!*/ - pIn++; - } -} - - -// Clip and convert to 8 bit +#else //MSC_VER //---GCCFIX: Asm replaced with C function // The C version was written by Rani Assaf , I believe -DWORD Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) +DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) { + int vumin = *lpMin, vumax = *lpMax; unsigned char *p = (unsigned char *)lp8; for (UINT i=0; i MIXING_CLIPMAX) n = MIXING_CLIPMAX; - if (n < mins[i&1]) - mins[i&1]= n; - else if (n > maxs[i&1]) - maxs[i&1] = n; + if (n < vumin) + vumin = n; + else if (n > vumax) + vumax = n; p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80; // 8-bit unsigned } + *lpMin = vumin; + *lpMax = vumax; return lSampleCount; } +#endif //MSC_VER, else + + +#ifdef MSC_VER +// Clip and convert to 16 bit +__declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +//----------------------------------------------------------------------------------------------------------------------------- +{ + _asm { + push ebx + push esi + push edi + mov ebx, 16[esp] // ebx = 16-bit buffer + mov eax, 28[esp] + mov esi, 20[esp] // esi = pBuffer + mov ecx, dword ptr [eax] // ecx = clipmin + mov edi, 24[esp] // edi = lSampleCount + mov eax, 32[esp] + push ebp + mov ebp, dword ptr [eax] // edx = clipmax +cliploop: + mov eax, dword ptr [esi] + add ebx, 2 + cdq + and edx, (1 << (16-MIXING_ATTENUATION)) - 1 + add esi, 4 + add eax, edx + cmp eax, MIXING_CLIPMIN + jl cliplow + cmp eax, MIXING_CLIPMAX + jg cliphigh + cmp eax, ecx + jl updatemin + cmp eax, ebp + jg updatemax +cliprecover: + sar eax, 16-MIXING_ATTENUATION + dec edi + mov word ptr [ebx-2], ax + jnz cliploop + mov edx, ebp + pop ebp + mov eax, 28[esp] + mov dword ptr [eax], ecx + mov eax, 32[esp] + mov dword ptr [eax], edx + mov eax, 24[esp] + pop edi + shl eax, 1 + pop esi + pop ebx + ret +updatemin: + mov ecx, eax + jmp cliprecover +updatemax: + mov ebp, eax + jmp cliprecover +cliplow: + mov ecx, MIXING_CLIPMIN + mov ebp, MIXING_CLIPMAX + mov eax, MIXING_CLIPMIN + jmp cliprecover +cliphigh: + mov ecx, MIXING_CLIPMIN + mov ebp, MIXING_CLIPMAX + mov eax, MIXING_CLIPMAX + jmp cliprecover + } +} +#else //MSC_VER //---GCCFIX: Asm replaced with C function // The C version was written by Rani Assaf , I believe -DWORD Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) +DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) { + int vumin = *lpMin, vumax = *lpMax; signed short *p = (signed short *)lp16; for (UINT i=0; i MIXING_CLIPMAX) n = MIXING_CLIPMAX; - if (n < mins[i&1]) - mins[i&1]= n; - else if (n > maxs[i&1]) - maxs[i&1] = n; + if (n < vumin) + vumin = n; + else if (n > vumax) + vumax = n; p[i] = n >> (16-MIXING_ATTENUATION); // 16-bit signed } + *lpMin = vumin; + *lpMax = vumax; return lSampleCount * 2; } +#endif //MSC_VER, else + +#ifdef MSC_VER +// Clip and convert to 24 bit +__declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +//----------------------------------------------------------------------------------------------------------------------------- +{ + _asm { + push ebx + push esi + push edi + mov ebx, 16[esp] // ebx = 8-bit buffer + mov esi, 20[esp] // esi = pBuffer + mov edi, 24[esp] // edi = lSampleCount + mov eax, 28[esp] + mov ecx, dword ptr [eax] // ecx = clipmin + mov eax, 32[esp] + push ebp + mov edx, dword ptr [eax] // edx = clipmax +cliploop: + mov eax, dword ptr [esi] + mov ebp, eax + sar ebp, 31 + and ebp, (1 << (8-MIXING_ATTENUATION)) - 1 + add eax, ebp + cmp eax, MIXING_CLIPMIN + jl cliplow + cmp eax, MIXING_CLIPMAX + jg cliphigh + cmp eax, ecx + jl updatemin + cmp eax, edx + jg updatemax +cliprecover: + add ebx, 3 + sar eax, 8-MIXING_ATTENUATION + add esi, 4 + mov word ptr [ebx-3], ax + shr eax, 16 + dec edi + mov byte ptr [ebx-1], al + jnz cliploop + pop ebp + mov eax, 28[esp] + mov dword ptr [eax], ecx + mov eax, 32[esp] + mov dword ptr [eax], edx + mov edx, 24[esp] + mov eax, edx + pop edi + shl eax, 1 + pop esi + add eax, edx + pop ebx + ret +updatemin: + mov ecx, eax + jmp cliprecover +updatemax: + mov edx, eax + jmp cliprecover +cliplow: + mov ecx, MIXING_CLIPMIN + mov edx, MIXING_CLIPMAX + mov eax, MIXING_CLIPMIN + jmp cliprecover +cliphigh: + mov ecx, MIXING_CLIPMIN + mov edx, MIXING_CLIPMAX + mov eax, MIXING_CLIPMAX + jmp cliprecover + } +} +#else //MSC_VER //---GCCFIX: Asm replaced with C function -// 24-bit might not work... -DWORD Convert32To24(LPVOID lp24, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) +DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) { - /* the inventor of 24bit anything should be shot */ - unsigned char *p = (unsigned char *)lp24; - for (UINT i=0; i MIXING_CLIPMAX) + n = MIXING_CLIPMAX; + if (n < vumin) + vumin = n; + else if (n > vumax) + vumax = n; + p = n >> (8-MIXING_ATTENUATION) ; // 24-bit signed +// buf[i*3] = p & 0xFF0000 ; //XXX +// buf[i*3+1] = p & 0x00FF00 ; +// buf[i*3+2] = p & 0x0000FF ; + buf[i*3] = (p & 0xFF0000) >> 16 ; + buf[i*3+1] = (p & 0x00FF00) >> 8 ; + buf[i*3+2] = p & 0x0000FF ; + } + *lpMin = vumin; + *lpMax = vumax; + return lSampleCount * 3; +} +#endif + +#ifdef MSC_VER +// Clip and convert to 32 bit +__declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +//----------------------------------------------------------------------------------------------------------------------------- +{ + _asm { + push ebx + push esi + push edi + mov ebx, 16[esp] // ebx = 32-bit buffer + mov esi, 20[esp] // esi = pBuffer + mov edi, 24[esp] // edi = lSampleCount + mov eax, 28[esp] + mov ecx, dword ptr [eax] // ecx = clipmin + mov eax, 32[esp] + mov edx, dword ptr [eax] // edx = clipmax +cliploop: + mov eax, dword ptr [esi] + add ebx, 4 + add esi, 4 + cmp eax, MIXING_CLIPMIN + jl cliplow + cmp eax, MIXING_CLIPMAX + jg cliphigh + cmp eax, ecx + jl updatemin + cmp eax, edx + jg updatemax +cliprecover: + shl eax, MIXING_ATTENUATION + dec edi + mov dword ptr [ebx-4], eax + jnz cliploop + mov eax, 28[esp] + mov dword ptr [eax], ecx + mov eax, 32[esp] + mov dword ptr [eax], edx + mov edx, 24[esp] + pop edi + mov eax, edx + pop esi + shl eax, 2 + pop ebx + ret +updatemin: + mov ecx, eax + jmp cliprecover +updatemax: + mov edx, eax + jmp cliprecover +cliplow: + mov ecx, MIXING_CLIPMIN + mov edx, MIXING_CLIPMAX + mov eax, MIXING_CLIPMIN + jmp cliprecover +cliphigh: + mov ecx, MIXING_CLIPMIN + mov edx, MIXING_CLIPMAX + mov eax, MIXING_CLIPMAX + jmp cliprecover + } +} +#else +//---GCCFIX: Asm replaced with C function +DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +{ + UINT i ; + int vumin = *lpMin, vumax = *lpMax; + signed long *p = (signed long *)lp16; + + for ( i=0; i MIXING_CLIPMAX) n = MIXING_CLIPMAX; - if (n < mins[i&1]) - mins[i&1]= n; - else if (n > maxs[i&1]) - maxs[i&1] = n; - n = n >> (8-MIXING_ATTENUATION); // 24-bit signed - /* err, assume same endian */ - memcpy(p, &n, 3); - p += 3; + if (n < vumin) + vumin = n; + else if (n > vumax) + vumax = n; + p[i] = n << MIXING_ATTENUATION; // 32-bit signed } - return lSampleCount * 2; + *lpMin = vumin; + *lpMax = vumax; + return lSampleCount * 4; } -//---GCCFIX: Asm replaced with C function -// 32-bit might not work... -DWORD Convert32To32(LPVOID lp32, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) +#endif + + +#ifdef MSC_VER +void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) +//------------------------------------------------------------ { - signed int *p = (signed int *)lp32; - for (UINT i=0; i MIXING_CLIPMAX) - n = MIXING_CLIPMAX; - if (n < mins[i&1]) - mins[i&1]= n; - else if (n > maxs[i&1]) - maxs[i&1] = n; - p[i] = (n >> MIXING_ATTENUATION); // 32-bit signed + _asm { + mov ecx, nSamples + mov esi, pBuffer + xor eax, eax + mov edx, ecx + shr ecx, 2 + and edx, 3 + jz unroll4x +loop1x: + add esi, 4 + dec edx + mov dword ptr [esi-4], eax + jnz loop1x +unroll4x: + or ecx, ecx + jnz loop4x + jmp done +loop4x: + add esi, 16 + dec ecx + mov dword ptr [esi-16], eax + mov dword ptr [esi-12], eax + mov dword ptr [esi-8], eax + mov dword ptr [esi-4], eax + jnz loop4x +done:; } - return lSampleCount * 2; } +#else //---GCCFIX: Asm replaced with C function // Will fill in later. -void InitMixBuffer(int *pBuffer, UINT nSamples) +void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) { memset(pBuffer, 0, nSamples * sizeof(int)); } +#endif -//---GCCFIX: Asm replaced with C function -void InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) + +#ifdef MSC_VER +__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) +//------------------------------------------------------------------------------------------------------ { - DWORD i=0; - - pRearBuf[i] = pFrontBuf[1]; - for (i = 1; i < nSamples; i++) { - pRearBuf[i] = pFrontBuf[(i*2)+1]; - pFrontBuf[i] = pFrontBuf[i*2]; + _asm { + push ebx + push ebp + push esi + push edi + mov ecx, 28[esp] // ecx = samplecount + mov esi, 20[esp] // esi = front buffer + mov edi, 24[esp] // edi = rear buffer + lea esi, [esi+ecx*4] // esi = &front[N] + lea edi, [edi+ecx*4] // edi = &rear[N] + lea ebx, [esi+ecx*4] // ebx = &front[N*2] +interleaveloop: + mov eax, dword ptr [esi-8] + mov edx, dword ptr [esi-4] + sub ebx, 16 + mov ebp, dword ptr [edi-8] + mov dword ptr [ebx], eax + mov dword ptr [ebx+4], edx + mov eax, dword ptr [edi-4] + sub esi, 8 + sub edi, 8 + dec ecx + mov dword ptr [ebx+8], ebp + mov dword ptr [ebx+12], eax + jnz interleaveloop + pop edi + pop esi + pop ebp + pop ebx + ret } } +#else //---GCCFIX: Asm replaced with C function -VOID MonoFromStereo(int *pMixBuf, UINT nSamples) +// Multichannel not supported. +void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) +{ +} +#endif + + +#ifdef MSC_VER +VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) +//------------------------------------------------------------- +{ + _asm { + mov ecx, nSamples + mov esi, pMixBuf + mov edi, esi +stloop: + mov eax, dword ptr [esi] + mov edx, dword ptr [esi+4] + add edi, 4 + add esi, 8 + add eax, edx + sar eax, 1 + dec ecx + mov dword ptr [edi-4], eax + jnz stloop + } +} +#else +//---GCCFIX: Asm replaced with C function +VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) { UINT j; for(UINT i = 0; i < nSamples; i++) @@ -1752,11 +2095,89 @@ pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1; } } +#endif +#define OFSDECAYSHIFT 8 +#define OFSDECAYMASK 0xFF + + +#ifdef MSC_VER +void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) +//--------------------------------------------------------------------------------------- +{ + _asm { + mov edi, pBuffer + mov ecx, nSamples + mov eax, lpROfs + mov edx, lpLOfs + mov eax, [eax] + mov edx, [edx] + or ecx, ecx + jz fill_loop + mov ebx, eax + or ebx, edx + jz fill_loop +ofsloop: + mov ebx, eax + mov esi, edx + neg ebx + neg esi + sar ebx, 31 + sar esi, 31 + and ebx, OFSDECAYMASK + and esi, OFSDECAYMASK + add ebx, eax + add esi, edx + sar ebx, OFSDECAYSHIFT + sar esi, OFSDECAYSHIFT + sub eax, ebx + sub edx, esi + mov ebx, eax + or ebx, edx + jz fill_loop + add edi, 8 + dec ecx + mov [edi-8], eax + mov [edi-4], edx + jnz ofsloop +fill_loop: + mov ebx, ecx + and ebx, 3 + jz fill4x +fill1x: + mov [edi], eax + mov [edi+4], edx + add edi, 8 + dec ebx + jnz fill1x +fill4x: + shr ecx, 2 + or ecx, ecx + jz done +fill4xloop: + mov [edi], eax + mov [edi+4], edx + mov [edi+8], eax + mov [edi+12], edx + add edi, 8*4 + dec ecx + mov [edi-16], eax + mov [edi-12], edx + mov [edi-8], eax + mov [edi-4], edx + jnz fill4xloop +done: + mov esi, lpROfs + mov edi, lpLOfs + mov [esi], eax + mov [edi], edx + } +} +#else //---GCCFIX: Asm replaced with C function #define OFSDECAYSHIFT 8 #define OFSDECAYMASK 0xFF -void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) +void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) //--------------------------------------------------------------------------------------------------------- { int rofs = *lpROfs; @@ -1764,7 +2185,7 @@ if ((!rofs) && (!lofs)) { - InitMixBuffer(pBuffer, nSamples*2); + X86_InitMixBuffer(pBuffer, nSamples*2); return; } for (UINT i=0; inROfs; int lofs = pChannel->nLOfs; @@ -1799,9 +2264,7 @@ pChannel->nROfs = rofs; pChannel->nLOfs = lofs; } - - - +#endif ////////////////////////////////////////////////////////////////////////////////// @@ -1813,11 +2276,72 @@ #define MIXING_LIMITMAX (0x08100000) #define MIXING_LIMITMIN (-MIXING_LIMITMAX) +#ifdef MSC_VER +__declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC) +//------------------------------------------------------------------------------- +{ + __asm { + push ebx + push ebp + push esi + push edi + mov esi, 20[esp] // esi = pBuffer+i + mov ecx, 24[esp] // ecx = i + mov edi, 28[esp] // edi = AGC (0..256) +agcloop: + mov eax, dword ptr [esi] + imul edi + shrd eax, edx, AGC_PRECISION + add esi, 4 + cmp eax, MIXING_LIMITMIN + jl agcupdate + cmp eax, MIXING_LIMITMAX + jg agcupdate +agcrecover: + dec ecx + mov dword ptr [esi-4], eax + jnz agcloop + mov eax, edi + pop edi + pop esi + pop ebp + pop ebx + ret +agcupdate: + dec edi + jmp agcrecover + } +} + +#pragma warning (default:4100) +#else +// Version for GCC +UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC) +{ + int x; + + while(nSamples) + { + x = ((long long int)(*pBuffer) * nAGC) >> AGC_PRECISION; + + if((x < MIXING_LIMITMIN) || (x > MIXING_LIMITMAX)) + nAGC--; + + *pBuffer = x; + + pBuffer++; + nSamples--; + } + + return nAGC; +} +#endif + void CSoundFile::ProcessAGC(int count) //------------------------------------ { static DWORD gAGCRecoverCount = 0; - UINT agc = AGC(MixSoundBuffer, count, gnAGC); + UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC); // Some kind custom law, so that the AGC stays quite stable, but slowly // goes back up if the sound level stays below a level inversely proportional // to the AGC level. (J'me comprends) @@ -1847,4 +2371,3 @@ } #endif // NO_AGC - diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/it_defs.h --- a/src/modplug/it_defs.h Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/it_defs.h Fri Dec 07 12:13:37 2007 -0600 @@ -7,8 +7,7 @@ { DWORD id; // 0x4D504D49 CHAR songname[26]; - BYTE hilight_minor; - BYTE hilight_major; + WORD reserved1; // 0x1004 WORD ordnum; WORD insnum; WORD smpnum; @@ -22,7 +21,7 @@ BYTE speed; BYTE tempo; BYTE sep; - BYTE pwd; + BYTE zero; WORD msglength; DWORD msgoffset; DWORD reserved2; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_669.cxx --- a/src/modplug/load_669.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_669.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -51,9 +51,12 @@ || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE; DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600; if (dontfuckwithme > dwMemLength) return FALSE; - for (int n = 0; n < 128; n++) - if (pfh->breaks[n] > 0x3f) - return false; + for (UINT ichk=0; ichksamples; ichk++) + { + DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length))); + dontfuckwithme += len; + } + if (dontfuckwithme > dwMemLength) return FALSE; // That should be enough checking: this must be a 669 module. m_nType = MOD_TYPE_669; m_dwSongFlags |= SONG_LINEARSLIDES; @@ -62,8 +65,7 @@ m_nDefaultTempo = 125; m_nDefaultSpeed = 6; m_nChannels = 8; - memcpy(m_szNames[0], pfh->songmessage, 31); - m_szNames[0][31] = 0; + memcpy(m_szNames[0], pfh->songmessage, 16); m_nSamples = pfh->samples; for (UINT nins=1; nins<=m_nSamples; nins++, psmp++) { @@ -84,15 +86,9 @@ Ins[nins].nPan = 128; } // Song Message - m_lpszSongComments = new char[114]; - memcpy(m_lpszSongComments, pfh->songmessage, 36); - m_lpszSongComments[36] = '\015'; - m_lpszSongComments[37] = '\012'; - memcpy(m_lpszSongComments + 38, pfh->songmessage + 36, 36); - m_lpszSongComments[74] = '\015'; - m_lpszSongComments[75] = '\012'; - memcpy(m_lpszSongComments + 76, pfh->songmessage + 72, 36); - m_lpszSongComments[112] = 0; + m_lpszSongComments = new char[109]; + memcpy(m_lpszSongComments, pfh->songmessage, 108); + m_lpszSongComments[108] = 0; // Reading Orders memcpy(Order, pfh->orders, 128); m_nRestartPos = pfh->restartpos; @@ -110,7 +106,6 @@ Patterns[npat] = AllocatePattern(64, m_nChannels); if (!Patterns[npat]) break; PatternSize[npat] = 64; - PatternAllocSize[npat] = 64; MODCOMMAND *m = Patterns[npat]; const BYTE *p = lpStream + dwMemPos; for (UINT row=0; row<64; row++) diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_amf.cxx --- a/src/modplug/load_amf.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_amf.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -1,8 +1,11 @@ /* - * This source code is public domain. + * This program is free software; you can redistribute it and modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the license or (at your + * option) any later version. * * Authors: Olivier Lapicque - */ +*/ /////////////////////////////////////////////////// // @@ -220,7 +223,6 @@ if (!p) break; Patterns[iPat] = p; PatternSize[iPat] = 64; - PatternAllocSize[iPat] = 64; const UCHAR *pin = lpStream + dwMemPos; for (UINT i=0; i<8*64; i++) { @@ -312,11 +314,9 @@ { Order[iOrd] = iOrd; PatternSize[iOrd] = 64; - PatternAllocSize[iOrd] = 64; if (pfh->version >= 14) { PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); - PatternAllocSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos)); dwMemPos += 2; } ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos); @@ -353,7 +353,8 @@ if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1)) { sampleseekpos[iIns] = bswapLE32(psh->offset); - if (bswapLE32(psh->offset) > maxsampleseekpos) maxsampleseekpos = bswapLE32(psh->offset); + if (bswapLE32(psh->offset) > maxsampleseekpos) + maxsampleseekpos = bswapLE32(psh->offset); if ((pins->nLoopEnd > pins->nLoopStart + 2) && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP; } @@ -417,5 +418,3 @@ } return TRUE; } - - diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_ams.cxx --- a/src/modplug/load_ams.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_ams.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -142,7 +142,6 @@ dwMemPos += 4; if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE; PatternSize[iPat] = 64; - PatternAllocSize[iPat] = 64; MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels); if (!m) return TRUE; Patterns[iPat] = m; @@ -335,7 +334,6 @@ m_nDefaultSpeed = psh->speed; m_nInstruments = psh->instruments; m_nSamples = 0; - m_dwSongFlags |= SONG_INSTRUMENTMODE; if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES; for (UINT nIns=1; nIns<=m_nInstruments; nIns++) { @@ -380,15 +378,15 @@ // Volume Envelope { UINT pos = 0; - penv->VolEnv.nNodes = (volenv->points > 16) ? 16 : volenv->points; - penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = volenv->sustain; - penv->VolEnv.nLoopStart = volenv->loopbegin; - penv->VolEnv.nLoopEnd = volenv->loopend; - for (int i=0; iVolEnv.nNodes; i++) + penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points; + penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain; + penv->nVolLoopStart = volenv->loopbegin; + penv->nVolLoopEnd = volenv->loopend; + for (UINT i=0; inVolEnv; i++) { - penv->VolEnv.Values[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); + penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8); - penv->VolEnv.Ticks[i] = (WORD)pos; + penv->VolPoints[i] = (WORD)pos; } } penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3; @@ -489,7 +487,6 @@ SetPatternName(ipat, s); } PatternSize[ipat] = numrows; - PatternAllocSize[ipat] = numrows; Patterns[ipat] = AllocatePattern(numrows, m_nChannels); if (!Patterns[ipat]) return TRUE; // Unpack Pattern Data diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_dbm.cxx --- a/src/modplug/load_dbm.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_dbm.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -158,7 +158,7 @@ } Headers[iIns+1] = penv; penv->nFadeOut = 1024; // ??? - penv->nGlobalVol = 128; + penv->nGlobalVol = 64; penv->nPan = bswapBE16(pih->panning); if ((penv->nPan) && (penv->nPan < 256)) penv->dwFlags = ENV_SETPANNING; @@ -193,7 +193,6 @@ chunk_pos += sizeof(DBMINSTRUMENT); m_nInstruments = iIns+1; } - m_dwSongFlags |= SONG_INSTRUMENTMODE; } else // Volume Envelopes if (chunk_id == DBM_ID_VENV) @@ -216,15 +215,15 @@ if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME; if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP; - penv->VolEnv.nNodes = peh->numpoints + 1; - if (penv->VolEnv.nNodes > MAX_ENVPOINTS) penv->VolEnv.nNodes = MAX_ENVPOINTS; - penv->VolEnv.nLoopStart = peh->loopbegin; - penv->VolEnv.nLoopEnd = peh->loopend; - penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = peh->sustain1; - for (int i=0; iVolEnv.nNodes; i++) + penv->nVolEnv = peh->numpoints + 1; + if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS; + penv->nVolLoopStart = peh->loopbegin; + penv->nVolLoopEnd = peh->loopend; + penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1; + for (UINT i=0; inVolEnv; i++) { - penv->VolEnv.Ticks[i] = bswapBE16(peh->volenv[i*2]); - penv->VolEnv.Values[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); + penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]); + penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); } } chunk_pos += sizeof(DBMENVELOPE); @@ -255,7 +254,6 @@ UINT i = 0; PatternSize[iPat] = nRows; - PatternAllocSize[iPat] = nRows; Patterns[iPat] = m; while ((i+3jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; PatternSize[npat] = (WORD)ticks; - PatternAllocSize[npat] = (WORD)ticks; MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels); if (!m) goto dmfexit; Patterns[npat] = m; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_dsm.cxx --- a/src/modplug/load_dsm.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_dsm.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -136,7 +136,6 @@ MODCOMMAND *m = AllocatePattern(64, m_nChannels); if (!m) break; PatternSize[nPat] = 64; - PatternAllocSize[nPat] = 64; Patterns[nPat] = m; UINT row = 0; while ((row < 64) && (dwPos + 2 <= dwMemPos)) diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_far.cxx --- a/src/modplug/load_far.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_far.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -64,9 +64,10 @@ UINT headerlen; BYTE samplemap[8]; - if ((!lpStream) || (dwMemLength < 1024) || (pmh1->id != FARFILEMAGIC) + if ((!lpStream) || (dwMemLength < 1024) || (bswapLE32(pmh1->id) != FARFILEMAGIC) || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE; - headerlen = pmh1->headerlen; + headerlen = bswapLE16(pmh1->headerlen); + pmh1->stlen = bswapLE16( pmh1->stlen ); /* inplace byteswap -- Toad */ if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE; // Globals m_nType = MOD_TYPE_FAR; @@ -111,6 +112,14 @@ dwMemPos += headerlen - (869 + pmh1->stlen); if (dwMemPos >= dwMemLength) return TRUE; + // byteswap pattern data -- Toad + UINT psfix = 0 ; + while( psfix++ < 256 ) + { + pmh2->patsiz[psfix] = bswapLE16( pmh2->patsiz[psfix] ) ; + } + // end byteswap of pattern data + WORD *patsiz = (WORD *)pmh2->patsiz; for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat]) { @@ -130,7 +139,6 @@ if (rows > 256) rows = 256; if (rows < 16) rows = 16; PatternSize[ipat] = rows; - PatternAllocSize[ipat] = rows; if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; MODCOMMAND *m = Patterns[ipat]; UINT patbrk = lpStream[dwMemPos]; @@ -233,9 +241,10 @@ dwMemPos += sizeof(FARSAMPLE); m_nSamples = ismp + 1; memcpy(m_szNames[ismp+1], pfs->samplename, 32); - pins->nLength = pfs->length; - pins->nLoopStart = pfs->reppos; - pins->nLoopEnd = pfs->repend; + pfs->length = bswapLE32( pfs->length ) ; /* endian fix - Toad */ + pins->nLength = pfs->length ; + pins->nLoopStart = bswapLE32(pfs->reppos) ; + pins->nLoopEnd = bswapLE32(pfs->repend) ; pins->nFineTune = 0; pins->nC4Speed = 8363*2; pins->nGlobalVol = 64; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_it.cxx --- a/src/modplug/load_it.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_it.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -2,17 +2,15 @@ * This source code is public domain. * * Authors: Olivier Lapicque , - * Adam Goode (endian and char fixes for PPC) + * Adam Goode (Endian and char fixes for PPC) + * Marco Trillo (Endian fixes for SaveIT, XM->IT Sample Converter) + * */ #include "stdafx.h" #include "sndfile.h" #include "it_defs.h" -/* blah, -mrsb. -this is a schism header */ -#include "midi.h" - #ifdef MSC_VER #pragma warning(disable:4244) #endif @@ -24,8 +22,11 @@ { 0, 2, 4, 1, 3, 0, 0, 0 }; ////////////////////////////////////////////////////////// -// Impulse Tracker IT file support (import only) +// Impulse Tracker IT file support +// for conversion of XM samples +extern WORD XMPeriodTable[96+8]; +extern UINT XMLinearTable[768]; static inline UINT ConvertVolParam(UINT value) //-------------------------------------------- @@ -43,7 +44,7 @@ memcpy(penv->name, pis->name, 26); memcpy(penv->filename, pis->filename, 12); penv->nFadeOut = bswapLE16(pis->fadeout) << 6; - penv->nGlobalVol = 128; + penv->nGlobalVol = 64; for (UINT j=0; j<120; j++) { UINT note = pis->keyboard[j*2]; @@ -55,19 +56,19 @@ if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME; if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP; if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN; - penv->VolEnv.nLoopStart = pis->vls; - penv->VolEnv.nLoopEnd = pis->vle; - penv->VolEnv.nSustainStart = pis->sls; - penv->VolEnv.nSustainEnd = pis->sle; - penv->VolEnv.nNodes = 25; + penv->nVolLoopStart = pis->vls; + penv->nVolLoopEnd = pis->vle; + penv->nVolSustainBegin = pis->sls; + penv->nVolSustainEnd = pis->sle; + penv->nVolEnv = 25; for (UINT ev=0; ev<25; ev++) { - if ((penv->VolEnv.Ticks[ev] = pis->nodes[ev*2]) == 0xFF) + if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF) { - penv->VolEnv.nNodes = ev; + penv->nVolEnv = ev; break; } - penv->VolEnv.Values[ev] = pis->nodes[ev*2+1]; + penv->VolEnv[ev] = pis->nodes[ev*2+1]; } penv->nNNA = pis->nna; penv->nDCT = pis->dnc; @@ -81,8 +82,8 @@ penv->nMidiChannel = pis->mch; penv->wMidiBank = bswapLE16(pis->mbank); penv->nFadeOut = bswapLE16(pis->fadeout) << 5; - penv->nGlobalVol = pis->gbv; - if (penv->nGlobalVol > 128) penv->nGlobalVol = 128; + penv->nGlobalVol = pis->gbv >> 1; + if (penv->nGlobalVol > 64) penv->nGlobalVol = 64; for (UINT j=0; j<120; j++) { UINT note = pis->keyboard[j*2]; @@ -96,49 +97,49 @@ if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP; if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN; if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY; - penv->VolEnv.nNodes = pis->volenv.num; - if (penv->VolEnv.nNodes > 25) penv->VolEnv.nNodes = 25; + penv->nVolEnv = pis->volenv.num; + if (penv->nVolEnv > 25) penv->nVolEnv = 25; - penv->VolEnv.nLoopStart = pis->volenv.lpb; - penv->VolEnv.nLoopEnd = pis->volenv.lpe; - penv->VolEnv.nSustainStart = pis->volenv.slb; - penv->VolEnv.nSustainEnd = pis->volenv.sle; + penv->nVolLoopStart = pis->volenv.lpb; + penv->nVolLoopEnd = pis->volenv.lpe; + penv->nVolSustainBegin = pis->volenv.slb; + penv->nVolSustainEnd = pis->volenv.sle; // Panning Envelope if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING; if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP; if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN; if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY; - penv->PanEnv.nNodes = pis->panenv.num; - if (penv->PanEnv.nNodes > 25) penv->PanEnv.nNodes = 25; - penv->PanEnv.nLoopStart = pis->panenv.lpb; - penv->PanEnv.nLoopEnd = pis->panenv.lpe; - penv->PanEnv.nSustainStart = pis->panenv.slb; - penv->PanEnv.nSustainEnd = pis->panenv.sle; + penv->nPanEnv = pis->panenv.num; + if (penv->nPanEnv > 25) penv->nPanEnv = 25; + penv->nPanLoopStart = pis->panenv.lpb; + penv->nPanLoopEnd = pis->panenv.lpe; + penv->nPanSustainBegin = pis->panenv.slb; + penv->nPanSustainEnd = pis->panenv.sle; // Pitch Envelope if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH; if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP; if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN; if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY; if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER; - penv->PitchEnv.nNodes = pis->pitchenv.num; - if (penv->PitchEnv.nNodes > 25) penv->PitchEnv.nNodes = 25; - penv->PitchEnv.nLoopStart = pis->pitchenv.lpb; - penv->PitchEnv.nLoopEnd = pis->pitchenv.lpe; - penv->PitchEnv.nSustainStart = pis->pitchenv.slb; - penv->PitchEnv.nSustainEnd = pis->pitchenv.sle; + penv->nPitchEnv = pis->pitchenv.num; + if (penv->nPitchEnv > 25) penv->nPitchEnv = 25; + penv->nPitchLoopStart = pis->pitchenv.lpb; + penv->nPitchLoopEnd = pis->pitchenv.lpe; + penv->nPitchSustainBegin = pis->pitchenv.slb; + penv->nPitchSustainEnd = pis->pitchenv.sle; // Envelopes Data for (UINT ev=0; ev<25; ev++) { - penv->VolEnv.Values[ev] = pis->volenv.data[ev*3]; - penv->VolEnv.Ticks[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]); - penv->PanEnv.Values[ev] = pis->panenv.data[ev*3] + 32; - penv->PanEnv.Ticks[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]); - penv->PitchEnv.Values[ev] = pis->pitchenv.data[ev*3] + 32; - penv->PitchEnv.Ticks[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]); + penv->VolEnv[ev] = pis->volenv.data[ev*3]; + penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]); + penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32; + penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]); + penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32; + penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]); } - penv->nNNA = pis->nna % 4; - penv->nDCT = pis->dct % 4; - penv->nDNA = pis->dca % 3; + penv->nNNA = pis->nna; + penv->nDCT = pis->dct; + penv->nDNA = pis->dca; penv->nPPS = pis->pps; penv->nPPC = pis->ppc; penv->nIFC = pis->ifc; @@ -149,8 +150,8 @@ if (penv->nPan > 256) penv->nPan = 128; if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING; } - if ((penv->VolEnv.nLoopStart >= 25) || (penv->VolEnv.nLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP; - if ((penv->VolEnv.nSustainStart >= 25) || (penv->VolEnv.nSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN; + if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP; + if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN; return TRUE; } @@ -166,112 +167,8 @@ BYTE chnmask[64], channels_used[64]; MODCOMMAND lastvalue[64]; - if ((!lpStream) || (dwMemLength < 0xc2)) return FALSE; - pifh.id = bswapLE32(pifh.id); - if (pifh.id == 0x49504D49) { - if (dwMemLength < 554) return FALSE; - - WORD tv; - INSTRUMENTHEADER *zenv = new INSTRUMENTHEADER; - if (!zenv) return FALSE; - memset(zenv, 0, sizeof(INSTRUMENTHEADER)); - memcpy(&tv, lpStream+0x1C, 2); /* trkvers */ - if (!ITInstrToMPT(lpStream, zenv, tv)) { - delete zenv; - return FALSE; - } - - /* okay, we need samples now */ - unsigned int q = 554; - BYTE expect_samples = lpStream[0x1E]; - - m_nType = MOD_TYPE_IT; - m_nInstruments = 1; - m_nSamples = expect_samples; - m_dwSongFlags = SONG_INSTRUMENTMODE | SONG_LINEARSLIDES /* eh? */; - - memcpy(m_szNames[0], lpStream + 0x20, 26); - m_szNames[0][26] = 0; - - if (q+(80*expect_samples) >= dwMemLength) { - delete zenv; - return FALSE; - } - - for (UINT nsmp = 0; nsmp < expect_samples; nsmp++) { - - ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+q); - q += 80; /* length of ITS header */ - - pis.id = bswapLE32(pis.id); - pis.length = bswapLE32(pis.length); - pis.loopbegin = bswapLE32(pis.loopbegin); - pis.loopend = bswapLE32(pis.loopend); - pis.C5Speed = bswapLE32(pis.C5Speed); - pis.susloopbegin = bswapLE32(pis.susloopbegin); - pis.susloopend = bswapLE32(pis.susloopend); - pis.samplepointer = bswapLE32(pis.samplepointer); - - if (pis.id == 0x53504D49) - { - MODINSTRUMENT *pins = &Ins[nsmp+1]; - memcpy(pins->name, pis.filename, 12); - pins->uFlags = 0; - pins->nLength = 0; - pins->nLoopStart = pis.loopbegin; - pins->nLoopEnd = pis.loopend; - pins->nSustainStart = pis.susloopbegin; - pins->nSustainEnd = pis.susloopend; - pins->nC4Speed = pis.C5Speed; - if (!pins->nC4Speed) pins->nC4Speed = 8363; - //if (pis.C5Speed < 256) pins->nC4Speed = 256; - pins->nVolume = pis.vol << 2; - if (pins->nVolume > 256) pins->nVolume = 256; - pins->nGlobalVol = pis.gvl; - if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; - if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP; - if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP; - if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP; - if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN; - pins->nPan = (pis.dfp & 0x7F) << 2; - if (pins->nPan > 256) pins->nPan = 256; - if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING; - pins->nVibType = autovibit2xm[pis.vit & 7]; - pins->nVibRate = pis.vis; - pins->nVibDepth = pis.vid & 0x7F; - pins->nVibSweep = pis.vir; - if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length)) - { - pins->nLength = pis.length; - if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH; - UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U; - if (pis.flags & 2) - { - flags += 5; - if (pis.flags & 4) flags |= RSF_STEREO; - pins->uFlags |= CHN_16BIT; - // IT 2.14 16-bit packed sample ? - if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416; - } else - { - if (pis.flags & 4) flags |= RSF_STEREO; - if (pis.cvt == 0xFF) flags = RS_ADPCM4; else - // IT 2.14 8-bit packed sample ? - if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148; - } - ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer); - } - } - memcpy(m_szNames[nsmp+1], pis.name, 26); - - } - - Headers[1] = zenv; - return TRUE; - } - - + pifh.reserved1 = bswapLE16(pifh.reserved1); pifh.ordnum = bswapLE16(pifh.ordnum); pifh.insnum = bswapLE16(pifh.insnum); pifh.smpnum = bswapLE16(pifh.smpnum); @@ -284,42 +181,29 @@ pifh.msgoffset = bswapLE32(pifh.msgoffset); pifh.reserved2 = bswapLE32(pifh.reserved2); - - + if ((!lpStream) || (dwMemLength < 0x100)) return FALSE; if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS) - || (pifh.smpnum >= MAX_INSTRUMENTS)) return FALSE; + || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE; if (dwMemPos + pifh.ordnum + pifh.insnum*4 + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE; m_nType = MOD_TYPE_IT; - if (!(pifh.flags & 0x01)) m_dwSongFlags |= SONG_NOSTEREO; - if (pifh.flags & 0x04) m_dwSongFlags |= SONG_INSTRUMENTMODE; if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES; if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS; if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE; - if (pifh.flags & 0x40) { - midi_flags |= MIDI_PITCH_BEND; - midi_pitch_depth = pifh.pwd; - } if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG; if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE; memcpy(m_szNames[0], pifh.songname, 26); m_szNames[0][26] = 0; - if (pifh.cwtv >= 0x0213) { - m_rowHighlightMinor = pifh.hilight_minor; - m_rowHighlightMajor = pifh.hilight_major; - } else { - m_rowHighlightMinor = 4; - m_rowHighlightMajor = 16; + // Global Volume + if (pifh.globalvol) + { + m_nDefaultGlobalVolume = pifh.globalvol << 1; + if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256; + if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256; } - // Global Volume - m_nDefaultGlobalVolume = pifh.globalvol << 1; - if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256; if (pifh.speed) m_nDefaultSpeed = pifh.speed; if (pifh.tempo) m_nDefaultTempo = pifh.tempo; - m_nSongPreAmp = pifh.mv; - if (m_nSongPreAmp > 128) - m_nSongPreAmp = 128; - m_nStereoSeparation = pifh.sep; + m_nSongPreAmp = pifh.mv & 0x7F; // Reading Channels Pan Positions for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF) { @@ -345,7 +229,6 @@ UINT nordsize = pifh.ordnum; if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS; memcpy(Order, lpStream+dwMemPos, nordsize); - dwMemPos += pifh.ordnum; // Reading Instrument Offsets memset(inspos, 0, sizeof(inspos)); @@ -380,17 +263,6 @@ patpos[j] = bswapLE32(patpos[j]); } dwMemPos += pifh.patnum * 4; - - for (UINT i = 0; i < pifh.ordnum; i++) { - if (Order[i] >= pifh.patnum && Order[i] < MAX_PATTERNS) { - pifh.patnum = Order[i]; - for (UINT j = patpossize; j < (unsigned)(pifh.patnum>>2); j++) - patpos[j] = 0; - patpossize = pifh.patnum; - } - } - - // Reading IT Extra Info if (dwMemPos + 2 < dwMemLength) { @@ -405,13 +277,8 @@ { memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG)); dwMemPos += sizeof(MODMIDICFG); - } else { - ResetMidiCfg(); } - } else { - ResetMidiCfg(); } -#if 0 // Read pattern names: "PNAM" if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) { @@ -428,10 +295,8 @@ dwMemPos += len; } } -#endif // 4-channels minimum m_nChannels = 4; -#if 0 // Read channel names: "CNAM" if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) { @@ -454,7 +319,6 @@ { dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos); } -#endif // Checking for unused channels UINT npatterns = pifh.patnum; if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS; @@ -502,7 +366,8 @@ } } // Reading Instruments - m_nInstruments = pifh.insnum; + m_nInstruments = 0; + if (pifh.flags & 0x04) m_nInstruments = pifh.insnum; if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1; for (UINT nins=0; ninsnSustainEnd = pis.susloopend; pins->nC4Speed = pis.C5Speed; if (!pins->nC4Speed) pins->nC4Speed = 8363; - //if (pis.C5Speed < 256) pins->nC4Speed = 256; + if (pis.C5Speed < 256) pins->nC4Speed = 256; pins->nVolume = pis.vol << 2; if (pins->nVolume > 256) pins->nVolume = 256; pins->nGlobalVol = pis.gvl; @@ -557,7 +422,7 @@ pins->nVibType = autovibit2xm[pis.vit & 7]; pins->nVibRate = pis.vis; pins->nVibDepth = pis.vid & 0x7F; - pins->nVibSweep = pis.vir; + pins->nVibSweep = (pis.vir + 3) / 4; if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length)) { pins->nLength = pis.length; @@ -588,7 +453,6 @@ if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength)) { PatternSize[npat] = 64; - PatternAllocSize[npat] = 64; Patterns[npat] = AllocatePattern(64, m_nChannels); continue; } @@ -598,7 +462,6 @@ if ((rows < 4) || (rows > 256)) continue; if (patpos[npat]+8+len > dwMemLength) continue; PatternSize[npat] = rows; - PatternAllocSize[npat] = rows; if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue; memset(lastvalue, 0, sizeof(lastvalue)); memset(chnmask, 0, sizeof(chnmask)); @@ -688,7 +551,7 @@ // 193-202: Portamento To if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else // 203-212: Vibrato - if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATO; m[ch].vol = vol - 203; } + if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; } lastvalue[ch].volcmd = m[ch].volcmd; lastvalue[ch].vol = m[ch].vol; } @@ -729,18 +592,14 @@ #ifndef MODPLUG_NO_FILESAVE //#define SAVEITTIMESTAMP +#pragma warning(disable:4100) -#ifdef MSC_VER -#pragma warning(disable:4100) -#endif - -#if 0 BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking) //--------------------------------------------------------- { DWORD dwPatNamLen, dwChnNamLen; - ITFILEHEADER header; - ITINSTRUMENT iti; + ITFILEHEADER header, writeheader; + ITINSTRUMENT iti, writeiti; ITSAMPLESTRUCT itss; BYTE smpcount[MAX_SAMPLES]; DWORD inspos[MAX_INSTRUMENTS]; @@ -762,10 +621,9 @@ memset(&header, 0, sizeof(header)); dwPatNamLen = 0; dwChnNamLen = 0; - header.id = 0x4D504D49; - lstrcpyn(header.songname, m_szNames[0], 27); - header.hilight_minor = m_rowHighlightMinor; - header.hilight_major = m_rowHighlightMajor; + header.id = 0x4D504D49; // IMPM + lstrcpyn((char *)header.songname, m_szNames[0], 27); + header.reserved1 = 0x1004; header.ordnum = 0; while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++; if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF; @@ -777,13 +635,16 @@ header.cmwt = 0x200; header.flags = 0x0001; header.special = 0x0006; - if (m_dwSongFlags & SONG_INSTRUMENTMODE) header.flags |= 0x04; + if (m_nInstruments) header.flags |= 0x04; if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08; if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10; if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20; if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000; header.globalvol = m_nDefaultGlobalVolume >> 1; header.mv = m_nSongPreAmp; + // clip song pre-amp values (between 0x20 and 0x7f) + if (header.mv < 0x20) header.mv = 0x20; + if (header.mv > 0x7F) header.mv = 0x7F; header.speed = m_nDefaultSpeed; header.tempo = m_nDefaultTempo; header.sep = m_nStereoSeparation; @@ -830,7 +691,25 @@ header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4; } // Write file header - fwrite(&header, 1, sizeof(header), f); + memcpy(writeheader, header, sizeof(header)); + + // Byteswap header information + writeheader.id = bswapLE32(writeheader.id); + writeheader.reserved1 = bswapLE16(writeheader.reserved1); + writeheader.ordnum = bswapLE16(writeheader.ordnum); + writeheader.insnum = bswapLE16(writeheader.insnum); + writeheader.smpnum = bswapLE16(writeheader.smpnum); + writeheader.patnum = bswapLE16(writeheader.patnum); + writeheader.cwtv = bswapLE16(writeheader.cwtv); + writeheader.cmwt = bswapLE16(writeheader.cmwt); + writeheader.flags = bswapLE16(writeheader.flags); + writeheader.special = bswapLE16(writeheader.special); + writeheader.msglength = bswapLE16(writeheader.msglength); + writeheader.msgoffset = bswapLE32(writeheader.msgoffset); + writeheader.reserved2 = bswapLE32(writeheader.reserved2); + + fwrite(&writeheader, 1, sizeof(writeheader), f); + fwrite(Order, 1, header.ordnum, f); if (header.insnum) fwrite(inspos, 4, header.insnum, f); if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); @@ -861,17 +740,19 @@ // Writing pattern names if (dwPatNamLen) { - DWORD d = 0x4d414e50; + DWORD d = bswapLE32(0x4d414e50); + UINT len= bswapLE32(dwPatNamLen); fwrite(&d, 1, 4, f); - fwrite(&dwPatNamLen, 1, 4, f); + write(&len, 1, 4, f); fwrite(m_lpszPatternNames, 1, dwPatNamLen, f); } // Writing channel Names if (dwChnNamLen) { - DWORD d = 0x4d414e43; + DWORD d = bswapLE32(0x4d414e43); + UINT len= bswapLE32(dwChnNamLen); fwrite(&d, 1, 4, f); - fwrite(&dwChnNamLen, 1, 4, f); + fwrite(&len, 1, 4, f); UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME; for (UINT inam=0; inamnFadeOut >> 5; iti.pps = penv->nPPS; iti.ppc = penv->nPPC; - iti.gbv = (BYTE)penv->nGlobalVol; + iti.gbv = (BYTE)(penv->nGlobalVol << 1); iti.dfp = (BYTE)penv->nPan >> 2; if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80; iti.rv = penv->nVolSwing; @@ -932,44 +813,44 @@ if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02; if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04; if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08; - iti.volenv.num = (BYTE)penv->VolEnv.nNodes; - iti.volenv.lpb = (BYTE)penv->VolEnv.nLoopStart; - iti.volenv.lpe = (BYTE)penv->VolEnv.nLoopEnd; - iti.volenv.slb = penv->VolEnv.nSustainStart; - iti.volenv.sle = penv->VolEnv.nSustainEnd; + iti.volenv.num = (BYTE)penv->nVolEnv; + iti.volenv.lpb = (BYTE)penv->nVolLoopStart; + iti.volenv.lpe = (BYTE)penv->nVolLoopEnd; + iti.volenv.slb = penv->nVolSustainBegin; + iti.volenv.sle = penv->nVolSustainEnd; // Writing Panning envelope if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01; if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02; if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04; if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08; - iti.panenv.num = (BYTE)penv->PanEnv.nNodes; - iti.panenv.lpb = (BYTE)penv->PanEnv.nLoopStart; - iti.panenv.lpe = (BYTE)penv->PanEnv.nLoopEnd; - iti.panenv.slb = penv->PanEnv.nSustainStart; - iti.panenv.sle = penv->PanEnv.nSustainEnd; + iti.panenv.num = (BYTE)penv->nPanEnv; + iti.panenv.lpb = (BYTE)penv->nPanLoopStart; + iti.panenv.lpe = (BYTE)penv->nPanLoopEnd; + iti.panenv.slb = penv->nPanSustainBegin; + iti.panenv.sle = penv->nPanSustainEnd; // Writing Pitch Envelope if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01; if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02; if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04; if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08; if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80; - iti.pitchenv.num = (BYTE)penv->PitchEnv.nNodes; - iti.pitchenv.lpb = (BYTE)penv->PitchEnv.nLoopStart; - iti.pitchenv.lpe = (BYTE)penv->PitchEnv.nLoopEnd; - iti.pitchenv.slb = (BYTE)penv->PitchEnv.nSustainStart; - iti.pitchenv.sle = (BYTE)penv->PitchEnv.nSustainEnd; + iti.pitchenv.num = (BYTE)penv->nPitchEnv; + iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart; + iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd; + iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin; + iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd; // Writing Envelopes data for (UINT ev=0; ev<25; ev++) { - iti.volenv.data[ev*3] = penv->VolEnv.Values[ev]; - iti.volenv.data[ev*3+1] = penv->VolEnv.Ticks[ev] & 0xFF; - iti.volenv.data[ev*3+2] = penv->VolEnv.Ticks[ev] >> 8; - iti.panenv.data[ev*3] = penv->PanEnv.Values[ev] - 32; - iti.panenv.data[ev*3+1] = penv->PanEnv.Ticks[ev] & 0xFF; - iti.panenv.data[ev*3+2] = penv->PanEnv.Ticks[ev] >> 8; - iti.pitchenv.data[ev*3] = penv->PitchEnv.Values[ev] - 32; - iti.pitchenv.data[ev*3+1] = penv->PitchEnv.Ticks[ev] & 0xFF; - iti.pitchenv.data[ev*3+2] = penv->PitchEnv.Ticks[ev] >> 8; + iti.volenv.data[ev*3] = penv->VolEnv[ev]; + iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF; + iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8; + iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32; + iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF; + iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8; + iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32; + iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF; + iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8; } } else // Save Empty Instrument @@ -984,7 +865,15 @@ // Writing instrument inspos[nins-1] = dwPos; dwPos += sizeof(ITINSTRUMENT); - fwrite(&iti, 1, sizeof(ITINSTRUMENT), f); + + memcpy(&writeiti, &iti, sizeof(ITINSTRUMENT)); + + writeiti.fadeout = bswapLE16(writeiti.fadeout); + writeiti.id = bswapLE32(writeiti.id); + writeiti.trkvers = bswapLE16(writeiti.trkvers); + writeiti.mbank = bswapLE16(writeiti.mbank); + + fwrite(&writeiti, 1, sizeof(ITINSTRUMENT), f); } // Writing sample headers memset(&itss, 0, sizeof(itss)); @@ -1002,7 +891,7 @@ if (!Patterns[npat]) continue; patpos[npat] = dwPos; patinfo[0] = 0; - patinfo[1] = PatternSize[npat]; + patinfo[1] = bswapLE16(PatternSize[npat]); patinfo[2] = 0; patinfo[3] = 0; // Check for empty pattern @@ -1010,8 +899,7 @@ { MODCOMMAND *pzc = Patterns[npat]; UINT nz = PatternSize[npat] * m_nChannels; - UINT iz; - for (iz=0; iznote; if (note) b |= 1; - if ((note) && (note < 0x80)) note--; + if ((note) && (note < 0x80)) note--; // 0xfe->0x80 --Toad if (m->instr) b |= 2; if (m->volcmd) { @@ -1051,8 +939,8 @@ case VOLCMD_VOLSLIDEDOWN: vol = 95 + ConvertVolParam(m->vol); break; case VOLCMD_FINEVOLUP: vol = 65 + ConvertVolParam(m->vol); break; case VOLCMD_FINEVOLDOWN: vol = 75 + ConvertVolParam(m->vol); break; - case VOLCMD_VIBRATOSPEED: vol = 203; break; - case VOLCMD_VIBRATO: vol = 203 + ConvertVolParam(m->vol); break; + case VOLCMD_VIBRATOSPEED: vol = 203 + ConvertVolParam(m->vol); break; + case VOLCMD_VIBRATO: vol = 203; break; case VOLCMD_TONEPORTAMENTO: vol = 193 + ConvertVolParam(m->vol); break; case VOLCMD_PORTADOWN: vol = 105 + ConvertVolParam(m->vol); break; case VOLCMD_PORTAUP: vol = 115 + ConvertVolParam(m->vol); break; @@ -1146,6 +1034,7 @@ fwrite(buf, 1, len, f); } fseek(f, dwPatPos, SEEK_SET); + patinfo[0] = bswapLE16(patinfo[0]); // byteswap -- Toad fwrite(patinfo, 8, 1, f); fseek(f, dwPos, SEEK_SET); } @@ -1158,7 +1047,7 @@ memcpy(itss.name, m_szNames[nsmp], 26); itss.id = 0x53504D49; itss.gvl = (BYTE)psmp->nGlobalVol; - if (m_dwSongFlags & SONG_INSTRUMENTMODE) + if (m_nInstruments) { for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu]) { @@ -1178,7 +1067,25 @@ if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40; if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; itss.C5Speed = psmp->nC4Speed; - if (!itss.C5Speed) itss.C5Speed = 8363; + if (!itss.C5Speed) // if no C5Speed assume it is XM Sample + { + UINT period; + + /** + * C5 note => number 61, but in XM samples: + * RealNote = Note + RelativeTone + */ + period = GetPeriodFromNote(61+psmp->RelativeTone, psmp->nFineTune, 0); + + if (period) + itss.C5Speed = GetFreqFromPeriod(period, 0, 0); + /** + * If it didn`t work, it may not be a XM file; + * so put the default C5Speed, 8363Hz. + */ + if (!itss.C5Speed) itss.C5Speed = 8363; + } + itss.length = psmp->nLength; itss.loopbegin = psmp->nLoopStart; itss.loopend = psmp->nLoopEnd; @@ -1189,7 +1096,7 @@ itss.vit = autovibxm2it[psmp->nVibType & 7]; itss.vis = psmp->nVibRate; itss.vid = psmp->nVibDepth; - itss.vir = psmp->nVibSweep; + itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255; if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80; if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01; UINT flags = RS_PCM8S; @@ -1197,7 +1104,7 @@ if (nPacking) { if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample(psmp->pSample, psmp->nLength, nPacking))) + && (CanPackSample((char *)psmp->pSample, psmp->nLength, nPacking))) { flags = RS_ADPCM4; itss.cvt = 0xFF; @@ -1218,6 +1125,16 @@ } itss.samplepointer = dwPos; fseek(f, smppos[nsmp-1], SEEK_SET); + + itss.id = bswapLE32(itss.id); + itss.length = bswapLE32(itss.length); + itss.loopbegin = bswapLE32(itss.loopbegin); + itss.loopend = bswapLE32(itss.loopend); + itss.C5Speed = bswapLE32(itss.C5Speed); + itss.susloopbegin = bswapLE32(itss.susloopbegin); + itss.susloopend = bswapLE32(itss.susloopend); + itss.samplepointer = bswapLE32(itss.samplepointer); + fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); fseek(f, dwPos, SEEK_SET); if ((psmp->pSample) && (psmp->nLength)) @@ -1227,18 +1144,33 @@ } // Updating offsets fseek(f, dwHdrPos, SEEK_SET); + + /* Now we can byteswap them ;-) */ + UINT WW; + UINT WX; + WX = (UINT)header.insnum; + WX <<= 2; + for (WW=0; WW < (WX>>2); WW++) + inspos[WW] = bswapLE32(inspos[WW]); + + WX = (UINT)header.smpnum; + WX <<= 2; + for (WW=0; WW < (WX>>2); WW++) + smppos[WW] = bswapLE32(smppos[WW]); + + WX=(UINT)header.patnum; + WX <<= 2; + for (WW=0; WW < (WX>>2); WW++) + patpos[WW] = bswapLE32(patpos[WW]); + if (header.insnum) fwrite(inspos, 4, header.insnum, f); if (header.smpnum) fwrite(smppos, 4, header.smpnum, f); if (header.patnum) fwrite(patpos, 4, header.patnum, f); fclose(f); return TRUE; } -#endif -#ifdef MSC_VER -#pragma warning(default:4100) -#endif - +//#pragma warning(default:4100) #endif // MODPLUG_NO_FILESAVE ////////////////////////////////////////////////////////////////////////////// @@ -1442,7 +1374,8 @@ { DWORD chinfo[64]; CHAR s[32]; - DWORD nPluginSize; + DWORD nPluginSize, writeSwapDWORD; + SNDMIXPLUGININFO writePluginInfo; UINT nTotalSize = 0; UINT nChInfo = 0; @@ -1467,9 +1400,23 @@ s[2] = '0' + (i/10); s[3] = '0' + (i%10); fwrite(s, 1, 4, f); - fwrite(&nPluginSize, 1, 4, f); - fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f); - fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f); + writeSwapDWORD = bswapLE32(nPluginSize); + fwrite(&writeSwapDWORD, 1, 4, f); + + // Copy Information To Be Written for ByteSwapping + memcpy(&writePluginInfo, &p->Info, sizeof(SNDMIXPLUGININFO)); + writePluginInfo.dwPluginId1 = bswapLE32(p->Info.dwPluginId1); + writePluginInfo.dwPluginId2 = bswapLE32(p->Info.dwPluginId2); + writePluginInfo.dwInputRouting = bswapLE32(p->Info.dwInputRouting); + writePluginInfo.dwOutputRouting = bswapLE32(p->Info.dwOutputRouting); + for (UINT j=0; j<4; j++) + { + writePluginInfo.dwReserved[j] = bswapLE32(p->Info.dwReserved[j]); + } + + fwrite(&writePluginInfo, 1, sizeof(SNDMIXPLUGININFO), f); + writeSwapDWORD = bswapLE32(m_MixPlugins[i].nPluginDataSize); + fwrite(&writeSwapDWORD, 1, 4, f); if (m_MixPlugins[i].pPluginData) { fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f); @@ -1485,6 +1432,7 @@ if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0) { nChInfo = j+1; + chinfo[j] = bswapLE32(chinfo[j]); // inplace BS } } } @@ -1492,10 +1440,11 @@ { if (f) { - nPluginSize = 0x58464843; + nPluginSize = bswapLE32(0x58464843); fwrite(&nPluginSize, 1, 4, f); nPluginSize = nChInfo*4; - fwrite(&nPluginSize, 1, 4, f); + writeSwapDWORD = bswapLE32(nPluginSize); + fwrite(&writeSwapDWORD, 1, 4, f); fwrite(chinfo, 1, nPluginSize, f); } nTotalSize += nChInfo*4 + 8; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_mdl.cxx --- a/src/modplug/load_mdl.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_mdl.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -76,31 +76,8 @@ } break; case 0x0F: command = CMD_SPEED; break; - - case 0x10: - if ((param & 0xF0) != 0xE0) { - command = CMD_VOLUMESLIDE; - if ((param & 0xF0) == 0xF0) { - param = ((param << 4) | 0x0F); - } else { - param >>= 2; - if (param > 0xF) - param = 0xF; - param <<= 4; - } - } - break; - case 0x20: - if ((param & 0xF0) != 0xE0) { - command = CMD_VOLUMESLIDE; - if ((param & 0xF0) != 0xF0) { - param >>= 2; - if (param > 0xF) - param = 0xF; - } - } - break; - + case 0x10: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break; + case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break; case 0x30: command = CMD_RETRIG; break; case 0x40: command = CMD_TREMOLO; break; case 0x50: command = CMD_TREMOR; break; @@ -217,7 +194,7 @@ UINT nvolenv, npanenv, npitchenv; if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((bswapLE32(pmsh->id) != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; + if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; memset(patterntracks, 0, sizeof(patterntracks)); memset(smpinfo, 0, sizeof(smpinfo)); memset(insvolenv, 0, sizeof(insvolenv)); @@ -227,13 +204,10 @@ pvolenv = ppanenv = ppitchenv = NULL; nvolenv = npanenv = npitchenv = 0; m_nSamples = m_nInstruments = 0; - m_dwSongFlags |= SONG_INSTRUMENTMODE; while (dwMemPos+6 < dwMemLength) { block = *((WORD *)(lpStream+dwMemPos)); blocklen = *((DWORD *)(lpStream+dwMemPos+2)); - block = bswapLE16(block); - blocklen = bswapLE32(blocklen); dwMemPos += 6; if (dwMemPos + blocklen > dwMemLength) { @@ -246,12 +220,10 @@ case 0x4E49: pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos); memcpy(m_szNames[0], pmib->songname, 32); - norders = bswapLE16(pmib->norders); + norders = pmib->norders; if (norders > MAX_ORDERS) norders = MAX_ORDERS; - m_nRestartPos = bswapLE16(pmib->repeatpos); + m_nRestartPos = pmib->repeatpos; m_nDefaultGlobalVolume = pmib->globalvol; - if (m_nDefaultGlobalVolume == 255) - m_nDefaultGlobalVolume++; m_nDefaultTempo = pmib->tempo; m_nDefaultSpeed = pmib->speed; m_nChannels = 4; @@ -290,12 +262,11 @@ pmpd = (MDLPATTERNDATA *)(lpStream + dwPos); if (pmpd->channels > 32) break; PatternSize[i] = pmpd->lastrow+1; - PatternAllocSize[i] = pmpd->lastrow+1; if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels; dwPos += 18 + 2*pmpd->channels; for (j=0; jchannels; j++) { - patterntracks[i*32+j] = bswapLE16(pmpd->data[j]); + patterntracks[i*32+j] = pmpd->data[j]; } } break; @@ -303,7 +274,6 @@ case 0x5254: if (dwTrackPos) break; ntracks = *((WORD *)(lpStream+dwMemPos)); - ntracks = bswapLE16(ntracks); dwTrackPos = dwMemPos+2; break; // II: Instruments @@ -322,7 +292,7 @@ INSTRUMENTHEADER *penv = Headers[nins]; memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, lpStream+dwPos+2, 32); - penv->nGlobalVol = 128; + penv->nGlobalVol = 64; penv->nPPC = 5*12; for (j=0; jname, lpStream+dwPos+33, 8); pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41)); - pins->nC4Speed = bswapLE32(pins->nC4Speed); pins->nLength = *((DWORD *)(lpStream+dwPos+45)); - pins->nLength = bswapLE32(pins->nLength); pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49)); - pins->nLoopStart = bswapLE32(pins->nLoopStart); pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53)); - pins->nLoopEnd = bswapLE32(pins->nLoopEnd); if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP; pins->nGlobalVol = 64; if (lpStream[dwPos+58] & 0x01) @@ -428,7 +394,6 @@ } else { DWORD dwLen = *((DWORD *)(lpStream+dwPos)); - dwLen = bswapLE32(dwLen); dwPos += 4; if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4)) { @@ -466,23 +431,23 @@ for (UINT nve=0; nveVolEnv.nNodes = 15; + penv->nVolEnv = 15; for (UINT iv=0; iv<15; iv++) { if (iv) vtick += pve[iv*2+1]; - penv->VolEnv.Ticks[iv] = vtick; - penv->VolEnv.Values[iv] = pve[iv*2+2]; + penv->VolPoints[iv] = vtick; + penv->VolEnv[iv] = pve[iv*2+2]; if (!pve[iv*2+1]) { - penv->VolEnv.nNodes = iv+1; + penv->nVolEnv = iv+1; break; } } - penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pve[31] & 0x0F; + penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F; if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN; if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP; - penv->VolEnv.nLoopStart = pve[32] & 0x0F; - penv->VolEnv.nLoopEnd = pve[32] >> 4; + penv->nVolLoopStart = pve[32] & 0x0F; + penv->nVolLoopEnd = pve[32] >> 4; } } // Setup panning envelope @@ -492,22 +457,22 @@ for (UINT npe=0; npePanEnv.nNodes = 15; + penv->nPanEnv = 15; for (UINT iv=0; iv<15; iv++) { if (iv) vtick += ppe[iv*2+1]; - penv->PanEnv.Ticks[iv] = vtick; - penv->PanEnv.Values[iv] = ppe[iv*2+2]; + penv->PanPoints[iv] = vtick; + penv->PanEnv[iv] = ppe[iv*2+2]; if (!ppe[iv*2+1]) { - penv->PanEnv.nNodes = iv+1; + penv->nPanEnv = iv+1; break; } } if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN; if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP; - penv->PanEnv.nLoopStart = ppe[32] & 0x0F; - penv->PanEnv.nLoopEnd = ppe[32] >> 4; + penv->nPanLoopStart = ppe[32] & 0x0F; + penv->nPanLoopEnd = ppe[32] >> 4; } } } diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_med.cxx --- a/src/modplug/load_med.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_med.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -572,7 +572,6 @@ m_nChannels = 4; m_nSamples = pmsh->numsamples; if (m_nSamples > 63) m_nSamples = 63; - m_nStereoSeparation = ((pmsh2->mix_stereosep < 0) ? -32 : 32) * pmsh2->mix_stereosep; // Tempo m_nDefaultTempo = 125; deftempo = bswapBE16(pmsh->deftempo); @@ -812,7 +811,6 @@ if (!tracks) tracks = m_nChannels; if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue; PatternSize[iBlk] = lines; - PatternAllocSize[iBlk] = lines; MODCOMMAND *p = Patterns[iBlk]; LPBYTE s = (LPBYTE)(lpStream + dwPos + 2); UINT maxlen = tracks*lines*3; @@ -849,7 +847,6 @@ if (!tracks) tracks = m_nChannels; if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue; PatternSize[iBlk] = (WORD)lines; - PatternAllocSize[iBlk] = (WORD)lines; DWORD dwBlockInfo = bswapBE32(pmb->info); if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO))) { diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_mod.cxx --- a/src/modplug/load_mod.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_mod.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -110,7 +110,7 @@ case CMD_PATTERNBREAK: command = 0x0D; param = ((param / 10) << 4) | (param % 10); break; case CMD_MODCMDEX: command = 0x0E; break; case CMD_SPEED: command = 0x0F; if (param > 0x20) param = 0x20; break; - case CMD_TEMPO: if (param > 0x20) { command = 0x0F; break; } return 0; + case CMD_TEMPO: if (param > 0x20) { command = 0x0F; break; } case CMD_GLOBALVOLUME: command = 'G' - 55; break; case CMD_GLOBALVOLSLIDE: command = 'H' - 55; break; case CMD_KEYOFF: command = 'K' - 55; break; @@ -192,7 +192,7 @@ || (IsMagic(s, "M&K!")) || (IsMagic(s, "N.T."))) m_nChannels = 4; else if ((IsMagic(s, "CD81")) || (IsMagic(s, "OKTA"))) m_nChannels = 8; else if ((s[0]=='F') && (s[1]=='L') && (s[2]=='T') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else - if ((s[0]>='4') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else + if ((s[0]>='2') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else if ((s[0]=='1') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 10; else if ((s[0]=='2') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 20; else if ((s[0]=='3') && (s[1]>='0') && (s[1]<='2') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 30; else @@ -228,13 +228,19 @@ } psmp->nLoopStart = loopstart; psmp->nLoopEnd = loopstart + looplen; - if (psmp->nLength < 2) psmp->nLength = 0; + if (psmp->nLength < 4) psmp->nLength = 0; if (psmp->nLength) { UINT derr = 0; if (psmp->nLoopStart >= psmp->nLength) { psmp->nLoopStart = psmp->nLength-1; derr|=1; } if (psmp->nLoopEnd > psmp->nLength) { psmp->nLoopEnd = psmp->nLength; derr |= 1; } if (psmp->nLoopStart > psmp->nLoopEnd) derr |= 1; + if ((psmp->nLoopStart > psmp->nLoopEnd) || (psmp->nLoopEnd <= 8) + || (psmp->nLoopEnd - psmp->nLoopStart <= 4)) + { + psmp->nLoopStart = 0; + psmp->nLoopEnd = 0; + } if (psmp->nLoopEnd > psmp->nLoopStart) { psmp->uFlags |= CHN_LOOP; @@ -300,10 +306,11 @@ for (UINT ich=0; ich= dwMemLength) break; MODCOMMAND *m = Patterns[ipat]; LPCBYTE p = lpStream + dwMemPos; @@ -357,27 +363,22 @@ #ifndef MODPLUG_NO_FILESAVE +#pragma warning(disable:4100) -#ifdef MSC_VER -#pragma warning(disable:4100) -#endif - -BOOL CSoundFile::SaveMod(diskwriter_driver_t *fp, UINT nPacking) +BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking) //---------------------------------------------------------- { BYTE insmap[32]; UINT inslen[32]; BYTE bTab[32]; BYTE ord[128]; - UINT chanlim; + FILE *f; - if ((!m_nChannels) || (!fp)) return FALSE; - chanlim = GetHighestUsedChannel(); - if (chanlim < 4) chanlim = 4; - + if ((!m_nChannels) || (!lpszFileName)) return FALSE; + if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; memset(ord, 0, sizeof(ord)); memset(inslen, 0, sizeof(inslen)); - if (m_dwSongFlags & SONG_INSTRUMENTMODE) + if (m_nInstruments) { memset(insmap, 0, sizeof(insmap)); for (UINT i=1; i<32; i++) if (Headers[i]) @@ -393,28 +394,25 @@ for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i; } // Writing song name - fp->o(fp, (const unsigned char *)m_szNames, 20); + fwrite(m_szNames, 20, 1, f); // Writing instrument definition for (UINT iins=1; iins<=31; iins++) { MODINSTRUMENT *pins = &Ins[insmap[iins]]; - WORD gg; - FrequencyToTranspose(pins); - memcpy(bTab, m_szNames[iins],22); inslen[iins] = pins->nLength; if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0; - gg = bswapBE16(inslen[iins] / 2); - memcpy(bTab+22, &gg, 2); + bTab[22] = inslen[iins] >> 9; + bTab[23] = inslen[iins] >> 1; if (pins->RelativeTone < 0) bTab[24] = 0x08; else if (pins->RelativeTone > 0) bTab[24] = 0x07; else bTab[24] = (BYTE)XM2MODFineTune(pins->nFineTune); - bTab[25] = pins->nVolume / 4; - gg = bswapBE16(pins->nLoopStart / 2); - memcpy(bTab+26, &gg, 2); - gg = bswapBE16((pins->nLoopEnd - pins->nLoopStart)/ 2); - memcpy(bTab+28, &gg, 2); - fp->o(fp,(const unsigned char *) bTab, 30); + bTab[25] = pins->nVolume >> 2; + bTab[26] = pins->nLoopStart >> 9; + bTab[27] = pins->nLoopStart >> 1; + bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9; + bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1; + fwrite(bTab, 30, 1, f); } // Writing number of patterns UINT nbp=0, norders=128; @@ -429,27 +427,26 @@ } bTab[0] = norders; bTab[1] = m_nRestartPos; - fp->o(fp, (const unsigned char *)bTab, 2); + fwrite(bTab, 2, 1, f); // Writing pattern list if (norders) memcpy(ord, Order, norders); - fp->o(fp, (const unsigned char *)ord, 128); + fwrite(ord, 128, 1, f); // Writing signature - if (chanlim == 4) + if (m_nChannels == 4) lstrcpy((LPSTR)&bTab, "M.K."); else - wsprintf((LPSTR)&bTab, "%uCHN", chanlim); - fp->o(fp, (const unsigned char *)bTab, 4); + wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels); + fwrite(bTab, 4, 1, f); // Writing patterns for (UINT ipat=0; ipat> 8; param &= 0xFF; @@ -464,16 +461,16 @@ period = ProTrackerPeriodTable[period]; } UINT instr = (m->instr > 31) ? 0 : m->instr; - p[0] = ((period / 256) & 0x0F) | (instr & 0x10); - p[1] = period % 256; + p[0] = ((period >> 8) & 0x0F) | (instr & 0x10); + p[1] = period & 0xFF; p[2] = ((instr & 0x0F) << 4) | (command & 0x0F); p[3] = param; } - fp->o(fp, (const unsigned char *)s, chanlim*4); + fwrite(s, m_nChannels, 4, f); } else { - memset(s, 0, chanlim*4); - fp->o(fp, (const unsigned char *)s, chanlim*4); + memset(s, 0, m_nChannels*4); + fwrite(s, m_nChannels, 4, f); } } // Writing instruments @@ -486,18 +483,16 @@ { if ((nPacking) && (CanPackSample((char *)pins->pSample, inslen[ismpd], nPacking))) { - fp->o(fp, (const unsigned char *)"ADPCM", 5); + fwrite("ADPCM", 1, 5, f); flags = RS_ADPCM4; } } #endif - WriteSample(fp, pins, flags, inslen[ismpd]); + WriteSample(f, pins, flags, inslen[ismpd]); } + fclose(f); return TRUE; } -#ifdef MSC_VER #pragma warning(default:4100) -#endif - #endif // MODPLUG_NO_FILESAVE diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_mt2.cxx --- a/src/modplug/load_mt2.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_mt2.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -282,7 +282,6 @@ Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen); #endif PatternSize[iPat] = nLines; - PatternAllocSize[iPat] = nLines; Patterns[iPat] = AllocatePattern(nLines, m_nChannels); if (!Patterns[iPat]) return TRUE; MODCOMMAND *m = Patterns[iPat]; @@ -396,7 +395,6 @@ #endif memset(InstrMap, 0, sizeof(InstrMap)); m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1; - m_dwSongFlags |= SONG_INSTRUMENTMODE; for (UINT iIns=1; iIns<=255; iIns++) { if (dwMemPos+36 > dwMemLength) return TRUE; @@ -410,7 +408,7 @@ { memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, pmi->szName, 32); - penv->nGlobalVol = 128; + penv->nGlobalVol = 64; penv->nPan = 128; for (UINT i=0; i<120; i++) { @@ -462,7 +460,7 @@ for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv]) { MT2ENVELOPE *pme = pehdr[iEnv]; - int *pEnvPoints = NULL; + WORD *pEnvPoints = NULL; BYTE *pEnvData = NULL; #ifdef MT2DEBUG Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints); @@ -474,12 +472,12 @@ if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME; if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN; if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP; - penv->VolEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pme->nSustainPos; - penv->VolEnv.nLoopStart = pme->nLoopStart; - penv->VolEnv.nLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->VolEnv.Ticks; - pEnvData = penv->VolEnv.Values; + penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; + penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos; + penv->nVolLoopStart = pme->nLoopStart; + penv->nVolLoopEnd = pme->nLoopEnd; + pEnvPoints = penv->VolPoints; + pEnvData = penv->VolEnv; break; // Panning Envelope @@ -487,12 +485,12 @@ if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING; if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN; if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP; - penv->PanEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->PanEnv.nSustainStart = penv->PanEnv.nSustainEnd = pme->nSustainPos; - penv->PanEnv.nLoopStart = pme->nLoopStart; - penv->PanEnv.nLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->PanEnv.Ticks; - pEnvData = penv->PanEnv.Values; + penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; + penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos; + penv->nPanLoopStart = pme->nLoopStart; + penv->nPanLoopEnd = pme->nLoopEnd; + pEnvPoints = penv->PanPoints; + pEnvData = penv->PanEnv; break; // Pitch/Filter envelope @@ -500,12 +498,12 @@ if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH; if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN; if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP; - penv->PitchEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints; - penv->PitchEnv.nSustainStart = penv->PitchEnv.nSustainEnd = pme->nSustainPos; - penv->PitchEnv.nLoopStart = pme->nLoopStart; - penv->PitchEnv.nLoopEnd = pme->nLoopEnd; - pEnvPoints = penv->PitchEnv.Ticks; - pEnvData = penv->PitchEnv.Values; + penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints; + penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos; + penv->nPitchLoopStart = pme->nLoopStart; + penv->nPitchLoopEnd = pme->nLoopEnd; + pEnvPoints = penv->PitchPoints; + pEnvData = penv->PitchEnv; } // Envelope data if ((pEnvPoints) && (pEnvData) && (pedata[iEnv])) @@ -594,7 +592,7 @@ Ins[nSmp].nVibType = pmi->bVibType; Ins[nSmp].nVibSweep = pmi->bVibSweep; Ins[nSmp].nVibDepth = pmi->bVibDepth; - Ins[nSmp].nVibRate = pmi->bVibRate/4; + Ins[nSmp].nVibRate = pmi->bVibRate; } } } diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_mtm.cxx --- a/src/modplug/load_mtm.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_mtm.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -59,8 +59,8 @@ || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) return FALSE; strncpy(m_szNames[0], pmh->songname, 20); m_szNames[0][20] = 0; - if (dwMemPos + 37*pmh->numsamples + 128 + 192*bswapLE16(pmh->numtracks) - + 64 * (pmh->lastpattern+1) + bswapLE16(pmh->commentsize) >= dwMemLength) return FALSE; + if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks + + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) return FALSE; m_nType = MOD_TYPE_MTM; m_nSamples = pmh->numsamples; m_nChannels = pmh->numchannels; @@ -72,12 +72,12 @@ m_szNames[i][22] = 0; Ins[i].nVolume = pms->volume << 2; Ins[i].nGlobalVol = 64; - DWORD len = bswapLE32(pms->length); + DWORD len = pms->length; if ((len > 4) && (len <= MAX_SAMPLE_LENGTH)) { Ins[i].nLength = len; - Ins[i].nLoopStart = bswapLE32(pms->reppos); - Ins[i].nLoopEnd = bswapLE32(pms->repend); + Ins[i].nLoopStart = pms->reppos; + Ins[i].nLoopEnd = pms->repend; if (Ins[i].nLoopEnd > Ins[i].nLength) Ins[i].nLoopEnd = Ins[i].nLength; if (Ins[i].nLoopStart + 4 >= Ins[i].nLoopEnd) Ins[i].nLoopStart = Ins[i].nLoopEnd = 0; if (Ins[i].nLoopEnd) Ins[i].uFlags |= CHN_LOOP; @@ -104,14 +104,13 @@ dwMemPos += 128; // Reading Patterns LPCBYTE pTracks = lpStream + dwMemPos; - dwMemPos += 192 * bswapLE16(pmh->numtracks); + dwMemPos += 192 * pmh->numtracks; LPWORD pSeq = (LPWORD)(lpStream + dwMemPos); for (UINT pat=0; pat<=pmh->lastpattern; pat++) { PatternSize[pat] = 64; - PatternAllocSize[pat] = 64; if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break; - for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= bswapLE16(pmh->numtracks)) && (n < m_nChannels)) + for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels)) { LPCBYTE p = pTracks + 192 * (pSeq[n]-1); MODCOMMAND *m = Patterns[pat] + n; @@ -133,9 +132,9 @@ pSeq += 32; } dwMemPos += 64*(pmh->lastpattern+1); - if (bswapLE16(pmh->commentsize) && (dwMemPos + bswapLE16(pmh->commentsize) < dwMemLength)) + if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) { - UINT n = bswapLE16(pmh->commentsize); + UINT n = pmh->commentsize; m_lpszSongComments = new char[n+1]; if (m_lpszSongComments) { @@ -150,7 +149,7 @@ } } } - dwMemPos += bswapLE16(pmh->commentsize); + dwMemPos += pmh->commentsize; // Reading Samples for (UINT ismp=1; ismp<=m_nSamples; ismp++) { diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_okt.cxx --- a/src/modplug/load_okt.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_okt.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -120,7 +120,6 @@ if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; MODCOMMAND *m = Patterns[npat]; PatternSize[npat] = rows; - PatternAllocSize[npat] = rows; UINT imax = m_nChannels*rows; for (UINT i=0; iid); + pfh_swap.len = bswapLE32(pfh->len); + pfh_swap.listid = bswapLE32(pfh->listid); + // Chunk0: "PSM ",filesize,"FILE" if (dwMemLength < 256) return FALSE; - if (bswapLE32(pfh->id) == PSM_ID_OLD) + if (pfh_swap.id == PSM_ID_OLD) { #ifdef PSM_LOG - printf("Old PSM format not supported\n"); + Log("Old PSM format not supported\n"); #endif return FALSE; } - if ((bswapLE32(pfh->id) != PSM_ID_NEW) - || (bswapLE32(pfh->len)+12 > dwMemLength) - || (bswapLE32(pfh->listid) != IFFID_FILE)) return FALSE; + if ((pfh_swap.id != PSM_ID_NEW) || (pfh_swap.len+12 > dwMemLength) || (pfh_swap.listid != IFFID_FILE)) return FALSE; m_nType = MOD_TYPE_PSM; m_nChannels = 16; m_nSamples = 0; @@ -108,16 +111,19 @@ UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40; ChnSettings[iChPan].nPan = pan; } - m_szNames[0][0]=0; while (dwMemPos+8 < dwMemLength) { PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); - if ((bswapLE32(pchunk->len) >= dwMemLength - 8) - || (dwMemPos + bswapLE32(pchunk->len) + 8 > dwMemLength)) break; + + pchunk->id = bswapLE32(pchunk->id); + pchunk->len = bswapLE32(pchunk->len); + pchunk->listid = bswapLE32(pchunk->listid); + + if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break; dwMemPos += 8; PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = bswapLE32(pchunk->len); - if (len) switch(bswapLE32(pchunk->id)) + ULONG len = pchunk->len; + if (len) switch(pchunk->id) { // "TITL": Song title case IFFID_TITL: @@ -146,16 +152,23 @@ m_nSamples++; MODINSTRUMENT *pins = &Ins[m_nSamples]; PSMSAMPLE *psmp = (PSMSAMPLE *)pdata; - smpnames[m_nSamples] = bswapLE32(psmp->smpid); + + psmp->smpid = bswapLE32(psmp->smpid); + psmp->length = bswapLE32(psmp->length); + psmp->loopstart = bswapLE32(psmp->loopstart); + psmp->loopend = bswapLE32(psmp->loopend); + psmp->samplerate = bswapLE32(psmp->samplerate); + + smpnames[m_nSamples] = psmp->smpid; memcpy(m_szNames[m_nSamples], psmp->samplename, 31); m_szNames[m_nSamples][31] = 0; samplemap[m_nSamples-1] = (BYTE)m_nSamples; // Init sample pins->nGlobalVol = 0x40; - pins->nC4Speed = bswapLE32(psmp->samplerate); - pins->nLength = bswapLE32(psmp->length); - pins->nLoopStart = bswapLE32(psmp->loopstart); - pins->nLoopEnd = bswapLE32(psmp->loopend); + pins->nC4Speed = psmp->samplerate; + pins->nLength = psmp->length; + pins->nLoopStart = psmp->loopstart; + pins->nLoopEnd = psmp->loopend; pins->nPan = 128; pins->nVolume = (psmp->defvol+1) * 2; pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0; @@ -184,7 +197,7 @@ } #endif } - dwMemPos += bswapLE32(pchunk->len); + dwMemPos += pchunk->len; } // Step #1: convert song structure PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8); @@ -197,12 +210,16 @@ while (dwMemPos + 8 < dwSongEnd) { PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos); + + pchunk->id = bswapLE32(pchunk->id); + pchunk->len = bswapLE32(pchunk->len); + pchunk->listid = bswapLE32(pchunk->listid); + dwMemPos += 8; - if ((bswapLE32(pchunk->len) > dwSongEnd) - || (dwMemPos + bswapLE32(pchunk->len) > dwSongEnd)) break; + if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break; PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = bswapLE32(pchunk->len); - switch(bswapLE32(pchunk->id)) + ULONG len = pchunk->len; + switch(pchunk->id) { case IFFID_OPLH: if (len >= 0x20) @@ -248,7 +265,7 @@ } break; } - dwMemPos += bswapLE32(pchunk->len); + dwMemPos += pchunk->len; } } @@ -256,66 +273,85 @@ for (UINT nPat=0; nPatrows); - if (len > bswapLE32(pPsmPat->size)) len = bswapLE32(pPsmPat->size); + + pPsmPat->size = bswapLE32(pPsmPat->size); + pPsmPat->name = bswapLE32(pPsmPat->name); + pPsmPat->rows = bswapLE16(pPsmPat->rows); + + ULONG len = *(DWORD *)(lpStream+patptrs[nPat]+4) - 12; + UINT nRows = pPsmPat->rows; + if (len > pPsmPat->size) len = pPsmPat->size; if ((nRows < 64) || (nRows > 256)) nRows = 64; PatternSize[nPat] = nRows; - PatternAllocSize[nPat] = nRows; if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break; MODCOMMAND *m = Patterns[nPat]; - MODCOMMAND *sp, dummy; BYTE *p = pPsmPat->data; UINT pos = 0; UINT row = 0; - UINT rowlim; + UINT oldch = 0; + BOOL bNewRow = FALSE; #ifdef PSM_LOG - //printf("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); + Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); #endif - rowlim = bswapLE16(pPsmPat->reserved1)-2; while ((row < nRows) && (pos+1 < len)) { - UINT flags, ch; - if ((pos+1) >= rowlim) { - pos = rowlim; - rowlim = (((int)p[pos+1])<<8) - | ((int)p[pos+0]); - m += m_nChannels; - row++; - rowlim += pos; - pos += 2; + UINT flags = p[pos++]; + UINT ch = p[pos++]; + + #ifdef PSM_LOG + //Log("flags+ch: %02X.%02X\n", flags, ch); + #endif + if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/) + { + if ((pos+1= m_nChannels) { + if ((pos >= len) || (row >= nRows)) break; + if (!(flags & 0xf0)) + { #ifdef PSM_LOG - printf("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); + //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]); #endif - sp = &dummy; - } else { - sp = &m[ch]; + row++; + m += m_nChannels; + bNewRow = TRUE; + oldch = ch; + continue; + } + bNewRow = FALSE; + if (ch >= m_nChannels) + { + #ifdef PSM_LOG + if (!nPat) Log("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); + #endif + ch = 0; } // Note + Instr - if ((flags & 0x80) && (pos+1 < len)) + if ((flags & 0x40) && (pos+1 < len)) { UINT note = p[pos++]; - note = (note>>4)*12+(note&0x0f)+12+1; - if (note > 0x80) note = 0; - sp->note = note; - } - if ((flags & 0x40) && (pos+1 < len)) - { UINT nins = p[pos++]; #ifdef PSM_LOG - if ((!nPat) && (nins >= m_nSamples)) printf("WARNING: invalid instrument number (%d)\n", nins); + //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins); + if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins); #endif - sp->instr = samplemap[nins]; + if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1; + m[ch].instr = samplemap[nins]; + m[ch].note = note; } // Volume if ((flags & 0x20) && (pos < len)) { - sp->volcmd = VOLCMD_VOLUME; - sp->vol = p[pos++] / 2; + m[ch].volcmd = VOLCMD_VOLUME; + m[ch].vol = p[pos++] / 2; } // Effect if ((flags & 0x10) && (pos+1 < len)) @@ -323,94 +359,40 @@ UINT command = p[pos++]; UINT param = p[pos++]; // Convert effects - switch(command & 0x3F) + switch(command) { // 01: fine volslide up - case 0x01: -#if PSM_LOG - printf("fvup command pat=%d row=%d ch=%d %02x %02x\n", - nPat, - row,1+ch, - command, param); -#endif -#if 0 - if (!sp->volcmd) { - sp->volcmd = VOLCMD_FINEVOLUP; - sp->vol = (param >> 1) & 0xF; - command = CMD_PORTAMENTOUP; - param>>=4; param |= 0xf0; - if (param == 240) param=241; - } else { -#endif - command = CMD_VOLUMESLIDE; - param |= 0x0f; - if (param == 15) param=31; - break; - // 02: volslide up - case 0x02: command = CMD_VOLUMESLIDE; param>>=1; param<<=4; break; - // 03: fine volslide down - case 0x03: -#if PSM_LOG - printf("fvdown command pat=%d row=%d ch=%d %02x %02x\n", - nPat, - row,1+ch, - command, param); -#endif -#if 0 - if (!sp->volcmd) { - sp->volcmd = VOLCMD_FINEVOLDOWN; - sp->vol = (param >> 2) & 0xF; - if (!sp->vol) sp->vol = 1; - command = CMD_PORTAMENTODOWN; - } -#endif - command = CMD_VOLUMESLIDE; - param>>=4; param |= 0xf0; - if (param == 240) param=241; - break; - // 04: volslide down - case 0x04: command = CMD_VOLUMESLIDE; param>>=1; break; + case 0x01: command = CMD_VOLUMESLIDE; param |= 0x0f; break; + // 04: fine volslide down + case 0x04: command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break; // 0C: portamento up case 0x0C: command = CMD_PORTAMENTOUP; param = (param+1)/2; break; // 0E: portamento down case 0x0E: command = CMD_PORTAMENTODOWN; param = (param+1)/2; break; - // 0F: tone portamento - case 0x0F: command = CMD_TONEPORTAMENTO; param = param/4; break; - // 15: vibrato - case 0x15: command = CMD_VIBRATO; break; - // 29: wtf - case 0x29: pos += 2; break; - // 2A: retrig - case 0x2A: command = CMD_RETRIG; break; // 33: Position Jump case 0x33: command = CMD_POSITIONJUMP; break; // 34: Pattern break case 0x34: command = CMD_PATTERNBREAK; break; // 3D: speed - case 0x3D: command = CMD_SPEED; - if (!row && !nPat) - m_nDefaultSpeed = param; - break; + case 0x3D: command = CMD_SPEED; break; // 3E: tempo - case 0x3E: command = CMD_TEMPO; - if (!row && !nPat) - m_nDefaultTempo = param; - break; + case 0x3E: command = CMD_TEMPO; break; // Unknown default: #ifdef PSM_LOG - printf("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); + Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); #endif command = param = 0; } - sp->command = (BYTE)command; - sp->param = (BYTE)param; + m[ch].command = (BYTE)command; + m[ch].param = (BYTE)param; } + oldch = ch; } #ifdef PSM_LOG if (pos < len) { -// printf("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); + Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); } #endif } diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_ptm.cxx --- a/src/modplug/load_ptm.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_ptm.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -115,10 +115,10 @@ { UINT smpflg = RS_PCM8D; DWORD samplepos; - pins->nLength = bswapLE32(*psmp->length); - pins->nLoopStart = bswapLE32(*psmp->loopbeg); - pins->nLoopEnd = bswapLE32(*psmp->loopend); - samplepos = bswapLE32(*psmp->fileofs); + pins->nLength = bswapLE32(*(LPDWORD)(psmp->length)); + pins->nLoopStart = bswapLE32(*(LPDWORD)(psmp->loopbeg)); + pins->nLoopEnd = bswapLE32(*(LPDWORD)(psmp->loopend)); + samplepos = bswapLE32(*(LPDWORD)(&psmp->fileofs)); if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP; if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP; if (psmp->sampletype & 16) @@ -141,7 +141,6 @@ dwMemPos = ((UINT)pfh.patseg[ipat]) << 4; if ((!dwMemPos) || (dwMemPos >= dwMemLength)) continue; PatternSize[ipat] = 64; - PatternAllocSize[ipat] = 64; if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break; // MODCOMMAND *m = Patterns[ipat]; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_s3m.cxx --- a/src/modplug/load_s3m.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_s3m.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -289,14 +289,14 @@ { UINT j = bswapLE32(*((LPDWORD)(s+0x10))); if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 2) j = 0; + if (j < 4) j = 0; Ins[iSmp].nLength = j; j = bswapLE32(*((LPDWORD)(s+0x14))); if (j >= Ins[iSmp].nLength) j = Ins[iSmp].nLength - 1; Ins[iSmp].nLoopStart = j; j = bswapLE32(*((LPDWORD)(s+0x18))); if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 2) j = 0; + if (j < 4) j = 0; if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength; Ins[iSmp].nLoopEnd = j; j = s[0x1C]; @@ -319,15 +319,11 @@ // Reading patterns for (UINT iPat=0; iPat dwMemLength) continue; + UINT nInd = ((DWORD)ptr[nins+iPat]) << 4; + if (nInd + 0x40 > dwMemLength) continue; WORD len = bswapLE16(*((WORD *)(lpStream+nInd))); nInd += 2; PatternSize[iPat] = 64; - PatternAllocSize[iPat] = 64; if ((!len) || (nInd + len > dwMemLength - 6) || ((Patterns[iPat] = AllocatePattern(64, m_nChannels)) == NULL)) continue; LPBYTE src = (LPBYTE)(lpStream+nInd); @@ -387,11 +383,8 @@ // Reading samples for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw])) { - UINT flags; - if (insflags[iRaw-1] & 4) - flags = (psfh.version == 1) ? RS_PCM16S : RS_PCM16U; - else - flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; + UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; + if (insflags[iRaw-1] & 4) flags += 5; if (insflags[iRaw-1] & 2) flags |= RSF_STEREO; if (inspack[iRaw-1] == 4) flags = RS_ADPCM4; dwMemPos = insfile[iRaw]; @@ -405,10 +398,7 @@ #ifndef MODPLUG_NO_FILESAVE - -#ifdef MSC_VER #pragma warning(disable:4100) -#endif static BYTE S3MFiller[16] = { @@ -417,18 +407,19 @@ }; -BOOL CSoundFile::SaveS3M(diskwriter_driver_t *fp, UINT nPacking) +BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking) //---------------------------------------------------------- { + FILE *f; BYTE header[0x60]; UINT nbo,nbi,nbp,i; - UINT chanlim; WORD patptr[128]; WORD insptr[128]; BYTE buffer[5*1024]; S3MSAMPLESTRUCT insex[128]; - if ((!m_nChannels) || (!fp)) return FALSE; + if ((!m_nChannels) || (!lpszFileName)) return FALSE; + if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; // Writing S3M header memset(header, 0, sizeof(header)); memset(insex, 0, sizeof(insex)); @@ -436,14 +427,12 @@ header[0x1B] = 0; header[0x1C] = 0x1A; header[0x1D] = 0x10; - nbo = (GetNumPatterns()); - if (nbo == 0) - nbo = 2; - else if (nbo & 1) - nbo++; - header[0x20] = nbo & 0xFF; + nbo = (GetNumPatterns() + 15) & 0xF0; + if (!nbo) nbo = 16; + header[0x20] = nbo & 0xFF; header[0x21] = nbo >> 8; - nbi = m_nSamples; + nbi = m_nInstruments; + if (!nbi) nbi = m_nSamples; if (nbi > 99) nbi = 99; header[0x22] = nbi & 0xFF; header[0x23] = nbi >> 8; @@ -467,67 +456,55 @@ header[0x32] = m_nDefaultTempo; header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80; // Stereo header[0x35] = 0xFC; - - chanlim = GetHighestUsedChannel()+1; - if (chanlim < 4) chanlim = 4; - if (chanlim > 32) chanlim = 32; - for (i=0; i<32; i++) { - if (i < chanlim) + if (i < m_nChannels) { UINT tmp = (i & 0x0F) >> 1; header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp); } else header[0x40+i] = 0xFF; } - fp->o(fp, (const unsigned char *)header, 0x60); - fp->o(fp, (const unsigned char *)Order, nbo); + fwrite(header, 0x60, 1, f); + fwrite(Order, nbo, 1, f); memset(patptr, 0, sizeof(patptr)); memset(insptr, 0, sizeof(insptr)); UINT ofs0 = 0x60 + nbo; - UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0); + UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0) + 0x20; UINT ofs = ofs1; - if (header[0x35] == 0xFC) { - ofs += 0x20; - ofs1 += 0x20; - } - for (i=0; io(fp, (const unsigned char *)insptr, nbi*2); - fp->o(fp, (const unsigned char *)patptr, nbp*2); + for (i=0; i> 4) : 0x08; + chnpan[i] = 0x20 | (ChnSettings[i].nPan >> 4); } - fp->o(fp, (const unsigned char *)chnpan, 0x20); + fwrite(chnpan, 0x20, 1, f); } if ((nbi*2+nbp*2) & 0x0F) { - fp->o(fp, (const unsigned char *)S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F)); + fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f); } - fp->l(fp, ofs1); - ofs1 = fp->pos; - fp->o(fp, (const unsigned char *)insex, nbi*0x50); + ofs1 = ftell(f); + fwrite(insex, nbi, 0x50, f); // Packing patterns ofs += nbi*0x50; - fp->l(fp,ofs); for (i=0; ivol; UINT command = m->command; UINT param = m->param; - UINT inst = m->instr; - if (m_dwSongFlags & SONG_INSTRUMENTMODE - && note && inst) { - UINT nn = Headers[inst]->Keyboard[note]; - UINT nm = Headers[inst]->NoteMap[note]; - /* translate on save */ - note = nm; - inst = nn; - } - - - if ((note) || (inst)) b |= 0x20; + if ((note) || (m->instr)) b |= 0x20; if (!note) note = 0xFF; else if (note >= 0xFE) note = 0xFE; else if (note < 13) note = 0; else note -= 13; @@ -573,7 +539,7 @@ if (b & 0x20) { buffer[len++] = note; - buffer[len++] = inst; + buffer[len++] = m->instr; } if (b & 0x40) { @@ -594,31 +560,46 @@ buffer[0] = (len - 2) & 0xFF; buffer[1] = (len - 2) >> 8; len = (len+15) & (~0x0F); - - fp->o(fp, (const unsigned char *)buffer, len); + fwrite(buffer, len, 1, f); ofs += len; } // Writing samples for (i=1; i<=nbi; i++) { MODINSTRUMENT *pins = &Ins[i]; + if (m_nInstruments) + { + pins = Ins; + if (Headers[i]) + { + for (UINT j=0; j<128; j++) + { + UINT n = Headers[i]->Keyboard[j]; + if ((n) && (n < MAX_INSTRUMENTS)) + { + pins = &Ins[n]; + break; + } + } + } + } memcpy(insex[i-1].dosname, pins->name, 12); memcpy(insex[i-1].name, m_szNames[i], 28); memcpy(insex[i-1].scrs, "SCRS", 4); insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20); - insex[i-1].memseg = bswapLE16((WORD)((DWORD)ofs >> 4)); + insex[i-1].memseg = (WORD)((DWORD)ofs >> 4); if (pins->pSample) { insex[i-1].type = 1; - insex[i-1].length = bswapLE32(pins->nLength); - insex[i-1].loopbegin = bswapLE32(pins->nLoopStart); - insex[i-1].loopend = bswapLE32(pins->nLoopEnd); + insex[i-1].length = pins->nLength; + insex[i-1].loopbegin = pins->nLoopStart; + insex[i-1].loopend = pins->nLoopEnd; insex[i-1].vol = pins->nVolume / 4; insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0; if (pins->nC4Speed) - insex[i-1].finetune = bswapLE32(pins->nC4Speed); + insex[i-1].finetune = pins->nC4Speed; else - insex[i-1].finetune = bswapLE32(TransposeToFrequency(pins->RelativeTone, pins->nFineTune)); + insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune); UINT flags = RS_PCM8U; #ifndef NO_PACKING if (nPacking) @@ -643,28 +624,27 @@ flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U; } } - DWORD len = WriteSample(fp, pins, flags); + DWORD len = WriteSample(f, pins, flags); if (len & 0x0F) { - fp->o(fp, (const unsigned char *)S3MFiller, 0x10 - (len & 0x0F)); + fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f); } ofs += (len + 15) & (~0x0F); - } else { + } else + { insex[i-1].length = 0; } } // Updating parapointers - fp->l(fp, ofs0); - fp->o(fp, (const unsigned char *)insptr, nbi*2); - fp->o(fp, (const unsigned char *)patptr, nbp*2); - fp->l(fp, ofs1); - fp->o(fp, (const unsigned char *)insex, 0x50*nbi); + fseek(f, ofs0, SEEK_SET); + fwrite(insptr, nbi, 2, f); + fwrite(patptr, nbp, 2, f); + fseek(f, ofs1, SEEK_SET); + fwrite(insex, 0x50, nbi, f); + fclose(f); return TRUE; } -#ifdef MSC_VER #pragma warning(default:4100) -#endif - #endif // MODPLUG_NO_FILESAVE diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_stm.cxx --- a/src/modplug/load_stm.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_stm.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -94,14 +94,14 @@ STMSAMPLE *pStm = &phdr->sample[nIns]; // STM sample data memcpy(pIns->name, pStm->filename, 13); memcpy(m_szNames[nIns+1], pStm->filename, 12); - pIns->nC4Speed = pStm->c2spd; + pIns->nC4Speed = bswapLE16(pStm->c2spd); pIns->nGlobalVol = 64; pIns->nVolume = pStm->volume << 2; if (pIns->nVolume > 256) pIns->nVolume = 256; - pIns->nLength = pStm->length; - if ((pIns->nLength < 2) || (!pIns->nVolume)) pIns->nLength = 0; - pIns->nLoopStart = pStm->loopbeg; - pIns->nLoopEnd = pStm->loopend; + pIns->nLength = bswapLE16(pStm->length); + if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0; + pIns->nLoopStart = bswapLE16(pStm->loopbeg); + pIns->nLoopEnd = bswapLE16(pStm->loopend); if ((pIns->nLoopEnd > pIns->nLoopStart) && (pIns->nLoopEnd != 0xFFFF)) pIns->uFlags |= CHN_LOOP; } dwMemPos = sizeof(STMHEADER); @@ -111,7 +111,6 @@ { if (dwMemPos + 64*4*4 > dwMemLength) return TRUE; PatternSize[nPat] = 64; - PatternAllocSize[nPat] = 64; if ((Patterns[nPat] = AllocatePattern(64, m_nChannels)) == NULL) return TRUE; MODCOMMAND *m = Patterns[nPat]; STMNOTE *p = (STMNOTE *)(lpStream + dwMemPos); diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_ult.cxx --- a/src/modplug/load_ult.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_ult.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -135,7 +135,6 @@ if (nAllocPat < MAX_PATTERNS) { PatternSize[nAllocPat] = 64; - PatternAllocSize[nAllocPat] = 64; Patterns[nAllocPat] = AllocatePattern(64, m_nChannels); } } diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_wav.cxx --- a/src/modplug/load_wav.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_wav.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -18,53 +18,26 @@ //--------------------------------------------------------------- { DWORD dwMemPos = 0; - WAVEFILEHEADER phdr; - WAVEFORMATHEADER pfmt; - - if ((!lpStream) - || (dwMemLength < (DWORD)(sizeof(WAVEFORMATHEADER)+sizeof(WAVEFILEHEADER)))) - return FALSE; - - memcpy(&phdr, lpStream, sizeof(phdr)); - memcpy(&pfmt, lpStream+sizeof(phdr), sizeof(pfmt)); - - phdr.id_RIFF = bswapLE32(phdr.id_RIFF); - phdr.filesize = bswapLE32(phdr.filesize); - phdr.id_WAVE = bswapLE32(phdr.id_WAVE); - - pfmt.id_fmt = bswapLE32(pfmt.id_fmt); - pfmt.hdrlen = bswapLE32(pfmt.hdrlen); - pfmt.format = bswapLE16(pfmt.format); - pfmt.channels = bswapLE16(pfmt.channels); - pfmt.freqHz = bswapLE32(pfmt.freqHz); - pfmt.bytessec = bswapLE32(pfmt.bytessec); - pfmt.samplesize = bswapLE16(pfmt.samplesize); - pfmt.bitspersample = bswapLE16(pfmt.bitspersample); - - if ((phdr.id_RIFF != IFFID_RIFF) || (phdr.id_WAVE != IFFID_WAVE) - || (pfmt.id_fmt != IFFID_fmt)) return FALSE; - - dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt.hdrlen; - + WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream; + WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER)); + if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE; + if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE) + || (pfmt->id_fmt != IFFID_fmt)) return FALSE; + dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen; if ((dwMemPos + 8 >= dwMemLength) - || ((pfmt.format != WAVE_FORMAT_PCM) && (pfmt.format != WAVE_FORMAT_EXTENSIBLE)) - || (pfmt.channels > 4) - || (!pfmt.channels) - || (!pfmt.freqHz) - || (pfmt.bitspersample & 7) - || (pfmt.bitspersample < 8) - || (pfmt.bitspersample > 32)) return FALSE; - - WAVEDATAHEADER pdata; - + || ((pfmt->format != WAVE_FORMAT_PCM) && (pfmt->format != WAVE_FORMAT_EXTENSIBLE)) + || (pfmt->channels > 4) + || (!pfmt->channels) + || (!pfmt->freqHz) + || (pfmt->bitspersample & 7) + || (pfmt->bitspersample < 8) + || (pfmt->bitspersample > 32)) return FALSE; + WAVEDATAHEADER *pdata; for (;;) { - memcpy(&pdata, lpStream+dwMemPos, sizeof(pdata)); - pdata.id_data = bswapLE32(pdata.id_data); - pdata.length = bswapLE32(pdata.length); - - if (pdata.id_data == IFFID_data) break; - dwMemPos += pdata.length + 8; + pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos); + if (pdata->id_data == IFFID_data) break; + dwMemPos += pdata->length + 8; if (dwMemPos + 8 >= dwMemLength) return FALSE; } m_nType = MOD_TYPE_WAV; @@ -77,19 +50,18 @@ Order[0] = 0; Order[1] = 0xFF; PatternSize[0] = PatternSize[1] = 64; - PatternAllocSize[0] = PatternAllocSize[1] = 64; if ((Patterns[0] = AllocatePattern(64, 4)) == NULL) return TRUE; if ((Patterns[1] = AllocatePattern(64, 4)) == NULL) return TRUE; - UINT samplesize = (pfmt.channels * pfmt.bitspersample) >> 3; - UINT len = pdata.length, bytelen; + UINT samplesize = (pfmt->channels * pfmt->bitspersample) >> 3; + UINT len = pdata->length, bytelen; if (dwMemPos + len > dwMemLength - 8) len = dwMemLength - dwMemPos - 8; len /= samplesize; bytelen = len; - if (pfmt.bitspersample >= 16) bytelen *= 2; + if (pfmt->bitspersample >= 16) bytelen *= 2; if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH; if (!len) return TRUE; // Setting up module length - DWORD dwTime = ((len * 50) / pfmt.freqHz) + 1; + DWORD dwTime = ((len * 50) / pfmt->freqHz) + 1; DWORD framesperrow = (dwTime + 63) / 63; if (framesperrow < 4) framesperrow = 4; UINT norders = 1; @@ -115,7 +87,7 @@ pcmd[0].instr = 1; pcmd[1].note = pcmd[0].note; pcmd[1].instr = pcmd[0].instr; - m_nSamples = pfmt.channels; + m_nSamples = pfmt->channels; // Support for Multichannel Wave for (UINT nChn=0; nChnnLength = len; - pins->nC4Speed = pfmt.freqHz; + pins->nC4Speed = pfmt->freqHz; pins->nVolume = 256; pins->nPan = 128; pins->nGlobalVol = 64; - pins->uFlags = (WORD)((pfmt.bitspersample >= 16) ? CHN_16BIT : 0); + pins->uFlags = (WORD)((pfmt->bitspersample >= 16) ? CHN_16BIT : 0); pins->uFlags |= CHN_PANNING; if (m_nSamples > 1) { @@ -141,14 +113,14 @@ } } if ((pins->pSample = AllocateSample(bytelen+8)) == NULL) return TRUE; - if (pfmt.bitspersample >= 16) + if (pfmt->bitspersample >= 16) { - int slsize = pfmt.bitspersample >> 3; + int slsize = pfmt->bitspersample >> 3; signed short *p = (signed short *)pins->pSample; signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn*slsize+slsize-2); for (UINT i=0; i 4)) { int nIndex; - value = bswapLE16(*((short int *)psrc)); - nIndex = bswapLE16((short int)psrc[2]); + value = *((short int *)psrc); + nIndex = psrc[2]; psrc += 4; dwBytes -= 4; pdest[nPos++] = (short int)value; @@ -228,7 +200,7 @@ { delta = (BYTE)((*psrc) & 0x0F); } - int v = gIMAUnpackTable[nIndex % 90] >> 3; + int v = gIMAUnpackTable[nIndex] >> 3; if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2; if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1; if (delta & 4) v += gIMAUnpackTable[nIndex]; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/load_xm.cxx --- a/src/modplug/load_xm.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/load_xm.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -93,10 +93,10 @@ memcpy(m_szNames[0], lpStream+17, 20); dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60))); norders = bswapLE16(*((WORD *)(lpStream+64))); - if (norders > MAX_ORDERS) return FALSE; + if ((!norders) || (norders > MAX_ORDERS)) return FALSE; restartpos = bswapLE16(*((WORD *)(lpStream+66))); channels = bswapLE16(*((WORD *)(lpStream+68))); - if (channels > 64) return FALSE; + if ((!channels) || (channels > 64)) return FALSE; m_nType = MOD_TYPE_XM; m_nMinPeriod = 27; m_nMaxPeriod = 54784; @@ -107,7 +107,6 @@ instruments = bswapLE16(*((WORD *)(lpStream+72))); if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1; m_nInstruments = instruments; - m_dwSongFlags |= SONG_INSTRUMENTMODE; m_nSamples = 0; memcpy(&xmflags, lpStream+74, 2); xmflags = bswapLE16(xmflags); @@ -174,7 +173,6 @@ if (ipatmap < MAX_PATTERNS) { PatternSize[ipatmap] = rows; - PatternAllocSize[ipatmap] = rows; if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE; if (!packsize) continue; p = Patterns[ipatmap]; @@ -388,42 +386,42 @@ if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP; if (xmsh.vnum > 12) xmsh.vnum = 12; if (xmsh.pnum > 12) xmsh.pnum = 12; - penv->VolEnv.nNodes = xmsh.vnum; + penv->nVolEnv = xmsh.vnum; if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME; if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING; - penv->PanEnv.nNodes = xmsh.pnum; - penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = xmsh.vsustain; + penv->nPanEnv = xmsh.pnum; + penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain; if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN; - penv->VolEnv.nLoopStart = xmsh.vloops; - penv->VolEnv.nLoopEnd = xmsh.vloope; - if (penv->VolEnv.nLoopEnd >= 12) penv->VolEnv.nLoopEnd = 0; - if (penv->VolEnv.nLoopStart >= penv->VolEnv.nLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP; - penv->PanEnv.nSustainStart = penv->PanEnv.nSustainEnd = xmsh.psustain; + penv->nVolLoopStart = xmsh.vloops; + penv->nVolLoopEnd = xmsh.vloope; + if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0; + if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP; + penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain; if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN; - penv->PanEnv.nLoopStart = xmsh.ploops; - penv->PanEnv.nLoopEnd = xmsh.ploope; - if (penv->PanEnv.nLoopEnd >= 12) penv->PanEnv.nLoopEnd = 0; - if (penv->PanEnv.nLoopStart >= penv->PanEnv.nLoopEnd) penv->dwFlags &= ~ENV_PANLOOP; - penv->nGlobalVol = 128; + penv->nPanLoopStart = xmsh.ploops; + penv->nPanLoopEnd = xmsh.ploope; + if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0; + if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP; + penv->nGlobalVol = 64; for (UINT ienv=0; ienv<12; ienv++) { - penv->VolEnv.Ticks[ienv] = (WORD)xmsh.venv[ienv*2]; - penv->VolEnv.Values[ienv] = (BYTE)xmsh.venv[ienv*2+1]; - penv->PanEnv.Ticks[ienv] = (WORD)xmsh.penv[ienv*2]; - penv->PanEnv.Values[ienv] = (BYTE)xmsh.penv[ienv*2+1]; + penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2]; + penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1]; + penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2]; + penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1]; if (ienv) { - if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1]) + if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) { - penv->VolEnv.Ticks[ienv] &= 0xFF; - penv->VolEnv.Ticks[ienv] += penv->VolEnv.Ticks[ienv-1] & 0xFF00; - if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1]) penv->VolEnv.Ticks[ienv] += 0x100; + penv->VolPoints[ienv] &= 0xFF; + penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00; + if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100; } - if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1]) + if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) { - penv->PanEnv.Ticks[ienv] &= 0xFF; - penv->PanEnv.Ticks[ienv] += penv->PanEnv.Ticks[ienv-1] & 0xFF00; - if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1]) penv->PanEnv.Ticks[ienv] += 0x100; + penv->PanPoints[ienv] &= 0xFF; + penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00; + if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100; } } } @@ -493,7 +491,7 @@ pins->nVibType = xmsh.vibtype; pins->nVibSweep = xmsh.vibsweep; pins->nVibDepth = xmsh.vibdepth; - pins->nVibRate = xmsh.vibrate/4; + pins->nVibRate = xmsh.vibrate; memcpy(pins->name, xmss.name, 22); pins->name[21] = 0; } @@ -513,12 +511,70 @@ if (dwMemPos >= dwMemLength) break; } } - /* set these to default */ - for (UINT in=0; in= MAX_PATTERNNAME)) + { + m_lpszPatternNames = new char[len]; + + if (m_lpszPatternNames) + { + m_nPatternNames = len / MAX_PATTERNNAME; + memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); + } + dwMemPos += len; + } + } + // Read channel names: "CNAM" + if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) + { + UINT len = *((DWORD *)(lpStream+dwMemPos+4)); + dwMemPos += 8; + if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME)) + { + UINT n = len / MAX_CHANNELNAME; + for (UINT i=0; io(fp, (const unsigned char *)"Extended Module: ", 17); - fp->o(fp, (const unsigned char *)m_szNames[0], 20); + if ((!m_nChannels) || (!lpszFileName)) return FALSE; + if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE; + fwrite("Extended Module: ", 17, 1, f); + fwrite(m_szNames[0], 20, 1, f); s[0] = 0x1A; lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "FastTracker v2.00 "); s[21] = 0x04; s[22] = 0x01; - fp->o(fp, (const unsigned char *)s, 23); + fwrite(s, 23, 1, f); // Writing song header memset(&header, 0, sizeof(header)); - header.size = bswapLE32(sizeof(XMFILEHEADER)); - header.restartpos = bswapLE16(m_nRestartPos); - header.channels = bswapLE16(chanlim); - np = 0; - no = 0; + header.size = sizeof(XMFILEHEADER); + header.norder = 0; + header.restartpos = m_nRestartPos; + header.channels = m_nChannels; + header.patterns = 0; for (i=0; i= np) && (Order[i] < MAX_PATTERNS)) np = Order[i]+1; + header.norder++; + if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1; } - header.patterns = bswapLE16(np); - if (m_nInstruments && (m_dwSongFlags & SONG_INSTRUMENTMODE)) - ni = m_nInstruments; - else - ni = m_nSamples; - header.instruments = bswapLE16(ni); + header.instruments = m_nInstruments; + if (!header.instruments) header.instruments = m_nSamples; header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00; if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000; - header.tempo = bswapLE16(m_nDefaultTempo); - header.speed = bswapLE16(m_nDefaultSpeed); - header.flags = bswapLE16(header.flags); - header.norder = bswapLE16(no); - memcpy(header.order, Order, no); - fp->o(fp, (const unsigned char *)&header, sizeof(header)); + header.tempo = m_nDefaultTempo; + header.speed = m_nDefaultSpeed; + memcpy(header.order, Order, header.norder); + fwrite(&header, 1, sizeof(header), f); // Writing patterns - for (i=0; i> 8); - - UINT row = 0; - UINT col = 0; - for (UINT j=chanlim*PatternSize[i]; j; j--) + for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++) { - MODCOMMAND *p = &pm[col + row*m_nChannels]; - col++; - if (col >= chanlim) { - col=0; - row++; - } - UINT note = p->note; UINT param = ModSaveCommand(p, TRUE); UINT command = param >> 8; @@ -608,7 +645,6 @@ if ((note <= 12) || (note > 96+12)) note = 0; else note -= 12; UINT vol = 0; - if (p->volcmd) { UINT volcmd = p->volcmd; @@ -653,31 +689,29 @@ } xmph[7] = (BYTE)(len & 0xFF); xmph[8] = (BYTE)(len >> 8); - fp->o(fp, (const unsigned char *)xmph, 9); - fp->o(fp, (const unsigned char *)s, len); + fwrite(xmph, 1, 9, f); + fwrite(s, 1, len, f); } else { memset(&xmph, 0, sizeof(xmph)); xmph[0] = 9; xmph[5] = (BYTE)(PatternSize[i] & 0xFF); xmph[6] = (BYTE)(PatternSize[i] >> 8); - fp->o(fp, (const unsigned char *)xmph, 9); + fwrite(xmph, 1, 9, f); } // Writing instruments - for (i=1; i<=ni; i++) + for (i=1; i<=header.instruments; i++) { MODINSTRUMENT *pins; - int tmpsize, tmpsize2; BYTE flags[32]; memset(&xmih, 0, sizeof(xmih)); memset(&xmsh, 0, sizeof(xmsh)); - xmih.size = tmpsize = sizeof(xmih) + sizeof(xmsh); - xmih.size = bswapLE32(xmih.size); + xmih.size = sizeof(xmih) + sizeof(xmsh); memcpy(xmih.name, m_szNames[i], 22); xmih.type = 0; xmih.samples = 0; - if (m_nInstruments && (m_dwSongFlags & SONG_INSTRUMENTMODE)) + if (m_nInstruments) { INSTRUMENTHEADER *penv = Headers[i]; if (penv) @@ -685,16 +719,16 @@ memcpy(xmih.name, penv->name, 22); xmih.type = penv->nMidiProgram; xmsh.volfade = penv->nFadeOut; - xmsh.vnum = (BYTE)penv->VolEnv.nNodes; - xmsh.pnum = (BYTE)penv->PanEnv.nNodes; + xmsh.vnum = (BYTE)penv->nVolEnv; + xmsh.pnum = (BYTE)penv->nPanEnv; if (xmsh.vnum > 12) xmsh.vnum = 12; if (xmsh.pnum > 12) xmsh.pnum = 12; for (UINT ienv=0; ienv<12; ienv++) { - xmsh.venv[ienv*2] = bswapLE16(penv->VolEnv.Ticks[ienv]); - xmsh.venv[ienv*2+1] = bswapLE16(penv->VolEnv.Values[ienv]); - xmsh.penv[ienv*2] = bswapLE16(penv->PanEnv.Ticks[ienv]); - xmsh.penv[ienv*2+1] = bswapLE16(penv->PanEnv.Values[ienv]); + xmsh.venv[ienv*2] = penv->VolPoints[ienv]; + xmsh.venv[ienv*2+1] = penv->VolEnv[ienv]; + xmsh.penv[ienv*2] = penv->PanPoints[ienv]; + xmsh.penv[ienv*2+1] = penv->PanEnv[ienv]; } if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1; if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2; @@ -702,12 +736,12 @@ if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1; if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2; if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4; - xmsh.vsustain = (BYTE)penv->VolEnv.nSustainStart; - xmsh.vloops = (BYTE)penv->VolEnv.nLoopStart; - xmsh.vloope = (BYTE)penv->VolEnv.nLoopEnd; - xmsh.psustain = (BYTE)penv->PanEnv.nSustainStart; - xmsh.ploops = (BYTE)penv->PanEnv.nLoopStart; - xmsh.ploope = (BYTE)penv->PanEnv.nLoopEnd; + xmsh.vsustain = (BYTE)penv->nVolSustainBegin; + xmsh.vloops = (BYTE)penv->nVolLoopStart; + xmsh.vloope = (BYTE)penv->nVolLoopEnd; + xmsh.psustain = (BYTE)penv->nPanSustainBegin; + xmsh.ploops = (BYTE)penv->nPanLoopStart; + xmsh.ploope = (BYTE)penv->nPanLoopEnd; for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12]) { UINT k; @@ -728,7 +762,7 @@ smptable[0] = i; } xmsh.shsize = (xmih.samples) ? 40 : 0; - fp->o(fp, (const unsigned char *)&xmih, sizeof(xmih)); + fwrite(&xmih, 1, sizeof(xmih), f); if (smptable[0]) { MODINSTRUMENT *pvib = &Ins[smptable[0]]; @@ -737,27 +771,17 @@ xmsh.vibdepth = pvib->nVibDepth; xmsh.vibrate = pvib->nVibRate; } - - tmpsize2 = xmsh.shsize; - xmsh.shsize = bswapLE32(xmsh.shsize); - xmsh.volfade = bswapLE16(xmsh.volfade); - xmsh.res = bswapLE16(xmsh.res); - - fp->o(fp, (const unsigned char *)&xmsh, tmpsize - sizeof(xmih)); + fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f); if (!xmih.samples) continue; for (UINT ins=0; insnLength; xmss.loopstart = pins->nLoopStart; xmss.looplen = pins->nLoopEnd - pins->nLoopStart; xmss.vol = pins->nVolume / 4; - xmss.finetune = (char)pins->nFineTune; xmss.type = 0; if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1; @@ -766,7 +790,7 @@ if (nPacking) { if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char*)pins->pSample, pins->nLength, nPacking))) + && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) { flags[ins] = RS_ADPCM4; xmss.res = 0xAD; @@ -791,18 +815,10 @@ xmss.samplen *= 2; } } - if (pins->uFlags & CHN_PANNING) { - xmss.pan = 255; - if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan; - } else { - /* set panning to support default */ - xmss.pan = 128; - } + xmss.pan = 255; + if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan; xmss.relnote = (signed char)pins->RelativeTone; - xmss.samplen = bswapLE32(xmss.samplen); - xmss.loopstart = bswapLE32(xmss.loopstart); - xmss.looplen = bswapLE32(xmss.looplen); - fp->o(fp, (const unsigned char *)&xmss, tmpsize2); + fwrite(&xmss, 1, xmsh.shsize, f); } for (UINT ismpd=0; ismpdpSample) { #ifndef NO_PACKING - if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample((char*)pins->pSample, pins->nLength, nPacking); + if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample((char *)pins->pSample, pins->nLength, nPacking); #endif // NO_PACKING - WriteSample(fp, pins, flags[ismpd]); + WriteSample(f, pins, flags[ismpd]); } } } + // Writing song comments + if ((m_lpszSongComments) && (m_lpszSongComments[0])) + { + DWORD d = 0x74786574; + fwrite(&d, 1, 4, f); + d = strlen(m_lpszSongComments); + fwrite(&d, 1, 4, f); + fwrite(m_lpszSongComments, 1, d, f); + } + // Writing midi cfg + if (m_dwSongFlags & SONG_EMBEDMIDICFG) + { + DWORD d = 0x4944494D; + fwrite(&d, 1, 4, f); + d = sizeof(MODMIDICFG); + fwrite(&d, 1, 4, f); + fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); + } + // Writing Pattern Names + if ((m_nPatternNames) && (m_lpszPatternNames)) + { + DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME; + while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME; + if (dwLen >= MAX_PATTERNNAME) + { + DWORD d = 0x4d414e50; + fwrite(&d, 1, 4, f); + fwrite(&dwLen, 1, 4, f); + fwrite(m_lpszPatternNames, 1, dwLen, f); + } + } + // Writing Channel Names + { + UINT nChnNames = 0; + for (UINT inam=0; inam [100Hz-8060Hz] // EMU10K1 docs: cutoff = reg[0-127]*62+100 +#define FILTER_PRECISION 8192 #ifndef NO_FILTER -static int filter_cutoff[] = { - 130, 132, 134, 136, 138, 140, 142, 144, - 146, 148, 151, 153, 155, 157, 160, 162, - 164, 167, 169, 172, 174, 177, 179, 182, - 184, 187, 190, 193, 195, 198, 201, 204, - 207, 210, 213, 216, 220, 223, 226, 229, - 233, 236, 239, 243, 246, 250, 254, 257, - 261, 265, 269, 273, 277, 281, 285, 289, - 293, 297, 302, 306, 311, 315, 320, 324, - 329, 334, 339, 344, 349, 354, 359, 364, - 369, 375, 380, 386, 391, 397, 403, 409, - 415, 421, 427, 433, 440, 446, 452, 459, - 466, 472, 479, 486, 493, 501, 508, 515, - 523, 530, 538, 546, 554, 562, 570, 578, - 587, 595, 604, 613, 622, 631, 640, 649, - 659, 668, 678, 688, 698, 708, 718, 729, - 739, 750, 761, 772, 783, 795, 806, 818, - 830, 842, 854, 867, 880, 892, 905, 918, - 932, 945, 959, 973, 987, 1002, 1016, 1031, - 1046, 1061, 1077, 1092, 1108, 1124, 1141, 1157, - 1174, 1191, 1209, 1226, 1244, 1262, 1280, 1299, - 1318, 1337, 1357, 1376, 1396, 1417, 1437, 1458, - 1479, 1501, 1523, 1545, 1567, 1590, 1613, 1637, - 1661, 1685, 1709, 1734, 1760, 1785, 1811, 1837, - 1864, 1891, 1919, 1947, 1975, 2004, 2033, 2062, - 2093, 2123, 2154, 2185, 2217, 2249, 2282, 2315, - 2349, 2383, 2418, 2453, 2489, 2525, 2561, 2599, - 2637, 2675, 2714, 2753, 2793, 2834, 2875, 2917, - 2959, 3003, 3046, 3091, 3135, 3181, 3227, 3274, - 3322, 3370, 3419, 3469, 3520, 3571, 3623, 3675, - 3729, 3783, 3838, 3894, 3951, 4008, 4066, 4125, - 4186, 4246, 4308, 4371, 4434, 4499, 4564, 4631, - 4698, 4766, 4836, 4906, 4978, 5050, 5123, 5198 -}; -int dmpfac[] = { - 131072, 128272, 125533, 122852, 120229, 117661, 115148, 112689, - 110283, 107928, 105623, 103367, 101160, 98999, 96885, 94816, - 92791, 90810, 88870, 86973, 85115, 83298, 81519, 79778, - 78074, 76407, 74775, 73178, 71615, 70086, 68589, 67125, - 65691, 64288, 62915, 61572, 60257, 58970, 57711, 56478, - 55272, 54092, 52937, 51806, 50700, 49617, 48557, 47520, - 46506, 45512, 44540, 43589, 42658, 41747, 40856, 39983, - 39130, 38294, 37476, 36676, 35893, 35126, 34376, 33642, - 32923, 32220, 31532, 30859, 30200, 29555, 28924, 28306, - 27701, 27110, 26531, 25964, 25410, 24867, 24336, 23816, - 23308, 22810, 22323, 21846, 21380, 20923, 20476, 20039, - 19611, 19192, 18782, 18381, 17989, 17604, 17228, 16861, - 16500, 16148, 15803, 15466, 15135, 14812, 14496, 14186, - 13883, 13587, 13297, 13013, 12735, 12463, 12197, 11936, - 11681, 11432, 11188, 10949, 10715, 10486, 10262, 10043, - 9829, 9619, 9413, 9212, 9015, 8823, 8634, 8450, - 8270, 8093, 7920, 7751, 7585, 7423, 7265, 7110, - 6958, 6809, 6664, 6522, 6382, 6246, 6113, 5982, - 5854, 5729, 5607, 5487, 5370, 5255, 5143, 5033, - 4926, 4820, 4718, 4617, 4518, 4422, 4327, 4235, - 4144, 4056, 3969, 3884, 3801, 3720, 3641, 3563, - 3487, 3412, 3340, 3268, 3198, 3130, 3063, 2998, - 2934, 2871, 2810, 2750, 2691, 2634, 2577, 2522, - 2468, 2416, 2364, 2314, 2264, 2216, 2169, 2122, - 2077, 2032, 1989, 1947, 1905, 1864, 1824, 1786, - 1747, 1710, 1674, 1638, 1603, 1569, 1535, 1502, - 1470, 1439, 1408, 1378, 1348, 1320, 1291, 1264, - 1237, 1210, 1185, 1159, 1135, 1110, 1087, 1063, - 1041, 1018, 997, 975, 955, 934, 914, 895, - 876, 857, 838, 821, 803, 786, 769, 753, - 737, 721, 705, 690, 676, 661, 647, 633, - 620, 606, 593, 581, 568, 556, 544, 533 -}; +#ifdef MSC_VER +#define _ASM_MATH +#endif + +#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 #include +#endif // _ASM_MATH -#define PI ((double)3.14159265358979323846) + +DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const +//----------------------------------------------------------------------- +{ + float Fc; + + if (m_dwSongFlags & SONG_EXFILTERRANGE) + Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.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 > 10000) return 10000; + if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1; + return (DWORD)freq; +} + + // Simple 2-poles resonant filter -void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier, int) const +void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const //---------------------------------------------------------------------------------------- { - int cutoff = pChn->nCutOff * 2; - cutoff *= (flt_modifier+256) / 2; - cutoff /= 256; - if (cutoff>=255) cutoff=255; + float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier); + float fs = (float)gdwMixingFreq; + float fg, fb0, fb1; - int resonance = pChn->nResonance; - if (resonance>=255) resonance=255; - - float fc = (float)filter_cutoff[cutoff]; - float fs = (float)gdwMixingFreq; - float fg, fb0, fb1; - float d2, d, e; + fc *= (float)(2.0*3.14159265358/fs); + float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f); + float d = (1.0f-2.0f*dmpfac)* fc; + if (d>2.0) d = 2.0; + d = (2.0f*dmpfac - d)/fc; + float e = pow(1.0f/fc,2.0); - fc *= 3.14159265358979 * 2 / fs; - d2 = ((float)dmpfac[resonance]) / 65536.0; - d = (1.0 - d2) * fc; - - if (d > 2.0) - d = 2.0; - - d = (d2 - d) / fc; - e = 1.0 / (fc * fc); + fg=1/(1+d+e); + fb0=(d+e+e)/(1+d+e); + fb1=-e/(1+d+e); - fg = 1.0 / (1 + d + e); - fb0 = (d + e + e) / (1 + d + e); - fb1 = -e / (1 + d + e); + pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); + pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); + pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); - pChn->nFilter_A0 = (double)fg; - pChn->nFilter_B0 = (double)fb0; - pChn->nFilter_B1 = (double)fb1; - - if (bReset) { + if (bReset) + { pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0; pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0; } pChn->dwFlags |= CHN_FILTER; } + #endif // NO_FILTER diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/snd_fx.cxx --- a/src/modplug/snd_fx.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/snd_fx.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -64,7 +64,6 @@ UINT nSpeedCount = 0; nRow = nNextRow; nCurrentPattern = nNextPattern; - // Check if pattern is valid nPattern = Order[nCurrentPattern]; while (nPattern >= MAX_PATTERNS) @@ -91,20 +90,6 @@ nNextPattern = nCurrentPattern + 1; nNextRow = 0; } - /* muahahaha */ - if (stop_at_order > -1 && stop_at_row > -1) { - if (stop_at_order <= (signed) nCurrentPattern && stop_at_row <= (signed) nRow) - goto EndMod; - if (stop_at_time > 0) { - /* stupid api decision */ - if (((dwElapsedTime+500) / 1000) >= stop_at_time) { - stop_at_order = nCurrentPattern; - stop_at_row = nRow; - goto EndMod; - } - } - } - if (!nRow) { for (UINT ipck=0; ipck= 0x20) nMusicTempo = param; else // Tempo Slide - // FIXME: this is totally wrong! if ((param & 0xF0) == 0x10) { nMusicTempo += param & 0x0F; @@ -314,7 +298,7 @@ BOOL bInstrumentChanged = FALSE; if (instr >= MAX_INSTRUMENTS) return; - INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL; + INSTRUMENTHEADER *penv = Headers[instr]; MODINSTRUMENT *psmp = &Ins[instr]; UINT note = pChn->nNewNote; if ((penv) && (note) && (note <= 128)) @@ -322,9 +306,8 @@ if (penv->NoteMap[note-1] >= 0xFE) return; UINT n = penv->Keyboard[note-1]; psmp = ((n) && (n < MAX_SAMPLES)) ? &Ins[n] : NULL; - pChn->dwFlags &= ~CHN_SUSTAINLOOP; // turn off sustain } else - if (m_dwSongFlags & SONG_INSTRUMENTMODE) + if (m_nInstruments) { if (note >= 0xFE) return; psmp = NULL; @@ -349,11 +332,9 @@ pChn->nNewIns = 0; if (psmp) { - psmp->played = 1; if (penv) { - penv->played = 1; - pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 7; + pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6; if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan; pChn->nNNA = penv->nNNA; } else @@ -440,38 +421,29 @@ } -void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv, BOOL bManual) -//----------------------------------------------------------------------------------------- +void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv) +//--------------------------------------------------------------------------- { if (note < 1) return; MODCHANNEL * const pChn = &Chn[nChn]; MODINSTRUMENT *pins = pChn->pInstrument; - INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL; + INSTRUMENTHEADER *penv = pChn->pHeader; if ((penv) && (note <= 0x80)) { UINT n = penv->Keyboard[note - 1]; if ((n) && (n < MAX_SAMPLES)) pins = &Ins[n]; note = penv->NoteMap[note-1]; - pChn->dwFlags &= ~CHN_SUSTAINLOOP; // turn off sustain } // Key Off if (note >= 0x80) // 0xFE or invalid note => key off { - // technically this is "wrong", as anything besides ^^^, ===, and a valid note - // should cause a note fade... (oh well, it's just a quick hack anyway.) - if (note == 0xFD) { - pChn->dwFlags |= CHN_NOTEFADE; - return; - } - // Key Off KeyOff(nChn); // Note Cut if (note == 0xFE) { pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP); - if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_INSTRUMENTMODE)) - pChn->nVolume = 0; + if ((!(m_nType & MOD_TYPE_IT)) || (m_nInstruments)) pChn->nVolume = 0; pChn->nFadeOutVol = 0; } return; @@ -568,9 +540,8 @@ // Volume Swing if (penv->nVolSwing) { - /* this was wrong */ - int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 256; - pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/256); + int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128; + pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128); } // Pan Swing if (penv->nPanSwing) @@ -598,42 +569,21 @@ if ((pChn->nCutOff < 0x7F) && (bFlt)) SetupChannelFilter(pChn, TRUE); #endif // NO_FILTER } - // Special case for MPT - if (bManual) pChn->dwFlags &= ~CHN_MUTE; - if (((pChn->dwFlags & CHN_MUTE) && (gdwSoundSetup & SNDMIX_MUTECHNMODE)) - || ((pChn->pInstrument) && (pChn->pInstrument->uFlags & CHN_MUTE) && (!bManual)) - || ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) - && (pChn->pHeader->dwFlags & ENV_MUTE) && (!bManual))) - { - if (!bManual) pChn->nPeriod = 0; - } } -UINT CSoundFile::GetNNAChannel(UINT nChn) +UINT CSoundFile::GetNNAChannel(UINT nChn) const //--------------------------------------------- { - MODCHANNEL *pChn = &Chn[nChn]; + const MODCHANNEL *pChn = &Chn[nChn]; // Check for empty channel - MODCHANNEL *pi = &Chn[m_nChannels]; - for (UINT i=m_nChannels; inLength) { - if (pi->dwFlags & CHN_MUTE) { - if (pi->dwFlags & CHN_NNAMUTE) { - pi->dwFlags &= ~(CHN_NNAMUTE|CHN_MUTE); - } else { - /* this channel is muted; skip */ - continue; - } - } - return i; - } - } + const MODCHANNEL *pi = &Chn[m_nChannels]; + for (UINT i=m_nChannels; inLength) return i; if (!pChn->nFadeOutVol) return 0; // All channels are used: check for lowest volume UINT result = 0; DWORD vol = 64*65536; // 25% - int envpos = 0xFFFFFF; + DWORD envpos = 0xFFFFFF; const MODCHANNEL *pj = &Chn[m_nChannels]; for (UINT j=m_nChannels; jpHeader : NULL; - INSTRUMENTHEADER *pHeader; + INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader; signed char *pSample; if (note > 0x80) note = 0; if (note < 1) return; // Always NNA cut - using - if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!(m_dwSongFlags & SONG_INSTRUMENTMODE)) || (bForceCut)) + if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!m_nInstruments) || (bForceCut)) { if ((m_dwSongFlags & SONG_CPUVERYHIGH) || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE) || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return; UINT n = GetNNAChannel(nChn); if (!n) return; - p = &Chn[n]; + MODCHANNEL *p = &Chn[n]; // Copy Channel *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_PORTAMENTO); + p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); p->nMasterChn = nChn+1; p->nCommand = 0; // Cut the note @@ -697,7 +641,7 @@ pHeader = pChn->pHeader; if ((instr) && (note)) { - pHeader = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL; + pHeader = Headers[instr]; if (pHeader) { UINT n = 0; @@ -710,7 +654,7 @@ } else pSample = NULL; } if (!penv) return; - p = pChn; + MODCHANNEL *p = pChn; for (UINT i=nChn; i= m_nChannels) || (p == pChn)) { @@ -722,7 +666,7 @@ { // Note case DCT_NOTE: - if ((note) && ((int)p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE; + if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE; break; // Sample case DCT_SAMPLE: @@ -767,10 +711,10 @@ UINT n = GetNNAChannel(nChn); if (n) { - p = &Chn[n]; + MODCHANNEL *p = &Chn[n]; // Copy Channel *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_PORTAMENTO); + p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); p->nMasterChn = nChn+1; p->nCommand = 0; // Key Off the note @@ -801,19 +745,17 @@ MODCHANNEL *pChn = Chn; for (UINT nChn=0; nChnnCommand=0; - UINT instr = pChn->nRowInstr; UINT volcmd = pChn->nRowVolCmd; UINT vol = pChn->nRowVolume; UINT cmd = pChn->nRowCommand; UINT param = pChn->nRowParam; BOOL bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE; - UINT nStartTick = pChn->nTickStart; + UINT nStartTick = 0; pChn->dwFlags &= ~CHN_FASTVOLRAMP; // Process special effects (note delay, pattern delay, pattern loop) - if (((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX))) + if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX)) { if ((!param) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param; // Note Delay ? @@ -855,7 +797,7 @@ } if ((!note) && (instr)) { - if (m_dwSongFlags & SONG_INSTRUMENTMODE) + if (m_nInstruments) { if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume; if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) @@ -880,7 +822,7 @@ // Note Cut/Off => ignore instrument if (note >= 0xFE) instr = 0; if ((note) && (note <= 128)) pChn->nNewNote = note; - // New Note Action ? (not when paused!!!) + // New Note Action ? if ((note) && (note <= 128) && (!bPorta)) { CheckNNA(nChn, instr, note, FALSE); @@ -929,7 +871,6 @@ if (vol > 64) vol = 64; pChn->nPan = vol << 2; pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->dwFlags &= ~CHN_SURROUND; } } @@ -1007,14 +948,6 @@ { pChn->nVolume = (param < 64) ? param*4 : 256; pChn->dwFlags |= CHN_FASTVOLRAMP; - for (UINT i=m_nChannels; inMasterChn == (nChn+1)) { - c->nVolume = pChn->nVolume; - c->dwFlags |= CHN_FASTVOLRAMP; - } - } } break; @@ -1071,22 +1004,7 @@ if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo; } SetTempo(param); - } else { - param = pChn->nOldTempo; // this just got set on tick zero - - switch (param >> 4) { - case 0: - m_nMusicTempo -= param & 0xf; - if (m_nMusicTempo < 32) - m_nMusicTempo = 32; - break; - case 1: - m_nMusicTempo += param & 0xf; - if (m_nMusicTempo > 255) - m_nMusicTempo = 255; - break; - } - } + } break; // Set Offset @@ -1121,9 +1039,9 @@ // Arpeggio case CMD_ARPEGGIO: - pChn->nCommand = CMD_ARPEGGIO; if ((m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break; if ((!param) && (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break; + pChn->nCommand = CMD_ARPEGGIO; if (param) pChn->nArpeggio = param; break; @@ -1135,18 +1053,14 @@ if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F; param |= 0x100; // increment retrig count on first row } - // various bits of retriggery commented out here & below, reverting to old method... - // -Storlek 04aug07 - // if (pChn->nRowNote && !m_nTickCount) pChn->nRetrigCount = 0; if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam; - // pChn->nCommand = CMD_RETRIG; RetrigNote(nChn, param); break; // Tremor case CMD_TREMOR: + if (m_nTickCount) break; pChn->nCommand = CMD_TREMOR; - if (m_nTickCount) break; if (param) pChn->nTremorParam = param; break; @@ -1235,35 +1149,12 @@ { pChn->nGlobalVol = param; pChn->dwFlags |= CHN_FASTVOLRAMP; - for (UINT i=m_nChannels; inMasterChn == (nChn+1)) { - c->nGlobalVol = param; - c->dwFlags |= CHN_FASTVOLRAMP; - } - } } break; // Channel volume slide case CMD_CHANNELVOLSLIDE: - { - int saw_self = 0; - - for (UINT i=m_nChannels; inMasterChn == (nChn+1)) { - if (c == pChn) saw_self = 1; - ChannelVolSlide(c, param); - } - } - if (!saw_self) { - ChannelVolSlide(pChn, param); - } - } - + ChannelVolSlide(pChn, param); break; // Panbrello (IT) @@ -1278,10 +1169,10 @@ pChn->nVolEnvPosition = param; pChn->nPanEnvPosition = param; pChn->nPitchEnvPosition = param; - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) + if (pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; - if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes) && ((int)param > penv->PanEnv.Ticks[penv->PanEnv.nNodes-1])) + if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1])) { pChn->dwFlags &= ~CHN_PANENV; } @@ -1376,8 +1267,6 @@ //--------------------------------------------------------- { if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown; - if (m_dwSongFlags & SONG_ITCOMPATMODE) pChn->nPortamentoSlide=param*4; - else pChn->nPortamentoDest=0; if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0)) { if (param & 0x0F) @@ -1405,8 +1294,6 @@ //----------------------------------------------------------- { if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown; - if (m_dwSongFlags & SONG_ITCOMPATMODE) pChn->nPortamentoSlide=param*4; - else pChn->nPortamentoDest=0; if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0)) { if (param & 0x0F) @@ -1679,7 +1566,6 @@ if (nPanSlide > 256) nPanSlide = 256; pChn->nPan = nPanSlide; } - pChn->dwFlags &= ~CHN_SURROUND; } @@ -1853,29 +1739,17 @@ } break; // S8x: Set 4-bit Panning - case 0x80: - pChn->dwFlags &= ~CHN_SURROUND; - if (!m_nTickCount) { - pChn->nPan = (param << 4) + 8; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } - break; + case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; // S9x: Set Surround case 0x90: ExtendedChannelEffect(pChn, param & 0x0F); break; // SAx: Set 64k Offset case 0xA0: if (!m_nTickCount) { - if (m_nType & MOD_TYPE_S3M) { - pChn->nPan = ((param ^ 8) << 4) + 8; - pChn->dwFlags &= ~CHN_SURROUND; - pChn->dwFlags |= CHN_FASTVOLRAMP; - } else { - pChn->nOldHiOffset = param; - if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) - { - DWORD pos = param << 16; - if (pos < pChn->nLength) pChn->nPos = pos; - } + pChn->nOldHiOffset = param; + if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) + { + DWORD pos = param << 16; + if (pos < pChn->nLength) pChn->nPos = pos; } } break; @@ -1898,12 +1772,12 @@ if (m_nTickCount) return; switch(param & 0x0F) { - // S91: Surround On + // S90: Surround Off + case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break; + // S91: Surround On case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break; //////////////////////////////////////////////////////////// // Modplug Extensions - // S90: Surround Off - case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break; // S98: Reverb Off case 0x08: pChn->dwFlags &= ~CHN_REVERB; @@ -1946,176 +1820,102 @@ } } -// this is all brisby -void CSoundFile::MidiSend(unsigned char *data, unsigned int len, UINT nChn, int fake) + +void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param) +//--------------------------------------------------------------------------- { MODCHANNEL *pChn = &Chn[nChn]; - int oldcutoff; + DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F; + // Not Internal Device ? + if (dwMacro != 0x30463046) + { + UINT pos = 0, nNib = 0, nBytes = 0; + DWORD dwMidiCode = 0, dwByteCode = 0; + while (pos+6 <= 32) + { + CHAR cData = pszMidiMacro[pos++]; + if (!cData) break; + if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else + if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else + if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else + if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else + if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else + if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else + if (nNib >= 2) + { + nNib = 0; + dwMidiCode |= dwByteCode << (nBytes*8); + dwByteCode = 0; + nBytes++; + if (nBytes >= 3) + { + UINT nMasterCh = (nChn < m_nChannels) ? nChn+1 : pChn->nMasterChn; + if ((nMasterCh) && (nMasterCh <= m_nChannels)) + { + UINT nPlug = ChnSettings[nMasterCh-1].nMixPlugin; + if ((nPlug) && (nPlug <= MAX_MIXPLUGINS)) + { + IMixPlugin *pPlugin = m_MixPlugins[nPlug-1].pMixPlugin; + if ((pPlugin) && (m_MixPlugins[nPlug-1].pMixState)) + { + pPlugin->MidiSend(dwMidiCode); + } + } + } + nBytes = 0; + dwMidiCode = 0; + } + } - if (len > 2 && data[0] == 0xF0 && data[1] == 0xF0) { - /* impulse tracker filter control (mfg. 0xF0) */ - if (len == 5) { - switch (data[2]) { - case 0x00: /* set cutoff */ - oldcutoff = pChn->nCutOff; - if (data[3] < 0x80) pChn->nCutOff = data[3]; + } + return; + } + // Internal device + pszMidiMacro += 4; + // Filter ? + if (pszMidiMacro[0] == '0') + { + CHAR cData1 = pszMidiMacro[2]; + DWORD dwParam = 0; + if ((cData1 == 'z') || (cData1 == 'Z')) + { + dwParam = param; + } else + { + CHAR cData2 = pszMidiMacro[3]; + if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else + if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4; + if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else + if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A); + } + switch(pszMidiMacro[1]) + { + // F0.F0.00.xx: Set CutOff + case '0': + { + int oldcutoff = pChn->nCutOff; + if (dwParam < 0x80) pChn->nCutOff = dwParam; #ifndef NO_FILTER oldcutoff -= pChn->nCutOff; if (oldcutoff < 0) oldcutoff = -oldcutoff; if ((pChn->nVolume > 0) || (oldcutoff < 0x10) - || (!(pChn->dwFlags & CHN_FILTER)) - || (!(pChn->nLeftVol|pChn->nRightVol))) - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) - ? FALSE : TRUE); -#endif // NO_FILTER - break; - case 0x01: /* set resonance */ - if (data[3] < 0x80) pChn->nResonance = data[3]; -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); + || (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol))) + SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); #endif // NO_FILTER - break; - }; - } - } - - if (!fake && _midi_out_raw) { - /* okay, this is kind of how it works. - we pass m_nBufferCount as here because while - 1000 * ((8((buffer_size/2) - m_nBufferCount)) / sample_rate) - is the number of msec we need to delay by, libmodplug simply doesn't know - what the buffer size is at this point so m_nBufferCount simply has no - frame of reference. - - fortunately, schism does and can complete this (tags: _schism_midi_out_raw ) - - */ - _midi_out_raw(data, len, m_nBufferCount); - } -} - -static int _was_complete_midi(unsigned char *q, unsigned int len, int nextc) -{ - if (len == 0) return 0; - if (*q == 0xF0) return (q[len-1] == 0xF7 ? 1 : 0); - return ((nextc & 0x80) ? 1 : 0); -} - -void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param, - UINT note, UINT velocity, UINT use_instr) -//--------------------------------------------------------------------------- -{ -/* this was all wrong. -mrsb */ - MODCHANNEL *pChn = &Chn[nChn]; - INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) - ? Headers[use_instr - ?use_instr - :pChn->nLastInstr] - : NULL; - unsigned char outbuffer[64]; - unsigned char cx; - int mc, fake = 0; - int saw_c; - int i, j, x; - - saw_c = 0; - if (!penv || penv->nMidiChannel == 0) { - /* okay, there _IS_ no real midi channel. forget this for now... */ - mc = 15; - fake = 1; - - } else if (penv->nMidiChannel > 16) { - mc = (nChn-1) % 16; - } else { - mc = (penv->nMidiChannel-1); - } + } + break; - for (i = j = x = 0, cx =0; i <= 32 && pszMidiMacro[i]; i++) { - int c, cw; - if (pszMidiMacro[i] >= '0' && pszMidiMacro[i] <= '9') { - c = pszMidiMacro[i] - '0'; - cw = 1; - } else if (pszMidiMacro[i] >= 'A' && pszMidiMacro[i] <= 'F') { - c = (pszMidiMacro[i] - 'A') + 10; - cw = 1; - } else if (pszMidiMacro[i] == 'c') { - c = mc; - cw = 1; - saw_c = 1; - } else if (pszMidiMacro[i] == 'n') { - c = (note-1); - cw = 2; - } else if (pszMidiMacro[i] == 'v') { - c = velocity; - cw = 2; - } else if (pszMidiMacro[i] == 'u') { - c = (pChn->nVolume >> 1); - if (c > 127) c = 127; - cw = 2; - } else if (pszMidiMacro[i] == 'x') { - c = pChn->nPan; - if (c > 127) c = 127; - cw = 2; - } else if (pszMidiMacro[i] == 'y') { - c = pChn->nRealPan; - if (c > 127) c = 127; - cw = 2; - } else if (pszMidiMacro[i] == 'a') { - if (!penv) - c = 0; - else - c = (penv->wMidiBank >> 7) & 127; - cw = 2; - } else if (pszMidiMacro[i] == 'b') { - if (!penv) - c = 0; - else - c = penv->wMidiBank & 127; - cw = 2; - } else if (pszMidiMacro[i] == 'z' || pszMidiMacro[i] == 'p') { - c = param & 0x7F; - cw = 2; - } else { - continue; + // F0.F0.01.xx: Set Resonance + case '1': + if (dwParam < 0x80) pChn->nResonance = dwParam; +#ifndef NO_FILTER + SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE); +#endif // NO_FILTER + + break; } - if (j == 0 && cw == 1) { - cx = c; - j = 1; - continue; - } else if (j == 1 && cw == 1) { - cx = (cx << 4) | c; - j = 0; - } else if (j == 0) { - cx = c; - } else if (j == 1) { - outbuffer[x] = cx; - x++; - cx = c; - j = 0; - } - // start of midi message - if (_was_complete_midi(outbuffer,x,cx)) { - MidiSend(outbuffer, x, nChn,saw_c && fake); - x = 0; - } - outbuffer[x] = cx; - x++; - } - if (j == 1) { - outbuffer[x] = cx; - x++; - } - if (x) { - // terminate sysex - if (!_was_complete_midi(outbuffer,x,0xFF)) { - if (*outbuffer == 0xF0) { - outbuffer[x] = 0xF7; - x++; - } - } - MidiSend(outbuffer, x, nChn,saw_c && fake); } } @@ -2132,18 +1932,10 @@ if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) { if (!nRetrigSpeed) nRetrigSpeed = 1; - if (m_nMusicSpeed < nRetrigSpeed) { - if (nRetrigCount >= nRetrigSpeed) { - bDoRetrig = TRUE; - nRetrigCount = 0; - } else { - nRetrigCount++; - } - } else { - if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE; - nRetrigCount++; - } - } else { + if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE; + nRetrigCount++; + } else + { UINT realspeed = nRetrigSpeed; if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++; if ((m_nTickCount) || (param & 0x100)) @@ -2230,10 +2022,9 @@ if (m_nTickCount == nTick) { MODCHANNEL *pChn = &Chn[nChn]; - // if (m_dwSongFlags & SONG_INSTRUMENTMODE) KeyOff(pChn); ? + // if (m_nInstruments) KeyOff(pChn); ? pChn->nVolume = 0; pChn->dwFlags |= CHN_FASTVOLRAMP; - pChn->nLength = 0; } } @@ -2245,7 +2036,7 @@ BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE; pChn->dwFlags |= CHN_KEYOFF; //if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV))) - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV))) + if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV))) { pChn->dwFlags |= CHN_NOTEFADE; } @@ -2270,7 +2061,7 @@ pChn->nLength = psmp->nLength; } } - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) + if (pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; if (((penv->dwFlags & ENV_VOLLOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut)) @@ -2286,8 +2077,22 @@ void CSoundFile::SetSpeed(UINT param) //----------------------------------- { - if (param) - m_nMusicSpeed = param; + UINT max = (m_nType == MOD_TYPE_IT) ? 256 : 128; + // Modplug Tracker and Mod-Plugin don't do this check +#ifndef MODPLUG_TRACKER +#ifndef MODPLUG_FASTSOUNDLIB + // Big Hack!!! + if ((!param) || (param >= 0x80) || ((m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E))) + { + if (IsSongFinished(m_nCurrentPattern, m_nRow+1)) + { + GlobalFadeSong(1000); + } + } +#endif // MODPLUG_FASTSOUNDLIB +#endif // MODPLUG_TRACKER + if ((m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80; + if ((param) && (param <= max)) m_nMusicSpeed = param; } @@ -2296,7 +2101,6 @@ { if (param < 0x20) { -#if 0 // argh... this is completely wrong // Tempo Slide if ((param & 0xF0) == 0x10) { @@ -2307,7 +2111,6 @@ m_nMusicTempo -= (param & 0x0F) * 2; if ((LONG)m_nMusicTempo < 32) m_nMusicTempo = 32; } -#endif } else { m_nMusicTempo = param; @@ -2323,28 +2126,15 @@ if (pChn->nPatternLoopCount) { pChn->nPatternLoopCount--; - if (!pChn->nPatternLoopCount) { - // this should get rid of that nasty infinite loop for cases like - // ... .. .. SB0 - // ... .. .. SB1 - // ... .. .. SB1 - // it still doesn't work right in a few strange cases, but oh well :P - pChn->nPatternLoop = m_nRow + 1; - return -1; - } + if (!pChn->nPatternLoopCount) return -1; } else { - // hmm. the pattern loop shouldn't care about - // other channels at all... i'm not really - // sure what this code is doing :/ -#if 0 MODCHANNEL *p = Chn; for (UINT i=0; inPatternLoopCount) return -1; } -#endif pChn->nPatternLoopCount = param; } return pChn->nPatternLoop; @@ -2507,33 +2297,6 @@ } } -// this last param was nC4Speed -UINT CSoundFile::GetLinearPeriodFromNote(UINT note, int nFineTune, UINT) const -{ - if ((!note) || (note > 0xF0)) return 0; - if (m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV - |MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM)) - { - note--; - return (FreqS3MTable[note % 12] << 5) >> (note / 12); - } else - if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) - { - if (note < 13) note = 13; - note -= 13; - LONG l = ((120 - note) << 6) - (nFineTune / 2); - if (l < 1) l = 1; - return (UINT)l; - } else - { - note--; - nFineTune = XM2MODFineTune(nFineTune); - if ((nFineTune) || (note < 36) || (note >= 36+6*12)) - return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12); - else - return (ProTrackerPeriodTable[note-36] << 2); - } -} UINT CSoundFile::GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/sndfile.cxx --- a/src/modplug/sndfile.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/sndfile.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -15,7 +15,6 @@ extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); #endif - // External decompressors extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter); extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); @@ -51,7 +50,6 @@ { m_nType = MOD_TYPE_NONE; m_dwSongFlags = 0; - m_nStereoSeparation = 128; m_nChannels = 0; m_nMixChannels = 0; m_nSamples = 0; @@ -64,8 +62,6 @@ m_nMinPeriod = 0x20; m_nMaxPeriod = 0x7FFF; m_nRepeatCount = 0; - m_rowHighlightMajor = 16; - m_rowHighlightMinor = 4; memset(Chn, 0, sizeof(Chn)); memset(ChnMix, 0, sizeof(ChnMix)); memset(Ins, 0, sizeof(Ins)); @@ -90,10 +86,8 @@ { int i; - // deja vu... m_nType = MOD_TYPE_NONE; m_dwSongFlags = 0; - m_nStereoSeparation = 128; m_nChannels = 0; m_nMixChannels = 0; m_nSamples = 0; @@ -117,6 +111,7 @@ m_nMaxPeriod = 32767; m_nSongPreAmp = 0x30; m_nPatternNames = 0; + m_nMaxOrderPosition = 0; m_lpszPatternNames = NULL; m_lpszSongComments = NULL; memset(Ins, 0, sizeof(Ins)); @@ -128,10 +123,7 @@ memset(m_szNames, 0, sizeof(m_szNames)); memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); ResetMidiCfg(); - for (UINT npt=0; npt= 0) && (p[j] == ' ')) p[j--] = 0; + } // Adjust channels for (i=0; ipSample) { if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; + if (pins->nLoopStart + 3 >= pins->nLoopEnd) + { + pins->nLoopStart = 0; + pins->nLoopEnd = 0; + } if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength; - } else { + if (pins->nSustainStart + 3 >= pins->nSustainEnd) + { + pins->nSustainStart = 0; + pins->nSustainEnd = 0; + } + } else + { pins->nLength = 0; pins->nLoopStart = 0; pins->nLoopEnd = 0; @@ -209,7 +221,8 @@ // Check invalid instruments while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--; // Set default values - if (m_nDefaultTempo < 31) m_nDefaultTempo = 31; + if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; + if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; m_nMusicSpeed = m_nDefaultSpeed; m_nMusicTempo = m_nDefaultTempo; @@ -238,7 +251,14 @@ } } } - return m_nType ? TRUE : FALSE; + if (m_nType) + { + UINT maxpreamp = 0x10+(m_nChannels*8); + if (maxpreamp > 100) maxpreamp = 100; + if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp; + return TRUE; + } + return FALSE; } @@ -447,7 +467,6 @@ gdwMixingFreq = nRate; gnBitsPerSample = nBits; InitPlayer(bReset); -//printf("Rate=%u Bits=%u Channels=%u MMX=%u\n",gdwMixingFreq,gnBitsPerSample,gnChannels,bMMX); return TRUE; } @@ -475,7 +494,7 @@ { if (nVol < 1) nVol = 1; if (nVol > 0x200) nVol = 0x200; // x4 maximum - if ((gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) + if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) { gnAGC = gnAGC * m_nMasterVolume / nVol; if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY; @@ -678,6 +697,7 @@ m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); } + void CSoundFile::ResetChannels() //------------------------------ { @@ -690,21 +710,6 @@ } -void CSoundFile::ResetTimestamps() -//-------------------------------- -{ - int n; - - for (n = 1; n < MAX_SAMPLES; n++) { - Ins[n].played = 0; - } - for (n = 1; n < MAX_INSTRUMENTS; n++) { - if (Headers[n]) - Headers[n]->played = 0; - } -} - - void CSoundFile::LoopPattern(int nPat, int nRow) //---------------------------------------------- { @@ -751,7 +756,7 @@ case MOD_TYPE_S3M: n = MOD_TYPE_S3M; } n |= MOD_TYPE_XM | MOD_TYPE_IT; - if (!(m_dwSongFlags & SONG_INSTRUMENTMODE)) + if (!m_nInstruments) { if (m_nSamples < 32) n |= MOD_TYPE_MOD; n |= MOD_TYPE_S3M; @@ -850,8 +855,7 @@ #ifndef MODPLUG_NO_FILESAVE -UINT CSoundFile::WriteSample(diskwriter_driver_t *f, MODINSTRUMENT *pins, - UINT nFlags, UINT nMaxLen) +UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen) //----------------------------------------------------------------------------------- { UINT len = 0, bufcount; @@ -869,7 +873,7 @@ { int pos; len = (nLen + 1) / 2; - f->o(f, (const unsigned char *)CompressionTable, 16); + fwrite(CompressionTable, 16, 1, f); bufcount = 0; pos = 0; for (UINT j=0; j= sizeof(buffer)) { - f->o(f, (const unsigned char *)buffer, bufcount); + fwrite(buffer, 1, bufcount, f); bufcount = 0; } } - if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount); + if (bufcount) fwrite(buffer, 1, bufcount, f); len += 16; } break; @@ -913,20 +917,22 @@ } if (nFlags == RS_PCM16D) { - *((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new - s_old)); + short temp = bswapLE16((short)(s_new - s_old)); + *((short *)(&buffer[bufcount])) = temp; s_old = s_new; } else { - *((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new + s_ofs)); + short temp = bswapLE16((short)(s_new + s_ofs)); + *((short *)(&buffer[bufcount])) = temp; } bufcount += 2; if (bufcount >= sizeof(buffer) - 1) { - f->o(f, (const unsigned char *)buffer, bufcount); + fwrite(buffer, 1, bufcount, f); bufcount = 0; } } - if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount); + if (bufcount) fwrite(buffer, 1, bufcount, f); } break; @@ -957,11 +963,11 @@ } if (bufcount >= sizeof(buffer)) { - f->o(f, (const unsigned char *)buffer, bufcount); + fwrite(buffer, 1, bufcount, f); bufcount = 0; } } - if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount); + if (bufcount) fwrite(buffer, 1, bufcount, f); } } len = nLen * 2; @@ -985,20 +991,22 @@ p += 2; if (nFlags == RS_STPCM16D) { - *((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new - s_old)); + short temp = bswapLE16((short)(s_new - s_old)); + *((short *)(&buffer[bufcount])) = temp; s_old = s_new; } else { - *((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new + s_ofs)); + short temp = bswapLE16((short)(s_new - s_ofs)); + *((short *)(&buffer[bufcount])) = temp; } bufcount += 2; if (bufcount >= sizeof(buffer)) { - f->o(f, (const unsigned char *)buffer, bufcount); + fwrite(buffer, 1, bufcount, f); bufcount = 0; } } - if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount); + if (bufcount) fwrite(buffer, 1, bufcount, f); } } len = nLen*4; @@ -1008,25 +1016,8 @@ case RS_STIPCM8S: case RS_STIPCM16S: len = nLen * 2; - if (nFlags == RS_STIPCM16S) { - { - signed short *p = (signed short *)pSample; - bufcount = 0; - for (UINT j=0; j= sizeof(buffer)) - { - f->o(f, (const unsigned char *)buffer, bufcount); - bufcount = 0; - } - } - if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount); - }; - } else { - f->o(f, (const unsigned char *)pSample, len); - } + if (nFlags == RS_STIPCM16S) len *= 2; + fwrite(pSample, 1, len, f); break; // Default: assume 8-bit PCM data @@ -1036,12 +1027,6 @@ { signed char *p = pSample; int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1; - if (bswapLE16(0xff00) == 0x00ff) { - /* skip first byte; significance is at other end */ - p++; - len--; - } - int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0; if (pins->uFlags & CHN_16BIT) p++; for (UINT j=0; j= sizeof(buffer)) { - f->o(f, (const unsigned char *)buffer, bufcount); + fwrite(buffer, 1, bufcount, f); bufcount = 0; } } - if (bufcount) f->o(f,(const unsigned char *)buffer,bufcount); + if (bufcount) fwrite(buffer, 1, bufcount, f); } } return len; @@ -1089,10 +1074,11 @@ UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength) //------------------------------------------------------------------------------------------------ { - UINT len = 0, mem = pIns->nLength+6; + UINT len = 0, mem; - if ((!pIns) || (pIns->nLength < 1) || (!lpMemFile)) return 0; + if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0; if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; + mem = pIns->nLength+6; pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO); if (nFlags & RSF_16BIT) { @@ -1166,15 +1152,13 @@ { len = pIns->nLength * 2; if (len > dwMemLength) break; - short *pSample = (short *)pIns->pSample; - short *p = (short *)lpMemFile; - unsigned short tmp; + short int *pSample = (short int *)pIns->pSample; + short int *p = (short int *)lpMemFile; int delta16 = 0; for (UINT j=0; jnLength * 2; - if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len); + if (len > dwMemLength) break; short int *pSample = (short int *)pIns->pSample; - for (UINT j=0; jpSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158)); else ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516)); break; +#ifndef MODPLUG_BASIC_SUPPORT #ifndef MODPLUG_FASTSOUNDLIB // 8-bit interleaved stereo samples case RS_STIPCM8S: @@ -1382,7 +1364,7 @@ for (UINT j=0; juFlags & CHN_STEREO) { - pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; - pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; + pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0; + pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0; } else { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; + pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; } if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) { @@ -1612,11 +1595,12 @@ // Adjust end of sample if (pIns->uFlags & CHN_STEREO) { - pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; - pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; + pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0; + pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0; + } else { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; + pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; } if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) { @@ -1641,6 +1625,8 @@ //----------------------------------------------------------- { //---GCCFIX: Removed assembly. + return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536))); + #ifdef MSC_VER const float _fbase = 8363; const float _factor = 1.0f/(12.0f*128.0f); @@ -1670,8 +1656,6 @@ if (derr <= 5) freq -= derr; if (derr >= 995) freq += 1000-derr; return freq; -#else - return (DWORD) (8363.0 * pow(2, (transp * 128.0 + ftune) / 1536.0)); #endif } @@ -1681,6 +1665,8 @@ //---------------------------------------------- { //---GCCFIX: Removed assembly. + return int(1536*(log(freq/8363)/log(2))); + #ifdef MSC_VER const float _f1_8363 = 1.0f / 8363.0f; const float _factor = 128 * 12; @@ -1696,8 +1682,6 @@ fistp result } return result; -#else - return (int) (1536.0 * (log(freq / 8363.0) / log(2))); #endif } @@ -1794,32 +1778,6 @@ return FALSE; } -UINT CSoundFile::GetHighestUsedChannel() -//------------------------------ -{ - UINT highchan = 0; - - for (UINT ipat=0; ipatnote) && (p->note <= 120)) - { - if ((j % m_nChannels) > highchan) - highchan = j % m_nChannels; - } - } - } - } - - return highchan; -} - - #ifndef MODPLUG_FASTSOUNDLIB @@ -1829,7 +1787,7 @@ UINT nExt = 0; if (!pbIns) return 0; - if (m_dwSongFlags & SONG_INSTRUMENTMODE) + if (m_nInstruments) { memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); for (UINT ipat=0; ipat (endian and char fixes for PPC) */ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "diskwriter.h" +#include "config.h" #ifndef __SNDFILE_H #define __SNDFILE_H -#define MODPLUG_TRACKER 1 -#define MODPLUG_PLAYER 1 - #ifdef UNDER_CE int _strnicmp(const char *str1,const char *str2, int n); #endif @@ -35,7 +28,7 @@ #ifdef MODPLUG_FASTSOUNDLIB #define MAX_CHANNELS 80 #else -#define MAX_CHANNELS 256 +#define MAX_CHANNELS 128 #endif #define MAX_BASECHANNELS 64 #define MAX_ENVPOINTS 32 @@ -72,6 +65,7 @@ #define MOD_TYPE_MT2 0x100000 #define MOD_TYPE_AMF0 0x200000 #define MOD_TYPE_PSM 0x400000 +#define MOD_TYPE_J2B 0x800000 #define MOD_TYPE_UMX 0x80000000 // Fake type #define MAX_MODTYPE 23 @@ -108,8 +102,6 @@ #define CHN_EXTRALOUD 0x2000000 #define CHN_REVERB 0x4000000 #define CHN_NOREVERB 0x8000000 -// used to turn off mute but have it reset later -#define CHN_NNAMUTE 0x10000000 #define ENV_VOLUME 0x0001 @@ -126,7 +118,6 @@ #define ENV_VOLCARRY 0x0800 #define ENV_PANCARRY 0x1000 #define ENV_PITCHCARRY 0x2000 -#define ENV_MUTE 0x4000 #define CMD_NONE 0 #define CMD_ARPEGGIO 1 @@ -263,9 +254,6 @@ #define SONG_SURROUNDPAN 0x4000 #define SONG_EXFILTERRANGE 0x8000 #define SONG_AMIGALIMITS 0x10000 -#define SONG_INSTRUMENTMODE 0x20000 -#define SONG_ORDERLOCKED 0x40000 -#define SONG_NOSTEREO 0x80000 // Global Options (Renderer) #define SNDMIX_REVERSESTEREO 0x0001 @@ -284,10 +272,7 @@ #define SNDMIX_ENABLEMMX 0x20000 #define SNDMIX_NOBACKWARDJUMPS 0x40000 #define SNDMIX_MAXDEFAULTPAN 0x80000 // Used by the MOD loader -#define SNDMIX_MUTECHNMODE 0x100000 // Notes are not played on muted channels -#define SNDMIX_NOSURROUND 0x200000 -#define SNDMIX_NOMIXING 0x400000 // don't actually do any mixing (values only) -#define SNDMIX_NORAMPING 0x800000 + // Reverb Types (GM2 Presets) enum { @@ -317,59 +302,66 @@ UINT nSustainStart, nSustainEnd; signed char *pSample; UINT nC4Speed; - UINT nPan; - UINT nVolume; - UINT nGlobalVol; - UINT uFlags; - int RelativeTone; - int nFineTune; - UINT nVibType; - UINT nVibSweep; - UINT nVibDepth; - UINT nVibRate; + WORD nPan; + WORD nVolume; + WORD nGlobalVol; + WORD uFlags; + signed char RelativeTone; + signed char nFineTune; + BYTE nVibType; + BYTE nVibSweep; + BYTE nVibDepth; + BYTE nVibRate; CHAR name[22]; - int played; // for note playback dots } MODINSTRUMENT; -typedef struct _INSTRUMENTENVELOPE { - int Ticks[32]; - BYTE Values[32]; - int nNodes; - int nLoopStart; - int nLoopEnd; - int nSustainStart; - int nSustainEnd; -} INSTRUMENTENVELOPE; - // Instrument Struct typedef struct _INSTRUMENTHEADER { UINT nFadeOut; DWORD dwFlags; - unsigned int nGlobalVol; - unsigned int nPan; - unsigned int Keyboard[128]; - unsigned int NoteMap[128]; - INSTRUMENTENVELOPE VolEnv; - INSTRUMENTENVELOPE PanEnv; - INSTRUMENTENVELOPE PitchEnv; - unsigned int nNNA; - unsigned int nDCT; - unsigned int nDNA; - unsigned int nPanSwing; - unsigned int nVolSwing; - unsigned int nIFC; - unsigned int nIFR; - unsigned int wMidiBank; - unsigned int nMidiProgram; - unsigned int nMidiChannel; - unsigned int nMidiDrumKey; - int nPPS; - unsigned int nPPC; + WORD nGlobalVol; + WORD nPan; + WORD VolPoints[MAX_ENVPOINTS]; + WORD PanPoints[MAX_ENVPOINTS]; + WORD PitchPoints[MAX_ENVPOINTS]; + BYTE VolEnv[MAX_ENVPOINTS]; + BYTE PanEnv[MAX_ENVPOINTS]; + BYTE PitchEnv[MAX_ENVPOINTS]; + BYTE Keyboard[128]; + BYTE NoteMap[128]; + + BYTE nVolEnv; + BYTE nPanEnv; + BYTE nPitchEnv; + BYTE nVolLoopStart; + BYTE nVolLoopEnd; + BYTE nVolSustainBegin; + BYTE nVolSustainEnd; + BYTE nPanLoopStart; + BYTE nPanLoopEnd; + BYTE nPanSustainBegin; + BYTE nPanSustainEnd; + BYTE nPitchLoopStart; + BYTE nPitchLoopEnd; + BYTE nPitchSustainBegin; + BYTE nPitchSustainEnd; + BYTE nNNA; + BYTE nDCT; + BYTE nDNA; + BYTE nPanSwing; + BYTE nVolSwing; + BYTE nIFC; + BYTE nIFR; + WORD wMidiBank; + BYTE nMidiProgram; + BYTE nMidiChannel; + BYTE nMidiDrumKey; + signed char nPPS; + unsigned char nPPC; CHAR name[32]; CHAR filename[12]; - int played; // for note playback dots } INSTRUMENTHEADER; @@ -380,7 +372,6 @@ signed char * pCurrentSample; DWORD nPos; DWORD nPosLo; // actually 16-bit - unsigned int topnote_offset; LONG nInc; // 16.16 LONG nRightVol; LONG nLeftVol; @@ -393,10 +384,8 @@ DWORD nLoopEnd; LONG nRampRightVol; LONG nRampLeftVol; - - double nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4; - double nFilter_A0, nFilter_B0, nFilter_B1; - + LONG nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4; + LONG nFilter_A0, nFilter_B0, nFilter_B1; LONG nROfs, nLOfs; LONG nRampLength; // Information not used in the mixer @@ -404,42 +393,37 @@ LONG nNewRightVol, nNewLeftVol; LONG nRealVolume, nRealPan; LONG nVolume, nPan, nFadeOutVol; - LONG nPeriod, nC4Speed, sample_freq, nPortamentoDest; + LONG nPeriod, nC4Speed, nPortamentoDest; INSTRUMENTHEADER *pHeader; MODINSTRUMENT *pInstrument; - int nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition; + DWORD nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition; DWORD nMasterChn, nVUMeter; LONG nGlobalVol, nInsVol; LONG nFineTune, nTranspose; LONG nPortamentoSlide, nAutoVibDepth; UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos; // 16-bit members - int nVolSwing, nPanSwing; - - // formally 8-bit members - unsigned int nNote, nNNA; - unsigned int nNewNote, nNewIns, nCommand, nArpeggio; - unsigned int nOldVolumeSlide, nOldFineVolUpDown; - unsigned int nOldPortaUpDown, nOldFinePortaUpDown; - unsigned int nOldPanSlide, nOldChnVolSlide; - unsigned int nVibratoType, nVibratoSpeed, nVibratoDepth; - unsigned int nTremoloType, nTremoloSpeed, nTremoloDepth; - unsigned int nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth; - unsigned int nOldCmdEx, nOldVolParam, nOldTempo; - unsigned int nOldOffset, nOldHiOffset; - unsigned int nCutOff, nResonance; - unsigned int nRetrigCount, nRetrigParam; - unsigned int nTremorCount, nTremorParam; - unsigned int nPatternLoop, nPatternLoopCount; - unsigned int nRowNote, nRowInstr; - unsigned int nRowVolCmd, nRowVolume; - unsigned int nRowCommand, nRowParam; - unsigned int nLeftVU, nRightVU; - unsigned int nActiveMacro, nLastInstr; - unsigned int nTickStart; - unsigned int nRealtime; - BYTE stupid_gcc_workaround; - + signed short nVolSwing, nPanSwing; + // 8-bit members + BYTE nNote, nNNA; + BYTE nNewNote, nNewIns, nCommand, nArpeggio; + BYTE nOldVolumeSlide, nOldFineVolUpDown; + BYTE nOldPortaUpDown, nOldFinePortaUpDown; + BYTE nOldPanSlide, nOldChnVolSlide; + BYTE nVibratoType, nVibratoSpeed, nVibratoDepth; + BYTE nTremoloType, nTremoloSpeed, nTremoloDepth; + BYTE nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth; + BYTE nOldCmdEx, nOldVolParam, nOldTempo; + BYTE nOldOffset, nOldHiOffset; + BYTE nCutOff, nResonance; + BYTE nRetrigCount, nRetrigParam; + BYTE nTremorCount, nTremorParam; + BYTE nPatternLoop, nPatternLoopCount; + BYTE nRowNote, nRowInstr; + BYTE nRowVolCmd, nRowVolume; + BYTE nRowCommand, nRowParam; + BYTE nLeftVU, nRightVU; + BYTE nActiveMacro, nPadding; } MODCHANNEL; @@ -470,13 +454,12 @@ class IMixPlugin { public: - virtual ~IMixPlugin() = 0; virtual int AddRef() = 0; virtual int Release() = 0; virtual void SaveAllParameters() = 0; virtual void RestoreAllParameters() = 0; - virtual void Process(float *pOutL, float *pOutR, unsigned int nSamples) = 0; - virtual void Init(unsigned int nFreq, int bReset) = 0; + virtual void Process(float *pOutL, float *pOutR, unsigned long nSamples) = 0; + virtual void Init(unsigned long nFreq, int bReset) = 0; virtual void MidiSend(DWORD dwMidiCode) = 0; virtual void MidiCommand(UINT nMidiCh, UINT nMidiProg, UINT note, UINT vol) = 0; }; @@ -540,7 +523,7 @@ } MODMIDICFG, *LPMODMIDICFG; -typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned int, unsigned int); // buffer, samples, channels +typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels @@ -552,11 +535,11 @@ static UINT m_nXBassDepth, m_nXBassRange; static UINT m_nReverbDepth, m_nReverbDelay, gnReverbType; static UINT m_nProLogicDepth, m_nProLogicDelay; + static UINT m_nStereoSeparation; static UINT m_nMaxMixChannels; static LONG m_nStreamVolume; static DWORD gdwSysInfo, gdwSoundSetup, gdwMixingFreq, gnBitsPerSample, gnChannels; - static UINT gnAGC, gnVolumeRampSamples, gnCPUUsage; - static UINT gnVULeft, gnVURight; + static UINT gnAGC, gnVolumeRampSamples, gnVUMeter, gnCPUUsage; static LPSNDMIXHOOKPROC gpSndMixHook; static PMIXPLUGINCREATEPROC gpMixPluginCreateProc; @@ -568,34 +551,27 @@ MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; // Channels settings MODCOMMAND *Patterns[MAX_PATTERNS]; // Patterns WORD PatternSize[MAX_PATTERNS]; // Patterns Lengths - WORD PatternAllocSize[MAX_PATTERNS]; // Allocated pattern lengths (for async. resizing/playback) BYTE Order[MAX_ORDERS]; // Pattern Orders MODMIDICFG m_MidiCfg; // Midi macro config table SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; // Mix plugins UINT m_nDefaultSpeed, m_nDefaultTempo, m_nDefaultGlobalVolume; DWORD m_dwSongFlags; // Song flags SONG_XXXX - UINT m_nStereoSeparation; UINT m_nChannels, m_nMixChannels, m_nMixStat, m_nBufferCount; UINT m_nType, m_nSamples, m_nInstruments; UINT m_nTickCount, m_nTotalCount, m_nPatternDelay, m_nFrameDelay; UINT m_nMusicSpeed, m_nMusicTempo; UINT m_nNextRow, m_nRow; - UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nLockedPattern,m_nRestartPos; + UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nRestartPos; UINT m_nMasterVolume, m_nGlobalVolume, m_nSongPreAmp; UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide; LONG m_nMinPeriod, m_nMaxPeriod, m_nRepeatCount, m_nInitialRepeatCount; DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples; - BYTE m_rowHighlightMajor, m_rowHighlightMinor; + UINT m_nMaxOrderPosition; UINT m_nPatternNames; LPSTR m_lpszSongComments, m_lpszPatternNames; char m_szNames[MAX_INSTRUMENTS][32]; // changed from CHAR CHAR CompressionTable[16]; - // chaseback - int stop_at_order; - int stop_at_row; - unsigned int stop_at_time; - public: CSoundFile(); ~CSoundFile(); @@ -603,7 +579,6 @@ public: BOOL Create(LPCBYTE lpStream, DWORD dwMemLength=0); BOOL Destroy(); - UINT GetHighestUsedChannel(); UINT GetType() const { return m_nType; } UINT GetNumChannels() const; UINT GetLogicalChannels() const { return m_nChannels; } @@ -658,17 +633,15 @@ BOOL ReadAMF(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadMT2(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength); + BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength); // Save Functions #ifndef MODPLUG_NO_FILESAVE - UINT WriteSample(diskwriter_driver_t *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0); - BOOL SaveXM(diskwriter_driver_t *f, UINT nPacking=0); - BOOL SaveS3M(diskwriter_driver_t *f, UINT nPacking=0); - BOOL SaveMod(diskwriter_driver_t *f, UINT nPacking=0); -#if 0 + UINT WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0); + BOOL SaveXM(LPCSTR lpszFileName, UINT nPacking=0); + BOOL SaveS3M(LPCSTR lpszFileName, UINT nPacking=0); + BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0); BOOL SaveIT(LPCSTR lpszFileName, UINT nPacking=0); -#endif #endif // MODPLUG_NO_FILESAVE // MOD Convert function UINT GetBestSaveFormat() const; @@ -677,10 +650,6 @@ void S3MConvert(MODCOMMAND *m, BOOL bIT) const; void S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const; WORD ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const; -public: - // backhooks :) - static void (*_midi_out_note)(int chan, const MODCOMMAND *m); - static void (*_midi_out_raw)(unsigned char *,unsigned int, unsigned int); public: // Real-time sound functions @@ -709,23 +678,6 @@ static void ResetAGC(); static void ProcessAGC(int count); - // Floats - static VOID StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount); - static VOID FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount); - static VOID MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount); - static VOID FloatToMonoMix(const float *pIn, int *pOut, UINT nCount); - - - - - - // wee... - static void InitializeEQ(BOOL bReset=TRUE); - static void SetEQGains(const UINT *pGains, UINT nBands, const UINT *pFreqs=NULL, BOOL bReset=FALSE); // 0=-12dB, 32=+12dB - /*static*/ void EQStereo(int *pbuffer, UINT nCount); - /*static*/ void EQMono(int *pbuffer, UINT nCount); - - //GCCFIX -- added these functions back in! static BOOL SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ); // DSP Effects @@ -742,9 +694,9 @@ BOOL ReadNote(); BOOL ProcessRow(); BOOL ProcessEffects(); - UINT GetNNAChannel(UINT nChn); + UINT GetNNAChannel(UINT nChn) const; void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut); - void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE, BOOL bManual=FALSE); + void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE); void InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE); // Channel Effects void PortamentoUp(MODCHANNEL *pChn, UINT param); @@ -770,10 +722,8 @@ void ExtendedMODCommands(UINT nChn, UINT param); void ExtendedS3MCommands(UINT nChn, UINT param); void ExtendedChannelEffect(MODCHANNEL *, UINT param); - void MidiSend(unsigned char *data, unsigned int len, UINT nChn=0, int fake = 0); - void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0, - UINT note=0, UINT velocity=0, UINT use_instr=0); - void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256,int freq=0) const; + void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0); + void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256) const; // Low-Level effect processing void DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide); // Global Effects @@ -801,7 +751,6 @@ // Period/Note functions UINT GetNoteFromPeriod(UINT period) const; UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const; - UINT GetLinearPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const; UINT GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac=0) const; // Misc functions MODINSTRUMENT *GetSample(UINT n) { return Ins+n; } @@ -810,7 +759,9 @@ BOOL ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers); UINT SaveMixPlugins(FILE *f=NULL, BOOL bUpdate=TRUE); UINT LoadMixPlugins(const void *pData, UINT nLen); - void ResetTimestamps(); // for note playback dots +#ifndef NO_FILTER + DWORD CutOffToFrequency(UINT nCutOff, int flt_modifier=256) const; // [0-255] => [1-10KHz] +#endif // Static helper functions public: @@ -958,8 +909,8 @@ #define MIXBUFFERSIZE 512 #define MIXING_ATTENUATION 4 -#define MIXING_CLIPMIN (-0x04000000) -#define MIXING_CLIPMAX (0x03FFFFFF) +#define MIXING_CLIPMIN (-0x08000000) +#define MIXING_CLIPMAX (0x07FFFFFF) #define VOLUMERAMPPRECISION 12 #define FADESONGDELAY 100 #define EQ_BUFFERSIZE (MIXBUFFERSIZE) @@ -978,21 +929,75 @@ #define MOD2XMFineTune(k) ((int)( (signed char)((k)<<4) )) #define XM2MODFineTune(k) ((int)( (k>>4)&0x0f )) -// Return (a*b)/c - no divide error -static inline int _muldiv(int a, int b, int c) -{ - return ((unsigned long long) a * (unsigned long long) b ) / c; -} +int _muldiv(long a, long b, long c); +int _muldivr(long a, long b, long c); -// Return (a*b+c/2)/c - no divide error -static inline int _muldivr(int a, int b, int c) +// Byte swapping functions from the GNU C Library and libsdl + +/* Swap bytes in 16 bit value. */ +#ifdef __GNUC__ +# define bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __bsx = (x); \ + ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); })) +#else +static __inline unsigned short int +bswap_16 (unsigned short int __bsx) { - return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c; + return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); +} +#endif + +/* Swap bytes in 32 bit value. */ +#ifdef __GNUC__ +# define bswap_32(x) \ + (__extension__ \ + ({ unsigned int __bsx = (x); \ + ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \ + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); })) +#else +static __inline unsigned int +bswap_32 (unsigned int __bsx) +{ + return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | + (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); +} +#endif + +#if (defined ARM) && (defined _WIN32_WCE) +static __inline unsigned short int +ARM_get16(const void *data) +{ + unsigned short int s; + memcpy(&s,data,sizeof(s)); + return s; } +static __inline unsigned int +ARM_get32(const void *data) +{ + unsigned int s; + memcpy(&s,data,sizeof(s)); + return s; +} -#define NEED_BYTESWAP -#include "headers.h" +#define bswapLE16(X) ARM_get16(&X) +#define bswapLE32(X) ARM_get32(&X) +#define bswapBE16(X) bswap_16(ARM_get16(&X)) +#define bswapBE32(X) bswap_32(ARM_get32(&X)) + +// From libsdl +#elif WORDS_BIGENDIAN +#define bswapLE16(X) bswap_16(X) +#define bswapLE32(X) bswap_32(X) +#define bswapBE16(X) (X) +#define bswapBE32(X) (X) +#else +#define bswapLE16(X) (X) +#define bswapLE32(X) (X) +#define bswapBE16(X) bswap_16(X) +#define bswapBE32(X) bswap_32(X) +#endif #endif diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/sndmix.cxx --- a/src/modplug/sndmix.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/sndmix.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -7,14 +7,18 @@ #include "stdafx.h" #include "sndfile.h" +#ifdef MODPLUG_TRACKER +#define ENABLE_STEREOVU +#endif // Volume ramp length, in 1/10 ms #define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz // VU-Meter -#define VUMETER_DECAY 16 +#define VUMETER_DECAY 4 // SNDMIX: These are global flags for playback control +UINT CSoundFile::m_nStereoSeparation = 128; LONG CSoundFile::m_nStreamVolume = 0x8000; UINT CSoundFile::m_nMaxMixChannels = 32; // Mixing Configuration (SetWaveConfig) @@ -26,8 +30,7 @@ // Mixing data initialized in UINT CSoundFile::gnAGC = AGC_UNITY; UINT CSoundFile::gnVolumeRampSamples = 64; -UINT CSoundFile::gnVULeft = 0; -UINT CSoundFile::gnVURight = 0; +UINT CSoundFile::gnVUMeter = 0; UINT CSoundFile::gnCPUUsage = 0; LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; @@ -39,15 +42,15 @@ typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); -extern DWORD MPPASMCALL Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern DWORD MPPASMCALL Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern DWORD MPPASMCALL Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern DWORD MPPASMCALL Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern UINT MPPASMCALL AGC(int *pBuffer, UINT nSamples, UINT nAGC); -extern VOID MPPASMCALL Dither(int *pBuffer, UINT nSamples, UINT nBits); -extern VOID MPPASMCALL InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); -extern VOID MPPASMCALL StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); -extern VOID MPPASMCALL MonoFromStereo(int *pMixBuf, UINT nSamples); +extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC); +extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits); +extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); +extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); +extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples); extern short int ModSinusTable[64]; extern short int ModRampDownTable[64]; @@ -82,6 +85,104 @@ }; +// Return (a*b)/c - no divide error +int _muldiv(long a, long b, long c) +{ +#ifdef MSC_VER + int sign, result; + _asm { + mov eax, a + mov ebx, b + or eax, eax + mov edx, eax + jge aneg + neg eax +aneg: + xor edx, ebx + or ebx, ebx + mov ecx, c + jge bneg + neg ebx +bneg: + xor edx, ecx + or ecx, ecx + mov sign, edx + jge cneg + neg ecx +cneg: + mul ebx + cmp edx, ecx + jae diverr + div ecx + jmp ok +diverr: + mov eax, 0x7fffffff +ok: + mov edx, sign + or edx, edx + jge rneg + neg eax +rneg: + mov result, eax + } + return result; +#else + return ((unsigned long long) a * (unsigned long long) b ) / c; +#endif +} + + +// Return (a*b+c/2)/c - no divide error +int _muldivr(long a, long b, long c) +{ +#ifdef MSC_VER + int sign, result; + _asm { + mov eax, a + mov ebx, b + or eax, eax + mov edx, eax + jge aneg + neg eax +aneg: + xor edx, ebx + or ebx, ebx + mov ecx, c + jge bneg + neg ebx +bneg: + xor edx, ecx + or ecx, ecx + mov sign, edx + jge cneg + neg ecx +cneg: + mul ebx + mov ebx, ecx + shr ebx, 1 + add eax, ebx + adc edx, 0 + cmp edx, ecx + jae diverr + div ecx + jmp ok +diverr: + mov eax, 0x7fffffff +ok: + mov edx, sign + or edx, edx + jge rneg + neg eax +rneg: + mov result, eax + } + return result; +#else + return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c; +#endif +} + + BOOL CSoundFile::InitPlayer(BOOL bReset) //-------------------------------------- { @@ -94,13 +195,11 @@ gnRvbROfsVol = gnRvbLOfsVol = 0; if (bReset) { - gnVULeft = 0; - gnVURight = 0; + gnVUMeter = 0; gnCPUUsage = 0; } gbInitPlugins = (bReset) ? 3 : 1; InitializeDSP(bReset); - InitializeEQ(bReset); return TRUE; } @@ -146,28 +245,22 @@ //------------------------------------------------------- { LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; - LPCONVERTPROC pCvt = Convert32To8; - LONG vu_min[2]; - LONG vu_max[2]; + LPCONVERTPROC pCvt = X86_Convert32To8; UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; -#if 0 + LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF; UINT nMaxPlugins; -#endif - vu_min[0] = vu_min[1] = 0x7FFFFFFF; - vu_max[0] = vu_max[1] = -0x7FFFFFFF; - -#if 0 { nMaxPlugins = MAX_MIXPLUGINS; while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--; } -#endif m_nMixStat = 0; lSampleSize = gnChannels; - if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; } - else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; } - else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; } + if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; } +#ifndef MODPLUG_FASTSOUNDLIB + else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; } + else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; } +#endif lMax = cbBuffer / lSampleSize; if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; lRead = lMax; @@ -175,19 +268,26 @@ while (lRead > 0) { // Update Channel Data - UINT lTotalSampleCount; if (!m_nBufferCount) { - if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) - m_nBufferCount = lRead; - if (!ReadNote()) { +#ifndef MODPLUG_FASTSOUNDLIB + if (m_dwSongFlags & SONG_FADINGSONG) + { m_dwSongFlags |= SONG_ENDREACHED; - if (stop_at_order > -1) return 0; /* faster */ - if (lRead == lMax) goto MixDone; - if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) + m_nBufferCount = lRead; + } else +#endif + if (!ReadNote()) + { +#ifndef MODPLUG_FASTSOUNDLIB + if (!FadeSong(FADESONGDELAY)) +#endif + { + m_dwSongFlags |= SONG_ENDREACHED; + if (lRead == lMax) goto MixDone; m_nBufferCount = lRead; + } } - if (!m_nBufferCount) goto MixDone; } lCount = m_nBufferCount; if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; @@ -197,46 +297,30 @@ #ifndef MODPLUG_NO_REVERB gnReverbSend = 0; #endif - // Resetting sound buffer - StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); + X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); if (gnChannels >= 2) { lSampleCount *= 2; m_nMixStat += CreateStereoMix(lCount); -#if 0 - if (nMaxPlugins) ProcessPlugins(lCount); -#endif ProcessStereoDSP(lCount); } else { m_nMixStat += CreateStereoMix(lCount); -#if 0 - if (nMaxPlugins) ProcessPlugins(lCount); -#endif - MonoFromStereo(MixSoundBuffer, lCount); - ProcessMonoDSP(lCount); + ProcessStereoDSP(lCount); + X86_MonoFromStereo(MixSoundBuffer, lCount); } - - if (gdwSoundSetup & SNDMIX_EQ) - { - if (gnChannels >= 2) - EQStereo(MixSoundBuffer, lCount); - else - EQMono(MixSoundBuffer, lCount); - } - - nStat++; #ifndef NO_AGC // Automatic Gain Control if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount); #endif - lTotalSampleCount = lSampleCount; + UINT lTotalSampleCount = lSampleCount; +#ifndef MODPLUG_FASTSOUNDLIB // Multichannel if (gnChannels > 2) { - InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); + X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); lTotalSampleCount *= 2; } // Hook Function @@ -244,8 +328,9 @@ { gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); } +#endif // Perform clipping + VU-Meter - lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max); + lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax); // Buffer ready lRead -= lCount; m_nBufferCount -= lCount; @@ -253,16 +338,10 @@ MixDone: if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); // VU-Meter - vu_min[0] >>= 18; - vu_min[1] >>= 18; - vu_max[0] >>= 18; - vu_max[1] >>= 18; - if (vu_max[0] < vu_min[0]) vu_max[0] = vu_min[0]; - if (vu_max[1] < vu_min[1]) vu_max[1] = vu_min[1]; - if ((gnVULeft = (UINT)(vu_max[0] - vu_min[0])) > 0xFF) - gnVULeft = 0xFF; - if ((gnVURight = (UINT)(vu_max[1] - vu_min[1])) > 0xFF) - gnVURight = 0xFF; + nVUMeterMin >>= (24-MIXING_ATTENUATION); + nVUMeterMax >>= (24-MIXING_ATTENUATION); + if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin; + if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF; if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } return lMax - lRead; } @@ -276,75 +355,77 @@ //--------------------------- { if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay) - { + { m_nPatternDelay = 0; m_nFrameDelay = 0; m_nTickCount = 0; m_nRow = m_nNextRow; - // Reset Pattern Loop Effect - if (m_nCurrentPattern != m_nNextPattern) { - if (m_nLockedPattern < MAX_ORDERS) { - m_nCurrentPattern = m_nLockedPattern; - if (!(m_dwSongFlags & SONG_ORDERLOCKED)) - m_nLockedPattern = MAX_ORDERS; - } else { - m_nCurrentPattern = m_nNextPattern; - } - - // Check if pattern is valid - if (!(m_dwSongFlags & SONG_PATTERNLOOP)) + if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern; + // Check if pattern is valid + if (!(m_dwSongFlags & SONG_PATTERNLOOP)) + { + m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; + if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; + while (m_nPattern >= MAX_PATTERNS) { + // End of song ? + if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) + { + //if (!m_nRepeatCount) + return FALSE; //never repeat entire song + if (!m_nRestartPos) + { + m_nMusicSpeed = m_nDefaultSpeed; + m_nMusicTempo = m_nDefaultTempo; + m_nGlobalVolume = m_nDefaultGlobalVolume; + for (UINT i=0; i 0) m_nRepeatCount--; + m_nCurrentPattern = m_nRestartPos; + m_nRow = 0; + if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE; + } else + { + m_nCurrentPattern++; + } m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - while (m_nPattern >= MAX_PATTERNS) - { - // End of song ? - if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) - { - if (m_nRepeatCount > 0) m_nRepeatCount--; - if (!m_nRepeatCount) return FALSE; - m_nCurrentPattern = m_nRestartPos; - if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) - || (!Patterns[Order[m_nCurrentPattern]])) - return FALSE; - } else { - m_nCurrentPattern++; - } - m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; - if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - } - m_nNextPattern = m_nCurrentPattern; - } else if (m_nCurrentPattern < 255) { - if (m_nRepeatCount > 0) m_nRepeatCount--; - if (!m_nRepeatCount) return FALSE; } - } -#ifdef MODPLUG_TRACKER - if (m_dwSongFlags & SONG_STEP) - { - m_dwSongFlags &= ~SONG_STEP; - m_dwSongFlags |= SONG_PAUSED; - } -#endif // MODPLUG_TRACKER - if (!PatternSize[m_nPattern] || !Patterns[m_nPattern]) { - /* okay, this is wrong. allocate the pattern _NOW_ */ - Patterns[m_nPattern] = AllocatePattern(64,64); - PatternSize[m_nPattern] = 64; - PatternAllocSize[m_nPattern] = 64; + m_nNextPattern = m_nCurrentPattern; } // Weird stuff? - if (m_nPattern >= MAX_PATTERNS) return FALSE; + if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE; // Should never happen - // ... sure it should: suppose there's a C70 effect before a 64-row pattern. - // It's in fact very easy to make this happen ;) - // - chisel if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0; - m_nNextRow = m_nRow + 1; + m_nNextRow = m_nRow + 1; if (m_nNextRow >= PatternSize[m_nPattern]) { if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1; - else if (m_nRepeatCount > 0) return FALSE; m_nNextRow = 0; } // Reset channel values @@ -352,18 +433,7 @@ MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; for (UINT nChn=0; nChnnRealtime) continue; - - // this is where we're going to spit out our midi - // commands... ALL WE DO is dump raw midi data to - // our super-secret "midi buffer" - // -mrsb - if (_midi_out_note) - _midi_out_note(nChn, m); - pChn->nRowNote = m->note; - if (m->instr) pChn->nLastInstr = m->instr; pChn->nRowInstr = m->instr; pChn->nRowVolCmd = m->volcmd; pChn->nRowVolume = m->vol; @@ -375,14 +445,6 @@ pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO); pChn->nCommand = 0; } - - } else if (_midi_out_note) { - MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; - for (UINT nChn=0; nChn= m_nMusicSpeed) { - m_nTickCount = 0; - } - if (!ProcessEffects()) return FALSE; - } else - { - if (!ProcessRow()) return FALSE; - } - - { /* handle realtime closures */ - MODCHANNEL *pChn = Chn; - for (UINT nChn=0; nChnnRealtime && pChn->nRowNote && (pChn->nTickStart % m_nMusicSpeed) == (m_nTickCount % m_nMusicSpeed)) { - pChn->nRealtime = 0; - pChn->nRowNote = 0; - pChn->nRowInstr = 0; - //pChn->nMaster - pChn->nRowVolCmd = 0; - pChn->nRowVolume = 0; - pChn->nRowCommand = 0; - pChn->nRowParam = 0; - pChn->nTickStart = 0; - } - } - }; - + if (!ProcessRow()) return FALSE; //////////////////////////////////////////////////////////////////////////////////// m_nTotalCount++; if (!m_nMusicTempo) return FALSE; m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); -#ifdef MODPLUG_TRACKER - if (m_dwSongFlags & SONG_PAUSED) - { - m_nBufferCount = gdwMixingFreq / 64; // 1/64 seconds - } -#endif - - // chaseback hoo hah - if (stop_at_order > -1 && stop_at_row > -1) { - if (stop_at_order <= (signed) m_nCurrentPattern && stop_at_row <= (signed) m_nRow) { - return FALSE; - } - } - // Master Volume + Pre-Amplification / Attenuation setup DWORD nMasterVol; { - int nchn32 = 0; - MODCHANNEL *pChn = Chn; - for (UINT nChn=0; nChn 31) nchn32 = 31; - + int nchn32 = (m_nChannels < 32) ? m_nChannels : 31; + if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6; int realmastervol = m_nMasterVolume; if (realmastervol > 0x80) { realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; } - - DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 6; -// if (mastervol > 0x200) mastervol = 0x200; + UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; + DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6; + if (mastervol > 0x200) mastervol = 0x200; if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples)) { mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples); } - - UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; - if (attenuation < 1) attenuation = 1; - nMasterVol = (mastervol << 7) / attenuation; if (nMasterVol > 0x180) nMasterVol = 0x180; } //////////////////////////////////////////////////////////////////////////////////// // Update channels data - if (CSoundFile::gdwSoundSetup & SNDMIX_NOMIXING) return TRUE; m_nMixChannels = 0; MODCHANNEL *pChn = Chn; for (UINT nChn=0; nChnnROfs = pChn->nLOfs = 0; } // Check for unused channel - if ((nChn >= m_nChannels) && (!pChn->nLength)) + if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength))) { + pChn->nVUMeter = 0; +#ifdef ENABLE_STEREOVU pChn->nLeftVU = pChn->nRightVU = 0; +#endif continue; } // Reset channel data @@ -577,33 +575,33 @@ if (vol > 0x100) vol = 0x100; vol <<= 6; // Process Envelopes - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) + if (pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; // Volume Envelope - if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes)) + if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv)) { int envpos = pChn->nVolEnvPosition; - UINT pt = penv->VolEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++) + UINT pt = penv->nVolEnv - 1; + for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++) { - if (envpos <= penv->VolEnv.Ticks[i]) + if (envpos <= penv->VolPoints[i]) { pt = i; break; } } - int x2 = penv->VolEnv.Ticks[pt]; + int x2 = penv->VolPoints[pt]; int x1, envvol; if (envpos >= x2) { - envvol = penv->VolEnv.Values[pt] << 2; + envvol = penv->VolEnv[pt] << 2; x1 = x2; } else if (pt) { - envvol = penv->VolEnv.Values[pt-1] << 2; - x1 = penv->VolEnv.Ticks[pt-1]; + envvol = penv->VolEnv[pt-1] << 2; + x1 = penv->VolPoints[pt-1]; } else { envvol = 0; @@ -612,26 +610,26 @@ if (envpos > x2) envpos = x2; if ((x2 > x1) && (envpos > x1)) { - envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[pt]<<2) - envvol)) / (x2 - x1); + envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1); } if (envvol < 0) envvol = 0; if (envvol > 256) envvol = 256; vol = (vol * envvol) >> 8; } // Panning Envelope - if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes)) + if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv)) { int envpos = pChn->nPanEnvPosition; - UINT pt = penv->PanEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++) + UINT pt = penv->nPanEnv - 1; + for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++) { - if (envpos <= penv->PanEnv.Ticks[i]) + if (envpos <= penv->PanPoints[i]) { pt = i; break; } } - int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt]; + int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt]; int x1, envpan; if (envpos >= x2) { @@ -640,8 +638,8 @@ } else if (pt) { - envpan = penv->PanEnv.Values[pt-1]; - x1 = penv->PanEnv.Ticks[pt-1]; + envpan = penv->PanEnv[pt-1]; + x1 = penv->PanPoints[pt-1]; } else { envpan = 128; @@ -716,13 +714,8 @@ { switch(m_nTickCount % 3) { -#if 0 case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; -#else - case 1: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; - case 2: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; -#endif } } @@ -733,32 +726,30 @@ } // Pitch/Filter Envelope - int envpitch = 0; - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) - && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes)) + if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv)) { INSTRUMENTHEADER *penv = pChn->pHeader; int envpos = pChn->nPitchEnvPosition; - UINT pt = penv->PitchEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++) + UINT pt = penv->nPitchEnv - 1; + for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++) { - if (envpos <= penv->PitchEnv.Ticks[i]) + if (envpos <= penv->PitchPoints[i]) { pt = i; break; } } - int x2 = penv->PitchEnv.Ticks[pt]; - int x1; + int x2 = penv->PitchPoints[pt]; + int x1, envpitch; if (envpos >= x2) { - envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; + envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8; x1 = x2; } else if (pt) { - envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8; - x1 = penv->PitchEnv.Ticks[pt-1]; + envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8; + x1 = penv->PitchPoints[pt-1]; } else { envpitch = 0; @@ -767,13 +758,19 @@ if (envpos > x2) envpos = x2; if ((x2 > x1) && (envpos > x1)) { - int envpitchdest = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; + int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8; envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); } if (envpitch < -256) envpitch = -256; if (envpitch > 256) envpitch = 256; + // Filter Envelope: controls cutoff frequency + if (penv->dwFlags & ENV_FILTER) + { +#ifndef NO_FILTER + SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); +#endif // NO_FILTER + } else // Pitch Envelope - if (!(penv->dwFlags & ENV_FILTER)) { int l = envpitch; if (l < 0) @@ -863,16 +860,6 @@ if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth)) { MODINSTRUMENT *pins = pChn->pInstrument; - /* this isn't correct, but its better... */ - - if (pins->nVibSweep == 0) { - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } else { - pChn->nAutoVibDepth += pins->nVibSweep; - if ((pChn->nAutoVibDepth >> 8) > (int)pins->nVibDepth) - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } -#if 0 if (pins->nVibSweep == 0) { pChn->nAutoVibDepth = pins->nVibDepth << 8; @@ -880,7 +867,7 @@ { if (m_nType & MOD_TYPE_IT) { - pChn->nAutoVibDepth += pins->nVibSweep; + pChn->nAutoVibDepth += pins->nVibSweep << 3; } else if (!(pChn->dwFlags & CHN_KEYOFF)) { @@ -889,8 +876,7 @@ if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) pChn->nAutoVibDepth = pins->nVibDepth << 8; } -#endif - pChn->nAutoVibPos += ((int)pins->nVibRate); + pChn->nAutoVibPos += pins->nVibRate; int val; switch(pins->nVibType) { @@ -911,10 +897,6 @@ val = ft2VibratoTable[pChn->nAutoVibPos & 255]; } int n = ((val * pChn->nAutoVibDepth) >> 8); - // is this right? -mrsb - if (!(m_dwSongFlags & SONG_ITOLDEFFECTS)) - n >>= 1; - if (m_nType & MOD_TYPE_IT) { int df1, df2; @@ -957,25 +939,12 @@ nPeriodFrac = 0; } UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); - - // Filter Envelope: controls cutoff frequency - if (pChn && pChn->pHeader && pChn->pHeader->dwFlags & ENV_FILTER) - { -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); -#endif // NO_FILTER - } - -#if 0 if ((m_nType & MOD_TYPE_IT) && (freq < 256)) { pChn->nFadeOutVol = 0; pChn->dwFlags |= CHN_NOTEFADE; pChn->nRealVolume = 0; } -#endif - pChn->sample_freq = freq; - UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq); if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000; if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7; @@ -984,7 +953,7 @@ } // Increment envelope position - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) + if (pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; // Volume Envelope @@ -995,13 +964,13 @@ // Volume Loop ? if (penv->dwFlags & ENV_VOLLOOP) { - int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd]; + UINT volloopend = penv->VolPoints[penv->nVolLoopEnd]; if (m_nType != MOD_TYPE_XM) volloopend++; if (pChn->nVolEnvPosition == volloopend) { - pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nLoopStart]; - if ((penv->VolEnv.nLoopEnd == penv->VolEnv.nLoopStart) && (!penv->VolEnv.Values[penv->VolEnv.nLoopStart]) - && ((!(m_nType & MOD_TYPE_XM)) || (penv->VolEnv.nLoopEnd+1 == penv->VolEnv.nNodes))) + pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart]; + if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart]) + && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv))) { pChn->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; @@ -1011,15 +980,15 @@ // Volume Sustain ? if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) { - if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1) - pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart]; + if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1) + pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin]; } else // End of Envelope ? - if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]) + if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1]) { if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; - pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]; - if ((!penv->VolEnv.Values[penv->VolEnv.nNodes-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) + pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1]; + if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) { pChn->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; @@ -1034,21 +1003,21 @@ pChn->nPanEnvPosition++; if (penv->dwFlags & ENV_PANLOOP) { - int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd]; + UINT panloopend = penv->PanPoints[penv->nPanLoopEnd]; if (m_nType != MOD_TYPE_XM) panloopend++; if (pChn->nPanEnvPosition == panloopend) - pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart]; + pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart]; } // Panning Sustain ? - if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1) + if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1) && (!(pChn->dwFlags & CHN_KEYOFF))) { // Panning sustained - pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart]; + pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin]; } else { - if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]) - pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]; + if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1]) + pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1]; } } // Pitch Envelope @@ -1059,22 +1028,22 @@ // Pitch Loop ? if (penv->dwFlags & ENV_PITCHLOOP) { - if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd]) - pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart]; + if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd]) + pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart]; } // Pitch Sustain ? if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) { - if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1) - pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart]; + if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1) + pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin]; } else { - if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]) - pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]; + if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1]) + pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1]; } } } -#if 0 +#ifdef MODPLUG_PLAYER // Limit CPU -> > 80% -> don't ramp if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) { @@ -1085,10 +1054,14 @@ pChn->dwFlags &= ~CHN_VOLUMERAMP; if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol)) pChn->dwFlags |= CHN_VOLUMERAMP; +#ifdef MODPLUG_PLAYER // Decrease VU-Meter if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0; +#endif // MODPLUG_PLAYER +#ifdef ENABLE_STEREOVU if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0; if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0; +#endif // Check for too big nInc if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP; pChn->nNewRightVol = pChn->nNewLeftVol = 0; @@ -1096,11 +1069,14 @@ if (pChn->pCurrentSample) { // Update VU-Meter (nRealVolume is 14-bit) +#ifdef MODPLUG_PLAYER UINT vutmp = pChn->nRealVolume >> (14 - 8); if (vutmp > 0xFF) vutmp = 0xFF; if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp; vutmp >>= 1; if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp; +#endif // MODPLUG_PLAYER +#ifdef ENABLE_STEREOVU UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14; if (vul > 127) vul = 127; if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul; @@ -1111,6 +1087,7 @@ if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur; vur >>= 1; if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur; +#endif #ifdef MODPLUG_TRACKER UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol; #else @@ -1126,8 +1103,9 @@ if (pan < 0) pan = 0; if (pan > 256) pan = 256; +#ifndef MODPLUG_FASTSOUNDLIB if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; - if (m_dwSongFlags & SONG_NOSTEREO) pan = 128; +#endif LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); if (gdwSoundSetup & SNDMIX_SOFTPANNING) { @@ -1156,7 +1134,6 @@ // Check IDO if (gdwSoundSetup & SNDMIX_NORESAMPLING) { - pChn->dwFlags &= ~(CHN_HQSRC); pChn->dwFlags |= CHN_NOIDO; } else { @@ -1174,26 +1151,21 @@ pChn->nNewLeftVol >>= MIXING_ATTENUATION; pChn->nRightRamp = pChn->nLeftRamp = 0; // Dolby Pro-Logic Surround - if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0) - pChn->nNewLeftVol = -pChn->nNewLeftVol; + if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol; // Checking Ping-Pong Loops if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; // Setting up volume ramp - if (!(gdwSoundSetup & SNDMIX_NORAMPING) - && (pChn->dwFlags & CHN_VOLUMERAMP) + if ((pChn->dwFlags & CHN_VOLUMERAMP) && ((pChn->nRightVol != pChn->nNewRightVol) || (pChn->nLeftVol != pChn->nNewLeftVol))) { LONG nRampLength = gnVolumeRampSamples; LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION); LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION); -#if 0 +#ifndef MODPLUG_FASTSOUNDLIB if ((gdwSoundSetup & SNDMIX_DIRECTTODISK) || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU)) && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20))) -#else - if (gdwSoundSetup & SNDMIX_HQRESAMPLER) -#endif { if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP))) { @@ -1202,6 +1174,7 @@ if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; } } +#endif pChn->nRightRamp = nRightDelta / nRampLength; pChn->nLeftRamp = nLeftDelta / nRampLength; pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); @@ -1224,15 +1197,15 @@ pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; // Adding the channel in the channel list - if (!(pChn->dwFlags & CHN_MUTE)) { - ChnMix[m_nMixChannels++] = nChn; - if (m_nMixChannels >= MAX_CHANNELS) break; - } + ChnMix[m_nMixChannels++] = nChn; + if (m_nMixChannels >= MAX_CHANNELS) break; } else { +#ifdef ENABLE_STEREOVU // Note change but no sample if (pChn->nLeftVU > 128) pChn->nLeftVU = 0; if (pChn->nRightVU > 128) pChn->nRightVU = 0; +#endif if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0; pChn->nLeftVol = pChn->nRightVol = 0; pChn->nLength = 0; diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/stdafx.h --- a/src/modplug/stdafx.h Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/stdafx.h Fri Dec 07 12:13:37 2007 -0600 @@ -9,7 +9,6 @@ #ifndef _STDAFX_H_ #define _STDAFX_H_ -#include "headers.h" #ifdef MSC_VER @@ -20,9 +19,7 @@ #include #include -inline void ProcessPlugins(int n) {} - -#else +#elif defined(__x86_64__) || defined(__powerpc64__) #include #include @@ -39,20 +36,24 @@ typedef unsigned short WORD; typedef unsigned char BYTE; typedef unsigned char * LPBYTE; -#ifdef __cplusplus typedef bool BOOL; -#endif typedef char * LPSTR; typedef void * LPVOID; typedef int * LPLONG; typedef unsigned int * LPDWORD; typedef unsigned short * LPWORD; typedef const char * LPCSTR; -typedef long long LONGLONG; +typedef long LONGLONG; typedef void * PVOID; typedef void VOID; +inline LONG MulDiv (int a, int b, int c) +{ + // if (!c) return 0; + return ((unsigned long)a * (unsigned long) b ) / c; +} +#define MODPLUG_NO_FILESAVE #define NO_AGC #define LPCTSTR LPCSTR #define lstrcpyn strncpy @@ -63,7 +64,6 @@ #define GHND 0 -#ifdef __cplusplus inline signed char * GlobalAllocPtr(unsigned int, size_t size) { signed char * p = (signed char *) malloc(size); @@ -72,13 +72,86 @@ return p; } -inline void ProcessPlugins(int) {} +#define GlobalFreePtr(p) free((void *)(p)) + +#define strnicmp(a,b,c) strncasecmp(a,b,c) +#define wsprintf sprintf + +#ifndef FALSE +#define FALSE false +#endif + +#ifndef TRUE +#define TRUE true +#endif + +#else + +#include +#include +#include + +typedef signed char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char* PUCHAR; +typedef unsigned short USHORT; +#if defined(__x86_64__) || defined(__powerpc64__) +typedef unsigned int ULONG; +typedef unsigned int UINT; +typedef unsigned int DWORD; +typedef int LONG; +typedef long LONGLONG; +typedef int * LPLONG; +typedef unsigned int * LPDWORD; +#else +typedef unsigned long ULONG; +typedef unsigned long UINT; +typedef unsigned long DWORD; +typedef long LONG; +typedef long long LONGLONG; +typedef long * LPLONG; +typedef unsigned long * LPDWORD; +#endif +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef unsigned char * LPBYTE; +typedef bool BOOL; +typedef char * LPSTR; +typedef void * LPVOID; +typedef unsigned short * LPWORD; +typedef const char * LPCSTR; +typedef void * PVOID; +typedef void VOID; + +inline LONG MulDiv (long a, long b, long c) +{ + // if (!c) return 0; + return ((unsigned long long) a * (unsigned long long) b ) / c; +} + +#define MODPLUG_NO_FILESAVE +#define NO_AGC +#define LPCTSTR LPCSTR +#define lstrcpyn strncpy +#define lstrcpy strcpy +#define lstrcmp strcmp +#define WAVE_FORMAT_PCM 1 +//#define ENABLE_EQ + +#define GHND 0 + +inline signed char * GlobalAllocPtr(unsigned int, size_t size) +{ + signed char * p = (signed char *) malloc(size); + + if (p != NULL) memset(p, 0, size); + return p; +} #define GlobalFreePtr(p) free((void *)(p)) #define strnicmp(a,b,c) strncasecmp(a,b,c) #define wsprintf sprintf -#endif #ifndef FALSE #define FALSE false diff -r 6a4d667a9183 -r 6907fc39b53f src/modplug/tables.cxx --- a/src/modplug/tables.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/tables.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -7,6 +7,10 @@ #include "stdafx.h" #include "sndfile.h" +#ifndef MODPLUG_FASTSOUNDLIB +//#pragma data_seg(".tables") +#endif + BYTE ImpulseTrackerPortaVolCmd[16] = { 0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40, 0x60,