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 ) {
|
|
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 }
|