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