Home | History | Annotate | Download | only in lib_src
      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