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