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;