Mercurial > SDL_sound_CoreAudio
annotate decoders/timidity/instrum_dls.c @ 562:7e08477b0fc1
MP3 decoder upgrade work.
Ripped out SMPEG and mpglib support, replaced it with "mpg123.c" and libmpg123.
libmpg123 is a much better version of mpglib, so it should solve all the
problems about MP3's not seeking, or most modern MP3's not playing at all,
etc. Since you no longer have to make a tradeoff with SMPEG for features, and
SMPEG is basically rotting, I removed it from the project.
There is still work to be done with libmpg123...there are MMX, 3DNow, SSE,
Altivec, etc decoders which we don't have enabled at the moment, and the
build system could use some work to make this compile more cleanly, etc.
Still: huge win.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 30 Jan 2009 02:44:47 -0500 |
parents | 4d2febf33dc7 |
children | d02c00ce16d9 |
rev | line source |
---|---|
455 | 1 /* |
2 | |
3 TiMidity -- Experimental MIDI to WAVE converter | |
4 Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi> | |
5 | |
6 This program is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 2 of the License, or | |
9 (at your option) any later version. | |
10 | |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program; if not, write to the Free Software | |
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | |
20 instrum.h | |
21 | |
22 */ | |
23 | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 | |
27 #include "SDL.h" | |
28 #include "SDL_endian.h" | |
29 #include "SDL_rwops.h" | |
30 | |
31 #include "SDL_sound.h" | |
32 | |
33 #define __SDL_SOUND_INTERNAL__ | |
34 #include "SDL_sound_internal.h" | |
35 | |
36 #include "timidity.h" | |
37 #include "options.h" | |
38 #include "instrum.h" | |
39 #include "tables.h" | |
40 #include "common.h" | |
41 | |
42 /*-------------------------------------------------------------------------*/ | |
43 /* * * * * * * * * * * * * * * * * load_riff.h * * * * * * * * * * * * * * */ | |
44 /*-------------------------------------------------------------------------*/ | |
45 typedef struct _RIFF_Chunk { | |
46 Uint32 magic; | |
47 Uint32 length; | |
48 Uint32 subtype; | |
49 Uint8 *data; | |
50 struct _RIFF_Chunk *child; | |
51 struct _RIFF_Chunk *next; | |
52 } RIFF_Chunk; | |
53 | |
54 extern DECLSPEC RIFF_Chunk* SDLCALL LoadRIFF(SDL_RWops *src); | |
55 extern DECLSPEC void SDLCALL FreeRIFF(RIFF_Chunk *chunk); | |
56 extern DECLSPEC void SDLCALL PrintRIFF(RIFF_Chunk *chunk, int level); | |
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
58 | |
59 /*-------------------------------------------------------------------------*/ | |
60 /* * * * * * * * * * * * * * * * * load_riff.c * * * * * * * * * * * * * * */ | |
61 /*-------------------------------------------------------------------------*/ | |
62 #define RIFF 0x46464952 /* "RIFF" */ | |
63 #define LIST 0x5453494c /* "LIST" */ | |
64 | |
65 static RIFF_Chunk *AllocRIFFChunk() | |
66 { | |
67 RIFF_Chunk *chunk = (RIFF_Chunk *)malloc(sizeof(*chunk)); | |
68 if ( !chunk ) { | |
459
4d2febf33dc7
Changed some SDL_Error()s to __Sound_SetError() to fix linking issues.
Ryan C. Gordon <icculus@icculus.org>
parents:
458
diff
changeset
|
69 __Sound_SetError(ERR_OUT_OF_MEMORY); |
455 | 70 return NULL; |
71 } | |
72 memset(chunk, 0, sizeof(*chunk)); | |
73 return chunk; | |
74 } | |
75 | |
76 static void FreeRIFFChunk(RIFF_Chunk *chunk) | |
77 { | |
78 if ( chunk->child ) { | |
79 FreeRIFFChunk(chunk->child); | |
80 } | |
458
69c8ba97f4bd
Fixed memory corruption when freeing DLS instruments
hercules
parents:
455
diff
changeset
|
81 if ( chunk->next ) { |
69c8ba97f4bd
Fixed memory corruption when freeing DLS instruments
hercules
parents:
455
diff
changeset
|
82 FreeRIFFChunk(chunk->next); |
455 | 83 } |
84 free(chunk); | |
85 } | |
86 | |
87 static int ChunkHasSubType(Uint32 magic) | |
88 { | |
89 static Uint32 chunk_list[] = { | |
90 RIFF, LIST | |
91 }; | |
92 int i; | |
93 for ( i = 0; i < SDL_TABLESIZE(chunk_list); ++i ) { | |
94 if ( magic == chunk_list[i] ) { | |
95 return 1; | |
96 } | |
97 } | |
98 return 0; | |
99 } | |
100 | |
101 static int ChunkHasSubChunks(Uint32 magic) | |
102 { | |
103 static Uint32 chunk_list[] = { | |
104 RIFF, LIST | |
105 }; | |
106 int i; | |
107 for ( i = 0; i < SDL_TABLESIZE(chunk_list); ++i ) { | |
108 if ( magic == chunk_list[i] ) { | |
109 return 1; | |
110 } | |
111 } | |
112 return 0; | |
113 } | |
114 | |
115 static void LoadSubChunks(RIFF_Chunk *chunk, Uint8 *data, Uint32 left) | |
116 { | |
117 Uint8 *subchunkData; | |
118 Uint32 subchunkDataLen; | |
119 | |
120 while ( left > 8 ) { | |
121 RIFF_Chunk *child = AllocRIFFChunk(); | |
122 RIFF_Chunk *next, *prev = NULL; | |
123 for ( next = chunk->child; next; next = next->next ) { | |
124 prev = next; | |
125 } | |
126 if ( prev ) { | |
127 prev->next = child; | |
128 } else { | |
129 chunk->child = child; | |
130 } | |
131 | |
132 child->magic = (data[0] << 0) | | |
133 (data[1] << 8) | | |
134 (data[2] << 16) | | |
135 (data[3] << 24); | |
136 data += 4; | |
137 left -= 4; | |
138 child->length = (data[0] << 0) | | |
139 (data[1] << 8) | | |
140 (data[2] << 16) | | |
141 (data[3] << 24); | |
142 data += 4; | |
143 left -= 4; | |
144 child->data = data; | |
145 | |
146 if ( child->length > left ) { | |
147 child->length = left; | |
148 } | |
149 | |
150 subchunkData = child->data; | |
151 subchunkDataLen = child->length; | |
152 if ( ChunkHasSubType(child->magic) && subchunkDataLen >= 4 ) { | |
153 child->subtype = (subchunkData[0] << 0) | | |
154 (subchunkData[1] << 8) | | |
155 (subchunkData[2] << 16) | | |
156 (subchunkData[3] << 24); | |
157 subchunkData += 4; | |
158 subchunkDataLen -= 4; | |
159 } | |
160 if ( ChunkHasSubChunks(child->magic) ) { | |
161 LoadSubChunks(child, subchunkData, subchunkDataLen); | |
162 } | |
163 | |
164 data += child->length; | |
165 left -= child->length; | |
166 } | |
167 } | |
168 | |
169 RIFF_Chunk *LoadRIFF(SDL_RWops *src) | |
170 { | |
171 RIFF_Chunk *chunk; | |
172 Uint8 *subchunkData; | |
173 Uint32 subchunkDataLen; | |
174 | |
175 /* Allocate the chunk structure */ | |
176 chunk = AllocRIFFChunk(); | |
177 | |
178 /* Make sure the file is in RIFF format */ | |
179 chunk->magic = SDL_ReadLE32(src); | |
180 chunk->length = SDL_ReadLE32(src); | |
181 if ( chunk->magic != RIFF ) { | |
459
4d2febf33dc7
Changed some SDL_Error()s to __Sound_SetError() to fix linking issues.
Ryan C. Gordon <icculus@icculus.org>
parents:
458
diff
changeset
|
182 __Sound_SetError("Not a RIFF file"); |
455 | 183 FreeRIFFChunk(chunk); |
184 return NULL; | |
185 } | |
186 chunk->data = (Uint8 *)malloc(chunk->length); | |
187 if ( chunk->data == NULL ) { | |
459
4d2febf33dc7
Changed some SDL_Error()s to __Sound_SetError() to fix linking issues.
Ryan C. Gordon <icculus@icculus.org>
parents:
458
diff
changeset
|
188 __Sound_SetError(ERR_OUT_OF_MEMORY); |
455 | 189 FreeRIFFChunk(chunk); |
190 return NULL; | |
191 } | |
192 if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) { | |
459
4d2febf33dc7
Changed some SDL_Error()s to __Sound_SetError() to fix linking issues.
Ryan C. Gordon <icculus@icculus.org>
parents:
458
diff
changeset
|
193 __Sound_SetError(ERR_IO_ERROR); |
455 | 194 FreeRIFF(chunk); |
195 return NULL; | |
196 } | |
197 subchunkData = chunk->data; | |
198 subchunkDataLen = chunk->length; | |
199 if ( ChunkHasSubType(chunk->magic) && subchunkDataLen >= 4 ) { | |
200 chunk->subtype = (subchunkData[0] << 0) | | |
201 (subchunkData[1] << 8) | | |
202 (subchunkData[2] << 16) | | |
203 (subchunkData[3] << 24); | |
204 subchunkData += 4; | |
205 subchunkDataLen -= 4; | |
206 } | |
207 if ( ChunkHasSubChunks(chunk->magic) ) { | |
208 LoadSubChunks(chunk, subchunkData, subchunkDataLen); | |
209 } | |
210 return chunk; | |
211 } | |
212 | |
213 void FreeRIFF(RIFF_Chunk *chunk) | |
214 { | |
215 free(chunk->data); | |
216 FreeRIFFChunk(chunk); | |
217 } | |
218 | |
219 void PrintRIFF(RIFF_Chunk *chunk, int level) | |
220 { | |
221 static char prefix[128]; | |
222 | |
223 if ( level == sizeof(prefix)-1 ) { | |
224 return; | |
225 } | |
226 if ( level > 0 ) { | |
227 prefix[(level-1)*2] = ' '; | |
228 prefix[(level-1)*2+1] = ' '; | |
229 } | |
230 prefix[level*2] = '\0'; | |
231 printf("%sChunk: %c%c%c%c (%d bytes)", prefix, | |
232 ((chunk->magic >> 0) & 0xFF), | |
233 ((chunk->magic >> 8) & 0xFF), | |
234 ((chunk->magic >> 16) & 0xFF), | |
235 ((chunk->magic >> 24) & 0xFF), chunk->length); | |
236 if ( chunk->subtype ) { | |
237 printf(" subtype: %c%c%c%c", | |
238 ((chunk->subtype >> 0) & 0xFF), | |
239 ((chunk->subtype >> 8) & 0xFF), | |
240 ((chunk->subtype >> 16) & 0xFF), | |
241 ((chunk->subtype >> 24) & 0xFF)); | |
242 } | |
243 printf("\n"); | |
244 if ( chunk->child ) { | |
245 printf("%s{\n", prefix); | |
246 PrintRIFF(chunk->child, level + 1); | |
247 printf("%s}\n", prefix); | |
248 } | |
249 if ( chunk->next ) { | |
250 PrintRIFF(chunk->next, level); | |
251 } | |
252 if ( level > 0 ) { | |
253 prefix[(level-1)*2] = '\0'; | |
254 } | |
255 } | |
256 | |
257 #ifdef TEST_MAIN_RIFF | |
258 | |
259 main(int argc, char *argv[]) | |
260 { | |
261 int i; | |
262 for ( i = 1; i < argc; ++i ) { | |
263 RIFF_Chunk *chunk; | |
264 SDL_RWops *src = SDL_RWFromFile(argv[i], "rb"); | |
265 if ( !src ) { | |
266 fprintf(stderr, "Couldn't open %s: %s", argv[i], SDL_GetError()); | |
267 continue; | |
268 } | |
269 chunk = LoadRIFF(src); | |
270 if ( chunk ) { | |
271 PrintRIFF(chunk, 0); | |
272 FreeRIFF(chunk); | |
273 } else { | |
274 fprintf(stderr, "Couldn't load %s: %s\n", argv[i], SDL_GetError()); | |
275 } | |
276 SDL_RWclose(src); | |
277 } | |
278 } | |
279 | |
280 #endif // TEST_MAIN | |
281 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
282 | |
283 /*-------------------------------------------------------------------------*/ | |
284 /* * * * * * * * * * * * * * * * * load_dls.h * * * * * * * * * * * * * * */ | |
285 /*-------------------------------------------------------------------------*/ | |
286 /* This code is based on the DLS spec version 1.1, available at: | |
287 http://www.midi.org/about-midi/dls/dlsspec.shtml | |
288 */ | |
289 | |
290 /* Some typedefs so the public dls headers don't need to be modified */ | |
291 #define FAR | |
292 typedef Uint8 BYTE; | |
293 typedef Sint16 SHORT; | |
294 typedef Uint16 USHORT; | |
295 typedef Uint16 WORD; | |
296 typedef Sint32 LONG; | |
297 typedef Uint32 ULONG; | |
298 typedef Uint32 DWORD; | |
299 #define mmioFOURCC(A, B, C, D) \ | |
300 (((A) << 0) | ((B) << 8) | ((C) << 16) | ((D) << 24)) | |
301 #define DEFINE_GUID(A, B, C, E, F, G, H, I, J, K, L, M) | |
302 | |
303 #include "dls1.h" | |
304 #include "dls2.h" | |
305 | |
306 typedef struct _WaveFMT { | |
307 WORD wFormatTag; | |
308 WORD wChannels; | |
309 DWORD dwSamplesPerSec; | |
310 DWORD dwAvgBytesPerSec; | |
311 WORD wBlockAlign; | |
312 WORD wBitsPerSample; | |
313 } WaveFMT; | |
314 | |
315 typedef struct _DLS_Wave { | |
316 WaveFMT *format; | |
317 Uint8 *data; | |
318 Uint32 length; | |
319 WSMPL *wsmp; | |
320 WLOOP *wsmp_loop; | |
321 } DLS_Wave; | |
322 | |
323 typedef struct _DLS_Region { | |
324 RGNHEADER *header; | |
325 WAVELINK *wlnk; | |
326 WSMPL *wsmp; | |
327 WLOOP *wsmp_loop; | |
328 CONNECTIONLIST *art; | |
329 CONNECTION *artList; | |
330 } DLS_Region; | |
331 | |
332 typedef struct _DLS_Instrument { | |
333 const char *name; | |
334 INSTHEADER *header; | |
335 DLS_Region *regions; | |
336 CONNECTIONLIST *art; | |
337 CONNECTION *artList; | |
338 } DLS_Instrument; | |
339 | |
340 typedef struct _DLS_Data { | |
341 struct _RIFF_Chunk *chunk; | |
342 | |
343 Uint32 cInstruments; | |
344 DLS_Instrument *instruments; | |
345 | |
346 POOLTABLE *ptbl; | |
347 POOLCUE *ptblList; | |
348 DLS_Wave *waveList; | |
349 | |
350 const char *name; | |
351 const char *artist; | |
352 const char *copyright; | |
353 const char *comments; | |
354 } DLS_Data; | |
355 | |
356 extern DECLSPEC DLS_Data* SDLCALL LoadDLS(SDL_RWops *src); | |
357 extern DECLSPEC void SDLCALL FreeDLS(DLS_Data *chunk); | |
358 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
359 | |
360 /*-------------------------------------------------------------------------*/ | |
361 /* * * * * * * * * * * * * * * * * load_dls.c * * * * * * * * * * * * * * */ | |
362 /*-------------------------------------------------------------------------*/ | |
363 | |
364 #define FOURCC_LIST 0x5453494c /* "LIST" */ | |
365 #define FOURCC_FMT 0x20746D66 /* "fmt " */ | |
366 #define FOURCC_DATA 0x61746164 /* "data" */ | |
367 #define FOURCC_INFO mmioFOURCC('I','N','F','O') | |
368 #define FOURCC_IARL mmioFOURCC('I','A','R','L') | |
369 #define FOURCC_IART mmioFOURCC('I','A','R','T') | |
370 #define FOURCC_ICMS mmioFOURCC('I','C','M','S') | |
371 #define FOURCC_ICMT mmioFOURCC('I','C','M','T') | |
372 #define FOURCC_ICOP mmioFOURCC('I','C','O','P') | |
373 #define FOURCC_ICRD mmioFOURCC('I','C','R','D') | |
374 #define FOURCC_IENG mmioFOURCC('I','E','N','G') | |
375 #define FOURCC_IGNR mmioFOURCC('I','G','N','R') | |
376 #define FOURCC_IKEY mmioFOURCC('I','K','E','Y') | |
377 #define FOURCC_IMED mmioFOURCC('I','M','E','D') | |
378 #define FOURCC_INAM mmioFOURCC('I','N','A','M') | |
379 #define FOURCC_IPRD mmioFOURCC('I','P','R','D') | |
380 #define FOURCC_ISBJ mmioFOURCC('I','S','B','J') | |
381 #define FOURCC_ISFT mmioFOURCC('I','S','F','T') | |
382 #define FOURCC_ISRC mmioFOURCC('I','S','R','C') | |
383 #define FOURCC_ISRF mmioFOURCC('I','S','R','F') | |
384 #define FOURCC_ITCH mmioFOURCC('I','T','C','H') | |
385 | |
386 | |
387 static void FreeRegions(DLS_Instrument *instrument) | |
388 { | |
389 if ( instrument->regions ) { | |
390 free(instrument->regions); | |
391 } | |
392 } | |
393 | |
394 static void AllocRegions(DLS_Instrument *instrument) | |
395 { | |
396 int datalen = (instrument->header->cRegions * sizeof(DLS_Region)); | |
397 FreeRegions(instrument); | |
398 instrument->regions = (DLS_Region *)malloc(datalen); | |
399 if ( instrument->regions ) { | |
400 memset(instrument->regions, 0, datalen); | |
401 } | |
402 } | |
403 | |
404 static void FreeInstruments(DLS_Data *data) | |
405 { | |
406 if ( data->instruments ) { | |
407 Uint32 i; | |
408 for ( i = 0; i < data->cInstruments; ++i ) { | |
409 FreeRegions(&data->instruments[i]); | |
410 } | |
411 free(data->instruments); | |
412 } | |
413 } | |
414 | |
415 static void AllocInstruments(DLS_Data *data) | |
416 { | |
417 int datalen = (data->cInstruments * sizeof(DLS_Instrument)); | |
418 FreeInstruments(data); | |
419 data->instruments = (DLS_Instrument *)malloc(datalen); | |
420 if ( data->instruments ) { | |
421 memset(data->instruments, 0, datalen); | |
422 } | |
423 } | |
424 | |
425 static void FreeWaveList(DLS_Data *data) | |
426 { | |
427 if ( data->waveList ) { | |
428 free(data->waveList); | |
429 } | |
430 } | |
431 | |
432 static void AllocWaveList(DLS_Data *data) | |
433 { | |
434 int datalen = (data->ptbl->cCues * sizeof(DLS_Wave)); | |
435 FreeWaveList(data); | |
436 data->waveList = (DLS_Wave *)malloc(datalen); | |
437 if ( data->waveList ) { | |
438 memset(data->waveList, 0, datalen); | |
439 } | |
440 } | |
441 | |
442 static void Parse_colh(DLS_Data *data, RIFF_Chunk *chunk) | |
443 { | |
444 data->cInstruments = SDL_SwapLE32(*(Uint32 *)chunk->data); | |
445 AllocInstruments(data); | |
446 } | |
447 | |
448 static void Parse_insh(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument) | |
449 { | |
450 INSTHEADER *header = (INSTHEADER *)chunk->data; | |
451 header->cRegions = SDL_SwapLE32(header->cRegions); | |
452 header->Locale.ulBank = SDL_SwapLE32(header->Locale.ulBank); | |
453 header->Locale.ulInstrument = SDL_SwapLE32(header->Locale.ulInstrument); | |
454 instrument->header = header; | |
455 AllocRegions(instrument); | |
456 } | |
457 | |
458 static void Parse_rgnh(DLS_Data *data, RIFF_Chunk *chunk, DLS_Region *region) | |
459 { | |
460 RGNHEADER *header = (RGNHEADER *)chunk->data; | |
461 header->RangeKey.usLow = SDL_SwapLE16(header->RangeKey.usLow); | |
462 header->RangeKey.usHigh = SDL_SwapLE16(header->RangeKey.usHigh); | |
463 header->RangeVelocity.usLow = SDL_SwapLE16(header->RangeVelocity.usLow); | |
464 header->RangeVelocity.usHigh = SDL_SwapLE16(header->RangeVelocity.usHigh); | |
465 header->fusOptions = SDL_SwapLE16(header->fusOptions); | |
466 header->usKeyGroup = SDL_SwapLE16(header->usKeyGroup); | |
467 region->header = header; | |
468 } | |
469 | |
470 static void Parse_wlnk(DLS_Data *data, RIFF_Chunk *chunk, DLS_Region *region) | |
471 { | |
472 WAVELINK *wlnk = (WAVELINK *)chunk->data; | |
473 wlnk->fusOptions = SDL_SwapLE16(wlnk->fusOptions); | |
474 wlnk->usPhaseGroup = SDL_SwapLE16(wlnk->usPhaseGroup); | |
475 wlnk->ulChannel = SDL_SwapLE16(wlnk->ulChannel); | |
476 wlnk->ulTableIndex = SDL_SwapLE16(wlnk->ulTableIndex); | |
477 region->wlnk = wlnk; | |
478 } | |
479 | |
480 static void Parse_wsmp(DLS_Data *data, RIFF_Chunk *chunk, WSMPL **wsmp_ptr, WLOOP **wsmp_loop_ptr) | |
481 { | |
482 Uint32 i; | |
483 WSMPL *wsmp = (WSMPL *)chunk->data; | |
484 WLOOP *loop; | |
485 wsmp->cbSize = SDL_SwapLE32(wsmp->cbSize); | |
486 wsmp->usUnityNote = SDL_SwapLE16(wsmp->usUnityNote); | |
487 wsmp->sFineTune = SDL_SwapLE16(wsmp->sFineTune); | |
488 wsmp->lAttenuation = SDL_SwapLE32(wsmp->lAttenuation); | |
489 wsmp->fulOptions = SDL_SwapLE32(wsmp->fulOptions); | |
490 wsmp->cSampleLoops = SDL_SwapLE32(wsmp->cSampleLoops); | |
491 loop = (WLOOP *)((Uint8 *)chunk->data + wsmp->cbSize); | |
492 *wsmp_ptr = wsmp; | |
493 *wsmp_loop_ptr = loop; | |
494 for ( i = 0; i < wsmp->cSampleLoops; ++i ) { | |
495 loop->cbSize = SDL_SwapLE32(loop->cbSize); | |
496 loop->ulType = SDL_SwapLE32(loop->ulType); | |
497 loop->ulStart = SDL_SwapLE32(loop->ulStart); | |
498 loop->ulLength = SDL_SwapLE32(loop->ulLength); | |
499 ++loop; | |
500 } | |
501 } | |
502 | |
503 static void Parse_art(DLS_Data *data, RIFF_Chunk *chunk, CONNECTIONLIST **art_ptr, CONNECTION **artList_ptr) | |
504 { | |
505 Uint32 i; | |
506 CONNECTIONLIST *art = (CONNECTIONLIST *)chunk->data; | |
507 CONNECTION *artList; | |
508 art->cbSize = SDL_SwapLE32(art->cbSize); | |
509 art->cConnections = SDL_SwapLE32(art->cConnections); | |
510 artList = (CONNECTION *)((Uint8 *)chunk->data + art->cbSize); | |
511 *art_ptr = art; | |
512 *artList_ptr = artList; | |
513 for ( i = 0; i < art->cConnections; ++i ) { | |
514 artList->usSource = SDL_SwapLE16(artList->usSource); | |
515 artList->usControl = SDL_SwapLE16(artList->usControl); | |
516 artList->usDestination = SDL_SwapLE16(artList->usDestination); | |
517 artList->usTransform = SDL_SwapLE16(artList->usTransform); | |
518 artList->lScale = SDL_SwapLE32(artList->lScale); | |
519 ++artList; | |
520 } | |
521 } | |
522 | |
523 static void Parse_lart(DLS_Data *data, RIFF_Chunk *chunk, CONNECTIONLIST **conn_ptr, CONNECTION **connList_ptr) | |
524 { | |
525 /* FIXME: This only supports one set of connections */ | |
526 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
527 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
528 switch(magic) { | |
529 case FOURCC_ART1: | |
530 case FOURCC_ART2: | |
531 Parse_art(data, chunk, conn_ptr, connList_ptr); | |
532 return; | |
533 } | |
534 } | |
535 } | |
536 | |
537 static void Parse_rgn(DLS_Data *data, RIFF_Chunk *chunk, DLS_Region *region) | |
538 { | |
539 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
540 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
541 switch(magic) { | |
542 case FOURCC_RGNH: | |
543 Parse_rgnh(data, chunk, region); | |
544 break; | |
545 case FOURCC_WLNK: | |
546 Parse_wlnk(data, chunk, region); | |
547 break; | |
548 case FOURCC_WSMP: | |
549 Parse_wsmp(data, chunk, ®ion->wsmp, ®ion->wsmp_loop); | |
550 break; | |
551 case FOURCC_LART: | |
552 case FOURCC_LAR2: | |
553 Parse_lart(data, chunk, ®ion->art, ®ion->artList); | |
554 break; | |
555 } | |
556 } | |
557 } | |
558 | |
559 static void Parse_lrgn(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument) | |
560 { | |
561 Uint32 region = 0; | |
562 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
563 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
564 switch(magic) { | |
565 case FOURCC_RGN: | |
566 case FOURCC_RGN2: | |
567 if ( region < instrument->header->cRegions ) { | |
568 Parse_rgn(data, chunk, &instrument->regions[region++]); | |
569 } | |
570 break; | |
571 } | |
572 } | |
573 } | |
574 | |
575 static void Parse_INFO_INS(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument) | |
576 { | |
577 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
578 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
579 switch(magic) { | |
580 case FOURCC_INAM: /* Name */ | |
581 instrument->name = chunk->data; | |
582 break; | |
583 } | |
584 } | |
585 } | |
586 | |
587 static void Parse_ins(DLS_Data *data, RIFF_Chunk *chunk, DLS_Instrument *instrument) | |
588 { | |
589 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
590 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
591 switch(magic) { | |
592 case FOURCC_INSH: | |
593 Parse_insh(data, chunk, instrument); | |
594 break; | |
595 case FOURCC_LRGN: | |
596 Parse_lrgn(data, chunk, instrument); | |
597 break; | |
598 case FOURCC_LART: | |
599 case FOURCC_LAR2: | |
600 Parse_lart(data, chunk, &instrument->art, &instrument->artList); | |
601 break; | |
602 case FOURCC_INFO: | |
603 Parse_INFO_INS(data, chunk, instrument); | |
604 break; | |
605 } | |
606 } | |
607 } | |
608 | |
609 static void Parse_lins(DLS_Data *data, RIFF_Chunk *chunk) | |
610 { | |
611 Uint32 instrument = 0; | |
612 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
613 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
614 switch(magic) { | |
615 case FOURCC_INS: | |
616 if ( instrument < data->cInstruments ) { | |
617 Parse_ins(data, chunk, &data->instruments[instrument++]); | |
618 } | |
619 break; | |
620 } | |
621 } | |
622 } | |
623 | |
624 static void Parse_ptbl(DLS_Data *data, RIFF_Chunk *chunk) | |
625 { | |
626 Uint32 i; | |
627 POOLTABLE *ptbl = (POOLTABLE *)chunk->data; | |
628 ptbl->cbSize = SDL_SwapLE32(ptbl->cbSize); | |
629 ptbl->cCues = SDL_SwapLE32(ptbl->cCues); | |
630 data->ptbl = ptbl; | |
631 data->ptblList = (POOLCUE *)((Uint8 *)chunk->data + ptbl->cbSize); | |
632 for ( i = 0; i < ptbl->cCues; ++i ) { | |
633 data->ptblList[i].ulOffset = SDL_SwapLE32(data->ptblList[i].ulOffset); | |
634 } | |
635 AllocWaveList(data); | |
636 } | |
637 | |
638 static void Parse_fmt(DLS_Data *data, RIFF_Chunk *chunk, DLS_Wave *wave) | |
639 { | |
640 WaveFMT *fmt = (WaveFMT *)chunk->data; | |
641 fmt->wFormatTag = SDL_SwapLE16(fmt->wFormatTag); | |
642 fmt->wChannels = SDL_SwapLE16(fmt->wChannels); | |
643 fmt->dwSamplesPerSec = SDL_SwapLE32(fmt->dwSamplesPerSec); | |
644 fmt->dwAvgBytesPerSec = SDL_SwapLE32(fmt->dwAvgBytesPerSec); | |
645 fmt->wBlockAlign = SDL_SwapLE16(fmt->wBlockAlign); | |
646 fmt->wBitsPerSample = SDL_SwapLE16(fmt->wBitsPerSample); | |
647 wave->format = fmt; | |
648 } | |
649 | |
650 static void Parse_data(DLS_Data *data, RIFF_Chunk *chunk, DLS_Wave *wave) | |
651 { | |
652 wave->data = chunk->data; | |
653 wave->length = chunk->length; | |
654 } | |
655 | |
656 static void Parse_wave(DLS_Data *data, RIFF_Chunk *chunk, DLS_Wave *wave) | |
657 { | |
658 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
659 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
660 switch(magic) { | |
661 case FOURCC_FMT: | |
662 Parse_fmt(data, chunk, wave); | |
663 break; | |
664 case FOURCC_DATA: | |
665 Parse_data(data, chunk, wave); | |
666 break; | |
667 case FOURCC_WSMP: | |
668 Parse_wsmp(data, chunk, &wave->wsmp, &wave->wsmp_loop); | |
669 break; | |
670 } | |
671 } | |
672 } | |
673 | |
674 static void Parse_wvpl(DLS_Data *data, RIFF_Chunk *chunk) | |
675 { | |
676 Uint32 wave = 0; | |
677 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
678 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
679 switch(magic) { | |
680 case FOURCC_wave: | |
681 if ( wave < data->ptbl->cCues ) { | |
682 Parse_wave(data, chunk, &data->waveList[wave++]); | |
683 } | |
684 break; | |
685 } | |
686 } | |
687 } | |
688 | |
689 static void Parse_INFO_DLS(DLS_Data *data, RIFF_Chunk *chunk) | |
690 { | |
691 for ( chunk = chunk->child; chunk; chunk = chunk->next ) { | |
692 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
693 switch(magic) { | |
694 case FOURCC_IARL: /* Archival Location */ | |
695 break; | |
696 case FOURCC_IART: /* Artist */ | |
697 data->artist = chunk->data; | |
698 break; | |
699 case FOURCC_ICMS: /* Commisioned */ | |
700 break; | |
701 case FOURCC_ICMT: /* Comments */ | |
702 data->comments = chunk->data; | |
703 break; | |
704 case FOURCC_ICOP: /* Copyright */ | |
705 data->copyright = chunk->data; | |
706 break; | |
707 case FOURCC_ICRD: /* Creation Date */ | |
708 break; | |
709 case FOURCC_IENG: /* Engineer */ | |
710 break; | |
711 case FOURCC_IGNR: /* Genre */ | |
712 break; | |
713 case FOURCC_IKEY: /* Keywords */ | |
714 break; | |
715 case FOURCC_IMED: /* Medium */ | |
716 break; | |
717 case FOURCC_INAM: /* Name */ | |
718 data->name = chunk->data; | |
719 break; | |
720 case FOURCC_IPRD: /* Product */ | |
721 break; | |
722 case FOURCC_ISBJ: /* Subject */ | |
723 break; | |
724 case FOURCC_ISFT: /* Software */ | |
725 break; | |
726 case FOURCC_ISRC: /* Source */ | |
727 break; | |
728 case FOURCC_ISRF: /* Source Form */ | |
729 break; | |
730 case FOURCC_ITCH: /* Technician */ | |
731 break; | |
732 } | |
733 } | |
734 } | |
735 | |
736 DLS_Data *LoadDLS(SDL_RWops *src) | |
737 { | |
738 RIFF_Chunk *chunk; | |
739 DLS_Data *data = (DLS_Data *)malloc(sizeof(*data)); | |
740 if ( !data ) { | |
459
4d2febf33dc7
Changed some SDL_Error()s to __Sound_SetError() to fix linking issues.
Ryan C. Gordon <icculus@icculus.org>
parents:
458
diff
changeset
|
741 __Sound_SetError(ERR_OUT_OF_MEMORY); |
455 | 742 return NULL; |
743 } | |
744 memset(data, 0, sizeof(*data)); | |
745 | |
746 data->chunk = LoadRIFF(src); | |
747 if ( !data->chunk ) { | |
748 FreeDLS(data); | |
749 return NULL; | |
750 } | |
751 | |
752 for ( chunk = data->chunk->child; chunk; chunk = chunk->next ) { | |
753 Uint32 magic = (chunk->magic == FOURCC_LIST) ? chunk->subtype : chunk->magic; | |
754 switch(magic) { | |
755 case FOURCC_COLH: | |
756 Parse_colh(data, chunk); | |
757 break; | |
758 case FOURCC_LINS: | |
759 Parse_lins(data, chunk); | |
760 break; | |
761 case FOURCC_PTBL: | |
762 Parse_ptbl(data, chunk); | |
763 break; | |
764 case FOURCC_WVPL: | |
765 Parse_wvpl(data, chunk); | |
766 break; | |
767 case FOURCC_INFO: | |
768 Parse_INFO_DLS(data, chunk); | |
769 break; | |
770 } | |
771 } | |
772 return data; | |
773 } | |
774 | |
775 void FreeDLS(DLS_Data *data) | |
776 { | |
777 if ( data->chunk ) { | |
778 FreeRIFF(data->chunk); | |
779 } | |
780 FreeInstruments(data); | |
781 FreeWaveList(data); | |
782 free(data); | |
783 } | |
784 | |
785 static const char *SourceToString(USHORT usSource) | |
786 { | |
787 switch(usSource) { | |
788 case CONN_SRC_NONE: | |
789 return "NONE"; | |
790 case CONN_SRC_LFO: | |
791 return "LFO"; | |
792 case CONN_SRC_KEYONVELOCITY: | |
793 return "KEYONVELOCITY"; | |
794 case CONN_SRC_KEYNUMBER: | |
795 return "KEYNUMBER"; | |
796 case CONN_SRC_EG1: | |
797 return "EG1"; | |
798 case CONN_SRC_EG2: | |
799 return "EG2"; | |
800 case CONN_SRC_PITCHWHEEL: | |
801 return "PITCHWHEEL"; | |
802 case CONN_SRC_CC1: | |
803 return "CC1"; | |
804 case CONN_SRC_CC7: | |
805 return "CC7"; | |
806 case CONN_SRC_CC10: | |
807 return "CC10"; | |
808 case CONN_SRC_CC11: | |
809 return "CC11"; | |
810 case CONN_SRC_POLYPRESSURE: | |
811 return "POLYPRESSURE"; | |
812 case CONN_SRC_CHANNELPRESSURE: | |
813 return "CHANNELPRESSURE"; | |
814 case CONN_SRC_VIBRATO: | |
815 return "VIBRATO"; | |
816 case CONN_SRC_MONOPRESSURE: | |
817 return "MONOPRESSURE"; | |
818 case CONN_SRC_CC91: | |
819 return "CC91"; | |
820 case CONN_SRC_CC93: | |
821 return "CC93"; | |
822 default: | |
823 return "UNKNOWN"; | |
824 } | |
825 } | |
826 | |
827 static const char *TransformToString(USHORT usTransform) | |
828 { | |
829 switch (usTransform) { | |
830 case CONN_TRN_NONE: | |
831 return "NONE"; | |
832 case CONN_TRN_CONCAVE: | |
833 return "CONCAVE"; | |
834 case CONN_TRN_CONVEX: | |
835 return "CONVEX"; | |
836 case CONN_TRN_SWITCH: | |
837 return "SWITCH"; | |
838 default: | |
839 return "UNKNOWN"; | |
840 } | |
841 } | |
842 | |
843 static const char *DestinationToString(USHORT usDestination) | |
844 { | |
845 switch (usDestination) { | |
846 case CONN_DST_NONE: | |
847 return "NONE"; | |
848 case CONN_DST_ATTENUATION: | |
849 return "ATTENUATION"; | |
850 case CONN_DST_PITCH: | |
851 return "PITCH"; | |
852 case CONN_DST_PAN: | |
853 return "PAN"; | |
854 case CONN_DST_LFO_FREQUENCY: | |
855 return "LFO_FREQUENCY"; | |
856 case CONN_DST_LFO_STARTDELAY: | |
857 return "LFO_STARTDELAY"; | |
858 case CONN_DST_EG1_ATTACKTIME: | |
859 return "EG1_ATTACKTIME"; | |
860 case CONN_DST_EG1_DECAYTIME: | |
861 return "EG1_DECAYTIME"; | |
862 case CONN_DST_EG1_RELEASETIME: | |
863 return "EG1_RELEASETIME"; | |
864 case CONN_DST_EG1_SUSTAINLEVEL: | |
865 return "EG1_SUSTAINLEVEL"; | |
866 case CONN_DST_EG2_ATTACKTIME: | |
867 return "EG2_ATTACKTIME"; | |
868 case CONN_DST_EG2_DECAYTIME: | |
869 return "EG2_DECAYTIME"; | |
870 case CONN_DST_EG2_RELEASETIME: | |
871 return "EG2_RELEASETIME"; | |
872 case CONN_DST_EG2_SUSTAINLEVEL: | |
873 return "EG2_SUSTAINLEVEL"; | |
874 case CONN_DST_KEYNUMBER: | |
875 return "KEYNUMBER"; | |
876 case CONN_DST_LEFT: | |
877 return "LEFT"; | |
878 case CONN_DST_RIGHT: | |
879 return "RIGHT"; | |
880 case CONN_DST_CENTER: | |
881 return "CENTER"; | |
882 case CONN_DST_LEFTREAR: | |
883 return "LEFTREAR"; | |
884 case CONN_DST_RIGHTREAR: | |
885 return "RIGHTREAR"; | |
886 case CONN_DST_LFE_CHANNEL: | |
887 return "LFE_CHANNEL"; | |
888 case CONN_DST_CHORUS: | |
889 return "CHORUS"; | |
890 case CONN_DST_REVERB: | |
891 return "REVERB"; | |
892 case CONN_DST_VIB_FREQUENCY: | |
893 return "VIB_FREQUENCY"; | |
894 case CONN_DST_VIB_STARTDELAY: | |
895 return "VIB_STARTDELAY"; | |
896 case CONN_DST_EG1_DELAYTIME: | |
897 return "EG1_DELAYTIME"; | |
898 case CONN_DST_EG1_HOLDTIME: | |
899 return "EG1_HOLDTIME"; | |
900 case CONN_DST_EG1_SHUTDOWNTIME: | |
901 return "EG1_SHUTDOWNTIME"; | |
902 case CONN_DST_EG2_DELAYTIME: | |
903 return "EG2_DELAYTIME"; | |
904 case CONN_DST_EG2_HOLDTIME: | |
905 return "EG2_HOLDTIME"; | |
906 case CONN_DST_FILTER_CUTOFF: | |
907 return "FILTER_CUTOFF"; | |
908 case CONN_DST_FILTER_Q: | |
909 return "FILTER_Q"; | |
910 default: | |
911 return "UNKOWN"; | |
912 } | |
913 } | |
914 | |
915 static void PrintArt(const char *type, CONNECTIONLIST *art, CONNECTION *artList) | |
916 { | |
917 Uint32 i; | |
918 printf("%s Connections:\n", type); | |
919 for ( i = 0; i < art->cConnections; ++i ) { | |
920 printf(" Source: %s, Control: %s, Destination: %s, Transform: %s, Scale: %d\n", | |
921 SourceToString(artList[i].usSource), | |
922 SourceToString(artList[i].usControl), | |
923 DestinationToString(artList[i].usDestination), | |
924 TransformToString(artList[i].usTransform), | |
925 artList[i].lScale); | |
926 } | |
927 } | |
928 | |
929 static void PrintWave(DLS_Wave *wave, Uint32 index) | |
930 { | |
931 WaveFMT *format = wave->format; | |
932 if ( format ) { | |
933 printf(" Wave %u: Format: %hu, %hu channels, %u Hz, %hu bits (length = %u)\n", index, format->wFormatTag, format->wChannels, format->dwSamplesPerSec, format->wBitsPerSample, wave->length); | |
934 } | |
935 if ( wave->wsmp ) { | |
936 Uint32 i; | |
937 printf(" wsmp->usUnityNote = %hu\n", wave->wsmp->usUnityNote); | |
938 printf(" wsmp->sFineTune = %hd\n", wave->wsmp->sFineTune); | |
939 printf(" wsmp->lAttenuation = %d\n", wave->wsmp->lAttenuation); | |
940 printf(" wsmp->fulOptions = 0x%8.8x\n", wave->wsmp->fulOptions); | |
941 printf(" wsmp->cSampleLoops = %u\n", wave->wsmp->cSampleLoops); | |
942 for ( i = 0; i < wave->wsmp->cSampleLoops; ++i ) { | |
943 WLOOP *loop = &wave->wsmp_loop[i]; | |
944 printf(" Loop %u:\n", i); | |
945 printf(" ulStart = %u\n", loop->ulStart); | |
946 printf(" ulLength = %u\n", loop->ulLength); | |
947 } | |
948 } | |
949 } | |
950 | |
951 static void PrintRegion(DLS_Region *region, Uint32 index) | |
952 { | |
953 printf(" Region %u:\n", index); | |
954 if ( region->header ) { | |
955 printf(" RangeKey = { %hu - %hu }\n", region->header->RangeKey.usLow, region->header->RangeKey.usHigh); | |
956 printf(" RangeVelocity = { %hu - %hu }\n", region->header->RangeVelocity.usLow, region->header->RangeVelocity.usHigh); | |
957 printf(" fusOptions = 0x%4.4hx\n", region->header->fusOptions); | |
958 printf(" usKeyGroup = %hu\n", region->header->usKeyGroup); | |
959 } | |
960 if ( region->wlnk ) { | |
961 printf(" wlnk->fusOptions = 0x%4.4hx\n", region->wlnk->fusOptions); | |
962 printf(" wlnk->usPhaseGroup = %hu\n", region->wlnk->usPhaseGroup); | |
963 printf(" wlnk->ulChannel = %u\n", region->wlnk->ulChannel); | |
964 printf(" wlnk->ulTableIndex = %u\n", region->wlnk->ulTableIndex); | |
965 } | |
966 if ( region->wsmp ) { | |
967 Uint32 i; | |
968 printf(" wsmp->usUnityNote = %hu\n", region->wsmp->usUnityNote); | |
969 printf(" wsmp->sFineTune = %hd\n", region->wsmp->sFineTune); | |
970 printf(" wsmp->lAttenuation = %d\n", region->wsmp->lAttenuation); | |
971 printf(" wsmp->fulOptions = 0x%8.8x\n", region->wsmp->fulOptions); | |
972 printf(" wsmp->cSampleLoops = %u\n", region->wsmp->cSampleLoops); | |
973 for ( i = 0; i < region->wsmp->cSampleLoops; ++i ) { | |
974 WLOOP *loop = ®ion->wsmp_loop[i]; | |
975 printf(" Loop %u:\n", i); | |
976 printf(" ulStart = %u\n", loop->ulStart); | |
977 printf(" ulLength = %u\n", loop->ulLength); | |
978 } | |
979 } | |
980 if ( region->art && region->art->cConnections > 0 ) { | |
981 PrintArt("Region", region->art, region->artList); | |
982 } | |
983 } | |
984 | |
985 static void PrintInstrument(DLS_Instrument *instrument, Uint32 index) | |
986 { | |
987 printf("Instrument %u:\n", index); | |
988 if ( instrument->name ) { | |
989 printf(" Name: %s\n", instrument->name); | |
990 } | |
991 if ( instrument->header ) { | |
992 Uint32 i; | |
993 printf(" ulBank = 0x%8.8x\n", instrument->header->Locale.ulBank); | |
994 printf(" ulInstrument = %u\n", instrument->header->Locale.ulInstrument); | |
995 printf(" Regions: %u\n", instrument->header->cRegions); | |
996 for ( i = 0; i < instrument->header->cRegions; ++i ) { | |
997 PrintRegion(&instrument->regions[i], i); | |
998 } | |
999 } | |
1000 if ( instrument->art && instrument->art->cConnections > 0 ) { | |
1001 PrintArt("Instrument", instrument->art, instrument->artList); | |
1002 } | |
1003 }; | |
1004 | |
1005 void PrintDLS(DLS_Data *data) | |
1006 { | |
1007 printf("DLS Data:\n"); | |
1008 printf("cInstruments = %u\n", data->cInstruments); | |
1009 if ( data->instruments ) { | |
1010 Uint32 i; | |
1011 for ( i = 0; i < data->cInstruments; ++i ) { | |
1012 PrintInstrument(&data->instruments[i], i); | |
1013 } | |
1014 } | |
1015 if ( data->ptbl && data->ptbl->cCues > 0 ) { | |
1016 Uint32 i; | |
1017 printf("Cues: "); | |
1018 for ( i = 0; i < data->ptbl->cCues; ++i ) { | |
1019 if ( i > 0 ) { | |
1020 printf(", "); | |
1021 } | |
1022 printf("%u", data->ptblList[i].ulOffset); | |
1023 } | |
1024 printf("\n"); | |
1025 } | |
1026 if ( data->waveList ) { | |
1027 Uint32 i; | |
1028 printf("Waves:\n"); | |
1029 for ( i = 0; i < data->ptbl->cCues; ++i ) { | |
1030 PrintWave(&data->waveList[i], i); | |
1031 } | |
1032 } | |
1033 if ( data->name ) { | |
1034 printf("Name: %s\n", data->name); | |
1035 } | |
1036 if ( data->artist ) { | |
1037 printf("Artist: %s\n", data->artist); | |
1038 } | |
1039 if ( data->copyright ) { | |
1040 printf("Copyright: %s\n", data->copyright); | |
1041 } | |
1042 if ( data->comments ) { | |
1043 printf("Comments: %s\n", data->comments); | |
1044 } | |
1045 } | |
1046 | |
1047 #ifdef TEST_MAIN_DLS | |
1048 | |
1049 main(int argc, char *argv[]) | |
1050 { | |
1051 int i; | |
1052 for ( i = 1; i < argc; ++i ) { | |
1053 DLS_Data *data; | |
1054 SDL_RWops *src = SDL_RWFromFile(argv[i], "rb"); | |
1055 if ( !src ) { | |
1056 fprintf(stderr, "Couldn't open %s: %s", argv[i], SDL_GetError()); | |
1057 continue; | |
1058 } | |
1059 data = LoadDLS(src); | |
1060 if ( data ) { | |
1061 PrintRIFF(data->chunk, 0); | |
1062 PrintDLS(data); | |
1063 FreeDLS(data); | |
1064 } else { | |
1065 fprintf(stderr, "Couldn't load %s: %s\n", argv[i], SDL_GetError()); | |
1066 } | |
1067 SDL_RWclose(src); | |
1068 } | |
1069 } | |
1070 | |
1071 #endif // TEST_MAIN | |
1072 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
1073 | |
1074 /*-------------------------------------------------------------------------*/ | |
1075 /* * * * * * * * * * * * * * * * * instrum_dls.c * * * * * * * * * * * * * */ | |
1076 /*-------------------------------------------------------------------------*/ | |
1077 | |
1078 DLS_Data *Timidity_LoadDLS(SDL_RWops *src) | |
1079 { | |
1080 DLS_Data *patches = LoadDLS(src); | |
1081 if (!patches) { | |
1082 SNDDBG(("%s", SDL_GetError())); | |
1083 } | |
1084 return patches; | |
1085 } | |
1086 | |
1087 void Timidity_FreeDLS(DLS_Data *patches) | |
1088 { | |
1089 FreeDLS(patches); | |
1090 } | |
1091 | |
1092 /* convert timecents to sec */ | |
1093 static double to_msec(int timecent) | |
1094 { | |
1095 if (timecent == 0x80000000 || timecent == 0) | |
1096 return 0.0; | |
1097 return 1000.0 * pow(2.0, (double)(timecent / 65536) / 1200.0); | |
1098 } | |
1099 | |
1100 /* convert decipercent to {0..1} */ | |
1101 static double to_normalized_percent(int decipercent) | |
1102 { | |
1103 return ((double)(decipercent / 65536)) / 1000.0; | |
1104 } | |
1105 | |
1106 /* convert from 8bit value to fractional offset (15.15) */ | |
1107 static Sint32 to_offset(int offset) | |
1108 { | |
1109 return (Sint32)offset << (7+15); | |
1110 } | |
1111 | |
1112 /* calculate ramp rate in fractional unit; | |
1113 * diff = 8bit, time = msec | |
1114 */ | |
1115 static Sint32 calc_rate(MidiSong *song, int diff, int sample_rate, double msec) | |
1116 { | |
1117 double rate; | |
1118 | |
1119 if(msec < 6) | |
1120 msec = 6; | |
1121 if(diff == 0) | |
1122 diff = 255; | |
1123 diff <<= (7+15); | |
1124 rate = ((double)diff / song->rate) * song->control_ratio * 1000.0 / msec; | |
1125 return (Sint32)rate; | |
1126 } | |
1127 | |
1128 static int load_connection(ULONG cConnections, CONNECTION *artList, USHORT destination) | |
1129 { | |
1130 ULONG i; | |
1131 int value = 0; | |
1132 for (i = 0; i < cConnections; ++i) { | |
1133 CONNECTION *conn = &artList[i]; | |
1134 if(conn->usDestination == destination) { | |
1135 // The formula for the destination is: | |
1136 // usDestination = usDestination + usTransform(usSource * (usControl * lScale)) | |
1137 // Since we are only handling source/control of NONE and identity | |
1138 // transform, this simplifies to: usDestination = usDestination + lScale | |
1139 if (conn->usSource == CONN_SRC_NONE && | |
1140 conn->usControl == CONN_SRC_NONE && | |
1141 conn->usTransform == CONN_TRN_NONE) | |
1142 value += conn->lScale; | |
1143 } | |
1144 } | |
1145 return value; | |
1146 } | |
1147 | |
1148 static void load_region_dls(MidiSong *song, Sample *sample, DLS_Instrument *ins, Uint32 index) | |
1149 { | |
1150 DLS_Region *rgn = &ins->regions[index]; | |
1151 DLS_Wave *wave = &song->patches->waveList[rgn->wlnk->ulTableIndex]; | |
1152 | |
1153 sample->low_freq = freq_table[rgn->header->RangeKey.usLow]; | |
1154 sample->high_freq = freq_table[rgn->header->RangeKey.usHigh]; | |
1155 sample->root_freq = freq_table[rgn->wsmp->usUnityNote]; | |
1156 sample->low_vel = rgn->header->RangeVelocity.usLow; | |
1157 sample->high_vel = rgn->header->RangeVelocity.usHigh; | |
1158 | |
1159 sample->modes = MODES_16BIT; | |
1160 sample->sample_rate = wave->format->dwSamplesPerSec; | |
1161 sample->data_length = wave->length / 2; | |
1162 sample->data = (sample_t *)safe_malloc(wave->length); | |
1163 memcpy(sample->data, wave->data, wave->length); | |
1164 if (rgn->wsmp->cSampleLoops) { | |
1165 sample->modes |= (MODES_LOOPING|MODES_SUSTAIN); | |
1166 sample->loop_start = rgn->wsmp_loop->ulStart / 2; | |
1167 sample->loop_end = sample->loop_start + (rgn->wsmp_loop->ulLength / 2); | |
1168 } | |
1169 sample->volume = 1.0f; | |
1170 | |
1171 if (sample->modes & MODES_SUSTAIN) { | |
1172 int value; | |
1173 double attack, hold, decay, release; int sustain; | |
1174 CONNECTIONLIST *art = NULL; | |
1175 CONNECTION *artList = NULL; | |
1176 | |
1177 if (ins->art && ins->art->cConnections > 0 && ins->artList) { | |
1178 art = ins->art; | |
1179 artList = ins->artList; | |
1180 } else { | |
1181 art = rgn->art; | |
1182 artList = rgn->artList; | |
1183 } | |
1184 | |
1185 value = load_connection(art->cConnections, artList, CONN_DST_EG1_ATTACKTIME); | |
1186 attack = to_msec(value); | |
1187 value = load_connection(art->cConnections, artList, CONN_DST_EG1_HOLDTIME); | |
1188 hold = to_msec(value); | |
1189 value = load_connection(art->cConnections, artList, CONN_DST_EG1_DECAYTIME); | |
1190 decay = to_msec(value); | |
1191 value = load_connection(art->cConnections, artList, CONN_DST_EG1_RELEASETIME); | |
1192 release = to_msec(value); | |
1193 value = load_connection(art->cConnections, artList, CONN_DST_EG1_SUSTAINLEVEL); | |
1194 sustain = (int)((1.0 - to_normalized_percent(value)) * 250.0); | |
1195 value = load_connection(art->cConnections, artList, CONN_DST_PAN); | |
1196 sample->panning = (int)((0.5 + to_normalized_percent(value)) * 127.0); | |
1197 | |
1198 /* | |
1199 printf("%d, Rate=%d LV=%d HV=%d Low=%d Hi=%d Root=%d Pan=%d Attack=%f Hold=%f Sustain=%d Decay=%f Release=%f\n", index, sample->sample_rate, rgn->header->RangeVelocity.usLow, rgn->header->RangeVelocity.usHigh, sample->low_freq, sample->high_freq, sample->root_freq, sample->panning, attack, hold, sustain, decay, release); | |
1200 */ | |
1201 | |
1202 sample->envelope_offset[0] = to_offset(255); | |
1203 sample->envelope_rate[0] = calc_rate(song, 255, sample->sample_rate, attack); | |
1204 | |
1205 sample->envelope_offset[1] = to_offset(250); | |
1206 sample->envelope_rate[1] = calc_rate(song, 5, sample->sample_rate, hold); | |
1207 | |
1208 sample->envelope_offset[2] = to_offset(sustain); | |
1209 sample->envelope_rate[2] = calc_rate(song, 255 - sustain, sample->sample_rate, decay); | |
1210 | |
1211 sample->envelope_offset[3] = to_offset(0); | |
1212 sample->envelope_rate[3] = calc_rate(song, 5 + sustain, sample->sample_rate, release); | |
1213 | |
1214 sample->envelope_offset[4] = to_offset(0); | |
1215 sample->envelope_rate[4] = to_offset(1); | |
1216 | |
1217 sample->envelope_offset[5] = to_offset(0); | |
1218 sample->envelope_rate[5] = to_offset(1); | |
1219 | |
1220 sample->modes |= MODES_ENVELOPE; | |
1221 } | |
1222 | |
1223 sample->data_length <<= FRACTION_BITS; | |
1224 sample->loop_start <<= FRACTION_BITS; | |
1225 sample->loop_end <<= FRACTION_BITS; | |
1226 } | |
1227 | |
1228 Instrument *load_instrument_dls(MidiSong *song, int drum, int bank, int instrument) | |
1229 { | |
1230 Instrument *inst; | |
1231 Uint32 i; | |
1232 DLS_Instrument *dls_ins; | |
1233 | |
1234 if (!song->patches) | |
1235 return(NULL); | |
1236 | |
1237 drum = drum ? 0x80000000 : 0; | |
1238 for (i = 0; i < song->patches->cInstruments; ++i) { | |
1239 dls_ins = &song->patches->instruments[i]; | |
1240 if ((dls_ins->header->Locale.ulBank & 0x80000000) == drum && | |
1241 ((dls_ins->header->Locale.ulBank >> 8) & 0xFF) == bank && | |
1242 dls_ins->header->Locale.ulInstrument == instrument) | |
1243 break; | |
1244 } | |
1245 if (i == song->patches->cInstruments && !bank) { | |
1246 for (i = 0; i < song->patches->cInstruments; ++i) { | |
1247 dls_ins = &song->patches->instruments[i]; | |
1248 if ((dls_ins->header->Locale.ulBank & 0x80000000) == drum && | |
1249 dls_ins->header->Locale.ulInstrument == instrument) | |
1250 break; | |
1251 } | |
1252 } | |
1253 if (i == song->patches->cInstruments) { | |
1254 SNDDBG(("Couldn't find %s instrument %d in bank %d\n", drum ? "drum" : "melodic", instrument, bank)); | |
1255 return(NULL); | |
1256 } | |
1257 | |
1258 inst = (Instrument *)safe_malloc(sizeof(*inst)); | |
1259 inst->samples = dls_ins->header->cRegions; | |
1260 inst->sample = (Sample *)safe_malloc(inst->samples * sizeof(*inst->sample)); | |
1261 memset(inst->sample, 0, inst->samples * sizeof(*inst->sample)); | |
1262 /* | |
1263 printf("Found %s instrument %d in bank %d named %s with %d regions\n", drum ? "drum" : "melodic", instrument, bank, dls_ins->name, inst->samples); | |
1264 */ | |
1265 for (i = 0; i < dls_ins->header->cRegions; ++i) { | |
1266 load_region_dls(song, &inst->sample[i], dls_ins, i); | |
1267 } | |
1268 return(inst); | |
1269 } |