# HG changeset patch # User "Tony Vroon " # Date 1201176359 0 # Node ID 107c1fed3d922fdeab41c41cb86e36de8f0256ca # Parent ad45d65e9ae7c03b13fcb5e7acb0425dcbfe8b6b Port Schism modplug core. diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/Makefile --- a/src/modplug/Makefile Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/Makefile Thu Jan 24 12:05:59 2008 +0000 @@ -5,6 +5,7 @@ tables.cxx \ sndmix.cxx \ sndfile.cxx \ + snd_eq.cxx \ snd_fx.cxx \ snd_flt.cxx \ snd_dsp.cxx \ @@ -21,6 +22,7 @@ load_mtm.cxx \ load_mod.cxx \ load_med.cxx \ + load_mid.cxx \ load_mdl.cxx \ load_it.cxx \ load_far.cxx \ @@ -33,7 +35,6 @@ load_j2b.cxx \ load_mt2.cxx \ load_psm.cxx \ - modplug.cxx \ archive/archive.cxx \ archive/open.cxx \ archive/arch_raw.cxx \ diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/fastmix.cxx --- a/src/modplug/fastmix.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/fastmix.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -12,10 +12,6 @@ #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]; @@ -25,14 +21,8 @@ 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; @@ -530,37 +520,39 @@ // Resonant Filters // Mono -#define MIX_BEGIN_FILTER\ - int fy1 = pChannel->nFilter_Y1;\ - int fy2 = pChannel->nFilter_Y2;\ +#define MIX_BEGIN_FILTER \ + double fy1 = pChannel->nFilter_Y1;\ + double fy2 = pChannel->nFilter_Y2;\ + double ta; -#define MIX_END_FILTER\ +#define MIX_END_FILTER \ pChannel->nFilter_Y1 = fy1;\ pChannel->nFilter_Y2 = fy2; -#define SNDMIX_PROCESSFILTER\ - vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\ - fy2 = fy1;\ - fy1 = vol;\ +#define SNDMIX_PROCESSFILTER \ +ta = ((double)vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\ +fy2 = fy1;\ +fy1 = ta;vol=(int)ta; // Stereo -#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_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_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\ - 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;\ +#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; ////////////////////////////////////////////////////////// // Interfaces @@ -659,11 +651,17 @@ ///////////////////////////////////////////////////// // -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); +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); ///////////////////////////////////////////////////// // Mono samples functions @@ -1466,9 +1464,7 @@ DWORD nchused, nchmixed; if (!count) return 0; -#ifndef MODPLUG_FASTSOUNDLIB - if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2); -#endif + if (gnChannels > 2) InitMixBuffer(MixRearBuffer, count*2); nchused = nchmixed = 0; for (UINT nChn=0; nChndwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER; #endif - if (!(pChannel->dwFlags & CHN_NOIDO)) + if (!(pChannel->dwFlags & CHN_NOIDO) + && !(gdwSoundSetup & SNDMIX_NORESAMPLING)) { // use hq-fir mixer? if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) ) - nFlags += MIXNDX_FIRSRC; - else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER ) - nFlags += MIXNDX_SPLINESRC; + nFlags |= MIXNDX_FIRSRC; + else if( (gdwSoundSetup & 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))) @@ -1536,7 +1533,7 @@ pChannel->nPos = 0; pChannel->nPosLo = 0; pChannel->nRampLength = 0; - X86_EndChannelOfs(pChannel, pbuffer, nsamples); + EndChannelOfs(pChannel, pbuffer, nsamples); *pOfsR += pChannel->nROfs; *pOfsL += pChannel->nLOfs; pChannel->nROfs = pChannel->nLOfs = 0; @@ -1557,6 +1554,10 @@ } 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]; @@ -1593,81 +1594,59 @@ return nchused; } +static float f2ic = (float)(1 << 28); +static float i2fc = (float)(1.0 / (1 << 28)); -#ifdef MSC_VER -#pragma warning (disable:4100) -#endif +VOID CSoundFile::StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount) +//----------------------------------------------------------------------------------------- +{ + for (UINT i = 0; i < nCount; i++) { + *pOut1++ = *pSrc * i2fc; /*!*/ + pSrc++; + + *pOut2++ = *pSrc * i2fc; /*!*/ + pSrc++; + } +} + + +VOID CSoundFile::FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount) +//--------------------------------------------------------------------------------------------- +{ + for (UINT i = 0; i < nCount; i++) { + *pOut++ = (int)(*pIn1 * f2ic); + *pOut++ = (int)(*pIn2 * f2ic); + pIn1++; + pIn2++; + } +} + + +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 -#ifdef MSC_VER -__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(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] - 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 - } -} -#else //MSC_VER //---GCCFIX: Asm replaced with C function // The C version was written by Rani Assaf , I believe -DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +DWORD Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) { - int vumin = *lpMin, vumax = *lpMax; unsigned char *p = (unsigned char *)lp8; for (UINT i=0; i MIXING_CLIPMAX) n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; + if (n < mins[i&1]) + mins[i&1]= n; + else if (n > maxs[i&1]) + maxs[i&1] = 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 MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +DWORD Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) { - int vumin = *lpMin, vumax = *lpMax; signed short *p = (signed short *)lp16; for (UINT i=0; i MIXING_CLIPMAX) n = MIXING_CLIPMAX; - if (n < vumin) - vumin = n; - else if (n > vumax) - vumax = n; + if (n < mins[i&1]) + mins[i&1]= n; + else if (n > maxs[i&1]) + maxs[i&1] = 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 -DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax) +// 24-bit might not work... +DWORD Convert32To24(LPVOID lp24, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2]) { - UINT i ; - int vumin = *lpMin, vumax = *lpMax; - int n,p ; - unsigned char* buf = (unsigned char*)lp16 ; - - for ( 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 < vumin) - vumin = n; - else if (n > vumax) - vumax = n; - p[i] = n << MIXING_ATTENUATION; // 32-bit signed + 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; } - *lpMin = vumin; - *lpMax = vumax; - return lSampleCount * 4; + return lSampleCount * 2; } -#endif - - -#ifdef MSC_VER -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) -//------------------------------------------------------------ +//---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]) { - _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:; + 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 } + return lSampleCount * 2; } -#else //---GCCFIX: Asm replaced with C function // Will fill in later. -void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples) +void InitMixBuffer(int *pBuffer, UINT nSamples) { memset(pBuffer, 0, nSamples * sizeof(int)); } -#endif - -#ifdef MSC_VER -__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) -//------------------------------------------------------------------------------------------------------ +//---GCCFIX: Asm replaced with C function +void InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples) { - _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 + DWORD i=0; + + pRearBuf[i] = pFrontBuf[1]; + for (i = 1; i < nSamples; i++) { + pRearBuf[i] = pFrontBuf[(i*2)+1]; + pFrontBuf[i] = pFrontBuf[i*2]; } } -#else //---GCCFIX: Asm replaced with C function -// 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) +VOID MonoFromStereo(int *pMixBuf, UINT nSamples) { UINT j; for(UINT i = 0; i < nSamples; i++) @@ -2095,89 +1755,11 @@ 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 MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) +void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs) //--------------------------------------------------------------------------------------------------------- { int rofs = *lpROfs; @@ -2185,7 +1767,7 @@ if ((!rofs) && (!lofs)) { - X86_InitMixBuffer(pBuffer, nSamples*2); + InitMixBuffer(pBuffer, nSamples*2); return; } for (UINT i=0; inROfs; int lofs = pChannel->nLOfs; @@ -2264,7 +1802,9 @@ pChannel->nROfs = rofs; pChannel->nLOfs = lofs; } -#endif + + + ////////////////////////////////////////////////////////////////////////////////// @@ -2276,72 +1816,11 @@ #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 = X86_AGC(MixSoundBuffer, count, gnAGC); + UINT agc = 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) @@ -2371,3 +1850,4 @@ } #endif // NO_AGC + diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/it_defs.h --- a/src/modplug/it_defs.h Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/it_defs.h Thu Jan 24 12:05:59 2008 +0000 @@ -7,7 +7,8 @@ { DWORD id; // 0x4D504D49 CHAR songname[26]; - WORD reserved1; // 0x1004 + BYTE hilight_minor; + BYTE hilight_major; WORD ordnum; WORD insnum; WORD smpnum; @@ -21,7 +22,7 @@ BYTE speed; BYTE tempo; BYTE sep; - BYTE zero; + BYTE pwd; WORD msglength; DWORD msgoffset; DWORD reserved2; diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_669.cxx --- a/src/modplug/load_669.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_669.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -51,12 +51,9 @@ || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE; DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600; if (dontfuckwithme > dwMemLength) return FALSE; - for (UINT ichk=0; ichksamples; ichk++) - { - DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length))); - dontfuckwithme += len; - } - if (dontfuckwithme > dwMemLength) return FALSE; + for (int n = 0; n < 128; n++) + if (pfh->breaks[n] > 0x3f) + return false; // That should be enough checking: this must be a 669 module. m_nType = MOD_TYPE_669; m_dwSongFlags |= SONG_LINEARSLIDES; @@ -65,7 +62,8 @@ m_nDefaultTempo = 125; m_nDefaultSpeed = 6; m_nChannels = 8; - memcpy(m_szNames[0], pfh->songmessage, 16); + memcpy(m_szNames[0], pfh->songmessage, 31); + m_szNames[0][31] = 0; m_nSamples = pfh->samples; for (UINT nins=1; nins<=m_nSamples; nins++, psmp++) { @@ -86,9 +84,15 @@ Ins[nins].nPan = 128; } // Song Message - m_lpszSongComments = new char[109]; - memcpy(m_lpszSongComments, pfh->songmessage, 108); - m_lpszSongComments[108] = 0; + 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; // Reading Orders memcpy(Order, pfh->orders, 128); m_nRestartPos = pfh->restartpos; @@ -106,6 +110,7 @@ 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_amf.cxx --- a/src/modplug/load_amf.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_amf.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -5,7 +5,7 @@ * option) any later version. * * Authors: Olivier Lapicque -*/ + */ /////////////////////////////////////////////////// // @@ -223,6 +223,7 @@ 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++) { @@ -314,9 +315,11 @@ { 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,8 +356,7 @@ 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; } @@ -373,7 +375,7 @@ for (UINT iTrack=0; iTrack= 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; @@ -334,6 +335,7 @@ 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++) { @@ -378,15 +380,15 @@ // Volume Envelope { UINT pos = 0; - 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.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->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); + penv->VolEnv.Values[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1); pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8); - penv->VolPoints[i] = (WORD)pos; + penv->VolEnv.Ticks[i] = (WORD)pos; } } penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3; @@ -487,6 +489,7 @@ 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_dbm.cxx --- a/src/modplug/load_dbm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_dbm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -158,7 +158,7 @@ } Headers[iIns+1] = penv; penv->nFadeOut = 1024; // ??? - penv->nGlobalVol = 64; + penv->nGlobalVol = 128; penv->nPan = bswapBE16(pih->panning); if ((penv->nPan) && (penv->nPan < 256)) penv->dwFlags = ENV_SETPANNING; @@ -193,6 +193,7 @@ chunk_pos += sizeof(DBMINSTRUMENT); m_nInstruments = iIns+1; } + m_dwSongFlags |= SONG_INSTRUMENTMODE; } else // Volume Envelopes if (chunk_id == DBM_ID_VENV) @@ -215,15 +216,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->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.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->VolPoints[i] = bswapBE16(peh->volenv[i*2]); - penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); + penv->VolEnv.Ticks[i] = bswapBE16(peh->volenv[i*2]); + penv->VolEnv.Values[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]); } } chunk_pos += sizeof(DBMENVELOPE); @@ -254,6 +255,7 @@ 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_dsm.cxx --- a/src/modplug/load_dsm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_dsm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -136,6 +136,7 @@ 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_far.cxx --- a/src/modplug/load_far.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_far.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -139,6 +139,7 @@ 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]; diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_it.cxx --- a/src/modplug/load_it.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_it.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -2,15 +2,17 @@ * This source code is public domain. * * Authors: Olivier Lapicque , - * Adam Goode (Endian and char fixes for PPC) - * Marco Trillo (Endian fixes for SaveIT, XM->IT Sample Converter) - * + * Adam Goode (endian and char fixes for PPC) */ #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 @@ -22,11 +24,8 @@ { 0, 2, 4, 1, 3, 0, 0, 0 }; ////////////////////////////////////////////////////////// -// Impulse Tracker IT file support +// Impulse Tracker IT file support (import only) -// for conversion of XM samples -extern WORD XMPeriodTable[96+8]; -extern UINT XMLinearTable[768]; static inline UINT ConvertVolParam(UINT value) //-------------------------------------------- @@ -44,7 +43,7 @@ memcpy(penv->name, pis->name, 26); memcpy(penv->filename, pis->filename, 12); penv->nFadeOut = bswapLE16(pis->fadeout) << 6; - penv->nGlobalVol = 64; + penv->nGlobalVol = 128; for (UINT j=0; j<120; j++) { UINT note = pis->keyboard[j*2]; @@ -56,19 +55,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->nVolLoopStart = pis->vls; - penv->nVolLoopEnd = pis->vle; - penv->nVolSustainBegin = pis->sls; - penv->nVolSustainEnd = pis->sle; - penv->nVolEnv = 25; + penv->VolEnv.nLoopStart = pis->vls; + penv->VolEnv.nLoopEnd = pis->vle; + penv->VolEnv.nSustainStart = pis->sls; + penv->VolEnv.nSustainEnd = pis->sle; + penv->VolEnv.nNodes = 25; for (UINT ev=0; ev<25; ev++) { - if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF) + if ((penv->VolEnv.Ticks[ev] = pis->nodes[ev*2]) == 0xFF) { - penv->nVolEnv = ev; + penv->VolEnv.nNodes = ev; break; } - penv->VolEnv[ev] = pis->nodes[ev*2+1]; + penv->VolEnv.Values[ev] = pis->nodes[ev*2+1]; } penv->nNNA = pis->nna; penv->nDCT = pis->dnc; @@ -82,8 +81,8 @@ penv->nMidiChannel = pis->mch; penv->wMidiBank = bswapLE16(pis->mbank); penv->nFadeOut = bswapLE16(pis->fadeout) << 5; - penv->nGlobalVol = pis->gbv >> 1; - if (penv->nGlobalVol > 64) penv->nGlobalVol = 64; + penv->nGlobalVol = pis->gbv; + if (penv->nGlobalVol > 128) penv->nGlobalVol = 128; for (UINT j=0; j<120; j++) { UINT note = pis->keyboard[j*2]; @@ -97,49 +96,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->nVolEnv = pis->volenv.num; - if (penv->nVolEnv > 25) penv->nVolEnv = 25; + penv->VolEnv.nNodes = pis->volenv.num; + if (penv->VolEnv.nNodes > 25) penv->VolEnv.nNodes = 25; - penv->nVolLoopStart = pis->volenv.lpb; - penv->nVolLoopEnd = pis->volenv.lpe; - penv->nVolSustainBegin = pis->volenv.slb; - penv->nVolSustainEnd = pis->volenv.sle; + penv->VolEnv.nLoopStart = pis->volenv.lpb; + penv->VolEnv.nLoopEnd = pis->volenv.lpe; + penv->VolEnv.nSustainStart = pis->volenv.slb; + penv->VolEnv.nSustainEnd = 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->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; + 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; // 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->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; + 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; // Envelopes Data for (UINT ev=0; ev<25; ev++) { - 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->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->nNNA = pis->nna; - penv->nDCT = pis->dct; - penv->nDNA = pis->dca; + penv->nNNA = pis->nna % 4; + penv->nDCT = pis->dct % 4; + penv->nDNA = pis->dca % 3; penv->nPPS = pis->pps; penv->nPPC = pis->ppc; penv->nIFC = pis->ifc; @@ -150,8 +149,8 @@ if (penv->nPan > 256) penv->nPan = 128; if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING; } - if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP; - if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN; + 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; return TRUE; } @@ -167,8 +166,112 @@ BYTE chnmask[64], channels_used[64]; MODCOMMAND lastvalue[64]; + if ((!lpStream) || (dwMemLength < 0xc2)) return FALSE; + pifh.id = bswapLE32(pifh.id); - pifh.reserved1 = bswapLE16(pifh.reserved1); + 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.ordnum = bswapLE16(pifh.ordnum); pifh.insnum = bswapLE16(pifh.insnum); pifh.smpnum = bswapLE16(pifh.smpnum); @@ -181,29 +284,42 @@ 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) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE; + || (pifh.smpnum >= MAX_INSTRUMENTS)) 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; - } + 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 & 0x7F; + m_nSongPreAmp = pifh.mv; + if (m_nSongPreAmp > 128) + m_nSongPreAmp = 128; + m_nStereoSeparation = pifh.sep; // Reading Channels Pan Positions for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF) { @@ -229,6 +345,7 @@ 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)); @@ -263,6 +380,17 @@ 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) { @@ -277,8 +405,13 @@ { 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)) { @@ -295,8 +428,10 @@ dwMemPos += len; } } +#endif // 4-channels minimum m_nChannels = 4; +#if 0 // Read channel names: "CNAM" if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43)) { @@ -319,6 +454,7 @@ { dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos); } +#endif // Checking for unused channels UINT npatterns = pifh.patnum; if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS; @@ -366,8 +502,7 @@ } } // Reading Instruments - m_nInstruments = 0; - if (pifh.flags & 0x04) m_nInstruments = pifh.insnum; + 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; @@ -422,7 +557,7 @@ pins->nVibType = autovibit2xm[pis.vit & 7]; pins->nVibRate = pis.vis; pins->nVibDepth = pis.vid & 0x7F; - pins->nVibSweep = (pis.vir + 3) / 4; + pins->nVibSweep = pis.vir; if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length)) { pins->nLength = pis.length; @@ -453,6 +588,7 @@ if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength)) { PatternSize[npat] = 64; + PatternAllocSize[npat] = 64; Patterns[npat] = AllocatePattern(64, m_nChannels); continue; } @@ -462,6 +598,7 @@ 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)); @@ -551,7 +688,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_VIBRATOSPEED; m[ch].vol = vol - 203; } + if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATO; m[ch].vol = vol - 203; } lastvalue[ch].volcmd = m[ch].volcmd; lastvalue[ch].vol = m[ch].vol; } @@ -590,589 +727,6 @@ } -#ifndef MODPLUG_NO_FILESAVE -//#define SAVEITTIMESTAMP -#pragma warning(disable:4100) - -BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking) -//--------------------------------------------------------- -{ - DWORD dwPatNamLen, dwChnNamLen; - ITFILEHEADER header, writeheader; - ITINSTRUMENT iti, writeiti; - ITSAMPLESTRUCT itss; - BYTE smpcount[MAX_SAMPLES]; - DWORD inspos[MAX_INSTRUMENTS]; - DWORD patpos[MAX_PATTERNS]; - DWORD smppos[MAX_SAMPLES]; - DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2; - WORD patinfo[4]; - BYTE chnmask[64]; - BYTE buf[512]; - MODCOMMAND lastvalue[64]; - FILE *f; - - - if ((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return FALSE; - memset(inspos, 0, sizeof(inspos)); - memset(patpos, 0, sizeof(patpos)); - memset(smppos, 0, sizeof(smppos)); - // Writing Header - memset(&header, 0, sizeof(header)); - dwPatNamLen = 0; - dwChnNamLen = 0; - 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; - header.insnum = m_nInstruments; - header.smpnum = m_nSamples; - header.patnum = MAX_PATTERNS; - while ((header.patnum > 0) && (!Patterns[header.patnum-1])) header.patnum--; - header.cwtv = 0x217; - header.cmwt = 0x200; - header.flags = 0x0001; - header.special = 0x0006; - 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; - dwHdrPos = sizeof(header) + header.ordnum; - // Channel Pan and Volume - memset(header.chnpan, 0xFF, 64); - memset(header.chnvol, 64, 64); - for (UINT ich=0; ich> 2; - if (ChnSettings[ich].dwFlags & CHN_SURROUND) header.chnpan[ich] = 100; - header.chnvol[ich] = ChnSettings[ich].nVolume; - if (ChnSettings[ich].dwFlags & CHN_MUTE) header.chnpan[ich] |= 0x80; - if (ChnSettings[ich].szName[0]) - { - dwChnNamLen = (ich+1) * MAX_CHANNELNAME; - } - } - if (dwChnNamLen) dwExtra += dwChnNamLen + 8; -#ifdef SAVEITTIMESTAMP - dwExtra += 8; // Time Stamp -#endif - if (m_dwSongFlags & SONG_EMBEDMIDICFG) - { - header.flags |= 0x80; - header.special |= 0x08; - dwExtra += sizeof(MODMIDICFG); - } - // Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) - { - dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME; - if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0; - if (dwPatNamLen) dwExtra += dwPatNamLen + 8; - } - // Mix Plugins - dwExtra += SaveMixPlugins(NULL, TRUE); - // Comments - if (m_lpszSongComments) - { - header.special |= 1; - header.msglength = strlen(m_lpszSongComments)+1; - header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4; - } - // Write file header - 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); - if (header.patnum) fwrite(patpos, 4, header.patnum, f); - // Writing editor history information - { -#ifdef SAVEITTIMESTAMP - SYSTEMTIME systime; - FILETIME filetime; - WORD timestamp[4]; - WORD nInfoEx = 1; - memset(timestamp, 0, sizeof(timestamp)); - fwrite(&nInfoEx, 1, 2, f); - GetSystemTime(&systime); - SystemTimeToFileTime(&systime, &filetime); - FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]); - fwrite(timestamp, 1, 8, f); -#else - WORD nInfoEx = 0; - fwrite(&nInfoEx, 1, 2, f); -#endif - } - // Writing midi cfg - if (header.flags & 0x80) - { - fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); - } - // Writing pattern names - if (dwPatNamLen) - { - DWORD d = bswapLE32(0x4d414e50); - UINT len= bswapLE32(dwPatNamLen); - fwrite(&d, 1, 4, f); - write(&len, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwPatNamLen, f); - } - // Writing channel Names - if (dwChnNamLen) - { - DWORD d = bswapLE32(0x4d414e43); - UINT len= bswapLE32(dwChnNamLen); - fwrite(&d, 1, 4, f); - fwrite(&len, 1, 4, f); - UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME; - for (UINT inam=0; inamfilename, 12); - memcpy(iti.name, penv->name, 26); - iti.mbank = penv->wMidiBank; - iti.mpr = penv->nMidiProgram; - iti.mch = penv->nMidiChannel; - iti.nna = penv->nNNA; - iti.dct = penv->nDCT; - iti.dca = penv->nDNA; - iti.fadeout = penv->nFadeOut >> 5; - iti.pps = penv->nPPS; - iti.ppc = penv->nPPC; - iti.gbv = (BYTE)(penv->nGlobalVol << 1); - iti.dfp = (BYTE)penv->nPan >> 2; - if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80; - iti.rv = penv->nVolSwing; - iti.rp = penv->nPanSwing; - iti.ifc = penv->nIFC; - iti.ifr = penv->nIFR; - iti.nos = 0; - for (UINT i=0; i<120; i++) if (penv->Keyboard[i] < MAX_SAMPLES) - { - UINT smp = penv->Keyboard[i]; - if ((smp) && (!smpcount[smp])) - { - smpcount[smp] = 1; - iti.nos++; - } - iti.keyboard[i*2] = penv->NoteMap[i] - 1; - iti.keyboard[i*2+1] = smp; - } - // Writing Volume envelope - if (penv->dwFlags & ENV_VOLUME) iti.volenv.flags |= 0x01; - 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->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->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->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[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 - { - for (UINT i=0; i<120; i++) iti.keyboard[i*2] = i; - iti.ppc = 5*12; - iti.gbv = 128; - iti.dfp = 0x20; - iti.ifc = 0xFF; - } - if (!iti.nos) iti.trkvers = 0; - // Writing instrument - inspos[nins-1] = dwPos; - dwPos += sizeof(ITINSTRUMENT); - - 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)); - for (UINT hsmp=0; hsmpcommand; - UINT param = m->param; - UINT vol = 0xFF; - UINT note = m->note; - if (note) b |= 1; - if ((note) && (note < 0x80)) note--; // 0xfe->0x80 --Toad - if (m->instr) b |= 2; - if (m->volcmd) - { - UINT volcmd = m->volcmd; - switch(volcmd) - { - case VOLCMD_VOLUME: vol = m->vol; if (vol > 64) vol = 64; break; - case VOLCMD_PANNING: vol = m->vol + 128; if (vol > 192) vol = 192; break; - case VOLCMD_VOLSLIDEUP: vol = 85 + ConvertVolParam(m->vol); break; - 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 + 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; - default: vol = 0xFF; - } - } - if (vol != 0xFF) b |= 4; - if (command) - { - S3MSaveConvert(&command, ¶m, TRUE); - if (command) b |= 8; - } - // Packing information - if (b) - { - // Same note ? - if (b & 1) - { - if ((note == lastvalue[ch].note) && (lastvalue[ch].volcmd & 1)) - { - b &= ~1; - b |= 0x10; - } else - { - lastvalue[ch].note = note; - lastvalue[ch].volcmd |= 1; - } - } - // Same instrument ? - if (b & 2) - { - if ((m->instr == lastvalue[ch].instr) && (lastvalue[ch].volcmd & 2)) - { - b &= ~2; - b |= 0x20; - } else - { - lastvalue[ch].instr = m->instr; - lastvalue[ch].volcmd |= 2; - } - } - // Same volume column byte ? - if (b & 4) - { - if ((vol == lastvalue[ch].vol) && (lastvalue[ch].volcmd & 4)) - { - b &= ~4; - b |= 0x40; - } else - { - lastvalue[ch].vol = vol; - lastvalue[ch].volcmd |= 4; - } - } - // Same command / param ? - if (b & 8) - { - if ((command == lastvalue[ch].command) && (param == lastvalue[ch].param) && (lastvalue[ch].volcmd & 8)) - { - b &= ~8; - b |= 0x80; - } else - { - lastvalue[ch].command = command; - lastvalue[ch].param = param; - lastvalue[ch].volcmd |= 8; - } - } - if (b != chnmask[ch]) - { - chnmask[ch] = b; - buf[len++] = (ch+1) | 0x80; - buf[len++] = b; - } else - { - buf[len++] = ch+1; - } - if (b & 1) buf[len++] = note; - if (b & 2) buf[len++] = m->instr; - if (b & 4) buf[len++] = vol; - if (b & 8) - { - buf[len++] = command; - buf[len++] = param; - } - } - } - buf[len++] = 0; - dwPos += len; - patinfo[0] += len; - 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); - } - // Writing Sample Data - for (UINT nsmp=1; nsmp<=header.smpnum; nsmp++) - { - MODINSTRUMENT *psmp = &Ins[nsmp]; - memset(&itss, 0, sizeof(itss)); - memcpy(itss.filename, psmp->name, 12); - memcpy(itss.name, m_szNames[nsmp], 26); - itss.id = 0x53504D49; - itss.gvl = (BYTE)psmp->nGlobalVol; - if (m_nInstruments) - { - for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu]) - { - INSTRUMENTHEADER *penv = Headers[iu]; - for (UINT ju=0; ju<128; ju++) if (penv->Keyboard[ju] == nsmp) - { - itss.flags = 0x01; - break; - } - } - } else - { - itss.flags = 0x01; - } - if (psmp->uFlags & CHN_LOOP) itss.flags |= 0x10; - if (psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20; - if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40; - if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; - itss.C5Speed = psmp->nC4Speed; - 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; - itss.susloopbegin = psmp->nSustainStart; - itss.susloopend = psmp->nSustainEnd; - itss.vol = psmp->nVolume >> 2; - itss.dfp = psmp->nPan >> 2; - itss.vit = autovibxm2it[psmp->nVibType & 7]; - itss.vis = psmp->nVibRate; - itss.vid = psmp->nVibDepth; - 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; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)psmp->pSample, psmp->nLength, nPacking))) - { - flags = RS_ADPCM4; - itss.cvt = 0xFF; - } - } else -#endif // NO_PACKING - { - if (psmp->uFlags & CHN_STEREO) - { - flags = RS_STPCM8S; - itss.flags |= 0x04; - } - if (psmp->uFlags & CHN_16BIT) - { - itss.flags |= 0x02; - flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; - } - } - 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)) - { - dwPos += WriteSample(f, psmp, flags); - } - } - // 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; -} - -//#pragma warning(default:4100) -#endif // MODPLUG_NO_FILESAVE - ////////////////////////////////////////////////////////////////////////////// // IT 2.14 compression @@ -1374,8 +928,7 @@ { DWORD chinfo[64]; CHAR s[32]; - DWORD nPluginSize, writeSwapDWORD; - SNDMIXPLUGININFO writePluginInfo; + DWORD nPluginSize; UINT nTotalSize = 0; UINT nChInfo = 0; @@ -1400,23 +953,9 @@ s[2] = '0' + (i/10); s[3] = '0' + (i%10); fwrite(s, 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); + fwrite(&nPluginSize, 1, 4, f); + fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f); + fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f); if (m_MixPlugins[i].pPluginData) { fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f); @@ -1432,7 +971,6 @@ if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0) { nChInfo = j+1; - chinfo[j] = bswapLE32(chinfo[j]); // inplace BS } } } @@ -1440,11 +978,10 @@ { if (f) { - nPluginSize = bswapLE32(0x58464843); + nPluginSize = 0x58464843; fwrite(&nPluginSize, 1, 4, f); nPluginSize = nChInfo*4; - writeSwapDWORD = bswapLE32(nPluginSize); - fwrite(&writeSwapDWORD, 1, 4, f); + fwrite(&nPluginSize, 1, 4, f); fwrite(chinfo, 1, nPluginSize, f); } nTotalSize += nChInfo*4 + 8; diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_mdl.cxx --- a/src/modplug/load_mdl.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_mdl.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -76,8 +76,31 @@ } 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; } break; - case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } 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 0x30: command = CMD_RETRIG; break; case 0x40: command = CMD_TREMOLO; break; case 0x50: command = CMD_TREMOR; break; @@ -194,7 +217,7 @@ UINT nvolenv, npanenv, npitchenv; if ((!lpStream) || (dwMemLength < 1024)) return FALSE; - if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; + if ((bswapLE32(pmsh->id) != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE; memset(patterntracks, 0, sizeof(patterntracks)); memset(smpinfo, 0, sizeof(smpinfo)); memset(insvolenv, 0, sizeof(insvolenv)); @@ -204,10 +227,13 @@ 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) { @@ -220,10 +246,12 @@ case 0x4E49: pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos); memcpy(m_szNames[0], pmib->songname, 32); - norders = pmib->norders; + norders = bswapLE16(pmib->norders); if (norders > MAX_ORDERS) norders = MAX_ORDERS; - m_nRestartPos = pmib->repeatpos; + m_nRestartPos = bswapLE16(pmib->repeatpos); m_nDefaultGlobalVolume = pmib->globalvol; + if (m_nDefaultGlobalVolume == 255) + m_nDefaultGlobalVolume++; m_nDefaultTempo = pmib->tempo; m_nDefaultSpeed = pmib->speed; m_nChannels = 4; @@ -262,11 +290,12 @@ 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] = pmpd->data[j]; + patterntracks[i*32+j] = bswapLE16(pmpd->data[j]); } } break; @@ -274,6 +303,7 @@ case 0x5254: if (dwTrackPos) break; ntracks = *((WORD *)(lpStream+dwMemPos)); + ntracks = bswapLE16(ntracks); dwTrackPos = dwMemPos+2; break; // II: Instruments @@ -292,7 +322,7 @@ INSTRUMENTHEADER *penv = Headers[nins]; memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, lpStream+dwPos+2, 32); - penv->nGlobalVol = 64; + penv->nGlobalVol = 128; 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) @@ -394,6 +428,7 @@ } else { DWORD dwLen = *((DWORD *)(lpStream+dwPos)); + dwLen = bswapLE32(dwLen); dwPos += 4; if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4)) { @@ -431,23 +466,23 @@ for (UINT nve=0; nvenVolEnv = 15; + penv->VolEnv.nNodes = 15; for (UINT iv=0; iv<15; iv++) { if (iv) vtick += pve[iv*2+1]; - penv->VolPoints[iv] = vtick; - penv->VolEnv[iv] = pve[iv*2+2]; + penv->VolEnv.Ticks[iv] = vtick; + penv->VolEnv.Values[iv] = pve[iv*2+2]; if (!pve[iv*2+1]) { - penv->nVolEnv = iv+1; + penv->VolEnv.nNodes = iv+1; break; } } - penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F; + penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pve[31] & 0x0F; if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN; if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP; - penv->nVolLoopStart = pve[32] & 0x0F; - penv->nVolLoopEnd = pve[32] >> 4; + penv->VolEnv.nLoopStart = pve[32] & 0x0F; + penv->VolEnv.nLoopEnd = pve[32] >> 4; } } // Setup panning envelope @@ -457,22 +492,22 @@ for (UINT npe=0; npenPanEnv = 15; + penv->PanEnv.nNodes = 15; for (UINT iv=0; iv<15; iv++) { if (iv) vtick += ppe[iv*2+1]; - penv->PanPoints[iv] = vtick; - penv->PanEnv[iv] = ppe[iv*2+2]; + penv->PanEnv.Ticks[iv] = vtick; + penv->PanEnv.Values[iv] = ppe[iv*2+2]; if (!ppe[iv*2+1]) { - penv->nPanEnv = iv+1; + penv->PanEnv.nNodes = iv+1; break; } } if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN; if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP; - penv->nPanLoopStart = ppe[32] & 0x0F; - penv->nPanLoopEnd = ppe[32] >> 4; + penv->PanEnv.nLoopStart = ppe[32] & 0x0F; + penv->PanEnv.nLoopEnd = ppe[32] >> 4; } } } diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_med.cxx --- a/src/modplug/load_med.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_med.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -572,6 +572,7 @@ 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); @@ -811,6 +812,7 @@ 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; @@ -847,6 +849,7 @@ 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_mod.cxx --- a/src/modplug/load_mod.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_mod.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -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; } + case CMD_TEMPO: if (param > 0x20) { command = 0x0F; break; } return 0; 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]>='2') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '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]=='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,19 +228,13 @@ } psmp->nLoopStart = loopstart; psmp->nLoopEnd = loopstart + looplen; - if (psmp->nLength < 4) psmp->nLength = 0; + if (psmp->nLength < 2) 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; @@ -306,11 +300,10 @@ for (UINT ich=0; ich= dwMemLength) break; MODCOMMAND *m = Patterns[ipat]; LPCBYTE p = lpStream + dwMemPos; @@ -362,137 +356,3 @@ } -#ifndef MODPLUG_NO_FILESAVE -#pragma warning(disable:4100) - -BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - BYTE insmap[32]; - UINT inslen[32]; - BYTE bTab[32]; - BYTE ord[128]; - FILE *f; - - 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_nInstruments) - { - memset(insmap, 0, sizeof(insmap)); - for (UINT i=1; i<32; i++) if (Headers[i]) - { - for (UINT j=0; j<128; j++) if (Headers[i]->Keyboard[j]) - { - insmap[i] = Headers[i]->Keyboard[j]; - break; - } - } - } else - { - for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i; - } - // Writing song name - fwrite(m_szNames, 20, 1, f); - // Writing instrument definition - for (UINT iins=1; iins<=31; iins++) - { - MODINSTRUMENT *pins = &Ins[insmap[iins]]; - memcpy(bTab, m_szNames[iins],22); - inslen[iins] = pins->nLength; - if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0; - 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 >> 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; - for (UINT iord=0; iord<128; iord++) - { - if (Order[iord] == 0xFF) - { - norders = iord; - break; - } - if ((Order[iord] < 0x80) && (nbp<=Order[iord])) nbp = Order[iord]+1; - } - bTab[0] = norders; - bTab[1] = m_nRestartPos; - fwrite(bTab, 2, 1, f); - // Writing pattern list - if (norders) memcpy(ord, Order, norders); - fwrite(ord, 128, 1, f); - // Writing signature - if (m_nChannels == 4) - lstrcpy((LPSTR)&bTab, "M.K."); - else - wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels); - fwrite(bTab, 4, 1, f); - // Writing patterns - for (UINT ipat=0; ipat> 8; - param &= 0xFF; - if (command > 0x0F) command = param = 0; - if ((m->vol >= 0x10) && (m->vol <= 0x50) && (!command) && (!param)) { command = 0x0C; param = m->vol - 0x10; } - UINT period = m->note; - if (period) - { - if (period < 37) period = 37; - period -= 37; - if (period >= 6*12) period = 6*12-1; - period = ProTrackerPeriodTable[period]; - } - UINT instr = (m->instr > 31) ? 0 : m->instr; - p[0] = ((period >> 8) & 0x0F) | (instr & 0x10); - p[1] = period & 0xFF; - p[2] = ((instr & 0x0F) << 4) | (command & 0x0F); - p[3] = param; - } - fwrite(s, m_nChannels, 4, f); - } else - { - memset(s, 0, m_nChannels*4); - fwrite(s, m_nChannels, 4, f); - } - } - // Writing instruments - for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd]) - { - MODINSTRUMENT *pins = &Ins[insmap[ismpd]]; - UINT flags = RS_PCM8S; -#ifndef NO_PACKING - if (!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - { - if ((nPacking) && (CanPackSample((char *)pins->pSample, inslen[ismpd], nPacking))) - { - fwrite("ADPCM", 1, 5, f); - flags = RS_ADPCM4; - } - } -#endif - WriteSample(f, pins, flags, inslen[ismpd]); - } - fclose(f); - return TRUE; -} - -#pragma warning(default:4100) -#endif // MODPLUG_NO_FILESAVE diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_mt2.cxx --- a/src/modplug/load_mt2.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_mt2.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -282,6 +282,7 @@ 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]; @@ -395,6 +396,7 @@ #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; @@ -408,7 +410,7 @@ { memset(penv, 0, sizeof(INSTRUMENTHEADER)); memcpy(penv->name, pmi->szName, 32); - penv->nGlobalVol = 64; + penv->nGlobalVol = 128; penv->nPan = 128; for (UINT i=0; i<120; i++) { @@ -460,7 +462,7 @@ for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv]) { MT2ENVELOPE *pme = pehdr[iEnv]; - WORD *pEnvPoints = NULL; + int *pEnvPoints = NULL; BYTE *pEnvData = NULL; #ifdef MT2DEBUG Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints); @@ -472,12 +474,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->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; + 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; break; // Panning Envelope @@ -485,12 +487,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->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; + 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; break; // Pitch/Filter envelope @@ -498,12 +500,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->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; + 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; } // Envelope data if ((pEnvPoints) && (pEnvData) && (pedata[iEnv])) @@ -592,7 +594,7 @@ Ins[nSmp].nVibType = pmi->bVibType; Ins[nSmp].nVibSweep = pmi->bVibSweep; Ins[nSmp].nVibDepth = pmi->bVibDepth; - Ins[nSmp].nVibRate = pmi->bVibRate; + Ins[nSmp].nVibRate = pmi->bVibRate/4; } } } diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_mtm.cxx --- a/src/modplug/load_mtm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_mtm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -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*pmh->numtracks - + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) return FALSE; + if (dwMemPos + 37*pmh->numsamples + 128 + 192*bswapLE16(pmh->numtracks) + + 64 * (pmh->lastpattern+1) + bswapLE16(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 = pms->length; + DWORD len = bswapLE32(pms->length); if ((len > 4) && (len <= MAX_SAMPLE_LENGTH)) { Ins[i].nLength = len; - Ins[i].nLoopStart = pms->reppos; - Ins[i].nLoopEnd = pms->repend; + Ins[i].nLoopStart = bswapLE32(pms->reppos); + Ins[i].nLoopEnd = bswapLE32(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,13 +104,14 @@ dwMemPos += 128; // Reading Patterns LPCBYTE pTracks = lpStream + dwMemPos; - dwMemPos += 192 * pmh->numtracks; + dwMemPos += 192 * bswapLE16(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] <= pmh->numtracks) && (n < m_nChannels)) + for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= bswapLE16(pmh->numtracks)) && (n < m_nChannels)) { LPCBYTE p = pTracks + 192 * (pSeq[n]-1); MODCOMMAND *m = Patterns[pat] + n; @@ -132,9 +133,9 @@ pSeq += 32; } dwMemPos += 64*(pmh->lastpattern+1); - if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) + if (bswapLE16(pmh->commentsize) && (dwMemPos + bswapLE16(pmh->commentsize) < dwMemLength)) { - UINT n = pmh->commentsize; + UINT n = bswapLE16(pmh->commentsize); m_lpszSongComments = new char[n+1]; if (m_lpszSongComments) { @@ -149,7 +150,7 @@ } } } - dwMemPos += pmh->commentsize; + dwMemPos += bswapLE16(pmh->commentsize); // Reading Samples for (UINT ismp=1; ismp<=m_nSamples; ismp++) { diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_okt.cxx --- a/src/modplug/load_okt.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_okt.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -120,6 +120,7 @@ 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 (pfh_swap.id == PSM_ID_OLD) + if (bswapLE32(pfh->id) == PSM_ID_OLD) { #ifdef PSM_LOG - Log("Old PSM format not supported\n"); + printf("Old PSM format not supported\n"); #endif return FALSE; } - if ((pfh_swap.id != PSM_ID_NEW) || (pfh_swap.len+12 > dwMemLength) || (pfh_swap.listid != IFFID_FILE)) return FALSE; + if ((bswapLE32(pfh->id) != PSM_ID_NEW) + || (bswapLE32(pfh->len)+12 > dwMemLength) + || (bswapLE32(pfh->listid) != IFFID_FILE)) return FALSE; m_nType = MOD_TYPE_PSM; m_nChannels = 16; m_nSamples = 0; @@ -111,19 +108,16 @@ 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); - - 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; + if ((bswapLE32(pchunk->len) >= dwMemLength - 8) + || (dwMemPos + bswapLE32(pchunk->len) + 8 > dwMemLength)) break; dwMemPos += 8; PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - if (len) switch(pchunk->id) + ULONG len = bswapLE32(pchunk->len); + if (len) switch(bswapLE32(pchunk->id)) { // "TITL": Song title case IFFID_TITL: @@ -152,23 +146,16 @@ m_nSamples++; MODINSTRUMENT *pins = &Ins[m_nSamples]; PSMSAMPLE *psmp = (PSMSAMPLE *)pdata; - - 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; + smpnames[m_nSamples] = bswapLE32(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 = psmp->samplerate; - pins->nLength = psmp->length; - pins->nLoopStart = psmp->loopstart; - pins->nLoopEnd = psmp->loopend; + pins->nC4Speed = bswapLE32(psmp->samplerate); + pins->nLength = bswapLE32(psmp->length); + pins->nLoopStart = bswapLE32(psmp->loopstart); + pins->nLoopEnd = bswapLE32(psmp->loopend); pins->nPan = 128; pins->nVolume = (psmp->defvol+1) * 2; pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0; @@ -197,7 +184,7 @@ } #endif } - dwMemPos += pchunk->len; + dwMemPos += bswapLE32(pchunk->len); } // Step #1: convert song structure PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8); @@ -210,16 +197,12 @@ 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 ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break; + if ((bswapLE32(pchunk->len) > dwSongEnd) + || (dwMemPos + bswapLE32(pchunk->len) > dwSongEnd)) break; PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos); - ULONG len = pchunk->len; - switch(pchunk->id) + ULONG len = bswapLE32(pchunk->len); + switch(bswapLE32(pchunk->id)) { case IFFID_OPLH: if (len >= 0x20) @@ -265,7 +248,7 @@ } break; } - dwMemPos += pchunk->len; + dwMemPos += bswapLE32(pchunk->len); } } @@ -273,85 +256,66 @@ for (UINT nPat=0; nPatsize = 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; + ULONG len = bswapLE32(*(DWORD *)(lpStream+patptrs[nPat]+4)) - 12; + UINT nRows = bswapLE16(pPsmPat->rows); + if (len > bswapLE32(pPsmPat->size)) len = bswapLE32(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 oldch = 0; - BOOL bNewRow = FALSE; + UINT rowlim; #ifdef PSM_LOG - Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream)); + //printf("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 = 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= rowlim) { + pos = rowlim; + rowlim = (((int)p[pos+1])<<8) + | ((int)p[pos+0]); + m += m_nChannels; + row++; + rowlim += pos; + pos += 2; } - if ((pos >= len) || (row >= nRows)) break; - if (!(flags & 0xf0)) - { + flags = p[pos++]; + ch = p[pos++]; + if (ch >= m_nChannels) { #ifdef PSM_LOG - //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]); + printf("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch); #endif - 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; + sp = &dummy; + } else { + sp = &m[ch]; } // Note + Instr + if ((flags & 0x80) && (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 note = p[pos++]; UINT nins = p[pos++]; #ifdef PSM_LOG - //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins); - if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins); + if ((!nPat) && (nins >= m_nSamples)) printf("WARNING: invalid instrument number (%d)\n", nins); #endif - if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1; - m[ch].instr = samplemap[nins]; - m[ch].note = note; + sp->instr = samplemap[nins]; } // Volume if ((flags & 0x20) && (pos < len)) { - m[ch].volcmd = VOLCMD_VOLUME; - m[ch].vol = p[pos++] / 2; + sp->volcmd = VOLCMD_VOLUME; + sp->vol = p[pos++] / 2; } // Effect if ((flags & 0x10) && (pos+1 < len)) @@ -359,40 +323,94 @@ UINT command = p[pos++]; UINT param = p[pos++]; // Convert effects - switch(command) + switch(command & 0x3F) { // 01: fine volslide up - case 0x01: command = CMD_VOLUMESLIDE; param |= 0x0f; break; - // 04: fine volslide down - case 0x04: command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break; + 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; // 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; break; + case 0x3D: command = CMD_SPEED; + if (!row && !nPat) + m_nDefaultSpeed = param; + break; // 3E: tempo - case 0x3E: command = CMD_TEMPO; break; + case 0x3E: command = CMD_TEMPO; + if (!row && !nPat) + m_nDefaultTempo = param; + break; // Unknown default: #ifdef PSM_LOG - Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); + printf("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param); #endif command = param = 0; } - m[ch].command = (BYTE)command; - m[ch].param = (BYTE)param; + sp->command = (BYTE)command; + sp->param = (BYTE)param; } - oldch = ch; } #ifdef PSM_LOG if (pos < len) { - Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); +// printf("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos); } #endif } diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_ptm.cxx --- a/src/modplug/load_ptm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_ptm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -115,10 +115,10 @@ { UINT smpflg = RS_PCM8D; DWORD samplepos; - pins->nLength = bswapLE32(*(LPDWORD)(void*)(psmp->length)); - pins->nLoopStart = bswapLE32(*(LPDWORD)(void*)(psmp->loopbeg)); - pins->nLoopEnd = bswapLE32(*(LPDWORD)(void*)(psmp->loopend)); - samplepos = bswapLE32(*(LPDWORD)(void*)(&psmp->fileofs)); + pins->nLength = bswapLE32(*psmp->length); + pins->nLoopStart = bswapLE32(*psmp->loopbeg); + pins->nLoopEnd = bswapLE32(*psmp->loopend); + samplepos = bswapLE32(*psmp->fileofs); if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP; if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP; if (psmp->sampletype & 16) @@ -141,6 +141,7 @@ 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_s3m.cxx --- a/src/modplug/load_s3m.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_s3m.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -289,14 +289,14 @@ { UINT j = bswapLE32(*((LPDWORD)(s+0x10))); if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH; - if (j < 4) j = 0; + if (j < 2) 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 < 4) j = 0; + if (j < 2) j = 0; if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength; Ins[iSmp].nLoopEnd = j; j = s[0x1C]; @@ -319,11 +319,15 @@ // Reading patterns for (UINT iPat=0; iPat dwMemLength) continue; + UINT nInd = ((DWORD)ptr[nins+iPat]) << 4; + // if the parapointer is zero, the pattern is blank (so ignore it) + if (nInd == 0) + continue; + 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); @@ -383,8 +387,11 @@ // Reading samples for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw])) { - UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; - if (insflags[iRaw-1] & 4) flags += 5; + UINT flags; + if (insflags[iRaw-1] & 4) + flags = (psfh.version == 1) ? RS_PCM16S : RS_PCM16U; + else + flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U; if (insflags[iRaw-1] & 2) flags |= RSF_STEREO; if (inspack[iRaw-1] == 4) flags = RS_ADPCM4; dwMemPos = insfile[iRaw]; @@ -397,254 +404,3 @@ } -#ifndef MODPLUG_NO_FILESAVE -#pragma warning(disable:4100) - -static BYTE S3MFiller[16] = -{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - - -BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking) -//---------------------------------------------------------- -{ - FILE *f; - BYTE header[0x60]; - UINT nbo,nbi,nbp,i; - WORD patptr[128]; - WORD insptr[128]; - BYTE buffer[5*1024]; - S3MSAMPLESTRUCT insex[128]; - - 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)); - memcpy(header, m_szNames[0], 0x1C); - header[0x1B] = 0; - header[0x1C] = 0x1A; - header[0x1D] = 0x10; - nbo = (GetNumPatterns() + 15) & 0xF0; - if (!nbo) nbo = 16; - header[0x20] = nbo & 0xFF; - header[0x21] = nbo >> 8; - nbi = m_nInstruments; - if (!nbi) nbi = m_nSamples; - if (nbi > 99) nbi = 99; - header[0x22] = nbi & 0xFF; - header[0x23] = nbi >> 8; - nbp = 0; - for (i=0; Patterns[i]; i++) { nbp = i+1; if (nbp >= MAX_PATTERNS) break; } - for (i=0; i= nbp)) nbp = Order[i] + 1; - header[0x24] = nbp & 0xFF; - header[0x25] = nbp >> 8; - if (m_dwSongFlags & SONG_FASTVOLSLIDES) header[0x26] |= 0x40; - if ((m_nMaxPeriod < 20000) || (m_dwSongFlags & SONG_AMIGALIMITS)) header[0x26] |= 0x10; - header[0x28] = 0x20; - header[0x29] = 0x13; - header[0x2A] = 0x02; // Version = 1 => Signed samples - header[0x2B] = 0x00; - header[0x2C] = 'S'; - header[0x2D] = 'C'; - header[0x2E] = 'R'; - header[0x2F] = 'M'; - header[0x30] = m_nDefaultGlobalVolume >> 2; - header[0x31] = m_nDefaultSpeed; - header[0x32] = m_nDefaultTempo; - header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80; // Stereo - header[0x35] = 0xFC; - for (i=0; i<32; i++) - { - if (i < m_nChannels) - { - UINT tmp = (i & 0x0F) >> 1; - header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp); - } else header[0x40+i] = 0xFF; - } - 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) + 0x20; - UINT ofs = ofs1; - - for (i=0; i> 4); - } - fwrite(chnpan, 0x20, 1, f); - } - if ((nbi*2+nbp*2) & 0x0F) - { - fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f); - } - ofs1 = ftell(f); - fwrite(insex, nbi, 0x50, f); - // Packing patterns - ofs += nbi*0x50; - for (i=0; inote; - UINT volcmd = m->volcmd; - UINT vol = m->vol; - UINT command = m->command; - UINT param = m->param; - - 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; - if (note < 0xFE) note = (note % 12) + ((note / 12) << 4); - if (command == CMD_VOLUME) - { - command = 0; - if (param > 64) param = 64; - volcmd = VOLCMD_VOLUME; - vol = param; - } - if (volcmd == VOLCMD_VOLUME) b |= 0x40; else - if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; } - if (command) - { - S3MSaveConvert(&command, ¶m, FALSE); - if (command) b |= 0x80; - } - if (b & 0xE0) - { - buffer[len++] = b; - if (b & 0x20) - { - buffer[len++] = note; - buffer[len++] = m->instr; - } - if (b & 0x40) - { - buffer[len++] = vol; - } - if (b & 0x80) - { - buffer[len++] = command; - buffer[len++] = param; - } - if (len > sizeof(buffer) - 20) break; - } - } - buffer[len++] = 0; - if (len > sizeof(buffer) - 20) break; - } - } - buffer[0] = (len - 2) & 0xFF; - buffer[1] = (len - 2) >> 8; - len = (len+15) & (~0x0F); - 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 = (WORD)((DWORD)ofs >> 4); - if (pins->pSample) - { - insex[i-1].type = 1; - 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 = pins->nC4Speed; - else - insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune); - UINT flags = RS_PCM8U; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - insex[i-1].pack = 4; - flags = RS_ADPCM4; - } - } else -#endif // NO_PACKING - { - if (pins->uFlags & CHN_16BIT) - { - insex[i-1].flags |= 4; - flags = RS_PCM16U; - } - if (pins->uFlags & CHN_STEREO) - { - insex[i-1].flags |= 2; - flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U; - } - } - DWORD len = WriteSample(f, pins, flags); - if (len & 0x0F) - { - fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f); - } - ofs += (len + 15) & (~0x0F); - } else - { - insex[i-1].length = 0; - } - } - // Updating parapointers - 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; -} - -#pragma warning(default:4100) -#endif // MODPLUG_NO_FILESAVE - diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_stm.cxx --- a/src/modplug/load_stm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_stm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -111,6 +111,7 @@ { 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_ult.cxx --- a/src/modplug/load_ult.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_ult.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -135,6 +135,7 @@ if (nAllocPat < MAX_PATTERNS) { PatternSize[nAllocPat] = 64; + PatternAllocSize[nAllocPat] = 64; Patterns[nAllocPat] = AllocatePattern(64, m_nChannels); } } diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_wav.cxx --- a/src/modplug/load_wav.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_wav.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -18,26 +18,53 @@ //--------------------------------------------------------------- { DWORD dwMemPos = 0; - 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; + 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; + 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 (;;) { - pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos); - if (pdata->id_data == IFFID_data) break; - dwMemPos += pdata->length + 8; + 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; if (dwMemPos + 8 >= dwMemLength) return FALSE; } m_nType = MOD_TYPE_WAV; @@ -50,18 +77,19 @@ 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; @@ -87,7 +115,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) { @@ -113,14 +141,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 = *((short int *)psrc); - nIndex = psrc[2]; + value = bswapLE16(*((short int *)psrc)); + nIndex = bswapLE16((short int)psrc[2]); psrc += 4; dwBytes -= 4; pdest[nPos++] = (short int)value; @@ -200,7 +228,7 @@ { delta = (BYTE)((*psrc) & 0x0F); } - int v = gIMAUnpackTable[nIndex] >> 3; + int v = gIMAUnpackTable[nIndex % 90] >> 3; if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2; if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1; if (delta & 4) v += gIMAUnpackTable[nIndex]; diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/load_xm.cxx --- a/src/modplug/load_xm.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/load_xm.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -93,10 +93,10 @@ memcpy(m_szNames[0], lpStream+17, 20); dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60))); norders = bswapLE16(*((WORD *)(lpStream+64))); - if ((!norders) || (norders > MAX_ORDERS)) return FALSE; + if (norders > MAX_ORDERS) return FALSE; restartpos = bswapLE16(*((WORD *)(lpStream+66))); channels = bswapLE16(*((WORD *)(lpStream+68))); - if ((!channels) || (channels > 64)) return FALSE; + if (channels > 64) return FALSE; m_nType = MOD_TYPE_XM; m_nMinPeriod = 27; m_nMaxPeriod = 54784; @@ -107,6 +107,7 @@ 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); @@ -173,6 +174,7 @@ 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]; @@ -386,42 +388,42 @@ if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP; if (xmsh.vnum > 12) xmsh.vnum = 12; if (xmsh.pnum > 12) xmsh.pnum = 12; - penv->nVolEnv = xmsh.vnum; + penv->VolEnv.nNodes = xmsh.vnum; if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME; if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING; - penv->nPanEnv = xmsh.pnum; - penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain; + penv->PanEnv.nNodes = xmsh.pnum; + penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = xmsh.vsustain; if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN; - 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; + 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; if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN; - 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; + 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; for (UINT ienv=0; ienv<12; ienv++) { - 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]; + 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]; if (ienv) { - if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) + if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1]) { - penv->VolPoints[ienv] &= 0xFF; - penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00; - if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100; + 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; } - if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) + if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1]) { - penv->PanPoints[ienv] &= 0xFF; - penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00; - if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100; + 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; } } } @@ -491,7 +493,7 @@ pins->nVibType = xmsh.vibtype; pins->nVibSweep = xmsh.vibsweep; pins->nVibDepth = xmsh.vibdepth; - pins->nVibRate = xmsh.vibrate; + pins->nVibRate = xmsh.vibrate/4; memcpy(pins->name, xmss.name, 22); pins->name[21] = 0; } @@ -511,382 +513,14 @@ if (dwMemPos >= dwMemLength) break; } } - // Read song comments: "TEXT" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len < 16384)) - { - m_lpszSongComments = new char[len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, len); - m_lpszSongComments[len] = 0; - } - dwMemPos += len; - } - } - // Read midi config: "MIDI" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D)) - { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); - dwMemPos += 8; - if (len == sizeof(MODMIDICFG)) - { - memcpy(&m_MidiCfg, lpStream+dwMemPos, len); - m_dwSongFlags |= SONG_EMBEDMIDICFG; - } - } - // Read pattern names: "PNAM" - if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) + /* 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; i= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1; - } - 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 = 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); - for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++) - { - UINT note = p->note; - UINT param = ModSaveCommand(p, TRUE); - UINT command = param >> 8; - param &= 0xFF; - if (note >= 0xFE) note = 97; else - if ((note <= 12) || (note > 96+12)) note = 0; else - note -= 12; - UINT vol = 0; - if (p->volcmd) - { - UINT volcmd = p->volcmd; - switch(volcmd) - { - case VOLCMD_VOLUME: vol = 0x10 + p->vol; break; - case VOLCMD_VOLSLIDEDOWN: vol = 0x60 + (p->vol & 0x0F); break; - case VOLCMD_VOLSLIDEUP: vol = 0x70 + (p->vol & 0x0F); break; - case VOLCMD_FINEVOLDOWN: vol = 0x80 + (p->vol & 0x0F); break; - case VOLCMD_FINEVOLUP: vol = 0x90 + (p->vol & 0x0F); break; - case VOLCMD_VIBRATOSPEED: vol = 0xA0 + (p->vol & 0x0F); break; - case VOLCMD_VIBRATO: vol = 0xB0 + (p->vol & 0x0F); break; - case VOLCMD_PANNING: vol = 0xC0 + (p->vol >> 2); if (vol > 0xCF) vol = 0xCF; break; - case VOLCMD_PANSLIDELEFT: vol = 0xD0 + (p->vol & 0x0F); break; - case VOLCMD_PANSLIDERIGHT: vol = 0xE0 + (p->vol & 0x0F); break; - case VOLCMD_TONEPORTAMENTO: vol = 0xF0 + (p->vol & 0x0F); break; - } - } - if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param)) - { - s[len++] = note; - s[len++] = p->instr; - s[len++] = vol; - s[len++] = command; - s[len++] = param; - } else - { - BYTE b = 0x80; - if (note) b |= 0x01; - if (p->instr) b |= 0x02; - if (vol >= 0x10) b |= 0x04; - if (command) b |= 0x08; - if (param) b |= 0x10; - s[len++] = b; - if (b & 1) s[len++] = note; - if (b & 2) s[len++] = p->instr; - if (b & 4) s[len++] = vol; - if (b & 8) s[len++] = command; - if (b & 16) s[len++] = param; - } - if (len > sizeof(s) - 5) break; - } - xmph[7] = (BYTE)(len & 0xFF); - xmph[8] = (BYTE)(len >> 8); - 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); - fwrite(xmph, 1, 9, f); - } - // Writing instruments - for (i=1; i<=header.instruments; i++) - { - MODINSTRUMENT *pins; - BYTE flags[32]; - - memset(&xmih, 0, sizeof(xmih)); - memset(&xmsh, 0, sizeof(xmsh)); - xmih.size = sizeof(xmih) + sizeof(xmsh); - memcpy(xmih.name, m_szNames[i], 22); - xmih.type = 0; - xmih.samples = 0; - if (m_nInstruments) - { - INSTRUMENTHEADER *penv = Headers[i]; - if (penv) - { - memcpy(xmih.name, penv->name, 22); - xmih.type = penv->nMidiProgram; - xmsh.volfade = penv->nFadeOut; - 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] = 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; - if (penv->dwFlags & ENV_VOLLOOP) xmsh.vtype |= 4; - 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->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; - for (k=0; kKeyboard[j+12]) break; - if (k == xmih.samples) - { - smptable[xmih.samples++] = penv->Keyboard[j+12]; - } - if (xmih.samples >= 32) break; - xmsh.snum[j] = k; - } -// xmsh.reserved2 = xmih.samples; - } - } else - { - xmih.samples = 1; -// xmsh.reserved2 = 1; - smptable[0] = i; - } - xmsh.shsize = (xmih.samples) ? 40 : 0; - fwrite(&xmih, 1, sizeof(xmih), f); - if (smptable[0]) - { - MODINSTRUMENT *pvib = &Ins[smptable[0]]; - xmsh.vibtype = pvib->nVibType; - xmsh.vibsweep = pvib->nVibSweep; - xmsh.vibdepth = pvib->nVibDepth; - xmsh.vibrate = pvib->nVibRate; - } - 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; - flags[ins] = RS_PCM8D; -#ifndef NO_PACKING - if (nPacking) - { - if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO))) - && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking))) - { - flags[ins] = RS_ADPCM4; - xmss.res = 0xAD; - } - } else -#endif - { - if (pins->uFlags & CHN_16BIT) - { - flags[ins] = RS_PCM16D; - xmss.type |= 0x10; - xmss.looplen *= 2; - xmss.loopstart *= 2; - xmss.samplen *= 2; - } - if (pins->uFlags & CHN_STEREO) - { - flags[ins] = (pins->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D; - xmss.type |= 0x20; - xmss.looplen *= 2; - xmss.loopstart *= 2; - xmss.samplen *= 2; - } - } - xmss.pan = 255; - if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan; - xmss.relnote = (signed char)pins->RelativeTone; - 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); -#endif // NO_PACKING - 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 + * copyright (c) 2005-2006 Mrs. Brisby + * URL: http://nimh.org/schism/ + * URL: http://rigelseven.com/schism/ + * + * This program is free software; you can redistribute it and/or 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MIDI_H +#define MIDI_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct midi_provider; +struct midi_port; + +struct midi_driver { + unsigned int flags; +#define MIDI_PORT_CAN_SCHEDULE 1 + + void (*poll)(struct midi_provider *m); + int (*thread)(struct midi_provider *m); + + int (*enable)(struct midi_port *d); + int (*disable)(struct midi_port *d); + + void (*send)(struct midi_port *d, + unsigned char *seq, unsigned int len, unsigned int delay); + void (*drain)(struct midi_port *d); +}; + +struct midi_provider { + const char *name; + void (*poll)(struct midi_provider *); + void *thread; /*actually SDL_Thread* */ + + struct midi_provider *next; + + /* forwarded; don't touch */ + int (*enable)(struct midi_port *d); + int (*disable)(struct midi_port *d); + + void (*send_now)(struct midi_port *d, + unsigned char *seq, unsigned int len, unsigned int delay); + void (*send_later)(struct midi_port *d, + unsigned char *seq, unsigned int len, unsigned int delay); + void (*drain)(struct midi_port *d); +}; +struct midi_port { + int io, iocap; +#define MIDI_INPUT 1 +#define MIDI_OUTPUT 2 + char *name; + int num; + + void *userdata; + int free_userdata; + int (*enable)(struct midi_port *d); + int (*disable)(struct midi_port *d); + void (*send_now)(struct midi_port *d, + unsigned char *seq, unsigned int len, unsigned int delay); + void (*send_later)(struct midi_port *d, + unsigned char *seq, unsigned int len, unsigned int delay); + void (*drain)(struct midi_port *d); + + struct midi_provider *provider; +}; + + +/* schism calls these directly */ +int midi_engine_start(void); +void midi_engine_reset(void); +void midi_engine_stop(void); +void midi_engine_poll_ports(void); + +/* some parts of schism call this; it means "immediately" */ +void midi_send_now(unsigned char *seq, unsigned int len); + +/* ... but the player calls this */ +void midi_send_buffer(unsigned char *data, unsigned int len, unsigned int pos); +void midi_send_flush(void); + +/* from the SDL event mechanism (x is really SDL_Event) */ +int midi_engine_handle_event(void *x); + +struct midi_port *midi_engine_port(int n, const char **name); +int midi_engine_port_count(void); + +/* midi engines register a provider (one each!) */ +struct midi_provider *midi_provider_register(const char *name, struct midi_driver *f); + + +/* midi engines list ports this way */ +int midi_port_register(struct midi_provider *p, +int inout, const char *name, void *userdata, int free_userdata); + +int midi_port_foreach(struct midi_provider *p, struct midi_port **cursor); +void midi_port_unregister(int num); + +/* only call these if the event isn't really MIDI but you want most of the system + to act like it is... + + midi drivers should never all these... +*/ +enum midi_note { + MIDI_NOTEOFF, + MIDI_NOTEON, + MIDI_KEYPRESS, +}; +void midi_event_note(enum midi_note mnstatus, int channel, int note, int velocity); +void midi_event_controller(int channel, int param, int value); +void midi_event_program(int channel, int value); +void midi_event_aftertouch(int channel, int value); +void midi_event_pitchbend(int channel, int value); +void midi_event_tick(void); +void midi_event_sysex(const unsigned char *data, unsigned int len); +void midi_event_system(int argv, int param); + +/* midi drivers call this when they received an event */ +void midi_received_cb(struct midi_port *src, unsigned char *data, unsigned int len); + + +#ifdef USE_NETWORK +int ip_midi_setup(void); +#endif +#ifdef USE_OSS +int oss_midi_setup(void); +#endif +#ifdef USE_ALSA +int alsa_midi_setup(void); +#endif +#ifdef USE_WIN32MM +int win32mm_midi_setup(void); +#endif +#ifdef MACOSX +int macosx_midi_setup(void); +#endif + + + +#define MIDI_TICK_QUANTIZE 0x00000001 +#define MIDI_BASE_PROGRAM1 0x00000002 +#define MIDI_RECORD_NOTEOFF 0x00000004 +#define MIDI_RECORD_VELOCITY 0x00000008 +#define MIDI_RECORD_AFTERTOUCH 0x00000010 +#define MIDI_CUT_NOTE_OFF 0x00000020 +#define MIDI_PITCH_BEND 0x00000040 +#define MIDI_EMBED_DATA 0x00000080 +#define MIDI_RECORD_SDX 0x00000100 +#define MIDI_DISABLE_RECORD 0x00010000 + +/* configurable midi stuff */ +int midi_flags = MIDI_TICK_QUANTIZE | MIDI_RECORD_NOTEOFF + | MIDI_RECORD_VELOCITY | MIDI_RECORD_AFTERTOUCH + | MIDI_PITCH_BEND; + +int midi_pitch_depth = 12; +int midi_amplification = 100; +int midi_c5note = 60; + +/* only available with networks */ +void ip_midi_setports(int n); +int ip_midi_getports(void); + +#ifdef __cplusplus +}; +#endif + +#endif diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/modplug.cxx --- a/src/modplug/modplug.cxx Wed Jan 23 19:37:05 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,271 +0,0 @@ -/* - * This source code is public domain. - * - * Authors: Kenton Varda (C interface wrapper) - */ - -#include "modplug.h" -#include "stdafx.h" -#include "sndfile.h" - -struct _ModPlugFile -{ - CSoundFile mSoundFile; -}; - -namespace ModPlug -{ - ModPlug_Settings gSettings = - { - MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION, - - 2, - 16, - 44100, - MODPLUG_RESAMPLE_LINEAR, - - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }; - - int gSampleSize; - - void UpdateSettings(bool updateBasicConfig) - { - if(gSettings.mFlags & MODPLUG_ENABLE_REVERB) - { - CSoundFile::SetReverbParameters(gSettings.mReverbDepth, - gSettings.mReverbDelay); - } - - if(gSettings.mFlags & MODPLUG_ENABLE_MEGABASS) - { - CSoundFile::SetXBassParameters(gSettings.mBassAmount, - gSettings.mBassRange); - } - else // modplug seems to ignore the SetWaveConfigEx() setting for bass boost - CSoundFile::SetXBassParameters(0, 0); - - if(gSettings.mFlags & MODPLUG_ENABLE_SURROUND) - { - CSoundFile::SetSurroundParameters(gSettings.mSurroundDepth, - gSettings.mSurroundDelay); - } - - if(updateBasicConfig) - { - CSoundFile::SetWaveConfig(gSettings.mFrequency, - gSettings.mBits, - gSettings.mChannels); - - gSampleSize = gSettings.mBits / 8 * gSettings.mChannels; - } - - CSoundFile::SetWaveConfigEx(gSettings.mFlags & MODPLUG_ENABLE_SURROUND, - !(gSettings.mFlags & MODPLUG_ENABLE_OVERSAMPLING), - gSettings.mFlags & MODPLUG_ENABLE_REVERB, - true, - gSettings.mFlags & MODPLUG_ENABLE_MEGABASS, - gSettings.mFlags & MODPLUG_ENABLE_NOISE_REDUCTION, - false); - CSoundFile::SetResamplingMode(gSettings.mResamplingMode); - } -} - -ModPlugFile* ModPlug_Load(const void* data, int size) -{ - ModPlugFile* result = new ModPlugFile; - ModPlug::UpdateSettings(true); - if(result->mSoundFile.Create((const BYTE*)data, size)) - { - result->mSoundFile.SetRepeatCount(ModPlug::gSettings.mLoopCount); - return result; - } - else - { - delete result; - return NULL; - } -} - -void ModPlug_Unload(ModPlugFile* file) -{ - file->mSoundFile.Destroy(); - delete file; -} - -int ModPlug_Read(ModPlugFile* file, void* buffer, int size) -{ - return file->mSoundFile.Read(buffer, size) * ModPlug::gSampleSize; -} - -const char* ModPlug_GetName(ModPlugFile* file) -{ - return file->mSoundFile.GetTitle(); -} - -int ModPlug_GetLength(ModPlugFile* file) -{ - return file->mSoundFile.GetSongTime() * 1000; -} - -void ModPlug_InitMixerCallback(ModPlugFile* file,ModPlugMixerProc proc) -{ - file->mSoundFile.gpSndMixHook = (LPSNDMIXHOOKPROC)proc ; - return; -} - -void ModPlug_UnloadMixerCallback(ModPlugFile* file) -{ - file->mSoundFile.gpSndMixHook = NULL; - return ; -} - -unsigned int ModPlug_GetMasterVolume(ModPlugFile* file) -{ - return (unsigned int)file->mSoundFile.m_nMasterVolume; -} - -void ModPlug_SetMasterVolume(ModPlugFile* file,unsigned int cvol) -{ - (void)file->mSoundFile.SetMasterVolume( (UINT)cvol, - FALSE ); - return ; -} - -int ModPlug_GetCurrentSpeed(ModPlugFile* file) -{ - return file->mSoundFile.m_nMusicSpeed; -} - -int ModPlug_GetCurrentTempo(ModPlugFile* file) -{ - return file->mSoundFile.m_nMusicTempo; -} - -int ModPlug_GetCurrentOrder(ModPlugFile* file) -{ - return file->mSoundFile.GetCurrentOrder(); -} - -int ModPlug_GetCurrentPattern(ModPlugFile* file) -{ - return file->mSoundFile.GetCurrentPattern(); -} - -int ModPlug_GetCurrentRow(ModPlugFile* file) -{ - return file->mSoundFile.m_nRow; -} - -int ModPlug_GetPlayingChannels(ModPlugFile* file) -{ - return ( file->mSoundFile.m_nMixChannels < file->mSoundFile.m_nMaxMixChannels ? file->mSoundFile.m_nMixChannels : file->mSoundFile.m_nMaxMixChannels ); -} - -void ModPlug_SeekOrder(ModPlugFile* file,int order) -{ - file->mSoundFile.SetCurrentOrder(order); -} - -int ModPlug_GetModuleType(ModPlugFile* file) -{ - return file->mSoundFile.m_nType; -} - -char* ModPlug_GetMessage(ModPlugFile* file) -{ - return file->mSoundFile.m_lpszSongComments; -} - -#ifndef MODPLUG_NO_FILESAVE -char ModPlug_ExportS3M(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveS3M(filepath,0); -} - -char ModPlug_ExportXM(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveXM(filepath,0); -} - -char ModPlug_ExportMOD(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveMod(filepath,0); -} - -char ModPlug_ExportIT(ModPlugFile* file,const char* filepath) -{ - return (char)file->mSoundFile.SaveIT(filepath,0); -} -#endif // MODPLUG_NO_FILESAVE - -unsigned int ModPlug_NumInstruments(ModPlugFile* file) -{ - return file->mSoundFile.m_nInstruments; -} - -unsigned int ModPlug_NumSamples(ModPlugFile* file) -{ - return file->mSoundFile.m_nSamples; -} - -unsigned int ModPlug_NumPatterns(ModPlugFile* file) -{ - return file->mSoundFile.GetNumPatterns(); -} - -unsigned int ModPlug_NumChannels(ModPlugFile* file) -{ - return file->mSoundFile.GetNumChannels(); -} - -unsigned int ModPlug_SampleName(ModPlugFile* file,unsigned int qual,char* buff) -{ - return file->mSoundFile.GetSampleName(qual,buff); -} - -unsigned int ModPlug_InstrumentName(ModPlugFile* file,unsigned int qual,char* buff) -{ - return file->mSoundFile.GetInstrumentName(qual,buff); -} - -ModPlugNote* ModPlug_GetPattern(ModPlugFile* file,int pattern,unsigned int* numrows) { - if ( patternmSoundFile.Patterns[pattern]) { - if (numrows) *numrows=(unsigned int)file->mSoundFile.PatternSize[pattern]; - return (ModPlugNote*)file->mSoundFile.Patterns[pattern]; - } - } - return NULL; -} - -void ModPlug_Seek(ModPlugFile* file, int millisecond) -{ - int maxpos; - int maxtime = file->mSoundFile.GetSongTime() * 1000; - float postime; - - if(millisecond > maxtime) - millisecond = maxtime; - maxpos = file->mSoundFile.GetMaxPosition(); - postime = (float)maxpos / (float)maxtime; - - file->mSoundFile.SetCurrentPos((int)(millisecond * postime)); -} - -void ModPlug_GetSettings(ModPlug_Settings* settings) -{ - memcpy(settings, &ModPlug::gSettings, sizeof(ModPlug_Settings)); -} - -void ModPlug_SetSettings(const ModPlug_Settings* settings) -{ - memcpy(&ModPlug::gSettings, settings, sizeof(ModPlug_Settings)); - ModPlug::UpdateSettings(false); // do not update basic config. -} diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/modplug.h --- a/src/modplug/modplug.h Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/modplug.h Thu Jan 24 12:05:59 2008 +0000 @@ -114,23 +114,6 @@ char* ModPlug_GetMessage(ModPlugFile* file); -#ifndef MODPLUG_NO_FILESAVE -/* - * EXPERIMENTAL Export Functions - */ -/*Export to a Scream Tracker 3 S3M module. EXPERIMENTAL (only works on Little-Endian platforms)*/ -char ModPlug_ExportS3M(ModPlugFile* file, const char* filepath); - -/*Export to a Extended Module (XM). EXPERIMENTAL (only works on Little-Endian platforms)*/ -char ModPlug_ExportXM(ModPlugFile* file, const char* filepath); - -/*Export to a Amiga MOD file. EXPERIMENTAL.*/ -char ModPlug_ExportMOD(ModPlugFile* file, const char* filepath); - -/*Export to a Impulse Tracker IT file. Should work OK in Little-Endian & Big-Endian platforms :-) */ -char ModPlug_ExportIT(ModPlugFile* file, const char* filepath); -#endif // MODPLUG_NO_FILESAVE - unsigned int ModPlug_NumInstruments(ModPlugFile* file); unsigned int ModPlug_NumSamples(ModPlugFile* file); unsigned int ModPlug_NumPatterns(ModPlugFile* file); diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/snd_dsp.cxx --- a/src/modplug/snd_dsp.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/snd_dsp.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -44,6 +44,9 @@ UINT CSoundFile::m_nProLogicDepth = 12; UINT CSoundFile::m_nProLogicDelay = 20; +void (*CSoundFile::_midi_out_note)(int chan, const MODCOMMAND *m) = NULL; +void (*CSoundFile::_midi_out_raw)(unsigned char *,unsigned int, unsigned int) = NULL; + //////////////////////////////////////////////////////////////////// // DSP Effects internal state @@ -168,6 +171,9 @@ memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3)); memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4)); memset(gRvbLowPass, 0, sizeof(gRvbLowPass)); +/* mrsb: libmodplug bug hahahah */ + memset(MixSoundBuffer,0,sizeof(MixSoundBuffer)); + memset(MixReverbBuffer,0,sizeof(MixReverbBuffer)); } } else nReverbSize = 0; #endif @@ -468,12 +474,12 @@ return TRUE; } -BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ) +BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL /*bNoOverSampling*/,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ) //---------------------------------------------------------------------------------------------------------------------------- { DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ); if (bSurround) d |= SNDMIX_SURROUND; - if (bNoOverSampling) d |= SNDMIX_NORESAMPLING; +// if (bNoOverSampling) d |= SNDMIX_NORESAMPLING; if (bReverb) d |= SNDMIX_REVERB; if (hqido) d |= SNDMIX_HQRESAMPLER; if (bMegaBass) d |= SNDMIX_MEGABASS; diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/snd_flt.cxx --- a/src/modplug/snd_flt.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/snd_flt.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -9,93 +9,122 @@ // AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz] // EMU10K1 docs: cutoff = reg[0-127]*62+100 -#define FILTER_PRECISION 8192 #ifndef NO_FILTER -#ifdef MSC_VER -#define _ASM_MATH -#endif - -#ifdef _ASM_MATH +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 +}; -// 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 - -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; -} - - +#define PI ((double)3.14159265358979323846) // Simple 2-poles resonant filter -void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const +void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier, int) const //---------------------------------------------------------------------------------------- { - float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier); - float fs = (float)gdwMixingFreq; - float fg, fb0, fb1; + int cutoff = pChn->nCutOff * 2; + cutoff *= (flt_modifier+256) / 2; + cutoff /= 256; + if (cutoff>=255) cutoff=255; - 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); + 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; - fg=1/(1+d+e); - fb0=(d+e+e)/(1+d+e); - fb1=-e/(1+d+e); + 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); - pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION); - pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION); - pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION); + fg = 1.0 / (1 + d + e); + fb0 = (d + e + e) / (1 + d + e); + fb1 = -e / (1 + d + e); - if (bReset) - { + pChn->nFilter_A0 = (double)fg; + pChn->nFilter_B0 = (double)fb0; + pChn->nFilter_B1 = (double)fb1; + + 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/snd_fx.cxx --- a/src/modplug/snd_fx.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/snd_fx.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -64,6 +64,7 @@ UINT nSpeedCount = 0; nRow = nNextRow; nCurrentPattern = nNextPattern; + // Check if pattern is valid nPattern = Order[nCurrentPattern]; while (nPattern >= MAX_PATTERNS) @@ -155,6 +156,7 @@ } if (param >= 0x20) nMusicTempo = param; else // Tempo Slide + // FIXME: this is totally wrong! if ((param & 0xF0) == 0x10) { nMusicTempo += param & 0x0F; @@ -298,7 +300,7 @@ BOOL bInstrumentChanged = FALSE; if (instr >= MAX_INSTRUMENTS) return; - INSTRUMENTHEADER *penv = Headers[instr]; + INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL; MODINSTRUMENT *psmp = &Ins[instr]; UINT note = pChn->nNewNote; if ((penv) && (note) && (note <= 128)) @@ -306,8 +308,9 @@ 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_nInstruments) + if (m_dwSongFlags & SONG_INSTRUMENTMODE) { if (note >= 0xFE) return; psmp = NULL; @@ -332,9 +335,11 @@ pChn->nNewIns = 0; if (psmp) { + psmp->played = 1; if (penv) { - pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6; + penv->played = 1; + pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 7; if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan; pChn->nNNA = penv->nNNA; } else @@ -421,29 +426,38 @@ } -void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv) -//--------------------------------------------------------------------------- +void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv, BOOL bManual) +//----------------------------------------------------------------------------------------- { if (note < 1) return; MODCHANNEL * const pChn = &Chn[nChn]; MODINSTRUMENT *pins = pChn->pInstrument; - INSTRUMENTHEADER *penv = pChn->pHeader; + INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL; 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_nInstruments)) pChn->nVolume = 0; + if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_INSTRUMENTMODE)) + pChn->nVolume = 0; pChn->nFadeOutVol = 0; } return; @@ -540,8 +554,9 @@ // Volume Swing if (penv->nVolSwing) { - int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128; - pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128); + /* this was wrong */ + int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 256; + pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/256); } // Pan Swing if (penv->nPanSwing) @@ -569,21 +584,42 @@ 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) const +UINT CSoundFile::GetNNAChannel(UINT nChn) //--------------------------------------------- { - const MODCHANNEL *pChn = &Chn[nChn]; + MODCHANNEL *pChn = &Chn[nChn]; // Check for empty channel - const MODCHANNEL *pi = &Chn[m_nChannels]; - for (UINT i=m_nChannels; inLength) return i; + 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; + } + } if (!pChn->nFadeOutVol) return 0; // All channels are used: check for lowest volume UINT result = 0; DWORD vol = 64*65536; // 25% - DWORD envpos = 0xFFFFFF; + int envpos = 0xFFFFFF; const MODCHANNEL *pj = &Chn[m_nChannels]; for (UINT j=m_nChannels; jpHeader, *pHeader; + INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL; + INSTRUMENTHEADER *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_nInstruments) || (bForceCut)) + if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!(m_dwSongFlags & SONG_INSTRUMENTMODE)) || (bForceCut)) { if ((m_dwSongFlags & SONG_CPUVERYHIGH) || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE) || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return; UINT n = GetNNAChannel(nChn); if (!n) return; - MODCHANNEL *p = &Chn[n]; + p = &Chn[n]; // Copy Channel *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); + p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_PORTAMENTO); p->nMasterChn = nChn+1; p->nCommand = 0; // Cut the note @@ -641,7 +683,7 @@ pHeader = pChn->pHeader; if ((instr) && (note)) { - pHeader = Headers[instr]; + pHeader = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL; if (pHeader) { UINT n = 0; @@ -654,7 +696,7 @@ } else pSample = NULL; } if (!penv) return; - MODCHANNEL *p = pChn; + p = pChn; for (UINT i=nChn; i= m_nChannels) || (p == pChn)) { @@ -666,7 +708,7 @@ { // Note case DCT_NOTE: - if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE; + if ((note) && ((int)p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE; break; // Sample case DCT_SAMPLE: @@ -711,10 +753,10 @@ UINT n = GetNNAChannel(nChn); if (n) { - MODCHANNEL *p = &Chn[n]; + p = &Chn[n]; // Copy Channel *p = *pChn; - p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO); + p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_PORTAMENTO); p->nMasterChn = nChn+1; p->nCommand = 0; // Key Off the note @@ -745,17 +787,19 @@ 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 = 0; + UINT nStartTick = pChn->nTickStart; 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 ? @@ -797,7 +841,7 @@ } if ((!note) && (instr)) { - if (m_nInstruments) + if (m_dwSongFlags & SONG_INSTRUMENTMODE) { if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume; if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) @@ -822,7 +866,7 @@ // Note Cut/Off => ignore instrument if (note >= 0xFE) instr = 0; if ((note) && (note <= 128)) pChn->nNewNote = note; - // New Note Action ? + // New Note Action ? (not when paused!!!) if ((note) && (note <= 128) && (!bPorta)) { CheckNNA(nChn, instr, note, FALSE); @@ -871,6 +915,7 @@ if (vol > 64) vol = 64; pChn->nPan = vol << 2; pChn->dwFlags |= CHN_FASTVOLRAMP; + pChn->dwFlags &= ~CHN_SURROUND; } } @@ -948,6 +993,14 @@ { 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; @@ -1004,7 +1057,22 @@ 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 @@ -1039,9 +1107,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; @@ -1053,14 +1121,18 @@ 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: + pChn->nCommand = CMD_TREMOR; if (m_nTickCount) break; - pChn->nCommand = CMD_TREMOR; if (param) pChn->nTremorParam = param; break; @@ -1149,12 +1221,35 @@ { 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: - ChannelVolSlide(pChn, param); + { + 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); + } + } + break; // Panbrello (IT) @@ -1169,10 +1264,10 @@ pChn->nVolEnvPosition = param; pChn->nPanEnvPosition = param; pChn->nPitchEnvPosition = param; - if (pChn->pHeader) + if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; - if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1])) + if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes) && ((int)param > penv->PanEnv.Ticks[penv->PanEnv.nNodes-1])) { pChn->dwFlags &= ~CHN_PANENV; } @@ -1267,6 +1362,8 @@ //--------------------------------------------------------- { 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) @@ -1294,6 +1391,8 @@ //----------------------------------------------------------- { 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) @@ -1566,6 +1665,7 @@ if (nPanSlide > 256) nPanSlide = 256; pChn->nPan = nPanSlide; } + pChn->dwFlags &= ~CHN_SURROUND; } @@ -1739,17 +1839,29 @@ } break; // S8x: Set 4-bit Panning - case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break; + case 0x80: + pChn->dwFlags &= ~CHN_SURROUND; + 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) { - pChn->nOldHiOffset = param; - if ((pChn->nRowNote) && (pChn->nRowNote < 0x80)) - { - DWORD pos = param << 16; - if (pos < pChn->nLength) pChn->nPos = pos; + 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; + } } } break; @@ -1772,12 +1884,12 @@ if (m_nTickCount) return; switch(param & 0x0F) { - // S90: Surround Off - case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break; - // S91: Surround On + // 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; @@ -1820,102 +1932,176 @@ } } - -void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param) -//--------------------------------------------------------------------------- +// this is all brisby +void CSoundFile::MidiSend(unsigned char *data, unsigned int len, UINT nChn, int fake) { MODCHANNEL *pChn = &Chn[nChn]; - 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; - } - } + int oldcutoff; - } - 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; + 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]; #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); + || (!(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); #endif // NO_FILTER - } - break; + 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); + } - // 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 + 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; + } + 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++; - break; + 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); } } @@ -1932,10 +2118,18 @@ if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) { if (!nRetrigSpeed) nRetrigSpeed = 1; - if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE; - nRetrigCount++; - } else - { + if (m_nMusicSpeed < nRetrigSpeed) { + if (nRetrigCount >= nRetrigSpeed) { + bDoRetrig = TRUE; + nRetrigCount = 0; + } else { + 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)) @@ -2022,9 +2216,10 @@ if (m_nTickCount == nTick) { MODCHANNEL *pChn = &Chn[nChn]; - // if (m_nInstruments) KeyOff(pChn); ? + // if (m_dwSongFlags & SONG_INSTRUMENTMODE) KeyOff(pChn); ? pChn->nVolume = 0; pChn->dwFlags |= CHN_FASTVOLRAMP; + pChn->nLength = 0; } } @@ -2036,7 +2231,7 @@ BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE; pChn->dwFlags |= CHN_KEYOFF; //if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV))) - if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV))) + if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV))) { pChn->dwFlags |= CHN_NOTEFADE; } @@ -2061,7 +2256,7 @@ pChn->nLength = psmp->nLength; } } - if (pChn->pHeader) + if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; if (((penv->dwFlags & ENV_VOLLOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut)) @@ -2077,22 +2272,8 @@ void CSoundFile::SetSpeed(UINT 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; + if (param) + m_nMusicSpeed = param; } @@ -2101,6 +2282,7 @@ { if (param < 0x20) { +#if 0 // argh... this is completely wrong // Tempo Slide if ((param & 0xF0) == 0x10) { @@ -2111,6 +2293,7 @@ m_nMusicTempo -= (param & 0x0F) * 2; if ((LONG)m_nMusicTempo < 32) m_nMusicTempo = 32; } +#endif } else { m_nMusicTempo = param; @@ -2126,15 +2309,28 @@ if (pChn->nPatternLoopCount) { pChn->nPatternLoopCount--; - if (!pChn->nPatternLoopCount) return -1; + 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; + } } 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; @@ -2297,6 +2493,33 @@ } } +// 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/sndfile.cxx --- a/src/modplug/sndfile.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/sndfile.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -15,6 +15,7 @@ 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); @@ -50,6 +51,7 @@ { m_nType = MOD_TYPE_NONE; m_dwSongFlags = 0; + m_nStereoSeparation = 128; m_nChannels = 0; m_nMixChannels = 0; m_nSamples = 0; @@ -62,6 +64,8 @@ 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)); @@ -86,8 +90,10 @@ { int i; + // deja vu... m_nType = MOD_TYPE_NONE; m_dwSongFlags = 0; + m_nStereoSeparation = 128; m_nChannels = 0; m_nMixChannels = 0; m_nSamples = 0; @@ -111,7 +117,6 @@ m_nMaxPeriod = 32767; m_nSongPreAmp = 0x30; m_nPatternNames = 0; - m_nMaxOrderPosition = 0; m_lpszPatternNames = NULL; m_lpszSongComments = NULL; memset(Ins, 0, sizeof(Ins)); @@ -123,7 +128,10 @@ 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; - if (pins->nSustainStart + 3 >= pins->nSustainEnd) - { - pins->nSustainStart = 0; - pins->nSustainEnd = 0; - } - } else - { + } else { pins->nLength = 0; pins->nLoopStart = 0; pins->nLoopEnd = 0; @@ -221,8 +209,7 @@ // Check invalid instruments while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--; // Set default values - if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; - if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; + if (m_nDefaultTempo < 31) m_nDefaultTempo = 31; if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; m_nMusicSpeed = m_nDefaultSpeed; m_nMusicTempo = m_nDefaultTempo; @@ -251,14 +238,7 @@ } } } - 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; + return m_nType ? TRUE : FALSE; } @@ -467,6 +447,7 @@ gdwMixingFreq = nRate; gnBitsPerSample = nBits; InitPlayer(bReset); +//printf("Rate=%u Bits=%u Channels=%u MMX=%u\n",gdwMixingFreq,gnBitsPerSample,gnChannels,bMMX); return TRUE; } @@ -494,7 +475,7 @@ { if (nVol < 1) nVol = 1; if (nVol > 0x200) nVol = 0x200; // x4 maximum - if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) + if ((gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) { gnAGC = gnAGC * m_nMasterVolume / nVol; if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY; @@ -697,7 +678,6 @@ m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); } - void CSoundFile::ResetChannels() //------------------------------ { @@ -710,6 +690,21 @@ } +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) //---------------------------------------------- { @@ -756,7 +751,7 @@ case MOD_TYPE_S3M: n = MOD_TYPE_S3M; } n |= MOD_TYPE_XM | MOD_TYPE_IT; - if (!m_nInstruments) + if (!(m_dwSongFlags & SONG_INSTRUMENTMODE)) { if (m_nSamples < 32) n |= MOD_TYPE_MOD; n |= MOD_TYPE_S3M; @@ -853,212 +848,6 @@ } #endif // NO_PACKING -#ifndef MODPLUG_NO_FILESAVE - -UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen) -//----------------------------------------------------------------------------------- -{ - UINT len = 0, bufcount; - signed char buffer[4096]; - signed char *pSample = (signed char *)pins->pSample; - UINT nLen = pins->nLength; - - if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen; - if ((!pSample) || (f == NULL) || (!nLen)) return 0; - switch(nFlags) - { -#ifndef NO_PACKING - // 3: 4-bit ADPCM data - case RS_ADPCM4: - { - int pos; - len = (nLen + 1) / 2; - fwrite(CompressionTable, 16, 1, f); - bufcount = 0; - pos = 0; - for (UINT j=0; j= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - len += 16; - } - break; -#endif // NO_PACKING - - // 16-bit samples - case RS_PCM16U: - case RS_PCM16D: - case RS_PCM16S: - { - short int *p = (short int *)pSample; - int s_old = 0, s_ofs; - len = nLen * 2; - bufcount = 0; - s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0; - for (UINT j=0; juFlags & CHN_STEREO) - { - s_new = (s_new + (*p) + 1) >> 1; - p++; - } - if (nFlags == RS_PCM16D) - { - short temp = bswapLE16((short)(s_new - s_old)); - *((short *)(&buffer[bufcount])) = temp; - s_old = s_new; - } else - { - short temp = bswapLE16((short)(s_new + s_ofs)); - *((short *)(&buffer[bufcount])) = temp; - } - bufcount += 2; - if (bufcount >= sizeof(buffer) - 1) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - break; - - - // 8-bit Stereo samples (not interleaved) - case RS_STPCM8S: - case RS_STPCM8U: - case RS_STPCM8D: - { - int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0; - for (UINT iCh=0; iCh<2; iCh++) - { - signed char *p = pSample + iCh; - int s_old = 0; - - bufcount = 0; - for (UINT j=0; j= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - len = nLen * 2; - break; - - // 16-bit Stereo samples (not interleaved) - case RS_STPCM16S: - case RS_STPCM16U: - case RS_STPCM16D: - { - int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0; - for (UINT iCh=0; iCh<2; iCh++) - { - signed short *p = ((signed short *)pSample) + iCh; - int s_old = 0; - - bufcount = 0; - for (UINT j=0; j= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - len = nLen*4; - break; - - // Stereo signed interleaved - case RS_STIPCM8S: - case RS_STIPCM16S: - len = nLen * 2; - if (nFlags == RS_STIPCM16S) len *= 2; - fwrite(pSample, 1, len, f); - break; - - // Default: assume 8-bit PCM data - default: - len = nLen; - bufcount = 0; - { - signed char *p = pSample; - int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1; - int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0; - if (pins->uFlags & CHN_16BIT) p++; - for (UINT j=0; juFlags & CHN_STEREO) - { - s_new = (s_new + ((int)*p) + 1) >> 1; - p += sinc; - } - if (nFlags == RS_PCM8D) - { - buffer[bufcount++] = (signed char)(s_new - s_old); - s_old = s_new; - } else - { - buffer[bufcount++] = (signed char)(s_new + s_ofs); - } - if (bufcount >= sizeof(buffer)) - { - fwrite(buffer, 1, bufcount, f); - bufcount = 0; - } - } - if (bufcount) fwrite(buffer, 1, bufcount, f); - } - } - return len; -} - -#endif // MODPLUG_NO_FILESAVE // Flags: @@ -1074,11 +863,10 @@ UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength) //------------------------------------------------------------------------------------------------ { - UINT len = 0, mem; + UINT len = 0, mem = pIns->nLength+6; - if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0; + if ((!pIns) || (pIns->nLength < 1) || (!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) { @@ -1152,13 +940,15 @@ { len = pIns->nLength * 2; if (len > dwMemLength) break; - short int *pSample = (short int *)pIns->pSample; - short int *p = (short int *)lpMemFile; + short *pSample = (short *)pIns->pSample; + short *p = (short *)lpMemFile; + unsigned short tmp; int delta16 = 0; for (UINT j=0; jnLength * 2; - if (len > dwMemLength) break; + if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len); short int *pSample = (short int *)pIns->pSample; - short int *pSrc = (short int *)lpMemFile; - 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: @@ -1364,7 +1156,7 @@ for (UINT j=0; juFlags & CHN_STEREO) { - 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; + 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]; } else { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; + pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; } if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) { @@ -1595,12 +1386,11 @@ // Adjust end of sample if (pIns->uFlags & CHN_STEREO) { - 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; - + 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]; } else { - pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0; + pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; } if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) { @@ -1625,8 +1415,6 @@ //----------------------------------------------------------- { //---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); @@ -1656,6 +1444,8 @@ 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 } @@ -1665,8 +1455,6 @@ //---------------------------------------------- { //---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; @@ -1682,6 +1470,8 @@ fistp result } return result; +#else + return (int) (1536.0 * (log(freq / 8363.0) / log(2))); #endif } @@ -1778,6 +1568,32 @@ 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 @@ -1787,7 +1603,7 @@ UINT nExt = 0; if (!pbIns) return 0; - if (m_nInstruments) + if (m_dwSongFlags & SONG_INSTRUMENTMODE) { memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); for (UINT ipat=0; ipat (endian and char fixes for PPC) */ -#include "config.h" +#include #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 @@ -28,7 +31,7 @@ #ifdef MODPLUG_FASTSOUNDLIB #define MAX_CHANNELS 80 #else -#define MAX_CHANNELS 128 +#define MAX_CHANNELS 256 #endif #define MAX_BASECHANNELS 64 #define MAX_ENVPOINTS 32 @@ -65,7 +68,6 @@ #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 @@ -102,6 +104,8 @@ #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 @@ -118,6 +122,7 @@ #define ENV_VOLCARRY 0x0800 #define ENV_PANCARRY 0x1000 #define ENV_PITCHCARRY 0x2000 +#define ENV_MUTE 0x4000 #define CMD_NONE 0 #define CMD_ARPEGGIO 1 @@ -254,6 +259,9 @@ #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 @@ -272,7 +280,10 @@ #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 { @@ -302,66 +313,59 @@ UINT nSustainStart, nSustainEnd; signed char *pSample; UINT nC4Speed; - WORD nPan; - WORD nVolume; - WORD nGlobalVol; - WORD uFlags; - signed char RelativeTone; - signed char nFineTune; - BYTE nVibType; - BYTE nVibSweep; - BYTE nVibDepth; - BYTE nVibRate; + UINT nPan; + UINT nVolume; + UINT nGlobalVol; + UINT uFlags; + int RelativeTone; + int nFineTune; + UINT nVibType; + UINT nVibSweep; + UINT nVibDepth; + UINT 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; - 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; + 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; CHAR name[32]; CHAR filename[12]; + int played; // for note playback dots } INSTRUMENTHEADER; @@ -372,6 +376,7 @@ signed char * pCurrentSample; DWORD nPos; DWORD nPosLo; // actually 16-bit + unsigned int topnote_offset; LONG nInc; // 16.16 LONG nRightVol; LONG nLeftVol; @@ -384,8 +389,10 @@ DWORD nLoopEnd; LONG nRampRightVol; LONG nRampLeftVol; - LONG nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4; - LONG nFilter_A0, nFilter_B0, nFilter_B1; + + double nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4; + double nFilter_A0, nFilter_B0, nFilter_B1; + LONG nROfs, nLOfs; LONG nRampLength; // Information not used in the mixer @@ -393,37 +400,42 @@ LONG nNewRightVol, nNewLeftVol; LONG nRealVolume, nRealPan; LONG nVolume, nPan, nFadeOutVol; - LONG nPeriod, nC4Speed, nPortamentoDest; + LONG nPeriod, nC4Speed, sample_freq, nPortamentoDest; INSTRUMENTHEADER *pHeader; MODINSTRUMENT *pInstrument; - DWORD nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition; + int nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition; DWORD nMasterChn, nVUMeter; LONG nGlobalVol, nInsVol; LONG nFineTune, nTranspose; LONG nPortamentoSlide, nAutoVibDepth; UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos; // 16-bit members - 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; + 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; + } MODCHANNEL; @@ -454,12 +466,13 @@ 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 long nSamples) = 0; - virtual void Init(unsigned long nFreq, int bReset) = 0; + virtual void Process(float *pOutL, float *pOutR, unsigned int nSamples) = 0; + virtual void Init(unsigned int nFreq, int bReset) = 0; virtual void MidiSend(DWORD dwMidiCode) = 0; virtual void MidiCommand(UINT nMidiCh, UINT nMidiProg, UINT note, UINT vol) = 0; }; @@ -523,7 +536,7 @@ } MODMIDICFG, *LPMODMIDICFG; -typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels +typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned int, unsigned int); // buffer, samples, channels @@ -535,11 +548,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, gnVUMeter, gnCPUUsage; + static UINT gnAGC, gnVolumeRampSamples, gnCPUUsage; + static UINT gnVULeft, gnVURight; static LPSNDMIXHOOKPROC gpSndMixHook; static PMIXPLUGINCREATEPROC gpMixPluginCreateProc; @@ -551,22 +564,24 @@ 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_nRestartPos; + UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nLockedPattern,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; - UINT m_nMaxOrderPosition; + BYTE m_rowHighlightMajor, m_rowHighlightMinor; UINT m_nPatternNames; LPSTR m_lpszSongComments, m_lpszPatternNames; char m_szNames[MAX_INSTRUMENTS][32]; // changed from CHAR @@ -579,6 +594,7 @@ 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; } @@ -635,14 +651,7 @@ BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength); - // Save Functions -#ifndef MODPLUG_NO_FILESAVE - 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 // MODPLUG_NO_FILESAVE + BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength); // MOD Convert function UINT GetBestSaveFormat() const; UINT GetSaveFormats() const; @@ -650,6 +659,10 @@ 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 @@ -678,6 +691,23 @@ 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 @@ -694,9 +724,9 @@ BOOL ReadNote(); BOOL ProcessRow(); BOOL ProcessEffects(); - UINT GetNNAChannel(UINT nChn) const; + UINT GetNNAChannel(UINT nChn); void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut); - void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE); + void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE, BOOL bManual=FALSE); void InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE); // Channel Effects void PortamentoUp(MODCHANNEL *pChn, UINT param); @@ -722,8 +752,10 @@ void ExtendedMODCommands(UINT nChn, UINT param); void ExtendedS3MCommands(UINT nChn, UINT param); void ExtendedChannelEffect(MODCHANNEL *, UINT param); - void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0); - void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256) const; + 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; // Low-Level effect processing void DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide); // Global Effects @@ -751,6 +783,7 @@ // 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; } @@ -759,9 +792,7 @@ BOOL ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers); UINT SaveMixPlugins(FILE *f=NULL, BOOL bUpdate=TRUE); UINT LoadMixPlugins(const void *pData, UINT nLen); -#ifndef NO_FILTER - DWORD CutOffToFrequency(UINT nCutOff, int flt_modifier=256) const; // [0-255] => [1-10KHz] -#endif + void ResetTimestamps(); // for note playback dots // Static helper functions public: @@ -909,8 +940,8 @@ #define MIXBUFFERSIZE 512 #define MIXING_ATTENUATION 4 -#define MIXING_CLIPMIN (-0x08000000) -#define MIXING_CLIPMAX (0x07FFFFFF) +#define MIXING_CLIPMIN (-0x04000000) +#define MIXING_CLIPMAX (0x03FFFFFF) #define VOLUMERAMPPRECISION 12 #define FADESONGDELAY 100 #define EQ_BUFFERSIZE (MIXBUFFERSIZE) @@ -929,8 +960,18 @@ #define MOD2XMFineTune(k) ((int)( (signed char)((k)<<4) )) #define XM2MODFineTune(k) ((int)( (k>>4)&0x0f )) -int _muldiv(long a, long b, long c); -int _muldivr(long a, long b, long c); +// 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; +} + + +// Return (a*b+c/2)/c - no divide error +static inline int _muldivr(int a, int b, int c) +{ + return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c; +} // Byte swapping functions from the GNU C Library and libsdl diff -r ad45d65e9ae7 -r 107c1fed3d92 src/modplug/sndmix.cxx --- a/src/modplug/sndmix.cxx Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/sndmix.cxx Thu Jan 24 12:05:59 2008 +0000 @@ -7,18 +7,14 @@ #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 4 +#define VUMETER_DECAY 16 // 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) @@ -30,7 +26,8 @@ // Mixing data initialized in UINT CSoundFile::gnAGC = AGC_UNITY; UINT CSoundFile::gnVolumeRampSamples = 64; -UINT CSoundFile::gnVUMeter = 0; +UINT CSoundFile::gnVULeft = 0; +UINT CSoundFile::gnVURight = 0; UINT CSoundFile::gnCPUUsage = 0; LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; @@ -42,15 +39,15 @@ typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); -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 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 short int ModSinusTable[64]; extern short int ModRampDownTable[64]; @@ -85,104 +82,6 @@ }; -// 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) //-------------------------------------- { @@ -195,11 +94,13 @@ gnRvbROfsVol = gnRvbLOfsVol = 0; if (bReset) { - gnVUMeter = 0; + gnVULeft = 0; + gnVURight = 0; gnCPUUsage = 0; } gbInitPlugins = (bReset) ? 3 : 1; InitializeDSP(bReset); + InitializeEQ(bReset); return TRUE; } @@ -245,22 +146,28 @@ //------------------------------------------------------- { LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; - LPCONVERTPROC pCvt = X86_Convert32To8; + LPCONVERTPROC pCvt = Convert32To8; + LONG vu_min[2]; + LONG vu_max[2]; UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; - LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF; +#if 0 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 = X86_Convert32To16; } -#ifndef MODPLUG_FASTSOUNDLIB - else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; } - else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; } -#endif + if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; } + else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; } + else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; } lMax = cbBuffer / lSampleSize; if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; lRead = lMax; @@ -268,26 +175,18 @@ while (lRead > 0) { // Update Channel Data + UINT lTotalSampleCount; if (!m_nBufferCount) { -#ifndef MODPLUG_FASTSOUNDLIB - if (m_dwSongFlags & SONG_FADINGSONG) - { - m_dwSongFlags |= SONG_ENDREACHED; + 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; + if (!ReadNote()) { + m_dwSongFlags |= SONG_ENDREACHED; + if (lRead == lMax) goto MixDone; + if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) m_nBufferCount = lRead; - } } + if (!m_nBufferCount) goto MixDone; } lCount = m_nBufferCount; if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; @@ -297,30 +196,46 @@ #ifndef MODPLUG_NO_REVERB gnReverbSend = 0; #endif + // Resetting sound buffer - X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); + 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); - ProcessStereoDSP(lCount); - X86_MonoFromStereo(MixSoundBuffer, lCount); +#if 0 + if (nMaxPlugins) ProcessPlugins(lCount); +#endif + MonoFromStereo(MixSoundBuffer, lCount); + ProcessMonoDSP(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 - UINT lTotalSampleCount = lSampleCount; -#ifndef MODPLUG_FASTSOUNDLIB + lTotalSampleCount = lSampleCount; // Multichannel if (gnChannels > 2) { - X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); + InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); lTotalSampleCount *= 2; } // Hook Function @@ -328,9 +243,8 @@ { gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); } -#endif // Perform clipping + VU-Meter - lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax); + lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max); // Buffer ready lRead -= lCount; m_nBufferCount -= lCount; @@ -338,10 +252,16 @@ MixDone: if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); // VU-Meter - nVUMeterMin >>= (24-MIXING_ATTENUATION); - nVUMeterMax >>= (24-MIXING_ATTENUATION); - if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin; - if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF; + 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; if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } return lMax - lRead; } @@ -355,77 +275,75 @@ //--------------------------- { 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) 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) + 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)) { - // 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; } - m_nNextPattern = m_nCurrentPattern; + } +#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; } // Weird stuff? - if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE; + if (m_nPattern >= MAX_PATTERNS) 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 @@ -433,7 +351,18 @@ 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; @@ -445,6 +374,14 @@ 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; + } + } + }; + //////////////////////////////////////////////////////////////////////////////////// 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 + // Master Volume + Pre-Amplification / Attenuation setup DWORD nMasterVol; { - int nchn32 = (m_nChannels < 32) ? m_nChannels : 31; - if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6; + int nchn32 = 0; + MODCHANNEL *pChn = Chn; + for (UINT nChn=0; nChn 31) nchn32 = 31; + int realmastervol = m_nMasterVolume; if (realmastervol > 0x80) { realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; } - UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; - DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6; - if (mastervol > 0x200) mastervol = 0x200; + + DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 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 ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength))) + if ((nChn >= m_nChannels) && (!pChn->nLength)) { - pChn->nVUMeter = 0; -#ifdef ENABLE_STEREOVU pChn->nLeftVU = pChn->nRightVU = 0; -#endif continue; } // Reset channel data @@ -575,33 +569,33 @@ if (vol > 0x100) vol = 0x100; vol <<= 6; // Process Envelopes - if (pChn->pHeader) + if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; // Volume Envelope - if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv)) + if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes)) { int envpos = pChn->nVolEnvPosition; - UINT pt = penv->nVolEnv - 1; - for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++) + UINT pt = penv->VolEnv.nNodes - 1; + for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++) { - if (envpos <= penv->VolPoints[i]) + if (envpos <= penv->VolEnv.Ticks[i]) { pt = i; break; } } - int x2 = penv->VolPoints[pt]; + int x2 = penv->VolEnv.Ticks[pt]; int x1, envvol; if (envpos >= x2) { - envvol = penv->VolEnv[pt] << 2; + envvol = penv->VolEnv.Values[pt] << 2; x1 = x2; } else if (pt) { - envvol = penv->VolEnv[pt-1] << 2; - x1 = penv->VolPoints[pt-1]; + envvol = penv->VolEnv.Values[pt-1] << 2; + x1 = penv->VolEnv.Ticks[pt-1]; } else { envvol = 0; @@ -610,26 +604,26 @@ if (envpos > x2) envpos = x2; if ((x2 > x1) && (envpos > x1)) { - envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1); + envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[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->nPanEnv)) + if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes)) { int envpos = pChn->nPanEnvPosition; - UINT pt = penv->nPanEnv - 1; - for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++) + UINT pt = penv->PanEnv.nNodes - 1; + for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++) { - if (envpos <= penv->PanPoints[i]) + if (envpos <= penv->PanEnv.Ticks[i]) { pt = i; break; } } - int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt]; + int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt]; int x1, envpan; if (envpos >= x2) { @@ -638,8 +632,8 @@ } else if (pt) { - envpan = penv->PanEnv[pt-1]; - x1 = penv->PanPoints[pt-1]; + envpan = penv->PanEnv.Values[pt-1]; + x1 = penv->PanEnv.Ticks[pt-1]; } else { envpan = 128; @@ -714,8 +708,13 @@ { 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 } } @@ -726,30 +725,32 @@ } // Pitch/Filter Envelope - if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv)) + int envpitch = 0; + if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) + && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes)) { INSTRUMENTHEADER *penv = pChn->pHeader; int envpos = pChn->nPitchEnvPosition; - UINT pt = penv->nPitchEnv - 1; - for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++) + UINT pt = penv->PitchEnv.nNodes - 1; + for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++) { - if (envpos <= penv->PitchPoints[i]) + if (envpos <= penv->PitchEnv.Ticks[i]) { pt = i; break; } } - int x2 = penv->PitchPoints[pt]; - int x1, envpitch; + int x2 = penv->PitchEnv.Ticks[pt]; + int x1; if (envpos >= x2) { - envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8; + envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; x1 = x2; } else if (pt) { - envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8; - x1 = penv->PitchPoints[pt-1]; + envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8; + x1 = penv->PitchEnv.Ticks[pt-1]; } else { envpitch = 0; @@ -758,19 +759,13 @@ if (envpos > x2) envpos = x2; if ((x2 > x1) && (envpos > x1)) { - int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8; + int envpitchdest = (((int)penv->PitchEnv.Values[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) @@ -860,6 +855,16 @@ 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; @@ -867,7 +872,7 @@ { if (m_nType & MOD_TYPE_IT) { - pChn->nAutoVibDepth += pins->nVibSweep << 3; + pChn->nAutoVibDepth += pins->nVibSweep; } else if (!(pChn->dwFlags & CHN_KEYOFF)) { @@ -876,7 +881,8 @@ if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) pChn->nAutoVibDepth = pins->nVibDepth << 8; } - pChn->nAutoVibPos += pins->nVibRate; +#endif + pChn->nAutoVibPos += ((int)pins->nVibRate); int val; switch(pins->nVibType) { @@ -897,6 +903,10 @@ 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; @@ -939,12 +949,25 @@ 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; @@ -953,7 +976,7 @@ } // Increment envelope position - if (pChn->pHeader) + if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; // Volume Envelope @@ -964,13 +987,13 @@ // Volume Loop ? if (penv->dwFlags & ENV_VOLLOOP) { - UINT volloopend = penv->VolPoints[penv->nVolLoopEnd]; + int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd]; if (m_nType != MOD_TYPE_XM) volloopend++; if (pChn->nVolEnvPosition == volloopend) { - 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->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->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; @@ -980,15 +1003,15 @@ // Volume Sustain ? if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) { - if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1) - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin]; + if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1) + pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart]; } else // End of Envelope ? - if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1]) + if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]) { if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; - pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1]; - if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) + 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->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; @@ -1003,21 +1026,21 @@ pChn->nPanEnvPosition++; if (penv->dwFlags & ENV_PANLOOP) { - UINT panloopend = penv->PanPoints[penv->nPanLoopEnd]; + int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd]; if (m_nType != MOD_TYPE_XM) panloopend++; if (pChn->nPanEnvPosition == panloopend) - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart]; + pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart]; } // Panning Sustain ? - if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1) + if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1) && (!(pChn->dwFlags & CHN_KEYOFF))) { // Panning sustained - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin]; + pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart]; } else { - if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1]) - pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1]; + if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]) + pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]; } } // Pitch Envelope @@ -1028,22 +1051,22 @@ // Pitch Loop ? if (penv->dwFlags & ENV_PITCHLOOP) { - if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd]) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart]; + if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd]) + pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart]; } // Pitch Sustain ? if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) { - if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin]; + if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1) + pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart]; } else { - if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1]) - pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1]; + if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]) + pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]; } } } -#ifdef MODPLUG_PLAYER +#if 0 // Limit CPU -> > 80% -> don't ramp if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) { @@ -1054,14 +1077,10 @@ 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; @@ -1069,14 +1088,11 @@ 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; @@ -1087,7 +1103,6 @@ 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 @@ -1103,9 +1118,8 @@ if (pan < 0) pan = 0; if (pan > 256) pan = 256; -#ifndef MODPLUG_FASTSOUNDLIB if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; -#endif + if (m_dwSongFlags & SONG_NOSTEREO) pan = 128; LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); if (gdwSoundSetup & SNDMIX_SOFTPANNING) { @@ -1134,6 +1148,7 @@ // Check IDO if (gdwSoundSetup & SNDMIX_NORESAMPLING) { + pChn->dwFlags &= ~(CHN_HQSRC); pChn->dwFlags |= CHN_NOIDO; } else { @@ -1151,21 +1166,26 @@ pChn->nNewLeftVol >>= MIXING_ATTENUATION; pChn->nRightRamp = pChn->nLeftRamp = 0; // Dolby Pro-Logic Surround - if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol; + if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0) + pChn->nNewLeftVol = -pChn->nNewLeftVol; // Checking Ping-Pong Loops if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; // Setting up volume ramp - if ((pChn->dwFlags & CHN_VOLUMERAMP) + if (!(gdwSoundSetup & SNDMIX_NORAMPING) + && (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); -#ifndef MODPLUG_FASTSOUNDLIB +#if 0 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))) { @@ -1174,7 +1194,6 @@ if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; } } -#endif pChn->nRightRamp = nRightDelta / nRampLength; pChn->nLeftRamp = nLeftDelta / nRampLength; pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); @@ -1197,15 +1216,15 @@ pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; // Adding the channel in the channel list - ChnMix[m_nMixChannels++] = nChn; - if (m_nMixChannels >= MAX_CHANNELS) break; + if (!(pChn->dwFlags & CHN_MUTE)) { + 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 ad45d65e9ae7 -r 107c1fed3d92 src/modplug/stdafx.h --- a/src/modplug/stdafx.h Wed Jan 23 19:37:05 2008 +0100 +++ b/src/modplug/stdafx.h Thu Jan 24 12:05:59 2008 +0000 @@ -9,7 +9,6 @@ #ifndef _STDAFX_H_ #define _STDAFX_H_ - #ifdef MSC_VER #pragma warning (disable:4201) @@ -19,7 +18,9 @@ #include #include -#elif defined(__x86_64__) || defined(__powerpc64__) +inline void ProcessPlugins(int n) {} + +#else #include #include @@ -36,24 +37,20 @@ 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 LONGLONG; +typedef long 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 @@ -64,6 +61,7 @@ #define GHND 0 +#ifdef __cplusplus inline signed char * GlobalAllocPtr(unsigned int, size_t size) { signed char * p = (signed char *) malloc(size); @@ -72,86 +70,13 @@ return p; } -#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; -} +inline void ProcessPlugins(int) {} #define GlobalFreePtr(p) free((void *)(p)) #define strnicmp(a,b,c) strncasecmp(a,b,c) #define wsprintf sprintf +#endif #ifndef FALSE #define FALSE false