| /*---------------------------------------------------------------------------- |
| * |
| * 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; |
| pStream->streamFlags = 0; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * 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; |
| |
| if (count <= 0) |
| return EAS_ERROR_PARAMETER_RANGE; |
| |
| /* 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; |
| } |
| |
| |