#include <functiondiscoverykeys.h>\r
#undef INITGUID\r
#endif\r
+#ifndef __MWERKS__\r
+#include <malloc.h>\r
+#include <memory.h>\r
+#endif /* __MWERKS__ */\r
\r
#include "pa_util.h"\r
#include "pa_allocation.h"\r
\r
HRESULT hr = S_OK;\r
UINT32 frames;\r
- BYTE *buffer = (BYTE *)_buffer;\r
- BYTE *data = NULL;\r
+ BYTE *user_buffer = (BYTE *)_buffer;\r
+ BYTE *wasapi_buffer = NULL;\r
DWORD flags = 0;\r
- UINT32 buffer_size;\r
+ UINT32 i;\r
\r
// validate\r
if (!stream->running)\r
// Notify blocking op has begun\r
ResetEvent(stream->hBlockingOpStreamRD);\r
\r
+ // make a local copy of the user buffer pointer(s), this is necessary\r
+ // because PaUtil_CopyOutput() advances these pointers every time it is called\r
+ if (!stream->bufferProcessor.userInputIsInterleaved)\r
+ {\r
+ user_buffer = (BYTE *)alloca(sizeof(BYTE *) * stream->bufferProcessor.inputChannelCount);\r
+ if (user_buffer == NULL)\r
+ return paInsufficientMemory;\r
+\r
+ for (i = 0; i < stream->bufferProcessor.inputChannelCount; ++i)\r
+ ((BYTE **)user_buffer)[i] = ((BYTE **)_buffer)[i];\r
+ }\r
+\r
while (_frames != 0)\r
{\r
+ UINT32 processed, processed_size;\r
+\r
// Get the available data in the shared buffer.\r
- if ((hr = IAudioCaptureClient_GetBuffer(stream->cclient, &data, &frames, &flags, NULL, NULL)) != S_OK)\r
+ if ((hr = IAudioCaptureClient_GetBuffer(stream->cclient, &wasapi_buffer, &frames, &flags, NULL, NULL)) != S_OK)\r
{\r
if (hr == AUDCLNT_S_BUFFER_EMPTY)\r
{\r
if (frames > _frames)\r
frames = _frames;\r
\r
- // Copy\r
- buffer_size = frames * stream->in.wavex.Format.nBlockAlign;\r
- memcpy(buffer, data, buffer_size);\r
- buffer += buffer_size;\r
+ // Register available frames to processor\r
+ PaUtil_SetInputFrameCount(&stream->bufferProcessor, frames);\r
+ \r
+ // Register host buffer pointer to processor\r
+ PaUtil_SetInterleavedInputChannels(&stream->bufferProcessor, 0, wasapi_buffer, stream->bufferProcessor.inputChannelCount);\r
+ \r
+ // Copy user data to host buffer (with conversion if applicable)\r
+ processed = PaUtil_CopyInput(&stream->bufferProcessor, (void **)&user_buffer, frames);\r
\r
- // Release buffer\r
- if ((hr = IAudioCaptureClient_ReleaseBuffer(stream->cclient, frames)) != S_OK)\r
+ // Advance user buffer to consumed portion\r
+ processed_size = processed * stream->in.wavex.Format.nBlockAlign;\r
+ if (stream->bufferProcessor.userInputIsInterleaved)\r
+ {\r
+ user_buffer += processed_size;\r
+ }\r
+ else\r
+ {\r
+ for (i = 0; i < stream->bufferProcessor.inputChannelCount; ++i)\r
+ ((BYTE **)user_buffer)[i] = ((BYTE **)user_buffer)[i] + processed_size;\r
+ }\r
+\r
+ // Release host buffer\r
+ if ((hr = IAudioCaptureClient_ReleaseBuffer(stream->cclient, processed)) != S_OK)\r
{\r
LogHostError(hr);\r
goto stream_rd_end;\r
}\r
\r
- _frames -= frames;\r
+ _frames -= processed;\r
}\r
\r
stream_rd_end:\r
PaWasapiStream *stream = (PaWasapiStream*)s;\r
\r
UINT32 frames;\r
- const BYTE *buffer = (BYTE *)_buffer;\r
- BYTE *data;\r
+ const BYTE *user_buffer = (const BYTE *)_buffer;\r
+ BYTE *wasapi_buffer;\r
HRESULT hr = S_OK;\r
UINT32 next_rev_sleep, blocks, block_sleep_ms;\r
UINT32 i;\r
Sleep(stream->out.prevSleep);\r
stream->out.prevSleep = next_rev_sleep;\r
\r
+ // make a local copy of the user buffer pointer(s), this is necessary\r
+ // because PaUtil_CopyOutput() advances these pointers every time it is called\r
+ if (!stream->bufferProcessor.userOutputIsInterleaved)\r
+ {\r
+ user_buffer = (const BYTE *)alloca(sizeof(const BYTE *) * stream->bufferProcessor.outputChannelCount);\r
+ if (user_buffer == NULL)\r
+ return paInsufficientMemory;\r
+\r
+ for (i = 0; i < stream->bufferProcessor.outputChannelCount; ++i)\r
+ ((const BYTE **)user_buffer)[i] = ((const BYTE **)_buffer)[i];\r
+ }\r
+\r
// Feed engine\r
for (i = 0; i < blocks; ++i)\r
{\r
- UINT32 available;\r
- UINT32 buffer_size;\r
+ UINT32 available, processed;\r
\r
// Get block frames\r
frames = stream->out.framesPerHostCallback;\r
while (frames != 0)\r
{\r
UINT32 padding = 0;\r
+ UINT32 processed_size;\r
\r
// Check if blocking call must be interrupted\r
if (WaitForSingleObject(stream->hCloseRequest, 0) != WAIT_TIMEOUT)\r
goto stream_wr_end;\r
}\r
\r
- // Get frames available\r
+ // Calculate frames available\r
if (frames >= padding)\r
available = frames - padding;\r
else\r
available = frames;\r
\r
- // Get buffer\r
- if ((hr = IAudioRenderClient_GetBuffer(stream->rclient, available, &data)) != S_OK)\r
+ // Get pointer to host buffer\r
+ if ((hr = IAudioRenderClient_GetBuffer(stream->rclient, available, &wasapi_buffer)) != S_OK)\r
{\r
// Buffer size is too big, waiting\r
if (hr == AUDCLNT_E_BUFFER_TOO_LARGE)\r
goto stream_wr_end;\r
}\r
\r
- // Copy\r
- buffer_size = available * stream->out.wavex.Format.nBlockAlign;\r
- memcpy(data, buffer, buffer_size);\r
- buffer += buffer_size;\r
+ // Register available frames to processor\r
+ PaUtil_SetOutputFrameCount(&stream->bufferProcessor, available);\r
+ \r
+ // Register host buffer pointer to processor\r
+ PaUtil_SetInterleavedOutputChannels(&stream->bufferProcessor, 0, wasapi_buffer, stream->bufferProcessor.outputChannelCount);\r
+ \r
+ // Copy user data to host buffer (with conversion if applicable)\r
+ processed = PaUtil_CopyOutput(&stream->bufferProcessor, (const void **)&user_buffer, available);\r
+\r
+ // Advance user buffer to consumed portion\r
+ processed_size = processed * stream->out.wavex.Format.nBlockAlign;\r
+ if (stream->bufferProcessor.userOutputIsInterleaved)\r
+ {\r
+ user_buffer += processed_size;\r
+ }\r
+ else\r
+ {\r
+ for (i = 0; i < stream->bufferProcessor.outputChannelCount; ++i)\r
+ ((const BYTE **)user_buffer)[i] = ((const BYTE **)user_buffer)[i] + processed_size;\r
+ }\r
\r
- // Release buffer\r
- if ((hr = IAudioRenderClient_ReleaseBuffer(stream->rclient, available, 0)) != S_OK)\r
+ // Release host buffer\r
+ if ((hr = IAudioRenderClient_ReleaseBuffer(stream->rclient, processed, 0)) != S_OK)\r
{\r
LogHostError(hr);\r
goto stream_wr_end;\r
}\r
\r
- frames -= available;\r
+ // Deduct frames\r
+ frames -= processed;\r
}\r
\r
_frames -= frames;\r