From d1d186eef20f4960b32f1f0d1b7df41726b43792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20K=C3=B6lbl?= Date: Wed, 18 May 2022 18:47:30 +0200 Subject: [PATCH] windows.media.speech: Store recorded audio in a temporary ringbuffer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernhard Kölbl --- dlls/windows.media.speech/recognizer.c | 34 +++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/dlls/windows.media.speech/recognizer.c b/dlls/windows.media.speech/recognizer.c index 72c08a1b06c..c2f386206b8 100644 --- a/dlls/windows.media.speech/recognizer.c +++ b/dlls/windows.media.speech/recognizer.c @@ -192,9 +192,10 @@ static DWORD CALLBACK session_worker_thread_cb( void *args ) ISpeechContinuousRecognitionSession *iface = args; struct session *impl = impl_from_ISpeechContinuousRecognitionSession(iface); BOOLEAN running = TRUE, paused = FALSE; + UINT32 frame_count, tmp_buf_size; + BYTE *audio_buf, *tmp_buf; DWORD flags, status; HANDLE events[2]; - BYTE *audio_buf; HRESULT hr; SetThreadDescription(GetCurrentThread(), L"wine_speech_recognition_session_worker"); @@ -202,6 +203,16 @@ static DWORD CALLBACK session_worker_thread_cb( void *args ) if (FAILED(hr = IAudioClient_Start(impl->audio_client))) goto error; + if (FAILED(hr = IAudioClient_GetBufferSize(impl->audio_client, &frame_count))) + goto error; + + tmp_buf_size = sizeof(*tmp_buf) * frame_count * impl->capture_wfx.nBlockAlign; + if (!(tmp_buf = malloc(tmp_buf_size))) + { + ERR("Memory allocation failed.\n"); + return 1; + } + while (running) { BOOLEAN old_paused = paused; @@ -232,13 +243,28 @@ static DWORD CALLBACK session_worker_thread_cb( void *args ) } else if (status == 1) /* audio_buf_event signaled */ { + SIZE_T packet_size = 0, tmp_buf_offset = 0; UINT32 frames_available = 0; - while (IAudioCaptureClient_GetBuffer(impl->capture_client, &audio_buf, &frames_available, &flags, NULL, NULL) == S_OK) + while (tmp_buf_offset < tmp_buf_size + && IAudioCaptureClient_GetBuffer(impl->capture_client, &audio_buf, &frames_available, &flags, NULL, NULL) == S_OK) { - /* TODO: Send mic data to recognizer and handle results. */ + packet_size = frames_available * impl->capture_wfx.nBlockAlign; + if (tmp_buf_offset + packet_size > tmp_buf_size) + { + /* Defer processing until the next iteration of the worker loop. */ + IAudioCaptureClient_ReleaseBuffer(impl->capture_client, 0); + SetEvent(impl->audio_buf_event); + break; + } + + memcpy(tmp_buf + tmp_buf_offset, audio_buf, packet_size); + tmp_buf_offset += packet_size; + IAudioCaptureClient_ReleaseBuffer(impl->capture_client, frames_available); } + + /* TODO: Send mic data to recognizer and handle results. */ } else { @@ -253,6 +279,8 @@ static DWORD CALLBACK session_worker_thread_cb( void *args ) if (FAILED(hr = IAudioClient_Reset(impl->audio_client))) ERR("IAudioClient_Reset failed with %#lx.\n", hr); + free(tmp_buf); + return 0; error: