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