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