Mercurial > audlegacy-plugins
comparison src/modplug/sndmix.cxx @ 2337:107c1fed3d92
Port Schism modplug core.
author | "Tony Vroon <chainsaw@gentoo.org>" |
---|---|
date | Thu, 24 Jan 2008 12:05:59 +0000 |
parents | 6907fc39b53f |
children | b24eda79942b |
comparison
equal
deleted
inserted
replaced
2336:ad45d65e9ae7 | 2337:107c1fed3d92 |
---|---|
5 */ | 5 */ |
6 | 6 |
7 #include "stdafx.h" | 7 #include "stdafx.h" |
8 #include "sndfile.h" | 8 #include "sndfile.h" |
9 | 9 |
10 #ifdef MODPLUG_TRACKER | |
11 #define ENABLE_STEREOVU | |
12 #endif | |
13 | 10 |
14 // Volume ramp length, in 1/10 ms | 11 // Volume ramp length, in 1/10 ms |
15 #define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz | 12 #define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz |
16 | 13 |
17 // VU-Meter | 14 // VU-Meter |
18 #define VUMETER_DECAY 4 | 15 #define VUMETER_DECAY 16 |
19 | 16 |
20 // SNDMIX: These are global flags for playback control | 17 // SNDMIX: These are global flags for playback control |
21 UINT CSoundFile::m_nStereoSeparation = 128; | |
22 LONG CSoundFile::m_nStreamVolume = 0x8000; | 18 LONG CSoundFile::m_nStreamVolume = 0x8000; |
23 UINT CSoundFile::m_nMaxMixChannels = 32; | 19 UINT CSoundFile::m_nMaxMixChannels = 32; |
24 // Mixing Configuration (SetWaveConfig) | 20 // Mixing Configuration (SetWaveConfig) |
25 DWORD CSoundFile::gdwSysInfo = 0; | 21 DWORD CSoundFile::gdwSysInfo = 0; |
26 DWORD CSoundFile::gnChannels = 1; | 22 DWORD CSoundFile::gnChannels = 1; |
28 DWORD CSoundFile::gdwMixingFreq = 44100; | 24 DWORD CSoundFile::gdwMixingFreq = 44100; |
29 DWORD CSoundFile::gnBitsPerSample = 16; | 25 DWORD CSoundFile::gnBitsPerSample = 16; |
30 // Mixing data initialized in | 26 // Mixing data initialized in |
31 UINT CSoundFile::gnAGC = AGC_UNITY; | 27 UINT CSoundFile::gnAGC = AGC_UNITY; |
32 UINT CSoundFile::gnVolumeRampSamples = 64; | 28 UINT CSoundFile::gnVolumeRampSamples = 64; |
33 UINT CSoundFile::gnVUMeter = 0; | 29 UINT CSoundFile::gnVULeft = 0; |
30 UINT CSoundFile::gnVURight = 0; | |
34 UINT CSoundFile::gnCPUUsage = 0; | 31 UINT CSoundFile::gnCPUUsage = 0; |
35 LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; | 32 LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; |
36 PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; | 33 PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; |
37 LONG gnDryROfsVol = 0; | 34 LONG gnDryROfsVol = 0; |
38 LONG gnDryLOfsVol = 0; | 35 LONG gnDryLOfsVol = 0; |
40 LONG gnRvbLOfsVol = 0; | 37 LONG gnRvbLOfsVol = 0; |
41 int gbInitPlugins = 0; | 38 int gbInitPlugins = 0; |
42 | 39 |
43 typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); | 40 typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); |
44 | 41 |
45 extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); | 42 extern DWORD MPPASMCALL Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); |
46 extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); | 43 extern DWORD MPPASMCALL Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); |
47 extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); | 44 extern DWORD MPPASMCALL Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); |
48 extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); | 45 extern DWORD MPPASMCALL Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); |
49 extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC); | 46 extern UINT MPPASMCALL AGC(int *pBuffer, UINT nSamples, UINT nAGC); |
50 extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits); | 47 extern VOID MPPASMCALL Dither(int *pBuffer, UINT nSamples, UINT nBits); |
51 extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); | 48 extern VOID MPPASMCALL InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); |
52 extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); | 49 extern VOID MPPASMCALL StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); |
53 extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples); | 50 extern VOID MPPASMCALL MonoFromStereo(int *pMixBuf, UINT nSamples); |
54 | 51 |
55 extern short int ModSinusTable[64]; | 52 extern short int ModSinusTable[64]; |
56 extern short int ModRampDownTable[64]; | 53 extern short int ModRampDownTable[64]; |
57 extern short int ModSquareTable[64]; | 54 extern short int ModSquareTable[64]; |
58 extern short int ModRandomTable[64]; | 55 extern short int ModRandomTable[64]; |
83 0x84, 0x88, 0x8C, 0x90, | 80 0x84, 0x88, 0x8C, 0x90, |
84 0x94, 0x98, 0x9C, 0xA0, | 81 0x94, 0x98, 0x9C, 0xA0, |
85 }; | 82 }; |
86 | 83 |
87 | 84 |
88 // Return (a*b)/c - no divide error | |
89 int _muldiv(long a, long b, long c) | |
90 { | |
91 #ifdef MSC_VER | |
92 int sign, result; | |
93 _asm { | |
94 mov eax, a | |
95 mov ebx, b | |
96 or eax, eax | |
97 mov edx, eax | |
98 jge aneg | |
99 neg eax | |
100 aneg: | |
101 xor edx, ebx | |
102 or ebx, ebx | |
103 mov ecx, c | |
104 jge bneg | |
105 neg ebx | |
106 bneg: | |
107 xor edx, ecx | |
108 or ecx, ecx | |
109 mov sign, edx | |
110 jge cneg | |
111 neg ecx | |
112 cneg: | |
113 mul ebx | |
114 cmp edx, ecx | |
115 jae diverr | |
116 div ecx | |
117 jmp ok | |
118 diverr: | |
119 mov eax, 0x7fffffff | |
120 ok: | |
121 mov edx, sign | |
122 or edx, edx | |
123 jge rneg | |
124 neg eax | |
125 rneg: | |
126 mov result, eax | |
127 } | |
128 return result; | |
129 #else | |
130 return ((unsigned long long) a * (unsigned long long) b ) / c; | |
131 #endif | |
132 } | |
133 | |
134 | |
135 // Return (a*b+c/2)/c - no divide error | |
136 int _muldivr(long a, long b, long c) | |
137 { | |
138 #ifdef MSC_VER | |
139 int sign, result; | |
140 _asm { | |
141 mov eax, a | |
142 mov ebx, b | |
143 or eax, eax | |
144 mov edx, eax | |
145 jge aneg | |
146 neg eax | |
147 aneg: | |
148 xor edx, ebx | |
149 or ebx, ebx | |
150 mov ecx, c | |
151 jge bneg | |
152 neg ebx | |
153 bneg: | |
154 xor edx, ecx | |
155 or ecx, ecx | |
156 mov sign, edx | |
157 jge cneg | |
158 neg ecx | |
159 cneg: | |
160 mul ebx | |
161 mov ebx, ecx | |
162 shr ebx, 1 | |
163 add eax, ebx | |
164 adc edx, 0 | |
165 cmp edx, ecx | |
166 jae diverr | |
167 div ecx | |
168 jmp ok | |
169 diverr: | |
170 mov eax, 0x7fffffff | |
171 ok: | |
172 mov edx, sign | |
173 or edx, edx | |
174 jge rneg | |
175 neg eax | |
176 rneg: | |
177 mov result, eax | |
178 } | |
179 return result; | |
180 #else | |
181 return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c; | |
182 #endif | |
183 } | |
184 | |
185 | |
186 BOOL CSoundFile::InitPlayer(BOOL bReset) | 85 BOOL CSoundFile::InitPlayer(BOOL bReset) |
187 //-------------------------------------- | 86 //-------------------------------------- |
188 { | 87 { |
189 if (m_nMaxMixChannels > MAX_CHANNELS) m_nMaxMixChannels = MAX_CHANNELS; | 88 if (m_nMaxMixChannels > MAX_CHANNELS) m_nMaxMixChannels = MAX_CHANNELS; |
190 if (gdwMixingFreq < 4000) gdwMixingFreq = 4000; | 89 if (gdwMixingFreq < 4000) gdwMixingFreq = 4000; |
193 if (gnVolumeRampSamples < 8) gnVolumeRampSamples = 8; | 92 if (gnVolumeRampSamples < 8) gnVolumeRampSamples = 8; |
194 gnDryROfsVol = gnDryLOfsVol = 0; | 93 gnDryROfsVol = gnDryLOfsVol = 0; |
195 gnRvbROfsVol = gnRvbLOfsVol = 0; | 94 gnRvbROfsVol = gnRvbLOfsVol = 0; |
196 if (bReset) | 95 if (bReset) |
197 { | 96 { |
198 gnVUMeter = 0; | 97 gnVULeft = 0; |
98 gnVURight = 0; | |
199 gnCPUUsage = 0; | 99 gnCPUUsage = 0; |
200 } | 100 } |
201 gbInitPlugins = (bReset) ? 3 : 1; | 101 gbInitPlugins = (bReset) ? 3 : 1; |
202 InitializeDSP(bReset); | 102 InitializeDSP(bReset); |
103 InitializeEQ(bReset); | |
203 return TRUE; | 104 return TRUE; |
204 } | 105 } |
205 | 106 |
206 | 107 |
207 BOOL CSoundFile::FadeSong(UINT msec) | 108 BOOL CSoundFile::FadeSong(UINT msec) |
243 | 144 |
244 UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer) | 145 UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer) |
245 //------------------------------------------------------- | 146 //------------------------------------------------------- |
246 { | 147 { |
247 LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; | 148 LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; |
248 LPCONVERTPROC pCvt = X86_Convert32To8; | 149 LPCONVERTPROC pCvt = Convert32To8; |
150 LONG vu_min[2]; | |
151 LONG vu_max[2]; | |
249 UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; | 152 UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; |
250 LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF; | 153 #if 0 |
251 UINT nMaxPlugins; | 154 UINT nMaxPlugins; |
252 | 155 #endif |
156 | |
157 vu_min[0] = vu_min[1] = 0x7FFFFFFF; | |
158 vu_max[0] = vu_max[1] = -0x7FFFFFFF; | |
159 | |
160 #if 0 | |
253 { | 161 { |
254 nMaxPlugins = MAX_MIXPLUGINS; | 162 nMaxPlugins = MAX_MIXPLUGINS; |
255 while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--; | 163 while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--; |
256 } | 164 } |
165 #endif | |
257 m_nMixStat = 0; | 166 m_nMixStat = 0; |
258 lSampleSize = gnChannels; | 167 lSampleSize = gnChannels; |
259 if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; } | 168 if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; } |
260 #ifndef MODPLUG_FASTSOUNDLIB | 169 else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; } |
261 else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; } | 170 else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; } |
262 else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; } | |
263 #endif | |
264 lMax = cbBuffer / lSampleSize; | 171 lMax = cbBuffer / lSampleSize; |
265 if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; | 172 if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; |
266 lRead = lMax; | 173 lRead = lMax; |
267 if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone; | 174 if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone; |
268 while (lRead > 0) | 175 while (lRead > 0) |
269 { | 176 { |
270 // Update Channel Data | 177 // Update Channel Data |
178 UINT lTotalSampleCount; | |
271 if (!m_nBufferCount) | 179 if (!m_nBufferCount) |
272 { | 180 { |
273 #ifndef MODPLUG_FASTSOUNDLIB | 181 if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) |
274 if (m_dwSongFlags & SONG_FADINGSONG) | 182 m_nBufferCount = lRead; |
275 { | 183 if (!ReadNote()) { |
276 m_dwSongFlags |= SONG_ENDREACHED; | 184 m_dwSongFlags |= SONG_ENDREACHED; |
277 m_nBufferCount = lRead; | 185 if (lRead == lMax) goto MixDone; |
278 } else | 186 if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) |
279 #endif | |
280 if (!ReadNote()) | |
281 { | |
282 #ifndef MODPLUG_FASTSOUNDLIB | |
283 if (!FadeSong(FADESONGDELAY)) | |
284 #endif | |
285 { | |
286 m_dwSongFlags |= SONG_ENDREACHED; | |
287 if (lRead == lMax) goto MixDone; | |
288 m_nBufferCount = lRead; | 187 m_nBufferCount = lRead; |
289 } | 188 } |
290 } | 189 if (!m_nBufferCount) goto MixDone; |
291 } | 190 } |
292 lCount = m_nBufferCount; | 191 lCount = m_nBufferCount; |
293 if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; | 192 if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; |
294 if (lCount > lRead) lCount = lRead; | 193 if (lCount > lRead) lCount = lRead; |
295 if (!lCount) break; | 194 if (!lCount) break; |
296 lSampleCount = lCount; | 195 lSampleCount = lCount; |
297 #ifndef MODPLUG_NO_REVERB | 196 #ifndef MODPLUG_NO_REVERB |
298 gnReverbSend = 0; | 197 gnReverbSend = 0; |
299 #endif | 198 #endif |
199 | |
300 // Resetting sound buffer | 200 // Resetting sound buffer |
301 X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); | 201 StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); |
302 if (gnChannels >= 2) | 202 if (gnChannels >= 2) |
303 { | 203 { |
304 lSampleCount *= 2; | 204 lSampleCount *= 2; |
305 m_nMixStat += CreateStereoMix(lCount); | 205 m_nMixStat += CreateStereoMix(lCount); |
206 #if 0 | |
207 if (nMaxPlugins) ProcessPlugins(lCount); | |
208 #endif | |
306 ProcessStereoDSP(lCount); | 209 ProcessStereoDSP(lCount); |
307 } else | 210 } else |
308 { | 211 { |
309 m_nMixStat += CreateStereoMix(lCount); | 212 m_nMixStat += CreateStereoMix(lCount); |
310 ProcessStereoDSP(lCount); | 213 #if 0 |
311 X86_MonoFromStereo(MixSoundBuffer, lCount); | 214 if (nMaxPlugins) ProcessPlugins(lCount); |
312 } | 215 #endif |
216 MonoFromStereo(MixSoundBuffer, lCount); | |
217 ProcessMonoDSP(lCount); | |
218 } | |
219 | |
220 if (gdwSoundSetup & SNDMIX_EQ) | |
221 { | |
222 if (gnChannels >= 2) | |
223 EQStereo(MixSoundBuffer, lCount); | |
224 else | |
225 EQMono(MixSoundBuffer, lCount); | |
226 } | |
227 | |
228 | |
313 nStat++; | 229 nStat++; |
314 #ifndef NO_AGC | 230 #ifndef NO_AGC |
315 // Automatic Gain Control | 231 // Automatic Gain Control |
316 if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount); | 232 if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount); |
317 #endif | 233 #endif |
318 UINT lTotalSampleCount = lSampleCount; | 234 lTotalSampleCount = lSampleCount; |
319 #ifndef MODPLUG_FASTSOUNDLIB | |
320 // Multichannel | 235 // Multichannel |
321 if (gnChannels > 2) | 236 if (gnChannels > 2) |
322 { | 237 { |
323 X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); | 238 InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); |
324 lTotalSampleCount *= 2; | 239 lTotalSampleCount *= 2; |
325 } | 240 } |
326 // Hook Function | 241 // Hook Function |
327 if (gpSndMixHook) | 242 if (gpSndMixHook) |
328 { | 243 { |
329 gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); | 244 gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); |
330 } | 245 } |
331 #endif | |
332 // Perform clipping + VU-Meter | 246 // Perform clipping + VU-Meter |
333 lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax); | 247 lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max); |
334 // Buffer ready | 248 // Buffer ready |
335 lRead -= lCount; | 249 lRead -= lCount; |
336 m_nBufferCount -= lCount; | 250 m_nBufferCount -= lCount; |
337 } | 251 } |
338 MixDone: | 252 MixDone: |
339 if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); | 253 if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); |
340 // VU-Meter | 254 // VU-Meter |
341 nVUMeterMin >>= (24-MIXING_ATTENUATION); | 255 vu_min[0] >>= 18; |
342 nVUMeterMax >>= (24-MIXING_ATTENUATION); | 256 vu_min[1] >>= 18; |
343 if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin; | 257 vu_max[0] >>= 18; |
344 if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF; | 258 vu_max[1] >>= 18; |
259 if (vu_max[0] < vu_min[0]) vu_max[0] = vu_min[0]; | |
260 if (vu_max[1] < vu_min[1]) vu_max[1] = vu_min[1]; | |
261 if ((gnVULeft = (UINT)(vu_max[0] - vu_min[0])) > 0xFF) | |
262 gnVULeft = 0xFF; | |
263 if ((gnVURight = (UINT)(vu_max[1] - vu_min[1])) > 0xFF) | |
264 gnVURight = 0xFF; | |
345 if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } | 265 if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } |
346 return lMax - lRead; | 266 return lMax - lRead; |
347 } | 267 } |
348 | 268 |
349 | 269 |
353 | 273 |
354 BOOL CSoundFile::ProcessRow() | 274 BOOL CSoundFile::ProcessRow() |
355 //--------------------------- | 275 //--------------------------- |
356 { | 276 { |
357 if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay) | 277 if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay) |
358 { | 278 { |
359 m_nPatternDelay = 0; | 279 m_nPatternDelay = 0; |
360 m_nFrameDelay = 0; | 280 m_nFrameDelay = 0; |
361 m_nTickCount = 0; | 281 m_nTickCount = 0; |
362 m_nRow = m_nNextRow; | 282 m_nRow = m_nNextRow; |
283 | |
363 // Reset Pattern Loop Effect | 284 // Reset Pattern Loop Effect |
364 if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern; | 285 if (m_nCurrentPattern != m_nNextPattern) { |
365 // Check if pattern is valid | 286 if (m_nLockedPattern < MAX_ORDERS) { |
366 if (!(m_dwSongFlags & SONG_PATTERNLOOP)) | 287 m_nCurrentPattern = m_nLockedPattern; |
367 { | 288 if (!(m_dwSongFlags & SONG_ORDERLOCKED)) |
368 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; | 289 m_nLockedPattern = MAX_ORDERS; |
369 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; | 290 } else { |
370 while (m_nPattern >= MAX_PATTERNS) | 291 m_nCurrentPattern = m_nNextPattern; |
371 { | 292 } |
372 // End of song ? | 293 |
373 if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) | 294 // Check if pattern is valid |
374 { | 295 if (!(m_dwSongFlags & SONG_PATTERNLOOP)) |
375 //if (!m_nRepeatCount) | 296 { |
376 return FALSE; //never repeat entire song | |
377 if (!m_nRestartPos) | |
378 { | |
379 m_nMusicSpeed = m_nDefaultSpeed; | |
380 m_nMusicTempo = m_nDefaultTempo; | |
381 m_nGlobalVolume = m_nDefaultGlobalVolume; | |
382 for (UINT i=0; i<MAX_CHANNELS; i++) | |
383 { | |
384 Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF; | |
385 Chn[i].nFadeOutVol = 0; | |
386 if (i < m_nChannels) | |
387 { | |
388 Chn[i].nGlobalVol = ChnSettings[i].nVolume; | |
389 Chn[i].nVolume = ChnSettings[i].nVolume; | |
390 Chn[i].nPan = ChnSettings[i].nPan; | |
391 Chn[i].nPanSwing = Chn[i].nVolSwing = 0; | |
392 Chn[i].nOldVolParam = 0; | |
393 Chn[i].nOldOffset = 0; | |
394 Chn[i].nOldHiOffset = 0; | |
395 Chn[i].nPortamentoDest = 0; | |
396 if (!Chn[i].nLength) | |
397 { | |
398 Chn[i].dwFlags = ChnSettings[i].dwFlags; | |
399 Chn[i].nLoopStart = 0; | |
400 Chn[i].nLoopEnd = 0; | |
401 Chn[i].pHeader = NULL; | |
402 Chn[i].pSample = NULL; | |
403 Chn[i].pInstrument = NULL; | |
404 } | |
405 } | |
406 } | |
407 } | |
408 // if (m_nRepeatCount > 0) m_nRepeatCount--; | |
409 m_nCurrentPattern = m_nRestartPos; | |
410 m_nRow = 0; | |
411 if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE; | |
412 } else | |
413 { | |
414 m_nCurrentPattern++; | |
415 } | |
416 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; | 297 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; |
417 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; | 298 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; |
418 } | 299 while (m_nPattern >= MAX_PATTERNS) |
419 m_nNextPattern = m_nCurrentPattern; | 300 { |
301 // End of song ? | |
302 if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) | |
303 { | |
304 if (m_nRepeatCount > 0) m_nRepeatCount--; | |
305 if (!m_nRepeatCount) return FALSE; | |
306 m_nCurrentPattern = m_nRestartPos; | |
307 if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) | |
308 || (!Patterns[Order[m_nCurrentPattern]])) | |
309 return FALSE; | |
310 } else { | |
311 m_nCurrentPattern++; | |
312 } | |
313 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; | |
314 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; | |
315 } | |
316 m_nNextPattern = m_nCurrentPattern; | |
317 } else if (m_nCurrentPattern < 255) { | |
318 if (m_nRepeatCount > 0) m_nRepeatCount--; | |
319 if (!m_nRepeatCount) return FALSE; | |
320 } | |
321 } | |
322 #ifdef MODPLUG_TRACKER | |
323 if (m_dwSongFlags & SONG_STEP) | |
324 { | |
325 m_dwSongFlags &= ~SONG_STEP; | |
326 m_dwSongFlags |= SONG_PAUSED; | |
327 } | |
328 #endif // MODPLUG_TRACKER | |
329 if (!PatternSize[m_nPattern] || !Patterns[m_nPattern]) { | |
330 /* okay, this is wrong. allocate the pattern _NOW_ */ | |
331 Patterns[m_nPattern] = AllocatePattern(64,64); | |
332 PatternSize[m_nPattern] = 64; | |
333 PatternAllocSize[m_nPattern] = 64; | |
420 } | 334 } |
421 // Weird stuff? | 335 // Weird stuff? |
422 if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE; | 336 if (m_nPattern >= MAX_PATTERNS) return FALSE; |
423 // Should never happen | 337 // Should never happen |
338 // ... sure it should: suppose there's a C70 effect before a 64-row pattern. | |
339 // It's in fact very easy to make this happen ;) | |
340 // - chisel | |
424 if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0; | 341 if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0; |
425 m_nNextRow = m_nRow + 1; | 342 m_nNextRow = m_nRow + 1; |
426 if (m_nNextRow >= PatternSize[m_nPattern]) | 343 if (m_nNextRow >= PatternSize[m_nPattern]) |
427 { | 344 { |
428 if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1; | 345 if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1; |
346 else if (m_nRepeatCount > 0) return FALSE; | |
429 m_nNextRow = 0; | 347 m_nNextRow = 0; |
430 } | 348 } |
431 // Reset channel values | 349 // Reset channel values |
432 MODCHANNEL *pChn = Chn; | 350 MODCHANNEL *pChn = Chn; |
433 MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; | 351 MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; |
434 for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++) | 352 for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++) |
435 { | 353 { |
354 /* skip realtime copyin */ | |
355 if (pChn->nRealtime) continue; | |
356 | |
357 // this is where we're going to spit out our midi | |
358 // commands... ALL WE DO is dump raw midi data to | |
359 // our super-secret "midi buffer" | |
360 // -mrsb | |
361 if (_midi_out_note) | |
362 _midi_out_note(nChn, m); | |
363 | |
436 pChn->nRowNote = m->note; | 364 pChn->nRowNote = m->note; |
365 if (m->instr) pChn->nLastInstr = m->instr; | |
437 pChn->nRowInstr = m->instr; | 366 pChn->nRowInstr = m->instr; |
438 pChn->nRowVolCmd = m->volcmd; | 367 pChn->nRowVolCmd = m->volcmd; |
439 pChn->nRowVolume = m->vol; | 368 pChn->nRowVolume = m->vol; |
440 pChn->nRowCommand = m->command; | 369 pChn->nRowCommand = m->command; |
441 pChn->nRowParam = m->param; | 370 pChn->nRowParam = m->param; |
442 | 371 |
443 pChn->nLeftVol = pChn->nNewLeftVol; | 372 pChn->nLeftVol = pChn->nNewLeftVol; |
444 pChn->nRightVol = pChn->nNewRightVol; | 373 pChn->nRightVol = pChn->nNewRightVol; |
445 pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO); | 374 pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO); |
446 pChn->nCommand = 0; | 375 pChn->nCommand = 0; |
376 } | |
377 | |
378 } else if (_midi_out_note) { | |
379 MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; | |
380 for (UINT nChn=0; nChn<m_nChannels; nChn++, m++) | |
381 { | |
382 /* m==NULL allows schism to receive notification of SDx and Scx commands */ | |
383 _midi_out_note(nChn, 0); | |
447 } | 384 } |
448 } | 385 } |
449 // Should we process tick0 effects? | 386 // Should we process tick0 effects? |
450 if (!m_nMusicSpeed) m_nMusicSpeed = 1; | 387 if (!m_nMusicSpeed) m_nMusicSpeed = 1; |
451 m_dwSongFlags |= SONG_FIRSTTICK; | 388 m_dwSongFlags |= SONG_FIRSTTICK; |
467 // Handles envelopes & mixer setup | 404 // Handles envelopes & mixer setup |
468 | 405 |
469 BOOL CSoundFile::ReadNote() | 406 BOOL CSoundFile::ReadNote() |
470 //------------------------- | 407 //------------------------- |
471 { | 408 { |
472 if (!ProcessRow()) return FALSE; | 409 // Checking end of row ? |
410 if (m_dwSongFlags & SONG_PAUSED) | |
411 { | |
412 /*m_nTickCount = 0;*/ | |
413 if (!m_nMusicSpeed) m_nMusicSpeed = 6; | |
414 if (!m_nMusicTempo) m_nMusicTempo = 125; | |
415 m_nPatternDelay = 0; | |
416 m_nFrameDelay = 0; | |
417 | |
418 m_dwSongFlags |= SONG_FIRSTTICK; | |
419 if (m_nTickCount) { | |
420 m_dwSongFlags &= ~SONG_FIRSTTICK; | |
421 } | |
422 | |
423 ProcessEffects(); | |
424 m_nTickCount++; | |
425 if (m_nTickCount >= m_nMusicSpeed) { | |
426 m_nTickCount = 0; | |
427 } | |
428 if (!ProcessEffects()) return FALSE; | |
429 } else | |
430 { | |
431 if (!ProcessRow()) return FALSE; | |
432 } | |
433 | |
434 { /* handle realtime closures */ | |
435 MODCHANNEL *pChn = Chn; | |
436 for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++) { | |
437 /* reset end of "row" */ | |
438 if (pChn->nRealtime && pChn->nRowNote && (pChn->nTickStart % m_nMusicSpeed) == (m_nTickCount % m_nMusicSpeed)) { | |
439 pChn->nRealtime = 0; | |
440 pChn->nRowNote = 0; | |
441 pChn->nRowInstr = 0; | |
442 //pChn->nMaster | |
443 pChn->nRowVolCmd = 0; | |
444 pChn->nRowVolume = 0; | |
445 pChn->nRowCommand = 0; | |
446 pChn->nRowParam = 0; | |
447 pChn->nTickStart = 0; | |
448 } | |
449 } | |
450 }; | |
451 | |
473 //////////////////////////////////////////////////////////////////////////////////// | 452 //////////////////////////////////////////////////////////////////////////////////// |
474 m_nTotalCount++; | 453 m_nTotalCount++; |
475 if (!m_nMusicTempo) return FALSE; | 454 if (!m_nMusicTempo) return FALSE; |
476 m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); | 455 m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); |
456 #ifdef MODPLUG_TRACKER | |
457 if (m_dwSongFlags & SONG_PAUSED) | |
458 { | |
459 m_nBufferCount = gdwMixingFreq / 64; // 1/64 seconds | |
460 } | |
461 #endif | |
462 | |
477 // Master Volume + Pre-Amplification / Attenuation setup | 463 // Master Volume + Pre-Amplification / Attenuation setup |
478 DWORD nMasterVol; | 464 DWORD nMasterVol; |
479 { | 465 { |
480 int nchn32 = (m_nChannels < 32) ? m_nChannels : 31; | 466 int nchn32 = 0; |
481 if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6; | 467 MODCHANNEL *pChn = Chn; |
468 for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++) { | |
469 nchn32++; | |
470 } | |
471 if (nchn32 < 1) nchn32 = 1; | |
472 if (nchn32 > 31) nchn32 = 31; | |
473 | |
482 int realmastervol = m_nMasterVolume; | 474 int realmastervol = m_nMasterVolume; |
483 if (realmastervol > 0x80) | 475 if (realmastervol > 0x80) |
484 { | 476 { |
485 realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; | 477 realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; |
486 } | 478 } |
479 | |
480 DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 6; | |
481 // if (mastervol > 0x200) mastervol = 0x200; | |
482 if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples)) | |
483 { | |
484 mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples); | |
485 } | |
486 | |
487 UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; | 487 UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; |
488 DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6; | 488 if (attenuation < 1) attenuation = 1; |
489 if (mastervol > 0x200) mastervol = 0x200; | 489 |
490 if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples)) | |
491 { | |
492 mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples); | |
493 } | |
494 nMasterVol = (mastervol << 7) / attenuation; | 490 nMasterVol = (mastervol << 7) / attenuation; |
495 if (nMasterVol > 0x180) nMasterVol = 0x180; | 491 if (nMasterVol > 0x180) nMasterVol = 0x180; |
496 } | 492 } |
497 //////////////////////////////////////////////////////////////////////////////////// | 493 //////////////////////////////////////////////////////////////////////////////////// |
498 // Update channels data | 494 // Update channels data |
495 if (CSoundFile::gdwSoundSetup & SNDMIX_NOMIXING) return TRUE; | |
499 m_nMixChannels = 0; | 496 m_nMixChannels = 0; |
500 MODCHANNEL *pChn = Chn; | 497 MODCHANNEL *pChn = Chn; |
501 for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++) | 498 for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++) |
502 { | 499 { |
503 if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol))) | 500 if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol))) |
504 { | 501 { |
505 pChn->nLength = 0; | 502 pChn->nLength = 0; |
506 pChn->nROfs = pChn->nLOfs = 0; | 503 pChn->nROfs = pChn->nLOfs = 0; |
507 } | 504 } |
508 // Check for unused channel | 505 // Check for unused channel |
509 if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength))) | 506 if ((nChn >= m_nChannels) && (!pChn->nLength)) |
510 { | 507 { |
511 pChn->nVUMeter = 0; | |
512 #ifdef ENABLE_STEREOVU | |
513 pChn->nLeftVU = pChn->nRightVU = 0; | 508 pChn->nLeftVU = pChn->nRightVU = 0; |
514 #endif | |
515 continue; | 509 continue; |
516 } | 510 } |
517 // Reset channel data | 511 // Reset channel data |
518 pChn->nInc = 0; | 512 pChn->nInc = 0; |
519 pChn->nRealVolume = 0; | 513 pChn->nRealVolume = 0; |
573 // Clip volume | 567 // Clip volume |
574 if (vol < 0) vol = 0; | 568 if (vol < 0) vol = 0; |
575 if (vol > 0x100) vol = 0x100; | 569 if (vol > 0x100) vol = 0x100; |
576 vol <<= 6; | 570 vol <<= 6; |
577 // Process Envelopes | 571 // Process Envelopes |
578 if (pChn->pHeader) | 572 if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) |
579 { | 573 { |
580 INSTRUMENTHEADER *penv = pChn->pHeader; | 574 INSTRUMENTHEADER *penv = pChn->pHeader; |
581 // Volume Envelope | 575 // Volume Envelope |
582 if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv)) | 576 if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes)) |
583 { | 577 { |
584 int envpos = pChn->nVolEnvPosition; | 578 int envpos = pChn->nVolEnvPosition; |
585 UINT pt = penv->nVolEnv - 1; | 579 UINT pt = penv->VolEnv.nNodes - 1; |
586 for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++) | 580 for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++) |
587 { | 581 { |
588 if (envpos <= penv->VolPoints[i]) | 582 if (envpos <= penv->VolEnv.Ticks[i]) |
589 { | 583 { |
590 pt = i; | 584 pt = i; |
591 break; | 585 break; |
592 } | 586 } |
593 } | 587 } |
594 int x2 = penv->VolPoints[pt]; | 588 int x2 = penv->VolEnv.Ticks[pt]; |
595 int x1, envvol; | 589 int x1, envvol; |
596 if (envpos >= x2) | 590 if (envpos >= x2) |
597 { | 591 { |
598 envvol = penv->VolEnv[pt] << 2; | 592 envvol = penv->VolEnv.Values[pt] << 2; |
599 x1 = x2; | 593 x1 = x2; |
600 } else | 594 } else |
601 if (pt) | 595 if (pt) |
602 { | 596 { |
603 envvol = penv->VolEnv[pt-1] << 2; | 597 envvol = penv->VolEnv.Values[pt-1] << 2; |
604 x1 = penv->VolPoints[pt-1]; | 598 x1 = penv->VolEnv.Ticks[pt-1]; |
605 } else | 599 } else |
606 { | 600 { |
607 envvol = 0; | 601 envvol = 0; |
608 x1 = 0; | 602 x1 = 0; |
609 } | 603 } |
610 if (envpos > x2) envpos = x2; | 604 if (envpos > x2) envpos = x2; |
611 if ((x2 > x1) && (envpos > x1)) | 605 if ((x2 > x1) && (envpos > x1)) |
612 { | 606 { |
613 envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1); | 607 envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[pt]<<2) - envvol)) / (x2 - x1); |
614 } | 608 } |
615 if (envvol < 0) envvol = 0; | 609 if (envvol < 0) envvol = 0; |
616 if (envvol > 256) envvol = 256; | 610 if (envvol > 256) envvol = 256; |
617 vol = (vol * envvol) >> 8; | 611 vol = (vol * envvol) >> 8; |
618 } | 612 } |
619 // Panning Envelope | 613 // Panning Envelope |
620 if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv)) | 614 if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes)) |
621 { | 615 { |
622 int envpos = pChn->nPanEnvPosition; | 616 int envpos = pChn->nPanEnvPosition; |
623 UINT pt = penv->nPanEnv - 1; | 617 UINT pt = penv->PanEnv.nNodes - 1; |
624 for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++) | 618 for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++) |
625 { | 619 { |
626 if (envpos <= penv->PanPoints[i]) | 620 if (envpos <= penv->PanEnv.Ticks[i]) |
627 { | 621 { |
628 pt = i; | 622 pt = i; |
629 break; | 623 break; |
630 } | 624 } |
631 } | 625 } |
632 int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt]; | 626 int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt]; |
633 int x1, envpan; | 627 int x1, envpan; |
634 if (envpos >= x2) | 628 if (envpos >= x2) |
635 { | 629 { |
636 envpan = y2; | 630 envpan = y2; |
637 x1 = x2; | 631 x1 = x2; |
638 } else | 632 } else |
639 if (pt) | 633 if (pt) |
640 { | 634 { |
641 envpan = penv->PanEnv[pt-1]; | 635 envpan = penv->PanEnv.Values[pt-1]; |
642 x1 = penv->PanPoints[pt-1]; | 636 x1 = penv->PanEnv.Ticks[pt-1]; |
643 } else | 637 } else |
644 { | 638 { |
645 envpan = 128; | 639 envpan = 128; |
646 x1 = 0; | 640 x1 = 0; |
647 } | 641 } |
712 // Arpeggio ? | 706 // Arpeggio ? |
713 if (pChn->nCommand == CMD_ARPEGGIO) | 707 if (pChn->nCommand == CMD_ARPEGGIO) |
714 { | 708 { |
715 switch(m_nTickCount % 3) | 709 switch(m_nTickCount % 3) |
716 { | 710 { |
711 #if 0 | |
717 case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; | 712 case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; |
718 case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; | 713 case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; |
714 #else | |
715 case 1: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; | |
716 case 2: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; | |
717 #endif | |
719 } | 718 } |
720 } | 719 } |
721 | 720 |
722 if (m_dwSongFlags & SONG_AMIGALIMITS) | 721 if (m_dwSongFlags & SONG_AMIGALIMITS) |
723 { | 722 { |
724 if (period < 113*4) period = 113*4; | 723 if (period < 113*4) period = 113*4; |
725 if (period > 856*4) period = 856*4; | 724 if (period > 856*4) period = 856*4; |
726 } | 725 } |
727 | 726 |
728 // Pitch/Filter Envelope | 727 // Pitch/Filter Envelope |
729 if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv)) | 728 int envpitch = 0; |
729 if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) | |
730 && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes)) | |
730 { | 731 { |
731 INSTRUMENTHEADER *penv = pChn->pHeader; | 732 INSTRUMENTHEADER *penv = pChn->pHeader; |
732 int envpos = pChn->nPitchEnvPosition; | 733 int envpos = pChn->nPitchEnvPosition; |
733 UINT pt = penv->nPitchEnv - 1; | 734 UINT pt = penv->PitchEnv.nNodes - 1; |
734 for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++) | 735 for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++) |
735 { | 736 { |
736 if (envpos <= penv->PitchPoints[i]) | 737 if (envpos <= penv->PitchEnv.Ticks[i]) |
737 { | 738 { |
738 pt = i; | 739 pt = i; |
739 break; | 740 break; |
740 } | 741 } |
741 } | 742 } |
742 int x2 = penv->PitchPoints[pt]; | 743 int x2 = penv->PitchEnv.Ticks[pt]; |
743 int x1, envpitch; | 744 int x1; |
744 if (envpos >= x2) | 745 if (envpos >= x2) |
745 { | 746 { |
746 envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8; | 747 envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; |
747 x1 = x2; | 748 x1 = x2; |
748 } else | 749 } else |
749 if (pt) | 750 if (pt) |
750 { | 751 { |
751 envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8; | 752 envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8; |
752 x1 = penv->PitchPoints[pt-1]; | 753 x1 = penv->PitchEnv.Ticks[pt-1]; |
753 } else | 754 } else |
754 { | 755 { |
755 envpitch = 0; | 756 envpitch = 0; |
756 x1 = 0; | 757 x1 = 0; |
757 } | 758 } |
758 if (envpos > x2) envpos = x2; | 759 if (envpos > x2) envpos = x2; |
759 if ((x2 > x1) && (envpos > x1)) | 760 if ((x2 > x1) && (envpos > x1)) |
760 { | 761 { |
761 int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8; | 762 int envpitchdest = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; |
762 envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); | 763 envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); |
763 } | 764 } |
764 if (envpitch < -256) envpitch = -256; | 765 if (envpitch < -256) envpitch = -256; |
765 if (envpitch > 256) envpitch = 256; | 766 if (envpitch > 256) envpitch = 256; |
766 // Filter Envelope: controls cutoff frequency | |
767 if (penv->dwFlags & ENV_FILTER) | |
768 { | |
769 #ifndef NO_FILTER | |
770 SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); | |
771 #endif // NO_FILTER | |
772 } else | |
773 // Pitch Envelope | 767 // Pitch Envelope |
768 if (!(penv->dwFlags & ENV_FILTER)) | |
774 { | 769 { |
775 int l = envpitch; | 770 int l = envpitch; |
776 if (l < 0) | 771 if (l < 0) |
777 { | 772 { |
778 l = -l; | 773 l = -l; |
858 int nPeriodFrac = 0; | 853 int nPeriodFrac = 0; |
859 // Instrument Auto-Vibrato | 854 // Instrument Auto-Vibrato |
860 if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth)) | 855 if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth)) |
861 { | 856 { |
862 MODINSTRUMENT *pins = pChn->pInstrument; | 857 MODINSTRUMENT *pins = pChn->pInstrument; |
858 /* this isn't correct, but its better... */ | |
859 | |
860 if (pins->nVibSweep == 0) { | |
861 pChn->nAutoVibDepth = pins->nVibDepth << 8; | |
862 } else { | |
863 pChn->nAutoVibDepth += pins->nVibSweep; | |
864 if ((pChn->nAutoVibDepth >> 8) > (int)pins->nVibDepth) | |
865 pChn->nAutoVibDepth = pins->nVibDepth << 8; | |
866 } | |
867 #if 0 | |
863 if (pins->nVibSweep == 0) | 868 if (pins->nVibSweep == 0) |
864 { | 869 { |
865 pChn->nAutoVibDepth = pins->nVibDepth << 8; | 870 pChn->nAutoVibDepth = pins->nVibDepth << 8; |
866 } else | 871 } else |
867 { | 872 { |
868 if (m_nType & MOD_TYPE_IT) | 873 if (m_nType & MOD_TYPE_IT) |
869 { | 874 { |
870 pChn->nAutoVibDepth += pins->nVibSweep << 3; | 875 pChn->nAutoVibDepth += pins->nVibSweep; |
871 } else | 876 } else |
872 if (!(pChn->dwFlags & CHN_KEYOFF)) | 877 if (!(pChn->dwFlags & CHN_KEYOFF)) |
873 { | 878 { |
874 pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep; | 879 pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep; |
875 } | 880 } |
876 if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) | 881 if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) |
877 pChn->nAutoVibDepth = pins->nVibDepth << 8; | 882 pChn->nAutoVibDepth = pins->nVibDepth << 8; |
878 } | 883 } |
879 pChn->nAutoVibPos += pins->nVibRate; | 884 #endif |
885 pChn->nAutoVibPos += ((int)pins->nVibRate); | |
880 int val; | 886 int val; |
881 switch(pins->nVibType) | 887 switch(pins->nVibType) |
882 { | 888 { |
883 case 4: // Random | 889 case 4: // Random |
884 val = ModRandomTable[pChn->nAutoVibPos & 0x3F]; | 890 val = ModRandomTable[pChn->nAutoVibPos & 0x3F]; |
895 break; | 901 break; |
896 default: // Sine | 902 default: // Sine |
897 val = ft2VibratoTable[pChn->nAutoVibPos & 255]; | 903 val = ft2VibratoTable[pChn->nAutoVibPos & 255]; |
898 } | 904 } |
899 int n = ((val * pChn->nAutoVibDepth) >> 8); | 905 int n = ((val * pChn->nAutoVibDepth) >> 8); |
906 // is this right? -mrsb | |
907 if (!(m_dwSongFlags & SONG_ITOLDEFFECTS)) | |
908 n >>= 1; | |
909 | |
900 if (m_nType & MOD_TYPE_IT) | 910 if (m_nType & MOD_TYPE_IT) |
901 { | 911 { |
902 int df1, df2; | 912 int df1, df2; |
903 if (n < 0) | 913 if (n < 0) |
904 { | 914 { |
937 } | 947 } |
938 period = m_nMaxPeriod; | 948 period = m_nMaxPeriod; |
939 nPeriodFrac = 0; | 949 nPeriodFrac = 0; |
940 } | 950 } |
941 UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); | 951 UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); |
952 | |
953 // Filter Envelope: controls cutoff frequency | |
954 if (pChn && pChn->pHeader && pChn->pHeader->dwFlags & ENV_FILTER) | |
955 { | |
956 #ifndef NO_FILTER | |
957 SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); | |
958 #endif // NO_FILTER | |
959 } | |
960 | |
961 #if 0 | |
942 if ((m_nType & MOD_TYPE_IT) && (freq < 256)) | 962 if ((m_nType & MOD_TYPE_IT) && (freq < 256)) |
943 { | 963 { |
944 pChn->nFadeOutVol = 0; | 964 pChn->nFadeOutVol = 0; |
945 pChn->dwFlags |= CHN_NOTEFADE; | 965 pChn->dwFlags |= CHN_NOTEFADE; |
946 pChn->nRealVolume = 0; | 966 pChn->nRealVolume = 0; |
947 } | 967 } |
968 #endif | |
969 pChn->sample_freq = freq; | |
970 | |
948 UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq); | 971 UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq); |
949 if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000; | 972 if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000; |
950 if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7; | 973 if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7; |
951 if (ninc > 0xFF0000) ninc = 0xFF0000; | 974 if (ninc > 0xFF0000) ninc = 0xFF0000; |
952 pChn->nInc = (ninc+1) & ~3; | 975 pChn->nInc = (ninc+1) & ~3; |
953 } | 976 } |
954 | 977 |
955 // Increment envelope position | 978 // Increment envelope position |
956 if (pChn->pHeader) | 979 if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) |
957 { | 980 { |
958 INSTRUMENTHEADER *penv = pChn->pHeader; | 981 INSTRUMENTHEADER *penv = pChn->pHeader; |
959 // Volume Envelope | 982 // Volume Envelope |
960 if (pChn->dwFlags & CHN_VOLENV) | 983 if (pChn->dwFlags & CHN_VOLENV) |
961 { | 984 { |
962 // Increase position | 985 // Increase position |
963 pChn->nVolEnvPosition++; | 986 pChn->nVolEnvPosition++; |
964 // Volume Loop ? | 987 // Volume Loop ? |
965 if (penv->dwFlags & ENV_VOLLOOP) | 988 if (penv->dwFlags & ENV_VOLLOOP) |
966 { | 989 { |
967 UINT volloopend = penv->VolPoints[penv->nVolLoopEnd]; | 990 int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd]; |
968 if (m_nType != MOD_TYPE_XM) volloopend++; | 991 if (m_nType != MOD_TYPE_XM) volloopend++; |
969 if (pChn->nVolEnvPosition == volloopend) | 992 if (pChn->nVolEnvPosition == volloopend) |
970 { | 993 { |
971 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart]; | 994 pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nLoopStart]; |
972 if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart]) | 995 if ((penv->VolEnv.nLoopEnd == penv->VolEnv.nLoopStart) && (!penv->VolEnv.Values[penv->VolEnv.nLoopStart]) |
973 && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv))) | 996 && ((!(m_nType & MOD_TYPE_XM)) || (penv->VolEnv.nLoopEnd+1 == penv->VolEnv.nNodes))) |
974 { | 997 { |
975 pChn->dwFlags |= CHN_NOTEFADE; | 998 pChn->dwFlags |= CHN_NOTEFADE; |
976 pChn->nFadeOutVol = 0; | 999 pChn->nFadeOutVol = 0; |
977 } | 1000 } |
978 } | 1001 } |
979 } | 1002 } |
980 // Volume Sustain ? | 1003 // Volume Sustain ? |
981 if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) | 1004 if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) |
982 { | 1005 { |
983 if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1) | 1006 if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1) |
984 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin]; | 1007 pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart]; |
985 } else | 1008 } else |
986 // End of Envelope ? | 1009 // End of Envelope ? |
987 if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1]) | 1010 if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]) |
988 { | 1011 { |
989 if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; | 1012 if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; |
990 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1]; | 1013 pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]; |
991 if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) | 1014 if ((!penv->VolEnv.Values[penv->VolEnv.nNodes-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) |
992 { | 1015 { |
993 pChn->dwFlags |= CHN_NOTEFADE; | 1016 pChn->dwFlags |= CHN_NOTEFADE; |
994 pChn->nFadeOutVol = 0; | 1017 pChn->nFadeOutVol = 0; |
995 | 1018 |
996 pChn->nRealVolume = 0; | 1019 pChn->nRealVolume = 0; |
1001 if (pChn->dwFlags & CHN_PANENV) | 1024 if (pChn->dwFlags & CHN_PANENV) |
1002 { | 1025 { |
1003 pChn->nPanEnvPosition++; | 1026 pChn->nPanEnvPosition++; |
1004 if (penv->dwFlags & ENV_PANLOOP) | 1027 if (penv->dwFlags & ENV_PANLOOP) |
1005 { | 1028 { |
1006 UINT panloopend = penv->PanPoints[penv->nPanLoopEnd]; | 1029 int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd]; |
1007 if (m_nType != MOD_TYPE_XM) panloopend++; | 1030 if (m_nType != MOD_TYPE_XM) panloopend++; |
1008 if (pChn->nPanEnvPosition == panloopend) | 1031 if (pChn->nPanEnvPosition == panloopend) |
1009 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart]; | 1032 pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart]; |
1010 } | 1033 } |
1011 // Panning Sustain ? | 1034 // Panning Sustain ? |
1012 if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1) | 1035 if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1) |
1013 && (!(pChn->dwFlags & CHN_KEYOFF))) | 1036 && (!(pChn->dwFlags & CHN_KEYOFF))) |
1014 { | 1037 { |
1015 // Panning sustained | 1038 // Panning sustained |
1016 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin]; | 1039 pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart]; |
1017 } else | 1040 } else |
1018 { | 1041 { |
1019 if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1]) | 1042 if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]) |
1020 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1]; | 1043 pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]; |
1021 } | 1044 } |
1022 } | 1045 } |
1023 // Pitch Envelope | 1046 // Pitch Envelope |
1024 if (pChn->dwFlags & CHN_PITCHENV) | 1047 if (pChn->dwFlags & CHN_PITCHENV) |
1025 { | 1048 { |
1026 // Increase position | 1049 // Increase position |
1027 pChn->nPitchEnvPosition++; | 1050 pChn->nPitchEnvPosition++; |
1028 // Pitch Loop ? | 1051 // Pitch Loop ? |
1029 if (penv->dwFlags & ENV_PITCHLOOP) | 1052 if (penv->dwFlags & ENV_PITCHLOOP) |
1030 { | 1053 { |
1031 if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd]) | 1054 if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd]) |
1032 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart]; | 1055 pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart]; |
1033 } | 1056 } |
1034 // Pitch Sustain ? | 1057 // Pitch Sustain ? |
1035 if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) | 1058 if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) |
1036 { | 1059 { |
1037 if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1) | 1060 if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1) |
1038 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin]; | 1061 pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart]; |
1039 } else | 1062 } else |
1040 { | 1063 { |
1041 if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1]) | 1064 if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]) |
1042 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1]; | 1065 pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]; |
1043 } | 1066 } |
1044 } | 1067 } |
1045 } | 1068 } |
1046 #ifdef MODPLUG_PLAYER | 1069 #if 0 |
1047 // Limit CPU -> > 80% -> don't ramp | 1070 // Limit CPU -> > 80% -> don't ramp |
1048 if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) | 1071 if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) |
1049 { | 1072 { |
1050 pChn->nLeftVol = pChn->nRightVol = 0; | 1073 pChn->nLeftVol = pChn->nRightVol = 0; |
1051 } | 1074 } |
1052 #endif // MODPLUG_PLAYER | 1075 #endif // MODPLUG_PLAYER |
1053 // Volume ramping | 1076 // Volume ramping |
1054 pChn->dwFlags &= ~CHN_VOLUMERAMP; | 1077 pChn->dwFlags &= ~CHN_VOLUMERAMP; |
1055 if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol)) | 1078 if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol)) |
1056 pChn->dwFlags |= CHN_VOLUMERAMP; | 1079 pChn->dwFlags |= CHN_VOLUMERAMP; |
1057 #ifdef MODPLUG_PLAYER | |
1058 // Decrease VU-Meter | 1080 // Decrease VU-Meter |
1059 if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0; | 1081 if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0; |
1060 #endif // MODPLUG_PLAYER | |
1061 #ifdef ENABLE_STEREOVU | |
1062 if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0; | 1082 if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0; |
1063 if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0; | 1083 if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0; |
1064 #endif | |
1065 // Check for too big nInc | 1084 // Check for too big nInc |
1066 if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP; | 1085 if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP; |
1067 pChn->nNewRightVol = pChn->nNewLeftVol = 0; | 1086 pChn->nNewRightVol = pChn->nNewLeftVol = 0; |
1068 pChn->pCurrentSample = ((pChn->pSample) && (pChn->nLength) && (pChn->nInc)) ? pChn->pSample : NULL; | 1087 pChn->pCurrentSample = ((pChn->pSample) && (pChn->nLength) && (pChn->nInc)) ? pChn->pSample : NULL; |
1069 if (pChn->pCurrentSample) | 1088 if (pChn->pCurrentSample) |
1070 { | 1089 { |
1071 // Update VU-Meter (nRealVolume is 14-bit) | 1090 // Update VU-Meter (nRealVolume is 14-bit) |
1072 #ifdef MODPLUG_PLAYER | |
1073 UINT vutmp = pChn->nRealVolume >> (14 - 8); | 1091 UINT vutmp = pChn->nRealVolume >> (14 - 8); |
1074 if (vutmp > 0xFF) vutmp = 0xFF; | 1092 if (vutmp > 0xFF) vutmp = 0xFF; |
1075 if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp; | 1093 if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp; |
1076 vutmp >>= 1; | 1094 vutmp >>= 1; |
1077 if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp; | 1095 if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp; |
1078 #endif // MODPLUG_PLAYER | |
1079 #ifdef ENABLE_STEREOVU | |
1080 UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14; | 1096 UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14; |
1081 if (vul > 127) vul = 127; | 1097 if (vul > 127) vul = 127; |
1082 if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul; | 1098 if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul; |
1083 vul >>= 1; | 1099 vul >>= 1; |
1084 if (pChn->nLeftVU < vul) pChn->nLeftVU = (BYTE)vul; | 1100 if (pChn->nLeftVU < vul) pChn->nLeftVU = (BYTE)vul; |
1085 UINT vur = (pChn->nRealVolume * (256-pChn->nRealPan)) >> 14; | 1101 UINT vur = (pChn->nRealVolume * (256-pChn->nRealPan)) >> 14; |
1086 if (vur > 127) vur = 127; | 1102 if (vur > 127) vur = 127; |
1087 if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur; | 1103 if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur; |
1088 vur >>= 1; | 1104 vur >>= 1; |
1089 if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur; | 1105 if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur; |
1090 #endif | |
1091 #ifdef MODPLUG_TRACKER | 1106 #ifdef MODPLUG_TRACKER |
1092 UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol; | 1107 UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol; |
1093 #else | 1108 #else |
1094 #define kChnMasterVol nMasterVol | 1109 #define kChnMasterVol nMasterVol |
1095 #endif // MODPLUG_TRACKER | 1110 #endif // MODPLUG_TRACKER |
1101 pan /= 128; | 1116 pan /= 128; |
1102 pan += 128; | 1117 pan += 128; |
1103 | 1118 |
1104 if (pan < 0) pan = 0; | 1119 if (pan < 0) pan = 0; |
1105 if (pan > 256) pan = 256; | 1120 if (pan > 256) pan = 256; |
1106 #ifndef MODPLUG_FASTSOUNDLIB | |
1107 if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; | 1121 if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; |
1108 #endif | 1122 if (m_dwSongFlags & SONG_NOSTEREO) pan = 128; |
1109 LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); | 1123 LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); |
1110 if (gdwSoundSetup & SNDMIX_SOFTPANNING) | 1124 if (gdwSoundSetup & SNDMIX_SOFTPANNING) |
1111 { | 1125 { |
1112 if (pan < 128) | 1126 if (pan < 128) |
1113 { | 1127 { |
1132 if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF; | 1146 if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF; |
1133 if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF; | 1147 if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF; |
1134 // Check IDO | 1148 // Check IDO |
1135 if (gdwSoundSetup & SNDMIX_NORESAMPLING) | 1149 if (gdwSoundSetup & SNDMIX_NORESAMPLING) |
1136 { | 1150 { |
1151 pChn->dwFlags &= ~(CHN_HQSRC); | |
1137 pChn->dwFlags |= CHN_NOIDO; | 1152 pChn->dwFlags |= CHN_NOIDO; |
1138 } else | 1153 } else |
1139 { | 1154 { |
1140 pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC); | 1155 pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC); |
1141 if( pChn->nInc == 0x10000 ) | 1156 if( pChn->nInc == 0x10000 ) |
1149 } | 1164 } |
1150 pChn->nNewRightVol >>= MIXING_ATTENUATION; | 1165 pChn->nNewRightVol >>= MIXING_ATTENUATION; |
1151 pChn->nNewLeftVol >>= MIXING_ATTENUATION; | 1166 pChn->nNewLeftVol >>= MIXING_ATTENUATION; |
1152 pChn->nRightRamp = pChn->nLeftRamp = 0; | 1167 pChn->nRightRamp = pChn->nLeftRamp = 0; |
1153 // Dolby Pro-Logic Surround | 1168 // Dolby Pro-Logic Surround |
1154 if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol; | 1169 if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0) |
1170 pChn->nNewLeftVol = -pChn->nNewLeftVol; | |
1155 // Checking Ping-Pong Loops | 1171 // Checking Ping-Pong Loops |
1156 if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; | 1172 if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; |
1157 // Setting up volume ramp | 1173 // Setting up volume ramp |
1158 if ((pChn->dwFlags & CHN_VOLUMERAMP) | 1174 if (!(gdwSoundSetup & SNDMIX_NORAMPING) |
1175 && (pChn->dwFlags & CHN_VOLUMERAMP) | |
1159 && ((pChn->nRightVol != pChn->nNewRightVol) | 1176 && ((pChn->nRightVol != pChn->nNewRightVol) |
1160 || (pChn->nLeftVol != pChn->nNewLeftVol))) | 1177 || (pChn->nLeftVol != pChn->nNewLeftVol))) |
1161 { | 1178 { |
1162 LONG nRampLength = gnVolumeRampSamples; | 1179 LONG nRampLength = gnVolumeRampSamples; |
1163 LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION); | 1180 LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION); |
1164 LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION); | 1181 LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION); |
1165 #ifndef MODPLUG_FASTSOUNDLIB | 1182 #if 0 |
1166 if ((gdwSoundSetup & SNDMIX_DIRECTTODISK) | 1183 if ((gdwSoundSetup & SNDMIX_DIRECTTODISK) |
1167 || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU)) | 1184 || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU)) |
1168 && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20))) | 1185 && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20))) |
1186 #else | |
1187 if (gdwSoundSetup & SNDMIX_HQRESAMPLER) | |
1188 #endif | |
1169 { | 1189 { |
1170 if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP))) | 1190 if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP))) |
1171 { | 1191 { |
1172 nRampLength = m_nBufferCount; | 1192 nRampLength = m_nBufferCount; |
1173 if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1)); | 1193 if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1)); |
1174 if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; | 1194 if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; |
1175 } | 1195 } |
1176 } | 1196 } |
1177 #endif | |
1178 pChn->nRightRamp = nRightDelta / nRampLength; | 1197 pChn->nRightRamp = nRightDelta / nRampLength; |
1179 pChn->nLeftRamp = nLeftDelta / nRampLength; | 1198 pChn->nLeftRamp = nLeftDelta / nRampLength; |
1180 pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); | 1199 pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); |
1181 pChn->nLeftVol = pChn->nNewLeftVol - ((pChn->nLeftRamp * nRampLength) >> VOLUMERAMPPRECISION); | 1200 pChn->nLeftVol = pChn->nNewLeftVol - ((pChn->nLeftRamp * nRampLength) >> VOLUMERAMPPRECISION); |
1182 if (pChn->nRightRamp|pChn->nLeftRamp) | 1201 if (pChn->nRightRamp|pChn->nLeftRamp) |
1195 pChn->nLeftVol = pChn->nNewLeftVol; | 1214 pChn->nLeftVol = pChn->nNewLeftVol; |
1196 } | 1215 } |
1197 pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; | 1216 pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; |
1198 pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; | 1217 pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; |
1199 // Adding the channel in the channel list | 1218 // Adding the channel in the channel list |
1200 ChnMix[m_nMixChannels++] = nChn; | 1219 if (!(pChn->dwFlags & CHN_MUTE)) { |
1201 if (m_nMixChannels >= MAX_CHANNELS) break; | 1220 ChnMix[m_nMixChannels++] = nChn; |
1221 if (m_nMixChannels >= MAX_CHANNELS) break; | |
1222 } | |
1202 } else | 1223 } else |
1203 { | 1224 { |
1204 #ifdef ENABLE_STEREOVU | |
1205 // Note change but no sample | 1225 // Note change but no sample |
1206 if (pChn->nLeftVU > 128) pChn->nLeftVU = 0; | 1226 if (pChn->nLeftVU > 128) pChn->nLeftVU = 0; |
1207 if (pChn->nRightVU > 128) pChn->nRightVU = 0; | 1227 if (pChn->nRightVU > 128) pChn->nRightVU = 0; |
1208 #endif | |
1209 if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0; | 1228 if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0; |
1210 pChn->nLeftVol = pChn->nRightVol = 0; | 1229 pChn->nLeftVol = pChn->nRightVol = 0; |
1211 pChn->nLength = 0; | 1230 pChn->nLength = 0; |
1212 } | 1231 } |
1213 } | 1232 } |