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