output/wasapi: Add dop support for WASAPI
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1102
This commit is contained in:
parent
93016ac6ab
commit
e1fe9ebcd6
1
NEWS
1
NEWS
@ -8,6 +8,7 @@ ver 0.22.7 (not yet released)
|
|||||||
* output
|
* output
|
||||||
- wasapi: add algorithm for finding usable audio format
|
- wasapi: add algorithm for finding usable audio format
|
||||||
- wasapi: use default device only if none was configured
|
- wasapi: use default device only if none was configured
|
||||||
|
- wasapi: add DoP support
|
||||||
|
|
||||||
ver 0.22.6 (2021/02/16)
|
ver 0.22.6 (2021/02/16)
|
||||||
* fix missing tags on songs in queue
|
* fix missing tags on songs in queue
|
||||||
|
@ -1171,6 +1171,8 @@ The `Windows Audio Session API <https://docs.microsoft.com/en-us/windows/win32/c
|
|||||||
- Enumerate all devices in log while playing started. Useful for device configuration. The default value is "no".
|
- Enumerate all devices in log while playing started. Useful for device configuration. The default value is "no".
|
||||||
* - **exclusive yes|no**
|
* - **exclusive yes|no**
|
||||||
- Exclusive mode blocks all other audio source, and get best audio quality without resampling. Stopping playing release the exclusive control of the output device. The default value is "no".
|
- Exclusive mode blocks all other audio source, and get best audio quality without resampling. Stopping playing release the exclusive control of the output device. The default value is "no".
|
||||||
|
* - **dop yes|no**
|
||||||
|
- Enable DSD over PCM. Require exclusive mode. The default value is "no".
|
||||||
|
|
||||||
|
|
||||||
.. _filter_plugins:
|
.. _filter_plugins:
|
||||||
|
@ -107,6 +107,17 @@ inline bool SafeSilenceTry(Functor &&functor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<WAVEFORMATEXTENSIBLE> GetFormats(const AudioFormat &audio_format) noexcept {
|
std::vector<WAVEFORMATEXTENSIBLE> GetFormats(const AudioFormat &audio_format) noexcept {
|
||||||
|
#ifdef ENABLE_DSD
|
||||||
|
if (audio_format.format == SampleFormat::DSD) {
|
||||||
|
AudioFormat dop_format = audio_format;
|
||||||
|
PcmExport::Params params;
|
||||||
|
params.dsd_mode = PcmExport::DsdMode::DOP;
|
||||||
|
dop_format.sample_rate =
|
||||||
|
params.CalcOutputSampleRate(audio_format.sample_rate);
|
||||||
|
dop_format.format = SampleFormat::S24_P32;
|
||||||
|
return GetFormats(dop_format);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
std::vector<WAVEFORMATEXTENSIBLE> Result;
|
std::vector<WAVEFORMATEXTENSIBLE> Result;
|
||||||
if (audio_format.format == SampleFormat::S24_P32) {
|
if (audio_format.format == SampleFormat::S24_P32) {
|
||||||
Result.resize(2);
|
Result.resize(2);
|
||||||
@ -238,6 +249,9 @@ private:
|
|||||||
bool is_started = false;
|
bool is_started = false;
|
||||||
bool is_exclusive;
|
bool is_exclusive;
|
||||||
bool enumerate_devices;
|
bool enumerate_devices;
|
||||||
|
#ifdef ENABLE_DSD
|
||||||
|
bool dop_setting;
|
||||||
|
#endif
|
||||||
std::string device_config;
|
std::string device_config;
|
||||||
ComPtr<IMMDeviceEnumerator> enumerator;
|
ComPtr<IMMDeviceEnumerator> enumerator;
|
||||||
ComPtr<IMMDevice> device;
|
ComPtr<IMMDevice> device;
|
||||||
@ -344,7 +358,11 @@ WasapiOutput::WasapiOutput(const ConfigBlock &block)
|
|||||||
: AudioOutput(FLAG_ENABLE_DISABLE | FLAG_PAUSE),
|
: AudioOutput(FLAG_ENABLE_DISABLE | FLAG_PAUSE),
|
||||||
is_exclusive(block.GetBlockValue("exclusive", false)),
|
is_exclusive(block.GetBlockValue("exclusive", false)),
|
||||||
enumerate_devices(block.GetBlockValue("enumerate", false)),
|
enumerate_devices(block.GetBlockValue("enumerate", false)),
|
||||||
device_config(block.GetBlockValue("device", "")) {}
|
#ifdef ENABLE_DSD
|
||||||
|
dop_setting(block.GetBlockValue("dop", false)),
|
||||||
|
#endif
|
||||||
|
device_config(block.GetBlockValue("device", "")) {
|
||||||
|
}
|
||||||
|
|
||||||
/// run inside COMWorkerThread
|
/// run inside COMWorkerThread
|
||||||
void WasapiOutput::DoDisable() noexcept {
|
void WasapiOutput::DoDisable() noexcept {
|
||||||
@ -379,20 +397,27 @@ void WasapiOutput::DoOpen(AudioFormat &audio_format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DSD
|
#ifdef ENABLE_DSD
|
||||||
if (audio_format.format == SampleFormat::DSD) {
|
if (!dop_setting && audio_format.format == SampleFormat::DSD) {
|
||||||
SetDSDFallback(audio_format);
|
SetDSDFallback(audio_format);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Exclusive()) {
|
if (Exclusive()) {
|
||||||
FindExclusiveFormatSupported(audio_format);
|
FindExclusiveFormatSupported(audio_format);
|
||||||
} else {
|
} else {
|
||||||
FindSharedFormatSupported(audio_format);
|
FindSharedFormatSupported(audio_format);
|
||||||
}
|
}
|
||||||
bool require_export = audio_format.format == SampleFormat::S24_P32;
|
bool require_export = audio_format.format == SampleFormat::S24_P32;
|
||||||
|
#ifdef ENABLE_DSD
|
||||||
|
require_export |= audio_format.format == SampleFormat::DSD;
|
||||||
|
#endif
|
||||||
if (require_export) {
|
if (require_export) {
|
||||||
PcmExport::Params params;
|
PcmExport::Params params;
|
||||||
params.dsd_mode = PcmExport::DsdMode::NONE;
|
params.dsd_mode = PcmExport::DsdMode::NONE;
|
||||||
|
#ifdef ENABLE_DSD
|
||||||
|
if (audio_format.format == SampleFormat::DSD) {
|
||||||
|
params.dsd_mode = PcmExport::DsdMode::DOP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
params.shift8 = false;
|
params.shift8 = false;
|
||||||
params.pack24 = false;
|
params.pack24 = false;
|
||||||
if (device_format.Format.wBitsPerSample == 32 &&
|
if (device_format.Format.wBitsPerSample == 32 &&
|
||||||
@ -659,6 +684,16 @@ void WasapiOutput::FindExclusiveFormatSupported(AudioFormat &audio_format) {
|
|||||||
channels = audio_format.channels;
|
channels = audio_format.channels;
|
||||||
}
|
}
|
||||||
auto old_channels = std::exchange(audio_format.channels, channels);
|
auto old_channels = std::exchange(audio_format.channels, channels);
|
||||||
|
#ifdef ENABLE_DSD
|
||||||
|
bool was_dsd = false;
|
||||||
|
if (audio_format.format == SampleFormat::DSD) {
|
||||||
|
if (dop_setting && TryFormatExclusive(audio_format)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
was_dsd = true;
|
||||||
|
SetDSDFallback(audio_format);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for (uint32_t rate : {0, 384000, 352800, 192000, 176400, 96000, 88200,
|
for (uint32_t rate : {0, 384000, 352800, 192000, 176400, 96000, 88200,
|
||||||
48000, 44100, 32000, 22050, 16000, 11025, 8000}) {
|
48000, 44100, 32000, 22050, 16000, 11025, 8000}) {
|
||||||
if (audio_format.sample_rate <= rate) {
|
if (audio_format.sample_rate <= rate) {
|
||||||
@ -690,6 +725,11 @@ void WasapiOutput::FindExclusiveFormatSupported(AudioFormat &audio_format) {
|
|||||||
}
|
}
|
||||||
audio_format.sample_rate = old_rate;
|
audio_format.sample_rate = old_rate;
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_DSD
|
||||||
|
if (was_dsd) {
|
||||||
|
audio_format.format = SampleFormat::DSD;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
audio_format.channels = old_channels;
|
audio_format.channels = old_channels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user