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