Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/extern
diff options
context:
space:
mode:
authorJörg Müller <nexyon@gmail.com>2021-07-01 15:24:06 +0300
committerJörg Müller <nexyon@gmail.com>2021-07-01 15:26:13 +0300
commit19d19970e4fa6a738010dfeb2b08886f4a3dd0d5 (patch)
treef1f976871deb4088bed9236952253365512c631c /extern
parent8c3855dc6e9b2f6e76953384b4aab4ea3ab987ff (diff)
Fix T88887: Audio causes issues with Playback when PC put to Sleep, Hibernate or when Screensaver appears
Porting WASAPI device reinitialization from upstream.
Diffstat (limited to 'extern')
-rw-r--r--extern/audaspace/include/devices/SoftwareDevice.h6
-rw-r--r--extern/audaspace/include/respec/Mixer.h6
-rw-r--r--extern/audaspace/plugins/wasapi/WASAPIDevice.cpp197
-rw-r--r--extern/audaspace/plugins/wasapi/WASAPIDevice.h5
-rw-r--r--extern/audaspace/src/devices/SoftwareDevice.cpp22
-rw-r--r--extern/audaspace/src/respec/Mixer.cpp30
6 files changed, 182 insertions, 84 deletions
diff --git a/extern/audaspace/include/devices/SoftwareDevice.h b/extern/audaspace/include/devices/SoftwareDevice.h
index 209be9941b1..c3af5cfd902 100644
--- a/extern/audaspace/include/devices/SoftwareDevice.h
+++ b/extern/audaspace/include/devices/SoftwareDevice.h
@@ -266,6 +266,12 @@ protected:
void setSpecs(Specs specs);
/**
+ * Sets the audio output specification of the device.
+ * \param specs The output specification.
+ */
+ void setSpecs(DeviceSpecs specs);
+
+ /**
* Empty default constructor. To setup the device call the function create()
* and to uninitialize call destroy().
*/
diff --git a/extern/audaspace/include/respec/Mixer.h b/extern/audaspace/include/respec/Mixer.h
index 600467826cd..9880d5fdcae 100644
--- a/extern/audaspace/include/respec/Mixer.h
+++ b/extern/audaspace/include/respec/Mixer.h
@@ -88,6 +88,12 @@ public:
void setSpecs(Specs specs);
/**
+ * Sets the target specification for superposing.
+ * \param specs The target specification.
+ */
+ void setSpecs(DeviceSpecs specs);
+
+ /**
* Mixes a buffer.
* \param buffer The buffer to superpose.
* \param start The start sample of the buffer.
diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
index b4632ebb83e..a5382bb9692 100644
--- a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
+++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
@@ -31,65 +31,81 @@ template <class T> void SafeRelease(T **ppT)
}
}
-void WASAPIDevice::runMixingThread()
+HRESULT WASAPIDevice::setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size)
{
- UINT32 buffer_size;
+ const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
+
UINT32 padding;
UINT32 length;
data_t* buffer;
- IAudioRenderClient* render_client = nullptr;
+ HRESULT result;
- {
- std::lock_guard<ILockable> lock(*this);
+ if(FAILED(result = m_audio_client->GetBufferSize(&buffer_size)))
+ return result;
- const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
+ if(FAILED(result = m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
+ return result;
- if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
- goto init_error;
+ if(FAILED(result = m_audio_client->GetCurrentPadding(&padding)))
+ return result;
- if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
- goto init_error;
+ length = buffer_size - padding;
- if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
- goto init_error;
+ if(FAILED(result = render_client->GetBuffer(length, &buffer)))
+ return result;
- length = buffer_size - padding;
+ mix((data_t*)buffer, length);
- if(FAILED(render_client->GetBuffer(length, &buffer)))
- goto init_error;
+ if(FAILED(result = render_client->ReleaseBuffer(length, 0)))
+ return result;
- mix((data_t*)buffer, length);
+ m_audio_client->Start();
- if(FAILED(render_client->ReleaseBuffer(length, 0)))
- {
- init_error:
- SafeRelease(&render_client);
- doStop();
- return;
- }
- }
+ return result;
+}
- m_audio_client->Start();
+void WASAPIDevice::runMixingThread()
+{
+ UINT32 buffer_size;
+
+ IAudioRenderClient* render_client = nullptr;
+
+ std::chrono::milliseconds sleep_duration;
- auto sleepDuration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
+ bool run_init = true;
for(;;)
{
+ HRESULT result = S_OK;
+
{
+ UINT32 padding;
+ UINT32 length;
+ data_t* buffer;
std::lock_guard<ILockable> lock(*this);
- if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
+ if(run_init)
+ {
+ result = setupRenderClient(render_client, buffer_size);
+
+ if(FAILED(result))
+ goto stop_thread;
+
+ sleep_duration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
+ }
+
+ if(FAILED(result = m_audio_client->GetCurrentPadding(&padding)))
goto stop_thread;
length = buffer_size - padding;
- if(FAILED(render_client->GetBuffer(length, &buffer)))
+ if(FAILED(result = render_client->GetBuffer(length, &buffer)))
goto stop_thread;
mix((data_t*)buffer, length);
- if(FAILED(render_client->ReleaseBuffer(length, 0)))
+ if(FAILED(result = render_client->ReleaseBuffer(length, 0)))
goto stop_thread;
// stop thread
@@ -98,53 +114,51 @@ void WASAPIDevice::runMixingThread()
stop_thread:
m_audio_client->Stop();
SafeRelease(&render_client);
- doStop();
- return;
+
+ if(result == AUDCLNT_E_DEVICE_INVALIDATED)
+ {
+ DeviceSpecs specs = m_specs;
+ if(!setupDevice(specs))
+ result = S_FALSE;
+ else
+ {
+ setSpecs(specs);
+
+ run_init = true;
+ }
+ }
+
+ if(result != AUDCLNT_E_DEVICE_INVALIDATED)
+ {
+ doStop();
+ return;
+ }
}
}
- std::this_thread::sleep_for(sleepDuration);
+ std::this_thread::sleep_for(sleep_duration);
}
}
-WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
- m_imm_device_enumerator(nullptr),
- m_imm_device(nullptr),
- m_audio_client(nullptr),
-
- m_wave_format_extensible({})
+bool WASAPIDevice::setupDevice(DeviceSpecs &specs)
{
- // initialize COM if it hasn't happened yet
- CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+ SafeRelease(&m_audio_client);
+ SafeRelease(&m_imm_device);
- const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
- const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
+ if(FAILED(m_imm_device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_imm_device)))
+ return false;
+
+ if(FAILED(m_imm_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audio_client))))
+ return false;
+
WAVEFORMATEXTENSIBLE wave_format_extensible_closest_match;
WAVEFORMATEXTENSIBLE* closest_match_pointer = &wave_format_extensible_closest_match;
- HRESULT result;
-
REFERENCE_TIME minimum_time = 0;
REFERENCE_TIME buffer_duration;
- if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(&m_imm_device_enumerator))))
- goto error;
-
- if(FAILED(m_imm_device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_imm_device)))
- goto error;
-
- if(FAILED(m_imm_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&m_audio_client))))
- goto error;
-
- if(specs.channels == CHANNELS_INVALID)
- specs.channels = CHANNELS_STEREO;
- if(specs.format == FORMAT_INVALID)
- specs.format = FORMAT_FLOAT32;
- if(specs.rate == RATE_INVALID)
- specs.rate = RATE_48000;
-
switch(specs.format)
{
case FORMAT_U8:
@@ -203,12 +217,14 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
m_wave_format_extensible.Format.cbSize = 22;
m_wave_format_extensible.Samples.wValidBitsPerSample = m_wave_format_extensible.Format.wBitsPerSample;
- result = m_audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&m_wave_format_extensible), reinterpret_cast<WAVEFORMATEX**>(&closest_match_pointer));
+ HRESULT result = m_audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&m_wave_format_extensible), reinterpret_cast<WAVEFORMATEX**>(&closest_match_pointer));
if(result == S_FALSE)
{
+ bool errored = false;
+
if(closest_match_pointer->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
- goto error;
+ goto closest_match_error;
specs.channels = Channels(closest_match_pointer->Format.nChannels);
specs.rate = closest_match_pointer->Format.nSamplesPerSec;
@@ -220,7 +236,7 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
else if(closest_match_pointer->Format.wBitsPerSample == 64)
specs.format = FORMAT_FLOAT64;
else
- goto error;
+ goto closest_match_error;
}
else if(closest_match_pointer->SubFormat == KSDATAFORMAT_SUBTYPE_PCM)
{
@@ -239,44 +255,81 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
specs.format = FORMAT_S32;
break;
default:
- goto error;
+ goto closest_match_error;
break;
}
}
else
- goto error;
+ goto closest_match_error;
m_wave_format_extensible = *closest_match_pointer;
+ if(false)
+ {
+ closest_match_error:
+ errored = true;
+ }
+
if(closest_match_pointer != &wave_format_extensible_closest_match)
{
CoTaskMemFree(closest_match_pointer);
closest_match_pointer = &wave_format_extensible_closest_match;
}
+
+ if(errored)
+ return false;
}
else if(FAILED(result))
- goto error;
+ return false;
if(FAILED(m_audio_client->GetDevicePeriod(nullptr, &minimum_time)))
- goto error;
+ return false;
- buffer_duration = REFERENCE_TIME(buffersize) * REFERENCE_TIME(10000000) / REFERENCE_TIME(specs.rate);
+ buffer_duration = REFERENCE_TIME(m_buffersize) * REFERENCE_TIME(10000000) / REFERENCE_TIME(specs.rate);
if(minimum_time > buffer_duration)
buffer_duration = minimum_time;
- m_specs = specs;
-
if(FAILED(m_audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, buffer_duration, 0, reinterpret_cast<WAVEFORMATEX*>(&m_wave_format_extensible), nullptr)))
+ return false;
+
+ return true;
+}
+
+WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
+ m_buffersize(buffersize),
+ m_imm_device_enumerator(nullptr),
+ m_imm_device(nullptr),
+ m_audio_client(nullptr),
+
+ m_wave_format_extensible({})
+{
+ // initialize COM if it hasn't happened yet
+ CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+
+ const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
+ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
+
+ if(specs.channels == CHANNELS_INVALID)
+ specs.channels = CHANNELS_STEREO;
+ if(specs.format == FORMAT_INVALID)
+ specs.format = FORMAT_FLOAT32;
+ if(specs.rate == RATE_INVALID)
+ specs.rate = RATE_48000;
+
+ if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(&m_imm_device_enumerator))))
+ goto error;
+
+ if(!setupDevice(specs))
goto error;
+ m_specs = specs;
+
create();
return;
error:
- if(closest_match_pointer != &wave_format_extensible_closest_match)
- CoTaskMemFree(closest_match_pointer);
SafeRelease(&m_imm_device);
SafeRelease(&m_imm_device_enumerator);
SafeRelease(&m_audio_client);
diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.h b/extern/audaspace/plugins/wasapi/WASAPIDevice.h
index 375f03bd255..3b11adc98ef 100644
--- a/extern/audaspace/plugins/wasapi/WASAPIDevice.h
+++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.h
@@ -43,16 +43,21 @@ AUD_NAMESPACE_BEGIN
class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice
{
private:
+ int m_buffersize;
IMMDeviceEnumerator* m_imm_device_enumerator;
IMMDevice* m_imm_device;
IAudioClient* m_audio_client;
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
+ AUD_LOCAL HRESULT setupRenderClient(IAudioRenderClient*& render_client, UINT32& buffer_size);
+
/**
* Streaming thread main function.
*/
AUD_LOCAL void runMixingThread();
+ AUD_LOCAL bool setupDevice(DeviceSpecs& specs);
+
// delete copy constructor and operator=
WASAPIDevice(const WASAPIDevice&) = delete;
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp
index 7a2561515f4..e11b49a0967 100644
--- a/extern/audaspace/src/devices/SoftwareDevice.cpp
+++ b/extern/audaspace/src/devices/SoftwareDevice.cpp
@@ -756,6 +756,7 @@ void SoftwareDevice::mix(data_t* buffer, int length)
// get the buffer from the source
pos = 0;
len = length;
+ eos = false;
// update 3D Info
sound->update();
@@ -842,6 +843,27 @@ void SoftwareDevice::setSpecs(Specs specs)
{
sound->setSpecs(specs);
}
+
+ for(auto& sound : m_pausedSounds)
+ {
+ sound->setSpecs(specs);
+ }
+}
+
+void SoftwareDevice::setSpecs(DeviceSpecs specs)
+{
+ m_specs = specs;
+ m_mixer->setSpecs(specs);
+
+ for(auto& sound : m_playingSounds)
+ {
+ sound->setSpecs(specs.specs);
+ }
+
+ for(auto& sound : m_pausedSounds)
+ {
+ sound->setSpecs(specs.specs);
+ }
}
SoftwareDevice::SoftwareDevice()
diff --git a/extern/audaspace/src/respec/Mixer.cpp b/extern/audaspace/src/respec/Mixer.cpp
index ad8d885df4e..15872fbcff2 100644
--- a/extern/audaspace/src/respec/Mixer.cpp
+++ b/extern/audaspace/src/respec/Mixer.cpp
@@ -21,9 +21,25 @@
AUD_NAMESPACE_BEGIN
-Mixer::Mixer(DeviceSpecs specs) :
- m_specs(specs)
+Mixer::Mixer(DeviceSpecs specs)
{
+ setSpecs(specs);
+}
+
+DeviceSpecs Mixer::getSpecs() const
+{
+ return m_specs;
+}
+
+void Mixer::setSpecs(Specs specs)
+{
+ m_specs.specs = specs;
+}
+
+void Mixer::setSpecs(DeviceSpecs specs)
+{
+ m_specs = specs;
+
switch(m_specs.format)
{
case FORMAT_U8:
@@ -54,16 +70,6 @@ Mixer::Mixer(DeviceSpecs specs) :
}
}
-DeviceSpecs Mixer::getSpecs() const
-{
- return m_specs;
-}
-
-void Mixer::setSpecs(Specs specs)
-{
- m_specs.specs = specs;
-}
-
void Mixer::clear(int length)
{
m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs));