[PATCH 02/12] winecoreaudio: Add a temporary capture_resample syscall.

Huw Davies huw at codeweavers.com
Tue Nov 23 01:54:59 CST 2021


Eventually everything that calls this will reside in the unixlib.

Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/winecoreaudio.drv/coreaudio.c | 105 +++++++++++++++++++++++++++++
 dlls/winecoreaudio.drv/mmdevdrv.c  | 102 +---------------------------
 dlls/winecoreaudio.drv/unixlib.h   |   2 +
 3 files changed, 108 insertions(+), 101 deletions(-)

diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
index f7f7777efcb..f1ab4cf7986 100644
--- a/dlls/winecoreaudio.drv/coreaudio.c
+++ b/dlls/winecoreaudio.drv/coreaudio.c
@@ -693,6 +693,7 @@ static NTSTATUS release_stream( void *args )
     }
 
     if(stream->converter) AudioConverterDispose(stream->converter);
+    free(stream->resamp_buffer);
     free(stream->wrap_buffer);
     free(stream->cap_buffer);
     if(stream->local_buffer)
@@ -1012,6 +1013,108 @@ unsupported:
     return STATUS_SUCCESS;
 }
 
+static UINT buf_ptr_diff(UINT left, UINT right, UINT bufsize)
+{
+    if(left <= right)
+        return right - left;
+    return bufsize - (left - right);
+}
+
+/* place data from cap_buffer into provided AudioBufferList */
+static OSStatus feed_cb(AudioConverterRef converter, UInt32 *nframes, AudioBufferList *data,
+                        AudioStreamPacketDescription **packets, void *user)
+{
+    struct coreaudio_stream *stream = user;
+
+    *nframes = min(*nframes, stream->cap_held_frames);
+    if(!*nframes){
+        data->mBuffers[0].mData = NULL;
+        data->mBuffers[0].mDataByteSize = 0;
+        data->mBuffers[0].mNumberChannels = stream->fmt->nChannels;
+        return noErr;
+    }
+
+    data->mBuffers[0].mDataByteSize = *nframes * stream->fmt->nBlockAlign;
+    data->mBuffers[0].mNumberChannels = stream->fmt->nChannels;
+
+    if(stream->cap_offs_frames + *nframes > stream->cap_bufsize_frames){
+        UINT32 chunk_frames = stream->cap_bufsize_frames - stream->cap_offs_frames;
+
+        if(stream->wrap_bufsize_frames < *nframes){
+            free(stream->wrap_buffer);
+            stream->wrap_buffer = malloc(data->mBuffers[0].mDataByteSize);
+            stream->wrap_bufsize_frames = *nframes;
+        }
+
+        memcpy(stream->wrap_buffer, stream->cap_buffer + stream->cap_offs_frames * stream->fmt->nBlockAlign,
+               chunk_frames * stream->fmt->nBlockAlign);
+        memcpy(stream->wrap_buffer + chunk_frames * stream->fmt->nBlockAlign, stream->cap_buffer,
+               (*nframes - chunk_frames) * stream->fmt->nBlockAlign);
+
+        data->mBuffers[0].mData = stream->wrap_buffer;
+    }else
+        data->mBuffers[0].mData = stream->cap_buffer + stream->cap_offs_frames * stream->fmt->nBlockAlign;
+
+    stream->cap_offs_frames += *nframes;
+    stream->cap_offs_frames %= stream->cap_bufsize_frames;
+    stream->cap_held_frames -= *nframes;
+
+    if(packets)
+        *packets = NULL;
+
+    return noErr;
+}
+
+static NTSTATUS capture_resample(void *args)
+{
+    struct coreaudio_stream *stream = args;
+    UINT32 resamp_period_frames = muldiv(stream->period_frames, stream->dev_desc.mSampleRate,
+                                         stream->fmt->nSamplesPerSec);
+    OSStatus sc;
+
+    /* the resampling process often needs more source frames than we'd
+     * guess from a straight conversion using the sample rate ratio. so
+     * only convert if we have extra source data. */
+    while(stream->cap_held_frames > resamp_period_frames * 2){
+        AudioBufferList converted_list;
+        UInt32 wanted_frames = stream->period_frames;
+
+        converted_list.mNumberBuffers = 1;
+        converted_list.mBuffers[0].mNumberChannels = stream->fmt->nChannels;
+        converted_list.mBuffers[0].mDataByteSize = wanted_frames * stream->fmt->nBlockAlign;
+
+        if(stream->resamp_bufsize_frames < wanted_frames){
+            free(stream->resamp_buffer);
+            stream->resamp_buffer = malloc(converted_list.mBuffers[0].mDataByteSize);
+            stream->resamp_bufsize_frames = wanted_frames;
+        }
+
+        converted_list.mBuffers[0].mData = stream->resamp_buffer;
+
+        sc = AudioConverterFillComplexBuffer(stream->converter, feed_cb,
+                                             stream, &wanted_frames, &converted_list, NULL);
+        if(sc != noErr){
+            WARN("AudioConverterFillComplexBuffer failed: %x\n", (int)sc);
+            break;
+        }
+
+        ca_wrap_buffer(stream->local_buffer,
+                       stream->wri_offs_frames * stream->fmt->nBlockAlign,
+                       stream->bufsize_frames * stream->fmt->nBlockAlign,
+                       stream->resamp_buffer, wanted_frames * stream->fmt->nBlockAlign);
+
+        stream->wri_offs_frames += wanted_frames;
+        stream->wri_offs_frames %= stream->bufsize_frames;
+        if(stream->held_frames + wanted_frames > stream->bufsize_frames){
+            stream->lcl_offs_frames += buf_ptr_diff(stream->lcl_offs_frames, stream->wri_offs_frames,
+                                                    stream->bufsize_frames);
+            stream->held_frames = stream->bufsize_frames;
+        }else
+            stream->held_frames += wanted_frames;
+    }
+    return STATUS_SUCCESS;
+}
+
 unixlib_entry_t __wine_unix_call_funcs[] =
 {
     get_endpoint_ids,
@@ -1019,4 +1122,6 @@ unixlib_entry_t __wine_unix_call_funcs[] =
     release_stream,
     get_mix_format,
     is_format_supported,
+
+    capture_resample /* temporary */
 };
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index 418bbfa00af..578312bf4ef 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -138,10 +138,6 @@ struct ACImpl {
 
     struct coreaudio_stream *stream;
     struct list entry;
-
-    /* Temporary */
-    BYTE *feed_wrap_buffer;
-    UINT32 feed_wrap_bufsize_frames;
 };
 
 static const IAudioClient3Vtbl AudioClient3_Vtbl;
@@ -581,7 +577,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
             if(This->stream->tmp_buffer)
                 NtFreeVirtualMemory(GetCurrentProcess(), (void **)&This->stream->tmp_buffer,
                                     &This->stream->tmp_buffer_size, MEM_RELEASE);
-            HeapFree(GetProcessHeap(), 0, This->stream->resamp_buffer);
             params.stream = This->stream;
             UNIX_CALL(release_stream, &params);
         }
@@ -591,7 +586,6 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
             LeaveCriticalSection(&g_sessions_lock);
         }
         HeapFree(GetProcessHeap(), 0, This->vols);
-        free(This->feed_wrap_buffer);
         IMMDevice_Release(This->parent);
         IUnknown_Release(This->pUnkFTMarshal);
         HeapFree(GetProcessHeap(), 0, This);
@@ -736,103 +730,9 @@ static void silence_buffer(struct coreaudio_stream *stream, BYTE *buffer, UINT32
         memset(buffer, 0, frames * stream->fmt->nBlockAlign);
 }
 
-static UINT buf_ptr_diff(UINT left, UINT right, UINT bufsize)
-{
-    if(left <= right)
-        return right - left;
-    return bufsize - (left - right);
-}
-
-/* place data from cap_buffer into provided AudioBufferList */
-static OSStatus feed_cb(AudioConverterRef converter, UInt32 *nframes, AudioBufferList *data,
-        AudioStreamPacketDescription **packets, void *user)
-{
-    ACImpl *This = user;
-
-    *nframes = min(*nframes, This->stream->cap_held_frames);
-    if(!*nframes){
-        data->mBuffers[0].mData = NULL;
-        data->mBuffers[0].mDataByteSize = 0;
-        data->mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
-        return noErr;
-    }
-
-    data->mBuffers[0].mDataByteSize = *nframes * This->stream->fmt->nBlockAlign;
-    data->mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
-
-    if(This->stream->cap_offs_frames + *nframes > This->stream->cap_bufsize_frames){
-        UINT32 chunk_frames = This->stream->cap_bufsize_frames - This->stream->cap_offs_frames;
-
-        if(This->feed_wrap_bufsize_frames < *nframes){
-            free(This->feed_wrap_buffer);
-            This->feed_wrap_buffer = malloc(data->mBuffers[0].mDataByteSize);
-            This->feed_wrap_bufsize_frames = *nframes;
-        }
-
-        memcpy(This->feed_wrap_buffer, This->stream->cap_buffer + This->stream->cap_offs_frames * This->stream->fmt->nBlockAlign,
-                chunk_frames * This->stream->fmt->nBlockAlign);
-        memcpy(This->feed_wrap_buffer + chunk_frames * This->stream->fmt->nBlockAlign, This->stream->cap_buffer,
-                (*nframes - chunk_frames) * This->stream->fmt->nBlockAlign);
-
-        data->mBuffers[0].mData = This->feed_wrap_buffer;
-    }else
-        data->mBuffers[0].mData = This->stream->cap_buffer + This->stream->cap_offs_frames * This->stream->fmt->nBlockAlign;
-
-    This->stream->cap_offs_frames += *nframes;
-    This->stream->cap_offs_frames %= This->stream->cap_bufsize_frames;
-    This->stream->cap_held_frames -= *nframes;
-
-    if(packets)
-        *packets = NULL;
-
-    return noErr;
-}
-
 static void capture_resample(ACImpl *This)
 {
-    UINT32 resamp_period_frames = MulDiv(This->stream->period_frames, This->stream->dev_desc.mSampleRate, This->stream->fmt->nSamplesPerSec);
-    OSStatus sc;
-
-    /* the resampling process often needs more source frames than we'd
-     * guess from a straight conversion using the sample rate ratio. so
-     * only convert if we have extra source data. */
-    while(This->stream->cap_held_frames > resamp_period_frames * 2){
-        AudioBufferList converted_list;
-        UInt32 wanted_frames = This->stream->period_frames;
-
-        converted_list.mNumberBuffers = 1;
-        converted_list.mBuffers[0].mNumberChannels = This->stream->fmt->nChannels;
-        converted_list.mBuffers[0].mDataByteSize = wanted_frames * This->stream->fmt->nBlockAlign;
-
-        if(This->stream->resamp_bufsize_frames < wanted_frames){
-            HeapFree(GetProcessHeap(), 0, This->stream->resamp_buffer);
-            This->stream->resamp_buffer = HeapAlloc(GetProcessHeap(), 0, converted_list.mBuffers[0].mDataByteSize);
-            This->stream->resamp_bufsize_frames = wanted_frames;
-        }
-
-        converted_list.mBuffers[0].mData = This->stream->resamp_buffer;
-
-        sc = AudioConverterFillComplexBuffer(This->stream->converter, feed_cb,
-                This, &wanted_frames, &converted_list, NULL);
-        if(sc != noErr){
-            WARN("AudioConverterFillComplexBuffer failed: %x\n", (int)sc);
-            break;
-        }
-
-        ca_wrap_buffer(This->stream->local_buffer,
-                This->stream->wri_offs_frames * This->stream->fmt->nBlockAlign,
-                This->stream->bufsize_frames * This->stream->fmt->nBlockAlign,
-                This->stream->resamp_buffer, wanted_frames * This->stream->fmt->nBlockAlign);
-
-        This->stream->wri_offs_frames += wanted_frames;
-        This->stream->wri_offs_frames %= This->stream->bufsize_frames;
-        if(This->stream->held_frames + wanted_frames > This->stream->bufsize_frames){
-            This->stream->lcl_offs_frames += buf_ptr_diff(This->stream->lcl_offs_frames,
-                    This->stream->wri_offs_frames, This->stream->bufsize_frames);
-            This->stream->held_frames = This->stream->bufsize_frames;
-        }else
-            This->stream->held_frames += wanted_frames;
-    }
+    UNIX_CALL(capture_resample, This->stream);
 }
 
 static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
index 23de92ecfdd..c1762c50e7e 100644
--- a/dlls/winecoreaudio.drv/unixlib.h
+++ b/dlls/winecoreaudio.drv/unixlib.h
@@ -100,6 +100,8 @@ enum unix_funcs
     unix_release_stream,
     unix_get_mix_format,
     unix_is_format_supported,
+
+    unix_capture_resample /* temporary */
 };
 
 extern unixlib_handle_t coreaudio_handle;
-- 
2.23.0




More information about the wine-devel mailing list