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