mirror of
https://github.com/holub/mame
synced 2025-07-05 01:48:29 +03:00
sound/wasapi_sound.cpp: Repeat the channel mask from the mix format back when initialising the audio client.
This commit is contained in:
parent
d1bac658e4
commit
97625ff9e0
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "interface/audio.h"
|
#include "interface/audio.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -115,15 +116,30 @@ HRESULT get_string_property_value(
|
|||||||
REFPROPERTYKEY key,
|
REFPROPERTYKEY key,
|
||||||
std::optional<std::string> &value);
|
std::optional<std::string> &value);
|
||||||
|
|
||||||
inline void populate_wave_format(WAVEFORMATEX &format, DWORD channels, DWORD rate)
|
inline void populate_wave_format(
|
||||||
|
WAVEFORMATEXTENSIBLE &format,
|
||||||
|
DWORD channels,
|
||||||
|
DWORD rate,
|
||||||
|
std::optional<DWORD> positions)
|
||||||
{
|
{
|
||||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
std::memset(&format, 0, sizeof(format));
|
||||||
format.nChannels = channels;
|
|
||||||
format.nSamplesPerSec = rate;
|
format.Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
format.nAvgBytesPerSec = 2 * channels * rate;
|
format.Format.nChannels = channels;
|
||||||
format.nBlockAlign = 2 * channels;
|
format.Format.nSamplesPerSec = rate;
|
||||||
format.wBitsPerSample = 16;
|
format.Format.nAvgBytesPerSec = 2 * channels * rate;
|
||||||
format.cbSize = 0;
|
format.Format.nBlockAlign = 2 * channels;
|
||||||
|
format.Format.wBitsPerSample = 16;
|
||||||
|
format.Format.cbSize = 0;
|
||||||
|
|
||||||
|
if (positions || (2 < channels))
|
||||||
|
{
|
||||||
|
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||||
|
format.Format.cbSize = sizeof(format) - sizeof(format.Format);
|
||||||
|
format.Samples.wValidBitsPerSample = 16;
|
||||||
|
format.dwChannelMask = positions ? *positions : 0;
|
||||||
|
format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace osd
|
} // namespace osd
|
||||||
|
@ -191,7 +191,7 @@ private:
|
|||||||
device_info_vector_iterator &device,
|
device_info_vector_iterator &device,
|
||||||
audio_client_ptr &client,
|
audio_client_ptr &client,
|
||||||
co_task_wave_format_ptr &mix_format,
|
co_task_wave_format_ptr &mix_format,
|
||||||
WAVEFORMATEX &format);
|
WAVEFORMATEXTENSIBLE &format);
|
||||||
|
|
||||||
void cleanup_task();
|
void cleanup_task();
|
||||||
|
|
||||||
@ -749,13 +749,13 @@ uint32_t sound_wasapi::stream_sink_open(uint32_t node, std::string name, uint32_
|
|||||||
device_info_vector_iterator device;
|
device_info_vector_iterator device;
|
||||||
audio_client_ptr client;
|
audio_client_ptr client;
|
||||||
co_task_wave_format_ptr mix;
|
co_task_wave_format_ptr mix;
|
||||||
WAVEFORMATEX format;
|
WAVEFORMATEXTENSIBLE format;
|
||||||
if (!activate_audio_client(node, name, rate, false, device, client, mix, format))
|
if (!activate_audio_client(node, name, rate, false, device, client, mix, format))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// need sample rate conversion if the sample rates don't match
|
// need sample rate conversion if the sample rates don't match
|
||||||
DWORD stream_flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
DWORD stream_flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||||
if (format.nSamplesPerSec != mix->nSamplesPerSec)
|
if (format.Format.nSamplesPerSec != mix->nSamplesPerSec)
|
||||||
stream_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
stream_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||||
|
|
||||||
// initialise the audio client interface
|
// initialise the audio client interface
|
||||||
@ -764,7 +764,7 @@ uint32_t sound_wasapi::stream_sink_open(uint32_t node, std::string name, uint32_
|
|||||||
stream_flags,
|
stream_flags,
|
||||||
lround(m_audio_latency * 1e4F), // 100 ns units
|
lround(m_audio_latency * 1e4F), // 100 ns units
|
||||||
0,
|
0,
|
||||||
&format,
|
&format.Format,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
@ -879,7 +879,7 @@ uint32_t sound_wasapi::stream_source_open(uint32_t node, std::string name, uint3
|
|||||||
device_info_vector_iterator device;
|
device_info_vector_iterator device;
|
||||||
audio_client_ptr client;
|
audio_client_ptr client;
|
||||||
co_task_wave_format_ptr mix;
|
co_task_wave_format_ptr mix;
|
||||||
WAVEFORMATEX format;
|
WAVEFORMATEXTENSIBLE format;
|
||||||
if (!activate_audio_client(node, name, rate, true, device, client, mix, format))
|
if (!activate_audio_client(node, name, rate, true, device, client, mix, format))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -887,7 +887,7 @@ uint32_t sound_wasapi::stream_source_open(uint32_t node, std::string name, uint3
|
|||||||
DWORD stream_flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
DWORD stream_flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||||
if (device->info.m_sinks)
|
if (device->info.m_sinks)
|
||||||
stream_flags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
|
stream_flags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
|
||||||
if (format.nSamplesPerSec != mix->nSamplesPerSec)
|
if (format.Format.nSamplesPerSec != mix->nSamplesPerSec)
|
||||||
stream_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
stream_flags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||||
|
|
||||||
// initialise the audio client interface
|
// initialise the audio client interface
|
||||||
@ -896,7 +896,7 @@ uint32_t sound_wasapi::stream_source_open(uint32_t node, std::string name, uint3
|
|||||||
stream_flags,
|
stream_flags,
|
||||||
10 * 10'000, // 10 ms in units of 100 ns
|
10 * 10'000, // 10 ms in units of 100 ns
|
||||||
0,
|
0,
|
||||||
&format,
|
&format.Format,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
@ -1519,7 +1519,7 @@ bool sound_wasapi::activate_audio_client(
|
|||||||
device_info_vector_iterator &device,
|
device_info_vector_iterator &device,
|
||||||
audio_client_ptr &client,
|
audio_client_ptr &client,
|
||||||
co_task_wave_format_ptr &mix_format,
|
co_task_wave_format_ptr &mix_format,
|
||||||
WAVEFORMATEX &format)
|
WAVEFORMATEXTENSIBLE &format)
|
||||||
{
|
{
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
|
|
||||||
@ -1581,10 +1581,14 @@ bool sound_wasapi::activate_audio_client(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set up desired format
|
// set up desired format
|
||||||
|
std::optional<DWORD> positions;
|
||||||
|
if (WAVE_FORMAT_EXTENSIBLE == mix_format->wFormatTag)
|
||||||
|
positions = reinterpret_cast<WAVEFORMATEXTENSIBLE const *>(mix_format.get())->dwChannelMask;
|
||||||
populate_wave_format(
|
populate_wave_format(
|
||||||
format,
|
format,
|
||||||
input ? device->info.m_sources : device->info.m_sinks,
|
input ? device->info.m_sources : device->info.m_sinks,
|
||||||
rate);
|
rate,
|
||||||
|
positions);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -712,8 +712,8 @@ uint32_t sound_xaudio2::stream_sink_open(uint32_t node, std::string name, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set up desired input format
|
// set up desired input format
|
||||||
WAVEFORMATEX format;
|
WAVEFORMATEXTENSIBLE format;
|
||||||
populate_wave_format(format, (*device)->info.m_sinks, rate);
|
populate_wave_format(format, (*device)->info.m_sinks, rate, std::nullopt);
|
||||||
|
|
||||||
// set up destinations
|
// set up destinations
|
||||||
XAUDIO2_SEND_DESCRIPTOR destination;
|
XAUDIO2_SEND_DESCRIPTOR destination;
|
||||||
@ -724,7 +724,7 @@ uint32_t sound_xaudio2::stream_sink_open(uint32_t node, std::string name, uint32
|
|||||||
sends.pSends = &destination;
|
sends.pSends = &destination;
|
||||||
|
|
||||||
// create the voice info object
|
// create the voice info object
|
||||||
voice_info_ptr info = std::make_unique<voice_info>(*this, format);
|
voice_info_ptr info = std::make_unique<voice_info>(*this, format.Format);
|
||||||
info->info.m_node = node;
|
info->info.m_node = node;
|
||||||
info->info.m_volumes.resize((*device)->info.m_sinks, 0.0F);
|
info->info.m_volumes.resize((*device)->info.m_sinks, 0.0F);
|
||||||
|
|
||||||
@ -732,7 +732,7 @@ uint32_t sound_xaudio2::stream_sink_open(uint32_t node, std::string name, uint32
|
|||||||
IXAudio2SourceVoice *source_voice_raw = nullptr;
|
IXAudio2SourceVoice *source_voice_raw = nullptr;
|
||||||
result = (*device)->engine->CreateSourceVoice(
|
result = (*device)->engine->CreateSourceVoice(
|
||||||
&source_voice_raw,
|
&source_voice_raw,
|
||||||
&format,
|
&format.Format,
|
||||||
XAUDIO2_VOICE_NOPITCH,
|
XAUDIO2_VOICE_NOPITCH,
|
||||||
1.0F,
|
1.0F,
|
||||||
info.get(),
|
info.get(),
|
||||||
@ -755,8 +755,8 @@ uint32_t sound_xaudio2::stream_sink_open(uint32_t node, std::string name, uint32
|
|||||||
// set the channel mapping
|
// set the channel mapping
|
||||||
result = info->voice->SetOutputMatrix(
|
result = info->voice->SetOutputMatrix(
|
||||||
nullptr,
|
nullptr,
|
||||||
format.nChannels,
|
format.Format.nChannels,
|
||||||
format.nChannels,
|
format.Format.nChannels,
|
||||||
info->volume_matrix.get(),
|
info->volume_matrix.get(),
|
||||||
XAUDIO2_COMMIT_NOW);
|
XAUDIO2_COMMIT_NOW);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
|
Loading…
Reference in New Issue
Block a user