eas_mdls.c revision 7df30109963092559d3760c0661a020f9daf1030
1/*----------------------------------------------------------------------------
2 *
3 * File:
4 * eas_mdls.c
5 *
6 * Contents and purpose:
7 * This file contains DLS to EAS converter.
8 *
9 * Copyright (c) 2005 Sonic Network Inc.
10
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 *----------------------------------------------------------------------------
24 * Revision Control:
25 *   $Revision: 818 $
26 *   $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $
27 *----------------------------------------------------------------------------
28*/
29
30/*
31 * NOTES:
32 *
33 * Processor Endian-ness:
34 *
35 * We use the EAS_HWGetDWord() and EAS_HWGetWord () functions
36 * extensively in this module. It would probably be faster to read
37 * an entire data structure, but this introduces the problem of
38 * sensitivity to processor endian-ness to the parser. By utlilizing
39 * the host wrapper functions, we avoid having to flip bytes around
40 * for big-endian processors. The default host wrapper versions of
41 * these functions are insensitive to processor endian-ness due to
42 * the fact that they read the file as a byte stream.
43 *
44 * Dynamic Memory:
45 *
46 * Dynamic memory allocation is a risky proposition in a mobile
47 * device. The memory can become fragmented, resulting in an
48 * inability to allocate a memory block, or garbage collection
49 * routines can use many CPU cycles. Either can contribute to
50 * failures of critical systems. Therefore, we try to minimize the
51 * number of memory allocations we make.
52 *
53 * We allocate a single large block of memory for the entire
54 * converted DLS collection, including the articulation data and
55 * samples. This block is then sub-allocated for the various
56 * data structures.
57 *
58 * Parser Overview:
59 *
60 * We make two passes through the file, the first pass to count the
61 * number of instruments, regions, etc. and allocate memory for
62 * them. The second pass parses the data into the allocated data
63 * structures.
64 *
65 * Conditional chunks are challenging in that they can occur
66 * anywhere in the list chunk that contains them. To simplify, we
67 * parse the blocks in a list in specific order, no matter which
68 * order they appear in the file. This way we don't allocate memory
69 * and parse a block that we end up throwing away later due to
70 * a conditional chunk.
71 *
72 * Assumptions that may bite us in the future:
73 *
74 * We make some assumptions to simplify things. The most fundamental
75 * assumption is that there will be no more than one of any type of
76 * chunk in a list. While this is consistent with the block diagram
77 * of the file layout in the mDLS spec, there is nothing in the
78 * spec that precludes having mulitple lar2 or rgn2 chunks, with
79 * conditional blocks that dictate their usage.
80 *
81 * DLS -> EAS Conversion Process:
82 *
83 * Another challenge is that the DLS structure does not map well to
84 * the current EAS sound library structure. Not all DLS constructs
85 * are supported, and data from DLS structures must sometimes be
86 * mapped to multiple EAS data structures. To simplify the process,
87 * the EAS region, articulation, and envelopes are treated as a
88 * single combined unit. Thus for each region, there must be one
89 * articulation element and two envelope elements.
90 *
91 * The sample processing is also a multi-step process. First the
92 * ptbl chunk is pre-parsed to determine the number of samples
93 * in the collection. The next step is to parse the instrument data
94 * to determine which samples are actually used by instruments.
95 * Some samples may not be used because they are used only in
96 * conditional blocks that the synthesizer cannot parse, or the
97 * author neglected to remove unused samples from the collection.
98 * In the next step, the active samples are read into memory and
99 * converted to the appropriate playback format. Finally, as the
100 * instruments are processed, the links are made to the samples and
101 * wsmp data is extracted for the region and articulation data
102 * structures.
103*/
104
105#ifndef _FILTER_ENABLED
106#error "Filter must be enabled if DLS_SYNTHESIZER is enabled"
107#endif
108
109/*------------------------------------
110 * includes
111 *------------------------------------
112*/
113
114/* this define allows us to use the sndlib.h structures as RW memory */
115#define SCNST
116
117#include "eas_data.h"
118#include "eas_host.h"
119#include "eas_mdls.h"
120#include "eas_math.h"
121#include "dls.h"
122#include "dls2.h"
123#include "eas_report.h"
124
125//2 we should replace log10() function with fixed point routine in ConvertSampleRate()
126/* lint is choking on the ARM math.h file, so we declare the log10 function here */
127extern double log10(double x);
128
129/*------------------------------------
130 * defines
131 *------------------------------------
132*/
133
134// #define _DEBUG_DLS
135
136#define DLS_MAX_WAVE_COUNT		1024
137#define DLS_MAX_ART_COUNT		2048
138#define DLS_MAX_REGION_COUNT	2048
139#define DLS_MAX_INST_COUNT		256
140#define MAX_DLS_WAVE_SIZE		(1024*1024)
141
142/*------------------------------------
143 * typedefs
144 *------------------------------------
145*/
146
147/* offsets to articulation data */
148typedef enum
149{
150	PARAM_MODIFIED = 0,
151	PARAM_MOD_LFO_FREQ,
152	PARAM_MOD_LFO_DELAY,
153
154	PARAM_VIB_LFO_FREQ,
155	PARAM_VIB_LFO_DELAY,
156
157	PARAM_VOL_EG_DELAY,
158	PARAM_VOL_EG_ATTACK,
159	PARAM_VOL_EG_HOLD,
160	PARAM_VOL_EG_DECAY,
161	PARAM_VOL_EG_SUSTAIN,
162	PARAM_VOL_EG_RELEASE,
163	PARAM_VOL_EG_SHUTDOWN,
164	PARAM_VOL_EG_VEL_TO_ATTACK,
165	PARAM_VOL_EG_KEY_TO_DECAY,
166	PARAM_VOL_EG_KEY_TO_HOLD,
167
168	PARAM_MOD_EG_DELAY,
169	PARAM_MOD_EG_ATTACK,
170	PARAM_MOD_EG_HOLD,
171	PARAM_MOD_EG_DECAY,
172	PARAM_MOD_EG_SUSTAIN,
173	PARAM_MOD_EG_RELEASE,
174	PARAM_MOD_EG_VEL_TO_ATTACK,
175	PARAM_MOD_EG_KEY_TO_DECAY,
176	PARAM_MOD_EG_KEY_TO_HOLD,
177
178	PARAM_INITIAL_FC,
179	PARAM_INITIAL_Q,
180	PARAM_MOD_LFO_TO_FC,
181	PARAM_MOD_LFO_CC1_TO_FC,
182	PARAM_MOD_LFO_CHAN_PRESS_TO_FC,
183	PARAM_MOD_EG_TO_FC,
184	PARAM_VEL_TO_FC,
185	PARAM_KEYNUM_TO_FC,
186
187	PARAM_MOD_LFO_TO_GAIN,
188	PARAM_MOD_LFO_CC1_TO_GAIN,
189	PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN,
190	PARAM_VEL_TO_GAIN,
191
192	PARAM_TUNING,
193	PARAM_KEYNUM_TO_PITCH,
194	PARAM_VIB_LFO_TO_PITCH,
195	PARAM_VIB_LFO_CC1_TO_PITCH,
196	PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH,
197	PARAM_MOD_LFO_TO_PITCH,
198	PARAM_MOD_LFO_CC1_TO_PITCH,
199	PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH,
200	PARAM_MOD_EG_TO_PITCH,
201
202	PARAM_DEFAULT_PAN,
203	PARAM_MIDI_CC91_TO_REVERB_SEND,
204	PARAM_DEFAULT_REVERB_SEND,
205	PARAM_MIDI_CC93_TO_CHORUS_SEND,
206	PARAM_DEFAULT_CHORUS_SEND,
207	PARAM_TABLE_SIZE
208} E_ART_INDEX;
209
210/* temporary data structure combining region, articulation, and envelope data */
211typedef struct s_art_dls_tag
212{
213	EAS_I16		values[PARAM_TABLE_SIZE];
214} S_DLS_ART_VALUES;
215
216/* temporary data structure for wlnk chunk data */
217typedef struct
218{
219	EAS_I32	gain;
220	EAS_U32	loopStart;
221	EAS_U32	loopLength;
222	EAS_U32	sampleRate;
223	EAS_U16	bitsPerSample;
224	EAS_I16	fineTune;
225	EAS_U8	unityNote;
226} S_WSMP_DATA;
227
228/* temporary data structure used while parsing a DLS file */
229typedef struct
230{
231	S_DLS				*pDLS;
232	EAS_HW_DATA_HANDLE	hwInstData;
233	EAS_FILE_HANDLE		fileHandle;
234	S_WSMP_DATA			*wsmpData;
235	EAS_U32				instCount;
236	EAS_U32				regionCount;
237	EAS_U32				artCount;
238	EAS_U32				waveCount;
239	EAS_U32				wavePoolSize;
240	EAS_U32				wavePoolOffset;
241	EAS_BOOL			bigEndian;
242	EAS_BOOL			filterUsed;
243} SDLS_SYNTHESIZER_DATA;
244
245/* connection lookup table */
246typedef struct s_connection_tag
247{
248	EAS_U16 source;
249	EAS_U16 control;
250	EAS_U16 destination;
251	EAS_U16 connection;
252} S_CONNECTION;
253
254static const S_CONNECTION connTable[] =
255{
256	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_FREQUENCY, PARAM_MOD_LFO_FREQ },
257	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_STARTDELAY, PARAM_MOD_LFO_DELAY},
258
259	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_FREQUENCY, PARAM_VIB_LFO_FREQ },
260	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_STARTDELAY, PARAM_VIB_LFO_DELAY },
261
262	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DELAYTIME, PARAM_VOL_EG_DELAY },
263	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_ATTACK },
264	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_HOLD },
265	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_DECAY },
266	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SUSTAINLEVEL, PARAM_VOL_EG_SUSTAIN },
267	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_RELEASETIME, PARAM_VOL_EG_RELEASE },
268	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SHUTDOWNTIME, PARAM_VOL_EG_SHUTDOWN },
269	{ CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_VEL_TO_ATTACK },
270	{ CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_KEY_TO_DECAY },
271	{ CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_KEY_TO_HOLD },
272
273	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DELAYTIME, PARAM_MOD_EG_DELAY },
274	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_ATTACK },
275	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_HOLD },
276	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_DECAY },
277	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_SUSTAINLEVEL, PARAM_MOD_EG_SUSTAIN },
278	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_RELEASETIME, PARAM_MOD_EG_RELEASE },
279	{ CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_VEL_TO_ATTACK },
280	{ CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_KEY_TO_DECAY },
281	{ CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_KEY_TO_HOLD },
282
283	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_INITIAL_FC },
284	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_Q, PARAM_INITIAL_Q },
285	{ CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_TO_FC },
286	{ CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CC1_TO_FC },
287	{ CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CHAN_PRESS_TO_FC },
288	{ CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_EG_TO_FC },
289	{ CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_VEL_TO_FC },
290	{ CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_KEYNUM_TO_FC },
291
292	{ CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_MOD_LFO_TO_GAIN },
293	{ CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_GAIN, PARAM_MOD_LFO_CC1_TO_GAIN },
294	{ CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_GAIN, PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN },
295	{ CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_VEL_TO_GAIN },
296
297	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_TUNING },
298	{ CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_KEYNUM_TO_PITCH },
299	{ CONN_SRC_VIBRATO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_VIB_LFO_TO_PITCH },
300	{ CONN_SRC_VIBRATO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_VIB_LFO_CC1_TO_PITCH },
301	{ CONN_SRC_VIBRATO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH },
302	{ CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_LFO_TO_PITCH },
303	{ CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_MOD_LFO_CC1_TO_PITCH },
304	{ CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH },
305	{ CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_EG_TO_PITCH },
306
307	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PAN, PARAM_DEFAULT_PAN },
308	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_DEFAULT_REVERB_SEND },
309	{ CONN_SRC_CC91, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC91_TO_REVERB_SEND },
310	{ CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_CHORUS, PARAM_DEFAULT_CHORUS_SEND },
311	{ CONN_SRC_CC93, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC93_TO_CHORUS_SEND }
312};
313#define ENTRIES_IN_CONN_TABLE (sizeof(connTable)/sizeof(S_CONNECTION))
314
315static const S_DLS_ART_VALUES defaultArt =
316{
317	0,				/* not modified */
318	-851,			/* Mod LFO frequency: 5 Hz */
319	-7973,			/* Mod LFO delay: 10 milliseconds */
320
321	-851,			/* Vib LFO frequency: 5 Hz */
322	-7973,			/* Vib LFO delay: 10 milliseconds */
323
324	-32768,			/* EG1 delay time: 0 secs */
325	-32768,			/* EG1 attack time: 0 secs */
326	-32768,			/* EG1 hold time: 0 secs */
327	-32768,			/* EG1 decay time: 0 secs */
328	1000,			/* EG1 sustain level: 100.0% */
329	-32768,			/* EG1 release time: 0 secs */
330	-7271,			/* EG1 shutdown time: 15 msecs */
331	0,				/* EG1 velocity to attack: 0 time cents */
332	0,				/* EG1 key number to decay: 0 time cents */
333	0,				/* EG1 key number to hold: 0 time cents */
334
335	-32768,			/* EG2 delay time: 0 secs */
336	-32768,			/* EG2 attack time: 0 secs */
337	-32768,			/* EG2 hold time: 0 secs */
338	-32768,			/* EG2 decay time: 0 secs */
339	1000,			/* EG2 sustain level: 100.0% */
340	-32768,			/* EG2 release time: 0 secs */
341	0,				/* EG2 velocity to attack: 0 time cents */
342	0,				/* EG2 key number to decay: 0 time cents */
343	0,				/* EG2 key number to hold: 0 time cents */
344
345	0x7fff,			/* Initial Fc: Disabled */
346	0,				/* Initial Q: 0 dB */
347	0,				/* Mod LFO to Fc: 0 cents */
348	0,				/* Mod LFO CC1 to Fc: 0 cents */
349	0,				/* Mod LFO channel pressure to Fc: 0 cents */
350	0,				/* EG2 to Fc: 0 cents */
351	0,				/* Velocity to Fc: 0 cents */
352	0,				/* Key number to Fc: 0 cents */
353
354	0,				/* Mod LFO to gain: 0 dB */
355	0,				/* Mod LFO CC1 to gain: 0 dB */
356	0,				/* Mod LFO channel pressure to gain: 0 dB */
357	960,			/* Velocity to gain: 96 dB */
358
359	0,				/* Tuning: 0 cents */
360	12800,			/* Key number to pitch: 12,800 cents */
361	0,				/* Vibrato to pitch: 0 cents */
362	0,				/* Vibrato CC1 to pitch: 0 cents */
363	0,				/* Vibrato channel pressure to pitch: 0 cents */
364	0,				/* Mod LFO to pitch: 0 cents */
365	0,				/* Mod LFO CC1 to pitch: 0 cents */
366	0,				/* Mod LFO channel pressure to pitch: 0 cents */
367	0,				/* Mod EG to pitch: 0 cents */
368
369	0,				/* Default pan: 0.0% */
370	0,				/* Default reverb send: 0.0% */
371	1000,			/* Default CC91 to reverb send: 100.0% */
372	0,				/* Default chorus send: 0.0% */
373	1000			/* Default CC93 to chorus send: 100.0% */
374};
375
376/*------------------------------------
377 * local variables
378 *------------------------------------
379*/
380
381#if defined(_8_BIT_SAMPLES)
382static const EAS_INT bitDepth = 8;
383#elif defined(_16_BIT_SAMPLES)
384static const EAS_INT bitDepth = 16;
385#else
386#error "Must define _8_BIT_SAMPLES or _16_BIT_SAMPLES"
387#endif
388
389static const EAS_U32 outputSampleRate = _OUTPUT_SAMPLE_RATE;
390static const EAS_I32 dlsRateConvert = DLS_RATE_CONVERT;
391static const EAS_I32 dlsLFOFrequencyConvert = DLS_LFO_FREQUENCY_CONVERT;
392
393/*------------------------------------
394 * inline functions
395 *------------------------------------
396*/
397EAS_INLINE void *PtrOfs (void *p, EAS_I32 offset)
398{
399	return (void*) (((EAS_U8*) p) + offset);
400}
401
402/*------------------------------------
403 * prototypes
404 *------------------------------------
405*/
406static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize);
407static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wsmpPos, EAS_I32 wsmpSize);
408static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex);
409static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p);
410static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p);
411static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *p, EAS_SAMPLE *pSample);
412static EAS_RESULT Parse_lins(SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size);
413static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size);
414static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale);
415static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions);
416static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex);
417static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn);
418static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt);
419static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt);
420static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex);
421static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue);
422static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp);
423static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt,  EAS_U16 artIndex);
424static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate);
425static EAS_I16 ConvertSustain (EAS_I32 sustain);
426static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents);
427static EAS_I8 ConvertPan (EAS_I32 pan);
428static EAS_U8 ConvertQ (EAS_I32 q);
429
430#ifdef _DEBUG_DLS
431static void DumpDLS (S_EAS *pEAS);
432#endif
433
434
435/*----------------------------------------------------------------------------
436 * DLSParser ()
437 *----------------------------------------------------------------------------
438 * Purpose:
439 *
440 * Inputs:
441 * pEASData - pointer to over EAS data instance
442 * fileHandle - file handle for input file
443 * offset - offset into file where DLS data starts
444 *
445 * Outputs:
446 * EAS_RESULT
447 * ppEAS - address of pointer to alternate EAS wavetable
448 *
449 *----------------------------------------------------------------------------
450*/
451EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS)
452{
453	EAS_RESULT result;
454	SDLS_SYNTHESIZER_DATA dls;
455	EAS_U32 temp;
456	EAS_I32 pos;
457	EAS_I32 chunkPos;
458	EAS_I32 size;
459	EAS_I32 instSize;
460	EAS_I32 rgnPoolSize;
461	EAS_I32 artPoolSize;
462	EAS_I32 waveLenSize;
463	EAS_I32 endDLS;
464	EAS_I32 wvplPos;
465	EAS_I32 wvplSize;
466	EAS_I32 linsPos;
467	EAS_I32 linsSize;
468	EAS_I32 ptblPos;
469	EAS_I32 ptblSize;
470	void *p;
471
472	/* zero counts and pointers */
473	EAS_HWMemSet(&dls, 0, sizeof(dls));
474
475	/* save file handle and hwInstData to save copying pointers around */
476	dls.hwInstData = hwInstData;
477	dls.fileHandle = fileHandle;
478
479	/* NULL return value in case of error */
480	*ppDLS = NULL;
481
482	/* seek to start of DLS and read in RIFF tag and set processor endian flag */
483	if ((result = EAS_HWFileSeek(dls.hwInstData, dls.fileHandle, offset)) != EAS_SUCCESS)
484		return result;
485	if ((result = EAS_HWReadFile(dls.hwInstData, dls.fileHandle, &temp, sizeof(temp), &size)) != EAS_SUCCESS)
486		return result;
487
488	/* check for processor endian-ness */
489	dls.bigEndian = (temp == CHUNK_RIFF);
490
491	/* first chunk should be DLS */
492	pos = offset;
493	if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
494		return result;
495	if (temp != CHUNK_DLS)
496	{
497		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected DLS chunk, got %08lx\n", temp); */ }
498		return EAS_ERROR_FILE_FORMAT;
499	}
500
501	/* no instrument or wavepool chunks */
502	linsSize = wvplSize = ptblSize = linsPos = wvplPos = ptblPos = 0;
503
504	/* scan the chunks in the DLS list */
505	endDLS = offset + size;
506	pos = offset + 12;
507	while (pos < endDLS)
508	{
509		chunkPos = pos;
510
511		/* get the next chunk type */
512		if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS)
513			return result;
514
515		/* parse useful chunks */
516		switch (temp)
517		{
518			case CHUNK_CDL:
519				if ((result = Parse_cdl(&dls, size, &temp)) != EAS_SUCCESS)
520					return result;
521				if (!temp)
522					return EAS_ERROR_UNRECOGNIZED_FORMAT;
523				break;
524
525			case CHUNK_LINS:
526				linsPos = chunkPos + 12;
527				linsSize = size - 4;
528				break;
529
530			case CHUNK_WVPL:
531				wvplPos = chunkPos + 12;
532				wvplSize = size - 4;
533				break;
534
535			case CHUNK_PTBL:
536				ptblPos = chunkPos + 8;
537				ptblSize = size - 4;
538				break;
539
540			default:
541				break;
542		}
543	}
544
545	/* must have a lins chunk */
546	if (linsSize == 0)
547	{
548		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No lins chunk found"); */ }
549		return EAS_ERROR_UNRECOGNIZED_FORMAT;
550	}
551
552	/* must have a wvpl chunk */
553	if (wvplSize == 0)
554	{
555		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No wvpl chunk found"); */ }
556		return EAS_ERROR_UNRECOGNIZED_FORMAT;
557	}
558
559	/* must have a ptbl chunk */
560	if ((ptblSize == 0) || (ptblSize > DLS_MAX_WAVE_COUNT * sizeof(POOLCUE) + sizeof(POOLTABLE)))
561	{
562		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No ptbl chunk found"); */ }
563		return EAS_ERROR_UNRECOGNIZED_FORMAT;
564	}
565
566	/* pre-parse the wave pool chunk */
567	if ((result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize)) != EAS_SUCCESS)
568		return result;
569
570	/* limit check  */
571	if ((dls.waveCount == 0) || (dls.waveCount > DLS_MAX_WAVE_COUNT))
572	{
573		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #waves [%u]\n", dls.waveCount); */ }
574		return EAS_ERROR_FILE_FORMAT;
575	}
576
577	/* allocate memory for wsmp data */
578	dls.wsmpData = EAS_HWMalloc(dls.hwInstData, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));
579	if (dls.wsmpData == NULL)
580	{
581		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc for wsmp data failed\n"); */ }
582		return EAS_ERROR_MALLOC_FAILED;
583	}
584	EAS_HWMemSet(dls.wsmpData, 0, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount));
585
586	/* pre-parse the lins chunk */
587	result = Parse_lins(&dls, linsPos, linsSize);
588	if (result == EAS_SUCCESS)
589	{
590
591		/* limit check  */
592		if ((dls.regionCount == 0) || (dls.regionCount > DLS_MAX_REGION_COUNT))
593		{
594			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #regions [%u]\n", dls.regionCount); */ }
595			return EAS_ERROR_FILE_FORMAT;
596		}
597
598		/* limit check  */
599		if ((dls.artCount == 0) || (dls.artCount > DLS_MAX_ART_COUNT))
600		{
601			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #articulations [%u]\n", dls.regionCount); */ }
602			return EAS_ERROR_FILE_FORMAT;
603		}
604
605		/* limit check  */
606		if ((dls.instCount == 0) || (dls.instCount > DLS_MAX_INST_COUNT))
607		{
608			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #instruments [%u]\n", dls.instCount); */ }
609			return EAS_ERROR_FILE_FORMAT;
610		}
611
612		/* Allocate memory for the converted DLS data */
613		/* calculate size of instrument data */
614		instSize = (EAS_I32) (sizeof(S_PROGRAM) * dls.instCount);
615
616		/* calculate size of region pool */
617		rgnPoolSize = (EAS_I32) (sizeof(S_DLS_REGION) * dls.regionCount);
618
619		/* calculate size of articulation pool, add one for default articulation */
620		dls.artCount++;
621		artPoolSize = (EAS_I32) (sizeof(S_DLS_ARTICULATION) * dls.artCount);
622
623		/* calculate size of wave length and offset arrays */
624		waveLenSize = (EAS_I32) (dls.waveCount * sizeof(EAS_U32));
625
626		/* calculate final memory size */
627		size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize;
628		if (size <= 0) {
629			return EAS_ERROR_FILE_FORMAT;
630		}
631
632		/* allocate the main EAS chunk */
633		dls.pDLS = EAS_HWMalloc(dls.hwInstData, size);
634		if (dls.pDLS == NULL)
635		{
636			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc failed for DLS memory allocation size %ld\n", size); */ }
637			return EAS_ERROR_MALLOC_FAILED;
638		}
639		EAS_HWMemSet(dls.pDLS, 0, size);
640		dls.pDLS->refCount = 1;
641		p = PtrOfs(dls.pDLS, sizeof(S_EAS));
642
643		/* setup pointer to programs */
644		dls.pDLS->numDLSPrograms = (EAS_U16) dls.instCount;
645		dls.pDLS->pDLSPrograms = p;
646		p = PtrOfs(p, instSize);
647
648		/* setup pointer to regions */
649		dls.pDLS->pDLSRegions = p;
650		dls.pDLS->numDLSRegions = (EAS_U16) dls.regionCount;
651		p = PtrOfs(p, rgnPoolSize);
652
653		/* setup pointer to articulations */
654		dls.pDLS->numDLSArticulations = (EAS_U16) dls.artCount;
655		dls.pDLS->pDLSArticulations = p;
656		p = PtrOfs(p, artPoolSize);
657
658		/* setup pointer to wave length table */
659		dls.pDLS->numDLSSamples = (EAS_U16) dls.waveCount;
660		dls.pDLS->pDLSSampleLen = p;
661		p = PtrOfs(p, waveLenSize);
662
663		/* setup pointer to wave offsets table */
664		dls.pDLS->pDLSSampleOffsets = p;
665		p = PtrOfs(p, waveLenSize);
666
667		/* setup pointer to wave pool */
668		dls.pDLS->pDLSSamples = p;
669
670		/* clear filter flag */
671		dls.filterUsed = EAS_FALSE;
672
673		/* parse the wave pool and load samples */
674		result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize);
675	}
676
677	/* create the default articulation */
678	Convert_art(&dls, &defaultArt, 0);
679	dls.artCount = 1;
680
681	/* parse the lins chunk and load instruments */
682	dls.regionCount = dls.instCount = 0;
683	if (result == EAS_SUCCESS)
684		result = Parse_lins(&dls, linsPos, linsSize);
685
686	/* clean up any temporary objects that were allocated */
687	if (dls.wsmpData)
688		EAS_HWFree(dls.hwInstData, dls.wsmpData);
689
690	/* if successful, return a pointer to the EAS collection */
691	if (result == EAS_SUCCESS)
692	{
693		*ppDLS = dls.pDLS;
694#ifdef _DEBUG_DLS
695		DumpDLS(dls.pDLS);
696#endif
697	}
698
699	/* something went wrong, deallocate the EAS collection */
700	else
701		DLSCleanup(dls.hwInstData, dls.pDLS);
702
703	return result;
704}
705
706/*----------------------------------------------------------------------------
707 * DLSCleanup ()
708 *----------------------------------------------------------------------------
709 * Purpose:
710 *
711 * Inputs:
712 * pEASData - pointer to over EAS data instance
713 * pEAS - pointer to alternate EAS wavetable
714 *
715 * Outputs:
716 * EAS_RESULT
717 *
718 *----------------------------------------------------------------------------
719*/
720EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS)
721{
722
723	/* free the allocated memory */
724	if (pDLS)
725	{
726		if (pDLS->refCount)
727		{
728			if (--pDLS->refCount == 0)
729				EAS_HWFree(hwInstData, pDLS);
730		}
731	}
732	return EAS_SUCCESS;
733}
734
735/*----------------------------------------------------------------------------
736 * DLSAddRef ()
737 *----------------------------------------------------------------------------
738 * Increment reference count
739 *----------------------------------------------------------------------------
740*/
741void DLSAddRef (S_DLS *pDLS)
742{
743	if (pDLS)
744		pDLS->refCount++;
745}
746
747/*----------------------------------------------------------------------------
748 * NextChunk ()
749 *----------------------------------------------------------------------------
750 * Purpose:
751 * Returns the type and size of the next chunk in the file
752 *
753 * Inputs:
754 *
755 * Outputs:
756 *
757 * Side Effects:
758 *----------------------------------------------------------------------------
759*/
760static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize)
761{
762	EAS_RESULT result;
763
764	/* seek to start of chunk */
765	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, *pPos)) != EAS_SUCCESS)
766		return result;
767
768	/* read the chunk type */
769	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS)
770		return result;
771
772	/* read the chunk size */
773	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pSize, EAS_FALSE)) != EAS_SUCCESS)
774		return result;
775
776	/* get form type for RIFF and LIST types */
777	if ((*pChunkType == CHUNK_RIFF) || (*pChunkType == CHUNK_LIST))
778	{
779
780		/* read the form type */
781		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS)
782			return result;
783
784	}
785
786	/* calculate start of next chunk */
787	*pPos += *pSize + 8;
788
789	/* adjust to word boundary */
790	if (*pPos & 1)
791		(*pPos)++;
792
793	return EAS_SUCCESS;
794}
795
796/*----------------------------------------------------------------------------
797 * Parse_ptbl ()
798 *----------------------------------------------------------------------------
799 * Purpose:
800 *
801 *
802 * Inputs:
803 *
804 *
805 * Outputs:
806 *
807 *
808 *----------------------------------------------------------------------------
809*/
810static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wtblPos, EAS_I32 wtblSize)
811{
812	EAS_RESULT result;
813	EAS_U32 temp;
814	EAS_FILE_HANDLE tempFile;
815	EAS_U16 waveIndex;
816
817	/* seek to start of chunk */
818	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
819		return result;
820
821	/* get the structure size */
822	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &temp, EAS_FALSE)) != EAS_SUCCESS)
823		return result;
824
825	/* get the number of waves */
826	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSData->waveCount, EAS_FALSE)) != EAS_SUCCESS)
827		return result;
828
829#if 0
830	/* just need the wave count on the first pass */
831	if (!pDLSData->pDLS)
832		return EAS_SUCCESS;
833#endif
834
835	/* open duplicate file handle */
836	if ((result = EAS_HWDupHandle(pDLSData->hwInstData, pDLSData->fileHandle, &tempFile)) != EAS_SUCCESS)
837		return result;
838
839	/* read to end of chunk */
840	for (waveIndex = 0; waveIndex < pDLSData->waveCount; waveIndex++)
841	{
842
843		/* get the offset to the wave and make sure it is within the wtbl chunk */
844		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, tempFile, &temp, EAS_FALSE)) != EAS_SUCCESS)
845			return result;
846		if (temp > (EAS_U32) wtblSize)
847		{
848			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Ptbl offset exceeds size of wtbl\n"); */ }
849			EAS_HWCloseFile(pDLSData->hwInstData, tempFile);
850			return EAS_ERROR_FILE_FORMAT;
851		}
852
853		/* parse the wave */
854		if ((result = Parse_wave(pDLSData, wtblPos +(EAS_I32)  temp, waveIndex)) != EAS_SUCCESS)
855			return result;
856	}
857
858	/* close the temporary handle and return */
859	EAS_HWCloseFile(pDLSData->hwInstData, tempFile);
860	return EAS_SUCCESS;
861}
862
863/*----------------------------------------------------------------------------
864 * Parse_wave ()
865 *----------------------------------------------------------------------------
866 * Purpose:
867 *
868 *
869 * Inputs:
870 *
871 *
872 * Outputs:
873 *
874 *
875 *----------------------------------------------------------------------------
876*/
877static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex)
878{
879	EAS_RESULT result;
880	EAS_U32 temp;
881	EAS_I32 size;
882	EAS_I32 endChunk;
883	EAS_I32 chunkPos;
884	EAS_I32 wsmpPos = 0;
885	EAS_I32 fmtPos = 0;
886	EAS_I32 dataPos = 0;
887	EAS_I32 dataSize = 0;
888	S_WSMP_DATA *p;
889	void *pSample;
890	S_WSMP_DATA wsmp;
891
892	/* seek to start of chunk */
893	chunkPos = pos + 12;
894	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
895		return result;
896
897	/* get the chunk type */
898	if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
899		return result;
900
901	/* make sure it is a wave chunk */
902	if (temp != CHUNK_WAVE)
903	{
904		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Offset in ptbl does not point to wave chunk\n"); */ }
905		return EAS_ERROR_FILE_FORMAT;
906	}
907
908	/* read to end of chunk */
909	pos = chunkPos;
910	endChunk = pos + size;
911	while (pos < endChunk)
912	{
913		chunkPos = pos;
914
915		/* get the chunk type */
916		if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
917			return result;
918
919		/* parse useful chunks */
920		switch (temp)
921		{
922			case CHUNK_WSMP:
923				wsmpPos = chunkPos + 8;
924				break;
925
926			case CHUNK_FMT:
927				fmtPos = chunkPos + 8;
928				break;
929
930			case CHUNK_DATA:
931				dataPos = chunkPos + 8;
932				dataSize = size;
933				break;
934
935			default:
936				break;
937		}
938	}
939
940	// limit to reasonable size
941	if (dataSize > MAX_DLS_WAVE_SIZE)
942	{
943		return EAS_ERROR_SOUND_LIBRARY;
944	}
945
946	/* for first pass, use temporary variable */
947	if (pDLSData->pDLS == NULL)
948		p = &wsmp;
949	else
950		p = &pDLSData->wsmpData[waveIndex];
951
952	/* set the defaults */
953	p->fineTune = 0;
954	p->unityNote = 60;
955	p->gain = 0;
956	p->loopStart = 0;
957	p->loopLength = 0;
958
959	/* must have a fmt chunk */
960	if (!fmtPos)
961	{
962		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no fmt chunk\n"); */ }
963		return EAS_ERROR_UNRECOGNIZED_FORMAT;
964	}
965
966	/* must have a data chunk */
967	if (!dataPos)
968	{
969		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no data chunk\n"); */ }
970		return EAS_ERROR_UNRECOGNIZED_FORMAT;
971	}
972
973	/* parse the wsmp chunk */
974	if (wsmpPos)
975	{
976		if ((result = Parse_wsmp(pDLSData, wsmpPos, p)) != EAS_SUCCESS)
977			return result;
978	}
979
980	/* parse the fmt chunk */
981	if ((result = Parse_fmt(pDLSData, fmtPos, p)) != EAS_SUCCESS)
982		return result;
983
984	/* calculate the size of the wavetable needed. We need only half
985	 * the memory for 16-bit samples when in 8-bit mode, and we need
986	 * double the memory for 8-bit samples in 16-bit mode. For
987	 * unlooped samples, we may use ADPCM. If so, we need only 1/4
988	 * the memory.
989	 *
990	 * We also need to add one for looped samples to allow for
991	 * the first sample to be copied to the end of the loop.
992	 */
993
994	/* use ADPCM encode for unlooped 16-bit samples if ADPCM is enabled */
995	/*lint -e{506} -e{774} groundwork for future version to support 8 & 16 bit */
996	if (bitDepth == 8)
997	{
998		if (p->bitsPerSample == 8)
999			size = dataSize;
1000		else
1001			/*lint -e{704} use shift for performance */
1002			size = dataSize >> 1;
1003		if (p->loopLength)
1004			size++;
1005	}
1006
1007	else
1008	{
1009		if (p->bitsPerSample == 16)
1010			size = dataSize;
1011		else
1012			/*lint -e{703} use shift for performance */
1013			size = dataSize << 1;
1014		if (p->loopLength)
1015			size += 2;
1016	}
1017
1018	/* for first pass, add size to wave pool size and return */
1019	if (pDLSData->pDLS == NULL)
1020	{
1021		pDLSData->wavePoolSize += (EAS_U32) size;
1022		return EAS_SUCCESS;
1023	}
1024
1025	/* allocate memory and read in the sample data */
1026	pSample = pDLSData->pDLS->pDLSSamples + pDLSData->wavePoolOffset;
1027	pDLSData->pDLS->pDLSSampleOffsets[waveIndex] = pDLSData->wavePoolOffset;
1028	pDLSData->pDLS->pDLSSampleLen[waveIndex] = (EAS_U32) size;
1029	pDLSData->wavePoolOffset += (EAS_U32) size;
1030	if (pDLSData->wavePoolOffset > pDLSData->wavePoolSize)
1031	{
1032		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Wave pool exceeded allocation\n"); */ }
1033		return EAS_ERROR_SOUND_LIBRARY;
1034	}
1035
1036	if ((result = Parse_data(pDLSData, dataPos, dataSize, p, pSample)) != EAS_SUCCESS)
1037		return result;
1038
1039	return EAS_SUCCESS;
1040}
1041
1042/*----------------------------------------------------------------------------
1043 * Parse_wsmp ()
1044 *----------------------------------------------------------------------------
1045 * Purpose:
1046 *
1047 *
1048 * Inputs:
1049 *
1050 *
1051 * Outputs:
1052 *
1053 *
1054 *----------------------------------------------------------------------------
1055*/
1056static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p)
1057{
1058	EAS_RESULT result;
1059	EAS_U16 wtemp;
1060	EAS_U32 ltemp;
1061	EAS_U32 cbSize;
1062
1063	/* seek to start of chunk */
1064	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1065		return result;
1066
1067	/* get structure size */
1068	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &cbSize, EAS_FALSE)) != EAS_SUCCESS)
1069		return result;
1070
1071	/* get unity note */
1072	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
1073		return result;
1074	if (wtemp <= 127)
1075		p->unityNote = (EAS_U8) wtemp;
1076	else
1077	{
1078		p->unityNote = 60;
1079		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid unity note [%u] in DLS wsmp ignored, set to 60\n", wtemp); */ }
1080	}
1081
1082	/* get fine tune */
1083	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->fineTune, EAS_FALSE)) != EAS_SUCCESS)
1084		return result;
1085
1086	/* get gain */
1087	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->gain, EAS_FALSE)) != EAS_SUCCESS)
1088		return result;
1089	if (p->gain > 0)
1090	{
1091		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Positive gain [%ld] in DLS wsmp ignored, set to 0dB\n", p->gain); */ }
1092		p->gain = 0;
1093	}
1094
1095	/* option flags */
1096	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
1097		return result;
1098
1099	/* sample loops */
1100	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
1101		return result;
1102
1103	/* if looped sample, get loop data */
1104	if (ltemp)
1105	{
1106
1107		if (ltemp > 1)
1108			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS sample with %lu loops, ignoring extra loops\n", ltemp); */ }
1109
1110		/* skip ahead to loop data */
1111		if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + (EAS_I32) cbSize)) != EAS_SUCCESS)
1112			return result;
1113
1114		/* get structure size */
1115		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
1116			return result;
1117
1118		/* get loop type */
1119		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
1120			return result;
1121
1122		/* get loop start */
1123		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopStart, EAS_FALSE)) != EAS_SUCCESS)
1124			return result;
1125
1126		/* get loop length */
1127		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopLength, EAS_FALSE)) != EAS_SUCCESS)
1128			return result;
1129	}
1130
1131	return EAS_SUCCESS;
1132}
1133
1134/*----------------------------------------------------------------------------
1135 * Parse_fmt ()
1136 *----------------------------------------------------------------------------
1137 * Purpose:
1138 *
1139 *
1140 * Inputs:
1141 *
1142 *
1143 * Outputs:
1144 *
1145 *
1146 *----------------------------------------------------------------------------
1147*/
1148static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p)
1149{
1150	EAS_RESULT result;
1151	EAS_U16 wtemp;
1152	EAS_U32 ltemp;
1153
1154	/* seek to start of chunk */
1155	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1156		return result;
1157
1158	/* get format tag */
1159	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
1160		return result;
1161	if (wtemp != WAVE_FORMAT_PCM)
1162	{
1163		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS sample format %04x\n", wtemp); */ }
1164		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1165	}
1166
1167	/* get number of channels */
1168	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
1169		return result;
1170	if (wtemp != 1)
1171	{
1172		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No support for DLS multi-channel samples\n"); */ }
1173		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1174	}
1175
1176	/* get sample rate */
1177	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->sampleRate, EAS_FALSE)) != EAS_SUCCESS)
1178		return result;
1179
1180	/* bytes/sec */
1181	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &ltemp, EAS_FALSE)) != EAS_SUCCESS)
1182		return result;
1183
1184	/* block align */
1185	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS)
1186		return result;
1187
1188	/* bits/sample */
1189	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->bitsPerSample, EAS_FALSE)) != EAS_SUCCESS)
1190		return result;
1191
1192	if ((p->bitsPerSample != 8) && (p->bitsPerSample != 16))
1193	{
1194		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS bits-per-sample %d\n", p->bitsPerSample); */ }
1195		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1196	}
1197
1198	return EAS_SUCCESS;
1199}
1200
1201#if defined( _8_BIT_SAMPLES)
1202/*----------------------------------------------------------------------------
1203 * Parse_data ()
1204 *----------------------------------------------------------------------------
1205 * Purpose:
1206 *
1207 * NOTE: The optimized assembly versions of the interpolator require
1208 * an extra sample at the end of the loop - a copy of the first
1209 * sample. This routine must allocate an extra sample of data and
1210 * copy the first sample of the loop to the end.
1211 *
1212 * Inputs:
1213 *
1214 *
1215 * Outputs:
1216 *
1217 *
1218 *----------------------------------------------------------------------------
1219*/
1220static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *pWsmp, EAS_SAMPLE *pSample)
1221{
1222	EAS_RESULT result;
1223	EAS_U8 convBuf[SAMPLE_CONVERT_CHUNK_SIZE];
1224	EAS_I32 count;
1225	EAS_I32 i;
1226	EAS_I8 *p;
1227
1228	/* seek to start of chunk */
1229	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1230		return result;
1231
1232	/* 8-bit samples in an 8-bit synth, just copy the data, and flip bit 7 */
1233	p = pSample;
1234	if (pWsmp->bitsPerSample == 8)
1235	{
1236		if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pSample, size, &count)) != EAS_SUCCESS)
1237			return result;
1238		for (i = 0; i < size; i++)
1239			/*lint -e{734} convert from unsigned to signed audio */
1240			*p++ ^= 0x80;
1241	}
1242
1243	/* 16-bit samples, need to convert to 8-bit or ADPCM */
1244	else
1245	{
1246
1247		while (size)
1248		{
1249			EAS_I8 *pInput;
1250
1251			/* for undithered conversion, we're just copying the 8-bit data */
1252			if (pDLSData->bigEndian)
1253				pInput = (EAS_I8*) convBuf;
1254			else
1255				pInput = (EAS_I8*) convBuf + 1;
1256
1257			/* read a small chunk of data and convert it */
1258			count = (size < SAMPLE_CONVERT_CHUNK_SIZE ? size : SAMPLE_CONVERT_CHUNK_SIZE);
1259			if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, convBuf, count, &count)) != EAS_SUCCESS)
1260				return result;
1261			size -= count;
1262			/*lint -e{704} use shift for performance */
1263			count = count >> 1;
1264
1265			while (count--)
1266			{
1267				*p++ = *pInput;
1268				pInput += 2;
1269			}
1270		}
1271	}
1272
1273	/* for looped samples, copy the last sample to the end */
1274	if (pWsmp->loopLength)
1275		pSample[pWsmp->loopStart + pWsmp->loopLength] = pSample[pWsmp->loopStart];
1276
1277	return EAS_SUCCESS;
1278}
1279#elif defined(_16_BIT_SAMPLES)
1280#error "16-bit DLS conversion not implemented yet"
1281#else
1282#error "Must specifiy _8_BIT_SAMPLES or _16_BIT_SAMPLES"
1283#endif
1284
1285/*----------------------------------------------------------------------------
1286 * Parse_lins ()
1287 *----------------------------------------------------------------------------
1288 * Purpose:
1289 *
1290 *
1291 * Inputs:
1292 *
1293 *
1294 * Outputs:
1295 *
1296 *
1297 *----------------------------------------------------------------------------
1298*/
1299static EAS_RESULT Parse_lins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size)
1300{
1301	EAS_RESULT result;
1302	EAS_U32 temp;
1303	EAS_I32 endChunk;
1304	EAS_I32 chunkPos;
1305
1306	/* seek to start of chunk */
1307	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1308		return result;
1309
1310	/* read to end of chunk */
1311	endChunk = pos + size;
1312	while (pos < endChunk)
1313	{
1314		chunkPos = pos;
1315
1316		/* get the next chunk type */
1317		if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
1318			return result;
1319
1320		/* only instrument chunks are useful */
1321		if (temp != CHUNK_INS)
1322			continue;
1323
1324		if ((result = Parse_ins(pDLSData, chunkPos + 12, size)) != EAS_SUCCESS)
1325			return result;
1326	}
1327
1328	return EAS_SUCCESS;
1329}
1330
1331/*----------------------------------------------------------------------------
1332 * Parse_ins ()
1333 *----------------------------------------------------------------------------
1334 * Purpose:
1335 *
1336 *
1337 * Inputs:
1338 *
1339 *
1340 * Outputs:
1341 *
1342 *
1343 *----------------------------------------------------------------------------
1344*/
1345static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size)
1346{
1347	EAS_RESULT result;
1348	EAS_U32 temp;
1349	EAS_I32 chunkPos;
1350	EAS_I32 endChunk;
1351	EAS_I32 lrgnPos;
1352	EAS_I32 lrgnSize;
1353	EAS_I32 lartPos;
1354	EAS_I32 lartSize;
1355	EAS_I32 lar2Pos;
1356	EAS_I32 lar2Size;
1357	EAS_I32 inshPos;
1358	EAS_U32 regionCount;
1359	EAS_U32 locale;
1360	S_DLS_ART_VALUES art;
1361	S_PROGRAM *pProgram;
1362	EAS_U16 artIndex;
1363
1364	/* seek to start of chunk */
1365	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1366		return result;
1367
1368	/* no chunks yet */
1369	lrgnPos = lrgnSize = lartPos = lartSize = lar2Pos = lar2Size = inshPos = artIndex = 0;
1370
1371	/* read to end of chunk */
1372	endChunk = pos + size;
1373	while (pos < endChunk)
1374	{
1375		chunkPos = pos;
1376
1377		/* get the next chunk type */
1378		if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
1379			return result;
1380
1381		/* parse useful chunks */
1382		switch (temp)
1383		{
1384			case CHUNK_INSH:
1385				inshPos = chunkPos + 8;
1386				break;
1387
1388			case CHUNK_LART:
1389				lartPos = chunkPos + 12;
1390				lartSize = size;
1391				break;
1392
1393			case CHUNK_LAR2:
1394				lar2Pos = chunkPos + 12;
1395				lar2Size = size;
1396				break;
1397
1398			case CHUNK_LRGN:
1399				lrgnPos = chunkPos + 12;
1400				lrgnSize = size;
1401				break;
1402
1403			default:
1404				break;
1405		}
1406	}
1407
1408	/* must have an lrgn to be useful */
1409	if (!lrgnPos)
1410	{
1411		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no lrgn chunk\n"); */ }
1412		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1413	}
1414
1415	/* must have an insh to be useful */
1416	if (!inshPos)
1417	{
1418		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no insh chunk\n"); */ }
1419		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1420	}
1421
1422	/* parse the instrument header */
1423	if ((result = Parse_insh(pDLSData, inshPos, &regionCount, &locale)) != EAS_SUCCESS)
1424		return result;
1425
1426	/* initialize and parse the global data first */
1427	EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES));
1428	if (lartPos)
1429		if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS)
1430			return result;
1431	if (lar2Pos)
1432		if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS)
1433			return result;
1434
1435	if (art.values[PARAM_MODIFIED])
1436	{
1437		artIndex = (EAS_U16) pDLSData->artCount;
1438		pDLSData->artCount++;
1439	}
1440
1441	/* convert data on second pass */
1442	if (pDLSData->pDLS)
1443	{
1444
1445		if (art.values[PARAM_MODIFIED])
1446			Convert_art(pDLSData, &art, artIndex);
1447
1448		/* setup pointers */
1449		pProgram = &pDLSData->pDLS->pDLSPrograms[pDLSData->instCount];
1450
1451		/* initialize instrument */
1452		pProgram->locale = locale;
1453		pProgram->regionIndex = (EAS_U16) pDLSData->regionCount | FLAG_RGN_IDX_DLS_SYNTH;
1454
1455	}
1456
1457	/* parse the region data */
1458	if ((result = Parse_lrgn(pDLSData, lrgnPos, lrgnSize, artIndex, regionCount)) != EAS_SUCCESS)
1459		return result;
1460
1461	/* bump instrument count */
1462	pDLSData->instCount++;
1463	return EAS_SUCCESS;
1464}
1465
1466/*----------------------------------------------------------------------------
1467 * Parse_insh ()
1468 *----------------------------------------------------------------------------
1469 * Purpose:
1470 *
1471 *
1472 * Inputs:
1473 *
1474 *
1475 * Outputs:
1476 *
1477 *
1478 *----------------------------------------------------------------------------
1479*/
1480static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale)
1481{
1482	EAS_RESULT result;
1483	EAS_U32 bank;
1484	EAS_U32 program;
1485
1486	/* seek to start of chunk */
1487	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1488		return result;
1489
1490	/* get the region count and locale */
1491	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pRgnCount, EAS_FALSE)) != EAS_SUCCESS)
1492		return result;
1493	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &bank, EAS_FALSE)) != EAS_SUCCESS)
1494		return result;
1495	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &program, EAS_FALSE)) != EAS_SUCCESS)
1496		return result;
1497
1498	/* verify the parameters are valid */
1499	if (bank & 0x7fff8080)
1500	{
1501		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS bank number is out of range: %08lx\n", bank); */ }
1502		bank &= 0xff7f;
1503	}
1504	if (program > 127)
1505	{
1506		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS program number is out of range: %08lx\n", program); */ }
1507		program &= 0x7f;
1508	}
1509
1510	/* save the program number */
1511	*pLocale = (bank << 8) | program;
1512	return EAS_SUCCESS;
1513}
1514
1515/*----------------------------------------------------------------------------
1516 * Parse_lrgn ()
1517 *----------------------------------------------------------------------------
1518 * Purpose:
1519 *
1520 *
1521 * Inputs:
1522 *
1523 *
1524 * Outputs:
1525 *
1526 *
1527 *----------------------------------------------------------------------------
1528*/
1529static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions)
1530{
1531	EAS_RESULT result;
1532	EAS_U32 temp;
1533	EAS_I32 chunkPos;
1534	EAS_I32 endChunk;
1535	EAS_U16 regionCount;
1536
1537	/* seek to start of chunk */
1538	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1539		return result;
1540
1541	/* read to end of chunk */
1542	regionCount = 0;
1543	endChunk = pos + size;
1544	while (pos < endChunk)
1545	{
1546		chunkPos = pos;
1547
1548		/* get the next chunk type */
1549		if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
1550			return result;
1551
1552		if ((temp == CHUNK_RGN) || (temp == CHUNK_RGN2))
1553		{
1554			if (regionCount == numRegions)
1555			{
1556				{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS region count exceeded cRegions value in insh, extra region ignored\n"); */ }
1557				return EAS_SUCCESS;
1558			}
1559			if ((result = Parse_rgn(pDLSData, chunkPos + 12, size, artIndex)) != EAS_SUCCESS)
1560				return result;
1561			regionCount++;
1562		}
1563	}
1564
1565	/* set a flag in the last region */
1566	if ((pDLSData->pDLS != NULL) && (regionCount > 0))
1567		pDLSData->pDLS->pDLSRegions[pDLSData->regionCount - 1].wtRegion.region.keyGroupAndFlags |= REGION_FLAG_LAST_REGION;
1568
1569	return EAS_SUCCESS;
1570}
1571
1572/*----------------------------------------------------------------------------
1573 * Parse_rgn ()
1574 *----------------------------------------------------------------------------
1575 * Purpose:
1576 *
1577 *
1578 * Inputs:
1579 *
1580 *
1581 * Outputs:
1582 *
1583 *
1584 *----------------------------------------------------------------------------
1585*/
1586static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex)
1587{
1588	EAS_RESULT result;
1589	EAS_U32 temp;
1590	EAS_I32 chunkPos;
1591	EAS_I32 endChunk;
1592	EAS_I32 rgnhPos;
1593	EAS_I32 lartPos;
1594	EAS_I32 lartSize;
1595	EAS_I32 lar2Pos;
1596	EAS_I32 lar2Size;
1597	EAS_I32 wlnkPos;
1598	EAS_I32 wsmpPos;
1599	EAS_U32 waveIndex;
1600	S_DLS_ART_VALUES art;
1601	S_WSMP_DATA wsmp;
1602	S_WSMP_DATA *pWsmp;
1603	EAS_U16 regionIndex;
1604
1605	/* seek to start of chunk */
1606	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1607		return result;
1608
1609	/* no chunks found yet */
1610	rgnhPos = lartPos = lartSize = lar2Pos = lar2Size = wsmpPos = wlnkPos = 0;
1611	regionIndex = (EAS_U16) pDLSData->regionCount;
1612
1613	/* read to end of chunk */
1614	endChunk = pos + size;
1615	while (pos < endChunk)
1616	{
1617		chunkPos = pos;
1618
1619		/* get the next chunk type */
1620		if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
1621			return result;
1622
1623		/* parse useful chunks */
1624		switch (temp)
1625		{
1626			case CHUNK_CDL:
1627				if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS)
1628					return result;
1629
1630				/* if conditional chunk evaluates false, skip this list */
1631				if (!temp)
1632					return EAS_SUCCESS;
1633				break;
1634
1635			case CHUNK_RGNH:
1636				rgnhPos = chunkPos + 8;
1637				break;
1638
1639			case CHUNK_WLNK:
1640				wlnkPos = chunkPos + 8;
1641				break;
1642
1643			case CHUNK_WSMP:
1644				wsmpPos = chunkPos + 8;
1645				break;
1646
1647			case CHUNK_LART:
1648				lartPos = chunkPos + 12;
1649				lartSize = size;
1650				break;
1651
1652			case CHUNK_LAR2:
1653				lar2Pos = chunkPos + 12;
1654				lar2Size = size;
1655				break;
1656
1657			default:
1658				break;
1659		}
1660	}
1661
1662	/* must have a rgnh chunk to be useful */
1663	if (!rgnhPos)
1664	{
1665		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no rgnh chunk\n"); */ }
1666		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1667	}
1668
1669	/* must have a wlnk chunk to be useful */
1670	if (!wlnkPos)
1671	{
1672		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no wlnk chunk\n"); */ }
1673		return EAS_ERROR_UNRECOGNIZED_FORMAT;
1674	}
1675
1676	/* parse wlnk chunk */
1677	if ((result = Parse_wlnk(pDLSData, wlnkPos, &waveIndex)) != EAS_SUCCESS)
1678		return result;
1679	pWsmp = &pDLSData->wsmpData[waveIndex];
1680
1681	/* if there is any articulation data, parse it */
1682	EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES));
1683	if (lartPos)
1684	{
1685		if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS)
1686			return result;
1687	}
1688
1689	if (lar2Pos)
1690	{
1691		if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS)
1692			return result;
1693	}
1694
1695	/* if second pass, process region header */
1696	if (pDLSData->pDLS)
1697	{
1698
1699		/* if local data was found convert it */
1700		if (art.values[PARAM_MODIFIED] == EAS_TRUE)
1701		{
1702			Convert_art(pDLSData, &art, (EAS_U16) pDLSData->artCount);
1703			artIndex = (EAS_U16) pDLSData->artCount;
1704		}
1705
1706		/* parse region header */
1707		if ((result = Parse_rgnh(pDLSData, rgnhPos, &pDLSData->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK])) != EAS_SUCCESS)
1708			return result;
1709
1710		/* parse wsmp chunk, copying parameters from original first */
1711		if (wsmpPos)
1712		{
1713			EAS_HWMemCpy(&wsmp, pWsmp, sizeof(wsmp));
1714			if ((result = Parse_wsmp(pDLSData, wsmpPos, &wsmp)) != EAS_SUCCESS)
1715				return result;
1716
1717			pWsmp = &wsmp;
1718		}
1719
1720		Convert_rgn(pDLSData, regionIndex, artIndex, (EAS_U16) waveIndex, pWsmp);
1721	}
1722
1723	/* if local articulation, bump count */
1724	if (art.values[PARAM_MODIFIED])
1725		pDLSData->artCount++;
1726
1727	/* increment region count */
1728	pDLSData->regionCount++;
1729	return EAS_SUCCESS;
1730}
1731
1732/*----------------------------------------------------------------------------
1733 * Parse_rgnh ()
1734 *----------------------------------------------------------------------------
1735 * Purpose:
1736 *
1737 *
1738 * Inputs:
1739 *
1740 *
1741 * Outputs:
1742 *
1743 *
1744 *----------------------------------------------------------------------------
1745*/
1746static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn)
1747{
1748	EAS_RESULT result;
1749	EAS_U16 lowKey;
1750	EAS_U16 highKey;
1751	EAS_U16 lowVel;
1752	EAS_U16 highVel;
1753	EAS_U16 optionFlags;
1754	EAS_U16 keyGroup;
1755
1756	/* seek to start of chunk */
1757	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1758		return result;
1759
1760	/* get the key range */
1761	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowKey, EAS_FALSE)) != EAS_SUCCESS)
1762		return result;
1763	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highKey, EAS_FALSE)) != EAS_SUCCESS)
1764		return result;
1765
1766	/* check the range */
1767	if (lowKey > 127)
1768	{
1769		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low key out of range [%u]\n", lowKey); */ }
1770		lowKey = 127;
1771	}
1772	if (highKey > 127)
1773	{
1774		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High key out of range [%u]\n", lowKey); */ }
1775		highKey = 127;
1776	}
1777
1778	/* get the velocity range */
1779	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowVel, EAS_FALSE)) != EAS_SUCCESS)
1780		return result;
1781	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highVel, EAS_FALSE)) != EAS_SUCCESS)
1782		return result;
1783
1784	/* check the range */
1785	if (lowVel > 127)
1786	{
1787		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low velocity out of range [%u]\n", lowVel); */ }
1788		lowVel = 127;
1789	}
1790	if (highVel > 127)
1791	{
1792		{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High velocity out of range [%u]\n", highVel); */ }
1793		highVel = 127;
1794	}
1795
1796	/* get the option flags */
1797	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &optionFlags, EAS_FALSE)) != EAS_SUCCESS)
1798		return result;
1799
1800	/* get the key group */
1801	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &keyGroup, EAS_FALSE)) != EAS_SUCCESS)
1802		return result;
1803
1804	/* save the key range and key group */
1805	pRgn->wtRegion.region.rangeLow = (EAS_U8) lowKey;
1806	pRgn->wtRegion.region.rangeHigh = (EAS_U8) highKey;
1807
1808	/*lint -e{734} keyGroup will always be from 0-15 */
1809	pRgn->wtRegion.region.keyGroupAndFlags = keyGroup << 8;
1810	pRgn->velLow = (EAS_U8) lowVel;
1811	pRgn->velHigh = (EAS_U8) highVel;
1812	if (optionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE)
1813		pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_NON_SELF_EXCLUSIVE;
1814
1815	return EAS_SUCCESS;
1816}
1817
1818/*----------------------------------------------------------------------------
1819 * Parse_lart ()
1820 *----------------------------------------------------------------------------
1821 * Purpose:
1822 *
1823 *
1824 * Inputs:
1825 *
1826 *
1827 * Outputs:
1828 *
1829 *
1830 *----------------------------------------------------------------------------
1831*/
1832static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt)
1833{
1834	EAS_RESULT result;
1835	EAS_U32 temp;
1836	EAS_I32 endChunk;
1837	EAS_I32 chunkPos;
1838	EAS_I32 art1Pos;
1839	EAS_I32 art2Pos;
1840
1841	/* seek to start of chunk */
1842	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1843		return result;
1844
1845	/* no articulation chunks yet */
1846	art1Pos = art2Pos = 0;
1847
1848	/* read to end of chunk */
1849	endChunk = pos + size;
1850	while (pos < endChunk)
1851	{
1852		chunkPos = pos;
1853
1854		/* get the next chunk type */
1855		if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS)
1856			return result;
1857
1858		/* parse useful chunks */
1859		switch (temp)
1860		{
1861			case CHUNK_CDL:
1862				if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS)
1863					return result;
1864
1865				/* if conditional chunk evaluates false, skip this list */
1866				if (!temp)
1867					return EAS_SUCCESS;
1868				break;
1869
1870			case CHUNK_ART1:
1871				art1Pos = chunkPos + 8;
1872				break;
1873
1874			case CHUNK_ART2:
1875				art2Pos = chunkPos + 8;
1876				break;
1877
1878			default:
1879				break;
1880
1881		}
1882	}
1883
1884	if (art1Pos)
1885	{
1886		if ((result = Parse_art(pDLSData, art1Pos, pArt)) != EAS_SUCCESS)
1887			return result;
1888	}
1889
1890	if (art2Pos)
1891	{
1892		if ((result = Parse_art(pDLSData, art2Pos, pArt)) != EAS_SUCCESS)
1893			return result;
1894	}
1895
1896	return EAS_SUCCESS;
1897}
1898
1899/*----------------------------------------------------------------------------
1900 * Parse_art()
1901 *----------------------------------------------------------------------------
1902 * Purpose:
1903 *
1904 *
1905 * Inputs:
1906 *
1907 *
1908 * Outputs:
1909 *
1910 *
1911 *----------------------------------------------------------------------------
1912*/
1913static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt)
1914{
1915	EAS_RESULT result;
1916	EAS_U32 structSize;
1917	EAS_U32 numConnections;
1918	EAS_U16 source;
1919	EAS_U16 control;
1920	EAS_U16 destination;
1921	EAS_U16 transform;
1922	EAS_I32 scale;
1923	EAS_INT i;
1924
1925	/* seek to start of data */
1926	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1927		return result;
1928
1929	/* get the structure size */
1930	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &structSize, EAS_FALSE)) != EAS_SUCCESS)
1931		return result;
1932	pos += (EAS_I32) structSize;
1933
1934	/* get the number of connections */
1935	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &numConnections, EAS_FALSE)) != EAS_SUCCESS)
1936		return result;
1937
1938	/* skip to start of connections */
1939	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS)
1940		return result;
1941
1942	while (numConnections--)
1943	{
1944
1945		/* read the connection data */
1946		if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &source, EAS_FALSE)) != EAS_SUCCESS)
1947			return result;
1948		if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &control, EAS_FALSE)) != EAS_SUCCESS)
1949			return result;
1950		if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &destination, EAS_FALSE)) != EAS_SUCCESS)
1951			return result;
1952		if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &transform, EAS_FALSE)) != EAS_SUCCESS)
1953			return result;
1954		if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &scale, EAS_FALSE)) != EAS_SUCCESS)
1955			return result;
1956
1957		/* look up the connection */
1958		for (i = 0; i < (EAS_INT) ENTRIES_IN_CONN_TABLE; i++)
1959		{
1960			if ((connTable[i].source == source) &&
1961				(connTable[i].destination == destination) &&
1962				(connTable[i].control == control))
1963			{
1964				/*lint -e{704} use shift for performance */
1965				pArt->values[connTable[i].connection] = (EAS_I16) (scale >> 16);
1966				pArt->values[PARAM_MODIFIED] = EAS_TRUE;
1967				break;
1968			}
1969		}
1970		if (i == PARAM_TABLE_SIZE)
1971			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "WARN: Unsupported parameter in DLS file\n"); */ }
1972	}
1973
1974	return EAS_SUCCESS;
1975}
1976
1977/*----------------------------------------------------------------------------
1978 * Parse_wlnk ()
1979 *----------------------------------------------------------------------------
1980 * Purpose:
1981 *
1982 *
1983 * Inputs:
1984 *
1985 *
1986 * Outputs:
1987 *
1988 *
1989 *----------------------------------------------------------------------------
1990*/
1991static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex)
1992{
1993	EAS_RESULT result;
1994
1995	/* we only care about the the index */
1996	if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + 8)) != EAS_SUCCESS)
1997		return result;
1998
1999	/* read the index */
2000	return EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle,pWaveIndex, EAS_FALSE);
2001}
2002
2003/*----------------------------------------------------------------------------
2004 * PopcdlStack ()
2005 *----------------------------------------------------------------------------
2006 * Purpose:
2007 *
2008 *
2009 * Inputs:
2010 *
2011 *
2012 * Outputs:
2013 *
2014 *
2015 *----------------------------------------------------------------------------
2016*/
2017static EAS_RESULT PopcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 *pValue)
2018{
2019
2020	/* stack underflow, cdl block has an errorr */
2021	if (*pStackPtr < 0)
2022		return EAS_ERROR_FILE_FORMAT;
2023
2024	/* pop the value off the stack */
2025	*pValue = pStack[*pStackPtr];
2026	*pStackPtr = *pStackPtr - 1;
2027	return EAS_SUCCESS;
2028}
2029
2030/*----------------------------------------------------------------------------
2031 * PushcdlStack ()
2032 *----------------------------------------------------------------------------
2033 * Purpose:
2034 *
2035 *
2036 * Inputs:
2037 *
2038 *
2039 * Outputs:
2040 *
2041 *
2042 *----------------------------------------------------------------------------
2043*/
2044static EAS_RESULT PushcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 value)
2045{
2046
2047	/* stack overflow, return an error */
2048	if (*pStackPtr >= CDL_STACK_SIZE)
2049		return EAS_ERROR_FILE_FORMAT;
2050
2051	/* push the value onto the stack */
2052	*pStackPtr = *pStackPtr + 1;
2053	pStack[*pStackPtr] = value;
2054	return EAS_SUCCESS;
2055}
2056
2057/*----------------------------------------------------------------------------
2058 * QueryGUID ()
2059 *----------------------------------------------------------------------------
2060 * Purpose:
2061 *
2062 *
2063 * Inputs:
2064 *
2065 *
2066 * Outputs:
2067 *
2068 *
2069 *----------------------------------------------------------------------------
2070*/
2071static EAS_BOOL QueryGUID (const DLSID *pGUID, EAS_U32 *pValue)
2072{
2073
2074	/* assume false */
2075	*pValue = 0;
2076	if (EAS_HWMemCmp(&DLSID_GMInHardware, pGUID, sizeof(DLSID)) == 0)
2077	{
2078		*pValue = 0xffffffff;
2079		return EAS_TRUE;
2080	}
2081
2082	if (EAS_HWMemCmp(&DLSID_GSInHardware, pGUID, sizeof(DLSID)) == 0)
2083		return EAS_TRUE;
2084
2085	if (EAS_HWMemCmp(&DLSID_XGInHardware, pGUID, sizeof(DLSID)) == 0)
2086		return EAS_TRUE;
2087
2088	if (EAS_HWMemCmp(&DLSID_SupportsDLS1, pGUID, sizeof(DLSID)) == 0)
2089	{
2090		*pValue = 0xffffffff;
2091		return EAS_TRUE;
2092	}
2093
2094	if (EAS_HWMemCmp(&DLSID_SupportsDLS2, pGUID, sizeof(DLSID)) == 0)
2095		return EAS_TRUE;
2096
2097	if (EAS_HWMemCmp(&DLSID_SampleMemorySize, pGUID, sizeof(DLSID)) == 0)
2098	{
2099		*pValue = MAX_DLS_MEMORY;
2100		return EAS_TRUE;
2101	}
2102
2103	if (EAS_HWMemCmp(&DLSID_ManufacturersID, pGUID, sizeof(DLSID)) == 0)
2104	{
2105		*pValue = 0x0000013A;
2106		return EAS_TRUE;
2107	}
2108
2109	if (EAS_HWMemCmp(&DLSID_ProductID, pGUID, sizeof(DLSID)) == 0)
2110	{
2111		*pValue = LIB_VERSION;
2112		return EAS_TRUE;
2113	}
2114
2115	if (EAS_HWMemCmp(&DLSID_SamplePlaybackRate, pGUID, sizeof(DLSID)) == 0)
2116	{
2117		*pValue = (EAS_U32) outputSampleRate;
2118		return EAS_TRUE;
2119	}
2120
2121	/* unrecognized DLSID */
2122	return EAS_FALSE;
2123}
2124
2125/*----------------------------------------------------------------------------
2126 * ReadDLSID ()
2127 *----------------------------------------------------------------------------
2128 * Purpose:
2129 * Reads a DLSID in a manner that is not sensitive to processor endian-ness
2130 *
2131 * Inputs:
2132 *
2133 *
2134 * Outputs:
2135 *
2136 *
2137 *----------------------------------------------------------------------------
2138*/
2139static EAS_RESULT ReadDLSID (SDLS_SYNTHESIZER_DATA *pDLSData, DLSID *pDLSID)
2140{
2141	EAS_RESULT result;
2142	EAS_I32 n;
2143
2144	if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data1, EAS_FALSE)) != EAS_SUCCESS)
2145		return result;
2146	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data2, EAS_FALSE)) != EAS_SUCCESS)
2147		return result;
2148	if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data3, EAS_FALSE)) != EAS_SUCCESS)
2149		return result;
2150	return EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pDLSID->Data4, sizeof(pDLSID->Data4), &n);
2151}
2152
2153/*----------------------------------------------------------------------------
2154 * Parse_cdl ()
2155 *----------------------------------------------------------------------------
2156 * Purpose:
2157 *
2158 *
2159 * Inputs:
2160 *
2161 *
2162 * Outputs:
2163 *
2164 *
2165 *----------------------------------------------------------------------------
2166*/
2167static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue)
2168{
2169	EAS_RESULT result;
2170	EAS_U32 stack[CDL_STACK_SIZE];
2171	EAS_U16 opcode;
2172	EAS_INT stackPtr;
2173	EAS_U32 x, y;
2174	DLSID dlsid;
2175
2176	stackPtr = -1;
2177	*pValue = 0;
2178	x = 0;
2179	while (size)
2180	{
2181		/* read the opcode */
2182		if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &opcode, EAS_FALSE)) != EAS_SUCCESS)
2183			return result;
2184
2185		/* handle binary opcodes */
2186		if (opcode <= DLS_CDL_EQ)
2187		{
2188			/* pop X and Y */
2189			if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS)
2190				return result;
2191			if ((result = PopcdlStack(stack, &stackPtr, &y)) != EAS_SUCCESS)
2192				return result;
2193			switch (opcode)
2194			{
2195				case DLS_CDL_AND:
2196					x = x & y;
2197					break;
2198				case DLS_CDL_OR:
2199					x = x | y;
2200					break;
2201				case DLS_CDL_XOR:
2202					x = x ^ y;
2203					break;
2204				case DLS_CDL_ADD:
2205					x = x + y;
2206					break;
2207				case DLS_CDL_SUBTRACT:
2208					x = x - y;
2209					break;
2210				case DLS_CDL_MULTIPLY:
2211					x = x * y;
2212					break;
2213				case DLS_CDL_DIVIDE:
2214					if (!y)
2215						return EAS_ERROR_FILE_FORMAT;
2216					x = x / y;
2217					break;
2218				case DLS_CDL_LOGICAL_AND:
2219					x = (x && y);
2220					break;
2221				case DLS_CDL_LOGICAL_OR:
2222					x = (x || y);
2223					break;
2224				case DLS_CDL_LT:
2225					x = (x < y);
2226					break;
2227				case DLS_CDL_LE:
2228					x = (x <= y);
2229					break;
2230				case DLS_CDL_GT:
2231					x = (x > y);
2232					break;
2233				case DLS_CDL_GE:
2234					x = (x >= y);
2235					break;
2236				case DLS_CDL_EQ:
2237					x = (x == y);
2238					break;
2239				default:
2240					break;
2241			}
2242		}
2243
2244		else if (opcode == DLS_CDL_NOT)
2245		{
2246			if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS)
2247				return result;
2248			x = !x;
2249		}
2250
2251		else if (opcode == DLS_CDL_CONST)
2252		{
2253			if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &x, EAS_FALSE)) != EAS_SUCCESS)
2254				return result;
2255		}
2256
2257		else if (opcode == DLS_CDL_QUERY)
2258		{
2259			if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS)
2260				return result;
2261			QueryGUID(&dlsid, &x);
2262		}
2263
2264		else if (opcode == DLS_CDL_QUERYSUPPORTED)
2265		{
2266			if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS)
2267				return result;
2268			x = QueryGUID(&dlsid, &y);
2269		}
2270		else
2271			{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported opcode %d in DLS file\n", opcode); */ }
2272
2273		/* push the result on the stack */
2274		if ((result = PushcdlStack(stack, &stackPtr, x)) != EAS_SUCCESS)
2275			return result;
2276	}
2277
2278	/* pop the last result off the stack */
2279	return PopcdlStack(stack, &stackPtr, pValue);
2280}
2281
2282/*----------------------------------------------------------------------------
2283 * Convert_rgn()
2284 *----------------------------------------------------------------------------
2285 * Purpose:
2286 * Convert region data from DLS to EAS
2287 *
2288 * Inputs:
2289 *
2290 *
2291 * Outputs:
2292 *
2293 *
2294 *----------------------------------------------------------------------------
2295*/
2296static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp)
2297{
2298	S_DLS_REGION *pRgn;
2299
2300	/* setup pointers to data structures */
2301	pRgn = &pDLSData->pDLS->pDLSRegions[regionIndex];
2302
2303	/* intiailize indices */
2304	pRgn->wtRegion.artIndex = artIndex;
2305	pRgn->wtRegion.waveIndex = waveIndex;
2306
2307	/* convert region data */
2308	/*lint -e{704} use shift for performance */
2309	pRgn->wtRegion.gain = (EAS_I16) (pWsmp->gain >> 16);
2310	pRgn->wtRegion.loopStart = pWsmp->loopStart;
2311	pRgn->wtRegion.loopEnd = (pWsmp->loopStart + pWsmp->loopLength);
2312	pRgn->wtRegion.tuning = pWsmp->fineTune -(pWsmp->unityNote * 100) + ConvertSampleRate(pWsmp->sampleRate);
2313	if (pWsmp->loopLength != 0)
2314		pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_IS_LOOPED;
2315}
2316
2317/*----------------------------------------------------------------------------
2318 * Convert_art()
2319 *----------------------------------------------------------------------------
2320 * Purpose:
2321 * Convert articulation data from DLS to EAS
2322 *
2323 * Inputs:
2324 *
2325 *
2326 * Outputs:
2327 *
2328 *
2329 *----------------------------------------------------------------------------
2330*/
2331static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt,  EAS_U16 artIndex)
2332{
2333	S_DLS_ARTICULATION *pArt;
2334
2335	/* setup pointers to data structures */
2336	pArt = &pDLSData->pDLS->pDLSArticulations[artIndex];
2337
2338	/* LFO parameters */
2339	pArt->modLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_MOD_LFO_FREQ]);
2340	pArt->modLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_MOD_LFO_DELAY]);
2341	pArt->vibLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_VIB_LFO_FREQ]);
2342	pArt->vibLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_VIB_LFO_DELAY]);
2343
2344	/* EG1 parameters */
2345	pArt->eg1.delayTime = ConvertDelay(pDLSArt->values[PARAM_VOL_EG_DELAY]);
2346	pArt->eg1.attackTime = pDLSArt->values[PARAM_VOL_EG_ATTACK];
2347	pArt->eg1.holdTime = pDLSArt->values[PARAM_VOL_EG_HOLD];
2348	pArt->eg1.decayTime = pDLSArt->values[PARAM_VOL_EG_DECAY];
2349	pArt->eg1.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_VOL_EG_SUSTAIN]);
2350	pArt->eg1.releaseTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_RELEASE]);
2351	pArt->eg1.velToAttack = pDLSArt->values[PARAM_VOL_EG_VEL_TO_ATTACK];
2352	pArt->eg1.keyNumToDecay = pDLSArt->values[PARAM_VOL_EG_KEY_TO_DECAY];
2353	pArt->eg1.keyNumToHold = pDLSArt->values[PARAM_VOL_EG_KEY_TO_HOLD];
2354	pArt->eg1ShutdownTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_SHUTDOWN]);
2355
2356	/* EG2 parameters */
2357	pArt->eg2.delayTime = ConvertDelay(pDLSArt->values[PARAM_MOD_EG_DELAY]);
2358	pArt->eg2.attackTime = pDLSArt->values[PARAM_MOD_EG_ATTACK];
2359	pArt->eg2.holdTime = pDLSArt->values[PARAM_MOD_EG_HOLD];
2360	pArt->eg2.decayTime = pDLSArt->values[PARAM_MOD_EG_DECAY];
2361	pArt->eg2.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_MOD_EG_SUSTAIN]);
2362	pArt->eg2.releaseTime = ConvertRate(pDLSArt->values[PARAM_MOD_EG_RELEASE]);
2363	pArt->eg2.velToAttack = pDLSArt->values[PARAM_MOD_EG_VEL_TO_ATTACK];
2364	pArt->eg2.keyNumToDecay = pDLSArt->values[PARAM_MOD_EG_KEY_TO_DECAY];
2365	pArt->eg2.keyNumToHold = pDLSArt->values[PARAM_MOD_EG_KEY_TO_HOLD];
2366
2367	/* filter parameters */
2368	pArt->filterCutoff = pDLSArt->values[PARAM_INITIAL_FC];
2369	pArt->filterQandFlags = ConvertQ(pDLSArt->values[PARAM_INITIAL_Q]);
2370	pArt->modLFOToFc = pDLSArt->values[PARAM_MOD_LFO_TO_FC];
2371	pArt->modLFOCC1ToFc = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_FC];
2372	pArt->modLFOChanPressToFc = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_FC];
2373	pArt->eg2ToFc = pDLSArt->values[PARAM_MOD_EG_TO_FC];
2374	pArt->velToFc = pDLSArt->values[PARAM_VEL_TO_FC];
2375	pArt->keyNumToFc = pDLSArt->values[PARAM_KEYNUM_TO_FC];
2376
2377	/* gain parameters */
2378	pArt->modLFOToGain = pDLSArt->values[PARAM_MOD_LFO_TO_GAIN];
2379	pArt->modLFOCC1ToGain = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_GAIN];
2380	pArt->modLFOChanPressToGain = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN];
2381
2382	/* pitch parameters */
2383	pArt->tuning = pDLSArt->values[PARAM_TUNING];
2384	pArt->keyNumToPitch = pDLSArt->values[PARAM_KEYNUM_TO_PITCH];
2385	pArt->vibLFOToPitch = pDLSArt->values[PARAM_VIB_LFO_TO_PITCH];
2386	pArt->vibLFOCC1ToPitch = pDLSArt->values[PARAM_VIB_LFO_CC1_TO_PITCH];
2387	pArt->vibLFOChanPressToPitch = pDLSArt->values[PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH];
2388	pArt->modLFOToPitch = pDLSArt->values[PARAM_MOD_LFO_TO_PITCH];
2389	pArt->modLFOCC1ToPitch = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_PITCH];
2390	pArt->modLFOChanPressToPitch = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH];
2391	pArt->eg2ToPitch = pDLSArt->values[PARAM_MOD_EG_TO_PITCH];
2392
2393	/* output parameters */
2394	pArt->pan = ConvertPan(pDLSArt->values[PARAM_DEFAULT_PAN]);
2395
2396	if (pDLSArt->values[PARAM_VEL_TO_GAIN] != 0)
2397		pArt->filterQandFlags |= FLAG_DLS_VELOCITY_SENSITIVE;
2398
2399#ifdef _REVERB
2400	pArt->reverbSend = pDLSArt->values[PARAM_DEFAULT_REVERB_SEND];
2401	pArt->cc91ToReverbSend = pDLSArt->values[PARAM_MIDI_CC91_TO_REVERB_SEND];
2402#endif
2403
2404#ifdef _CHORUS
2405	pArt->chorusSend = pDLSArt->values[PARAM_DEFAULT_CHORUS_SEND];
2406	pArt->cc93ToChorusSend = pDLSArt->values[PARAM_MIDI_CC93_TO_CHORUS_SEND];
2407#endif
2408}
2409
2410/*----------------------------------------------------------------------------
2411 * ConvertSampleRate()
2412 *----------------------------------------------------------------------------
2413 * Purpose:
2414 *
2415 * Inputs:
2416 *
2417 * Outputs:
2418 *
2419 * Side Effects:
2420 *----------------------------------------------------------------------------
2421*/
2422static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate)
2423{
2424	return (EAS_I16) (1200.0 * log10((double) sampleRate / (double) outputSampleRate) / log10(2.0));
2425}
2426
2427/*----------------------------------------------------------------------------
2428 * ConvertSustainEG2()
2429 *----------------------------------------------------------------------------
2430 * Convert sustain level to pitch/Fc multipler for EG2
2431 *----------------------------------------------------------------------------
2432*/
2433static EAS_I16 ConvertSustain (EAS_I32 sustain)
2434{
2435	/* check for sustain level of zero */
2436	if (sustain == 0)
2437		return 0;
2438
2439	/* convert to log2 factor */
2440	/*lint -e{704} use shift for performance */
2441	sustain = (sustain * SUSTAIN_LINEAR_CONVERSION_FACTOR) >> 15;
2442
2443	if (sustain > SYNTH_FULL_SCALE_EG1_GAIN)
2444		return SYNTH_FULL_SCALE_EG1_GAIN;
2445	return (EAS_I16) sustain;
2446}
2447
2448/*----------------------------------------------------------------------------
2449 * ConvertDelay ()
2450 *----------------------------------------------------------------------------
2451 * Converts timecents to frame count. Used for LFO and envelope
2452 * delay times.
2453 *----------------------------------------------------------------------------
2454*/
2455EAS_I16 ConvertDelay (EAS_I32 timeCents)
2456{
2457	EAS_I32 temp;
2458
2459	if (timeCents == ZERO_TIME_IN_CENTS)
2460		return 0;
2461
2462	/* divide time by secs per frame to get number of frames */
2463	temp = timeCents - dlsRateConvert;
2464
2465	/* convert from time cents to 10-bit fraction */
2466	temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2);
2467
2468	/* convert to frame count */
2469	temp = EAS_LogToLinear16(temp - (15 << 10));
2470
2471	if (temp < SYNTH_FULL_SCALE_EG1_GAIN)
2472		return (EAS_I16) temp;
2473	return SYNTH_FULL_SCALE_EG1_GAIN;
2474}
2475
2476/*----------------------------------------------------------------------------
2477 * ConvertRate ()
2478 *----------------------------------------------------------------------------
2479 * Convert timecents to rate
2480 *----------------------------------------------------------------------------
2481*/
2482EAS_I16 ConvertRate (EAS_I32 timeCents)
2483{
2484	EAS_I32 temp;
2485
2486	if (timeCents == ZERO_TIME_IN_CENTS)
2487		return SYNTH_FULL_SCALE_EG1_GAIN;
2488
2489	/* divide frame rate by time in log domain to get rate */
2490	temp = dlsRateConvert - timeCents;
2491
2492#if 1
2493	temp = EAS_Calculate2toX(temp);
2494#else
2495	/* convert from time cents to 10-bit fraction */
2496	temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2);
2497
2498	/* convert to rate */
2499	temp = EAS_LogToLinear16(temp);
2500#endif
2501
2502	if (temp < SYNTH_FULL_SCALE_EG1_GAIN)
2503		return (EAS_I16) temp;
2504	return SYNTH_FULL_SCALE_EG1_GAIN;
2505}
2506
2507
2508/*----------------------------------------------------------------------------
2509 * ConvertLFOPhaseIncrement()
2510 *----------------------------------------------------------------------------
2511 * Purpose:
2512 *
2513 * Inputs:
2514 *
2515 * Outputs:
2516 *
2517 * Side Effects:
2518 *----------------------------------------------------------------------------
2519*/
2520static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents)
2521{
2522
2523	/* check range */
2524	if (pitchCents > MAX_LFO_FREQUENCY_IN_PITCHCENTS)
2525		pitchCents = MAX_LFO_FREQUENCY_IN_PITCHCENTS;
2526	if (pitchCents < MIN_LFO_FREQUENCY_IN_PITCHCENTS)
2527		pitchCents = MIN_LFO_FREQUENCY_IN_PITCHCENTS;
2528
2529	/* double the rate and divide by frame rate by subtracting in log domain */
2530	pitchCents = pitchCents - dlsLFOFrequencyConvert;
2531
2532	/* convert to phase increment */
2533	return (EAS_I16) EAS_Calculate2toX(pitchCents);
2534}
2535
2536/*----------------------------------------------------------------------------
2537 * ConvertPan()
2538 *----------------------------------------------------------------------------
2539 * Purpose:
2540 *
2541 * Inputs:
2542 *
2543 * Outputs:
2544 *
2545 * Side Effects:
2546 *----------------------------------------------------------------------------
2547*/
2548static EAS_I8 ConvertPan (EAS_I32 pan)
2549{
2550
2551	/* multiply by conversion factor */
2552	pan = FMUL_15x15 (PAN_CONVERSION_FACTOR, pan);
2553	if (pan < MIN_PAN_VALUE)
2554		return MIN_PAN_VALUE;
2555	if (pan > MAX_PAN_VALUE)
2556		return MAX_PAN_VALUE;
2557	return (EAS_I8) pan;
2558}
2559
2560/*----------------------------------------------------------------------------
2561 * ConvertQ()
2562 *----------------------------------------------------------------------------
2563 * Convert the DLS filter resonance to an index value used by the synth
2564 * that accesses tables of coefficients based on the Q.
2565 *----------------------------------------------------------------------------
2566*/
2567static EAS_U8 ConvertQ (EAS_I32 q)
2568{
2569
2570	/* apply limits */
2571	if (q <= 0)
2572		return 0;
2573
2574	/* convert to table index */
2575	/*lint -e{704} use shift for performance */
2576	q = (FILTER_Q_CONVERSION_FACTOR * q + 0x4000) >> 15;
2577
2578	/* apply upper limit */
2579	if (q >= FILTER_RESONANCE_NUM_ENTRIES)
2580		q = FILTER_RESONANCE_NUM_ENTRIES - 1;
2581	return (EAS_U8) q;
2582}
2583
2584#ifdef _DEBUG_DLS
2585/*----------------------------------------------------------------------------
2586 * DumpDLS()
2587 *----------------------------------------------------------------------------
2588*/
2589static void DumpDLS (S_EAS *pEAS)
2590{
2591	S_DLS_ARTICULATION *pArt;
2592	S_DLS_REGION *pRegion;
2593	EAS_INT i;
2594	EAS_INT j;
2595
2596	EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000022 , pEAS->numPrograms);
2597	EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000023 , pEAS->numWTRegions);
2598	EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000024 , pEAS->numDLSArticulations);
2599	EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000025 , pEAS->numSamples);
2600
2601	/* dump the instruments */
2602	for (i = 0; i < pEAS->numPrograms; i++)
2603	{
2604		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000026 ,
2605				pEAS->pPrograms[i].locale >> 16,
2606				(pEAS->pPrograms[i].locale >> 8) & 0x7f,
2607				pEAS->pPrograms[i].locale & 0x7f);
2608
2609		for (j = pEAS->pPrograms[i].regionIndex; ; j++)
2610		{
2611			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000027 , j);
2612			pRegion = &pEAS->pWTRegions[j];
2613			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000028 , pRegion->gain);
2614			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000029 , pRegion->region.rangeLow, pRegion->region.rangeHigh);
2615			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002a , pRegion->region.keyGroupAndFlags);
2616			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002b , pRegion->loopStart);
2617			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002c , pRegion->loopEnd);
2618			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002d , pRegion->tuning);
2619			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002e , pRegion->artIndex);
2620			EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002f , pRegion->waveIndex);
2621
2622			if (pRegion->region.keyGroupAndFlags & REGION_FLAG_LAST_REGION)
2623				break;
2624		}
2625
2626	}
2627
2628	/* dump the articulation data */
2629	for (i = 0; i < pEAS->numDLSArticulations; i++)
2630	{
2631		/* articulation data */
2632		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000030 , i);
2633		pArt = &pEAS->pDLSArticulations[i];
2634		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000031 , pArt->m_nEG2toFilterDepth);
2635		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000032 , pArt->m_nEG2toPitchDepth);
2636		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000033 , pArt->m_nFilterCutoffFrequency);
2637		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000034 , pArt->m_nFilterResonance);
2638		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000035 , pArt->m_nLFOAmplitudeDepth);
2639		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000036 , pArt->m_nLFODelayTime);
2640		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000037 , pArt->m_nLFOFrequency);
2641		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000038 , pArt->m_nLFOPitchDepth);
2642		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000039 , pArt->m_nPan);
2643
2644		/* EG1 data */
2645		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003a , pArt->m_sEG1.m_nAttack);
2646		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003b , pArt->m_sEG1.m_nDecay);
2647		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003c , pArt->m_sEG1.m_nSustain);
2648		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003d , pArt->m_sEG1.m_nRelease);
2649
2650		/* EG2 data */
2651		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003e , pArt->m_sEG2.m_nAttack);
2652		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003f , pArt->m_sEG2.m_nDecay);
2653		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000040 , pArt->m_sEG2.m_nSustain);
2654		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000041 , pArt->m_sEG2.m_nRelease);
2655
2656	}
2657
2658	/* dump the waves */
2659	for (i = 0; i < pEAS->numSamples; i++)
2660	{
2661		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000042 , i);
2662		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000043 , pEAS->pSampleLen[i]);
2663		EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000044 , pEAS->ppSamples[i]);
2664	}
2665
2666}
2667#endif
2668
2669