[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, &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