📄 wmaudiostream.c
字号:
* NULL if all buffers are currently full.
*---------------------------------------------------------------------------*/
void *WMAudioStartRendering( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
void *pDMABuffer;
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
/*
* Get the buffer from the DMA.
*/
pDMABuffer = WMDMAGetChannelBuffer( hDevice, pStreamCtx->DMAChan );
return pDMABuffer;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioFinishRendering
*
* WMAudioFinishRendering tells the library that the application has finished with
* the current buffer. This will start the DMA if necessary.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream whose buffer it is
* (from WMAudioOpenStream).
* pBuffer the buffer to complete (from WMAudioStartRendering).
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioFinishRendering( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream,
void *pBuffer
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
if( STREAM_OUTPUT & pStreamCtx->flags )
{
/*
* And now tell the DMA this buffer's full.
*/
WMDMAMarkBufferFull( hDevice, pStreamCtx->DMAChan, pBuffer );
}
else
{
WMDMAMarkBufferEmpty( hDevice, pStreamCtx->DMAChan, pBuffer );
}
}
/*-----------------------------------------------------------------------------
* Function: WMAudioClearBuffer
*
* This function fills the whole of the DMA buffer with silence. This will
* start the DMA if necessary.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to play on (from WMAudioOpenStream).
* This must be an output stream.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioClearBuffer( 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_OUTPUT );
/*
* Completely fill the current DMA buffer with silence.
*/
pStreamCtx->nSamples = 0;
private_ClearRestOfBuffer( hDevice, pStreamCtx );
}
/*-----------------------------------------------------------------------------
* Function: private_ClearRestOfBuffer
*
* This function fills the DMA buffer with silence.
* It works out the starting point by checking how many samples have already
* been written in to this buffer. It will then fill up the rest of the buffer
* with silence and start the DMA if necessary.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* pStreamCtx pointer to the StreamCtx for the stream. This must be an
* output channel and have been initialised using WMAudioOpenStream.
*
* Returns: void
*---------------------------------------------------------------------------*/
static void private_ClearRestOfBuffer( WM_DEVICE_HANDLE hDevice,
StreamCtx *pStreamCtx
)
{
char *pDMABuffer;
char *pFreeSpace;
unsigned int sampleCount;
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_OUTPUT );
/*
* Work out how many samples to clear in the DMA buffer.
*/
sampleCount = pStreamCtx->samplesPerBuffer - pStreamCtx->nSamples;
/*
* Get the current DMA Buffer
*/
pDMABuffer = (char *) WMDMAGetChannelBuffer( hDevice,
pStreamCtx->DMAChan
);
if ( !pDMABuffer )
{
goto end;
}
/*
* Work out how much free space in bytes is left in the DMA Buffer.
*/
pFreeSpace = pDMABuffer + ( pStreamCtx->nSamples * pStreamCtx->bytesPerDMASample );
/*
* Set the remainder of the DMA buffer to zero
*/
memset( pFreeSpace,
0,
sampleCount * pStreamCtx->bytesPerDMASample
);
/*
* Mark this buffer as full.
*/
WMDMAMarkBufferFull( hDevice, pStreamCtx->DMAChan, pDMABuffer );
/*
* The buffer is full now so set our sample counter back to zero.
*/
pStreamCtx->nSamples = 0;
end:
return;
}
#if WM_TESTING
/*-----------------------------------------------------------------------------
* Function: WMAudioPlaySineWave
*
* This function fills a DMA buffer with a sine wave and plays it.
* Note: it will overwrite a partially filled buffer.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to play on (from WMAudioOpenStream).
* This must be an output stream.
* frequency the fequency of the sine wave in Hz.
* amplitude the peak amplitude of the sine wave (0-32768).
* pRestart pointer to a restart context - position after previous
* call. Used to restart the wave where the previous call
* left off. Updated to the start position for the next call.
*
* Returns: WM_BOOL
* TRUE if data was transmitted.
* FALSE if there were no buffers available.
*---------------------------------------------------------------------------*/
WM_BOOL WMAudioPlaySineWave( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream,
unsigned short frequency,
unsigned short amplitude,
WM_WAVEGEN_CTX *pRestart
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
void *pDMABuffer;
WM_BOOL dataTransmitted = FALSE;
WM_WAVEGEN_FORMAT format;
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_OUTPUT );
/*
* Get the DMA buffer.
*/
pDMABuffer = WMDMAGetChannelBuffer( hDevice, pStreamCtx->DMAChan );
if ( !pDMABuffer )
{
goto end;
}
/*
* Now fill it.
*/
if ( pStreamCtx->flags & STREAM_STEREO_DMA )
{
format = WM_WAVEGEN_STEREO;
}
else if ( pStreamCtx->flags & STREAM_MONO_DMA )
{
format = WM_WAVEGEN_CONTIGUOUS;
}
else if ( pStreamCtx->flags & STREAM_MONO_DMA_WIDE )
{
format = WM_WAVEGEN_CONTIGUOUS_WIDE;
}
else
{
WM_ASSERT( hDevice, FALSE );
}
WMGenerateSineWave( (WM_AUDIO_STEREO_SAMPLE *) pDMABuffer,
pStreamCtx->samplesPerBuffer,
pStreamCtx->sampleRate,
frequency,
amplitude,
format,
pRestart
);
/*
* Now mark the buffer as full. This will start the DMA if necessary.
*/
WMDMAMarkBufferFull( hDevice, pStreamCtx->DMAChan, pDMABuffer );
pStreamCtx->nSamples = 0;
dataTransmitted = TRUE;
end:
return dataTransmitted;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioPlaySquareWave
*
* This function fills a DMA buffer with a square wave and plays it.
* Note: it will overwrite a partially filled buffer.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to play on (from WMAudioOpenStream).
* This must be an output stream.
* frequency the fequency of the square wave in Hz.
* amplitude the peak amplitude of the square wave (0-32767).
* pRestart pointer to a restart context - position after previous call.
* Used to restart the wave where the previous call left off.
* Updated to the start position for the next call.
*
* Returns: WM_BOOL
* TRUE if data was transmitted.
* FALSE if there were no buffers available.
*---------------------------------------------------------------------------*/
WM_BOOL WMAudioPlaySquareWave( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream,
unsigned short frequency,
unsigned short amplitude,
WM_WAVEGEN_CTX *pRestart
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
void *pDMABuffer;
WM_BOOL dataTransmitted = FALSE;
WM_WAVEGEN_FORMAT format;
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_OUTPUT );
/*
* Get the DMA buffer.
*/
pDMABuffer = WMDMAGetChannelBuffer( hDevice, pStreamCtx->DMAChan );
if ( !pDMABuffer )
{
goto end;
}
/*
* Now fill it.
*/
if ( pStreamCtx->flags & STREAM_STEREO_DMA )
{
format = WM_WAVEGEN_STEREO;
}
else
{
format = WM_WAVEGEN_CONTIGUOUS;
}
WMGenerateSquareWave( (WM_AUDIO_STEREO_SAMPLE *) pDMABuffer,
pStreamCtx->samplesPerBuffer,
pStreamCtx->sampleRate,
frequency,
amplitude,
format,
pRestart
);
/*
* Now switch buffers. This will start the DMA if necessary.
*/
WMDMAMarkBufferFull( hDevice, pStreamCtx->DMAChan, pDMABuffer );
pStreamCtx->nSamples = 0;
dataTransmitted = TRUE;
end:
return dataTransmitted;
}
#endif /* WM_TESTING */
/*-----------------------------------------------------------------------------
* Function: WMAudioReceiveData
*
* This function returns the recorded audio data from the buffer.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* hStream handle to the stream to record (from WMAudioOpenStream).
* This must be an input stream.
* buffer the buffer to receive the audio samples in the format
* specified in WMAudioOpenStream.
* dataSize the size of the buffer in bytes.
* pBytesCopied pointer to the number of bytes copied from the DMA
* buffer.
*
* Returns: WM_BOOL
* TRUE if all the data in the DMA buffer has been copied.
* FALSE if there is still data left in the DMA Buffer.
*---------------------------------------------------------------------------*/
WM_BOOL WMAudioReceiveData( WM_DEVICE_HANDLE hDevice,
WM_STREAM_HANDLE hStream,
void *buffer,
unsigned int dataSize,
unsigned int *pBytesCopied
)
{
StreamCtx *pStreamCtx = STREAM_CONTEXT_FROM_HANDLE( hStream );
char *pDMABuffer;
unsigned int sampleCount;
unsigned int nUserSamples;
WM_BOOL DMABufferEmpty = FALSE;
char *pFreeSpace;
/*
* Checks on the stream.
*/
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_ACTIVE );
WM_ASSERT( hDevice, pStreamCtx->flags & STREAM_INPUT );
WM_ASSERT( hDevice,
pStreamCtx->bytesPerDMASample == pStreamCtx->bytesPerUserSample
);
/*
* Work out how much data is left in this buffer.
* Note there should be some data - if there isn't we should have already
* switched buffers at the time we filled it.
*/
sampleCount = pStreamCtx->samplesPerBuffer - pStreamCtx->nSamples;
WM_ASSERT( hDevice, sampleCount > 0 );
/*
* Work out how many samples to record.
*/
nUserSamples = dataSize / pStreamCtx->bytesPerUserSample;
if ( sampleCount > nUserSamples )
sampleCount = nUserSamples;
/*
* Get the DMA buffer and copy it to the application buffer.
*/
pDMABuffer = (char *) WMDMAGetChannelBuffer( hDevice, pStreamCtx->DMAChan );
/*
* If there's no data, there's not much we can do...
*/
if ( !pDMABuffer )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -