comparison src/modplug/load_amf.cxx @ 136:6b5a52635b3b trunk

[svn] - like with so many other things, modplug is now maintained by us.
author nenolod
date Sun, 29 Oct 2006 01:04:52 -0700
parents
children 032053ca08ab 3673c7ec4ea2
comparison
equal deleted inserted replaced
135:33d24bd94ccc 136:6b5a52635b3b
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 */
9
10 ///////////////////////////////////////////////////
11 //
12 // AMF module loader
13 //
14 // There is 2 types of AMF files:
15 // - ASYLUM Music Format
16 // - Advanced Music Format(DSM)
17 //
18 ///////////////////////////////////////////////////
19 #include "stdafx.h"
20 #include "sndfile.h"
21
22 //#define AMFLOG
23
24 //#pragma warning(disable:4244)
25
26 #pragma pack(1)
27
28 typedef struct _AMFFILEHEADER
29 {
30 UCHAR szAMF[3];
31 UCHAR version;
32 CHAR title[32];
33 UCHAR numsamples;
34 UCHAR numorders;
35 USHORT numtracks;
36 UCHAR numchannels;
37 } AMFFILEHEADER;
38
39 typedef struct _AMFSAMPLE
40 {
41 UCHAR type;
42 CHAR samplename[32];
43 CHAR filename[13];
44 ULONG offset;
45 ULONG length;
46 USHORT c2spd;
47 UCHAR volume;
48 } AMFSAMPLE;
49
50
51 #pragma pack()
52
53
54 #ifdef AMFLOG
55 extern void Log(LPCSTR, ...);
56 #endif
57
58 VOID AMF_Unpack(MODCOMMAND *pPat, const BYTE *pTrack, UINT nRows, UINT nChannels)
59 //-------------------------------------------------------------------------------
60 {
61 UINT lastinstr = 0;
62 UINT nTrkSize = bswapLE16(*(USHORT *)pTrack);
63 nTrkSize += (UINT)pTrack[2] <<16;
64 pTrack += 3;
65 while (nTrkSize--)
66 {
67 UINT row = pTrack[0];
68 UINT cmd = pTrack[1];
69 UINT arg = pTrack[2];
70 if (row >= nRows) break;
71 MODCOMMAND *m = pPat + row * nChannels;
72 if (cmd < 0x7F) // note+vol
73 {
74 m->note = cmd+1;
75 if (!m->instr) m->instr = lastinstr;
76 m->volcmd = VOLCMD_VOLUME;
77 m->vol = arg;
78 } else
79 if (cmd == 0x7F) // duplicate row
80 {
81 signed char rdelta = (signed char)arg;
82 int rowsrc = (int)row + (int)rdelta;
83 if ((rowsrc >= 0) && (rowsrc < (int)nRows)) memcpy(m, &pPat[rowsrc*nChannels],sizeof(pPat[rowsrc*nChannels]));
84 } else
85 if (cmd == 0x80) // instrument
86 {
87 m->instr = arg+1;
88 lastinstr = m->instr;
89 } else
90 if (cmd == 0x83) // volume
91 {
92 m->volcmd = VOLCMD_VOLUME;
93 m->vol = arg;
94 } else
95 // effect
96 {
97 UINT command = cmd & 0x7F;
98 UINT param = arg;
99 switch(command)
100 {
101 // 0x01: Set Speed
102 case 0x01: command = CMD_SPEED; break;
103 // 0x02: Volume Slide
104 // 0x0A: Tone Porta + Vol Slide
105 // 0x0B: Vibrato + Vol Slide
106 case 0x02: command = CMD_VOLUMESLIDE;
107 case 0x0A: if (command == 0x0A) command = CMD_TONEPORTAVOL;
108 case 0x0B: if (command == 0x0B) command = CMD_VIBRATOVOL;
109 if (param & 0x80) param = (-(signed char)param)&0x0F;
110 else param = (param&0x0F)<<4;
111 break;
112 // 0x04: Porta Up/Down
113 case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = -(signed char)param; }
114 else { command = CMD_PORTAMENTODOWN; } break;
115 // 0x06: Tone Portamento
116 case 0x06: command = CMD_TONEPORTAMENTO; break;
117 // 0x07: Tremor
118 case 0x07: command = CMD_TREMOR; break;
119 // 0x08: Arpeggio
120 case 0x08: command = CMD_ARPEGGIO; break;
121 // 0x09: Vibrato
122 case 0x09: command = CMD_VIBRATO; break;
123 // 0x0C: Pattern Break
124 case 0x0C: command = CMD_PATTERNBREAK; break;
125 // 0x0D: Position Jump
126 case 0x0D: command = CMD_POSITIONJUMP; break;
127 // 0x0F: Retrig
128 case 0x0F: command = CMD_RETRIG; break;
129 // 0x10: Offset
130 case 0x10: command = CMD_OFFSET; break;
131 // 0x11: Fine Volume Slide
132 case 0x11: if (param) { command = CMD_VOLUMESLIDE;
133 if (param & 0x80) param = 0xF0|((-(signed char)param)&0x0F);
134 else param = 0x0F|((param&0x0F)<<4);
135 } else command = 0; break;
136 // 0x12: Fine Portamento
137 // 0x16: Extra Fine Portamento
138 case 0x12:
139 case 0x16: if (param) { int mask = (command == 0x16) ? 0xE0 : 0xF0;
140 command = (param & 0x80) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN;
141 if (param & 0x80) param = mask|((-(signed char)param)&0x0F);
142 else param |= mask;
143 } else command = 0; break;
144 // 0x13: Note Delay
145 case 0x13: command = CMD_S3MCMDEX; param = 0xD0|(param & 0x0F); break;
146 // 0x14: Note Cut
147 case 0x14: command = CMD_S3MCMDEX; param = 0xC0|(param & 0x0F); break;
148 // 0x15: Set Tempo
149 case 0x15: command = CMD_TEMPO; break;
150 // 0x17: Panning
151 case 0x17: param = (param+64)&0x7F;
152 if (m->command) { if (!m->volcmd) { m->volcmd = VOLCMD_PANNING; m->vol = param/2; } command = 0; }
153 else { command = CMD_PANNING8; }
154 // Unknown effects
155 default: command = param = 0;
156 }
157 if (command)
158 {
159 m->command = command;
160 m->param = param;
161 }
162 }
163 pTrack += 3;
164 }
165 }
166
167
168
169 BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, DWORD dwMemLength)
170 //-----------------------------------------------------------
171 {
172 AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream;
173 DWORD dwMemPos;
174
175 if ((!lpStream) || (dwMemLength < 2048)) return FALSE;
176 if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096))
177 {
178 UINT numorders, numpats, numsamples;
179
180 dwMemPos = 32;
181 numpats = lpStream[dwMemPos+3];
182 numorders = lpStream[dwMemPos+4];
183 numsamples = 64;
184 dwMemPos += 6;
185 if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders)
186 || (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE;
187 m_nType = MOD_TYPE_AMF0;
188 m_nChannels = 8;
189 m_nInstruments = 0;
190 m_nSamples = 31;
191 m_nDefaultTempo = 125;
192 m_nDefaultSpeed = 6;
193 for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
194 {
195 Order[iOrd] = (iOrd < numorders) ? lpStream[dwMemPos+iOrd] : 0xFF;
196 }
197 dwMemPos = 294; // ???
198 for (UINT iSmp=0; iSmp<numsamples; iSmp++)
199 {
200 MODINSTRUMENT *psmp = &Ins[iSmp+1];
201 memcpy(m_szNames[iSmp+1], lpStream+dwMemPos, 22);
202 psmp->nFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]);
203 psmp->nVolume = lpStream[dwMemPos+23];
204 psmp->nGlobalVol = 64;
205 if (psmp->nVolume > 0x40) psmp->nVolume = 0x40;
206 psmp->nVolume <<= 2;
207 psmp->nLength = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+25)));
208 psmp->nLoopStart = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+29)));
209 psmp->nLoopEnd = psmp->nLoopStart + bswapLE32(*((LPDWORD)(lpStream+dwMemPos+33)));
210 if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength))
211 {
212 psmp->uFlags = CHN_LOOP;
213 } else
214 {
215 psmp->nLoopStart = psmp->nLoopEnd = 0;
216 }
217 if ((psmp->nLength) && (iSmp>31)) m_nSamples = iSmp+1;
218 dwMemPos += 37;
219 }
220 for (UINT iPat=0; iPat<numpats; iPat++)
221 {
222 MODCOMMAND *p = AllocatePattern(64, m_nChannels);
223 if (!p) break;
224 Patterns[iPat] = p;
225 PatternSize[iPat] = 64;
226 const UCHAR *pin = lpStream + dwMemPos;
227 for (UINT i=0; i<8*64; i++)
228 {
229 p->note = 0;
230
231 if (pin[0])
232 {
233 p->note = pin[0] + 13;
234 }
235 p->instr = pin[1];
236 p->command = pin[2];
237 p->param = pin[3];
238 if (p->command > 0x0F)
239 {
240 #ifdef AMFLOG
241 Log("0x%02X.0x%02X ?", p->command, p->param);
242 #endif
243 p->command = 0;
244 }
245 ConvertModCommand(p);
246 pin += 4;
247 p++;
248 }
249 dwMemPos += 64*32;
250 }
251 // Read samples
252 for (UINT iData=0; iData<m_nSamples; iData++)
253 {
254 MODINSTRUMENT *psmp = &Ins[iData+1];
255 if (psmp->nLength)
256 {
257 dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength);
258 }
259 }
260 return TRUE;
261 }
262 ////////////////////////////
263 // DSM/AMF
264 USHORT *ptracks[MAX_PATTERNS];
265 DWORD sampleseekpos[MAX_SAMPLES];
266
267 if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F')
268 || (pfh->version < 10) || (pfh->version > 14) || (!bswapLE16(pfh->numtracks))
269 || (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS)
270 || (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES)
271 || (pfh->numchannels < 4) || (pfh->numchannels > 32))
272 return FALSE;
273 memcpy(m_szNames[0], pfh->title, 32);
274 dwMemPos = sizeof(AMFFILEHEADER);
275 m_nType = MOD_TYPE_AMF;
276 m_nChannels = pfh->numchannels;
277 m_nSamples = pfh->numsamples;
278 m_nInstruments = 0;
279 // Setup Channel Pan Positions
280 if (pfh->version >= 11)
281 {
282 signed char *panpos = (signed char *)(lpStream + dwMemPos);
283 UINT nchannels = (pfh->version >= 13) ? 32 : 16;
284 for (UINT i=0; i<nchannels; i++)
285 {
286 int pan = (panpos[i] + 64) * 2;
287 if (pan < 0) pan = 0;
288 if (pan > 256) { pan = 128; ChnSettings[i].dwFlags |= CHN_SURROUND; }
289 ChnSettings[i].nPan = pan;
290 }
291 dwMemPos += nchannels;
292 } else
293 {
294 for (UINT i=0; i<16; i++)
295 {
296 ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0;
297 }
298 dwMemPos += 16;
299 }
300 // Get Tempo/Speed
301 m_nDefaultTempo = 125;
302 m_nDefaultSpeed = 6;
303 if (pfh->version >= 13)
304 {
305 if (lpStream[dwMemPos] >= 32) m_nDefaultTempo = lpStream[dwMemPos];
306 if (lpStream[dwMemPos+1] <= 32) m_nDefaultSpeed = lpStream[dwMemPos+1];
307 dwMemPos += 2;
308 }
309 // Setup sequence list
310 for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
311 {
312 Order[iOrd] = 0xFF;
313 if (iOrd < pfh->numorders)
314 {
315 Order[iOrd] = iOrd;
316 PatternSize[iOrd] = 64;
317 if (pfh->version >= 14)
318 {
319 PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos));
320 dwMemPos += 2;
321 }
322 ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos);
323 dwMemPos += m_nChannels * sizeof(USHORT);
324 }
325 }
326 if (dwMemPos + m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE;
327 // Read Samples
328 UINT maxsampleseekpos = 0;
329 for (UINT iIns=0; iIns<m_nSamples; iIns++)
330 {
331 MODINSTRUMENT *pins = &Ins[iIns+1];
332 AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos);
333
334 dwMemPos += sizeof(AMFSAMPLE);
335 memcpy(m_szNames[iIns+1], psh->samplename, 32);
336 memcpy(pins->name, psh->filename, 13);
337 pins->nLength = bswapLE32(psh->length);
338 pins->nC4Speed = bswapLE16(psh->c2spd);
339 pins->nGlobalVol = 64;
340 pins->nVolume = psh->volume * 4;
341 if (pfh->version >= 11)
342 {
343 pins->nLoopStart = bswapLE32(*(DWORD *)(lpStream+dwMemPos));
344 pins->nLoopEnd = bswapLE32(*(DWORD *)(lpStream+dwMemPos+4));
345 dwMemPos += 8;
346 } else
347 {
348 pins->nLoopStart = bswapLE16(*(WORD *)(lpStream+dwMemPos));
349 pins->nLoopEnd = pins->nLength;
350 dwMemPos += 2;
351 }
352 sampleseekpos[iIns] = 0;
353 if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1))
354 {
355 sampleseekpos[iIns] = bswapLE32(psh->offset);
356 if (bswapLE32(psh->offset) > maxsampleseekpos)
357 maxsampleseekpos = bswapLE32(psh->offset);
358 if ((pins->nLoopEnd > pins->nLoopStart + 2)
359 && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP;
360 }
361 }
362 // Read Track Mapping Table
363 USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos);
364 UINT realtrackcnt = 0;
365 dwMemPos += pfh->numtracks * sizeof(USHORT);
366 for (UINT iTrkMap=0; iTrkMap<pfh->numtracks; iTrkMap++)
367 {
368 if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap];
369 }
370 // Store tracks positions
371 BYTE **pTrackData = new BYTE *[realtrackcnt];
372 memset(pTrackData, 0, sizeof(pTrackData));
373 for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos + 3 <= dwMemLength)
374 {
375 UINT nTrkSize = bswapLE16(*(USHORT *)(lpStream+dwMemPos));
376 nTrkSize += (UINT)lpStream[dwMemPos+2] << 16;
377
378 if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength)
379 {
380 pTrackData[iTrack] = (BYTE *)(lpStream + dwMemPos);
381 }
382 dwMemPos += nTrkSize * 3 + 3;
383 }
384 // Create the patterns from the list of tracks
385 for (UINT iPat=0; iPat<pfh->numorders; iPat++)
386 {
387 MODCOMMAND *p = AllocatePattern(PatternSize[iPat], m_nChannels);
388 if (!p) break;
389 Patterns[iPat] = p;
390 for (UINT iChn=0; iChn<m_nChannels; iChn++)
391 {
392 UINT nTrack = bswapLE16(ptracks[iPat][iChn]);
393 if ((nTrack) && (nTrack <= pfh->numtracks))
394 {
395 UINT realtrk = bswapLE16(pTrackMap[nTrack-1]);
396 if (realtrk)
397 {
398 realtrk--;
399 if ((realtrk < realtrackcnt) && (pTrackData[realtrk]))
400 {
401 AMF_Unpack(p+iChn, pTrackData[realtrk], PatternSize[iPat], m_nChannels);
402 }
403 }
404 }
405 }
406 }
407 delete pTrackData;
408 // Read Sample Data
409 for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++)
410 {
411 if (dwMemPos >= dwMemLength) break;
412 for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (iSeek == sampleseekpos[iSmp])
413 {
414 MODINSTRUMENT *pins = &Ins[iSmp+1];
415 dwMemPos += ReadSample(pins, RS_PCM8U, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
416 break;
417 }
418 }
419 return TRUE;
420 }