summaryrefslogtreecommitdiffstats
path: root/arm-fm-22k/lib_src/eas_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm-fm-22k/lib_src/eas_pcm.c')
-rw-r--r--arm-fm-22k/lib_src/eas_pcm.c1482
1 files changed, 0 insertions, 1482 deletions
diff --git a/arm-fm-22k/lib_src/eas_pcm.c b/arm-fm-22k/lib_src/eas_pcm.c
deleted file mode 100644
index 64b8f71..0000000
--- a/arm-fm-22k/lib_src/eas_pcm.c
+++ /dev/null
@@ -1,1482 +0,0 @@
-/*----------------------------------------------------------------------------
- *
- * File:
- * eas_pcm.c
- *
- * Contents and purpose:
- * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback.
- *
- * Copyright Sonic Network Inc. 2005
-
- * 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: 849 $
- * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $
- *----------------------------------------------------------------------------
-*/
-
-#include "eas_data.h"
-#include "eas_report.h"
-#include "eas_host.h"
-#include "eas_config.h"
-#include "eas_parser.h"
-#include "eas_pcm.h"
-#include "eas_math.h"
-#include "eas_mixer.h"
-
-#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1)
-
-/*----------------------------------------------------------------------------
- * Decoder interfaces
- *----------------------------------------------------------------------------
-*/
-
-static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState);
-static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time);
-
-static const S_DECODER_INTERFACE PCMDecoder =
-{
- NULL,
- LinearPCMDecode,
- LinearPCMLocate,
-};
-
-/* SMAF ADPCM decoder */
-#ifdef _SMAF_PARSER
-extern S_DECODER_INTERFACE SmafDecoder;
-#define SMAF_DECODER &SmafDecoder
-extern S_DECODER_INTERFACE Smaf7BitDecoder;
-#define SMAF_7BIT_DECODER &Smaf7BitDecoder
-#else
-#define SMAF_DECODER NULL
-#define SMAF_7BIT_DECODER NULL
-#endif
-
-/* IMA ADPCM decoder */
-#ifdef _IMA_DECODER
-extern S_DECODER_INTERFACE IMADecoder;
-#define IMA_DECODER &IMADecoder
-#else
-#define IMA_DECODER NULL
-#endif
-
-static const S_DECODER_INTERFACE * const decoders[] =
-{
- &PCMDecoder,
- SMAF_DECODER,
- IMA_DECODER,
- SMAF_7BIT_DECODER
-};
-
-/*----------------------------------------------------------------------------
- * Sample rate conversion
- *----------------------------------------------------------------------------
-*/
-
-#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE)
-
-#ifdef _LOOKUP_SAMPLE_RATE
-static const EAS_U32 srcConvRate[][2] =
-{
- 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE,
- 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE,
- 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE,
- 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE,
- 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE,
- 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE,
- 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE,
- 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE
-};
-static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate);
-#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2)
-#endif
-
-
-/* interface prototypes */
-static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples);
-
-
-/* local prototypes */
-static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData);
-static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState);
-
-/*----------------------------------------------------------------------------
- * EAS_PEInit()
- *----------------------------------------------------------------------------
- * Purpose:
- * Initializes the PCM engine
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData)
-{
- S_PCM_STATE *pState;
- EAS_INT i;
-
- /* check for static memory allocation */
- if (pEASData->staticMemoryModel)
- pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA);
- /* allocate dynamic memory */
- else
- pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS);
-
- if (!pEASData->pPCMStreams)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ }
- return EAS_ERROR_MALLOC_FAILED;
- }
-
- //zero the memory to insure complete initialization
- EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS);
-
- /* initialize the state data */
- for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
- pState->fileHandle = NULL;
-
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEShutdown()
- *----------------------------------------------------------------------------
- * Purpose:
- * Shuts down the PCM engine
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData)
-{
-
- /* free any dynamic memory */
- if (!pEASData->staticMemoryModel)
- {
- if (pEASData->pPCMStreams)
- {
- EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams);
- pEASData->pPCMStreams = NULL;
- }
- }
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PERender()
- *----------------------------------------------------------------------------
- * Purpose:
- * Render a buffer of PCM audio
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples)
-{
- S_PCM_STATE *pState;
- EAS_RESULT result;
- EAS_INT i;
-
- /* render all the active streams */
- for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
- {
- if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED))
- if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS)
- return result;
- }
- return EAS_SUCCESS;
-}
-
-
-/*----------------------------------------------------------------------------
- * EAS_PEState()
- *----------------------------------------------------------------------------
- * Purpose:
- * Returns the current state of the stream
- *
- * Inputs:
- * pEASData - pointer to overall EAS data structure
- * handle - pointer to file handle
- * pState - pointer to variable to store state
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- * Notes:
- * This interface is also exposed in the internal library for use by the other modules.
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState)
-{
- /* return current state */
- *pState = pInstData->state;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEClose()
- *----------------------------------------------------------------------------
- * Purpose:
- * Close the file and clean up
- *
- * Inputs:
- * pEASData - pointer to overall EAS data structure
- * handle - pointer to file handle
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
-{
- EAS_RESULT result;
-
- if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS)
- return result;
-
- pState->fileHandle = NULL;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * PCM_Reset()
- *----------------------------------------------------------------------------
- * Purpose:
- * Reset the sequencer. Used for locating backwards in the file.
- *
- * Inputs:
- * pEASData - pointer to overall EAS data structure
- * handle - pointer to file handle
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
-{
- EAS_RESULT result;
-
- /* reset file position to first byte of data in the stream */
- if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ }
- return result;
- }
-
- /* re-initialize stream */
- return InitPCMStream(pEASData, pState);
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEOpenStream()
- *----------------------------------------------------------------------------
- * Purpose:
- * Starts up a PCM playback
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle)
-{
- EAS_RESULT result;
- S_PCM_STATE *pState;
- EAS_I32 filePos;
-
- /* make sure we support this decoder */
- if (pParams->decoder >= NUM_DECODER_MODULES)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ }
- return EAS_ERROR_PARAMETER_RANGE;
- }
- if (decoders[pParams->decoder] == NULL)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ }
- return EAS_ERROR_FEATURE_NOT_AVAILABLE;
- }
-
- /* find a slot for the new stream */
- if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ }
- return EAS_ERROR_MAX_PCM_STREAMS;
- }
-
- /* get the current file position */
- if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ }
- pState->fileHandle = NULL;
- return result;
- }
-
- pState->pDecoder = decoders[pParams->decoder];
- pState->startPos = filePos;
- pState->bytesLeftLoop = pState->byteCount = pParams->size;
- pState->loopStart = pParams->loopStart;
- pState->samplesTilLoop = (EAS_I32) pState->loopStart;
- pState->loopSamples = pParams->loopSamples;
- pState->samplesInLoop = 0;
- pState->blockSize = (EAS_U16) pParams->blockSize;
- pState->flags = pParams->flags;
- pState->envData = pParams->envData;
- pState->volume = pParams->volume;
- pState->sampleRate = (EAS_U16) pParams->sampleRate;
-
- /* set the base frequency */
- pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15;
-
- /* calculate shift for frequencies > 1.0 */
- pState->rateShift = 0;
- while (pState->basefreq > 32767)
- {
- pState->basefreq = pState->basefreq >> 1;
- pState->rateShift++;
- }
-
- /* initialize */
- if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS)
- return result;
-
- *pHandle = pState;
-
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n",
- pState->startPos, pState->byteCount, pState->loopSamples); */ }
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEContinueStream()
- *----------------------------------------------------------------------------
- * Purpose:
- * Continues a PCM stream
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-/*lint -e{715} reserved for future use */
-EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size)
-{
-
- /* add new samples to count */
- pState->bytesLeft += size;
- if (pState->bytesLeft > 0)
- pState->flags &= ~PCM_FLAGS_EMPTY;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEGetFileHandle()
- *----------------------------------------------------------------------------
- * Purpose:
- * Returns the file handle of a stream
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle)
-{
- *pFileHandle = pState->fileHandle;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEUpdateParams()
- *----------------------------------------------------------------------------
- * Purpose:
- * Update the pitch and volume parameters for a PCM stream
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * handle - pointer to S_PCM_STATE for this stream
- * gainLeft - linear gain multipler in 1.15 fraction format
- * gainRight - linear gain multipler in 1.15 fraction format
- * pitch - pitch shift in cents
- * initial - initial settings, set current gain
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- * Notes
- * In mono mode, leftGain controls the output gain and rightGain is ignored
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-/*lint -esym(715, gainRight) used only in 2-channel version */
-EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight)
-{
-
- pState->gainLeft = gainLeft;
-
-#if (NUM_OUTPUT_CHANNELS == 2)
- pState->gainRight = gainRight;
-#endif
-
- pState->pitch = pitch;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PELocate()
- *----------------------------------------------------------------------------
- * Purpose:
- * This function seeks to the requested place in the file. Accuracy
- * is dependent on the sample rate and block size.
- *
- * Inputs:
- * pEASData - pointer to overall EAS data structure
- * pState - stream handle
- * time - media time in milliseconds
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time)
-{
- if (pState->pDecoder->pfLocate == NULL)
- return EAS_ERROR_FEATURE_NOT_AVAILABLE;
-
- return pState->pDecoder->pfLocate(pEASData, pState, time);
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEUpdateVolume()
- *----------------------------------------------------------------------------
- * Purpose:
- * Update the volume parameters for a PCM stream
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * handle - pointer to S_PCM_STATE for this stream
- * gainLeft - linear gain multipler in 1.15 fraction format
- * gainRight - linear gain multipler in 1.15 fraction format
- * initial - initial settings, set current gain
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- * Notes
- * In mono mode, leftGain controls the output gain and rightGain is ignored
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume)
-{
- pState->volume = volume;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEUpdatePitch()
- *----------------------------------------------------------------------------
- * Purpose:
- * Update the pitch parameter for a PCM stream
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * pState - pointer to S_PCM_STATE for this stream
- * pitch - new pitch value in pitch cents
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch)
-{
- pState->pitch = pitch;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEPause()
- *----------------------------------------------------------------------------
- * Purpose:
- * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback
- * at the end of the next audio frame.
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * handle - pointer to S_PCM_STATE for this stream
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
-{
- /* set state to stopping */
- pState->state = EAS_STATE_PAUSING;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PEResume()
- *----------------------------------------------------------------------------
- * Purpose:
- * Resume rendering a PCM stream. Sets the gain target back to its
- * previous setting and restarts playback at the end of the next audio
- * frame.
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * handle - pointer to S_PCM_STATE for this stream
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
-{
- /* set state to stopping */
- pState->state = EAS_STATE_PLAY;
- return EAS_SUCCESS;
-}
-
-EAS_U32 getDecayScale(EAS_U32 index)
-{
- EAS_U32 utemp;
-
- //envelope decay segment
- switch (index)
- {
- case 0: //no decay
- utemp = 512;//32768;
- break;
- case 1: //.0156 dB per update
- utemp = 511;//32709;
- break;
- case 2: //.03125
- utemp = 510;//32649;
- break;
- case 3: //.0625
- utemp = 508;//32532;
- break;
- case 4: //.125
- utemp = 505;//32298;
- break;
- case 5: //.25
- utemp = 497;//31835;
- break;
- case 6: //.5
- utemp = 483;//30929;
- break;
- case 7: //1.0
- utemp = 456;//29193;
- break;
- case 8: //2.0
- utemp = 406;//26008;
- break;
- case 9: //4.0
- utemp = 323;//20642;
- break;
- case 10: //8.0
- utemp = 203;//13004;
- break;
- case 11: //16.0
- utemp = 81;//5160;
- break;
- case 12: //32.0
- utemp = 13;//813;
- break;
- case 13: //64.0
- utemp = 0;//20;
- break;
- case 14: //128.0
- utemp = 0;
- break;
- case 15: //256.0
- default:
- utemp = 0;
- break;
- }
- //printf("getdecayscale returned %d\n",utemp);
- return utemp;
-}
-
-EAS_U32 getAttackIncrement(EAS_U32 index)
-{
- EAS_U32 utemp;
-
- //envelope decay segment
- switch (index)
- {
- case 0:
- utemp = 32;
- break;
- case 1:
- utemp = 64;
- break;
- case 2:
- utemp = 128;
- break;
- case 3:
- utemp = 256;
- break;
- case 4:
- utemp = 512;
- break;
- case 5:
- utemp = 1024;
- break;
- case 6:
- utemp = 2048;
- break;
- case 7:
- utemp = 4096;
- break;
- case 8:
- utemp = 8192;
- break;
- case 9:
- utemp = 16384;
- break;
- case 10:
- utemp = 32768;
- break;
- case 11:
- utemp = 65536;
- break;
- case 12:
- utemp = 65536;
- break;
- case 13:
- utemp = 65536;
- break;
- case 14:
- utemp = 65535;
- break;
- case 15:
- default:
- utemp = 0;
- break;
- }
- //printf("getattackincrement returned %d\n",utemp);
- return utemp;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PERelease()
- *----------------------------------------------------------------------------
- * Purpose:
- * Put the PCM stream envelope into release.
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * handle - pointer to S_PCM_STATE for this stream
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-/*lint -esym(715, pEASData) reserved for future use */
-EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState)
-{
- EAS_U32 utemp;
-
- //printf("handling note-off part of envelope\n");
- /*if the note is not ignore release or sustained*/
- if (((pState->envData >> 24) & 0x0F)==0)
- {
- /* set envelope state to release */
- pState->envState = PCM_ENV_RELEASE;
- utemp = ((pState->envData >> 20) & 0x0F);
- pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp);
- }
- else
- {
- /*else change envelope state to sustain */
- pState->envState = PCM_ENV_SUSTAIN;
- utemp = ((pState->envData >> 28) & 0x0F);
- pState->envScale = getDecayScale(utemp); //getSustainScale(utemp);
- }
- //since we are in release, don't let anything hang around too long
- //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale);
- if (pState->envScale > 505)
- pState->envScale = 505;
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * FindSlot()
- *----------------------------------------------------------------------------
- * Purpose:
- * Locates an empty stream slot and assigns the file handle
- *
- * Inputs:
- * pEASData - pointer to EAS library instance data
- * fileHandle - file handle
- * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED
- *
- * Outputs:
- * returns handle to slot or NULL if all slots are used
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData)
-{
- EAS_INT i;
- S_PCM_STATE *pState;
-
-#ifndef NO_PCM_STEAL
- S_PCM_STATE *foundState = NULL;
- EAS_INT count = 0;
- EAS_U32 startOrder = 0xFFFFFFFF;
- S_PCM_STATE *stealState = NULL;
- EAS_U32 youngest = 0;
-
- /* find an empty slot, count total in use, and find oldest in use (lowest start order) */
- for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++)
- {
- /* if this one is available */
- if (pState->fileHandle == NULL)
- {
- foundState = pState;
- }
- /* else this one is in use, so see if it is the oldest, and count total in use */
- /* also find youngest */
- else
- {
- /*one more voice in use*/
- count++;
- /* is this the oldest? (lowest start order) */
- if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder))
- {
- /* remember this one */
- stealState = pState;
- /* remember the oldest so far */
- startOrder = pState->startOrder;
- }
- /* is this the youngest? (highest start order) */
- if (pState->startOrder >= youngest)
- {
- youngest = pState->startOrder;
- }
- }
- }
-
- /* if there are too many voices active, stop the oldest one */
- if (count > PCM_STREAM_THRESHOLD)
- {
- //printf("stealing!!!\n");
- /* make sure we got one, although we should always have one at this point */
- if (stealState != NULL)
- {
- //flag this as stopping, so it will get shut off
- stealState->state = EAS_STATE_STOPPING;
- }
- }
-
- /* if there are no available open streams (we won't likely see this, due to stealing) */
- if (foundState == NULL)
- return NULL;
-
- /* save info */
- foundState->startOrder = youngest + 1;
- foundState->fileHandle = fileHandle;
- foundState->pCallback = pCallbackFunc;
- foundState->cbInstData = cbInstData;
- return foundState;
-#else
- /* find an empty slot*/
- for (i = 0; i < MAX_PCM_STREAMS; i++)
- {
- pState = &pEASData->pPCMStreams[i];
- if (pState->fileHandle != NULL)
- continue;
-
- pState->fileHandle = fileHandle;
- pState->pCallback = pCallbackFunc;
- pState->cbInstData = cbInstData;
- return pState;
- }
- return NULL;
-#endif
-}
-
-#ifdef _LOOKUP_SAMPLE_RATE
-/*----------------------------------------------------------------------------
- * CalcBaseFreq()
- *----------------------------------------------------------------------------
- * Purpose:
- * Calculates the fractional phase increment for the sample rate converter
- *
- * Inputs:
- * sampleRate - sample rate in samples/sec
- *
- * Outputs:
- * Returns fractional sample rate with a 15-bit fraction
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate)
-{
- EAS_INT i;
-
- /* look up the conversion rate */
- for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++)
- {
- if (srcConvRate[i][0] == sampleRate)
- return srcConvRate[i][1];
- }
-
- /* if not found in table, do it the long way */
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ }
-
- return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15;
-}
-#endif
-
-/*----------------------------------------------------------------------------
- * InitPCMStream()
- *----------------------------------------------------------------------------
- * Purpose:
- * Start an ADPCM stream playback. Decodes the header, preps the engine.
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState)
-{
-
- /* initialize the data structure */
- pState->bytesLeft = pState->byteCount;
- pState->phase = 0;
- pState->srcByte = 0;
- pState->decoderL.acc = 0;
- pState->decoderL.output = 0;
- pState->decoderL.x0 = pState->decoderL.x1 = 0;
- pState->decoderL.step = 0;
- pState->decoderR.acc = 0;
- pState->decoderR.output = 0;
- pState->decoderR.x0 = pState->decoderR.x1 = 0;
- pState->decoderR.step = 0;
- pState->hiNibble = EAS_FALSE;
- pState->pitch = 0;
- pState->blockCount = 0;
- pState->gainLeft = PCM_DEFAULT_GAIN_SETTING;
-// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING;
- pState->envValue = 0;
- pState->envState = PCM_ENV_START;
-
-#if (NUM_OUTPUT_CHANNELS == 2)
- pState->gainRight = PCM_DEFAULT_GAIN_SETTING;
-// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING;
-#endif
- pState->state = EAS_STATE_READY;
-
- /* initialize the decoder */
- if (pState->pDecoder->pfInit)
- return (*pState->pDecoder->pfInit)(pEASData, pState);
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * RenderPCMStream()
- *----------------------------------------------------------------------------
- * Purpose:
- * Decodes a buffer of ADPCM data.
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples)
-{
- EAS_RESULT result;
- EAS_U32 phaseInc;
- EAS_I32 gainLeft, gainIncLeft;
- EAS_I32 *pOut;
- EAS_I32 temp;
- EAS_U32 utemp;
-
-#if (NUM_OUTPUT_CHANNELS == 2)
- EAS_I32 gainRight, gainIncRight;
-#endif
-
-#if 0
- printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n",
- ((pState->envData >> 12) & 0x0F),
- ((pState->envData >> 16) & 0x0F),
- ((pState->envData >> 8) & 0x0F),
- ((pState->envData >> 28) & 0x0F),
- ((pState->envData >> 20) & 0x0F));
-#endif
-
- if (pState->envState == PCM_ENV_START)
- {
- //printf("env start\n");
- utemp = ((pState->envData >> 12) & 0x0F);
- //if fastest rate, attack is already completed
- //do the same for slowest rate, since that allows zero to be passed for default envelope
- if (utemp == 0x0F || utemp == 0x00)
- {
- //start envelope at full
- pState->envValue = (32768<<7);
- //jump right into decay
- utemp = ((pState->envData >> 16) & 0x0F);
- pState->envScale = getDecayScale(utemp);
- pState->envState = PCM_ENV_DECAY;
- pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume);
- pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume);
- }
- //else attack has a ramp
- else
- {
- //start the envelope very low
- pState->envValue = (2<<7);
- pState->currentGainLeft = 0;
- pState->currentGainRight = 0;
- //get envelope attack scaling value
- pState->envScale = getAttackIncrement(utemp);
- //go to attack state
- pState->envState = PCM_ENV_ATTACK;
- }
- }
- if (pState->envState == PCM_ENV_ATTACK)
- {
- //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
- //update envelope value
- pState->envValue = pState->envValue + (pState->envScale << 7);
- //check envelope level and update state if needed
- if (pState->envValue >= (32768<<7))
- {
- pState->envValue = (32768<<7);
- utemp = ((pState->envData >> 16) & 0x0F);
- pState->envScale = getDecayScale(utemp);
- pState->envState = PCM_ENV_DECAY;
- }
- }
- else if (pState->envState == PCM_ENV_DECAY)
- {
- //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
- //update envelope value
- pState->envValue = (pState->envValue * pState->envScale)>>9;
- //check envelope level against sustain level and update state if needed
- utemp = ((pState->envData >> 8) & 0x0F);
- if (utemp == (EAS_U32)0x0F)
- utemp = (2<<7);
- else
- {
- utemp = ((32769<<7) >> (utemp>>1));
- }
- if (pState->envValue <= utemp)
- {
- utemp = ((pState->envData >> 28) & 0x0F);
- pState->envScale = getDecayScale(utemp); //getSustainScale(utemp);
- pState->envState = PCM_ENV_SUSTAIN;
- }
- }
- else if (pState->envState == PCM_ENV_SUSTAIN)
- {
- //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
- //update envelope value
- pState->envValue = (pState->envValue * pState->envScale)>>9;
- //check envelope level against bottom level and update state if needed
- if (pState->envValue <= (2<<7))
- {
- //no more decay
- pState->envScale = 512;
- pState->envState = PCM_ENV_END;
- }
- }
- else if (pState->envState == PCM_ENV_RELEASE)
- {
- //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale);
- //update envelope value
- pState->envValue = (pState->envValue * pState->envScale)>>9;
- //check envelope level against bottom level and update state if needed
- if (pState->envValue <= (2<<7))
- {
- //no more decay
- pState->envScale = 512;
- pState->envState = PCM_ENV_END;
- }
- }
- else if (pState->envState == PCM_ENV_END)
- {
- //printf("env end\n");
- /* set state to stopping, already ramped down */
- pState->state = EAS_STATE_STOPPING;
- }
-
- //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15);
- //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15);
-
- /* gain to 32-bits to increase resolution on anti-zipper filter */
- /*lint -e{703} use shift for performance */
- gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS;
-#if (NUM_OUTPUT_CHANNELS == 2)
- /*lint -e{703} use shift for performance */
- gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS;
-#endif
-
- /* calculate a new gain increment, gain target is zero if pausing */
- if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED))
- {
- gainIncLeft = -pState->currentGainLeft;
-#if (NUM_OUTPUT_CHANNELS == 2)
- gainIncRight= -pState->currentGainRight;
-#endif
- }
- else
- {
- EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume);
- gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft;
-#if (NUM_OUTPUT_CHANNELS == 2)
- gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight;
-#endif
- }
-
- /* calculate phase increment */
- phaseInc = pState->basefreq;
-
- /* convert pitch cents to linear multiplier */
- if (pState->pitch)
- {
- temp = EAS_Calculate2toX(pState->pitch);
- phaseInc = FMUL_15x15(phaseInc, temp);
- }
- phaseInc = phaseInc << pState->rateShift;
-
- /* pointer to mix buffer */
- pOut = pEASData->pMixBuffer;
-
- /* render a buffer of samples */
- while (numSamples--)
- {
-
- /* interpolate an output sample */
- pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK);
-
- /* stereo output */
-#if (NUM_OUTPUT_CHANNELS == 2)
-
- /* stereo stream? */
- if (pState->flags & PCM_FLAGS_STEREO)
- pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK);
-
- /* gain scale and mix */
- /*lint -e{704} use shift instead of division */
- *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
- gainLeft += gainIncLeft;
-
- /*lint -e{704} use shift instead of division */
- if (pState->flags & PCM_FLAGS_STEREO)
- *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
- else
- *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
-
- gainRight += gainIncRight;
-
- /* mono output */
-#else
- /* if stereo stream, decode right channel and mix to mono */
- if (pState->flags & PCM_FLAGS_STEREO)
- {
- pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK);
-
- /* for mono, sum stereo ADPCM to mono */
- /*lint -e{704} use shift instead of division */
- *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
- }
- else
- /*lint -e{704} use shift instead of division */
- *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS;
-
- gainLeft += gainIncLeft;
-#endif
-
- /* advance phase accumulator */
- pState->phase += phaseInc;
-
- /* if integer part of phase accumulator is non-zero, advance to next sample */
- while (pState->phase & ~PHASE_FRAC_MASK)
- {
- pState->decoderL.x0 = pState->decoderL.x1;
- pState->decoderR.x0 = pState->decoderR.x1;
-
- /* give the source a chance to continue the stream */
- if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0))
- {
- pState->flags |= PCM_FLAGS_EMPTY;
- (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY);
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ }
- }
-
- /* decode the next sample */
- if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS)
- return result;
-
- /* adjust phase by one sample */
- pState->phase -= (1L << NUM_PHASE_FRAC_BITS);
- }
-
- }
-
- /* save new gain */
- /*lint -e{704} use shift instead of division */
- pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS);
-
-#if (NUM_OUTPUT_CHANNELS == 2)
- /*lint -e{704} use shift instead of division */
- pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS);
-#endif
-
- /* if pausing, set new state and notify */
- if (pState->state == EAS_STATE_PAUSING)
- {
- pState->state = EAS_STATE_PAUSED;
- if (pState->pCallback)
- (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state);
- }
-
- /* if out of data, set stopped state and notify */
- if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING)
- {
- pState->state = EAS_STATE_STOPPED;
-
- /* do callback unless the file has already been closed */
- if (pState->pCallback && pState->fileHandle)
- (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state);
- }
-
- if (pState->state == EAS_STATE_READY)
- pState->state = EAS_STATE_PLAY;
-
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * LinearPCMDecode()
- *----------------------------------------------------------------------------
- * Purpose:
- * Decodes a PCM sample
- *
- * Inputs:
- *
- *
- * Outputs:
- *
- *
- * Side Effects:
- *
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState)
-{
- EAS_RESULT result;
- EAS_HW_DATA_HANDLE hwInstData;
-
- hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData;
-
- /* if out of data, check for loop */
- if ((pState->bytesLeft == 0) && (pState->loopSamples != 0))
- {
- if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS)
- return result;
- pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop;
- pState->flags &= ~PCM_FLAGS_EMPTY;
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ }
- }
-
- if (pState->bytesLeft)
- {
-
- /* check format byte for 8-bit samples */
- if (pState->flags & PCM_FLAGS_8_BIT)
- {
- /* fetch left or mono sample */
- if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS)
- return result;
-
- /* if unsigned */
- if (pState->flags & PCM_FLAGS_UNSIGNED)
- {
- /*lint -e{734} converting unsigned 8-bit to signed 16-bit */
- pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000);
- }
- else
- {
- /*lint -e{734} converting signed 8-bit to signed 16-bit */
- pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8);
- }
- pState->bytesLeft--;
-
- /* fetch right sample */
- if(pState->flags & PCM_FLAGS_STEREO)
- {
- if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS)
- return result;
-
- /* if unsigned */
- if (pState->flags & PCM_FLAGS_UNSIGNED)
- {
- /*lint -e{734} converting unsigned 8-bit to signed 16-bit */
- pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000);
- }
- else
- {
- /*lint -e{734} converting signed 8-bit to signed 16-bit */
- pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8);
- }
- pState->bytesLeft--;
- }
- }
-
- /* must be 16-bit samples */
- else
- {
- //unsigned 16 bit currently not supported
- if (pState->flags & PCM_FLAGS_UNSIGNED)
- {
- return EAS_ERROR_INVALID_PCM_TYPE;
- }
-
- /* fetch left or mono sample */
- if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS)
- return result;
- pState->bytesLeft -= 2;
-
- /* fetch right sample */
- if(pState->flags & PCM_FLAGS_STEREO)
- {
- if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS)
- return result;
- pState->bytesLeft -= 2;
- }
- }
- }
-
- /* no more data, force zero samples */
- else
- pState->decoderL.x1 = pState->decoderR.x1 = 0;
-
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * LinearPCMLocate()
- *----------------------------------------------------------------------------
- * Purpose:
- * Locate in a linear PCM stream
- *----------------------------------------------------------------------------
-*/
-static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time)
-{
- EAS_RESULT result;
- EAS_I32 temp;
- EAS_I32 secs, msecs;
- EAS_INT shift;
-
- /* calculate size of sample frame */
- if (pState->flags & PCM_FLAGS_8_BIT)
- shift = 0;
- else
- shift = 1;
- if (pState->flags & PCM_FLAGS_STEREO)
- shift++;
-
- /* break down into secs and msecs */
- secs = time / 1000;
- msecs = time - (secs * 1000);
-
- /* calculate sample number fraction from msecs */
- temp = (msecs * pState->sampleRate);
- temp = (temp >> 10) + ((temp * 49) >> 21);
-
- /* add integer sample count */
- temp += secs * pState->sampleRate;
-
- /* calculate the position based on sample frame size */
- /*lint -e{703} use shift for performance */
- temp <<= shift;
-
- /* past end of sample? */
- if (temp > (EAS_I32) pState->loopStart)
- {
- /* if not looped, flag error */
- if (pState->loopSamples == 0)
- {
- pState->bytesLeft = 0;
- pState->flags |= PCM_FLAGS_EMPTY;
- return EAS_ERROR_LOCATE_BEYOND_END;
- }
-
- /* looped sample - calculate position in loop */
- while (temp > (EAS_I32) pState->loopStart)
- temp -= (EAS_I32) pState->loopStart;
- }
-
- /* seek to new position */
- if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS)
- return result;
-
- /* reset state */
- if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED))
- pState->state = EAS_STATE_READY;
-
- return EAS_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------
- * EAS_PESeek
- *----------------------------------------------------------------------------
- * Purpose:
- * Locate to a particular byte in a PCM stream
- *----------------------------------------------------------------------------
- * This bit is tricky because the chunks may not be contiguous,
- * so we have to rely on the parser to position in the file. We
- * do this by seeking to the end of each chunk and simulating an
- * empty buffer condition until we get to where we want to go.
- *
- * A better solution would be a parser API for re-positioning,
- * but there isn't time at the moment to re-factor all the
- * parsers to support a new API.
- *----------------------------------------------------------------------------
-*/
-EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation)
-{
- EAS_RESULT result;
-
- /* seek to start of audio */
- if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS)
- {
- pState->state = EAS_STATE_ERROR;
- return result;
- }
- pState->bytesLeft = pState->bytesLeftLoop;
-
- /* skip through chunks until we find the right chunk */
- while (*pLocation > (EAS_I32) pState->bytesLeft)
- {
- /* seek to end of audio chunk */
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ }
- if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS)
- {
- pState->state = EAS_STATE_ERROR;
- return result;
- }
- *pLocation -= pState->bytesLeft;
- pState->bytesLeft = 0;
- pState->flags |= PCM_FLAGS_EMPTY;
-
- /* retrieve more data */
- if (pState->pCallback)
- (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY);
-
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ }
-
- /* no more samples */
- if (pState->bytesLeft == 0)
- return EAS_ERROR_LOCATE_BEYOND_END;
- }
-
- /* seek to new offset in current chunk */
- if (*pLocation > 0)
- {
- { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ }
- if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS)
- {
- pState->state = EAS_STATE_ERROR;
- return result;
- }
-
- /* if not streamed, calculate number of bytes left */
- if (pState->flags & PCM_FLAGS_STREAMING)
- pState->bytesLeft = 0x7fffffff;
- else
- pState->bytesLeft -= *pLocation;
- }
- return EAS_SUCCESS;
-}
-