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