diff --git a/hooks/audio/backends/wasapi/dummy_audio_client.cpp b/hooks/audio/backends/wasapi/dummy_audio_client.cpp index 4478ec5..c0dc7e0 100644 --- a/hooks/audio/backends/wasapi/dummy_audio_client.cpp +++ b/hooks/audio/backends/wasapi/dummy_audio_client.cpp @@ -79,6 +79,9 @@ HRESULT STDMETHODCALLTYPE DummyIAudioClient::Initialize( log_info("audio::wasapi", "... hnsPeriodicity : {}", hnsPeriodicity); print_format(pFormat); + log_info("audio::wasapi", "IAudioClient::Initialize forwarding format"); + copy_wave_format(&hooks::audio::FORMAT, pFormat); + CHECK_RESULT(this->backend->on_initialize( &ShareMode, &StreamFlags, diff --git a/hooks/audio/implementations/asio.cpp b/hooks/audio/implementations/asio.cpp index 36b1e1d..fe3877e 100644 --- a/hooks/audio/implementations/asio.cpp +++ b/hooks/audio/implementations/asio.cpp @@ -132,7 +132,7 @@ static SampleType convert_asio_sample_type(AsioSampleType type) { } } -AsioBackend::AsioBackend() { +AsioBackend::AsioBackend() : format_(hooks::audio::FORMAT) { this->asio_thread = std::thread([this]() { std::unique_lock lock_handle(this->asio_thread_state_lock); @@ -750,7 +750,6 @@ HRESULT AsioBackend::on_initialize( { AsioError result; - copy_wave_format(&this->format_, pFormat); memcpy(&this->last_checked_format, &this->format_, sizeof(this->format_)); if (!this->asio_thread_initialized) { diff --git a/hooks/audio/implementations/asio.h b/hooks/audio/implementations/asio.h index 5670a6b..5b9ef3e 100644 --- a/hooks/audio/implementations/asio.h +++ b/hooks/audio/implementations/asio.h @@ -144,7 +144,7 @@ private: SampleType asio_sample_type = SampleType::UNSUPPORTED; std::atomic_bool started = false; - WAVEFORMATEXTENSIBLE format_ {}; + const WAVEFORMATEXTENSIBLE &format_; WAVEFORMATEXTENSIBLE last_checked_format {}; //std::vector last_sound_buffer; diff --git a/hooks/audio/implementations/wave_out.cpp b/hooks/audio/implementations/wave_out.cpp index cee1697..f4f54cc 100644 --- a/hooks/audio/implementations/wave_out.cpp +++ b/hooks/audio/implementations/wave_out.cpp @@ -3,26 +3,34 @@ #include "hooks/audio/audio.h" #include "hooks/audio/backends/wasapi/audio_client.h" #include "hooks/audio/backends/wasapi/defs.h" +#include "hooks/audio/util.h" +#include "hooks/audio/buffer.h" static REFERENCE_TIME WASAPI_TARGET_REFTIME = TARGET_REFTIME; HRESULT WaveOutBackend::init(uint32_t buffer_size) { - auto &format = hooks::audio::FORMAT.Format; - format.wFormatTag = WAVE_FORMAT_PCM; + MMRESULT ret; - log_info("audio::wave_out", "initializing waveOut backend with {} channels, {} Hz, {}-bit", - format.nChannels, - format.nSamplesPerSec, - format.wBitsPerSample); - log_info("audio::wave_out", "... nBlockAlign : {} bytes", format.nBlockAlign); - log_info("audio::wave_out", "... nAvgBytesPerSec : {} bytes", format.nAvgBytesPerSec); + if (format_.Format.nSamplesPerSec == 0) + { + log_warning("audio::wave_out", "format_ condition race"); + return static_cast(MMSYSERR_ERROR); + } + hooks::audio::FORMAT.Format.wFormatTag = WAVE_FORMAT_PCM; + log_info("audio::wave_out", "initializing waveOut backend with {} channels, {} Hz, {}-bit, {} format", + format_.Format.nChannels, + format_.Format.nSamplesPerSec, + format_.Format.wBitsPerSample, + format_.Format.wFormatTag); + log_info("audio::wave_out", "... nBlockAlign : {} bytes", format_.Format.nBlockAlign); + log_info("audio::wave_out", "... nAvgBytesPerSec : {} bytes", format_.Format.nAvgBytesPerSec); log_info("audio::wave_out", "... buffer reftime : {} ms", WASAPI_TARGET_REFTIME / 10000.f); log_info("audio::wave_out", "... buffer count : {} buffers", _countof(this->hdrs)); - MMRESULT ret = waveOutOpen( + ret = waveOutOpen( &this->handle, WAVE_MAPPER, - reinterpret_cast(&hooks::audio::FORMAT.Format), + reinterpret_cast(&format_.Format), reinterpret_cast(this->dispatcher_event), reinterpret_cast(nullptr), CALLBACK_EVENT); @@ -35,6 +43,7 @@ HRESULT WaveOutBackend::init(uint32_t buffer_size) { } // initialize buffers + log_info("audio::wave_out", "... device handle : {}", fmt::ptr(this->handle)); for (auto &hdr : this->hdrs) { memset(&hdr, 0, sizeof(hdr)); hdr.lpData = new char[buffer_size] {}; @@ -70,7 +79,7 @@ HRESULT WaveOutBackend::init(uint32_t buffer_size) { } const WAVEFORMATEXTENSIBLE &WaveOutBackend::format() const noexcept { - return hooks::audio::FORMAT; + return format_; } HRESULT WaveOutBackend::on_initialize( @@ -89,6 +98,8 @@ HRESULT WaveOutBackend::on_initialize( *hnsBufferDuration = WASAPI_TARGET_REFTIME; *hnsPeriodicity = WASAPI_TARGET_REFTIME; + log_info("audio::wave_out", "on_initialize"); + // this backend only supports stereo audio if (pFormat->nChannels > 2) { return AUDCLNT_E_UNSUPPORTED_FORMAT; @@ -115,7 +126,7 @@ HRESULT WaveOutBackend::on_get_current_padding(std::optional &padding_ } } - auto frames = static_cast(queued_bytes / hooks::audio::FORMAT.Format.nBlockAlign); + auto frames = static_cast(queued_bytes / format_.Format.nBlockAlign); //log_info("audio::wave_out", "queued_bytes = {}, frames = {}", queued_bytes, frames); padding_frames = frames; @@ -136,6 +147,7 @@ HRESULT WaveOutBackend::on_is_format_supported( return S_OK; } + //return waveOutOpen(nullptr, WAVE_MAPPER, reinterpret_cast(&format_.Format), NULL, NULL, WAVE_FORMAT_QUERY) == MMSYSERR_NOERROR ? S_OK : AUDCLNT_E_UNSUPPORTED_FORMAT; return AUDCLNT_E_UNSUPPORTED_FORMAT; } HRESULT WaveOutBackend::on_get_mix_format(WAVEFORMATEX **pp_device_format) noexcept { @@ -166,17 +178,20 @@ HRESULT WaveOutBackend::on_set_event_handle(HANDLE *event_handle) { } HRESULT WaveOutBackend::on_get_buffer(uint32_t num_frames_requested, BYTE **ppData) { - auto buffer_size = hooks::audio::FORMAT.Format.nBlockAlign * num_frames_requested; + size_t buffer_size = format_.Format.nBlockAlign * num_frames_requested; if (!this->initialized) { this->init(buffer_size); } + const size_t converted_size = required_buffer_size(num_frames_requested, format_.Format.nChannels, SampleType::SINT_16); + const size_t max_size = std::max(buffer_size, converted_size); + // wait for a free slot WaitForSingleObject(this->dispatcher_event, INFINITE); // allocate temporary sound buffer - this->active_sound_buffer = reinterpret_cast(CoTaskMemAlloc(buffer_size)); + this->active_sound_buffer = reinterpret_cast(CoTaskMemAlloc(max_size)); // hand the buffer to the callee *ppData = this->active_sound_buffer; @@ -222,3 +237,7 @@ HRESULT WaveOutBackend::on_release_buffer(uint32_t num_frames_written, DWORD dwF return S_OK; } +WaveOutBackend::WaveOutBackend() : format_(hooks::audio::FORMAT) +{ + +} diff --git a/hooks/audio/implementations/wave_out.h b/hooks/audio/implementations/wave_out.h index 09ed876..58b79ad 100644 --- a/hooks/audio/implementations/wave_out.h +++ b/hooks/audio/implementations/wave_out.h @@ -10,6 +10,7 @@ struct WaveOutBackend final : AudioBackend { public: + explicit WaveOutBackend(); ~WaveOutBackend() final = default; HRESULT init(uint32_t buffer_size); @@ -49,6 +50,7 @@ public: private: WrappedIAudioClient *client; + const WAVEFORMATEXTENSIBLE &format_; bool initialized = false; HANDLE relay_event = nullptr; HANDLE dispatcher_event = nullptr;