Diffstat (limited to 'core/multimedia/opieplayer/modplug/sndfile.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/sndfile.cpp | 1875 |
1 files changed, 1875 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/sndfile.cpp b/core/multimedia/opieplayer/modplug/sndfile.cpp new file mode 100644 index 0000000..1d0d610 --- a/dev/null +++ b/core/multimedia/opieplayer/modplug/sndfile.cpp | |||
@@ -0,0 +1,1875 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2 of the license or (at your | ||
5 | * option) any later version. | ||
6 | * | ||
7 | * Authors: Olivier Lapicque <olivierl@jps.net>, | ||
8 | * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC) | ||
9 | */ | ||
10 | |||
11 | #include <math.h> //for GCCFIX | ||
12 | #include "stdafx.h" | ||
13 | #include "sndfile.h" | ||
14 | |||
15 | #define MMCMP_SUPPORT | ||
16 | |||
17 | #ifdef MMCMP_SUPPORT | ||
18 | extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength); | ||
19 | #endif | ||
20 | |||
21 | // External decompressors | ||
22 | extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter); | ||
23 | extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); | ||
24 | extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen); | ||
25 | extern DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n); | ||
26 | extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); | ||
27 | extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215); | ||
28 | |||
29 | |||
30 | #define MAX_PACK_TABLES 3 | ||
31 | |||
32 | |||
33 | // Compression table | ||
34 | static const signed char UnpackTable[MAX_PACK_TABLES][16] = | ||
35 | //-------------------------------------------- | ||
36 | { | ||
37 | // CPU-generated dynamic table | ||
38 | {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, | ||
39 | // u-Law table | ||
40 | {0, 1, 2, 4, 8, 16, 32, 64, | ||
41 | -1, -2, -4, -8, -16, -32, -48, -64}, | ||
42 | // Linear table | ||
43 | {0, 1, 2, 3, 5, 7, 12, 19, | ||
44 | -1, -2, -3, -5, -7, -12, -19, -31} | ||
45 | }; | ||
46 | |||
47 | |||
48 | ////////////////////////////////////////////////////////// | ||
49 | // CSoundFile | ||
50 | |||
51 | CSoundFile::CSoundFile() | ||
52 | //---------------------- | ||
53 | { | ||
54 | m_nType = MOD_TYPE_NONE; | ||
55 | m_dwSongFlags = 0; | ||
56 | m_nChannels = 0; | ||
57 | m_nMixChannels = 0; | ||
58 | m_nSamples = 0; | ||
59 | m_nInstruments = 0; | ||
60 | m_nPatternNames = 0; | ||
61 | m_lpszPatternNames = NULL; | ||
62 | m_lpszSongComments = NULL; | ||
63 | m_nFreqFactor = m_nTempoFactor = 128; | ||
64 | m_nMasterVolume = 128; | ||
65 | m_nMinPeriod = 0x20; | ||
66 | m_nMaxPeriod = 0x7FFF; | ||
67 | m_nRepeatCount = 0; | ||
68 | memset(Chn, 0, sizeof(Chn)); | ||
69 | memset(ChnMix, 0, sizeof(ChnMix)); | ||
70 | memset(Ins, 0, sizeof(Ins)); | ||
71 | memset(ChnSettings, 0, sizeof(ChnSettings)); | ||
72 | memset(Headers, 0, sizeof(Headers)); | ||
73 | memset(Order, 0xFF, sizeof(Order)); | ||
74 | memset(Patterns, 0, sizeof(Patterns)); | ||
75 | memset(m_szNames, 0, sizeof(m_szNames)); | ||
76 | memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); | ||
77 | } | ||
78 | |||
79 | |||
80 | CSoundFile::~CSoundFile() | ||
81 | //----------------------- | ||
82 | { | ||
83 | Destroy(); | ||
84 | } | ||
85 | |||
86 | |||
87 | BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength) | ||
88 | //---------------------------------------------------------- | ||
89 | { | ||
90 | int i; | ||
91 | |||
92 | m_nType = MOD_TYPE_NONE; | ||
93 | m_dwSongFlags = 0; | ||
94 | m_nChannels = 0; | ||
95 | m_nMixChannels = 0; | ||
96 | m_nSamples = 0; | ||
97 | m_nInstruments = 0; | ||
98 | m_nFreqFactor = m_nTempoFactor = 128; | ||
99 | m_nMasterVolume = 128; | ||
100 | m_nDefaultGlobalVolume = 256; | ||
101 | m_nGlobalVolume = 256; | ||
102 | m_nOldGlbVolSlide = 0; | ||
103 | m_nDefaultSpeed = 6; | ||
104 | m_nDefaultTempo = 125; | ||
105 | m_nPatternDelay = 0; | ||
106 | m_nFrameDelay = 0; | ||
107 | m_nNextRow = 0; | ||
108 | m_nRow = 0; | ||
109 | m_nPattern = 0; | ||
110 | m_nCurrentPattern = 0; | ||
111 | m_nNextPattern = 0; | ||
112 | m_nRestartPos = 0; | ||
113 | m_nMinPeriod = 16; | ||
114 | m_nMaxPeriod = 32767; | ||
115 | m_nSongPreAmp = 0x30; | ||
116 | m_nPatternNames = 0; | ||
117 | m_nMaxOrderPosition = 0; | ||
118 | m_lpszPatternNames = NULL; | ||
119 | m_lpszSongComments = NULL; | ||
120 | memset(Ins, 0, sizeof(Ins)); | ||
121 | memset(ChnMix, 0, sizeof(ChnMix)); | ||
122 | memset(Chn, 0, sizeof(Chn)); | ||
123 | memset(Headers, 0, sizeof(Headers)); | ||
124 | memset(Order, 0xFF, sizeof(Order)); | ||
125 | memset(Patterns, 0, sizeof(Patterns)); | ||
126 | memset(m_szNames, 0, sizeof(m_szNames)); | ||
127 | memset(m_MixPlugins, 0, sizeof(m_MixPlugins)); | ||
128 | ResetMidiCfg(); | ||
129 | for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64; | ||
130 | for (UINT nch=0; nch<MAX_BASECHANNELS; nch++) | ||
131 | { | ||
132 | ChnSettings[nch].nPan = 128; | ||
133 | ChnSettings[nch].nVolume = 64; | ||
134 | ChnSettings[nch].dwFlags = 0; | ||
135 | ChnSettings[nch].szName[0] = 0; | ||
136 | } | ||
137 | if (lpStream) | ||
138 | { | ||
139 | #ifdef MMCMP_SUPPORT | ||
140 | BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength); | ||
141 | #endif | ||
142 | if ((!ReadXM(lpStream, dwMemLength)) | ||
143 | && (!ReadIT(lpStream, dwMemLength)) | ||
144 | && (!ReadS3M(lpStream, dwMemLength)) | ||
145 | // && (!ReadWav(lpStream, dwMemLength)) | ||
146 | #ifndef MODPLUG_BASIC_SUPPORT | ||
147 | && (!ReadSTM(lpStream, dwMemLength)) | ||
148 | && (!ReadMed(lpStream, dwMemLength)) | ||
149 | && (!ReadMTM(lpStream, dwMemLength)) | ||
150 | && (!ReadMDL(lpStream, dwMemLength)) | ||
151 | && (!ReadDBM(lpStream, dwMemLength)) | ||
152 | && (!Read669(lpStream, dwMemLength)) | ||
153 | && (!ReadFAR(lpStream, dwMemLength)) | ||
154 | && (!ReadAMS(lpStream, dwMemLength)) | ||
155 | && (!ReadOKT(lpStream, dwMemLength)) | ||
156 | && (!ReadPTM(lpStream, dwMemLength)) | ||
157 | && (!ReadUlt(lpStream, dwMemLength)) | ||
158 | && (!ReadDMF(lpStream, dwMemLength)) | ||
159 | && (!ReadDSM(lpStream, dwMemLength)) | ||
160 | && (!ReadUMX(lpStream, dwMemLength)) | ||
161 | && (!ReadAMF(lpStream, dwMemLength)) | ||
162 | && (!ReadPSM(lpStream, dwMemLength)) | ||
163 | && (!ReadMT2(lpStream, dwMemLength)) | ||
164 | #endif // MODPLUG_BASIC_SUPPORT | ||
165 | && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE; | ||
166 | #ifdef MMCMP_SUPPORT | ||
167 | if (bMMCmp) | ||
168 | { | ||
169 | GlobalFreePtr(lpStream); | ||
170 | lpStream = NULL; | ||
171 | } | ||
172 | #endif | ||
173 | } | ||
174 | // Adjust song names | ||
175 | for (i=0; i<MAX_SAMPLES; i++) | ||
176 | { | ||
177 | LPSTR p = m_szNames[i]; | ||
178 | int j = 31; | ||
179 | p[j] = 0; | ||
180 | while ((j>=0) && (p[j]<=' ')) p[j--] = 0; | ||
181 | while (j>=0) | ||
182 | { | ||
183 | if (((BYTE)p[j]) < ' ') p[j] = ' '; | ||
184 | j--; | ||
185 | } | ||
186 | } | ||
187 | // Adjust channels | ||
188 | for (i=0; i<MAX_BASECHANNELS; i++) | ||
189 | { | ||
190 | if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64; | ||
191 | if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128; | ||
192 | Chn[i].nPan = ChnSettings[i].nPan; | ||
193 | Chn[i].nGlobalVol = ChnSettings[i].nVolume; | ||
194 | Chn[i].dwFlags = ChnSettings[i].dwFlags; | ||
195 | Chn[i].nVolume = 256; | ||
196 | Chn[i].nCutOff = 0x7F; | ||
197 | } | ||
198 | // Checking instruments | ||
199 | MODINSTRUMENT *pins = Ins; | ||
200 | |||
201 | for (i=0; i<MAX_INSTRUMENTS; i++, pins++) | ||
202 | { | ||
203 | if (pins->pSample) | ||
204 | { | ||
205 | if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength; | ||
206 | if (pins->nLoopStart + 3 >= pins->nLoopEnd) | ||
207 | { | ||
208 | pins->nLoopStart = 0; | ||
209 | pins->nLoopEnd = 0; | ||
210 | } | ||
211 | if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength; | ||
212 | if (pins->nSustainStart + 3 >= pins->nSustainEnd) | ||
213 | { | ||
214 | pins->nSustainStart = 0; | ||
215 | pins->nSustainEnd = 0; | ||
216 | } | ||
217 | } else | ||
218 | { | ||
219 | pins->nLength = 0; | ||
220 | pins->nLoopStart = 0; | ||
221 | pins->nLoopEnd = 0; | ||
222 | pins->nSustainStart = 0; | ||
223 | pins->nSustainEnd = 0; | ||
224 | } | ||
225 | if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP; | ||
226 | if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP; | ||
227 | if (pins->nGlobalVol > 64) pins->nGlobalVol = 64; | ||
228 | } | ||
229 | // Check invalid instruments | ||
230 | while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--; | ||
231 | // Set default values | ||
232 | if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20; | ||
233 | if (m_nDefaultTempo < 32) m_nDefaultTempo = 125; | ||
234 | if (!m_nDefaultSpeed) m_nDefaultSpeed = 6; | ||
235 | m_nMusicSpeed = m_nDefaultSpeed; | ||
236 | m_nMusicTempo = m_nDefaultTempo; | ||
237 | m_nGlobalVolume = m_nDefaultGlobalVolume; | ||
238 | m_nNextPattern = 0; | ||
239 | m_nCurrentPattern = 0; | ||
240 | m_nPattern = 0; | ||
241 | m_nBufferCount = 0; | ||
242 | m_nTickCount = m_nMusicSpeed; | ||
243 | m_nNextRow = 0; | ||
244 | m_nRow = 0; | ||
245 | if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0; | ||
246 | // Load plugins | ||
247 | if (gpMixPluginCreateProc) | ||
248 | { | ||
249 | for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++) | ||
250 | { | ||
251 | if ((m_MixPlugins[iPlug].Info.dwPluginId1) | ||
252 | || (m_MixPlugins[iPlug].Info.dwPluginId2)) | ||
253 | { | ||
254 | gpMixPluginCreateProc(&m_MixPlugins[iPlug]); | ||
255 | if (m_MixPlugins[iPlug].pMixPlugin) | ||
256 | { | ||
257 | m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters(); | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | if (m_nType) | ||
263 | { | ||
264 | UINT maxpreamp = 0x10+(m_nChannels*8); | ||
265 | if (maxpreamp > 100) maxpreamp = 100; | ||
266 | if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp; | ||
267 | return TRUE; | ||
268 | } | ||
269 | return FALSE; | ||
270 | } | ||
271 | |||
272 | |||
273 | BOOL CSoundFile::Destroy() | ||
274 | |||
275 | //------------------------ | ||
276 | { | ||
277 | int i; | ||
278 | for (i=0; i<MAX_PATTERNS; i++) if (Patterns[i]) | ||
279 | { | ||
280 | FreePattern(Patterns[i]); | ||
281 | Patterns[i] = NULL; | ||
282 | } | ||
283 | m_nPatternNames = 0; | ||
284 | if (m_lpszPatternNames) | ||
285 | { | ||
286 | delete m_lpszPatternNames; | ||
287 | m_lpszPatternNames = NULL; | ||
288 | } | ||
289 | if (m_lpszSongComments) | ||
290 | { | ||
291 | delete m_lpszSongComments; | ||
292 | m_lpszSongComments = NULL; | ||
293 | } | ||
294 | for (i=1; i<MAX_SAMPLES; i++) | ||
295 | { | ||
296 | MODINSTRUMENT *pins = &Ins[i]; | ||
297 | if (pins->pSample) | ||
298 | { | ||
299 | FreeSample(pins->pSample); | ||
300 | pins->pSample = NULL; | ||
301 | } | ||
302 | } | ||
303 | for (i=0; i<MAX_INSTRUMENTS; i++) | ||
304 | { | ||
305 | if (Headers[i]) | ||
306 | { | ||
307 | delete Headers[i]; | ||
308 | Headers[i] = NULL; | ||
309 | } | ||
310 | } | ||
311 | for (i=0; i<MAX_MIXPLUGINS; i++) | ||
312 | { | ||
313 | if ((m_MixPlugins[i].nPluginDataSize) && (m_MixPlugins[i].pPluginData)) | ||
314 | { | ||
315 | m_MixPlugins[i].nPluginDataSize = 0; | ||
316 | delete [] (signed char*)m_MixPlugins[i].pPluginData; | ||
317 | m_MixPlugins[i].pPluginData = NULL; | ||
318 | } | ||
319 | m_MixPlugins[i].pMixState = NULL; | ||
320 | if (m_MixPlugins[i].pMixPlugin) | ||
321 | { | ||
322 | m_MixPlugins[i].pMixPlugin->Release(); | ||
323 | m_MixPlugins[i].pMixPlugin = NULL; | ||
324 | } | ||
325 | } | ||
326 | m_nType = MOD_TYPE_NONE; | ||
327 | m_nChannels = m_nSamples = m_nInstruments = 0; | ||
328 | return TRUE; | ||
329 | } | ||
330 | |||
331 | |||
332 | ////////////////////////////////////////////////////////////////////////// | ||
333 | // Memory Allocation | ||
334 | |||
335 | MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns) | ||
336 | //------------------------------------------------------------ | ||
337 | { | ||
338 | MODCOMMAND *p = new MODCOMMAND[rows*nchns]; | ||
339 | if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND)); | ||
340 | return p; | ||
341 | } | ||
342 | |||
343 | |||
344 | void CSoundFile::FreePattern(LPVOID pat) | ||
345 | //-------------------------------------- | ||
346 | { | ||
347 | if (pat) delete [] (signed char*)pat; | ||
348 | } | ||
349 | |||
350 | |||
351 | signed char* CSoundFile::AllocateSample(UINT nbytes) | ||
352 | //------------------------------------------- | ||
353 | { | ||
354 | signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7); | ||
355 | if (p) p += 16; | ||
356 | return p; | ||
357 | } | ||
358 | |||
359 | |||
360 | void CSoundFile::FreeSample(LPVOID p) | ||
361 | //----------------------------------- | ||
362 | { | ||
363 | if (p) | ||
364 | { | ||
365 | GlobalFreePtr(((LPSTR)p)-16); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | |||
370 | ////////////////////////////////////////////////////////////////////////// | ||
371 | // Misc functions | ||
372 | |||
373 | void CSoundFile::ResetMidiCfg() | ||
374 | //----------------------------- | ||
375 | { | ||
376 | memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); | ||
377 | lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF"); | ||
378 | lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC"); | ||
379 | lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v"); | ||
380 | lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0"); | ||
381 | lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); | ||
382 | lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); | ||
383 | for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8); | ||
384 | } | ||
385 | |||
386 | |||
387 | UINT CSoundFile::GetNumChannels() const | ||
388 | //------------------------------------- | ||
389 | { | ||
390 | UINT n = 0; | ||
391 | for (UINT i=0; i<m_nChannels; i++) if (ChnSettings[i].nVolume) n++; | ||
392 | return n; | ||
393 | } | ||
394 | |||
395 | |||
396 | UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize) | ||
397 | //---------------------------------------------------------------- | ||
398 | { | ||
399 | LPCSTR p = m_lpszSongComments; | ||
400 | if (!p) return 0; | ||
401 | UINT i = 2, ln=0; | ||
402 | if ((len) && (s)) s[0] = '\x0D'; | ||
403 | if ((len > 1) && (s)) s[1] = '\x0A'; | ||
404 | while ((*p)&& (i+2 < len)) | ||
405 | { | ||
406 | BYTE c = (BYTE)*p++; | ||
407 | if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) | ||
408 | { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } | ||
409 | else | ||
410 | if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } | ||
411 | } | ||
412 | if (s) s[i] = 0; | ||
413 | return i; | ||
414 | } | ||
415 | |||
416 | |||
417 | UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize) | ||
418 | //------------------------------------------------------------------- | ||
419 | { | ||
420 | LPCSTR p = m_lpszSongComments; | ||
421 | if (!p) return 0; | ||
422 | UINT i = 0, ln=0; | ||
423 | while ((*p)&& (i < len-1)) | ||
424 | { | ||
425 | BYTE c = (BYTE)*p++; | ||
426 | if ((c == 0x0D)|| (c == 0x0A)) | ||
427 | { | ||
428 | if (ln) | ||
429 | { | ||
430 | while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } | ||
431 | ln = 0; | ||
432 | } | ||
433 | } else | ||
434 | if ((c == ' ') && (!ln)) | ||
435 | { | ||
436 | UINT k=0; | ||
437 | while ((p[k]) && (p[k] >= ' '))k++; | ||
438 | if (k <= linesize) | ||
439 | { | ||
440 | if (s) s[i] = ' '; | ||
441 | i++; | ||
442 | ln++; | ||
443 | } | ||
444 | } else | ||
445 | { | ||
446 | if (s) s[i] = c; | ||
447 | i++; | ||
448 | ln++; | ||
449 | if (ln == linesize) ln = 0; | ||
450 | } | ||
451 | } | ||
452 | if (ln) | ||
453 | { | ||
454 | while ((ln < linesize) && (i < len)) | ||
455 | { | ||
456 | if (s) s[i] = ' '; | ||
457 | i++; | ||
458 | ln++; | ||
459 | } | ||
460 | } | ||
461 | if (s) s[i] = 0; | ||
462 | return i; | ||
463 | } | ||
464 | |||
465 | |||
466 | BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) | ||
467 | //---------------------------------------------------------------------------- | ||
468 | { | ||
469 | BOOL bReset = FALSE; | ||
470 | DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX; | ||
471 | if (bMMX) d |= SNDMIX_ENABLEMMX; | ||
472 | if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE; | ||
473 | gnChannels = nChannels; | ||
474 | gdwSoundSetup = d; | ||
475 | gdwMixingFreq = nRate; | ||
476 | gnBitsPerSample = nBits; | ||
477 | InitPlayer(bReset); | ||
478 | return TRUE; | ||
479 | } | ||
480 | |||
481 | |||
482 | BOOL CSoundFile::SetResamplingMode(UINT nMode) | ||
483 | //-------------------------------------------- | ||
484 | { | ||
485 | DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); | ||
486 | switch(nMode) | ||
487 | { | ||
488 | case SRCMODE_NEAREST:d |= SNDMIX_NORESAMPLING; break; | ||
489 | case SRCMODE_LINEAR:break; | ||
490 | case SRCMODE_SPLINE:d |= SNDMIX_HQRESAMPLER; break; | ||
491 | case SRCMODE_POLYPHASE:d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break; | ||
492 | default: | ||
493 | return FALSE; | ||
494 | } | ||
495 | gdwSoundSetup = d; | ||
496 | return TRUE; | ||
497 | } | ||
498 | |||
499 | |||
500 | BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC) | ||
501 | //---------------------------------------------------------- | ||
502 | { | ||
503 | if (nVol < 1) nVol = 1; | ||
504 | if (nVol > 0x200) nVol = 0x200;// x4 maximum | ||
505 | if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC)) | ||
506 | { | ||
507 | gnAGC = gnAGC * m_nMasterVolume / nVol; | ||
508 | if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY; | ||
509 | } | ||
510 | m_nMasterVolume = nVol; | ||
511 | return TRUE; | ||
512 | } | ||
513 | |||
514 | |||
515 | void CSoundFile::SetAGC(BOOL b) | ||
516 | //----------------------------- | ||
517 | { | ||
518 | if (b) | ||
519 | { | ||
520 | if (!(gdwSoundSetup & SNDMIX_AGC)) | ||
521 | { | ||
522 | gdwSoundSetup |= SNDMIX_AGC; | ||
523 | gnAGC = AGC_UNITY; | ||
524 | } | ||
525 | } else gdwSoundSetup &= ~SNDMIX_AGC; | ||
526 | } | ||
527 | |||
528 | |||
529 | UINT CSoundFile::GetNumPatterns() const | ||
530 | //------------------------------------- | ||
531 | { | ||
532 | UINT i = 0; | ||
533 | while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++; | ||
534 | return i; | ||
535 | } | ||
536 | |||
537 | |||
538 | UINT CSoundFile::GetNumInstruments() const | ||
539 | //---------------------------------------- | ||
540 | { | ||
541 | UINT n=0; | ||
542 | for (UINT i=0; i<MAX_INSTRUMENTS; i++) if (Ins[i].pSample) n++; | ||
543 | return n; | ||
544 | } | ||
545 | |||
546 | |||
547 | UINT CSoundFile::GetMaxPosition() const | ||
548 | //------------------------------------- | ||
549 | { | ||
550 | UINT max = 0; | ||
551 | UINT i = 0; | ||
552 | |||
553 | while ((i < MAX_ORDERS) && (Order[i] != 0xFF)) | ||
554 | { | ||
555 | if (Order[i] < MAX_PATTERNS) max += PatternSize[Order[i]]; | ||
556 | i++; | ||
557 | } | ||
558 | return max; | ||
559 | } | ||
560 | |||
561 | |||
562 | UINT CSoundFile::GetCurrentPos() const | ||
563 | //------------------------------------ | ||
564 | { | ||
565 | UINT pos = 0; | ||
566 | |||
567 | for (UINT i=0; i<m_nCurrentPattern; i++) if (Order[i] < MAX_PATTERNS) | ||
568 | pos += PatternSize[Order[i]]; | ||
569 | return pos + m_nRow; | ||
570 | } | ||
571 | |||
572 | |||
573 | void CSoundFile::SetCurrentPos(UINT nPos) | ||
574 | //--------------------------------------- | ||
575 | { | ||
576 | UINT i, nPattern; | ||
577 | |||
578 | for (i=0; i<MAX_CHANNELS; i++) | ||
579 | { | ||
580 | Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0; | ||
581 | Chn[i].pInstrument = NULL; | ||
582 | Chn[i].pHeader = NULL; | ||
583 | Chn[i].nPortamentoDest = 0; | ||
584 | Chn[i].nCommand = 0; | ||
585 | Chn[i].nPatternLoopCount = 0; | ||
586 | Chn[i].nPatternLoop = 0; | ||
587 | Chn[i].nFadeOutVol = 0; | ||
588 | Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE; | ||
589 | Chn[i].nTremorCount = 0; | ||
590 | } | ||
591 | if (!nPos) | ||
592 | { | ||
593 | for (i=0; i<MAX_CHANNELS; i++) | ||
594 | { | ||
595 | Chn[i].nPeriod = 0; | ||
596 | Chn[i].nPos = Chn[i].nLength = 0; | ||
597 | Chn[i].nLoopStart = 0; | ||
598 | Chn[i].nLoopEnd = 0; | ||
599 | Chn[i].nROfs = Chn[i].nLOfs = 0; | ||
600 | Chn[i].pSample = NULL; | ||
601 | Chn[i].pInstrument = NULL; | ||
602 | Chn[i].pHeader = NULL; | ||
603 | Chn[i].nCutOff = 0x7F; | ||
604 | Chn[i].nResonance = 0; | ||
605 | Chn[i].nLeftVol = Chn[i].nRightVol = 0; | ||
606 | Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0; | ||
607 | Chn[i].nLeftRamp = Chn[i].nRightRamp = 0; | ||
608 | Chn[i].nVolume = 256; | ||
609 | if (i < MAX_BASECHANNELS) | ||
610 | { | ||
611 | Chn[i].dwFlags = ChnSettings[i].dwFlags; | ||
612 | Chn[i].nPan = ChnSettings[i].nPan; | ||
613 | Chn[i].nGlobalVol = ChnSettings[i].nVolume; | ||
614 | } else | ||
615 | { | ||
616 | Chn[i].dwFlags = 0; | ||
617 | Chn[i].nPan = 128; | ||
618 | Chn[i].nGlobalVol = 64; | ||
619 | } | ||
620 | } | ||
621 | m_nGlobalVolume = m_nDefaultGlobalVolume; | ||
622 | m_nMusicSpeed = m_nDefaultSpeed; | ||
623 | m_nMusicTempo = m_nDefaultTempo; | ||
624 | } | ||
625 | m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); | ||
626 | for (nPattern = 0; nPattern < MAX_ORDERS; nPattern++) | ||
627 | { | ||
628 | UINT ord = Order[nPattern]; | ||
629 | if (ord == 0xFE) continue; | ||
630 | if (ord == 0xFF) break; | ||
631 | if (ord < MAX_PATTERNS) | ||
632 | { | ||
633 | if (nPos < (UINT)PatternSize[ord]) break; | ||
634 | nPos -= PatternSize[ord]; | ||
635 | } | ||
636 | } | ||
637 | // Buggy position ? | ||
638 | if ((nPattern >= MAX_ORDERS) | ||
639 | || (Order[nPattern] >= MAX_PATTERNS) | ||
640 | || (nPos >= PatternSize[Order[nPattern]])) | ||
641 | { | ||
642 | nPos = 0; | ||
643 | nPattern = 0; | ||
644 | } | ||
645 | UINT nRow = nPos; | ||
646 | if ((nRow) && (Order[nPattern] < MAX_PATTERNS)) | ||
647 | { | ||
648 | MODCOMMAND *p = Patterns[Order[nPattern]]; | ||
649 | if ((p) && (nRow < PatternSize[Order[nPattern]])) | ||
650 | { | ||
651 | BOOL bOk = FALSE; | ||
652 | while ((!bOk) && (nRow > 0)) | ||
653 | { | ||
654 | UINT n = nRow * m_nChannels; | ||
655 | for (UINT k=0; k<m_nChannels; k++, n++) | ||
656 | { | ||
657 | if (p[n].note) | ||
658 | { | ||
659 | bOk = TRUE; | ||
660 | break; | ||
661 | } | ||
662 | } | ||
663 | if (!bOk) nRow--; | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | m_nNextPattern = nPattern; | ||
668 | m_nNextRow = nRow; | ||
669 | m_nTickCount = m_nMusicSpeed; | ||
670 | m_nBufferCount = 0; | ||
671 | m_nPatternDelay = 0; | ||
672 | m_nFrameDelay = 0; | ||
673 | } | ||
674 | |||
675 | |||
676 | void CSoundFile::SetCurrentOrder(UINT nPos) | ||
677 | //----------------------------------------- | ||
678 | { | ||
679 | while ((nPos < MAX_ORDERS) && (Order[nPos] == 0xFE)) nPos++; | ||
680 | if ((nPos >= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return; | ||
681 | for (UINT j=0; j<MAX_CHANNELS; j++) | ||
682 | { | ||
683 | Chn[j].nPeriod = 0; | ||
684 | Chn[j].nNote = 0; | ||
685 | Chn[j].nPortamentoDest = 0; | ||
686 | Chn[j].nCommand = 0; | ||
687 | Chn[j].nPatternLoopCount = 0; | ||
688 | Chn[j].nPatternLoop = 0; | ||
689 | Chn[j].nTremorCount = 0; | ||
690 | } | ||
691 | if (!nPos) | ||
692 | { | ||
693 | SetCurrentPos(0); | ||
694 | } else | ||
695 | { | ||
696 | m_nNextPattern = nPos; | ||
697 | m_nRow = m_nNextRow = 0; | ||
698 | m_nPattern = 0; | ||
699 | m_nTickCount = m_nMusicSpeed; | ||
700 | m_nBufferCount = 0; | ||
701 | m_nTotalCount = 0; | ||
702 | m_nPatternDelay = 0; | ||
703 | m_nFrameDelay = 0; | ||
704 | } | ||
705 | m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); | ||
706 | } | ||
707 | |||
708 | |||
709 | void CSoundFile::ResetChannels() | ||
710 | //------------------------------ | ||
711 | { | ||
712 | m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE); | ||
713 | m_nBufferCount = 0; | ||
714 | for (UINT i=0; i<MAX_CHANNELS; i++) | ||
715 | { | ||
716 | Chn[i].nROfs = Chn[i].nLOfs = 0; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | |||
721 | void CSoundFile::LoopPattern(int nPat, int nRow) | ||
722 | //---------------------------------------------- | ||
723 | { | ||
724 | if ((nPat < 0) || (nPat >= MAX_PATTERNS) || (!Patterns[nPat])) | ||
725 | { | ||
726 | m_dwSongFlags &= ~SONG_PATTERNLOOP; | ||
727 | } else | ||
728 | { | ||
729 | if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0; | ||
730 | m_nPattern = nPat; | ||
731 | m_nRow = m_nNextRow = nRow; | ||
732 | m_nTickCount = m_nMusicSpeed; | ||
733 | m_nPatternDelay = 0; | ||
734 | m_nFrameDelay = 0; | ||
735 | m_nBufferCount = 0; | ||
736 | m_dwSongFlags |= SONG_PATTERNLOOP; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | |||
741 | UINT CSoundFile::GetBestSaveFormat() const | ||
742 | //---------------------------------------- | ||
743 | { | ||
744 | if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE; | ||
745 | if (!m_nType) return MOD_TYPE_NONE; | ||
746 | if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT)) | ||
747 | return MOD_TYPE_MOD; | ||
748 | if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM)) | ||
749 | return MOD_TYPE_S3M; | ||
750 | if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2)) | ||
751 | return MOD_TYPE_XM; | ||
752 | return MOD_TYPE_IT; | ||
753 | } | ||
754 | |||
755 | |||
756 | UINT CSoundFile::GetSaveFormats() const | ||
757 | //------------------------------------- | ||
758 | { | ||
759 | UINT n = 0; | ||
760 | if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0; | ||
761 | switch(m_nType) | ||
762 | { | ||
763 | case MOD_TYPE_MOD:n = MOD_TYPE_MOD; | ||
764 | case MOD_TYPE_S3M:n = MOD_TYPE_S3M; | ||
765 | } | ||
766 | n |= MOD_TYPE_XM | MOD_TYPE_IT; | ||
767 | if (!m_nInstruments) | ||
768 | { | ||
769 | if (m_nSamples < 32) n |= MOD_TYPE_MOD; | ||
770 | n |= MOD_TYPE_S3M; | ||
771 | } | ||
772 | return n; | ||
773 | } | ||
774 | |||
775 | |||
776 | UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const | ||
777 | //-------------------------------------------------------- | ||
778 | { | ||
779 | char sztmp[40] = ""; // changed from CHAR | ||
780 | memcpy(sztmp, m_szNames[nSample],32); | ||
781 | sztmp[31] = 0; | ||
782 | if (s) strcpy(s, sztmp); | ||
783 | return strlen(sztmp); | ||
784 | } | ||
785 | |||
786 | |||
787 | UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const | ||
788 | //----------------------------------------------------------- | ||
789 | { | ||
790 | char sztmp[40] = ""; // changed from CHAR | ||
791 | if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr])) | ||
792 | { | ||
793 | if (s) *s = 0; | ||
794 | return 0; | ||
795 | } | ||
796 | INSTRUMENTHEADER *penv = Headers[nInstr]; | ||
797 | memcpy(sztmp, penv->name, 32); | ||
798 | sztmp[31] = 0; | ||
799 | if (s) strcpy(s, sztmp); | ||
800 | return strlen(sztmp); | ||
801 | } | ||
802 | |||
803 | |||
804 | #ifndef NO_PACKING | ||
805 | UINT CSoundFile::PackSample(int &sample, int next) | ||
806 | //------------------------------------------------ | ||
807 | { | ||
808 | UINT i = 0; | ||
809 | int delta = next - sample; | ||
810 | if (delta >= 0) | ||
811 | { | ||
812 | for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break; | ||
813 | } else | ||
814 | { | ||
815 | for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break; | ||
816 | } | ||
817 | sample += (int)CompressionTable[i]; | ||
818 | return i; | ||
819 | } | ||
820 | |||
821 | |||
822 | BOOL CSoundFile::CanPackSample(LPSTR pSample, UINT nLen, UINT nPacking, BYTE *result) | ||
823 | //----------------------------------------------------------------------------------- | ||
824 | { | ||
825 | int pos, old, oldpos, besttable = 0; | ||
826 | DWORD dwErr, dwTotal, dwResult; | ||
827 | int i,j; | ||
828 | |||
829 | if (result) *result = 0; | ||
830 | if ((!pSample) || (nLen < 1024)) return FALSE; | ||
831 | // Try packing with different tables | ||
832 | dwResult = 0; | ||
833 | for (j=1; j<MAX_PACK_TABLES; j++) | ||
834 | { | ||
835 | memcpy(CompressionTable, UnpackTable[j], 16); | ||
836 | dwErr = 0; | ||
837 | dwTotal = 1; | ||
838 | old = pos = oldpos = 0; | ||
839 | for (i=0; i<(int)nLen; i++) | ||
840 | { | ||
841 | int s = (int)pSample[i]; | ||
842 | PackSample(pos, s); | ||
843 | dwErr += abs(pos - oldpos); | ||
844 | dwTotal += abs(s - old); | ||
845 | old = s; | ||
846 | oldpos = pos; | ||
847 | } | ||
848 | dwErr = _muldiv(dwErr, 100, dwTotal); | ||
849 | if (dwErr >= dwResult) | ||
850 | { | ||
851 | dwResult = dwErr; | ||
852 | besttable = j; | ||
853 | } | ||
854 | } | ||
855 | memcpy(CompressionTable, UnpackTable[besttable], 16); | ||
856 | if (result) | ||
857 | { | ||
858 | if (dwResult > 100) *result= 100; else *result = (BYTE)dwResult; | ||
859 | } | ||
860 | return (dwResult >= nPacking) ? TRUE : FALSE; | ||
861 | } | ||
862 | #endif // NO_PACKING | ||
863 | |||
864 | #ifndef MODPLUG_NO_FILESAVE | ||
865 | |||
866 | UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen) | ||
867 | //----------------------------------------------------------------------------------- | ||
868 | { | ||
869 | UINT len = 0, bufcount; | ||
870 | signed char buffer[4096]; | ||
871 | signed char *pSample = (signed char *)pins->pSample; | ||
872 | UINT nLen = pins->nLength; | ||
873 | |||
874 | if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen; | ||
875 | if ((!pSample) || (f == NULL) || (!nLen)) return 0; | ||
876 | switch(nFlags) | ||
877 | { | ||
878 | #ifndef NO_PACKING | ||
879 | // 3: 4-bit ADPCM data | ||
880 | case RS_ADPCM4: | ||
881 | { | ||
882 | int pos; | ||
883 | len = (nLen + 1) / 2; | ||
884 | fwrite(CompressionTable, 16, 1, f); | ||
885 | bufcount = 0; | ||
886 | pos = 0; | ||
887 | for (UINT j=0; j<len; j++) | ||
888 | { | ||
889 | BYTE b; | ||
890 | // Sample #1 | ||
891 | b = PackSample(pos, (int)pSample[j*2]); | ||
892 | // Sample #2 | ||
893 | b |= PackSample(pos, (int)pSample[j*2+1]) << 4; | ||
894 | buffer[bufcount++] = (signed char)b; | ||
895 | if (bufcount >= sizeof(buffer)) | ||
896 | { | ||
897 | fwrite(buffer, 1, bufcount, f); | ||
898 | bufcount = 0; | ||
899 | } | ||
900 | } | ||
901 | if (bufcount) fwrite(buffer, 1, bufcount, f); | ||
902 | len += 16; | ||
903 | } | ||
904 | break; | ||
905 | #endif // NO_PACKING | ||
906 | |||
907 | // 16-bit samples | ||
908 | case RS_PCM16U: | ||
909 | case RS_PCM16D: | ||
910 | case RS_PCM16S: | ||
911 | { | ||
912 | short int *p = (short int *)pSample; | ||
913 | int s_old = 0, s_ofs; | ||
914 | len = nLen * 2; | ||
915 | bufcount = 0; | ||
916 | s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0; | ||
917 | for (UINT j=0; j<nLen; j++) | ||
918 | { | ||
919 | int s_new = *p; | ||
920 | p++; | ||
921 | if (pins->uFlags & CHN_STEREO) | ||
922 | { | ||
923 | s_new = (s_new + (*p) + 1) >> 1; | ||
924 | p++; | ||
925 | } | ||
926 | if (nFlags == RS_PCM16D) | ||
927 | { | ||
928 | *((short *)(&buffer[bufcount])) = (short)(s_new - s_old); | ||
929 | s_old = s_new; | ||
930 | } else | ||
931 | { | ||
932 | *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs); | ||
933 | } | ||
934 | bufcount += 2; | ||
935 | if (bufcount >= sizeof(buffer) - 1) | ||
936 | { | ||
937 | fwrite(buffer, 1, bufcount, f); | ||
938 | bufcount = 0; | ||
939 | } | ||
940 | } | ||
941 | if (bufcount) fwrite(buffer, 1, bufcount, f); | ||
942 | } | ||
943 | break; | ||
944 | |||
945 | |||
946 | // 8-bit Stereo samples (not interleaved) | ||
947 | case RS_STPCM8S: | ||
948 | case RS_STPCM8U: | ||
949 | case RS_STPCM8D: | ||
950 | { | ||
951 | int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0; | ||
952 | for (UINT iCh=0; iCh<2; iCh++) | ||
953 | { | ||
954 | signed char *p = pSample + iCh; | ||
955 | int s_old = 0; | ||
956 | |||
957 | bufcount = 0; | ||
958 | for (UINT j=0; j<nLen; j++) | ||
959 | { | ||
960 | int s_new = *p; | ||
961 | p += 2; | ||
962 | if (nFlags == RS_STPCM8D) | ||
963 | { | ||
964 | buffer[bufcount++] = (signed char)(s_new - s_old); | ||
965 | s_old = s_new; | ||
966 | } else | ||
967 | { | ||
968 | buffer[bufcount++] = (signed char)(s_new + s_ofs); | ||
969 | } | ||
970 | if (bufcount >= sizeof(buffer)) | ||
971 | { | ||
972 | fwrite(buffer, 1, bufcount, f); | ||
973 | bufcount = 0; | ||
974 | } | ||
975 | } | ||
976 | if (bufcount) fwrite(buffer, 1, bufcount, f); | ||
977 | } | ||
978 | } | ||
979 | len = nLen * 2; | ||
980 | break; | ||
981 | |||
982 | // 16-bit Stereo samples (not interleaved) | ||
983 | case RS_STPCM16S: | ||
984 | case RS_STPCM16U: | ||
985 | case RS_STPCM16D: | ||
986 | { | ||
987 | int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0; | ||
988 | for (UINT iCh=0; iCh<2; iCh++) | ||
989 | { | ||
990 | signed short *p = ((signed short *)pSample) + iCh; | ||
991 | int s_old = 0; | ||
992 | |||
993 | bufcount = 0; | ||
994 | for (UINT j=0; j<nLen; j++) | ||
995 | { | ||
996 | int s_new = *p; | ||
997 | p += 2; | ||
998 | if (nFlags == RS_STPCM16D) | ||
999 | { | ||
1000 | *((short *)(&buffer[bufcount])) = (short)(s_new - s_old); | ||
1001 | s_old = s_new; | ||
1002 | } else | ||
1003 | { | ||
1004 | *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs); | ||
1005 | } | ||
1006 | bufcount += 2; | ||
1007 | if (bufcount >= sizeof(buffer)) | ||
1008 | { | ||
1009 | fwrite(buffer, 1, bufcount, f); | ||
1010 | bufcount = 0; | ||
1011 | } | ||
1012 | } | ||
1013 | if (bufcount) fwrite(buffer, 1, bufcount, f); | ||
1014 | } | ||
1015 | } | ||
1016 | len = nLen*4; | ||
1017 | break; | ||
1018 | |||
1019 | //Stereo signed interleaved | ||
1020 | case RS_STIPCM8S: | ||
1021 | case RS_STIPCM16S: | ||
1022 | len = nLen * 2; | ||
1023 | if (nFlags == RS_STIPCM16S) len *= 2; | ||
1024 | fwrite(pSample, 1, len, f); | ||
1025 | break; | ||
1026 | |||
1027 | // Default: assume 8-bit PCM data | ||
1028 | default: | ||
1029 | len = nLen; | ||
1030 | bufcount = 0; | ||
1031 | { | ||
1032 | signed char *p = pSample; | ||
1033 | int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1; | ||
1034 | int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0; | ||
1035 | if (pins->uFlags & CHN_16BIT) p++; | ||
1036 | for (UINT j=0; j<len; j++) | ||
1037 | { | ||
1038 | int s_new = (signed char)(*p); | ||
1039 | p += sinc; | ||
1040 | if (pins->uFlags & CHN_STEREO) | ||
1041 | { | ||
1042 | s_new = (s_new + ((int)*p) + 1) >> 1; | ||
1043 | p += sinc; | ||
1044 | } | ||
1045 | if (nFlags == RS_PCM8D) | ||
1046 | { | ||
1047 | buffer[bufcount++] = (signed char)(s_new - s_old); | ||
1048 | s_old = s_new; | ||
1049 | } else | ||
1050 | { | ||
1051 | buffer[bufcount++] = (signed char)(s_new + s_ofs); | ||
1052 | } | ||
1053 | if (bufcount >= sizeof(buffer)) | ||
1054 | { | ||
1055 | fwrite(buffer, 1, bufcount, f); | ||
1056 | bufcount = 0; | ||
1057 | } | ||
1058 | } | ||
1059 | if (bufcount) fwrite(buffer, 1, bufcount, f); | ||
1060 | } | ||
1061 | } | ||
1062 | return len; | ||
1063 | } | ||
1064 | |||
1065 | #endif // MODPLUG_NO_FILESAVE | ||
1066 | |||
1067 | |||
1068 | // Flags: | ||
1069 | //0 = signed 8-bit PCM data (default) | ||
1070 | //1 = unsigned 8-bit PCM data | ||
1071 | //2 = 8-bit ADPCM data with linear table | ||
1072 | //3 = 4-bit ADPCM data | ||
1073 | //4 = 16-bit ADPCM data with linear table | ||
1074 | //5 = signed 16-bit PCM data | ||
1075 | //6 = unsigned 16-bit PCM data | ||
1076 | |||
1077 | |||
1078 | UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength) | ||
1079 | //------------------------------------------------------------------------------------------------ | ||
1080 | { | ||
1081 | UINT len = 0, mem = pIns->nLength+6; | ||
1082 | |||
1083 | if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0; | ||
1084 | if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH; | ||
1085 | pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO); | ||
1086 | if (nFlags & RSF_16BIT) | ||
1087 | { | ||
1088 | mem *= 2; | ||
1089 | pIns->uFlags |= CHN_16BIT; | ||
1090 | } | ||
1091 | if (nFlags & RSF_STEREO) | ||
1092 | { | ||
1093 | mem *= 2; | ||
1094 | pIns->uFlags |= CHN_STEREO; | ||
1095 | } | ||
1096 | if ((pIns->pSample = AllocateSample(mem)) == NULL) | ||
1097 | { | ||
1098 | pIns->nLength = 0; | ||
1099 | return 0; | ||
1100 | } | ||
1101 | switch(nFlags) | ||
1102 | { | ||
1103 | // 1: 8-bit unsigned PCM data | ||
1104 | case RS_PCM8U: | ||
1105 | { | ||
1106 | len = pIns->nLength; | ||
1107 | if (len > dwMemLength) len = pIns->nLength = dwMemLength; | ||
1108 | signed char *pSample = pIns->pSample; | ||
1109 | for (UINT j=0; j<len; j++) pSample[j] = (signed char)(lpMemFile[j] - 0x80); | ||
1110 | } | ||
1111 | break; | ||
1112 | |||
1113 | // 2: 8-bit ADPCM data with linear table | ||
1114 | case RS_PCM8D: | ||
1115 | { | ||
1116 | len = pIns->nLength; | ||
1117 | if (len > dwMemLength) break; | ||
1118 | signed char *pSample = pIns->pSample; | ||
1119 | const signed char *p = (const signed char *)lpMemFile; | ||
1120 | int delta = 0; | ||
1121 | |||
1122 | for (UINT j=0; j<len; j++) | ||
1123 | { | ||
1124 | delta += p[j]; | ||
1125 | *pSample++ = (signed char)delta; | ||
1126 | } | ||
1127 | } | ||
1128 | break; | ||
1129 | |||
1130 | // 3: 4-bit ADPCM data | ||
1131 | case RS_ADPCM4: | ||
1132 | { | ||
1133 | len = (pIns->nLength + 1) / 2; | ||
1134 | if (len > dwMemLength - 16) break; | ||
1135 | memcpy(CompressionTable, lpMemFile, 16); | ||
1136 | lpMemFile += 16; | ||
1137 | signed char *pSample = pIns->pSample; | ||
1138 | signed char delta = 0; | ||
1139 | for (UINT j=0; j<len; j++) | ||
1140 | { | ||
1141 | BYTE b0 = (BYTE)lpMemFile[j]; | ||
1142 | BYTE b1 = (BYTE)(lpMemFile[j] >> 4); | ||
1143 | delta = (signed char)GetDeltaValue((int)delta, b0); | ||
1144 | pSample[0] = delta; | ||
1145 | delta = (signed char)GetDeltaValue((int)delta, b1); | ||
1146 | pSample[1] = delta; | ||
1147 | pSample += 2; | ||
1148 | } | ||
1149 | len += 16; | ||
1150 | } | ||
1151 | break; | ||
1152 | |||
1153 | // 4: 16-bit ADPCM data with linear table | ||
1154 | case RS_PCM16D: | ||
1155 | { | ||
1156 | len = pIns->nLength * 2; | ||
1157 | if (len > dwMemLength) break; | ||
1158 | short int *pSample = (short int *)pIns->pSample; | ||
1159 | short int *p = (short int *)lpMemFile; | ||
1160 | int delta16 = 0; | ||
1161 | for (UINT j=0; j<len; j+=2) | ||
1162 | { | ||
1163 | delta16 += bswapLE16(*p++); | ||
1164 | *pSample++ = (short int)delta16; | ||
1165 | } | ||
1166 | } | ||
1167 | break; | ||
1168 | |||
1169 | // 5: 16-bit signed PCM data | ||
1170 | case RS_PCM16S: | ||
1171 | { | ||
1172 | len = pIns->nLength * 2; | ||
1173 | if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len); | ||
1174 | short int *pSample = (short int *)pIns->pSample; | ||
1175 | for (UINT j=0; j<len; j+=2) | ||
1176 | { | ||
1177 | *pSample++ = bswapLE16(*pSample); | ||
1178 | } | ||
1179 | } | ||
1180 | break; | ||
1181 | |||
1182 | // 16-bit signed mono PCM motorola byte order | ||
1183 | case RS_PCM16M: | ||
1184 | len = pIns->nLength * 2; | ||
1185 | if (len > dwMemLength) len = dwMemLength & ~1; | ||
1186 | if (len > 1) | ||
1187 | { | ||
1188 | signed char *pSample = (signed char *)pIns->pSample; | ||
1189 | signed char *pSrc = (signed char *)lpMemFile; | ||
1190 | for (UINT j=0; j<len; j+=2) | ||
1191 | { | ||
1192 | // pSample[j] = pSrc[j+1]; | ||
1193 | // pSample[j+1] = pSrc[j]; | ||
1194 | *((unsigned short *)(pSample+j)) = bswapBE16(*((unsigned short *)(pSrc+j))); | ||
1195 | } | ||
1196 | } | ||
1197 | break; | ||
1198 | |||
1199 | // 6: 16-bit unsigned PCM data | ||
1200 | case RS_PCM16U: | ||
1201 | { | ||
1202 | len = pIns->nLength * 2; | ||
1203 | if (len > dwMemLength) break; | ||
1204 | short int *pSample = (short int *)pIns->pSample; | ||
1205 | short int *pSrc = (short int *)lpMemFile; | ||
1206 | for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000; | ||
1207 | } | ||
1208 | break; | ||
1209 | |||
1210 | // 16-bit signed stereo big endian | ||
1211 | case RS_STPCM16M: | ||
1212 | len = pIns->nLength * 2; | ||
1213 | if (len*2 <= dwMemLength) | ||
1214 | { | ||
1215 | signed char *pSample = (signed char *)pIns->pSample; | ||
1216 | signed char *pSrc = (signed char *)lpMemFile; | ||
1217 | for (UINT j=0; j<len; j+=2) | ||
1218 | { | ||
1219 | // pSample[j*2] = pSrc[j+1]; | ||
1220 | // pSample[j*2+1] = pSrc[j]; | ||
1221 | // pSample[j*2+2] = pSrc[j+1+len]; | ||
1222 | // pSample[j*2+3] = pSrc[j+len]; | ||
1223 | *((unsigned short *)(pSample+j*2)) = bswapBE16(*((unsigned short *)(pSrc+j))); | ||
1224 | *((unsigned short *)(pSample+j*2+2)) = bswapBE16(*((unsigned short *)(pSrc+j+len))); | ||
1225 | } | ||
1226 | len *= 2; | ||
1227 | } | ||
1228 | break; | ||
1229 | |||
1230 | // 8-bit stereo samples | ||
1231 | case RS_STPCM8S: | ||
1232 | case RS_STPCM8U: | ||
1233 | case RS_STPCM8D: | ||
1234 | { | ||
1235 | int iadd_l = 0, iadd_r = 0; | ||
1236 | if (nFlags == RS_STPCM8U) { iadd_l = iadd_r = -128; } | ||
1237 | len = pIns->nLength; | ||
1238 | signed char *psrc = (signed char *)lpMemFile; | ||
1239 | signed char *pSample = (signed char *)pIns->pSample; | ||
1240 | if (len*2 > dwMemLength) break; | ||
1241 | for (UINT j=0; j<len; j++) | ||
1242 | { | ||
1243 | pSample[j*2] = (signed char)(psrc[0] + iadd_l); | ||
1244 | pSample[j*2+1] = (signed char)(psrc[len] + iadd_r); | ||
1245 | psrc++; | ||
1246 | if (nFlags == RS_STPCM8D) | ||
1247 | { | ||
1248 | iadd_l = pSample[j*2]; | ||
1249 | iadd_r = pSample[j*2+1]; | ||
1250 | } | ||
1251 | } | ||
1252 | len *= 2; | ||
1253 | } | ||
1254 | break; | ||
1255 | |||
1256 | // 16-bit stereo samples | ||
1257 | case RS_STPCM16S: | ||
1258 | case RS_STPCM16U: | ||
1259 | case RS_STPCM16D: | ||
1260 | { | ||
1261 | int iadd_l = 0, iadd_r = 0; | ||
1262 | if (nFlags == RS_STPCM16U) { iadd_l = iadd_r = -0x8000; } | ||
1263 | len = pIns->nLength; | ||
1264 | short int *psrc = (short int *)lpMemFile; | ||
1265 | short int *pSample = (short int *)pIns->pSample; | ||
1266 | if (len*4 > dwMemLength) break; | ||
1267 | for (UINT j=0; j<len; j++) | ||
1268 | { | ||
1269 | pSample[j*2] = (short int) (bswapLE16(psrc[0]) + iadd_l); | ||
1270 | pSample[j*2+1] = (short int) (bswapLE16(psrc[len]) + iadd_r); | ||
1271 | psrc++; | ||
1272 | if (nFlags == RS_STPCM16D) | ||
1273 | { | ||
1274 | iadd_l = pSample[j*2]; | ||
1275 | iadd_r = pSample[j*2+1]; | ||
1276 | } | ||
1277 | } | ||
1278 | len *= 4; | ||
1279 | } | ||
1280 | break; | ||
1281 | |||
1282 | // IT 2.14 compressed samples | ||
1283 | case RS_IT2148: | ||
1284 | case RS_IT21416: | ||
1285 | case RS_IT2158: | ||
1286 | case RS_IT21516: | ||
1287 | len = dwMemLength; | ||
1288 | if (len < 4) break; | ||
1289 | if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158)) | ||
1290 | ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158)); | ||
1291 | else | ||
1292 | ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516)); | ||
1293 | break; | ||
1294 | |||
1295 | #ifndef MODPLUG_BASIC_SUPPORT | ||
1296 | #ifndef FASTSOUNDLIB | ||
1297 | // 8-bit interleaved stereo samples | ||
1298 | case RS_STIPCM8S: | ||
1299 | case RS_STIPCM8U: | ||
1300 | { | ||
1301 | int iadd = 0; | ||
1302 | if (nFlags == RS_STIPCM8U) { iadd = -0x80; } | ||
1303 | len = pIns->nLength; | ||
1304 | if (len*2 > dwMemLength) len = dwMemLength >> 1; | ||
1305 | LPBYTE psrc = (LPBYTE)lpMemFile; | ||
1306 | LPBYTE pSample = (LPBYTE)pIns->pSample; | ||
1307 | for (UINT j=0; j<len; j++) | ||
1308 | { | ||
1309 | pSample[j*2] = (signed char)(psrc[0] + iadd); | ||
1310 | pSample[j*2+1] = (signed char)(psrc[1] + iadd); | ||
1311 | psrc+=2; | ||
1312 | } | ||
1313 | len *= 2; | ||
1314 | } | ||
1315 | break; | ||
1316 | |||
1317 | // 16-bit interleaved stereo samples | ||
1318 | case RS_STIPCM16S: | ||
1319 | case RS_STIPCM16U: | ||
1320 | { | ||
1321 | int iadd = 0; | ||
1322 | if (nFlags == RS_STIPCM16U) iadd = -32768; | ||
1323 | len = pIns->nLength; | ||
1324 | if (len*4 > dwMemLength) len = dwMemLength >> 2; | ||
1325 | short int *psrc = (short int *)lpMemFile; | ||
1326 | short int *pSample = (short int *)pIns->pSample; | ||
1327 | for (UINT j=0; j<len; j++) | ||
1328 | { | ||
1329 | pSample[j*2] = (short int)(bswapLE16(psrc[0]) + iadd); | ||
1330 | pSample[j*2+1] = (short int)(bswapLE16(psrc[1]) + iadd); | ||
1331 | psrc += 2; | ||
1332 | } | ||
1333 | len *= 4; | ||
1334 | } | ||
1335 | break; | ||
1336 | |||
1337 | // AMS compressed samples | ||
1338 | case RS_AMS8: | ||
1339 | case RS_AMS16: | ||
1340 | len = 9; | ||
1341 | if (dwMemLength > 9) | ||
1342 | { | ||
1343 | const char *psrc = lpMemFile; | ||
1344 | char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample; | ||
1345 | len += bswapLE32(*((LPDWORD)(lpMemFile+4))); | ||
1346 | if (len > dwMemLength) len = dwMemLength; | ||
1347 | UINT dmax = pIns->nLength; | ||
1348 | if (pIns->uFlags & CHN_16BIT) dmax <<= 1; | ||
1349 | AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter); | ||
1350 | } | ||
1351 | break; | ||
1352 | |||
1353 | // PTM 8bit delta to 16-bit sample | ||
1354 | case RS_PTM8DTO16: | ||
1355 | { | ||
1356 | len = pIns->nLength * 2; | ||
1357 | if (len > dwMemLength) break; | ||
1358 | signed char *pSample = (signed char *)pIns->pSample; | ||
1359 | signed char delta8 = 0; | ||
1360 | for (UINT j=0; j<len; j++) | ||
1361 | { | ||
1362 | delta8 += lpMemFile[j]; | ||
1363 | *pSample++ = delta8; | ||
1364 | } | ||
1365 | WORD *pSampleW = (WORD *)pIns->pSample; | ||
1366 | for (UINT j=0; j<len; j+=2) // swaparoni! | ||
1367 | { | ||
1368 | *pSampleW++ = bswapLE16(*pSampleW); | ||
1369 | } | ||
1370 | } | ||
1371 | break; | ||
1372 | |||
1373 | // Huffman MDL compressed samples | ||
1374 | case RS_MDL8: | ||
1375 | case RS_MDL16: | ||
1376 | len = dwMemLength; | ||
1377 | if (len >= 4) | ||
1378 | { | ||
1379 | LPBYTE pSample = (LPBYTE)pIns->pSample; | ||
1380 | LPBYTE ibuf = (LPBYTE)lpMemFile; | ||
1381 | DWORD bitbuf = bswapLE32(*((DWORD *)ibuf)); | ||
1382 | UINT bitnum = 32; | ||
1383 | BYTE dlt = 0, lowbyte = 0; | ||
1384 | ibuf += 4; | ||
1385 | for (UINT j=0; j<pIns->nLength; j++) | ||
1386 | { | ||
1387 | BYTE hibyte; | ||
1388 | BYTE sign; | ||
1389 | if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8); | ||
1390 | sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1); | ||
1391 | if (MDLReadBits(bitbuf, bitnum, ibuf, 1)) | ||
1392 | { | ||
1393 | hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3); | ||
1394 | } else | ||
1395 | { | ||
1396 | hibyte = 8; | ||
1397 | while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10; | ||
1398 | hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4); | ||
1399 | } | ||
1400 | if (sign) hibyte = ~hibyte; | ||
1401 | dlt += hibyte; | ||
1402 | if (nFlags != RS_MDL16) | ||
1403 | pSample[j] = dlt; | ||
1404 | else | ||
1405 | { | ||
1406 | pSample[j<<1] = lowbyte; | ||
1407 | pSample[(j<<1)+1] = dlt; | ||
1408 | } | ||
1409 | } | ||
1410 | } | ||
1411 | break; | ||
1412 | |||
1413 | case RS_DMF8: | ||
1414 | case RS_DMF16: | ||
1415 | len = dwMemLength; | ||
1416 | if (len >= 4) | ||
1417 | { | ||
1418 | UINT maxlen = pIns->nLength; | ||
1419 | if (pIns->uFlags & CHN_16BIT) maxlen <<= 1; | ||
1420 | LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength); | ||
1421 | len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen); | ||
1422 | } | ||
1423 | break; | ||
1424 | |||
1425 | #ifdef MODPLUG_TRACKER | ||
1426 | // PCM 24-bit signed -> load sample, and normalize it to 16-bit | ||
1427 | case RS_PCM24S: | ||
1428 | case RS_PCM32S: | ||
1429 | len = pIns->nLength * 3; | ||
1430 | if (nFlags == RS_PCM32S) len += pIns->nLength; | ||
1431 | if (len > dwMemLength) break; | ||
1432 | if (len > 4*8) | ||
1433 | { | ||
1434 | UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3; | ||
1435 | LPBYTE pSrc = (LPBYTE)lpMemFile; | ||
1436 | LONG max = 255; | ||
1437 | if (nFlags == RS_PCM32S) pSrc++; | ||
1438 | for (UINT j=0; j<len; j+=slsize) | ||
1439 | { | ||
1440 | LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8; | ||
1441 | l /= 256; | ||
1442 | if (l > max) max = l; | ||
1443 | if (-l > max) max = -l; | ||
1444 | } | ||
1445 | max = (max / 128) + 1; | ||
1446 | signed short *pDest = (signed short *)pIns->pSample; | ||
1447 | for (UINT k=0; k<len; k+=slsize) | ||
1448 | { | ||
1449 | LONG l = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; | ||
1450 | *pDest++ = (signed short)(l / max); | ||
1451 | } | ||
1452 | } | ||
1453 | break; | ||
1454 | |||
1455 | // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit | ||
1456 | case RS_STIPCM24S: | ||
1457 | case RS_STIPCM32S: | ||
1458 | len = pIns->nLength * 6; | ||
1459 | if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2; | ||
1460 | if (len > dwMemLength) break; | ||
1461 | if (len > 8*8) | ||
1462 | { | ||
1463 | UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3; | ||
1464 | LPBYTE pSrc = (LPBYTE)lpMemFile; | ||
1465 | LONG max = 255; | ||
1466 | if (nFlags == RS_STIPCM32S) pSrc++; | ||
1467 | for (UINT j=0; j<len; j+=slsize) | ||
1468 | { | ||
1469 | LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8; | ||
1470 | l /= 256; | ||
1471 | if (l > max) max = l; | ||
1472 | if (-l > max) max = -l; | ||
1473 | } | ||
1474 | max = (max / 128) + 1; | ||
1475 | signed short *pDest = (signed short *)pIns->pSample; | ||
1476 | for (UINT k=0; k<len; k+=slsize) | ||
1477 | { | ||
1478 | LONG lr = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; | ||
1479 | k += slsize; | ||
1480 | LONG ll = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8; | ||
1481 | pDest[0] = (signed short)ll; | ||
1482 | pDest[1] = (signed short)lr; | ||
1483 | pDest += 2; | ||
1484 | } | ||
1485 | } | ||
1486 | break; | ||
1487 | |||
1488 | // 16-bit signed big endian interleaved stereo | ||
1489 | case RS_STIPCM16M: | ||
1490 | { | ||
1491 | len = pIns->nLength; | ||
1492 | if (len*4 > dwMemLength) len = dwMemLength >> 2; | ||
1493 | LPCBYTE psrc = (LPCBYTE)lpMemFile; | ||
1494 | short int *pSample = (short int *)pIns->pSample; | ||
1495 | for (UINT j=0; j<len; j++) | ||
1496 | { | ||
1497 | pSample[j*2] = (signed short)(((UINT)psrc[0] << 8) | (psrc[1])); | ||
1498 | pSample[j*2+1] = (signed short)(((UINT)psrc[2] << 8) | (psrc[3])); | ||
1499 | psrc += 4; | ||
1500 | } | ||
1501 | len *= 4; | ||
1502 | } | ||
1503 | break; | ||
1504 | |||
1505 | #endif // MODPLUG_TRACKER | ||
1506 | #endif // !FASTSOUNDLIB | ||
1507 | #endif // !MODPLUG_BASIC_SUPPORT | ||
1508 | |||
1509 | // Default: 8-bit signed PCM data | ||
1510 | default: | ||
1511 | len = pIns->nLength; | ||
1512 | if (len > dwMemLength) len = pIns->nLength = dwMemLength; | ||
1513 | memcpy(pIns->pSample, lpMemFile, len); | ||
1514 | } | ||
1515 | if (len > dwMemLength) | ||
1516 | { | ||
1517 | if (pIns->pSample) | ||
1518 | { | ||
1519 | pIns->nLength = 0; | ||
1520 | FreeSample(pIns->pSample); | ||
1521 | pIns->pSample = NULL; | ||
1522 | } | ||
1523 | return 0; | ||
1524 | } | ||
1525 | AdjustSampleLoop(pIns); | ||
1526 | return len; | ||
1527 | } | ||
1528 | |||
1529 | |||
1530 | void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns) | ||
1531 | //---------------------------------------------------- | ||
1532 | { | ||
1533 | if (!pIns->pSample) return; | ||
1534 | if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength; | ||
1535 | if (pIns->nLoopStart+2 >= pIns->nLoopEnd) | ||
1536 | { | ||
1537 | pIns->nLoopStart = pIns->nLoopEnd = 0; | ||
1538 | pIns->uFlags &= ~CHN_LOOP; | ||
1539 | } | ||
1540 | UINT len = pIns->nLength; | ||
1541 | if (pIns->uFlags & CHN_16BIT) | ||
1542 | { | ||
1543 | short int *pSample = (short int *)pIns->pSample; | ||
1544 | // Adjust end of sample | ||
1545 | if (pIns->uFlags & CHN_STEREO) | ||
1546 | { | ||
1547 | pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; | ||
1548 | pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; | ||
1549 | } else | ||
1550 | { | ||
1551 | pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; | ||
1552 | } | ||
1553 | if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) | ||
1554 | { | ||
1555 | // Fix bad loops | ||
1556 | if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M)) | ||
1557 | { | ||
1558 | pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; | ||
1559 | pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; | ||
1560 | pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; | ||
1561 | pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; | ||
1562 | pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; | ||
1563 | } | ||
1564 | } | ||
1565 | } else | ||
1566 | { | ||
1567 | signed char *pSample = pIns->pSample; | ||
1568 | #ifndef FASTSOUNDLIB | ||
1569 | // Crappy samples (except chiptunes) ? | ||
1570 | if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)) | ||
1571 | && (!(pIns->uFlags & CHN_STEREO))) | ||
1572 | { | ||
1573 | int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan; | ||
1574 | for (kscan=pIns->nLength-1; kscan>0; kscan--) | ||
1575 | { | ||
1576 | smpfix = pSample[kscan-1]; | ||
1577 | if (smpfix != smpend) break; | ||
1578 | } | ||
1579 | int delta = smpfix - smpend; | ||
1580 | if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd)) | ||
1581 | && ((delta < -8) || (delta > 8))) | ||
1582 | { | ||
1583 | while (kscan<(int)pIns->nLength) | ||
1584 | { | ||
1585 | if (!(kscan & 7)) | ||
1586 | { | ||
1587 | if (smpfix > 0) smpfix--; | ||
1588 | if (smpfix < 0) smpfix++; | ||
1589 | } | ||
1590 | pSample[kscan] = (signed char)smpfix; | ||
1591 | kscan++; | ||
1592 | } | ||
1593 | } | ||
1594 | } | ||
1595 | #endif | ||
1596 | // Adjust end of sample | ||
1597 | if (pIns->uFlags & CHN_STEREO) | ||
1598 | { | ||
1599 | pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2]; | ||
1600 | pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1]; | ||
1601 | } else | ||
1602 | { | ||
1603 | pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1]; | ||
1604 | } | ||
1605 | if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP) | ||
1606 | { | ||
1607 | if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) | ||
1608 | { | ||
1609 | pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart]; | ||
1610 | pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1]; | ||
1611 | pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2]; | ||
1612 | pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3]; | ||
1613 | pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4]; | ||
1614 | } | ||
1615 | } | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1619 | |||
1620 | ///////////////////////////////////////////////////////////// | ||
1621 | // Transpose <-> Frequency conversions | ||
1622 | |||
1623 | // returns 8363*2^((transp*128+ftune)/(12*128)) | ||
1624 | DWORD CSoundFile::TransposeToFrequency(int transp, int ftune) | ||
1625 | //----------------------------------------------------------- | ||
1626 | { | ||
1627 | //---GCCFIX: Removed assembly. | ||
1628 | return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536))); | ||
1629 | |||
1630 | #ifdef WIN32 | ||
1631 | const float _fbase = 8363; | ||
1632 | const float _factor = 1.0f/(12.0f*128.0f); | ||
1633 | int result; | ||
1634 | DWORD freq; | ||
1635 | |||
1636 | transp = (transp << 7) + ftune; | ||
1637 | _asm { | ||
1638 | fild transp | ||
1639 | fld _factor | ||
1640 | fmulp st(1), st(0) | ||
1641 | fist result | ||
1642 | fisub result | ||
1643 | f2xm1 | ||
1644 | fild result | ||
1645 | fld _fbase | ||
1646 | fscale | ||
1647 | fstp st(1) | ||
1648 | fmul st(1), st(0) | ||
1649 | faddp st(1), st(0) | ||
1650 | fistp freq | ||
1651 | } | ||
1652 | UINT derr = freq % 11025; | ||
1653 | if (derr <= 8) freq -= derr; | ||
1654 | if (derr >= 11015) freq += 11025-derr; | ||
1655 | derr = freq % 1000; | ||
1656 | if (derr <= 5) freq -= derr; | ||
1657 | if (derr >= 995) freq += 1000-derr; | ||
1658 | return freq; | ||
1659 | #endif | ||
1660 | } | ||
1661 | |||
1662 | |||
1663 | // returns 12*128*log2(freq/8363) | ||
1664 | int CSoundFile::FrequencyToTranspose(DWORD freq) | ||
1665 | //---------------------------------------------- | ||
1666 | { | ||
1667 | //---GCCFIX: Removed assembly. | ||
1668 | return int(1536*(log(freq/8363)/log(2))); | ||
1669 | |||
1670 | #ifdef WIN32 | ||
1671 | const float _f1_8363 = 1.0f / 8363.0f; | ||
1672 | const float _factor = 128 * 12; | ||
1673 | LONG result; | ||
1674 | |||
1675 | if (!freq) return 0; | ||
1676 | _asm { | ||
1677 | fld _factor | ||
1678 | fild freq | ||
1679 | fld _f1_8363 | ||
1680 | fmulp st(1), st(0) | ||
1681 | fyl2x | ||
1682 | fistp result | ||
1683 | } | ||
1684 | return result; | ||
1685 | #endif | ||
1686 | } | ||
1687 | |||
1688 | |||
1689 | void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp) | ||
1690 | //-------------------------------------------------------- | ||
1691 | { | ||
1692 | int f2t = FrequencyToTranspose(psmp->nC4Speed); | ||
1693 | int transp = f2t >> 7; | ||
1694 | int ftune = f2t & 0x7F; | ||
1695 | if (ftune > 80) | ||
1696 | { | ||
1697 | transp++; | ||
1698 | ftune -= 128; | ||
1699 | } | ||
1700 | if (transp > 127) transp = 127; | ||
1701 | if (transp < -127) transp = -127; | ||
1702 | psmp->RelativeTone = transp; | ||
1703 | psmp->nFineTune = ftune; | ||
1704 | } | ||
1705 | |||
1706 | |||
1707 | void CSoundFile::CheckCPUUsage(UINT nCPU) | ||
1708 | //--------------------------------------- | ||
1709 | { | ||
1710 | if (nCPU > 100) nCPU = 100; | ||
1711 | gnCPUUsage = nCPU; | ||
1712 | if (nCPU < 90) | ||
1713 | { | ||
1714 | m_dwSongFlags &= ~SONG_CPUVERYHIGH; | ||
1715 | } else | ||
1716 | if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94)) | ||
1717 | { | ||
1718 | UINT i=MAX_CHANNELS; | ||
1719 | while (i >= 8) | ||
1720 | { | ||
1721 | i--; | ||
1722 | if (Chn[i].nLength) | ||
1723 | { | ||
1724 | Chn[i].nLength = Chn[i].nPos = 0; | ||
1725 | nCPU -= 2; | ||
1726 | if (nCPU < 94) break; | ||
1727 | } | ||
1728 | } | ||
1729 | } else | ||
1730 | if (nCPU > 90) | ||
1731 | { | ||
1732 | m_dwSongFlags |= SONG_CPUVERYHIGH; | ||
1733 | } | ||
1734 | } | ||
1735 | |||
1736 | |||
1737 | BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName) | ||
1738 | //--------------------------------------------------------- | ||
1739 | { | ||
1740 | char szName[MAX_PATTERNNAME] = ""; // changed from CHAR | ||
1741 | if (nPat >= MAX_PATTERNS) return FALSE; | ||
1742 | if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME); | ||
1743 | szName[MAX_PATTERNNAME-1] = 0; | ||
1744 | if (!m_lpszPatternNames) m_nPatternNames = 0; | ||
1745 | if (nPat >= m_nPatternNames) | ||
1746 | { | ||
1747 | if (!lpszName[0]) return TRUE; | ||
1748 | UINT len = (nPat+1)*MAX_PATTERNNAME; | ||
1749 | char *p = new char[len]; // changed from CHAR | ||
1750 | if (!p) return FALSE; | ||
1751 | memset(p, 0, len); | ||
1752 | if (m_lpszPatternNames) | ||
1753 | { | ||
1754 | memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME); | ||
1755 | delete m_lpszPatternNames; | ||
1756 | m_lpszPatternNames = NULL; | ||
1757 | } | ||
1758 | m_lpszPatternNames = p; | ||
1759 | m_nPatternNames = nPat + 1; | ||
1760 | } | ||
1761 | memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME); | ||
1762 | return TRUE; | ||
1763 | } | ||
1764 | |||
1765 | |||
1766 | BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const | ||
1767 | //--------------------------------------------------------------------------- | ||
1768 | { | ||
1769 | if ((!lpszName) || (!cbSize)) return FALSE; | ||
1770 | lpszName[0] = 0; | ||
1771 | if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME; | ||
1772 | if ((m_lpszPatternNames) && (nPat < m_nPatternNames)) | ||
1773 | { | ||
1774 | memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize); | ||
1775 | lpszName[cbSize-1] = 0; | ||
1776 | return TRUE; | ||
1777 | } | ||
1778 | return FALSE; | ||
1779 | } | ||
1780 | |||
1781 | |||
1782 | #ifndef FASTSOUNDLIB | ||
1783 | |||
1784 | UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns) | ||
1785 | //----------------------------------------------- | ||
1786 | { | ||
1787 | UINT nExt = 0; | ||
1788 | |||
1789 | if (!pbIns) return 0; | ||
1790 | if (m_nInstruments) | ||
1791 | { | ||
1792 | memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL)); | ||
1793 | for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++) | ||
1794 | { | ||
1795 | MODCOMMAND *p = Patterns[ipat]; | ||
1796 | if (p) | ||
1797 | { | ||
1798 | UINT jmax = PatternSize[ipat] * m_nChannels; | ||
1799 | for (UINT j=0; j<jmax; j++, p++) | ||
1800 | { | ||
1801 | if ((p->note) && (p->note <= 120)) | ||
1802 | { | ||
1803 | if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) | ||
1804 | { | ||
1805 | INSTRUMENTHEADER *penv = Headers[p->instr]; | ||
1806 | if (penv) | ||
1807 | { | ||
1808 | UINT n = penv->Keyboard[p->note-1]; | ||
1809 | if (n < MAX_SAMPLES) pbIns[n] = TRUE; | ||
1810 | } | ||
1811 | } else | ||
1812 | { | ||
1813 | for (UINT k=1; k<=m_nInstruments; k++) | ||
1814 | { | ||
1815 | INSTRUMENTHEADER *penv = Headers[k]; | ||
1816 | if (penv) | ||
1817 | { | ||
1818 | UINT n = penv->Keyboard[p->note-1]; | ||
1819 | if (n < MAX_SAMPLES) pbIns[n] = TRUE; | ||
1820 | } | ||
1821 | } | ||
1822 | } | ||
1823 | } | ||
1824 | } | ||
1825 | } | ||
1826 | } | ||
1827 | for (UINT ichk=1; ichk<=m_nSamples; ichk++) | ||
1828 | { | ||
1829 | if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++; | ||
1830 | } | ||
1831 | } | ||
1832 | return nExt; | ||
1833 | } | ||
1834 | |||
1835 | |||
1836 | BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns) | ||
1837 | //------------------------------------------------- | ||
1838 | { | ||
1839 | if (!pbIns) return FALSE; | ||
1840 | for (UINT j=1; j<MAX_SAMPLES; j++) | ||
1841 | { | ||
1842 | if ((!pbIns[j]) && (Ins[j].pSample)) | ||
1843 | { | ||
1844 | DestroySample(j); | ||
1845 | if ((j == m_nSamples) && (j > 1)) m_nSamples--; | ||
1846 | } | ||
1847 | } | ||
1848 | return TRUE; | ||
1849 | } | ||
1850 | |||
1851 | |||
1852 | BOOL CSoundFile::DestroySample(UINT nSample) | ||
1853 | //------------------------------------------ | ||
1854 | { | ||
1855 | if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE; | ||
1856 | if (!Ins[nSample].pSample) return TRUE; | ||
1857 | MODINSTRUMENT *pins = &Ins[nSample]; | ||
1858 | signed char *pSample = pins->pSample; | ||
1859 | pins->pSample = NULL; | ||
1860 | pins->nLength = 0; | ||
1861 | pins->uFlags &= ~(CHN_16BIT); | ||
1862 | for (UINT i=0; i<MAX_CHANNELS; i++) | ||
1863 | { | ||
1864 | if (Chn[i].pSample == pSample) | ||
1865 | { | ||
1866 | Chn[i].nPos = Chn[i].nLength = 0; | ||
1867 | Chn[i].pSample = Chn[i].pCurrentSample = NULL; | ||
1868 | } | ||
1869 | } | ||
1870 | FreeSample(pSample); | ||
1871 | return TRUE; | ||
1872 | } | ||
1873 | |||
1874 | #endif // FASTSOUNDLIB | ||
1875 | |||