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, <emp, EAS_FALSE)) != EAS_SUCCESS) 1097 return result; 1098 1099 /* sample loops */ 1100 if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, 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, <emp, EAS_FALSE)) != EAS_SUCCESS) 1116 return result; 1117 1118 /* get loop type */ 1119 if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, 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, <emp, 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, ®ionCount, &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