📄 wmaudiostream.c
字号:
*pBytesCopied = 0;
DMABufferEmpty = TRUE;
goto end;
}
/*
* Work out how much free space in bytes is left in the DMA Buffer.
*/
pFreeSpace = pDMABuffer + ( pStreamCtx->nSamples * pStreamCtx->bytesPerDMASample );
pStreamCtx->copyFunc( buffer, pFreeSpace, sampleCount );
/*
* Update our buffer size.
*/
pStreamCtx->nSamples += sampleCount;
/*
* Work out the number of bytes we copied.
*/
*pBytesCopied = sampleCount * pStreamCtx->bytesPerUserSample;
/*
* If the number of samples we have copied is the size of the DMA buffer
* then we need to reset our sample counter and move on to the next
* available DMA buffer.
*/
if ( pStreamCtx->nSamples == pStreamCtx->samplesPerBuffer )
{
/* Tell the DMA we've read the current buffer. */
WMDMAMarkBufferEmpty( hDevice, pStreamCtx->DMAChan, pDMABuffer );
/* Set flag to show that all of the Data in the DMA Buffer has been copied. */
DMABufferEmpty = TRUE;
/* The buffer is full now so set our sample counter back to zero. */
pStreamCtx->nSamples = 0;
}
/*
* Return the status of the DMA Buffer.
*/
end:
return DMABufferEmpty;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioStartRecording
*
* This function starts the given input stream.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to start (from WMAudioOpenStream)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioStartRecording( WM_DEVICE_HANDLE hDevice, WM_STREAM_HANDLE hStream )
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_INPUT );
/*
* And start streaming.
*/
WMDMAStartChannel( hDevice, pStreamCtx->DMAChan );
}
/*-----------------------------------------------------------------------------
* Function: WMAudioStop
*
* This function stops the given stream. Any outstanding data in the DMA
* buffers is lost.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to stop (from WMAudioOpenStream)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioStop( WM_DEVICE_HANDLE hDevice, WM_STREAM_HANDLE hStream )
{
StreamCtx *pStreamCtx;
if ( NULL == hDevice )
{
goto finish;
}
/*
* if system calls are not allowed then we are under Power
* handling control so just finish if the stream does not exist.
*/
if ( !WMSystemCallsAllowed(hDevice) && ! hStream )
{
goto finish;
}
pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
if ( !WMSystemCallsAllowed(hDevice) && ! pStreamCtx )
{
goto finish;
}
/*
* Checks on the stream.
*/
if ( WMSystemCallsAllowed(hDevice) )
{
WM_ASSERT( hDevice, pStreamCtx );
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
}
/*
* And stop streaming.
*/
WMDMAStopChannel( hDevice, pStreamCtx->DMAChan );
finish:
return;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioCheckStreamInterrupts
*
* This function checks what interrupts have happened and clears them.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to check (from WMAudioOpenStream).
* Can be NULL to allow interrupt-handling code to call
* this when there are no active streams.
*
* Returns: WMAUDIO_INTSTATE
* bitmask listing the interrupts
*---------------------------------------------------------------------------*/
WMAUDIO_INTSTATE WMAudioCheckStreamInterrupts( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
if ( pStreamCtx && pStreamCtx->flags & STREAM_ACTIVE && pStreamCtx->DMAChan )
{
/*
* And pass the call on.
*/
return WMDMACheckChannelInterrupts( hDevice, pStreamCtx->DMAChan );
}
else
return 0;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioHandleInterrupt
*
* This function allows the library to do any processing required when an
* interrupt is received on an audio channel. This _must_ be called
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream which received the interrupt
* (from WMAudioOpenStream). Can be NULL to allow
* interrupt-handling code to call this when there
* are no active streams.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioHandleInterrupt( WM_DEVICE_HANDLE hDevice, WM_STREAM_HANDLE hStream )
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
/*
* And pass the call on.
*/
if ( pStreamCtx && pStreamCtx->flags & STREAM_ACTIVE )
{
WMDMAHandleInterrupt( hDevice, pStreamCtx->DMAChan );
}
}
/*-----------------------------------------------------------------------------
* Function: WMAudioBufferSize
*
* This function returns the size of the audio buffers in bytes.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to check (from WMAudioOpenStream)
*
* Returns: unsigned int
* The size of the audio buffers in bytes.
*---------------------------------------------------------------------------*/
unsigned int WMAudioBufferSize( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
return pStreamCtx->samplesPerBuffer * pStreamCtx->bytesPerDMASample;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioSamplesPerBuffer
*
* This function returns the max number of samples that each buffer can hold.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to check (from WMAudioOpenStream)
*
* Returns: int
* samplesPerBuffer
*---------------------------------------------------------------------------*/
int WMAudioSamplesPerBuffer( WM_DEVICE_HANDLE hDevice, WM_STREAM_HANDLE hStream )
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
return pStreamCtx->samplesPerBuffer;
}
#if WM_USE_DYNAMIC_DMA_CHANNEL
/*-----------------------------------------------------------------------------
* Function: WMAudioGetDMAEventHandle
*
* This function returns an interrupt event handle for the given audio channel
* (if relevant for this platform).
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to check (from WMAudioOpenStream)
*
* Returns: WMEvent_t *
* the interrupt event handle, or NULL if this is not relevant.
*---------------------------------------------------------------------------*/
WMEvent_t WMAudioGetDMAEventHandle( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream
)
{
WMEvent_t DMAEventHandle;
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
DMAEventHandle = WMDMAGetEventHandle( hDevice, pStreamCtx->DMAChan );
return DMAEventHandle;
}
#endif /* WM_USE_DYNAMIC_DMA_CHANNEL */
/*-----------------------------------------------------------------------------
* Function: WMAudioEnableDMAInterrupts
*
* This function enables DMA interrupts.
* NOTE: This function is intended for use only by the library test
* code and should not be used by standard library code.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioEnableDMAInterrupts( WM_DEVICE_HANDLE hDevice )
{
WMDMAEnableInterrupts( hDevice );
}
/*-----------------------------------------------------------------------------
* Function: WMAudioDisableDMAInterrupts
*
* This function disables DMA interrupts.
* NOTE: This function is intended for use only by the library test
* code and should not be used by standard library code.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioDisableDMAInterrupts( WM_DEVICE_HANDLE hDevice )
{
WMDMADisableInterrupts( hDevice );
}
/*-----------------------------------------------------------------------------
* Private functions *
*---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
* Function: private_GetStreamContext
*
* Returns the stream context for the given stream.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice).
* stream the stream to look up.
*
* Returns: StreamCtx *
* Pointer to the stream context corresponding to this stream, or
* NULL if no stream context corresponds to this stream.
*---------------------------------------------------------------------------*/
static StreamCtx *private_GetStreamContext( WM_DEVICE_HANDLE hDevice,
WM_STREAM_ID stream
)
{
int nStream;
for ( nStream = 0; nStream < WM_STREAM_CONTEXTS; nStream++ )
{
StreamCtx *pStreamCtx = &s_streamContexts[nStream];
if ( stream == pStreamCtx->stream )
{
return pStreamCtx;
}
}
/* Nothing found that matches */
return NULL;
}
/*-----------------------------------------------------------------------------
* Function: private_AllocateStreamContext
*
* Allocates a stream context for the given stream. Assumes the stream is
* not already allocated.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice).
* stream the stream to allocate for.
* ppStreamCtx variable to receive the allocated stream context.
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
static WMSTATUS private_AllocateStreamContext( WM_DEVICE_HANDLE hDevice,
WM_STREAM_ID stream,
StreamCtx **ppStreamCtx
)
{
WMSTATUS status;
int nStream;
StreamCtx *pStreamCtx = NULL;
/*
* Look up the stream context for this stream ID.
*/
pStreamCtx = private_GetStreamContext( hDevice, stream );
if ( pStreamCtx )
{
/*
* If we got one, check no-one else is already using it.
*/
if ( pStreamCtx->flags & STREAM_ACTIVE )
{
status = WMS_DEVICE_BUSY;
goto error;
}
}
else
{
/*
* Otherwise, look for a spare one we assign to this stream.
*/
for ( nStream = 0; nStream < WM_STREAM_CONTEXTS; nStream++ )
{
pStreamCtx = &s_streamContexts[nStream];
if ( STREAM_UNASSIGNED == pStreamCtx->stream )
{
/*
* We've found a spare one. Assign it to this stream.
*/
private_InitialiseStreamContext( hDevice,
stream,
pStreamCtx
);
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -