diff options
author | Shen-Ta Hsieh <ibmibmibm.tw@gmail.com> | 2020-12-02 06:26:46 +0800 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2021-03-05 19:40:32 +0100 |
commit | e1fe9ebcd63ebfe6fcb680fa2a5a4cbef9742439 (patch) | |
tree | 1144baf7705c2e735a6f5f1eb31db51aa65351e8 | |
parent | 93016ac6aba0053f1d740527c6c123a052d5e40d (diff) |
output/wasapi: Add dop support for WASAPI
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1102
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/plugins.rst | 2 | ||||
-rw-r--r-- | src/output/plugins/wasapi/WasapiOutputPlugin.cxx | 46 |
3 files changed, 46 insertions, 3 deletions
@@ -8,6 +8,7 @@ ver 0.22.7 (not yet released) * output - wasapi: add algorithm for finding usable audio format - wasapi: use default device only if none was configured + - wasapi: add DoP support ver 0.22.6 (2021/02/16) * fix missing tags on songs in queue diff --git a/doc/plugins.rst b/doc/plugins.rst index 571654df6..71b9ad004 100644 --- a/doc/plugins.rst +++ b/doc/plugins.rst @@ -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". * - **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". + * - **dop yes|no** + - Enable DSD over PCM. Require exclusive mode. The default value is "no". .. _filter_plugins: diff --git a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx index 9a3616817..3882474f1 100644 --- a/src/output/plugins/wasapi/WasapiOutputPlugin.cxx +++ b/src/output/plugins/wasapi/WasapiOutputPlugin.cxx @@ -107,6 +107,17 @@ inline bool SafeSilenceTry(Functor &&functor) { } 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; if (audio_format.format == SampleFormat::S24_P32) { Result.resize(2); @@ -238,6 +249,9 @@ private: bool is_started = false; bool is_exclusive; bool enumerate_devices; +#ifdef ENABLE_DSD + bool dop_setting; +#endif std::string device_config; ComPtr<IMMDeviceEnumerator> enumerator; ComPtr<IMMDevice> device; @@ -344,7 +358,11 @@ WasapiOutput::WasapiOutput(const ConfigBlock &block) : AudioOutput(FLAG_ENABLE_DISABLE | FLAG_PAUSE), is_exclusive(block.GetBlockValue("exclusive", 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 void WasapiOutput::DoDisable() noexcept { @@ -379,20 +397,27 @@ void WasapiOutput::DoOpen(AudioFormat &audio_format) { } #ifdef ENABLE_DSD - if (audio_format.format == SampleFormat::DSD) { + if (!dop_setting && audio_format.format == SampleFormat::DSD) { SetDSDFallback(audio_format); } #endif - if (Exclusive()) { FindExclusiveFormatSupported(audio_format); } else { FindSharedFormatSupported(audio_format); } bool require_export = audio_format.format == SampleFormat::S24_P32; +#ifdef ENABLE_DSD + require_export |= audio_format.format == SampleFormat::DSD; +#endif if (require_export) { PcmExport::Params params; 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.pack24 = false; if (device_format.Format.wBitsPerSample == 32 && @@ -659,6 +684,16 @@ void WasapiOutput::FindExclusiveFormatSupported(AudioFormat &audio_format) { channels = audio_format.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, 48000, 44100, 32000, 22050, 16000, 11025, 8000}) { if (audio_format.sample_rate <= rate) { @@ -690,6 +725,11 @@ void WasapiOutput::FindExclusiveFormatSupported(AudioFormat &audio_format) { } audio_format.sample_rate = old_rate; } +#ifdef ENABLE_DSD + if (was_dsd) { + audio_format.format = SampleFormat::DSD; + } +#endif audio_format.channels = old_channels; } } |