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