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