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