diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp index cb8724f965..864df5baa1 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -423,36 +423,40 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co break; } + ALCdevice* device = nullptr; + // Make sure we use a proper sampling rate - const auto fixup_samplingrate = [this](u32& rate) -> bool + // TODO: The used sample rate may vary for Sony's camera devices + const std::array samplingrates = { raw_samplingrate, 48000u, 32000u, 24000u, 16000u, 12000u, 8000u }; + + for (u32 samplingrate : samplingrates) { - // TODO: The used sample rate may vary for Sony's camera devices - const std::array samplingrates = { rate, 48000u, 32000u, 24000u, 16000u, 12000u, 8000u }; - - const auto test_samplingrate = [&samplingrates](const u32& rate) + if (!std::any_of(samplingrates.cbegin() + 1, samplingrates.cend(), [samplingrate](u32 r){ return r == samplingrate; })) { - // TODO: actually check if device supports sampling rates - return std::any_of(samplingrates.cbegin() + 1, samplingrates.cend(), [&rate](const u32& r){ return r == rate; }); - }; - - for (u32 samplingrate : samplingrates) - { - if (test_samplingrate(samplingrate)) - { - // Use this sampling rate - raw_samplingrate = samplingrate; - cellMic.notice("Using sampling rate %d.", samplingrate); - return true; - } - cellMic.warning("Requested sampling rate %d, but we do not support it. Trying next sampling rate...", samplingrate); + continue; } - return false; - }; + cellMic.notice("Trying sampling rate %d with %d channel(s)", samplingrate, num_channels); - if (!fixup_samplingrate(raw_samplingrate)) + device = open_device(devices[0].name, samplingrate, num_al_channels, inbuf_size); + if (!device) + { + continue; + } + + // Use this sampling rate + raw_samplingrate = samplingrate; + cellMic.notice("Using sampling rate %d and %d channel(s)", raw_samplingrate, num_channels); + break; + } + + if (!device) { + cellMic.error("Failed to open capture device '%s' (raw_samplingrate=%d, num_al_channels=0x%x, inbuf_size=%d)", devices[0].name, raw_samplingrate, num_al_channels, inbuf_size); +#ifdef _WIN32 + cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration"); +#endif return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT; } @@ -460,29 +464,19 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co ensure(!devices.empty()); - ALCdevice* device = alcCaptureOpenDevice(devices[0].name.c_str(), raw_samplingrate, num_al_channels, inbuf_size); - - if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device) - { - cellMic.error("Error opening capture device %s (error=%s, device=*0x%x)", devices[0].name, fmt::alc_error{device, err}, device); -#ifdef _WIN32 - cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration"); -#endif - return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT; - } - devices[0].device = device; devices[0].buf.resize(inbuf_size, 0); if (device_type == microphone_handler::singstar && devices.size() >= 2) { // Open a 2nd microphone into the same device - device = alcCaptureOpenDevice(devices[1].name.c_str(), raw_samplingrate, AL_FORMAT_MONO16, inbuf_size); + num_al_channels = AL_FORMAT_MONO16; + device = open_device(devices[1].name, raw_samplingrate, num_al_channels, inbuf_size); - if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device) + if (!device) { // Ignore it and move on - cellMic.error("Error opening 2nd SingStar capture device %s (error=%s, device=*0x%x)", devices[1].name, fmt::alc_error{device, err}, device); + cellMic.error("Failed to open 2nd SingStar capture device '%s' (raw_samplingrate=%d, num_al_channels=0x%x, inbuf_size=%d)", devices[1].name, raw_samplingrate, num_al_channels, inbuf_size); } else { @@ -517,7 +511,7 @@ error_code microphone_device::close_microphone() { if (alcCaptureCloseDevice(micdevice.device) != ALC_TRUE) { - cellMic.error("Error closing capture device %s", micdevice.name); + cellMic.error("Error closing capture device '%s'", micdevice.name); } micdevice.device = nullptr; @@ -539,7 +533,7 @@ error_code microphone_device::start_microphone() alcCaptureStart(micdevice.device); if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error starting capture of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); + cellMic.error("Error starting capture of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); stop_microphone(); return CELL_MICIN_ERROR_FATAL; } @@ -558,7 +552,7 @@ error_code microphone_device::stop_microphone() alcCaptureStop(micdevice.device); if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error stopping capture of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); + cellMic.error("Error stopping capture of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); } } #endif @@ -637,7 +631,7 @@ u32 microphone_device::capture_audio() if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error getting number of captured samples of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); + cellMic.error("Error getting number of captured samples of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); return CELL_MICIN_ERROR_FATAL; } @@ -655,7 +649,7 @@ u32 microphone_device::capture_audio() if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error capturing samples of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); + cellMic.error("Error capturing samples of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err}); } } @@ -667,6 +661,21 @@ u32 microphone_device::capture_audio() // Private functions +#ifndef WITHOUT_OPENAL +ALCdevice* microphone_device::open_device(std::string& name, u32 samplingrate, ALCenum num_al_channels, u32 buf_size) +{ + ALCdevice* device = alcCaptureOpenDevice(name.c_str(), samplingrate, num_al_channels, buf_size); + + if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device) + { + cellMic.warning("Failed to open capture device '%s' (error=%s, device=*0x%x, samplingrate=%d, num_al_channels=0x%x, buf_size=%d)", name, fmt::alc_error{device, err}, device, samplingrate, num_al_channels, buf_size); + device = nullptr; + } + + return device; +} +#endif + void microphone_device::get_data(const u32 num_samples) { if (num_samples == 0) diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h index f17b954278..e25488c19c 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.h +++ b/rpcs3/Emu/Cell/Modules/cellMic.h @@ -326,6 +326,10 @@ private: static inline void variable_byteswap(const void* src, void* dst); inline u32 convert_16_bit_pcm_to_float(const std::vector& buffer, u32 num_bytes); +#ifndef WITHOUT_OPENAL + ALCdevice* open_device(std::string& name, u32 samplingrate, ALCenum num_al_channels, u32 buf_size); +#endif + u32 capture_audio(); void get_data(const u32 num_samples); diff --git a/rpcs3/rpcs3qt/microphone_creator.cpp b/rpcs3/rpcs3qt/microphone_creator.cpp index a0e63a5d51..9ea04defde 100644 --- a/rpcs3/rpcs3qt/microphone_creator.cpp +++ b/rpcs3/rpcs3qt/microphone_creator.cpp @@ -28,9 +28,9 @@ void microphone_creator::refresh_list() { if (const char* devices = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER)) { - while (*devices != 0) + while (devices && *devices != 0) { - cfg_log.notice("Found microphone: %s", devices); + cfg_log.notice("Found microphone: '%s'", devices); m_microphone_list.append(devices); devices += strlen(devices) + 1; } @@ -43,6 +43,7 @@ void microphone_creator::refresh_list() if (const char* device = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER)) { + cfg_log.notice("Found default microphone: '%s'", device); m_microphone_list.append(device); } }