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