From 1f5299ad1b535b94106300ca5f32606d398c7a1d Mon Sep 17 00:00:00 2001 From: Karutoh Date: Tue, 1 Oct 2024 18:58:15 -0700 Subject: [PATCH] Fixed Win32 audio. --- include/ehs/io/audio/AudioDevice_W32.h | 10 +- src/io/audio/AudioDevice_W32.cpp | 177 +++++++++++++++---------- 2 files changed, 109 insertions(+), 78 deletions(-) diff --git a/include/ehs/io/audio/AudioDevice_W32.h b/include/ehs/io/audio/AudioDevice_W32.h index cefa13c..a7cdda6 100644 --- a/include/ehs/io/audio/AudioDevice_W32.h +++ b/include/ehs/io/audio/AudioDevice_W32.h @@ -37,11 +37,9 @@ namespace ehs void CloseStream() override; - UInt_64 GetAvailFrames() const override; + UInt_64 SendStream(const void *data, UInt_64 outFrameSize) override; - Byte* Map(UInt_64* offset, UInt_64* frames) override; - - void UnMap(const UInt_64 offset, const UInt_64 frames) override; + UInt_64 ReceiveStream(void *data, UInt_64 inFrameSize) override; Str_32 GetInterfaceName_32() const; @@ -59,8 +57,8 @@ namespace ehs bool IsValid() const override; - static AudioDevice GetDefault(const AudioDeviceType type); + static AudioDevice GetDefault(AudioDeviceType type); - static Array Get(const AudioDeviceType type, const AudioDeviceState state); + static Array Get(AudioDeviceType type, AudioDeviceState state); }; } diff --git a/src/io/audio/AudioDevice_W32.cpp b/src/io/audio/AudioDevice_W32.cpp index 7e751f4..b26f3d8 100644 --- a/src/io/audio/AudioDevice_W32.cpp +++ b/src/io/audio/AudioDevice_W32.cpp @@ -70,7 +70,7 @@ namespace ehs void AudioDevice::OpenStream() { - if (streaming) + if (IsStreaming()) return; HRESULT r = hdl->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&client); @@ -80,14 +80,14 @@ namespace ehs WAVEFORMATEXTENSIBLE* format; client->GetMixFormat((WAVEFORMATEX**)&format); - if (bitDepth) + if (byteDepth) { if (dataType == DataType::FLOAT) format->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; else format->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - format->Format.wBitsPerSample = bitDepth; + format->Format.wBitsPerSample = byteDepth * 8; } else { @@ -96,7 +96,7 @@ namespace ehs else dataType = FromAudioBitDepth(format->Format.wBitsPerSample); - bitDepth = format->Format.wBitsPerSample; + byteDepth = format->Format.wBitsPerSample / 8; } if (sampleRate) @@ -109,7 +109,7 @@ namespace ehs else channels = format->Format.nChannels; - format->Format.nBlockAlign = bitDepth / 8 * channels; + format->Format.nBlockAlign = byteDepth * channels; format->Format.nAvgBytesPerSec = format->Format.nBlockAlign * sampleRate; WAVEFORMATEX* match = {}; @@ -265,7 +265,7 @@ namespace ehs return; } - streaming = true; + EHS_LOG_SUCCESS(); } void AudioDevice::CloseStream() @@ -300,95 +300,128 @@ namespace ehs hdl->Release(); hdl = nullptr; } + + EHS_LOG_SUCCESS(); } - UInt_64 AudioDevice::GetAvailFrames() const + UInt_64 AudioDevice::SendStream(const void *data, UInt_64 outFrameSize) { - if (!IsValid() || !IsStreaming()) + if (!IsValid() || !IsStreaming() || !playbackClient || !data || !outFrameSize) return 0; - UInt_32 sampleSize = 0; + UInt_32 frameOffset = 0; - if (playbackClient) + HRESULT r = client->GetCurrentPadding(&frameOffset); + if (r == AUDCLNT_E_DEVICE_INVALIDATED) { - HRESULT r = client->GetCurrentPadding(&sampleSize); - if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 0, "The audio device has been invalidated."); - else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve samples padding with error #" + Str_8::FromNum(r) + "."); - - sampleSize = maxFrames - sampleSize; + EHS_LOG_INT(LogType::WARN, 0, "The audio device has been invalidated."); + return 0; } - else if (captureClient) + else if (FAILED(r)) { - HRESULT r = captureClient->GetNextPacketSize(&sampleSize); - if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 0, "The audio device has been invalidated."); - else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve samples size with error #" + Str_8::FromNum(r) + "."); + EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve samples padding with error #" + Str_8::FromNum(r) + "."); + return 0; } - return sampleSize; + UInt_32 frameSize = maxFrames - frameOffset; + if (frameSize > outFrameSize) + frameSize = outFrameSize; + + Byte *buffer = nullptr; + + r = playbackClient->GetBuffer(frameSize, &buffer); + if (r == AUDCLNT_E_DEVICE_INVALIDATED) + { + EHS_LOG_INT(LogType::WARN, 2, "The audio device has been invalidated."); + return 0; + } + else if (FAILED(r)) + { + EHS_LOG_INT(LogType::ERR, 3, "Failed to retrieve buffer with error #" + Str_8::FromNum(r) + "."); + return 0; + } + + r = playbackClient->ReleaseBuffer(frameSize, 0); + if (r == AUDCLNT_E_DEVICE_INVALIDATED) + { + EHS_LOG_INT(LogType::WARN, 4, "The audio device has been invalidated."); + return 0; + } + else if (FAILED(r)) + { + EHS_LOG_INT(LogType::ERR, 5, "Failed to release buffer with error #" + Str_8::FromNum(r) + "."); + return 0; + } + + return frameSize; } - Byte* AudioDevice::Map(UInt_64* offset, UInt_64* frames) + UInt_64 AudioDevice::ReceiveStream(void *data, UInt_64 inFrameSize) { + if (!IsValid() || !IsStreaming() || !captureClient || !data || !inFrameSize) + return 0; + + UInt_32 frameSize = 0; + HRESULT r = captureClient->GetNextPacketSize(&frameSize); + if (r == AUDCLNT_E_DEVICE_INVALIDATED) + { + EHS_LOG_INT(LogType::WARN, 0, "The audio device has been invalidated."); + return 0; + } + else if (FAILED(r)) + { + EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve samples size with error #" + Str_8::FromNum(r) + "."); + return 0; + } + + if (frameSize > inFrameSize) + frameSize = inFrameSize; + + UInt_64 frameOffset = 0; + r = client->GetCurrentPadding((UINT32*)&frameOffset); + if (r == AUDCLNT_E_DEVICE_INVALIDATED) + { + EHS_LOG_INT(LogType::WARN, 2, "The audio device has been invalidated."); + return 0; + } + else if (FAILED(r)) + { + EHS_LOG_INT(LogType::ERR, 3, "Failed to retrieve samples padding with error #" + Str_8::FromNum(r) + "."); + return 0; + } + + UInt_32 flags = 0; Byte* buffer = nullptr; - if (!IsValid()) - return buffer; - - HRESULT r = client->GetCurrentPadding((UINT32*)&offset); + r = captureClient->GetBuffer(&buffer, (UINT32*)&frameSize, (DWORD*)&flags, nullptr, nullptr); if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 0, "The audio device has been invalidated."); + { + EHS_LOG_INT(LogType::WARN, 4, "The audio device has been invalidated."); + return 0; + } else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve samples padding with error #" + Str_8::FromNum(r) + "."); - - if (playbackClient) { - r = playbackClient->GetBuffer(*frames, &buffer); - if (r == AUDCLNT_E_BUFFER_TOO_LARGE) - EHS_LOG_INT(LogType::ERR, 0, "The given frame size, " + Str_8::FromNum(*frames) + ", must be less than or equal to, " + Str_8::FromNum(maxFrames - *offset) + "."); - else if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 1, "The audio device has been invalidated."); - else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 2, "Failed to retrieve buffer with error #" + Str_8::FromNum(r) + "."); - } - else if (captureClient) - { - UInt_32 flags = 0; - - r = captureClient->GetBuffer(&buffer, (UINT32*)frames, (DWORD*)&flags, nullptr, nullptr); - if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 1, "The audio device has been invalidated."); - else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 2, "Failed to retrieve buffer with error #" + Str_8::FromNum(r) + "."); + EHS_LOG_INT(LogType::ERR, 5, "Failed to retrieve buffer with error #" + Str_8::FromNum(r) + "."); + return 0; } - return buffer; - } + Util::Copy(data, &buffer[frameOffset], frameSize * byteDepth * channels); - void AudioDevice::UnMap(const UInt_64 offset, const UInt_64 frames) - { - if (!IsValid() || !streaming) - return; + r = captureClient->ReleaseBuffer(frameSize); + if (r == AUDCLNT_E_DEVICE_INVALIDATED) + { + EHS_LOG_INT(LogType::WARN, 6, "The audio device has been invalidated."); + return 0; + } + else if (FAILED(r)) + { + EHS_LOG_INT(LogType::ERR, 7, "Failed to release buffer with error #" + Str_8::FromNum(r) + "."); + return 0; + } - if (playbackClient) - { - HRESULT r = playbackClient->ReleaseBuffer(frames, 0); - if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 0, "The audio device has been invalidated."); - else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 1, "Failed to release buffer with error #" + Str_8::FromNum(r) + "."); - } - else if (captureClient) - { - HRESULT r = captureClient->ReleaseBuffer(frames); - if (r == AUDCLNT_E_DEVICE_INVALIDATED) - EHS_LOG_INT(LogType::ERR, 0, "The audio device has been invalidated."); - else if (FAILED(r)) - EHS_LOG_INT(LogType::ERR, 1, "Failed to release buffer with error #" + Str_8::FromNum(r) + "."); - } + EHS_LOG_SUCCESS(); + + return frameSize; } Str_32 AudioDevice::GetInterfaceName_32() const