• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*----------------------------------------------------------------------------
2  *
3  * File:
4  * eas_public.c
5  *
6  * Contents and purpose:
7  * Contains EAS library public interface
8  *
9  * Copyright Sonic Network Inc. 2004
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: 842 $
26  *   $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $
27  *----------------------------------------------------------------------------
28 */
29 
30 #include "eas_synthcfg.h"
31 #include "eas.h"
32 #include "eas_config.h"
33 #include "eas_host.h"
34 #include "eas_report.h"
35 #include "eas_data.h"
36 #include "eas_parser.h"
37 #include "eas_pcm.h"
38 #include "eas_midi.h"
39 #include "eas_mixer.h"
40 #include "eas_build.h"
41 #include "eas_vm_protos.h"
42 #include "eas_math.h"
43 
44 #ifdef JET_INTERFACE
45 #include "jet_data.h"
46 #endif
47 
48 #ifdef DLS_SYNTHESIZER
49 #include "eas_mdls.h"
50 #endif
51 
52 /* number of events to parse before calling EAS_HWYield function */
53 #define YIELD_EVENT_COUNT       10
54 
55 /*----------------------------------------------------------------------------
56  * easLibConfig
57  *
58  * This structure is available through the EAS public interface to allow
59  * the user to check the configuration of the library.
60  *----------------------------------------------------------------------------
61 */
62 static const S_EAS_LIB_CONFIG easLibConfig =
63 {
64     LIB_VERSION,
65 #ifdef _CHECKED_BUILD
66     EAS_TRUE,
67 #else
68     EAS_FALSE,
69 #endif
70     MAX_SYNTH_VOICES,
71     NUM_OUTPUT_CHANNELS,
72     _OUTPUT_SAMPLE_RATE,
73     BUFFER_SIZE_IN_MONO_SAMPLES,
74 #ifdef _FILTER_ENABLED
75     EAS_TRUE,
76 #else
77     EAS_FALSE,
78 #endif
79     _BUILD_TIME_,
80     _BUILD_VERSION_
81 };
82 
83 /* local prototypes */
84 static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode);
85 
86 /*----------------------------------------------------------------------------
87  * EAS_SetStreamParameter
88  *----------------------------------------------------------------------------
89  * Sets the specified parameter in the stream. Allows access to
90  * customizable settings within the individual file parsers.
91  *----------------------------------------------------------------------------
92  * pEASData         - pointer to EAS persistent data object
93  * pStream          - stream handle
94  * param            - enumerated parameter (see eas_parser.h)
95  * value            - new value
96  *----------------------------------------------------------------------------
97 */
EAS_SetStreamParameter(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_I32 param,EAS_I32 value)98 EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value)
99 {
100     S_FILE_PARSER_INTERFACE *pParserModule;
101 
102     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
103     if (pParserModule->pfSetData)
104         return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value);
105     return EAS_ERROR_FEATURE_NOT_AVAILABLE;
106 }
107 
108 /*----------------------------------------------------------------------------
109  * EAS_GetStreamParameter
110  *----------------------------------------------------------------------------
111  * Sets the specified parameter in the stream. Allows access to
112  * customizable settings within the individual file parsers.
113  *----------------------------------------------------------------------------
114  * pEASData         - pointer to EAS persistent data object
115  * pStream          - stream handle
116  * param            - enumerated parameter (see eas_parser.h)
117  * pValue           - pointer to variable to receive current setting
118  *----------------------------------------------------------------------------
119 */
EAS_GetStreamParameter(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_I32 param,EAS_I32 * pValue)120 EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue)
121 {
122     S_FILE_PARSER_INTERFACE *pParserModule;
123 
124     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
125     if (pParserModule->pfGetData)
126         return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue);
127     return EAS_ERROR_FEATURE_NOT_AVAILABLE;
128 }
129 
130 /*----------------------------------------------------------------------------
131  * EAS_StreamReady()
132  *----------------------------------------------------------------------------
133  * This routine sets common parameters like transpose, volume, etc.
134  * First, it attempts to use the parser EAS_SetStreamParameter interface. If that
135  * fails, it attempts to get the synth handle from the parser and
136  * set the parameter directly on the synth. This eliminates duplicate
137  * code in the parser.
138  *----------------------------------------------------------------------------
139 */
EAS_StreamReady(S_EAS_DATA * pEASData,EAS_HANDLE pStream)140 EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream)
141 {
142     S_FILE_PARSER_INTERFACE *pParserModule;
143     EAS_STATE state;
144 
145     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
146     if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS)
147         return EAS_FALSE;
148     return (state < EAS_STATE_OPEN);
149 }
150 
151 /*----------------------------------------------------------------------------
152  * EAS_IntSetStrmParam()
153  *----------------------------------------------------------------------------
154  * This routine sets common parameters like transpose, volume, etc.
155  * First, it attempts to use the parser EAS_SetStreamParameter interface. If that
156  * fails, it attempts to get the synth handle from the parser and
157  * set the parameter directly on the synth. This eliminates duplicate
158  * code in the parser.
159  *----------------------------------------------------------------------------
160 */
EAS_IntSetStrmParam(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_INT param,EAS_I32 value)161 EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value)
162 {
163     S_SYNTH *pSynth;
164 
165     /* try to set the parameter using stream interface */
166     if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS)
167         return EAS_SUCCESS;
168 
169     /* get a pointer to the synth object and set it directly */
170     /*lint -e{740} we are cheating by passing a pointer through this interface */
171     if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
172         return EAS_ERROR_INVALID_PARAMETER;
173 
174     if (pSynth == NULL)
175         return EAS_ERROR_INVALID_PARAMETER;
176 
177     switch (param)
178     {
179 
180 #ifdef DLS_SYNTHESIZER
181         case PARSER_DATA_DLS_COLLECTION:
182             {
183                 EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value);
184                 if (result == EAS_SUCCESS)
185                 {
186                     DLSAddRef((S_DLS*) value);
187                     VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth);
188                 }
189                 return result;
190             }
191 #endif
192 
193         case PARSER_DATA_EAS_LIBRARY:
194             return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value);
195 
196         case PARSER_DATA_POLYPHONY:
197             return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value);
198 
199         case PARSER_DATA_PRIORITY:
200             return VMSetPriority(pEASData->pVoiceMgr, pSynth, value);
201 
202         case PARSER_DATA_TRANSPOSITION:
203             VMSetTranposition(pSynth, value);
204             break;
205 
206         case PARSER_DATA_VOLUME:
207             VMSetVolume(pSynth, (EAS_U16) value);
208             break;
209 
210         default:
211             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ }
212             return EAS_ERROR_INVALID_PARAMETER;
213     }
214 
215     return EAS_SUCCESS;
216 }
217 
218 /*----------------------------------------------------------------------------
219  * EAS_IntGetStrmParam()
220  *----------------------------------------------------------------------------
221  * This routine gets common parameters like transpose, volume, etc.
222  * First, it attempts to use the parser EAS_GetStreamParameter interface. If that
223  * fails, it attempts to get the synth handle from the parser and
224  * get the parameter directly on the synth.
225  *----------------------------------------------------------------------------
226 */
EAS_IntGetStrmParam(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_INT param,EAS_I32 * pValue)227 EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue)
228 {
229     S_SYNTH *pSynth;
230 
231     /* try to set the parameter */
232     if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS)
233         return EAS_SUCCESS;
234 
235     /* get a pointer to the synth object and retrieve data directly */
236     /*lint -e{740} we are cheating by passing a pointer through this interface */
237     if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
238         return EAS_ERROR_INVALID_PARAMETER;
239 
240     if (pSynth == NULL)
241         return EAS_ERROR_INVALID_PARAMETER;
242 
243     switch (param)
244     {
245         case PARSER_DATA_POLYPHONY:
246             return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue);
247 
248         case PARSER_DATA_PRIORITY:
249             return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue);
250 
251         case PARSER_DATA_TRANSPOSITION:
252             VMGetTranposition(pSynth, pValue);
253             break;
254 
255         case PARSER_DATA_NOTE_COUNT:
256             *pValue = VMGetNoteCount(pSynth);
257             break;
258 
259         default:
260             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ }
261             return EAS_ERROR_INVALID_PARAMETER;
262     }
263 
264     return EAS_SUCCESS;
265 }
266 
267 /*----------------------------------------------------------------------------
268  * EAS_AllocateStream()
269  *----------------------------------------------------------------------------
270  * Purpose:
271  * Allocates a stream handle
272  *
273  * Inputs:
274  *
275  * Outputs:
276  *
277  *----------------------------------------------------------------------------
278 */
EAS_AllocateStream(EAS_DATA_HANDLE pEASData)279 static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData)
280 {
281     EAS_INT streamNum;
282 
283     /* check for static allocation, only one stream allowed */
284     if (pEASData->staticMemoryModel)
285     {
286         if (pEASData->streams[0].handle != NULL)
287         {
288             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ }
289             return -1;
290         }
291         return 0;
292     }
293 
294     /* dynamic model */
295     for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++)
296         if (pEASData->streams[streamNum].handle == NULL)
297             break;
298     if (streamNum == MAX_NUMBER_STREAMS)
299     {
300         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ }
301         return -1;
302     }
303     return streamNum;
304 }
305 
306 /*----------------------------------------------------------------------------
307  * EAS_InitStream()
308  *----------------------------------------------------------------------------
309  * Purpose:
310  * Initialize a stream
311  *
312  * Inputs:
313  *
314  * Outputs:
315  *
316  *----------------------------------------------------------------------------
317 */
EAS_InitStream(S_EAS_STREAM * pStream,EAS_VOID_PTR pParserModule,EAS_VOID_PTR streamHandle)318 static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle)
319 {
320     pStream->pParserModule = pParserModule;
321     pStream->handle = streamHandle;
322     pStream->time = 0;
323     pStream->frameLength = AUDIO_FRAME_LENGTH;
324     pStream->repeatCount = 0;
325     pStream->volume = DEFAULT_STREAM_VOLUME;
326     pStream->streamFlags = 0;
327 }
328 
329 /*----------------------------------------------------------------------------
330  * EAS_Config()
331  *----------------------------------------------------------------------------
332  * Purpose:
333  * Returns a pointer to a structure containing the configuration options
334  * in this library build.
335  *
336  * Inputs:
337  *
338  * Outputs:
339  *
340  *----------------------------------------------------------------------------
341 */
EAS_Config(void)342 EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void)
343 {
344     return &easLibConfig;
345 }
346 
347 /*----------------------------------------------------------------------------
348  * EAS_Init()
349  *----------------------------------------------------------------------------
350  * Purpose:
351  * Initialize the synthesizer library
352  *
353  * Inputs:
354  *  ppEASData       - pointer to data handle variable for this instance
355  *
356  * Outputs:
357  *
358  *----------------------------------------------------------------------------
359 */
EAS_Init(EAS_DATA_HANDLE * ppEASData)360 EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData)
361 {
362     EAS_HW_DATA_HANDLE pHWInstData;
363     EAS_RESULT result;
364     S_EAS_DATA *pEASData;
365     EAS_INT module;
366     EAS_BOOL staticMemoryModel;
367 
368     /* get the memory model */
369     staticMemoryModel = EAS_CMStaticMemoryModel();
370 
371     /* initialize the host wrapper interface */
372     *ppEASData = NULL;
373     if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS)
374         return result;
375 
376     /* check Configuration Module for S_EAS_DATA allocation */
377     if (staticMemoryModel)
378         pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA);
379     else
380         pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA));
381     if (!pEASData)
382     {
383         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ }
384         return EAS_ERROR_MALLOC_FAILED;
385     }
386 
387     /* initialize some data */
388     EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA));
389     pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel;
390     pEASData->hwInstData = pHWInstData;
391     pEASData->renderTime = 0;
392 
393     /* set header search flag */
394 #ifdef FILE_HEADER_SEARCH
395     pEASData->searchHeaderFlag = EAS_TRUE;
396 #endif
397 
398     /* initalize parameters */
399     EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME);
400 
401 #ifdef _METRICS_ENABLED
402     /* initalize the metrics module */
403     pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS);
404     if (pEASData->pMetricsModule != NULL)
405     {
406         if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS)
407         {
408             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ }
409             return result;
410         }
411     }
412 #endif
413 
414     /* initailize the voice manager & synthesizer */
415     if ((result = VMInitialize(pEASData)) != EAS_SUCCESS)
416         return result;
417 
418     /* initialize mix engine */
419     if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS)
420     {
421         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ }
422         return result;
423     }
424 
425     /* initialize effects modules */
426     for (module = 0; module < NUM_EFFECTS_MODULES; module++)
427     {
428         pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module);
429         if (pEASData->effectsModules[module].effect != NULL)
430         {
431             if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS)
432             {
433                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ }
434                 return result;
435             }
436         }
437     }
438 
439     /* initialize PCM engine */
440     if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS)
441     {
442         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ }
443         return result;
444     }
445 
446     /* return instance data pointer to host */
447     *ppEASData = pEASData;
448 
449     return EAS_SUCCESS;
450 }
451 
452 /*----------------------------------------------------------------------------
453  * EAS_Shutdown()
454  *----------------------------------------------------------------------------
455  * Purpose:
456  * Shuts down the library. Deallocates any memory associated with the
457  * synthesizer (dynamic memory model only)
458  *
459  * Inputs:
460  *  pEASData        - handle to data for this instance
461  *
462  * Outputs:
463  *
464  *----------------------------------------------------------------------------
465 */
EAS_Shutdown(EAS_DATA_HANDLE pEASData)466 EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData)
467 {
468     EAS_HW_DATA_HANDLE hwInstData;
469     EAS_RESULT result, reportResult;
470     EAS_INT i;
471 
472     /* establish pointers */
473     hwInstData = pEASData->hwInstData;
474 
475     /* check for NULL handle */
476     if (!pEASData)
477         return EAS_ERROR_HANDLE_INTEGRITY;
478 
479     /* if there are streams open, close them */
480     reportResult = EAS_SUCCESS;
481     for (i = 0; i < MAX_NUMBER_STREAMS; i++)
482     {
483         if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle)
484         {
485             if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS)
486             {
487                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ }
488                 reportResult = result;
489             }
490         }
491     }
492 
493     /* shutdown PCM engine */
494     if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS)
495     {
496         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ }
497         if (reportResult == EAS_SUCCESS)
498             reportResult = result;
499     }
500 
501     /* shutdown mix engine */
502     if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS)
503     {
504         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ }
505         if (reportResult == EAS_SUCCESS)
506             reportResult = result;
507     }
508 
509     /* shutdown effects modules */
510     for (i = 0; i < NUM_EFFECTS_MODULES; i++)
511     {
512         if (pEASData->effectsModules[i].effect)
513         {
514             if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS)
515             {
516                 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ }
517                 if (reportResult == EAS_SUCCESS)
518                     reportResult = result;
519             }
520         }
521     }
522 
523     /* shutdown the voice manager & synthesizer */
524     VMShutdown(pEASData);
525 
526 #ifdef _METRICS_ENABLED
527     /* shutdown the metrics module */
528     if (pEASData->pMetricsModule != NULL)
529     {
530         if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS)
531         {
532             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ }
533             if (reportResult == EAS_SUCCESS)
534                 reportResult = result;
535         }
536     }
537 #endif
538 
539     /* release allocated memory */
540     if (!pEASData->staticMemoryModel)
541         EAS_HWFree(hwInstData, pEASData);
542 
543     /* shutdown host wrappers */
544     if (hwInstData)
545     {
546         if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS)
547         {
548             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ }
549             if (reportResult == EAS_SUCCESS)
550                 reportResult = result;
551         }
552     }
553 
554     return reportResult;
555 }
556 
557 #ifdef JET_INTERFACE
558 /*----------------------------------------------------------------------------
559  * EAS_OpenJETStream()
560  *----------------------------------------------------------------------------
561  * Private interface for JET to open an SMF stream with an offset
562  *----------------------------------------------------------------------------
563 */
EAS_OpenJETStream(EAS_DATA_HANDLE pEASData,EAS_FILE_HANDLE fileHandle,EAS_I32 offset,EAS_HANDLE * ppStream)564 EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream)
565 {
566     EAS_RESULT result;
567     EAS_VOID_PTR streamHandle;
568     S_FILE_PARSER_INTERFACE *pParserModule;
569     EAS_INT streamNum;
570 
571     /* allocate a stream */
572     if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
573         return EAS_ERROR_MAX_STREAMS_OPEN;
574 
575     /* check Configuration Module for SMF parser */
576     *ppStream = NULL;
577     streamHandle = NULL;
578     pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0);
579     if (pParserModule == NULL)
580         return EAS_ERROR_UNRECOGNIZED_FORMAT;
581 
582     /* see if SMF parser recognizes the file */
583     if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS)
584     {
585         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ }
586         return result;
587     }
588 
589     /* parser recognized the file, return the handle */
590     if (streamHandle)
591     {
592         EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle);
593         *ppStream = &pEASData->streams[streamNum];
594         return EAS_SUCCESS;
595     }
596 
597     return EAS_ERROR_UNRECOGNIZED_FORMAT;
598 }
599 #endif
600 
601 /*----------------------------------------------------------------------------
602  * EAS_OpenFile()
603  *----------------------------------------------------------------------------
604  * Purpose:
605  * Opens a file for audio playback.
606  *
607  * Inputs:
608  * pEASData         - pointer to overall EAS data structure
609  * pHandle          - pointer to file handle
610  *
611  * Outputs:
612  *
613  *
614  * Side Effects:
615  *
616  *----------------------------------------------------------------------------
617 */
EAS_OpenFile(EAS_DATA_HANDLE pEASData,EAS_FILE_LOCATOR locator,EAS_HANDLE * ppStream)618 EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream)
619 {
620     EAS_RESULT result;
621     EAS_FILE_HANDLE fileHandle;
622     EAS_VOID_PTR streamHandle;
623     S_FILE_PARSER_INTERFACE *pParserModule;
624     EAS_INT streamNum;
625     EAS_INT moduleNum;
626 
627     /* open the file */
628     if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
629         return result;
630 
631     /* allocate a stream */
632     if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
633         return EAS_ERROR_MAX_STREAMS_OPEN;
634 
635     /* check Configuration Module for file parsers */
636     pParserModule = NULL;
637     *ppStream = NULL;
638     streamHandle = NULL;
639     for (moduleNum = 0; ; moduleNum++)
640     {
641         pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum);
642         if (pParserModule == NULL)
643             break;
644 
645         /* see if this parser recognizes it */
646         if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS)
647         {
648             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ }
649             return result;
650         }
651 
652         /* parser recognized the file, return the handle */
653         if (streamHandle)
654         {
655 
656             /* save the parser pointer and file handle */
657             EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle);
658             *ppStream = &pEASData->streams[streamNum];
659             return EAS_SUCCESS;
660         }
661 
662         /* rewind the file for the next parser */
663         if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS)
664             return result;
665     }
666 
667     /* no parser was able to recognize the file, close it and return an error */
668     EAS_HWCloseFile(pEASData->hwInstData, fileHandle);
669     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ }
670     return EAS_ERROR_UNRECOGNIZED_FORMAT;
671 }
672 
673 #ifdef MMAPI_SUPPORT
674 /*----------------------------------------------------------------------------
675  * EAS_MMAPIToneControl()
676  *----------------------------------------------------------------------------
677  * Purpose:
678  * Opens a ToneControl file for audio playback.
679  *
680  * Inputs:
681  * pEASData         - pointer to overall EAS data structure
682  * pHandle          - pointer to file handle
683  *
684  * Outputs:
685  *
686  *
687  * Side Effects:
688  *
689  *----------------------------------------------------------------------------
690 */
EAS_MMAPIToneControl(EAS_DATA_HANDLE pEASData,EAS_FILE_LOCATOR locator,EAS_HANDLE * ppStream)691 EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream)
692 {
693     EAS_RESULT result;
694     EAS_FILE_HANDLE fileHandle;
695     EAS_VOID_PTR streamHandle;
696     S_FILE_PARSER_INTERFACE *pParserModule;
697     EAS_INT streamNum;
698 
699     /* check if the tone control parser is available */
700     *ppStream = NULL;
701     streamHandle = NULL;
702     pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL);
703     if (pParserModule == NULL)
704     {
705         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ }
706         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
707     }
708 
709     /* open the file */
710     if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
711         return result;
712 
713     /* allocate a stream */
714     if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
715         return EAS_ERROR_MAX_STREAMS_OPEN;
716 
717     /* see if ToneControl parser recognizes it */
718     if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS)
719     {
720         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ }
721         return result;
722     }
723 
724     /* parser accepted the file, return the handle */
725     if (streamHandle)
726     {
727 
728         /* save the parser pointer and file handle */
729         EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle);
730         *ppStream = &pEASData->streams[streamNum];
731         return EAS_SUCCESS;
732     }
733 
734     /* parser did not recognize the file, close it and return an error */
735     EAS_HWCloseFile(pEASData->hwInstData, fileHandle);
736     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ }
737     return EAS_ERROR_UNRECOGNIZED_FORMAT;
738 }
739 
740 /*----------------------------------------------------------------------------
741  * EAS_GetWaveFmtChunk
742  *----------------------------------------------------------------------------
743  * Helper function to retrieve WAVE file fmt chunk for MMAPI
744  *----------------------------------------------------------------------------
745  * pEASData         - pointer to EAS persistent data object
746  * pStream          - stream handle
747  * pFmtChunk        - pointer to variable to receive current setting
748  *----------------------------------------------------------------------------
749 */
EAS_GetWaveFmtChunk(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_VOID_PTR * ppFmtChunk)750 EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk)
751 {
752     EAS_RESULT result;
753     EAS_I32 value;
754 
755     if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS)
756         return result;
757     *ppFmtChunk = (EAS_VOID_PTR) value;
758     return EAS_SUCCESS;
759 }
760 #endif
761 
762 /*----------------------------------------------------------------------------
763  * EAS_GetFileType
764  *----------------------------------------------------------------------------
765  * Returns the file type (see eas_types.h for enumerations)
766  *----------------------------------------------------------------------------
767  * pEASData         - pointer to EAS persistent data object
768  * pStream          - stream handle
769  * pFileType        - pointer to variable to receive file type
770  *----------------------------------------------------------------------------
771 */
EAS_GetFileType(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_I32 * pFileType)772 EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType)
773 {
774     if (!EAS_StreamReady (pEASData, pStream))
775         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
776     return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType);
777 }
778 
779 /*----------------------------------------------------------------------------
780  * EAS_Prepare()
781  *----------------------------------------------------------------------------
782  * Purpose:
783  * Prepares the synthesizer to play the file or stream. Parses the first
784  * frame of data from the file and arms the synthesizer.
785  *
786  * Inputs:
787  * pEASData         - pointer to overall EAS data structure
788  * handle           - file or stream handle
789  *
790  * Outputs:
791  *
792  *
793  * Side Effects:
794  *
795  *----------------------------------------------------------------------------
796 */
EAS_Prepare(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream)797 EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
798 {
799     S_FILE_PARSER_INTERFACE *pParserModule;
800     EAS_STATE state;
801     EAS_RESULT result;
802 
803     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
804     if (pParserModule == NULL)
805         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
806 
807     /* check for valid state */
808     result = pParserModule->pfState(pEASData, pStream->handle, &state);
809     if (result == EAS_SUCCESS)
810     {
811         /* prepare the stream */
812         if (state == EAS_STATE_OPEN)
813         {
814             pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
815             result = (*pParserModule->pfPrepare)(pEASData, pStream->handle);
816 
817             /* set volume */
818             if (result == EAS_SUCCESS)
819                 result = EAS_SetVolume(pEASData, pStream, pStream->volume);
820         }
821         else
822             result = EAS_ERROR_NOT_VALID_IN_THIS_STATE;
823 
824     }
825 
826     return result;
827 }
828 
829 /*----------------------------------------------------------------------------
830  * EAS_Render()
831  *----------------------------------------------------------------------------
832  * Purpose:
833  * Parse the Midi data and render PCM audio data.
834  *
835  * Inputs:
836  *  pEASData        - buffer for internal EAS data
837  *  pOut            - output buffer pointer
838  *  nNumRequested   - requested num samples to generate
839  *  pnNumGenerated  - actual number of samples generated
840  *
841  * Outputs:
842  *  EAS_SUCCESS if PCM data was successfully rendered
843  *
844  *----------------------------------------------------------------------------
845 */
EAS_Render(EAS_DATA_HANDLE pEASData,EAS_PCM * pOut,EAS_I32 numRequested,EAS_I32 * pNumGenerated)846 EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated)
847 {
848     S_FILE_PARSER_INTERFACE *pParserModule;
849     EAS_RESULT result;
850     EAS_I32 voicesRendered;
851     EAS_STATE parserState;
852     EAS_INT streamNum;
853 
854     /* assume no samples generated and reset workload */
855     *pNumGenerated = 0;
856     VMInitWorkload(pEASData->pVoiceMgr);
857 
858     /* no support for other buffer sizes yet */
859     if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES)
860     {
861         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n",
862             (EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ }
863         return EAS_BUFFER_SIZE_MISMATCH;
864     }
865 
866 #ifdef _METRICS_ENABLED
867     /* start performance counter */
868     if (pEASData->pMetricsData)
869         (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME);
870 #endif
871 
872     /* prep the frame buffer, do mix engine prep only if TRUE */
873 #ifdef _SPLIT_ARCHITECTURE
874     if (VMStartFrame(pEASData))
875         EAS_MixEnginePrep(pEASData, numRequested);
876 #else
877     /* prep the mix engine */
878     EAS_MixEnginePrep(pEASData, numRequested);
879 #endif
880 
881     /* save the output buffer pointer */
882     pEASData->pOutputAudioBuffer = pOut;
883 
884 
885 #ifdef _METRICS_ENABLED
886         /* start performance counter */
887         if (pEASData->pMetricsData)
888             (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME);
889 #endif
890 
891     /* if we haven't finished parsing from last time, do it now */
892     /* need to parse another frame of events before we render again */
893     for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++)
894     {
895         /* clear the locate flag */
896         pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE;
897 
898         if (pEASData->streams[streamNum].pParserModule)
899         {
900 
901             /* establish pointer to parser module */
902             pParserModule = pEASData->streams[streamNum].pParserModule;
903 
904             /* handle pause */
905             if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE)
906             {
907                 if (pParserModule->pfPause)
908                     result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle);
909                 pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE;
910             }
911 
912             /* get current state */
913             if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS)
914                 return result;
915 
916             /* handle resume */
917             if (parserState == EAS_STATE_PAUSED)
918             {
919                 if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME)
920                 {
921                     if (pParserModule->pfResume)
922                         result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle);
923                     pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME;
924                 }
925             }
926 
927             /* if necessary, parse stream */
928             if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0)
929                 if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS)
930                     return result;
931 
932             /* check for an early abort */
933             if ((pEASData->streams[streamNum].streamFlags) == 0)
934             {
935 
936 #ifdef _METRICS_ENABLED
937                 /* stop performance counter */
938                 if (pEASData->pMetricsData)
939                     (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME);
940 #endif
941 
942                 return EAS_SUCCESS;
943             }
944 
945             /* check for repeat */
946             if (pEASData->streams[streamNum].repeatCount)
947             {
948 
949                 /* check for stopped state */
950                 if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS)
951                     return result;
952                 if (parserState == EAS_STATE_STOPPED)
953                 {
954 
955                     /* decrement repeat count, unless it is negative */
956                     if (pEASData->streams[streamNum].repeatCount > 0)
957                         pEASData->streams[streamNum].repeatCount--;
958 
959                     /* reset the parser */
960                     if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS)
961                         return result;
962                     pEASData->streams[streamNum].time = 0;
963                 }
964             }
965         }
966     }
967 
968 #ifdef _METRICS_ENABLED
969     /* stop performance counter */
970     if (pEASData->pMetricsData)
971         (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME);
972 #endif
973 
974 #ifdef _METRICS_ENABLED
975     /* start the render timer */
976     if (pEASData->pMetricsData)
977         (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME);
978 #endif
979 
980     /* render audio */
981     if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS)
982     {
983         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ }
984         return result;
985     }
986 
987 #ifdef _METRICS_ENABLED
988     /* stop the render timer */
989     if (pEASData->pMetricsData) {
990         (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1);
991         (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME);
992         (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered);
993         (void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered);
994     }
995 #endif
996 
997     //2 Do we really need frameParsed?
998     /* need to parse another frame of events before we render again */
999     for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++)
1000         if (pEASData->streams[streamNum].pParserModule != NULL)
1001             pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED;
1002 
1003 #ifdef _METRICS_ENABLED
1004     /* start performance counter */
1005     if (pEASData->pMetricsData)
1006         (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME);
1007 #endif
1008 
1009     /* render PCM audio */
1010     if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS)
1011     {
1012         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ }
1013         return result;
1014     }
1015 
1016 #ifdef _METRICS_ENABLED
1017     /* stop the stream timer */
1018     if (pEASData->pMetricsData)
1019         (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME);
1020 #endif
1021 
1022 #ifdef _METRICS_ENABLED
1023     /* start the post timer */
1024     if (pEASData->pMetricsData)
1025         (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME);
1026 #endif
1027 
1028     /* for split architecture, send DSP vectors.  Do post only if return is TRUE */
1029 #ifdef _SPLIT_ARCHITECTURE
1030     if (VMEndFrame(pEASData))
1031     {
1032         /* now do post-processing */
1033         EAS_MixEnginePost(pEASData, numRequested);
1034         *pNumGenerated = numRequested;
1035     }
1036 #else
1037     /* now do post-processing */
1038     EAS_MixEnginePost(pEASData, numRequested);
1039     *pNumGenerated = numRequested;
1040 #endif
1041 
1042 #ifdef _METRICS_ENABLED
1043     /* stop the post timer */
1044     if (pEASData->pMetricsData)
1045         (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME);
1046 #endif
1047 
1048     /* advance render time */
1049     pEASData->renderTime += AUDIO_FRAME_LENGTH;
1050 
1051 #if 0
1052     /* dump workload for debug */
1053     if (pEASData->pVoiceMgr->workload)
1054         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ }
1055 #endif
1056 
1057 #ifdef _METRICS_ENABLED
1058     /* stop performance counter */
1059     if (pEASData->pMetricsData)
1060     {
1061         PERF_TIMER temp;
1062         temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME);
1063 
1064         /* if max render time, record the number of voices and time */
1065         if ((*pEASData->pMetricsModule->pfRecordMaxValue)
1066             (pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp))
1067         {
1068             (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered);
1069             (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8));
1070         }
1071     }
1072 #endif
1073 
1074 #ifdef JET_INTERFACE
1075     /* let JET to do its thing */
1076     if (pEASData->jetHandle != NULL)
1077     {
1078         result = JET_Process(pEASData);
1079         if (result != EAS_SUCCESS)
1080             return result;
1081     }
1082 #endif
1083 
1084     return EAS_SUCCESS;
1085 }
1086 
1087 /*----------------------------------------------------------------------------
1088  * EAS_SetRepeat()
1089  *----------------------------------------------------------------------------
1090  * Purpose:
1091  * Set the selected stream to repeat.
1092  *
1093  * Inputs:
1094  *  pEASData        - handle to data for this instance
1095  *  handle          - handle to stream
1096  *  repeatCount     - repeat count
1097  *
1098  * Outputs:
1099  *
1100  * Side Effects:
1101  *
1102  * Notes:
1103  *  0 = no repeat
1104  *  1 = repeat once, i.e. play through twice
1105  *  -1 = repeat forever
1106  *----------------------------------------------------------------------------
1107 */
1108 /*lint -esym(715, pEASData) reserved for future use */
EAS_SetRepeat(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 repeatCount)1109 EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount)
1110 {
1111     pStream->repeatCount = repeatCount;
1112     return EAS_SUCCESS;
1113 }
1114 
1115 /*----------------------------------------------------------------------------
1116  * EAS_GetRepeat()
1117  *----------------------------------------------------------------------------
1118  * Purpose:
1119  * Gets the current repeat count for the selected stream.
1120  *
1121  * Inputs:
1122  *  pEASData        - handle to data for this instance
1123  *  handle          - handle to stream
1124  *  pRrepeatCount   - pointer to variable to hold repeat count
1125  *
1126  * Outputs:
1127  *
1128  * Side Effects:
1129  *
1130  * Notes:
1131  *  0 = no repeat
1132  *  1 = repeat once, i.e. play through twice
1133  *  -1 = repeat forever
1134  *----------------------------------------------------------------------------
1135 */
1136 /*lint -esym(715, pEASData) reserved for future use */
EAS_GetRepeat(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 * pRepeatCount)1137 EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount)
1138 {
1139     *pRepeatCount = pStream->repeatCount;
1140     return EAS_SUCCESS;
1141 }
1142 
1143 /*----------------------------------------------------------------------------
1144  * EAS_SetPlaybackRate()
1145  *----------------------------------------------------------------------------
1146  * Purpose:
1147  * Sets the playback rate.
1148  *
1149  * Inputs:
1150  *  pEASData        - handle to data for this instance
1151  *  handle          - handle to stream
1152  *  rate            - rate (28-bit fractional amount)
1153  *
1154  * Outputs:
1155  *
1156  * Side Effects:
1157  *
1158  *----------------------------------------------------------------------------
1159 */
1160 /*lint -esym(715, pEASData) reserved for future use */
EAS_SetPlaybackRate(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_U32 rate)1161 EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate)
1162 {
1163 
1164     /* check range */
1165     if ((rate < (1 << 27)) || (rate > (1 << 29)))
1166         return EAS_ERROR_INVALID_PARAMETER;
1167 
1168     /* calculate new frame length
1169      *
1170      * NOTE: The maximum frame length we can accomodate based on a
1171      * maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a
1172      * longer frame length or a higher maximum rate, the fixed point
1173      * divide below will need to be adjusted
1174      */
1175     pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20;
1176 
1177     /* notify stream of new playback rate */
1178     EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate);
1179     return EAS_SUCCESS;
1180 }
1181 
1182 /*----------------------------------------------------------------------------
1183  * EAS_SetTransposition)
1184  *----------------------------------------------------------------------------
1185  * Purpose:
1186  * Sets the key tranposition for the synthesizer. Transposes all
1187  * melodic instruments by the specified amount. Range is limited
1188  * to +/-12 semitones.
1189  *
1190  * Inputs:
1191  *  pEASData        - handle to data for this instance
1192  *  handle          - handle to stream
1193  *  transposition   - +/-12 semitones
1194  *
1195  * Outputs:
1196  *
1197  * Side Effects:
1198  *
1199  *----------------------------------------------------------------------------
1200 */
EAS_SetTransposition(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 transposition)1201 EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition)
1202 {
1203 
1204     /* check range */
1205     if ((transposition < -12) || (transposition > 12))
1206         return EAS_ERROR_INVALID_PARAMETER;
1207 
1208     if (!EAS_StreamReady(pEASData, pStream))
1209         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1210     return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition);
1211 }
1212 
1213 /*----------------------------------------------------------------------------
1214  * EAS_ParseEvents()
1215  *----------------------------------------------------------------------------
1216  * Purpose:
1217  * Parse events in the current streams until the desired time is reached.
1218  *
1219  * Inputs:
1220  *  pEASData        - buffer for internal EAS data
1221  *  endTime         - stop parsing if this time is reached
1222  *  parseMode       - play, locate, or metadata
1223  *
1224  * Outputs:
1225  *  EAS_SUCCESS if PCM data was successfully rendered
1226  *
1227  *----------------------------------------------------------------------------
1228 */
EAS_ParseEvents(S_EAS_DATA * pEASData,EAS_HANDLE pStream,EAS_U32 endTime,EAS_INT parseMode)1229 static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode)
1230 {
1231     S_FILE_PARSER_INTERFACE *pParserModule;
1232     EAS_RESULT result;
1233     EAS_I32 parserState;
1234     EAS_BOOL done;
1235     EAS_INT yieldCount = YIELD_EVENT_COUNT;
1236     EAS_U32 time = 0;
1237 
1238     /* does this parser have a time function? */
1239     pParserModule = pStream->pParserModule;
1240     if (pParserModule->pfTime == NULL)
1241     {
1242         /* check state */
1243         if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS)
1244             return result;
1245         /* if play state, advance time */
1246         if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING))
1247             pStream->time += pStream->frameLength;
1248         done = EAS_TRUE;
1249     }
1250 
1251     /* assume we're not done, in case we abort out */
1252     else
1253     {
1254         pStream->streamFlags &= ~STREAM_FLAGS_PARSED;
1255         done = EAS_FALSE;
1256     }
1257 
1258     while (!done)
1259     {
1260 
1261         /* check for stopped state */
1262         if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS)
1263             return result;
1264         if (parserState > EAS_STATE_PLAY)
1265         {
1266             /* save current time if we're not in play mode */
1267             if (parseMode != eParserModePlay)
1268                 pStream->time = time << 8;
1269             done = EAS_TRUE;
1270             break;
1271         }
1272 
1273         /* get the next event time */
1274         if (pParserModule->pfTime)
1275         {
1276             if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS)
1277                 return result;
1278 
1279             /* if next event is within this frame, parse it */
1280             if (time < (endTime >> 8))
1281             {
1282 
1283                 /* parse the next event */
1284                 if (pParserModule->pfEvent)
1285                     if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS)
1286                         return result;
1287             }
1288 
1289             /* no more events in this frame, advance time */
1290             else
1291             {
1292                 pStream->time = endTime;
1293                 done = EAS_TRUE;
1294             }
1295         }
1296 
1297         /* check for max workload exceeded */
1298         if (VMCheckWorkload(pEASData->pVoiceMgr))
1299         {
1300             /* stop even though we may not have parsed
1301              * all the events in this frame. The parser will try to
1302              * catch up on the next frame.
1303              */
1304             break;
1305         }
1306 
1307         /* give host a chance for an early abort */
1308         if (--yieldCount == 0)
1309         {
1310             if (EAS_HWYield(pEASData->hwInstData))
1311                 break;
1312             yieldCount = YIELD_EVENT_COUNT;
1313         }
1314     }
1315 
1316     /* if no early abort, parsing is complete for this frame */
1317     if (done)
1318         pStream->streamFlags |= STREAM_FLAGS_PARSED;
1319 
1320     return EAS_SUCCESS;
1321 }
1322 
1323 /*----------------------------------------------------------------------------
1324  * EAS_ParseMetaData()
1325  *----------------------------------------------------------------------------
1326  * Purpose:
1327  *
1328  *
1329  * Inputs:
1330  * pEASData         - pointer to overall EAS data structure
1331  * handle           - file or stream handle
1332  * playLength       - pointer to variable to store the play length (in msecs)
1333  *
1334  * Outputs:
1335  *
1336  *
1337  * Side Effects:
1338  *                  - resets the parser to the start of the file
1339  *----------------------------------------------------------------------------
1340 */
EAS_ParseMetaData(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 * playLength)1341 EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength)
1342 {
1343     S_FILE_PARSER_INTERFACE *pParserModule;
1344     EAS_RESULT result;
1345     EAS_STATE state;
1346 
1347     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
1348     if (pParserModule == NULL)
1349         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
1350 
1351     /* check parser state */
1352     if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS)
1353         return result;
1354     if (state >= EAS_STATE_OPEN)
1355         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1356 
1357     /* if parser has metadata function, use that */
1358     if (pParserModule->pfGetMetaData != NULL)
1359         return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength);
1360 
1361     /* reset the parser to the beginning */
1362     if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS)
1363         return result;
1364 
1365     /* parse the file to end */
1366     pStream->time = 0;
1367     VMInitWorkload(pEASData->pVoiceMgr);
1368     if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS)
1369         return result;
1370 
1371     /* get the parser time */
1372     if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS)
1373         return result;
1374 
1375     /* reset the parser to the beginning */
1376     pStream->time = 0;
1377     return (*pParserModule->pfReset)(pEASData, pStream->handle);
1378 }
1379 
1380 /*----------------------------------------------------------------------------
1381  * EAS_RegisterMetaDataCallback()
1382  *----------------------------------------------------------------------------
1383  * Purpose:
1384  * Registers a metadata callback function for parsed metadata.
1385  *
1386  * Inputs:
1387  * pEASData         - pointer to overall EAS data structure
1388  * handle           - file or stream handle
1389  * cbFunc           - pointer to host callback function
1390  * metaDataBuffer   - pointer to metadata buffer
1391  * metaDataBufSize  - maximum size of the metadata buffer
1392  *
1393  * Outputs:
1394  *
1395  *
1396  * Side Effects:
1397  *
1398  *----------------------------------------------------------------------------
1399 */
EAS_RegisterMetaDataCallback(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_METADATA_CBFUNC cbFunc,char * metaDataBuffer,EAS_I32 metaDataBufSize,EAS_VOID_PTR pUserData)1400 EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback (
1401     EAS_DATA_HANDLE pEASData,
1402     EAS_HANDLE pStream,
1403     EAS_METADATA_CBFUNC cbFunc,
1404     char *metaDataBuffer,
1405     EAS_I32 metaDataBufSize,
1406     EAS_VOID_PTR pUserData)
1407 {
1408     S_METADATA_CB metadata;
1409 
1410     if (!EAS_StreamReady(pEASData, pStream))
1411         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1412 
1413     /* register callback function */
1414     metadata.callback = cbFunc;
1415     metadata.buffer = metaDataBuffer;
1416     metadata.bufferSize = metaDataBufSize;
1417     metadata.pUserData = pUserData;
1418     return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata);
1419 }
1420 
1421 /*----------------------------------------------------------------------------
1422  * EAS_GetNoteCount ()
1423  *----------------------------------------------------------------------------
1424  * Returns the total number of notes played in this stream
1425  *----------------------------------------------------------------------------
1426 */
EAS_GetNoteCount(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 * pNoteCount)1427 EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount)
1428 {
1429     if (!EAS_StreamReady(pEASData, pStream))
1430         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1431     return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount);
1432 }
1433 
1434 /*----------------------------------------------------------------------------
1435  * EAS_CloseFile()
1436  *----------------------------------------------------------------------------
1437  * Purpose:
1438  * Closes an audio file or stream. Playback should have either paused or
1439  * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED).
1440  *
1441  * Inputs:
1442  * pEASData         - pointer to overall EAS data structure
1443  * handle           - file or stream handle
1444  *
1445  * Outputs:
1446  *
1447  *
1448  * Side Effects:
1449  *
1450  *----------------------------------------------------------------------------
1451 */
EAS_CloseFile(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream)1452 EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
1453 {
1454     S_FILE_PARSER_INTERFACE *pParserModule;
1455     EAS_RESULT result;
1456 
1457     /* call the close function */
1458     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
1459     if (pParserModule == NULL)
1460         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
1461 
1462     result = (*pParserModule->pfClose)(pEASData, pStream->handle);
1463 
1464     /* clear the handle and parser interface pointer */
1465     pStream->handle = NULL;
1466     pStream->pParserModule = NULL;
1467     return result;
1468 }
1469 
1470 /*----------------------------------------------------------------------------
1471  * EAS_OpenMIDIStream()
1472  *----------------------------------------------------------------------------
1473  * Purpose:
1474  * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer
1475  *
1476  * Inputs:
1477  * pEASData         - pointer to overall EAS data structure
1478  * pHandle          - pointer to variable to hold file or stream handle
1479  *
1480  * Outputs:
1481  *
1482  *
1483  * Side Effects:
1484  *
1485  *----------------------------------------------------------------------------
1486 */
EAS_OpenMIDIStream(EAS_DATA_HANDLE pEASData,EAS_HANDLE * ppStream,EAS_HANDLE streamHandle)1487 EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle)
1488 {
1489     EAS_RESULT result;
1490     S_INTERACTIVE_MIDI *pMIDIStream;
1491     EAS_INT streamNum;
1492 
1493     /* initialize some pointers */
1494     *ppStream = NULL;
1495 
1496     /* allocate a stream */
1497     if ((streamNum = EAS_AllocateStream(pEASData)) < 0)
1498         return EAS_ERROR_MAX_STREAMS_OPEN;
1499 
1500     /* check Configuration Module for S_EAS_DATA allocation */
1501     if (pEASData->staticMemoryModel)
1502         pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA);
1503     else
1504         pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI));
1505 
1506     /* allocate dynamic memory */
1507     if (!pMIDIStream)
1508     {
1509         { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ }
1510         return EAS_ERROR_MALLOC_FAILED;
1511     }
1512 
1513     /* zero the memory to insure complete initialization */
1514     EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI));
1515     EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream);
1516 
1517     /* instantiate a new synthesizer */
1518     if (streamHandle == NULL)
1519     {
1520         result = VMInitMIDI(pEASData, &pMIDIStream->pSynth);
1521     }
1522 
1523     /* use an existing synthesizer */
1524     else
1525     {
1526         EAS_I32 value;
1527         result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value);
1528         pMIDIStream->pSynth = (S_SYNTH*) value;
1529         VMIncRefCount(pMIDIStream->pSynth);
1530     }
1531     if (result != EAS_SUCCESS)
1532     {
1533         EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]);
1534         return result;
1535     }
1536 
1537     /* initialize the MIDI stream data */
1538     EAS_InitMIDIStream(&pMIDIStream->stream);
1539 
1540     *ppStream = (EAS_HANDLE) &pEASData->streams[streamNum];
1541     return EAS_SUCCESS;
1542 }
1543 
1544 /*----------------------------------------------------------------------------
1545  * EAS_WriteMIDIStream()
1546  *----------------------------------------------------------------------------
1547  * Purpose:
1548  * Send data to the MIDI stream device
1549  *
1550  * Inputs:
1551  * pEASData         - pointer to overall EAS data structure
1552  * handle           - stream handle
1553  * pBuffer          - pointer to buffer
1554  * count            - number of bytes to write
1555  *
1556  * Outputs:
1557  *
1558  *
1559  * Side Effects:
1560  *
1561  *----------------------------------------------------------------------------
1562 */
EAS_WriteMIDIStream(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_U8 * pBuffer,EAS_I32 count)1563 EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count)
1564 {
1565     S_INTERACTIVE_MIDI *pMIDIStream;
1566     EAS_RESULT result;
1567 
1568     pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle;
1569 
1570     if (count <= 0)
1571         return EAS_ERROR_PARAMETER_RANGE;
1572 
1573     /* send the entire buffer */
1574     while (count--)
1575     {
1576         if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS)
1577             return result;
1578     }
1579     return EAS_SUCCESS;
1580 }
1581 
1582 /*----------------------------------------------------------------------------
1583  * EAS_CloseMIDIStream()
1584  *----------------------------------------------------------------------------
1585  * Purpose:
1586  * Closes a raw MIDI stream
1587  *
1588  * Inputs:
1589  * pEASData         - pointer to overall EAS data structure
1590  * handle           - stream handle
1591  *
1592  * Outputs:
1593  *
1594  *
1595  * Side Effects:
1596  *
1597  *----------------------------------------------------------------------------
1598 */
EAS_CloseMIDIStream(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream)1599 EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
1600 {
1601     S_INTERACTIVE_MIDI *pMIDIStream;
1602 
1603     pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle;
1604 
1605     /* close synth */
1606     if (pMIDIStream->pSynth != NULL)
1607     {
1608         VMMIDIShutdown(pEASData, pMIDIStream->pSynth);
1609         pMIDIStream->pSynth = NULL;
1610     }
1611 
1612     /* release allocated memory */
1613     if (!pEASData->staticMemoryModel)
1614         EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream);
1615 
1616     pStream->handle = NULL;
1617     return EAS_SUCCESS;
1618 }
1619 
1620 /*----------------------------------------------------------------------------
1621  * EAS_State()
1622  *----------------------------------------------------------------------------
1623  * Purpose:
1624  * Returns the state of an audio file or stream.
1625  *
1626  * Inputs:
1627  * pEASData         - pointer to overall EAS data structure
1628  * handle           - file or stream handle
1629  *
1630  * Outputs:
1631  *
1632  *
1633  * Side Effects:
1634  *
1635  *----------------------------------------------------------------------------
1636 */
EAS_State(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_STATE * pState)1637 EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState)
1638 {
1639     S_FILE_PARSER_INTERFACE *pParserModule;
1640     EAS_RESULT result;
1641 
1642     /* call the parser to return state */
1643     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
1644     if (pParserModule == NULL)
1645         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
1646 
1647     if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS)
1648         return result;
1649 
1650     /* if repeat count is set for this parser, mask the stopped state from the application */
1651     if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED))
1652         *pState = EAS_STATE_PLAY;
1653 
1654     /* if we're not ready or playing, we don't need to hide state from host */
1655     if (*pState > EAS_STATE_PLAY)
1656         return EAS_SUCCESS;
1657 
1658     /* if stream is about to be paused, report it as paused */
1659     if (pStream->streamFlags & STREAM_FLAGS_PAUSE)
1660     {
1661         if (pStream->streamFlags & STREAM_FLAGS_LOCATE)
1662             *pState = EAS_STATE_PAUSED;
1663         else
1664             *pState = EAS_STATE_PAUSING;
1665     }
1666 
1667     /* if stream is about to resume, report it as playing */
1668     if (pStream->streamFlags & STREAM_FLAGS_RESUME)
1669         *pState = EAS_STATE_PLAY;
1670 
1671     return EAS_SUCCESS;
1672 }
1673 
1674 /*----------------------------------------------------------------------------
1675  * EAS_SetPolyphony()
1676  *----------------------------------------------------------------------------
1677  * Purpose:
1678  * Set the polyphony of the stream. A value of 0 allows the stream
1679  * to use all voices (set by EAS_SetSynthPolyphony).
1680  *
1681  * Inputs:
1682  * pEASData         - pointer to overall EAS data structure
1683  * streamHandle     - handle returned by EAS_OpenFile
1684  * polyphonyCount   - the desired polyphony count
1685  *
1686  * Outputs:
1687  *
1688  * Side Effects:
1689  *
1690  *----------------------------------------------------------------------------
1691 */
EAS_SetPolyphony(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 polyphonyCount)1692 EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount)
1693 {
1694     if (!EAS_StreamReady(pEASData, pStream))
1695         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1696     return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount);
1697 }
1698 
1699 /*----------------------------------------------------------------------------
1700  * EAS_GetPolyphony()
1701  *----------------------------------------------------------------------------
1702  * Purpose:
1703  * Returns the current polyphony setting of the stream
1704  *
1705  * Inputs:
1706  * pEASData         - pointer to overall EAS data structure
1707  * streamHandle     - handle returned by EAS_OpenFile
1708  * pPolyphonyCount  - pointer to variable to receive polyphony count
1709  *
1710  * Outputs:
1711  *
1712  * Side Effects:
1713  *
1714  *----------------------------------------------------------------------------
1715 */
EAS_GetPolyphony(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 * pPolyphonyCount)1716 EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount)
1717 {
1718     if (!EAS_StreamReady(pEASData, pStream))
1719         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1720     return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount);
1721 }
1722 
1723 /*----------------------------------------------------------------------------
1724  * EAS_SetSynthPolyphony()
1725  *----------------------------------------------------------------------------
1726  * Purpose:
1727  * Set the polyphony of the synth . Value must be >= 1 and <= the
1728  * maximum number of voices. This function will pin the polyphony
1729  * at those limits
1730  *
1731  * Inputs:
1732  * pEASData         - pointer to overall EAS data structure
1733  * synthNum         - synthesizer number (0 = onboard, 1 = DSP)
1734  * polyphonyCount   - the desired polyphony count
1735  *
1736  * Outputs:
1737  *
1738  * Side Effects:
1739  *
1740  *----------------------------------------------------------------------------
1741 */
EAS_SetSynthPolyphony(EAS_DATA_HANDLE pEASData,EAS_I32 synthNum,EAS_I32 polyphonyCount)1742 EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount)
1743 {
1744     return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount);
1745 }
1746 
1747 /*----------------------------------------------------------------------------
1748  * EAS_GetSynthPolyphony()
1749  *----------------------------------------------------------------------------
1750  * Purpose:
1751  * Returns the current polyphony setting of the synth
1752  *
1753  * Inputs:
1754  * pEASData         - pointer to overall EAS data structure
1755  * synthNum         - synthesizer number (0 = onboard, 1 = DSP)
1756  * pPolyphonyCount  - pointer to variable to receive polyphony count
1757  *
1758  * Outputs:
1759  *
1760  * Side Effects:
1761  *
1762  *----------------------------------------------------------------------------
1763 */
EAS_GetSynthPolyphony(EAS_DATA_HANDLE pEASData,EAS_I32 synthNum,EAS_I32 * pPolyphonyCount)1764 EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount)
1765 {
1766     return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount);
1767 }
1768 
1769 /*----------------------------------------------------------------------------
1770  * EAS_SetPriority()
1771  *----------------------------------------------------------------------------
1772  * Purpose:
1773  * Set the priority of the stream. Determines which stream's voices
1774  * are stolen when there are insufficient voices for all notes.
1775  * Value must be in the range of 1-15, lower values are higher
1776  * priority.
1777  *
1778  * Inputs:
1779  * pEASData         - pointer to overall EAS data structure
1780  * streamHandle     - handle returned by EAS_OpenFile
1781  * polyphonyCount   - the desired polyphony count
1782  *
1783  * Outputs:
1784  *
1785  * Side Effects:
1786  *
1787  *----------------------------------------------------------------------------
1788 */
EAS_SetPriority(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 priority)1789 EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority)
1790 {
1791     if (!EAS_StreamReady(pEASData, pStream))
1792         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1793     return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority);
1794 }
1795 
1796 /*----------------------------------------------------------------------------
1797  * EAS_GetPriority()
1798  *----------------------------------------------------------------------------
1799  * Purpose:
1800  * Returns the current priority setting of the stream
1801  *
1802  * Inputs:
1803  * pEASData         - pointer to overall EAS data structure
1804  * streamHandle     - handle returned by EAS_OpenFile
1805  * pPriority        - pointer to variable to receive priority
1806  *
1807  * Outputs:
1808  *
1809  * Side Effects:
1810  *
1811  *----------------------------------------------------------------------------
1812 */
EAS_GetPriority(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 * pPriority)1813 EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority)
1814 {
1815     if (!EAS_StreamReady(pEASData, pStream))
1816         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1817     return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority);
1818 }
1819 
1820 /*----------------------------------------------------------------------------
1821  * EAS_SetVolume()
1822  *----------------------------------------------------------------------------
1823  * Purpose:
1824  * Set the master gain for the mix engine in 1dB increments
1825  *
1826  * Inputs:
1827  * pEASData         - pointer to overall EAS data structure
1828  * volume           - the desired master gain (100 is max)
1829  * handle           - file or stream handle
1830  *
1831  * Outputs:
1832  *
1833  *
1834  * Side Effects:
1835  * overrides any previously set master volume from sysex
1836  *
1837  *----------------------------------------------------------------------------
1838 */
EAS_SetVolume(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 volume)1839 EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume)
1840 {
1841     EAS_I16 gain;
1842 
1843     /* check range */
1844     if ((volume < 0) || (volume > EAS_MAX_VOLUME))
1845         return EAS_ERROR_PARAMETER_RANGE;
1846 
1847     /* stream volume */
1848     if (pStream != NULL)
1849     {
1850         EAS_I32 gainOffset;
1851         EAS_RESULT result;
1852 
1853         if (!EAS_StreamReady(pEASData, pStream))
1854             return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1855 
1856         /* get gain offset */
1857         pStream->volume = (EAS_U8) volume;
1858         result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset);
1859         if (result == EAS_SUCCESS)
1860             volume += gainOffset;
1861 
1862         /* set stream volume */
1863         gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM);
1864 
1865         /* convert to linear scalar */
1866         return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain);
1867     }
1868 
1869     /* master volume */
1870     pEASData->masterVolume = (EAS_U8) volume;
1871 #if (NUM_OUTPUT_CHANNELS == 1)
1872     /* leave 3dB headroom for mono output */
1873     volume -= 3;
1874 #endif
1875 
1876     gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM);
1877     pEASData->masterGain = gain;
1878     return EAS_SUCCESS;
1879 }
1880 
1881 /*----------------------------------------------------------------------------
1882  * EAS_GetVolume()
1883  *----------------------------------------------------------------------------
1884  * Purpose:
1885  * Returns the master volume for the synthesizer. The default volume setting is
1886  * 50. The volume range is 0 to 100;
1887  *
1888  * Inputs:
1889  * pEASData         - pointer to overall EAS data structure
1890  * volume           - the desired master volume
1891  * handle           - file or stream handle
1892  *
1893  * Outputs:
1894  *
1895  *
1896  * Side Effects:
1897  * overrides any previously set master volume from sysex
1898  *
1899  *----------------------------------------------------------------------------
1900 */
EAS_GetVolume(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream)1901 EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
1902 {
1903     if (pStream == NULL)
1904         return pEASData->masterVolume;
1905 
1906     if (!EAS_StreamReady(pEASData, pStream))
1907         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1908     return pStream->volume;
1909 }
1910 
1911 /*----------------------------------------------------------------------------
1912  * EAS_SetMaxLoad()
1913  *----------------------------------------------------------------------------
1914  * Purpose:
1915  * Sets the maximum workload the parsers will do in a single call to
1916  * EAS_Render. The units are currently arbitrary, but should correlate
1917  * well to the actual CPU cycles consumed. The primary effect is to
1918  * reduce the occasional peaks in CPU cycles consumed when parsing
1919  * dense parts of a MIDI score.
1920  *
1921  * Inputs:
1922  *  pEASData        - handle to data for this instance
1923  *  maxLoad         - the desired maximum workload
1924  *
1925  * Outputs:
1926  *
1927  * Side Effects:
1928  *
1929  *----------------------------------------------------------------------------
1930 */
EAS_SetMaxLoad(EAS_DATA_HANDLE pEASData,EAS_I32 maxLoad)1931 EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad)
1932 {
1933     VMSetWorkload(pEASData->pVoiceMgr, maxLoad);
1934     return EAS_SUCCESS;
1935 }
1936 
1937 /*----------------------------------------------------------------------------
1938  * EAS_SetMaxPCMStreams()
1939  *----------------------------------------------------------------------------
1940  * Sets the maximum number of PCM streams allowed in parsers that
1941  * use PCM streaming.
1942  *
1943  * Inputs:
1944  * pEASData         - pointer to overall EAS data structure
1945  * streamHandle     - handle returned by EAS_OpenFile
1946  * maxNumStreams    - maximum number of PCM streams
1947  *----------------------------------------------------------------------------
1948 */
EAS_SetMaxPCMStreams(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 maxNumStreams)1949 EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams)
1950 {
1951     if (!EAS_StreamReady(pEASData, pStream))
1952         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1953     return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams);
1954 }
1955 
1956 /*----------------------------------------------------------------------------
1957  * EAS_Locate()
1958  *----------------------------------------------------------------------------
1959  * Purpose:
1960  * Locate into the file associated with the handle.
1961  *
1962  * Inputs:
1963  * pEASData - pointer to overall EAS data structure
1964  * handle           - file handle
1965  * milliseconds     - playback offset from start of file in milliseconds
1966  *
1967  * Outputs:
1968  *
1969  *
1970  * Side Effects:
1971  * the actual offset will be quantized to the closest update period, typically
1972  * a resolution of 5.9ms. Notes that are started prior to this time will not
1973  * sound. Any notes currently playing will be shut off.
1974  *
1975  *----------------------------------------------------------------------------
1976 */
EAS_Locate(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 milliseconds,EAS_BOOL offset)1977 EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset)
1978 {
1979     S_FILE_PARSER_INTERFACE *pParserModule;
1980     EAS_RESULT result;
1981     EAS_U32 requestedTime;
1982     EAS_STATE state;
1983 
1984     /* get pointer to parser function table */
1985     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
1986     if (pParserModule == NULL)
1987         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
1988 
1989     if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS)
1990         return result;
1991     if (state >= EAS_STATE_OPEN)
1992         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
1993 
1994     /* handle offset and limit to start of file */
1995     /*lint -e{704} use shift for performance*/
1996     if (offset)
1997         milliseconds += (EAS_I32) pStream->time >> 8;
1998     if (milliseconds < 0)
1999         milliseconds = 0;
2000 
2001     /* check to see if the request is different from the current time */
2002     requestedTime = (EAS_U32) milliseconds;
2003     if (requestedTime == (pStream->time >> 8))
2004         return EAS_SUCCESS;
2005 
2006     /* set the locate flag */
2007     pStream->streamFlags |= STREAM_FLAGS_LOCATE;
2008 
2009     /* use the parser locate function, if available */
2010     if (pParserModule->pfLocate != NULL)
2011     {
2012         EAS_BOOL parserLocate = EAS_FALSE;
2013         result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate);
2014         if (!parserLocate)
2015         {
2016             if (result == EAS_SUCCESS)
2017                 pStream->time = requestedTime << 8;
2018             return result;
2019         }
2020     }
2021 
2022     /* if we were paused and not going to resume, set pause request flag */
2023     if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0))
2024         pStream->streamFlags |= STREAM_FLAGS_PAUSE;
2025 
2026     /* reset the synth and parser */
2027     if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS)
2028         return result;
2029     pStream->time = 0;
2030 
2031     /* locating forward, clear parsed flag and parse data until we get to the requested location */
2032     if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS)
2033         return result;
2034 
2035     return EAS_SUCCESS;
2036 }
2037 
2038 /*----------------------------------------------------------------------------
2039  * EAS_GetLocation()
2040  *----------------------------------------------------------------------------
2041  * Purpose:
2042  * Returns the current playback offset
2043  *
2044  * Inputs:
2045  * pEASData         - pointer to overall EAS data structure
2046  * handle           - file handle
2047  *
2048  * Outputs:
2049  * The offset in milliseconds from the start of the current sequence, quantized
2050  * to the nearest update period. Actual resolution is typically 5.9 ms.
2051  *
2052  * Side Effects:
2053  *
2054  *----------------------------------------------------------------------------
2055 */
2056 /*lint -esym(715, pEASData) reserved for future use */
EAS_GetLocation(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 * pTime)2057 EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime)
2058 {
2059     if (!EAS_StreamReady(pEASData, pStream))
2060         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2061 
2062     *pTime = pStream->time >> 8;
2063     return EAS_SUCCESS;
2064 }
2065 
2066 /*----------------------------------------------------------------------------
2067  * EAS_GetRenderTime()
2068  *----------------------------------------------------------------------------
2069  * Purpose:
2070  * Returns the current playback offset
2071  *
2072  * Inputs:
2073  * pEASData         - pointer to overall EAS data structure
2074  *
2075  * Outputs:
2076  * Gets the render time clock in msecs.
2077  *
2078  * Side Effects:
2079  *
2080  *----------------------------------------------------------------------------
2081 */
EAS_GetRenderTime(EAS_DATA_HANDLE pEASData,EAS_I32 * pTime)2082 EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime)
2083 {
2084     *pTime = pEASData->renderTime >> 8;
2085     return EAS_SUCCESS;
2086 }
2087 
2088 /*----------------------------------------------------------------------------
2089  * EAS_Pause()
2090  *----------------------------------------------------------------------------
2091  * Purpose:
2092  * Pauses the playback of the data associated with this handle. The audio
2093  * is gracefully ramped down to prevent clicks and pops. It may take several
2094  * buffers of audio before the audio is muted.
2095  *
2096  * Inputs:
2097  * psEASData        - pointer to overall EAS data structure
2098  * handle           - file or stream handle
2099  *
2100  * Outputs:
2101  *
2102  *
2103  * Side Effects:
2104  *
2105  *
2106  *----------------------------------------------------------------------------
2107 */
EAS_Pause(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream)2108 EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
2109 {
2110     S_FILE_PARSER_INTERFACE *pParserModule;
2111     EAS_STATE state;
2112     EAS_RESULT result;
2113 
2114     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
2115     if (pParserModule == NULL)
2116         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
2117 
2118     /* check for valid state */
2119     result = pParserModule->pfState(pEASData, pStream->handle, &state);
2120     if (result == EAS_SUCCESS)
2121     {
2122         if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0))
2123             return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2124 
2125         /* make sure parser implements pause */
2126         if (pParserModule->pfPause == NULL)
2127             result = EAS_ERROR_NOT_IMPLEMENTED;
2128 
2129         /* clear resume flag */
2130         pStream->streamFlags &= ~STREAM_FLAGS_RESUME;
2131 
2132         /* set pause flag */
2133         pStream->streamFlags |= STREAM_FLAGS_PAUSE;
2134 
2135 #if 0
2136         /* pause the stream */
2137         if (pParserModule->pfPause)
2138             result = pParserModule->pfPause(pEASData, pStream->handle);
2139         else
2140             result = EAS_ERROR_NOT_IMPLEMENTED;
2141 #endif
2142     }
2143 
2144     return result;
2145 }
2146 
2147 /*----------------------------------------------------------------------------
2148  * EAS_Resume()
2149  *----------------------------------------------------------------------------
2150  * Purpose:
2151  * Resumes the playback of the data associated with this handle. The audio
2152  * is gracefully ramped up to prevent clicks and pops.
2153  *
2154  * Inputs:
2155  * psEASData        - pointer to overall EAS data structure
2156  * handle           - file or stream handle
2157  *
2158  * Outputs:
2159  *
2160  *
2161  * Side Effects:
2162  *
2163  *
2164  *----------------------------------------------------------------------------
2165 */
EAS_Resume(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream)2166 EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream)
2167 {
2168     S_FILE_PARSER_INTERFACE *pParserModule;
2169     EAS_STATE state;
2170     EAS_RESULT result;
2171 
2172     pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule;
2173     if (pParserModule == NULL)
2174         return EAS_ERROR_FEATURE_NOT_AVAILABLE;
2175 
2176     /* check for valid state */
2177     result = pParserModule->pfState(pEASData, pStream->handle, &state);
2178     if (result == EAS_SUCCESS)
2179     {
2180         if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0))
2181             return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2182 
2183         /* make sure parser implements this function */
2184         if (pParserModule->pfResume == NULL)
2185             result = EAS_ERROR_NOT_IMPLEMENTED;
2186 
2187         /* clear pause flag */
2188         pStream->streamFlags &= ~STREAM_FLAGS_PAUSE;
2189 
2190         /* set resume flag */
2191         pStream->streamFlags |= STREAM_FLAGS_RESUME;
2192 
2193 #if 0
2194         /* resume the stream */
2195         if (pParserModule->pfResume)
2196             result = pParserModule->pfResume(pEASData, pStream->handle);
2197         else
2198             result = EAS_ERROR_NOT_IMPLEMENTED;
2199 #endif
2200     }
2201 
2202     return result;
2203 }
2204 
2205 /*----------------------------------------------------------------------------
2206  * EAS_GetParameter()
2207  *----------------------------------------------------------------------------
2208  * Purpose:
2209  * Set the parameter of a module. See E_MODULES for a list of modules
2210  * and the header files of the modules for a list of parameters.
2211  *
2212  * Inputs:
2213  * psEASData        - pointer to overall EAS data structure
2214  * handle           - file or stream handle
2215  * module           - enumerated module number
2216  * param            - enumerated parameter number
2217  * pValue           - pointer to variable to receive parameter value
2218  *
2219  * Outputs:
2220  *
2221  *
2222  * Side Effects:
2223  *
2224  *
2225  *----------------------------------------------------------------------------
2226 */
EAS_GetParameter(EAS_DATA_HANDLE pEASData,EAS_I32 module,EAS_I32 param,EAS_I32 * pValue)2227 EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue)
2228 {
2229 
2230     if (module >= NUM_EFFECTS_MODULES)
2231         return EAS_ERROR_INVALID_MODULE;
2232 
2233     if (pEASData->effectsModules[module].effectData == NULL)
2234         return EAS_ERROR_INVALID_MODULE;
2235 
2236     return (*pEASData->effectsModules[module].effect->pFGetParam)
2237         (pEASData->effectsModules[module].effectData, param, pValue);
2238 }
2239 
2240 /*----------------------------------------------------------------------------
2241  * EAS_SetParameter()
2242  *----------------------------------------------------------------------------
2243  * Purpose:
2244  * Set the parameter of a module. See E_MODULES for a list of modules
2245  * and the header files of the modules for a list of parameters.
2246  *
2247  * Inputs:
2248  * psEASData        - pointer to overall EAS data structure
2249  * handle           - file or stream handle
2250  * module           - enumerated module number
2251  * param            - enumerated parameter number
2252  * value            - new parameter value
2253  *
2254  * Outputs:
2255  *
2256  *
2257  * Side Effects:
2258  *
2259  *
2260  *----------------------------------------------------------------------------
2261 */
EAS_SetParameter(EAS_DATA_HANDLE pEASData,EAS_I32 module,EAS_I32 param,EAS_I32 value)2262 EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value)
2263 {
2264 
2265     if (module >= NUM_EFFECTS_MODULES)
2266         return EAS_ERROR_INVALID_MODULE;
2267 
2268     if (pEASData->effectsModules[module].effectData == NULL)
2269         return EAS_ERROR_INVALID_MODULE;
2270 
2271     return (*pEASData->effectsModules[module].effect->pFSetParam)
2272         (pEASData->effectsModules[module].effectData, param, value);
2273 }
2274 
2275 #ifdef _METRICS_ENABLED
2276 /*----------------------------------------------------------------------------
2277  * EAS_MetricsReport()
2278  *----------------------------------------------------------------------------
2279  * Purpose:
2280  * Displays the current metrics through the metrics interface.
2281  *
2282  * Inputs:
2283  * p                - instance data handle
2284  *
2285  * Outputs:
2286  *
2287  *
2288  * Side Effects:
2289  *
2290  *----------------------------------------------------------------------------
2291 */
EAS_MetricsReport(EAS_DATA_HANDLE pEASData)2292 EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData)
2293 {
2294     if (!pEASData->pMetricsModule)
2295         return EAS_ERROR_INVALID_MODULE;
2296 
2297     return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData);
2298 }
2299 
2300 /*----------------------------------------------------------------------------
2301  * EAS_MetricsReset()
2302  *----------------------------------------------------------------------------
2303  * Purpose:
2304  * Resets the metrics.
2305  *
2306  * Inputs:
2307  * p                - instance data handle
2308  *
2309  * Outputs:
2310  *
2311  *
2312  * Side Effects:
2313  *
2314  *----------------------------------------------------------------------------
2315 */
EAS_MetricsReset(EAS_DATA_HANDLE pEASData)2316 EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData)
2317 {
2318 
2319     if (!pEASData->pMetricsModule)
2320         return EAS_ERROR_INVALID_MODULE;
2321 
2322     return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData);
2323 }
2324 #endif
2325 
2326 /*----------------------------------------------------------------------------
2327  * EAS_SetSoundLibrary()
2328  *----------------------------------------------------------------------------
2329  * Purpose:
2330  * Sets the location of the sound library.
2331  *
2332  * Inputs:
2333  * pEASData             - instance data handle
2334  * pSoundLib            - pointer to sound library
2335  *
2336  * Outputs:
2337  *
2338  *
2339  * Side Effects:
2340  *
2341  *----------------------------------------------------------------------------
2342 */
EAS_SetSoundLibrary(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_SNDLIB_HANDLE pSndLib)2343 EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib)
2344 {
2345     if (pStream)
2346     {
2347         if (!EAS_StreamReady(pEASData, pStream))
2348             return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2349         return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib);
2350     }
2351 
2352     return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib);
2353 }
2354 
2355 /*----------------------------------------------------------------------------
2356  * EAS_SetHeaderSearchFlag()
2357  *----------------------------------------------------------------------------
2358  * By default, when EAS_OpenFile is called, the parsers check the
2359  * first few bytes of the file looking for a specific header. Some
2360  * mobile devices may add a header to the start of a file, which
2361  * will prevent the parser from recognizing the file. If the
2362  * searchFlag is set to EAS_TRUE, the parser will search the entire
2363  * file looking for the header. This may enable EAS to recognize
2364  * some files that it would ordinarily reject. The negative is that
2365  * it make take slightly longer to process the EAS_OpenFile request.
2366  *
2367  * Inputs:
2368  * pEASData             - instance data handle
2369  * searchFlag           - search flag (EAS_TRUE or EAS_FALSE)
2370  *----------------------------------------------------------------------------
2371 */
EAS_SetHeaderSearchFlag(EAS_DATA_HANDLE pEASData,EAS_BOOL searchFlag)2372 EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag)
2373 {
2374     pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag;
2375     return EAS_SUCCESS;
2376 }
2377 
2378 /*----------------------------------------------------------------------------
2379  * EAS_SetPlayMode()
2380  *----------------------------------------------------------------------------
2381  * Some file formats support special play modes, such as iMode partial
2382  * play mode. This call can be used to change the play mode. The
2383  * default play mode (usually straight playback) is always zero.
2384  *
2385  * Inputs:
2386  * pEASData             - instance data handle
2387  * handle               - file or stream handle
2388  * playMode             - play mode (see file parser for specifics)
2389  *----------------------------------------------------------------------------
2390 */
EAS_SetPlayMode(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_I32 playMode)2391 EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode)
2392 {
2393     return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode);
2394 }
2395 
2396 #ifdef DLS_SYNTHESIZER
2397 /*----------------------------------------------------------------------------
2398  * EAS_LoadDLSCollection()
2399  *----------------------------------------------------------------------------
2400  * Purpose:
2401  * Sets the location of the sound library.
2402  *
2403  * Inputs:
2404  * pEASData             - instance data handle
2405  * pSoundLib            - pointer to sound library
2406  *
2407  * Outputs:
2408  *
2409  *
2410  * Side Effects:
2411  *
2412  *----------------------------------------------------------------------------
2413 */
EAS_LoadDLSCollection(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_FILE_LOCATOR locator)2414 EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator)
2415 {
2416     EAS_FILE_HANDLE fileHandle;
2417     EAS_RESULT result;
2418     EAS_DLSLIB_HANDLE pDLS;
2419 
2420     if (pStream != NULL)
2421     {
2422         if (!EAS_StreamReady(pEASData, pStream))
2423             return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2424     }
2425 
2426     /* open the file */
2427     if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS)
2428         return result;
2429 
2430     /* parse the file */
2431     result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS);
2432     EAS_HWCloseFile(pEASData->hwInstData, fileHandle);
2433 
2434     if (result == EAS_SUCCESS)
2435     {
2436 
2437         /* if a stream pStream is specified, point it to the DLS collection */
2438         if (pStream)
2439             result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS);
2440 
2441         /* global DLS load */
2442         else
2443             result = VMSetGlobalDLSLib(pEASData, pDLS);
2444     }
2445 
2446     return result;
2447 }
2448 #endif
2449 
2450 #ifdef EXTERNAL_AUDIO
2451 /*----------------------------------------------------------------------------
2452  * EAS_RegExtAudioCallback()
2453  *----------------------------------------------------------------------------
2454  * Purpose:
2455  * Registers callback functions for audio events.
2456  *
2457  * Inputs:
2458  * pEASData         - pointer to overall EAS data structure
2459  * handle           - file or stream handle
2460  * cbProgChgFunc    - pointer to host callback function for program change
2461  * cbEventFunc      - pointer to host callback functio for note events
2462  *
2463  * Outputs:
2464  *
2465  *
2466  * Side Effects:
2467  *
2468  *----------------------------------------------------------------------------
2469 */
EAS_RegExtAudioCallback(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_VOID_PTR pInstData,EAS_EXT_PRG_CHG_FUNC cbProgChgFunc,EAS_EXT_EVENT_FUNC cbEventFunc)2470 EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData,
2471     EAS_HANDLE pStream,
2472     EAS_VOID_PTR pInstData,
2473     EAS_EXT_PRG_CHG_FUNC cbProgChgFunc,
2474     EAS_EXT_EVENT_FUNC cbEventFunc)
2475 {
2476     S_SYNTH *pSynth;
2477 
2478     if (!EAS_StreamReady(pEASData, pStream))
2479         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2480 
2481     if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
2482         return EAS_ERROR_INVALID_PARAMETER;
2483 
2484     if (pSynth == NULL)
2485         return EAS_ERROR_INVALID_PARAMETER;
2486 
2487     VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc);
2488     return EAS_SUCCESS;
2489 }
2490 
2491 /*----------------------------------------------------------------------------
2492  * EAS_GetMIDIControllers()
2493  *----------------------------------------------------------------------------
2494  * Purpose:
2495  * Returns the current state of MIDI controllers on the requested channel.
2496  *
2497  * Inputs:
2498  * pEASData         - pointer to overall EAS data structure
2499  * handle           - file or stream handle
2500  * pControl         - pointer to structure to receive data
2501  *
2502  * Outputs:
2503  *
2504  *
2505  * Side Effects:
2506  *
2507  *----------------------------------------------------------------------------
2508 */
EAS_GetMIDIControllers(EAS_DATA_HANDLE pEASData,EAS_HANDLE pStream,EAS_U8 channel,S_MIDI_CONTROLLERS * pControl)2509 EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl)
2510 {
2511     S_SYNTH *pSynth;
2512 
2513     if (!EAS_StreamReady(pEASData, pStream))
2514         return EAS_ERROR_NOT_VALID_IN_THIS_STATE;
2515 
2516     if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS)
2517         return EAS_ERROR_INVALID_PARAMETER;
2518 
2519     if (pSynth == NULL)
2520         return EAS_ERROR_INVALID_PARAMETER;
2521 
2522     VMGetMIDIControllers(pSynth, channel, pControl);
2523     return EAS_SUCCESS;
2524 }
2525 #endif
2526 
2527 #ifdef _SPLIT_ARCHITECTURE
2528 /*----------------------------------------------------------------------------
2529  * EAS_SetFrameBuffer()
2530  *----------------------------------------------------------------------------
2531  * Purpose:
2532  * Sets the frame buffer pointer passed to the IPC communications functions
2533  *
2534  * Inputs:
2535  * pEASData             - instance data handle
2536  * locator              - file locator
2537  *
2538  * Outputs:
2539  *
2540  *
2541  * Side Effects:
2542  * May overlay instruments in the GM sound set
2543  *
2544  *----------------------------------------------------------------------------
2545 */
EAS_SetFrameBuffer(EAS_DATA_HANDLE pEASData,EAS_FRAME_BUFFER_HANDLE pFrameBuffer)2546 EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer)
2547 {
2548     if (pEASData->pVoiceMgr)
2549         pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer;
2550     return EAS_SUCCESS;
2551 }
2552 #endif
2553 
2554 /*----------------------------------------------------------------------------
2555  * EAS_SearchFile
2556  *----------------------------------------------------------------------------
2557  * Search file for specific sequence starting at current file
2558  * position. Returns offset to start of sequence.
2559  *
2560  * Inputs:
2561  * pEASData         - pointer to EAS persistent data object
2562  * fileHandle       - file handle
2563  * searchString     - pointer to search sequence
2564  * len              - length of search sequence
2565  * pOffset          - pointer to variable to store offset to sequence
2566  *
2567  * Returns EAS_EOF if end-of-file is reached
2568  *----------------------------------------------------------------------------
2569 */
EAS_SearchFile(S_EAS_DATA * pEASData,EAS_FILE_HANDLE fileHandle,const EAS_U8 * searchString,EAS_I32 len,EAS_I32 * pOffset)2570 EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset)
2571 {
2572     EAS_RESULT result;
2573     EAS_INT index;
2574     EAS_U8 c;
2575 
2576     *pOffset = -1;
2577     index = 0;
2578     for (;;)
2579     {
2580         result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c);
2581         if (result != EAS_SUCCESS)
2582             return result;
2583         if (c == searchString[index])
2584         {
2585             index++;
2586             if (index == 4)
2587             {
2588                 result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset);
2589                 if (result != EAS_SUCCESS)
2590                     return result;
2591                 *pOffset -= len;
2592                 break;
2593             }
2594         }
2595         else
2596             index = 0;
2597     }
2598     return EAS_SUCCESS;
2599 }
2600 
2601 
2602