/*---------------------------------------------------------------------------- | |
* | |
* File: | |
* eas_public.c | |
* | |
* Contents and purpose: | |
* Contains EAS library public interface | |
* | |
* Copyright Sonic Network Inc. 2004 | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* | |
*---------------------------------------------------------------------------- | |
* Revision Control: | |
* $Revision: 842 $ | |
* $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ | |
*---------------------------------------------------------------------------- | |
*/ | |
#include "eas_synthcfg.h" | |
#include "eas.h" | |
#include "eas_config.h" | |
#include "eas_host.h" | |
#include "eas_report.h" | |
#include "eas_data.h" | |
#include "eas_parser.h" | |
#include "eas_pcm.h" | |
#include "eas_midi.h" | |
#include "eas_mixer.h" | |
#include "eas_build.h" | |
#include "eas_vm_protos.h" | |
#include "eas_math.h" | |
#ifdef JET_INTERFACE | |
#include "jet_data.h" | |
#endif | |
#ifdef DLS_SYNTHESIZER | |
#include "eas_mdls.h" | |
#endif | |
/* number of events to parse before calling EAS_HWYield function */ | |
#define YIELD_EVENT_COUNT 10 | |
/*---------------------------------------------------------------------------- | |
* easLibConfig | |
* | |
* This structure is available through the EAS public interface to allow | |
* the user to check the configuration of the library. | |
*---------------------------------------------------------------------------- | |
*/ | |
static const S_EAS_LIB_CONFIG easLibConfig = | |
{ | |
LIB_VERSION, | |
#ifdef _CHECKED_BUILD | |
EAS_TRUE, | |
#else | |
EAS_FALSE, | |
#endif | |
MAX_SYNTH_VOICES, | |
NUM_OUTPUT_CHANNELS, | |
_OUTPUT_SAMPLE_RATE, | |
BUFFER_SIZE_IN_MONO_SAMPLES, | |
#ifdef _FILTER_ENABLED | |
EAS_TRUE, | |
#else | |
EAS_FALSE, | |
#endif | |
_BUILD_TIME_, | |
_BUILD_VERSION_ | |
}; | |
/* local prototypes */ | |
static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode); | |
/*---------------------------------------------------------------------------- | |
* EAS_SetStreamParameter | |
*---------------------------------------------------------------------------- | |
* Sets the specified parameter in the stream. Allows access to | |
* customizable settings within the individual file parsers. | |
*---------------------------------------------------------------------------- | |
* pEASData - pointer to EAS persistent data object | |
* pStream - stream handle | |
* param - enumerated parameter (see eas_parser.h) | |
* value - new value | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule->pfSetData) | |
return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value); | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetStreamParameter | |
*---------------------------------------------------------------------------- | |
* Sets the specified parameter in the stream. Allows access to | |
* customizable settings within the individual file parsers. | |
*---------------------------------------------------------------------------- | |
* pEASData - pointer to EAS persistent data object | |
* pStream - stream handle | |
* param - enumerated parameter (see eas_parser.h) | |
* pValue - pointer to variable to receive current setting | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule->pfGetData) | |
return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue); | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_StreamReady() | |
*---------------------------------------------------------------------------- | |
* This routine sets common parameters like transpose, volume, etc. | |
* First, it attempts to use the parser EAS_SetStreamParameter interface. If that | |
* fails, it attempts to get the synth handle from the parser and | |
* set the parameter directly on the synth. This eliminates duplicate | |
* code in the parser. | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_STATE state; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS) | |
return EAS_FALSE; | |
return (state < EAS_STATE_OPEN); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_IntSetStrmParam() | |
*---------------------------------------------------------------------------- | |
* This routine sets common parameters like transpose, volume, etc. | |
* First, it attempts to use the parser EAS_SetStreamParameter interface. If that | |
* fails, it attempts to get the synth handle from the parser and | |
* set the parameter directly on the synth. This eliminates duplicate | |
* code in the parser. | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value) | |
{ | |
S_SYNTH *pSynth; | |
/* try to set the parameter using stream interface */ | |
if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS) | |
return EAS_SUCCESS; | |
/* get a pointer to the synth object and set it directly */ | |
/*lint -e{740} we are cheating by passing a pointer through this interface */ | |
if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) | |
return EAS_ERROR_INVALID_PARAMETER; | |
if (pSynth == NULL) | |
return EAS_ERROR_INVALID_PARAMETER; | |
switch (param) | |
{ | |
#ifdef DLS_SYNTHESIZER | |
case PARSER_DATA_DLS_COLLECTION: | |
{ | |
EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value); | |
if (result == EAS_SUCCESS) | |
{ | |
DLSAddRef((S_DLS*) value); | |
VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); | |
} | |
return result; | |
} | |
#endif | |
case PARSER_DATA_EAS_LIBRARY: | |
return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value); | |
case PARSER_DATA_POLYPHONY: | |
return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value); | |
case PARSER_DATA_PRIORITY: | |
return VMSetPriority(pEASData->pVoiceMgr, pSynth, value); | |
case PARSER_DATA_TRANSPOSITION: | |
VMSetTranposition(pSynth, value); | |
break; | |
case PARSER_DATA_VOLUME: | |
VMSetVolume(pSynth, (EAS_U16) value); | |
break; | |
default: | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } | |
return EAS_ERROR_INVALID_PARAMETER; | |
} | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_IntGetStrmParam() | |
*---------------------------------------------------------------------------- | |
* This routine gets common parameters like transpose, volume, etc. | |
* First, it attempts to use the parser EAS_GetStreamParameter interface. If that | |
* fails, it attempts to get the synth handle from the parser and | |
* get the parameter directly on the synth. | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue) | |
{ | |
S_SYNTH *pSynth; | |
/* try to set the parameter */ | |
if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS) | |
return EAS_SUCCESS; | |
/* get a pointer to the synth object and retrieve data directly */ | |
/*lint -e{740} we are cheating by passing a pointer through this interface */ | |
if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) | |
return EAS_ERROR_INVALID_PARAMETER; | |
if (pSynth == NULL) | |
return EAS_ERROR_INVALID_PARAMETER; | |
switch (param) | |
{ | |
case PARSER_DATA_POLYPHONY: | |
return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue); | |
case PARSER_DATA_PRIORITY: | |
return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue); | |
case PARSER_DATA_TRANSPOSITION: | |
VMGetTranposition(pSynth, pValue); | |
break; | |
case PARSER_DATA_NOTE_COUNT: | |
*pValue = VMGetNoteCount(pSynth); | |
break; | |
default: | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } | |
return EAS_ERROR_INVALID_PARAMETER; | |
} | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_AllocateStream() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Allocates a stream handle | |
* | |
* Inputs: | |
* | |
* Outputs: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData) | |
{ | |
EAS_INT streamNum; | |
/* check for static allocation, only one stream allowed */ | |
if (pEASData->staticMemoryModel) | |
{ | |
if (pEASData->streams[0].handle != NULL) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ } | |
return -1; | |
} | |
return 0; | |
} | |
/* dynamic model */ | |
for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) | |
if (pEASData->streams[streamNum].handle == NULL) | |
break; | |
if (streamNum == MAX_NUMBER_STREAMS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ } | |
return -1; | |
} | |
return streamNum; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_InitStream() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Initialize a stream | |
* | |
* Inputs: | |
* | |
* Outputs: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle) | |
{ | |
pStream->pParserModule = pParserModule; | |
pStream->handle = streamHandle; | |
pStream->time = 0; | |
pStream->frameLength = AUDIO_FRAME_LENGTH; | |
pStream->repeatCount = 0; | |
pStream->volume = DEFAULT_STREAM_VOLUME; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Config() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns a pointer to a structure containing the configuration options | |
* in this library build. | |
* | |
* Inputs: | |
* | |
* Outputs: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void) | |
{ | |
return &easLibConfig; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Init() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Initialize the synthesizer library | |
* | |
* Inputs: | |
* ppEASData - pointer to data handle variable for this instance | |
* | |
* Outputs: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData) | |
{ | |
EAS_HW_DATA_HANDLE pHWInstData; | |
EAS_RESULT result; | |
S_EAS_DATA *pEASData; | |
EAS_INT module; | |
EAS_BOOL staticMemoryModel; | |
/* get the memory model */ | |
staticMemoryModel = EAS_CMStaticMemoryModel(); | |
/* initialize the host wrapper interface */ | |
*ppEASData = NULL; | |
if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS) | |
return result; | |
/* check Configuration Module for S_EAS_DATA allocation */ | |
if (staticMemoryModel) | |
pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA); | |
else | |
pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA)); | |
if (!pEASData) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ } | |
return EAS_ERROR_MALLOC_FAILED; | |
} | |
/* initialize some data */ | |
EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA)); | |
pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel; | |
pEASData->hwInstData = pHWInstData; | |
pEASData->renderTime = 0; | |
/* set header search flag */ | |
#ifdef FILE_HEADER_SEARCH | |
pEASData->searchHeaderFlag = EAS_TRUE; | |
#endif | |
/* initalize parameters */ | |
EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME); | |
#ifdef _METRICS_ENABLED | |
/* initalize the metrics module */ | |
pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS); | |
if (pEASData->pMetricsModule != NULL) | |
{ | |
if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ } | |
return result; | |
} | |
} | |
#endif | |
/* initailize the voice manager & synthesizer */ | |
if ((result = VMInitialize(pEASData)) != EAS_SUCCESS) | |
return result; | |
/* initialize mix engine */ | |
if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ } | |
return result; | |
} | |
/* initialize effects modules */ | |
for (module = 0; module < NUM_EFFECTS_MODULES; module++) | |
{ | |
pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module); | |
if (pEASData->effectsModules[module].effect != NULL) | |
{ | |
if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ } | |
return result; | |
} | |
} | |
} | |
/* initialize PCM engine */ | |
if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ } | |
return result; | |
} | |
/* return instance data pointer to host */ | |
*ppEASData = pEASData; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Shutdown() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Shuts down the library. Deallocates any memory associated with the | |
* synthesizer (dynamic memory model only) | |
* | |
* Inputs: | |
* pEASData - handle to data for this instance | |
* | |
* Outputs: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData) | |
{ | |
EAS_HW_DATA_HANDLE hwInstData; | |
EAS_RESULT result, reportResult; | |
EAS_INT i; | |
/* establish pointers */ | |
hwInstData = pEASData->hwInstData; | |
/* check for NULL handle */ | |
if (!pEASData) | |
return EAS_ERROR_HANDLE_INTEGRITY; | |
/* if there are streams open, close them */ | |
reportResult = EAS_SUCCESS; | |
for (i = 0; i < MAX_NUMBER_STREAMS; i++) | |
{ | |
if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle) | |
{ | |
if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ } | |
reportResult = result; | |
} | |
} | |
} | |
/* shutdown PCM engine */ | |
if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ } | |
if (reportResult == EAS_SUCCESS) | |
reportResult = result; | |
} | |
/* shutdown mix engine */ | |
if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ } | |
if (reportResult == EAS_SUCCESS) | |
reportResult = result; | |
} | |
/* shutdown effects modules */ | |
for (i = 0; i < NUM_EFFECTS_MODULES; i++) | |
{ | |
if (pEASData->effectsModules[i].effect) | |
{ | |
if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ } | |
if (reportResult == EAS_SUCCESS) | |
reportResult = result; | |
} | |
} | |
} | |
/* shutdown the voice manager & synthesizer */ | |
VMShutdown(pEASData); | |
#ifdef _METRICS_ENABLED | |
/* shutdown the metrics module */ | |
if (pEASData->pMetricsModule != NULL) | |
{ | |
if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ } | |
if (reportResult == EAS_SUCCESS) | |
reportResult = result; | |
} | |
} | |
#endif | |
/* release allocated memory */ | |
if (!pEASData->staticMemoryModel) | |
EAS_HWFree(hwInstData, pEASData); | |
/* shutdown host wrappers */ | |
if (hwInstData) | |
{ | |
if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ } | |
if (reportResult == EAS_SUCCESS) | |
reportResult = result; | |
} | |
} | |
return reportResult; | |
} | |
#ifdef JET_INTERFACE | |
/*---------------------------------------------------------------------------- | |
* EAS_OpenJETStream() | |
*---------------------------------------------------------------------------- | |
* Private interface for JET to open an SMF stream with an offset | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream) | |
{ | |
EAS_RESULT result; | |
EAS_VOID_PTR streamHandle; | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_INT streamNum; | |
/* allocate a stream */ | |
if ((streamNum = EAS_AllocateStream(pEASData)) < 0) | |
return EAS_ERROR_MAX_STREAMS_OPEN; | |
/* check Configuration Module for SMF parser */ | |
*ppStream = NULL; | |
streamHandle = NULL; | |
pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0); | |
if (pParserModule == NULL) | |
return EAS_ERROR_UNRECOGNIZED_FORMAT; | |
/* see if SMF parser recognizes the file */ | |
if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } | |
return result; | |
} | |
/* parser recognized the file, return the handle */ | |
if (streamHandle) | |
{ | |
EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); | |
*ppStream = &pEASData->streams[streamNum]; | |
return EAS_SUCCESS; | |
} | |
return EAS_ERROR_UNRECOGNIZED_FORMAT; | |
} | |
#endif | |
/*---------------------------------------------------------------------------- | |
* EAS_OpenFile() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Opens a file for audio playback. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* pHandle - pointer to file handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) | |
{ | |
EAS_RESULT result; | |
EAS_FILE_HANDLE fileHandle; | |
EAS_VOID_PTR streamHandle; | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_INT streamNum; | |
EAS_INT moduleNum; | |
/* open the file */ | |
if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) | |
return result; | |
/* allocate a stream */ | |
if ((streamNum = EAS_AllocateStream(pEASData)) < 0) | |
return EAS_ERROR_MAX_STREAMS_OPEN; | |
/* check Configuration Module for file parsers */ | |
pParserModule = NULL; | |
*ppStream = NULL; | |
streamHandle = NULL; | |
for (moduleNum = 0; ; moduleNum++) | |
{ | |
pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum); | |
if (pParserModule == NULL) | |
break; | |
/* see if this parser recognizes it */ | |
if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } | |
return result; | |
} | |
/* parser recognized the file, return the handle */ | |
if (streamHandle) | |
{ | |
/* save the parser pointer and file handle */ | |
EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); | |
*ppStream = &pEASData->streams[streamNum]; | |
return EAS_SUCCESS; | |
} | |
/* rewind the file for the next parser */ | |
if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS) | |
return result; | |
} | |
/* no parser was able to recognize the file, close it and return an error */ | |
EAS_HWCloseFile(pEASData->hwInstData, fileHandle); | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } | |
return EAS_ERROR_UNRECOGNIZED_FORMAT; | |
} | |
#ifdef MMAPI_SUPPORT | |
/*---------------------------------------------------------------------------- | |
* EAS_MMAPIToneControl() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Opens a ToneControl file for audio playback. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* pHandle - pointer to file handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) | |
{ | |
EAS_RESULT result; | |
EAS_FILE_HANDLE fileHandle; | |
EAS_VOID_PTR streamHandle; | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_INT streamNum; | |
/* check if the tone control parser is available */ | |
*ppStream = NULL; | |
streamHandle = NULL; | |
pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL); | |
if (pParserModule == NULL) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ } | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
} | |
/* open the file */ | |
if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) | |
return result; | |
/* allocate a stream */ | |
if ((streamNum = EAS_AllocateStream(pEASData)) < 0) | |
return EAS_ERROR_MAX_STREAMS_OPEN; | |
/* see if ToneControl parser recognizes it */ | |
if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } | |
return result; | |
} | |
/* parser accepted the file, return the handle */ | |
if (streamHandle) | |
{ | |
/* save the parser pointer and file handle */ | |
EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); | |
*ppStream = &pEASData->streams[streamNum]; | |
return EAS_SUCCESS; | |
} | |
/* parser did not recognize the file, close it and return an error */ | |
EAS_HWCloseFile(pEASData->hwInstData, fileHandle); | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } | |
return EAS_ERROR_UNRECOGNIZED_FORMAT; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetWaveFmtChunk | |
*---------------------------------------------------------------------------- | |
* Helper function to retrieve WAVE file fmt chunk for MMAPI | |
*---------------------------------------------------------------------------- | |
* pEASData - pointer to EAS persistent data object | |
* pStream - stream handle | |
* pFmtChunk - pointer to variable to receive current setting | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk) | |
{ | |
EAS_RESULT result; | |
EAS_I32 value; | |
if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS) | |
return result; | |
*ppFmtChunk = (EAS_VOID_PTR) value; | |
return EAS_SUCCESS; | |
} | |
#endif | |
/*---------------------------------------------------------------------------- | |
* EAS_GetFileType | |
*---------------------------------------------------------------------------- | |
* Returns the file type (see eas_types.h for enumerations) | |
*---------------------------------------------------------------------------- | |
* pEASData - pointer to EAS persistent data object | |
* pStream - stream handle | |
* pFileType - pointer to variable to receive file type | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType) | |
{ | |
if (!EAS_StreamReady (pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Prepare() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Prepares the synthesizer to play the file or stream. Parses the first | |
* frame of data from the file and arms the synthesizer. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_STATE state; | |
EAS_RESULT result; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
/* check for valid state */ | |
result = pParserModule->pfState(pEASData, pStream->handle, &state); | |
if (result == EAS_SUCCESS) | |
{ | |
/* prepare the stream */ | |
if (state == EAS_STATE_OPEN) | |
{ | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
result = (*pParserModule->pfPrepare)(pEASData, pStream->handle); | |
/* set volume */ | |
if (result == EAS_SUCCESS) | |
result = EAS_SetVolume(pEASData, pStream, pStream->volume); | |
} | |
else | |
result = EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
} | |
return result; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Render() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Parse the Midi data and render PCM audio data. | |
* | |
* Inputs: | |
* pEASData - buffer for internal EAS data | |
* pOut - output buffer pointer | |
* nNumRequested - requested num samples to generate | |
* pnNumGenerated - actual number of samples generated | |
* | |
* Outputs: | |
* EAS_SUCCESS if PCM data was successfully rendered | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_RESULT result; | |
EAS_I32 voicesRendered; | |
EAS_STATE parserState; | |
EAS_INT streamNum; | |
/* assume no samples generated and reset workload */ | |
*pNumGenerated = 0; | |
VMInitWorkload(pEASData->pVoiceMgr); | |
/* no support for other buffer sizes yet */ | |
if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n", | |
(EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ } | |
return EAS_BUFFER_SIZE_MISMATCH; | |
} | |
#ifdef _METRICS_ENABLED | |
/* start performance counter */ | |
if (pEASData->pMetricsData) | |
(*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); | |
#endif | |
/* prep the frame buffer, do mix engine prep only if TRUE */ | |
#ifdef _SPLIT_ARCHITECTURE | |
if (VMStartFrame(pEASData)) | |
EAS_MixEnginePrep(pEASData, numRequested); | |
#else | |
/* prep the mix engine */ | |
EAS_MixEnginePrep(pEASData, numRequested); | |
#endif | |
/* save the output buffer pointer */ | |
pEASData->pOutputAudioBuffer = pOut; | |
#ifdef _METRICS_ENABLED | |
/* start performance counter */ | |
if (pEASData->pMetricsData) | |
(*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); | |
#endif | |
/* if we haven't finished parsing from last time, do it now */ | |
/* need to parse another frame of events before we render again */ | |
for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) | |
{ | |
/* clear the locate flag */ | |
pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE; | |
if (pEASData->streams[streamNum].pParserModule) | |
{ | |
/* establish pointer to parser module */ | |
pParserModule = pEASData->streams[streamNum].pParserModule; | |
/* handle pause */ | |
if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE) | |
{ | |
if (pParserModule->pfPause) | |
result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle); | |
pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE; | |
} | |
/* get current state */ | |
if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) | |
return result; | |
/* handle resume */ | |
if (parserState == EAS_STATE_PAUSED) | |
{ | |
if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME) | |
{ | |
if (pParserModule->pfResume) | |
result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle); | |
pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME; | |
} | |
} | |
/* if necessary, parse stream */ | |
if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0) | |
if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS) | |
return result; | |
/* check for an early abort */ | |
if ((pEASData->streams[streamNum].streamFlags) == 0) | |
{ | |
#ifdef _METRICS_ENABLED | |
/* stop performance counter */ | |
if (pEASData->pMetricsData) | |
(*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); | |
#endif | |
return EAS_SUCCESS; | |
} | |
/* check for repeat */ | |
if (pEASData->streams[streamNum].repeatCount) | |
{ | |
/* check for stopped state */ | |
if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) | |
return result; | |
if (parserState == EAS_STATE_STOPPED) | |
{ | |
/* decrement repeat count, unless it is negative */ | |
if (pEASData->streams[streamNum].repeatCount > 0) | |
pEASData->streams[streamNum].repeatCount--; | |
/* reset the parser */ | |
if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS) | |
return result; | |
pEASData->streams[streamNum].time = 0; | |
} | |
} | |
} | |
} | |
#ifdef _METRICS_ENABLED | |
/* stop performance counter */ | |
if (pEASData->pMetricsData) | |
(void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); | |
#endif | |
#ifdef _METRICS_ENABLED | |
/* start the render timer */ | |
if (pEASData->pMetricsData) | |
(*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); | |
#endif | |
/* render audio */ | |
if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ } | |
return result; | |
} | |
#ifdef _METRICS_ENABLED | |
/* stop the render timer */ | |
if (pEASData->pMetricsData) { | |
(*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1); | |
(void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); | |
(*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered); | |
(void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered); | |
} | |
#endif | |
//2 Do we really need frameParsed? | |
/* need to parse another frame of events before we render again */ | |
for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) | |
if (pEASData->streams[streamNum].pParserModule != NULL) | |
pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED; | |
#ifdef _METRICS_ENABLED | |
/* start performance counter */ | |
if (pEASData->pMetricsData) | |
(*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); | |
#endif | |
/* render PCM audio */ | |
if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ } | |
return result; | |
} | |
#ifdef _METRICS_ENABLED | |
/* stop the stream timer */ | |
if (pEASData->pMetricsData) | |
(void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); | |
#endif | |
#ifdef _METRICS_ENABLED | |
/* start the post timer */ | |
if (pEASData->pMetricsData) | |
(*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); | |
#endif | |
/* for split architecture, send DSP vectors. Do post only if return is TRUE */ | |
#ifdef _SPLIT_ARCHITECTURE | |
if (VMEndFrame(pEASData)) | |
{ | |
/* now do post-processing */ | |
EAS_MixEnginePost(pEASData, numRequested); | |
*pNumGenerated = numRequested; | |
} | |
#else | |
/* now do post-processing */ | |
EAS_MixEnginePost(pEASData, numRequested); | |
*pNumGenerated = numRequested; | |
#endif | |
#ifdef _METRICS_ENABLED | |
/* stop the post timer */ | |
if (pEASData->pMetricsData) | |
(void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); | |
#endif | |
/* advance render time */ | |
pEASData->renderTime += AUDIO_FRAME_LENGTH; | |
#if 0 | |
/* dump workload for debug */ | |
if (pEASData->pVoiceMgr->workload) | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ } | |
#endif | |
#ifdef _METRICS_ENABLED | |
/* stop performance counter */ | |
if (pEASData->pMetricsData) | |
{ | |
PERF_TIMER temp; | |
temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); | |
/* if max render time, record the number of voices and time */ | |
if ((*pEASData->pMetricsModule->pfRecordMaxValue) | |
(pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp)) | |
{ | |
(*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered); | |
(*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8)); | |
} | |
} | |
#endif | |
#ifdef JET_INTERFACE | |
/* let JET to do its thing */ | |
if (pEASData->jetHandle != NULL) | |
{ | |
result = JET_Process(pEASData); | |
if (result != EAS_SUCCESS) | |
return result; | |
} | |
#endif | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetRepeat() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the selected stream to repeat. | |
* | |
* Inputs: | |
* pEASData - handle to data for this instance | |
* handle - handle to stream | |
* repeatCount - repeat count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
* Notes: | |
* 0 = no repeat | |
* 1 = repeat once, i.e. play through twice | |
* -1 = repeat forever | |
*---------------------------------------------------------------------------- | |
*/ | |
/*lint -esym(715, pEASData) reserved for future use */ | |
EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount) | |
{ | |
pStream->repeatCount = repeatCount; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetRepeat() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Gets the current repeat count for the selected stream. | |
* | |
* Inputs: | |
* pEASData - handle to data for this instance | |
* handle - handle to stream | |
* pRrepeatCount - pointer to variable to hold repeat count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
* Notes: | |
* 0 = no repeat | |
* 1 = repeat once, i.e. play through twice | |
* -1 = repeat forever | |
*---------------------------------------------------------------------------- | |
*/ | |
/*lint -esym(715, pEASData) reserved for future use */ | |
EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount) | |
{ | |
*pRepeatCount = pStream->repeatCount; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetPlaybackRate() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Sets the playback rate. | |
* | |
* Inputs: | |
* pEASData - handle to data for this instance | |
* handle - handle to stream | |
* rate - rate (28-bit fractional amount) | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
/*lint -esym(715, pEASData) reserved for future use */ | |
EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate) | |
{ | |
/* check range */ | |
if ((rate < (1 << 27)) || (rate > (1 << 29))) | |
return EAS_ERROR_INVALID_PARAMETER; | |
/* calculate new frame length | |
* | |
* NOTE: The maximum frame length we can accomodate based on a | |
* maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a | |
* longer frame length or a higher maximum rate, the fixed point | |
* divide below will need to be adjusted | |
*/ | |
pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20; | |
/* notify stream of new playback rate */ | |
EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate); | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetTransposition) | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Sets the key tranposition for the synthesizer. Transposes all | |
* melodic instruments by the specified amount. Range is limited | |
* to +/-12 semitones. | |
* | |
* Inputs: | |
* pEASData - handle to data for this instance | |
* handle - handle to stream | |
* transposition - +/-12 semitones | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition) | |
{ | |
/* check range */ | |
if ((transposition < -12) || (transposition > 12)) | |
return EAS_ERROR_INVALID_PARAMETER; | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_ParseEvents() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Parse events in the current streams until the desired time is reached. | |
* | |
* Inputs: | |
* pEASData - buffer for internal EAS data | |
* endTime - stop parsing if this time is reached | |
* parseMode - play, locate, or metadata | |
* | |
* Outputs: | |
* EAS_SUCCESS if PCM data was successfully rendered | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_RESULT result; | |
EAS_I32 parserState; | |
EAS_BOOL done; | |
EAS_INT yieldCount = YIELD_EVENT_COUNT; | |
EAS_U32 time = 0; | |
/* does this parser have a time function? */ | |
pParserModule = pStream->pParserModule; | |
if (pParserModule->pfTime == NULL) | |
{ | |
/* check state */ | |
if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) | |
return result; | |
/* if play state, advance time */ | |
if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING)) | |
pStream->time += pStream->frameLength; | |
done = EAS_TRUE; | |
} | |
/* assume we're not done, in case we abort out */ | |
else | |
{ | |
pStream->streamFlags &= ~STREAM_FLAGS_PARSED; | |
done = EAS_FALSE; | |
} | |
while (!done) | |
{ | |
/* check for stopped state */ | |
if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) | |
return result; | |
if (parserState > EAS_STATE_PLAY) | |
{ | |
/* save current time if we're not in play mode */ | |
if (parseMode != eParserModePlay) | |
pStream->time = time << 8; | |
done = EAS_TRUE; | |
break; | |
} | |
/* get the next event time */ | |
if (pParserModule->pfTime) | |
{ | |
if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS) | |
return result; | |
/* if next event is within this frame, parse it */ | |
if (time < (endTime >> 8)) | |
{ | |
/* parse the next event */ | |
if (pParserModule->pfEvent) | |
if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS) | |
return result; | |
} | |
/* no more events in this frame, advance time */ | |
else | |
{ | |
pStream->time = endTime; | |
done = EAS_TRUE; | |
} | |
} | |
/* check for max workload exceeded */ | |
if (VMCheckWorkload(pEASData->pVoiceMgr)) | |
{ | |
/* stop even though we may not have parsed | |
* all the events in this frame. The parser will try to | |
* catch up on the next frame. | |
*/ | |
break; | |
} | |
/* give host a chance for an early abort */ | |
if (--yieldCount == 0) | |
{ | |
if (EAS_HWYield(pEASData->hwInstData)) | |
break; | |
yieldCount = YIELD_EVENT_COUNT; | |
} | |
} | |
/* if no early abort, parsing is complete for this frame */ | |
if (done) | |
pStream->streamFlags |= STREAM_FLAGS_PARSED; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_ParseMetaData() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* playLength - pointer to variable to store the play length (in msecs) | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* - resets the parser to the start of the file | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_RESULT result; | |
EAS_STATE state; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
/* check parser state */ | |
if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) | |
return result; | |
if (state >= EAS_STATE_OPEN) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
/* if parser has metadata function, use that */ | |
if (pParserModule->pfGetMetaData != NULL) | |
return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength); | |
/* reset the parser to the beginning */ | |
if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) | |
return result; | |
/* parse the file to end */ | |
pStream->time = 0; | |
VMInitWorkload(pEASData->pVoiceMgr); | |
if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS) | |
return result; | |
/* get the parser time */ | |
if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS) | |
return result; | |
/* reset the parser to the beginning */ | |
pStream->time = 0; | |
return (*pParserModule->pfReset)(pEASData, pStream->handle); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_RegisterMetaDataCallback() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Registers a metadata callback function for parsed metadata. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* cbFunc - pointer to host callback function | |
* metaDataBuffer - pointer to metadata buffer | |
* metaDataBufSize - maximum size of the metadata buffer | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( | |
EAS_DATA_HANDLE pEASData, | |
EAS_HANDLE pStream, | |
EAS_METADATA_CBFUNC cbFunc, | |
char *metaDataBuffer, | |
EAS_I32 metaDataBufSize, | |
EAS_VOID_PTR pUserData) | |
{ | |
S_METADATA_CB metadata; | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
/* register callback function */ | |
metadata.callback = cbFunc; | |
metadata.buffer = metaDataBuffer; | |
metadata.bufferSize = metaDataBufSize; | |
metadata.pUserData = pUserData; | |
return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetNoteCount () | |
*---------------------------------------------------------------------------- | |
* Returns the total number of notes played in this stream | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_CloseFile() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Closes an audio file or stream. Playback should have either paused or | |
* completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_RESULT result; | |
/* call the close function */ | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
result = (*pParserModule->pfClose)(pEASData, pStream->handle); | |
/* clear the handle and parser interface pointer */ | |
pStream->handle = NULL; | |
pStream->pParserModule = NULL; | |
return result; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_OpenMIDIStream() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* pHandle - pointer to variable to hold file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle) | |
{ | |
EAS_RESULT result; | |
S_INTERACTIVE_MIDI *pMIDIStream; | |
EAS_INT streamNum; | |
/* initialize some pointers */ | |
*ppStream = NULL; | |
/* allocate a stream */ | |
if ((streamNum = EAS_AllocateStream(pEASData)) < 0) | |
return EAS_ERROR_MAX_STREAMS_OPEN; | |
/* check Configuration Module for S_EAS_DATA allocation */ | |
if (pEASData->staticMemoryModel) | |
pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA); | |
else | |
pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI)); | |
/* allocate dynamic memory */ | |
if (!pMIDIStream) | |
{ | |
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ } | |
return EAS_ERROR_MALLOC_FAILED; | |
} | |
/* zero the memory to insure complete initialization */ | |
EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI)); | |
EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream); | |
/* instantiate a new synthesizer */ | |
if (streamHandle == NULL) | |
{ | |
result = VMInitMIDI(pEASData, &pMIDIStream->pSynth); | |
} | |
/* use an existing synthesizer */ | |
else | |
{ | |
EAS_I32 value; | |
result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value); | |
pMIDIStream->pSynth = (S_SYNTH*) value; | |
VMIncRefCount(pMIDIStream->pSynth); | |
} | |
if (result != EAS_SUCCESS) | |
{ | |
EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]); | |
return result; | |
} | |
/* initialize the MIDI stream data */ | |
EAS_InitMIDIStream(&pMIDIStream->stream); | |
*ppStream = (EAS_HANDLE) &pEASData->streams[streamNum]; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_WriteMIDIStream() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Send data to the MIDI stream device | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - stream handle | |
* pBuffer - pointer to buffer | |
* count - number of bytes to write | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count) | |
{ | |
S_INTERACTIVE_MIDI *pMIDIStream; | |
EAS_RESULT result; | |
pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; | |
/* send the entire buffer */ | |
while (count--) | |
{ | |
if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS) | |
return result; | |
} | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_CloseMIDIStream() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Closes a raw MIDI stream | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) | |
{ | |
S_INTERACTIVE_MIDI *pMIDIStream; | |
pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; | |
/* close synth */ | |
if (pMIDIStream->pSynth != NULL) | |
{ | |
VMMIDIShutdown(pEASData, pMIDIStream->pSynth); | |
pMIDIStream->pSynth = NULL; | |
} | |
/* release allocated memory */ | |
if (!pEASData->staticMemoryModel) | |
EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream); | |
pStream->handle = NULL; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_State() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the state of an audio file or stream. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_RESULT result; | |
/* call the parser to return state */ | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS) | |
return result; | |
/* if repeat count is set for this parser, mask the stopped state from the application */ | |
if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED)) | |
*pState = EAS_STATE_PLAY; | |
/* if we're not ready or playing, we don't need to hide state from host */ | |
if (*pState > EAS_STATE_PLAY) | |
return EAS_SUCCESS; | |
/* if stream is about to be paused, report it as paused */ | |
if (pStream->streamFlags & STREAM_FLAGS_PAUSE) | |
{ | |
if (pStream->streamFlags & STREAM_FLAGS_LOCATE) | |
*pState = EAS_STATE_PAUSED; | |
else | |
*pState = EAS_STATE_PAUSING; | |
} | |
/* if stream is about to resume, report it as playing */ | |
if (pStream->streamFlags & STREAM_FLAGS_RESUME) | |
*pState = EAS_STATE_PLAY; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetPolyphony() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the polyphony of the stream. A value of 0 allows the stream | |
* to use all voices (set by EAS_SetSynthPolyphony). | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* streamHandle - handle returned by EAS_OpenFile | |
* polyphonyCount - the desired polyphony count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetPolyphony() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the current polyphony setting of the stream | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* streamHandle - handle returned by EAS_OpenFile | |
* pPolyphonyCount - pointer to variable to receive polyphony count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetSynthPolyphony() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the polyphony of the synth . Value must be >= 1 and <= the | |
* maximum number of voices. This function will pin the polyphony | |
* at those limits | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* synthNum - synthesizer number (0 = onboard, 1 = DSP) | |
* polyphonyCount - the desired polyphony count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount) | |
{ | |
return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetSynthPolyphony() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the current polyphony setting of the synth | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* synthNum - synthesizer number (0 = onboard, 1 = DSP) | |
* pPolyphonyCount - pointer to variable to receive polyphony count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount) | |
{ | |
return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetPriority() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the priority of the stream. Determines which stream's voices | |
* are stolen when there are insufficient voices for all notes. | |
* Value must be in the range of 1-15, lower values are higher | |
* priority. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* streamHandle - handle returned by EAS_OpenFile | |
* polyphonyCount - the desired polyphony count | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetPriority() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the current priority setting of the stream | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* streamHandle - handle returned by EAS_OpenFile | |
* pPriority - pointer to variable to receive priority | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetVolume() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the master gain for the mix engine in 1dB increments | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* volume - the desired master gain (100 is max) | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* overrides any previously set master volume from sysex | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume) | |
{ | |
EAS_I16 gain; | |
/* check range */ | |
if ((volume < 0) || (volume > EAS_MAX_VOLUME)) | |
return EAS_ERROR_PARAMETER_RANGE; | |
/* stream volume */ | |
if (pStream != NULL) | |
{ | |
EAS_I32 gainOffset; | |
EAS_RESULT result; | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
/* get gain offset */ | |
pStream->volume = (EAS_U8) volume; | |
result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset); | |
if (result == EAS_SUCCESS) | |
volume += gainOffset; | |
/* set stream volume */ | |
gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); | |
/* convert to linear scalar */ | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain); | |
} | |
/* master volume */ | |
pEASData->masterVolume = (EAS_U8) volume; | |
#if (NUM_OUTPUT_CHANNELS == 1) | |
/* leave 3dB headroom for mono output */ | |
volume -= 3; | |
#endif | |
gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); | |
pEASData->masterGain = gain; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetVolume() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the master volume for the synthesizer. The default volume setting is | |
* 50. The volume range is 0 to 100; | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* volume - the desired master volume | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* overrides any previously set master volume from sysex | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) | |
{ | |
if (pStream == NULL) | |
return pEASData->masterVolume; | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return pStream->volume; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetMaxLoad() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Sets the maximum workload the parsers will do in a single call to | |
* EAS_Render. The units are currently arbitrary, but should correlate | |
* well to the actual CPU cycles consumed. The primary effect is to | |
* reduce the occasional peaks in CPU cycles consumed when parsing | |
* dense parts of a MIDI score. | |
* | |
* Inputs: | |
* pEASData - handle to data for this instance | |
* maxLoad - the desired maximum workload | |
* | |
* Outputs: | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad) | |
{ | |
VMSetWorkload(pEASData->pVoiceMgr, maxLoad); | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetMaxPCMStreams() | |
*---------------------------------------------------------------------------- | |
* Sets the maximum number of PCM streams allowed in parsers that | |
* use PCM streaming. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* streamHandle - handle returned by EAS_OpenFile | |
* maxNumStreams - maximum number of PCM streams | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Locate() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Locate into the file associated with the handle. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file handle | |
* milliseconds - playback offset from start of file in milliseconds | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* the actual offset will be quantized to the closest update period, typically | |
* a resolution of 5.9ms. Notes that are started prior to this time will not | |
* sound. Any notes currently playing will be shut off. | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_RESULT result; | |
EAS_U32 requestedTime; | |
EAS_STATE state; | |
/* get pointer to parser function table */ | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) | |
return result; | |
if (state >= EAS_STATE_OPEN) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
/* handle offset and limit to start of file */ | |
/*lint -e{704} use shift for performance*/ | |
if (offset) | |
milliseconds += (EAS_I32) pStream->time >> 8; | |
if (milliseconds < 0) | |
milliseconds = 0; | |
/* check to see if the request is different from the current time */ | |
requestedTime = (EAS_U32) milliseconds; | |
if (requestedTime == (pStream->time >> 8)) | |
return EAS_SUCCESS; | |
/* set the locate flag */ | |
pStream->streamFlags |= STREAM_FLAGS_LOCATE; | |
/* use the parser locate function, if available */ | |
if (pParserModule->pfLocate != NULL) | |
{ | |
EAS_BOOL parserLocate = EAS_FALSE; | |
result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate); | |
if (!parserLocate) | |
{ | |
if (result == EAS_SUCCESS) | |
pStream->time = requestedTime << 8; | |
return result; | |
} | |
} | |
/* if we were paused and not going to resume, set pause request flag */ | |
if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) | |
pStream->streamFlags |= STREAM_FLAGS_PAUSE; | |
/* reset the synth and parser */ | |
if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) | |
return result; | |
pStream->time = 0; | |
/* locating forward, clear parsed flag and parse data until we get to the requested location */ | |
if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS) | |
return result; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetLocation() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the current playback offset | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file handle | |
* | |
* Outputs: | |
* The offset in milliseconds from the start of the current sequence, quantized | |
* to the nearest update period. Actual resolution is typically 5.9 ms. | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
/*lint -esym(715, pEASData) reserved for future use */ | |
EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
*pTime = pStream->time >> 8; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetRenderTime() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the current playback offset | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* | |
* Outputs: | |
* Gets the render time clock in msecs. | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime) | |
{ | |
*pTime = pEASData->renderTime >> 8; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Pause() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Pauses the playback of the data associated with this handle. The audio | |
* is gracefully ramped down to prevent clicks and pops. It may take several | |
* buffers of audio before the audio is muted. | |
* | |
* Inputs: | |
* psEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_STATE state; | |
EAS_RESULT result; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
/* check for valid state */ | |
result = pParserModule->pfState(pEASData, pStream->handle, &state); | |
if (result == EAS_SUCCESS) | |
{ | |
if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
/* make sure parser implements pause */ | |
if (pParserModule->pfPause == NULL) | |
result = EAS_ERROR_NOT_IMPLEMENTED; | |
/* clear resume flag */ | |
pStream->streamFlags &= ~STREAM_FLAGS_RESUME; | |
/* set pause flag */ | |
pStream->streamFlags |= STREAM_FLAGS_PAUSE; | |
#if 0 | |
/* pause the stream */ | |
if (pParserModule->pfPause) | |
result = pParserModule->pfPause(pEASData, pStream->handle); | |
else | |
result = EAS_ERROR_NOT_IMPLEMENTED; | |
#endif | |
} | |
return result; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_Resume() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Resumes the playback of the data associated with this handle. The audio | |
* is gracefully ramped up to prevent clicks and pops. | |
* | |
* Inputs: | |
* psEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) | |
{ | |
S_FILE_PARSER_INTERFACE *pParserModule; | |
EAS_STATE state; | |
EAS_RESULT result; | |
pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; | |
if (pParserModule == NULL) | |
return EAS_ERROR_FEATURE_NOT_AVAILABLE; | |
/* check for valid state */ | |
result = pParserModule->pfState(pEASData, pStream->handle, &state); | |
if (result == EAS_SUCCESS) | |
{ | |
if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
/* make sure parser implements this function */ | |
if (pParserModule->pfResume == NULL) | |
result = EAS_ERROR_NOT_IMPLEMENTED; | |
/* clear pause flag */ | |
pStream->streamFlags &= ~STREAM_FLAGS_PAUSE; | |
/* set resume flag */ | |
pStream->streamFlags |= STREAM_FLAGS_RESUME; | |
#if 0 | |
/* resume the stream */ | |
if (pParserModule->pfResume) | |
result = pParserModule->pfResume(pEASData, pStream->handle); | |
else | |
result = EAS_ERROR_NOT_IMPLEMENTED; | |
#endif | |
} | |
return result; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetParameter() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the parameter of a module. See E_MODULES for a list of modules | |
* and the header files of the modules for a list of parameters. | |
* | |
* Inputs: | |
* psEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* module - enumerated module number | |
* param - enumerated parameter number | |
* pValue - pointer to variable to receive parameter value | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue) | |
{ | |
if (module >= NUM_EFFECTS_MODULES) | |
return EAS_ERROR_INVALID_MODULE; | |
if (pEASData->effectsModules[module].effectData == NULL) | |
return EAS_ERROR_INVALID_MODULE; | |
return (*pEASData->effectsModules[module].effect->pFGetParam) | |
(pEASData->effectsModules[module].effectData, param, pValue); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetParameter() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Set the parameter of a module. See E_MODULES for a list of modules | |
* and the header files of the modules for a list of parameters. | |
* | |
* Inputs: | |
* psEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* module - enumerated module number | |
* param - enumerated parameter number | |
* value - new parameter value | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value) | |
{ | |
if (module >= NUM_EFFECTS_MODULES) | |
return EAS_ERROR_INVALID_MODULE; | |
if (pEASData->effectsModules[module].effectData == NULL) | |
return EAS_ERROR_INVALID_MODULE; | |
return (*pEASData->effectsModules[module].effect->pFSetParam) | |
(pEASData->effectsModules[module].effectData, param, value); | |
} | |
#ifdef _METRICS_ENABLED | |
/*---------------------------------------------------------------------------- | |
* EAS_MetricsReport() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Displays the current metrics through the metrics interface. | |
* | |
* Inputs: | |
* p - instance data handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData) | |
{ | |
if (!pEASData->pMetricsModule) | |
return EAS_ERROR_INVALID_MODULE; | |
return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_MetricsReset() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Resets the metrics. | |
* | |
* Inputs: | |
* p - instance data handle | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData) | |
{ | |
if (!pEASData->pMetricsModule) | |
return EAS_ERROR_INVALID_MODULE; | |
return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData); | |
} | |
#endif | |
/*---------------------------------------------------------------------------- | |
* EAS_SetSoundLibrary() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Sets the location of the sound library. | |
* | |
* Inputs: | |
* pEASData - instance data handle | |
* pSoundLib - pointer to sound library | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib) | |
{ | |
if (pStream) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib); | |
} | |
return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib); | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetHeaderSearchFlag() | |
*---------------------------------------------------------------------------- | |
* By default, when EAS_OpenFile is called, the parsers check the | |
* first few bytes of the file looking for a specific header. Some | |
* mobile devices may add a header to the start of a file, which | |
* will prevent the parser from recognizing the file. If the | |
* searchFlag is set to EAS_TRUE, the parser will search the entire | |
* file looking for the header. This may enable EAS to recognize | |
* some files that it would ordinarily reject. The negative is that | |
* it make take slightly longer to process the EAS_OpenFile request. | |
* | |
* Inputs: | |
* pEASData - instance data handle | |
* searchFlag - search flag (EAS_TRUE or EAS_FALSE) | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag) | |
{ | |
pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag; | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_SetPlayMode() | |
*---------------------------------------------------------------------------- | |
* Some file formats support special play modes, such as iMode partial | |
* play mode. This call can be used to change the play mode. The | |
* default play mode (usually straight playback) is always zero. | |
* | |
* Inputs: | |
* pEASData - instance data handle | |
* handle - file or stream handle | |
* playMode - play mode (see file parser for specifics) | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode) | |
{ | |
return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode); | |
} | |
#ifdef DLS_SYNTHESIZER | |
/*---------------------------------------------------------------------------- | |
* EAS_LoadDLSCollection() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Sets the location of the sound library. | |
* | |
* Inputs: | |
* pEASData - instance data handle | |
* pSoundLib - pointer to sound library | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator) | |
{ | |
EAS_FILE_HANDLE fileHandle; | |
EAS_RESULT result; | |
EAS_DLSLIB_HANDLE pDLS; | |
if (pStream != NULL) | |
{ | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
} | |
/* open the file */ | |
if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) | |
return result; | |
/* parse the file */ | |
result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS); | |
EAS_HWCloseFile(pEASData->hwInstData, fileHandle); | |
if (result == EAS_SUCCESS) | |
{ | |
/* if a stream pStream is specified, point it to the DLS collection */ | |
if (pStream) | |
result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS); | |
/* global DLS load */ | |
else | |
result = VMSetGlobalDLSLib(pEASData, pDLS); | |
} | |
return result; | |
} | |
#endif | |
#ifdef EXTERNAL_AUDIO | |
/*---------------------------------------------------------------------------- | |
* EAS_RegExtAudioCallback() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Registers callback functions for audio events. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* cbProgChgFunc - pointer to host callback function for program change | |
* cbEventFunc - pointer to host callback functio for note events | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, | |
EAS_HANDLE pStream, | |
EAS_VOID_PTR pInstData, | |
EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, | |
EAS_EXT_EVENT_FUNC cbEventFunc) | |
{ | |
S_SYNTH *pSynth; | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) | |
return EAS_ERROR_INVALID_PARAMETER; | |
if (pSynth == NULL) | |
return EAS_ERROR_INVALID_PARAMETER; | |
VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc); | |
return EAS_SUCCESS; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_GetMIDIControllers() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Returns the current state of MIDI controllers on the requested channel. | |
* | |
* Inputs: | |
* pEASData - pointer to overall EAS data structure | |
* handle - file or stream handle | |
* pControl - pointer to structure to receive data | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) | |
{ | |
S_SYNTH *pSynth; | |
if (!EAS_StreamReady(pEASData, pStream)) | |
return EAS_ERROR_NOT_VALID_IN_THIS_STATE; | |
if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) | |
return EAS_ERROR_INVALID_PARAMETER; | |
if (pSynth == NULL) | |
return EAS_ERROR_INVALID_PARAMETER; | |
VMGetMIDIControllers(pSynth, channel, pControl); | |
return EAS_SUCCESS; | |
} | |
#endif | |
#ifdef _SPLIT_ARCHITECTURE | |
/*---------------------------------------------------------------------------- | |
* EAS_SetFrameBuffer() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Sets the frame buffer pointer passed to the IPC communications functions | |
* | |
* Inputs: | |
* pEASData - instance data handle | |
* locator - file locator | |
* | |
* Outputs: | |
* | |
* | |
* Side Effects: | |
* May overlay instruments in the GM sound set | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) | |
{ | |
if (pEASData->pVoiceMgr) | |
pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer; | |
return EAS_SUCCESS; | |
} | |
#endif | |
/*---------------------------------------------------------------------------- | |
* EAS_SearchFile | |
*---------------------------------------------------------------------------- | |
* Search file for specific sequence starting at current file | |
* position. Returns offset to start of sequence. | |
* | |
* Inputs: | |
* pEASData - pointer to EAS persistent data object | |
* fileHandle - file handle | |
* searchString - pointer to search sequence | |
* len - length of search sequence | |
* pOffset - pointer to variable to store offset to sequence | |
* | |
* Returns EAS_EOF if end-of-file is reached | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset) | |
{ | |
EAS_RESULT result; | |
EAS_INT index; | |
EAS_U8 c; | |
*pOffset = -1; | |
index = 0; | |
for (;;) | |
{ | |
result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c); | |
if (result != EAS_SUCCESS) | |
return result; | |
if (c == searchString[index]) | |
{ | |
index++; | |
if (index == 4) | |
{ | |
result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset); | |
if (result != EAS_SUCCESS) | |
return result; | |
*pOffset -= len; | |
break; | |
} | |
} | |
else | |
index = 0; | |
} | |
return EAS_SUCCESS; | |
} | |