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