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