[PATCH 02/12] winecoreaudio: Add a temporary capture_resample syscall.
Andrew Eikum
aeikum at codeweavers.com
Tue Nov 23 09:22:12 CST 2021
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Tue, Nov 23, 2021 at 07:54:59AM +0000, Huw Davies wrote:
> 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, ¶ms);
> }
> @@ -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