From a3f0ffdf2440422e395e9613907d29b263daf99e Mon Sep 17 00:00:00 2001 From: Marcelo Fernandez Date: Thu, 30 Nov 2017 19:51:27 -0300 Subject: [PATCH] Fix wasapi going silent when number of channels are not supported --- drivers/wasapi/audio_driver_wasapi.cpp | 84 ++++++++++++++------------ drivers/wasapi/audio_driver_wasapi.h | 2 + 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index 2c87fb58db69..10b6a61b2d3c 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -74,21 +74,22 @@ Error AudioDriverWASAPI::init_device(bool reinit) { ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Since we're using WASAPI Shared Mode we can't control any of these, we just tag along - channels = pwfex->nChannels; + wasapi_channels = pwfex->nChannels; mix_rate = pwfex->nSamplesPerSec; format_tag = pwfex->wFormatTag; bits_per_sample = pwfex->wBitsPerSample; - switch (channels) { + switch (wasapi_channels) { case 2: // Stereo case 4: // Surround 3.1 case 6: // Surround 5.1 case 8: // Surround 7.1 + channels = wasapi_channels; break; default: - ERR_PRINTS("WASAPI: Unsupported number of channels: " + itos(channels)); - ERR_FAIL_V(ERR_CANT_OPEN); + WARN_PRINTS("WASAPI: Unsupported number of channels: " + itos(wasapi_channels)); + channels = 2; break; } @@ -206,6 +207,35 @@ AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const { return get_speaker_mode_by_total_channels(channels); } +void AudioDriverWASAPI::write_sample(AudioDriverWASAPI *ad, BYTE *buffer, int i, int32_t sample) { + if (ad->format_tag == WAVE_FORMAT_PCM) { + switch (ad->bits_per_sample) { + case 8: + ((int8_t *)buffer)[i] = sample >> 24; + break; + + case 16: + ((int16_t *)buffer)[i] = sample >> 16; + break; + + case 24: + ((int8_t *)buffer)[i * 3 + 2] = sample >> 24; + ((int8_t *)buffer)[i * 3 + 1] = sample >> 16; + ((int8_t *)buffer)[i * 3 + 0] = sample >> 8; + break; + + case 32: + ((int32_t *)buffer)[i] = sample; + break; + } + } else if (ad->format_tag == WAVE_FORMAT_IEEE_FLOAT) { + ((float *)buffer)[i] = (sample >> 16) / 32768.f; + } else { + ERR_PRINT("WASAPI: Unknown format tag"); + ad->exit_thread = true; + } +} + void AudioDriverWASAPI::thread_func(void *p_udata) { AudioDriverWASAPI *ad = (AudioDriverWASAPI *)p_udata; @@ -240,42 +270,21 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { if (hr == S_OK) { // We're using WASAPI Shared Mode so we must convert the buffer - if (ad->format_tag == WAVE_FORMAT_PCM) { - switch (ad->bits_per_sample) { - case 8: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((int8_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 24; - } - break; - - case 16: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((int16_t *)buffer)[i] = ad->samples_in[buffer_idx++] >> 16; - } - break; - - case 24: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - int32_t sample = ad->samples_in[buffer_idx++]; - ((int8_t *)buffer)[i * 3 + 2] = sample >> 24; - ((int8_t *)buffer)[i * 3 + 1] = sample >> 16; - ((int8_t *)buffer)[i * 3 + 0] = sample >> 8; - } - break; - - case 32: - for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((int32_t *)buffer)[i] = ad->samples_in[buffer_idx++]; - } - break; - } - } else if (ad->format_tag == WAVE_FORMAT_IEEE_FLOAT) { + if (ad->channels == ad->wasapi_channels) { for (unsigned int i = 0; i < write_frames * ad->channels; i++) { - ((float *)buffer)[i] = (ad->samples_in[buffer_idx++] >> 16) / 32768.f; + ad->write_sample(ad, buffer, i, ad->samples_in[buffer_idx++]); } } else { - ERR_PRINT("WASAPI: Unknown format tag"); - ad->exit_thread = true; + for (unsigned int i = 0; i < write_frames; i++) { + for (unsigned int j = 0; j < MIN(ad->channels, ad->wasapi_channels); j++) { + ad->write_sample(ad, buffer, i * ad->wasapi_channels + j, ad->samples_in[buffer_idx++]); + } + if (ad->wasapi_channels > ad->channels) { + for (unsigned int j = ad->channels; j < ad->wasapi_channels; j++) { + ad->write_sample(ad, buffer, i * ad->wasapi_channels + j, 0); + } + } + } } hr = ad->render_client->ReleaseBuffer(write_frames, 0); @@ -380,6 +389,7 @@ AudioDriverWASAPI::AudioDriverWASAPI() { buffer_size = 0; channels = 0; + wasapi_channels = 0; mix_rate = 0; buffer_frames = 0; diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index 87a2db724c73..5921645f6e6e 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -55,6 +55,7 @@ class AudioDriverWASAPI : public AudioDriver { unsigned int buffer_size; unsigned int channels; + unsigned int wasapi_channels; int mix_rate; int buffer_frames; @@ -62,6 +63,7 @@ class AudioDriverWASAPI : public AudioDriver { mutable bool exit_thread; bool active; + _FORCE_INLINE_ void write_sample(AudioDriverWASAPI *ad, BYTE *buffer, int i, int32_t sample); static void thread_func(void *p_udata); Error init_device(bool reinit = false);