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