Skip to content
This repository was archived by the owner on Feb 15, 2024. It is now read-only.

Commit a19308b

Browse files
committed
small refactor, do more sanity checks
1 parent 7e2aeea commit a19308b

File tree

3 files changed

+108
-74
lines changed

3 files changed

+108
-74
lines changed
File renamed without changes.

mono-to-stereo/mono-to-stereo.cpp

+107-73
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include "common.h"
44

55
HRESULT LoopbackCapture(
6-
IMMDevice *pMMInDevice,
7-
IMMDevice *pMMOutDevice,
6+
IMMDevice* pMMInDevice,
7+
IMMDevice* pMMOutDevice,
88
int iBufferMs,
99
bool bSwapChannels,
1010
HANDLE hStartedEvent,
@@ -13,7 +13,7 @@ HRESULT LoopbackCapture(
1313
);
1414

1515
DWORD WINAPI LoopbackCaptureThreadFunction(LPVOID pContext) {
16-
LoopbackCaptureThreadFunctionArguments *pArgs =
16+
LoopbackCaptureThreadFunctionArguments* pArgs =
1717
(LoopbackCaptureThreadFunctionArguments*)pContext;
1818

1919
pArgs->hr = CoInitialize(NULL);
@@ -36,7 +36,12 @@ DWORD WINAPI LoopbackCaptureThreadFunction(LPVOID pContext) {
3636
return 0;
3737
}
3838

39-
void swapMemcpy(void *_dst, void *_src, size_t size, size_t chunkSize) {
39+
void swapMemcpy(void* _dst, const void* _src, size_t size, bool doSwap, size_t chunkSize) {
40+
if (!doSwap) {
41+
memcpy(_dst, _src, size);
42+
return;
43+
}
44+
4045
size_t blockSize = chunkSize * 2;
4146

4247
if (size % blockSize != 0) {
@@ -45,7 +50,7 @@ void swapMemcpy(void *_dst, void *_src, size_t size, size_t chunkSize) {
4550
}
4651

4752
BYTE* dst = (BYTE*)_dst;
48-
BYTE* src = (BYTE*)_src;
53+
const BYTE* src = (BYTE*)_src;
4954

5055
for (size_t i = 0; i < size / blockSize; i++) {
5156
memcpy(dst + i * blockSize, src + i * blockSize + chunkSize, chunkSize);
@@ -54,8 +59,8 @@ void swapMemcpy(void *_dst, void *_src, size_t size, size_t chunkSize) {
5459
}
5560

5661
HRESULT LoopbackCapture(
57-
IMMDevice *pMMInDevice,
58-
IMMDevice *pMMOutDevice,
62+
IMMDevice* pMMInDevice,
63+
IMMDevice* pMMOutDevice,
5964
int iBufferMs,
6065
bool bSwapChannels,
6166
HANDLE hStartedEvent,
@@ -65,7 +70,7 @@ HRESULT LoopbackCapture(
6570
HRESULT hr;
6671

6772
// activate an IAudioClient
68-
IAudioClient *pAudioClient;
73+
IAudioClient* pAudioClient;
6974
hr = pMMInDevice->Activate(
7075
__uuidof(IAudioClient),
7176
CLSCTX_ALL, NULL,
@@ -86,7 +91,7 @@ HRESULT LoopbackCapture(
8691
}
8792

8893
// get the default device format
89-
WAVEFORMATEX *pwfx;
94+
WAVEFORMATEX* pwfx;
9095
hr = pAudioClient->GetMixFormat(&pwfx);
9196
if (FAILED(hr)) {
9297
ERR(L"IAudioClient::GetMixFormat failed: hr = 0x%08x", hr);
@@ -96,7 +101,21 @@ HRESULT LoopbackCapture(
96101

97102
if (pwfx->nChannels != 1) {
98103
ERR(L"device doesn't have 1 channel, has %d", pwfx->nChannels);
99-
return hr;
104+
return E_UNEXPECTED;
105+
}
106+
107+
if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
108+
auto pwfxExtensible = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(pwfx);
109+
if (!IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pwfxExtensible->SubFormat) && !IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pwfxExtensible->SubFormat)) {
110+
OLECHAR subFormatGUID[39];
111+
StringFromGUID2(pwfxExtensible->SubFormat, subFormatGUID, _countof(subFormatGUID));
112+
ERR(L"extensible input format not PCM, got %s", subFormatGUID);
113+
return E_UNEXPECTED;
114+
}
115+
}
116+
else if (pwfx->wFormatTag != WAVE_FORMAT_PCM && pwfx->wFormatTag != WAVE_FORMAT_IEEE_FLOAT) {
117+
ERR(L"input format not PCM, got %d", pwfx->wFormatTag);
118+
return E_UNEXPECTED;
100119
}
101120

102121
pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
@@ -116,7 +135,7 @@ HRESULT LoopbackCapture(
116135
}
117136

118137
// activate an IAudioCaptureClient
119-
IAudioCaptureClient *pAudioCaptureClient;
138+
IAudioCaptureClient* pAudioCaptureClient;
120139
hr = pAudioClient->GetService(
121140
__uuidof(IAudioCaptureClient),
122141
(void**)&pAudioCaptureClient
@@ -161,9 +180,10 @@ HRESULT LoopbackCapture(
161180
pwfx->nChannels *= 2;
162181
pwfx->nSamplesPerSec /= 2;
163182
pwfx->nBlockAlign *= 2;
183+
UINT32 OutputBlockAlign = pwfx->nBlockAlign;
164184

165185
// set up output device
166-
IAudioClient *pAudioOutClient;
186+
IAudioClient* pAudioOutClient;
167187
hr = pMMOutDevice->Activate(
168188
__uuidof(IAudioClient), CLSCTX_ALL,
169189
NULL, (void**)&pAudioOutClient);
@@ -175,7 +195,7 @@ HRESULT LoopbackCapture(
175195
hr = pAudioOutClient->Initialize(
176196
AUDCLNT_SHAREMODE_SHARED,
177197
0,
178-
(REFERENCE_TIME)iBufferMs * 10000,
198+
static_cast<REFERENCE_TIME>(iBufferMs) * 10000,
179199
0,
180200
pwfx,
181201
NULL);
@@ -184,7 +204,7 @@ HRESULT LoopbackCapture(
184204
return hr;
185205
}
186206

187-
IAudioRenderClient *pRenderClient;
207+
IAudioRenderClient* pRenderClient;
188208
hr = pAudioOutClient->GetService(
189209
__uuidof(IAudioRenderClient),
190210
(void**)&pRenderClient);
@@ -197,8 +217,8 @@ HRESULT LoopbackCapture(
197217
return hr;
198218
}
199219

200-
// Grab the entire buffer for the initial fill operation.
201-
BYTE *tmp;
220+
// Grab half the buffer for the initial fill operation.
221+
BYTE* tmp;
202222
hr = pRenderClient->GetBuffer(clientBufferFrameCount / 2, &tmp);
203223
if (FAILED(hr)) {
204224
ERR(L"IAudioClient::GetBuffer failed (output): hr = 0x%08x", hr);
@@ -242,75 +262,89 @@ HRESULT LoopbackCapture(
242262
return E_UNEXPECTED;
243263
}
244264

245-
// get the captured data
246-
BYTE *pData;
247-
BYTE *pOutData;
248-
UINT32 nNumFramesToRead;
249-
DWORD dwFlags;
250-
251-
hr = pAudioCaptureClient->GetBuffer(
252-
&pData,
253-
&nNumFramesToRead,
254-
&dwFlags,
255-
NULL,
256-
NULL
257-
);
258-
if (FAILED(hr)) {
259-
ERR(L"IAudioCaptureClient::GetBuffer failed after %u frames: hr = 0x%08x", *pnFrames, hr);
260-
return hr;
261-
}
265+
for (;;) {
266+
// get the captured data
267+
BYTE* pData;
268+
BYTE* pOutData;
269+
UINT32 nNextPacketSize;
270+
UINT32 nNumFramesToRead;
271+
DWORD dwFlags;
272+
273+
hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize);
274+
if (FAILED(hr)) {
275+
ERR(L"IAudioCaptureClient::GetNextPacketSize failed after %u frames: hr = 0x%08x", *pnFrames, hr);
276+
return hr;
277+
}
262278

263-
if (AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY == dwFlags) {
264-
LOG(L"Probably spurious glitch reported after %u frames", *pnFrames);
265-
}
266-
else if (0 != dwFlags) {
267-
LOG(L"IAudioCaptureClient::GetBuffer set flags to 0x%08x after %u frames", dwFlags, *pnFrames);
268-
return E_UNEXPECTED;
269-
}
279+
if (nNextPacketSize == 0) {
280+
break;
281+
}
282+
283+
hr = pAudioCaptureClient->GetBuffer(
284+
&pData,
285+
&nNumFramesToRead,
286+
&dwFlags,
287+
NULL,
288+
NULL
289+
);
290+
if (FAILED(hr)) {
291+
ERR(L"IAudioCaptureClient::GetBuffer failed after %u frames: hr = 0x%08x", *pnFrames, hr);
292+
return hr;
293+
}
270294

271-
nNumFramesToRead &= ~1;
295+
if (nNextPacketSize != nNumFramesToRead) {
296+
ERR(L"GetNextPacketSize and GetBuffer values don't match (%u and %u) after %u frames", nNextPacketSize, nNumFramesToRead, *pnFrames);
297+
return E_UNEXPECTED;
298+
}
272299

273-
if (0 == nNumFramesToRead) {
274-
LOG(L"IAudioCaptureClient::GetBuffer said to read 0 frames after %u frames", *pnFrames);
275-
continue;
276-
}
300+
if (AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY == dwFlags) {
301+
if (*pnFrames != 0) {
302+
LOG(L"Probably spurious glitch reported after %u frames", *pnFrames);
303+
}
304+
}
305+
else if (0 != dwFlags) {
306+
LOG(L"IAudioCaptureClient::GetBuffer set flags to 0x%08x after %u frames", dwFlags, *pnFrames);
307+
return E_UNEXPECTED;
308+
}
277309

278-
LONG lBytesToWrite = nNumFramesToRead * nBlockAlign;
310+
if (nNumFramesToRead % 1 != 0) {
311+
ERR("frames to output is odd (%u), will miss the last sample after %u frames", nNumFramesToRead, *pnFrames);
312+
}
279313

280-
for (;;) {
281-
hr = pRenderClient->GetBuffer(nNumFramesToRead / 2, &pOutData);
282-
if (hr == AUDCLNT_E_BUFFER_TOO_LARGE) {
283-
ERR(L"%s", L"buffer overflow!");
284-
Sleep(1);
285-
continue;
314+
UINT32 output_frames_to_write = nNumFramesToRead / 2;
315+
316+
LONG lBytesToWrite = output_frames_to_write * OutputBlockAlign;
317+
318+
for (;;) {
319+
hr = pRenderClient->GetBuffer(output_frames_to_write, &pOutData);
320+
if (hr == AUDCLNT_E_BUFFER_TOO_LARGE) {
321+
ERR(L"%s", L"buffer overflow!");
322+
Sleep(1);
323+
continue;
324+
}
325+
if (FAILED(hr)) {
326+
ERR(L"IAudioCaptureClient::GetBuffer failed (output) after %u frames: hr = 0x%08x", *pnFrames, hr);
327+
return hr;
328+
}
329+
break;
286330
}
331+
332+
swapMemcpy(pOutData, pData, lBytesToWrite, bSwapChannels, nBlockAlign);
333+
334+
hr = pRenderClient->ReleaseBuffer(output_frames_to_write, 0);
287335
if (FAILED(hr)) {
288-
ERR(L"IAudioCaptureClient::GetBuffer failed (output) after %u frames: hr = 0x%08x", *pnFrames, hr);
336+
ERR(L"IAudioCaptureClient::ReleaseBuffer failed (output) after %u frames: hr = 0x%08x", *pnFrames, hr);
289337
return hr;
290338
}
291-
break;
292-
}
293-
294-
if (bSwapChannels) {
295-
swapMemcpy(pOutData, pData, lBytesToWrite, pwfx->wBitsPerSample / 8);
296-
}
297-
else {
298-
memcpy(pOutData, pData, lBytesToWrite);
299-
}
300339

301-
hr = pRenderClient->ReleaseBuffer(nNumFramesToRead / 2, 0);
302-
if (FAILED(hr)) {
303-
ERR(L"IAudioCaptureClient::ReleaseBuffer failed (output) after %u frames: hr = 0x%08x", *pnFrames, hr);
304-
return hr;
305-
}
340+
hr = pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
341+
if (FAILED(hr)) {
342+
ERR(L"IAudioCaptureClient::ReleaseBuffer failed after %u frames: hr = 0x%08x", *pnFrames, hr);
343+
return hr;
344+
}
306345

307-
hr = pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
308-
if (FAILED(hr)) {
309-
ERR(L"IAudioCaptureClient::ReleaseBuffer failed after %u frames: hr = 0x%08x", *pnFrames, hr);
310-
return hr;
346+
*pnFrames += nNumFramesToRead;
311347
}
312-
313-
*pnFrames += nNumFramesToRead;
314348
} // capture loop
315349

316350
return hr;

mono-to-stereo/mono-to-stereo.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// until the stop event is set
88
// any failures will be propagated back via hr
99

10-
#define VERSION L"0.2"
10+
#define VERSION L"0.3"
1111

1212
struct LoopbackCaptureThreadFunctionArguments {
1313
IMMDevice *pMMInDevice;

0 commit comments

Comments
 (0)