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