Closed star69rem closed 1 year ago
What function is returning this hresult?
Resume()
i ended up changing the soundeffect class in my project so that it doesn't have ownership of the wav data, because the problem is that if some other program takes exclusive control of the audio device and audioengine bombs out, after the other program does its thing and you go to reinitialize audioengine, you don't really want to load all the wav files over again when only the instances need to be recreated--not the actual wav bytes so i basically have to look for the lost device HRESULT, reset all my directxtk soundeffect instances, and then reinitalize audio engine using the wav data that i've stored elsewhere
There's already support for 'silent' mode that should avoid the need to load all the wave data again.
Do you have an example of software that grabs the exclusive ownership?
Note the bug here is that Resume assumes the device is still there. That's not necessarily true as you've noted.
Foobar, MAME with port audio in exclusive/low latency mode, any WASAPI software using exclusive mode, etc.
I had the understanding that if you created the audio engine in silent mode that you wouldn't get any sounds. Are you saying if you start it in silent mode, then you can reset it, and then on future failures it will be able to reset itself without reloading the data?
After more testing, this also impacts initializing as well as resume. If you already started a program that is taking exclusive control of an audio device, the instantiation bombs out. I worked around it by adding this:
else if (hr == AUDCLNT_E_DEVICE_IN_USE) { DebugTrace("ERROR: AudioEngine failed (%08X) to initialize using device [%ls] because it was already in use."); }
Makes sense. Thanks for digging. I'll add both the explicit checking of AUDCLNT_E_DEVICE_IN_USE
as well as improving the Resume method later this week.
Seems to work okay. This is unrelated, but I'm wondering why you're guessing 16 on the bit depth on line 1332. Couldn't you get the PKEY_AudioEngine_DeviceFormat property and get the actual wBitsPerSample? You're already accessing the properties to get the device name on Windows.
The PKEY_AudioEngine_DeviceFormat
doesn't seem entirely reliable. On my system it reports "32" which I know isn't right--I have basic on-board motherboard audio.
If I use PKEY_AudioEngine_OEMFormat
I get "16".
What values are you seeing for your audio part?
It looks like PKEY_AudioEngine_DeviceFormat
just reports the information set in the Sound Settings dialog for the end-point. It was set to '32' for my speakers, but that's not at all what the DAC actually supports.
Is that information useful?
Please open a new issue for the reporting of the bit-depth, and I'll look into it.
For the bit-depth issue, see:
Thanks. Is it useful to get WAVEFORMATEXTENSIBLE instead of WAVEFORMATEX?
The WAVEFORMATEXTENSIBLE structure defines the format of waveform-audio data for formats having more than two channels or higher sample resolutions than allowed by WAVEFORMATEX. It can also be used to define any format that can be defined by WAVEFORMATEX.
Also, would it make sense to also get the sample rate from the waveformat returned from this property, too?
This was what I was doing in my hacked up version:
if (SUCCEEDED(props->GetValue(PKEY_AudioEngine_DeviceFormat, &var)))
{
if (var.vt == VT_BLOB && var.blob.cbSize >= sizeof(WAVEFORMATEX))
{
const WAVEFORMATEXTENSIBLE* deviceFormatProperties = reinterpret_cast<const WAVEFORMATEXTENSIBLE*>(var.blob.pBlobData);
device.sampleRate = deviceFormatProperties->Format.nSamplesPerSec;
device.bitDepth = deviceFormatProperties->Format.wBitsPerSample;
PropVariantClear(&var);
return true;
}
PropVariantClear(&var);
}
There's no difference at all between:
auto deviceFormatProperties = reinterpret_cast<const WAVEFORMATEXTENSIBLE*>(var.blob.pBlobData);
device.sampleRate = deviceFormatProperties->Format.nSamplesPerSec;
device.bitDepth = deviceFormatProperties->Format.wBitsPerSample;
and
auto deviceFormatProperties = reinterpret_cast<const WAVEFORMATEX*>(var.blob.pBlobData);
device.sampleRate = deviceFormatProperties->nSamplesPerSec;
device.bitDepth = deviceFormatProperties->wBitsPerSample;
If you're using the DirectXTK AudioEngine, and another program takes over your device in exclusive mode, AudioEngine will bomb out because of this.