From 667db0f2ded25a7f39aacabe31ed48737559fe66 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 5 Aug 2024 23:50:56 +0200 Subject: [PATCH] cellMic: remove duplicate code and add size checks --- rpcs3/Emu/Cell/Modules/cellMic.cpp | 206 +++++++++++++++-------------- rpcs3/Emu/Cell/Modules/cellMic.h | 23 +++- 2 files changed, 126 insertions(+), 103 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp index 776481e9b9..03f0d4c994 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -260,7 +260,9 @@ microphone_device::microphone_device(microphone_handler type) void microphone_device::add_device(const std::string& name) { - device_name.push_back(name); + devices.push_back(mic_device{ + .name = name + }); } error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, const u32 raw_r, const u8 channels) @@ -406,39 +408,37 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co aux_samplingrate = dsp_samplingrate = raw_samplingrate; // Same rate for now - ensure(!device_name.empty()); + ensure(!devices.empty()); - ALCdevice* device = alcCaptureOpenDevice(device_name[0].c_str(), raw_samplingrate, num_al_channels, inbuf_size); + 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=0x%x, device=*0x%x)", device_name[0], err, device); + cellMic.error("Error opening capture device %s (error=0x%x, device=*0x%x)", devices[0].name, 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; } - input_devices.push_back(device); - internal_bufs.emplace_back(); - internal_bufs[0].resize(inbuf_size, 0); + devices[0].device = device; + devices[0].buf.resize(inbuf_size, 0); temp_buf.resize(inbuf_size, 0); - if (device_type == microphone_handler::singstar && device_name.size() >= 2) + if (device_type == microphone_handler::singstar && devices.size() >= 2) { // Open a 2nd microphone into the same device - device = alcCaptureOpenDevice(device_name[1].c_str(), raw_samplingrate, AL_FORMAT_MONO16, inbuf_size); + device = alcCaptureOpenDevice(devices[1].name.c_str(), raw_samplingrate, AL_FORMAT_MONO16, inbuf_size); if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device) { // Ignore it and move on - cellMic.error("Error opening 2nd SingStar capture device %s (error=0x%x, device=*0x%x)", device_name[1], err, device); + cellMic.error("Error opening 2nd SingStar capture device %s (error=0x%x, device=*0x%x)", devices[1].name, err, device); } else { - input_devices.push_back(device); - internal_bufs.emplace_back(); - internal_bufs[1].resize(inbuf_size, 0); + devices[1].device = device; + devices[1].buf.resize(inbuf_size, 0); } } @@ -455,16 +455,16 @@ error_code microphone_device::close_microphone() stop_microphone(); } - for (const auto& micdevice : input_devices) + for (mic_device& micdevice : devices) { - if (alcCaptureCloseDevice(micdevice) != ALC_TRUE) + if (alcCaptureCloseDevice(micdevice.device) != ALC_TRUE) { - cellMic.error("Error closing capture device"); + cellMic.error("Error closing capture device %s", micdevice.name); } - } - input_devices.clear(); - internal_bufs.clear(); + micdevice.device = nullptr; + micdevice.buf.clear(); + } mic_opened = false; @@ -473,12 +473,12 @@ error_code microphone_device::close_microphone() error_code microphone_device::start_microphone() { - for (ALCdevice* micdevice : input_devices) + for (const mic_device& micdevice : devices) { - alcCaptureStart(micdevice); - if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR) + alcCaptureStart(micdevice.device); + if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error starting capture (error=0x%x)", err); + cellMic.error("Error starting capture of device %s (error=0x%x)", micdevice.name, err); stop_microphone(); return CELL_MICIN_ERROR_FATAL; } @@ -491,12 +491,12 @@ error_code microphone_device::start_microphone() error_code microphone_device::stop_microphone() { - for (ALCdevice* micdevice : input_devices) + for (const mic_device& micdevice : devices) { - alcCaptureStop(micdevice); - if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR) + alcCaptureStop(micdevice.device); + if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error stopping capture (error=0x%x)", err); + cellMic.error("Error stopping capture of device %s (error=0x%x)", micdevice.name, err); } } @@ -515,9 +515,15 @@ void microphone_device::update_audio() const u32 num_samples = capture_audio(); if (signal_types & CELLMIC_SIGTYPE_RAW) + { get_raw(num_samples); + } + if (signal_types & CELLMIC_SIGTYPE_DSP) + { get_dsp(num_samples); + } + // TODO: aux? } } @@ -533,21 +539,26 @@ u32 microphone_device::capture_audio() u32 num_samples = inbuf_size / sample_size; - for (ALCdevice* micdevice : input_devices) + for (const mic_device& micdevice : devices) { ALCint samples_in = 0; - alcGetIntegerv(micdevice, ALC_CAPTURE_SAMPLES, 1, &samples_in); - if (ALCenum err = alcGetError(micdevice); err != ALC_NO_ERROR) + alcGetIntegerv(micdevice.device, ALC_CAPTURE_SAMPLES, 1, &samples_in); + if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) { - cellMic.error("Error getting number of captured samples (error=0x%x)", err); + cellMic.error("Error getting number of captured samples of device %s (error=0x%x)", micdevice.name, err); return CELL_MICIN_ERROR_FATAL; } num_samples = std::min(num_samples, samples_in); } - for (u32 index = 0; index < input_devices.size(); index++) + for (mic_device& micdevice : devices) { - alcCaptureSamples(input_devices[index], internal_bufs[index].data(), num_samples); + alcCaptureSamples(micdevice.device, micdevice.buf.data(), num_samples); + + if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR) + { + cellMic.error("Error capturing samples of device %s (error=0x%x)", micdevice.name, err); + } } return num_samples; @@ -555,115 +566,116 @@ u32 microphone_device::capture_audio() // Private functions -void microphone_device::get_raw(const u32 num_samples) +void microphone_device::get_data(const u32 num_samples) { + ensure(num_samples > 0); + u8* tmp_ptr = temp_buf.data(); switch (device_type) { case microphone_handler::real_singstar: + { + const usz bufsize = num_samples * sample_size; + const mic_device& device = ::at32(devices, 0); + ensure(bufsize <= device.buf.size()); + ensure(bufsize <= temp_buf.size()); + // Straight copy from device - memcpy(tmp_ptr, internal_bufs[0].data(), num_samples * (bit_resolution / 8) * num_channels); + std::memcpy(tmp_ptr, device.buf.data(), bufsize); break; + } case microphone_handler::standard: case microphone_handler::rocksmith: + { + const u8 channel_size = bit_resolution / 8; + const usz bufsize = num_samples * sample_size; + const std::vector& buf = ::at32(devices, 0).buf; + ensure(bufsize <= buf.size()); + ensure(bufsize <= temp_buf.size()); + // BE Translation for (u32 index = 0; index < num_samples; index++) { + const u32 sample_pos = index * sample_size; + for (u32 indchan = 0; indchan < num_channels; indchan++) { - const u32 curindex = (index * sample_size) + indchan * (bit_resolution / 8); - microphone_device::variable_byteswap(internal_bufs[0].data() + curindex, tmp_ptr + curindex, bit_resolution / 8); + const u32 curindex = sample_pos + indchan * channel_size; + microphone_device::variable_byteswap(buf.data() + curindex, tmp_ptr + curindex, channel_size); } } break; + } case microphone_handler::singstar: + { ensure(sample_size == 4); - // Mixing the 2 mics as if channels - if (input_devices.size() == 2) + // Each device buffer contains 16 bit mono samples + const usz bufsize = num_samples * sizeof(u16); + const std::vector& buf_0 = ::at32(devices, 0).buf; + ensure(bufsize <= buf_0.size()); + + // Mixing the 2 mics into the 2 destination channels + if (devices.size() == 2) { + const std::vector& buf_1 = ::at32(devices, 1).buf; + ensure(bufsize <= buf_1.size()); + for (u32 index = 0; index < (num_samples * 4); index += 4) { - tmp_ptr[index] = internal_bufs[0][(index / 2)]; - tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1]; - tmp_ptr[index + 2] = internal_bufs[1][(index / 2)]; - tmp_ptr[index + 3] = internal_bufs[1][(index / 2) + 1]; + const u32 src_index = index / 2; + + tmp_ptr[index] = buf_0[src_index]; + tmp_ptr[index + 1] = buf_0[src_index + 1]; + tmp_ptr[index + 2] = buf_1[src_index]; + tmp_ptr[index + 3] = buf_1[src_index + 1]; } } else { for (u32 index = 0; index < (num_samples * 4); index += 4) { - tmp_ptr[index] = internal_bufs[0][(index / 2)]; - tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1]; + const u32 src_index = index / 2; + + tmp_ptr[index] = buf_0[src_index]; + tmp_ptr[index + 1] = buf_0[src_index + 1]; tmp_ptr[index + 2] = 0; tmp_ptr[index + 3] = 0; } } break; + } case microphone_handler::null: - default: ensure(false); break; + ensure(false); + break; + } +} + +void microphone_device::get_raw(const u32 num_samples) +{ + if (num_samples == 0) + { + return; } - rbuf_raw.write_bytes(tmp_ptr, num_samples * sample_size); -}; + get_data(num_samples); + + rbuf_raw.write_bytes(temp_buf.data(), num_samples * sample_size); +} void microphone_device::get_dsp(const u32 num_samples) { - u8* tmp_ptr = temp_buf.data(); - - switch (device_type) + if (num_samples == 0) { - case microphone_handler::real_singstar: - // Straight copy from device - memcpy(tmp_ptr, internal_bufs[0].data(), num_samples * (bit_resolution / 8) * num_channels); - break; - case microphone_handler::standard: - case microphone_handler::rocksmith: - // BE Translation - for (u32 index = 0; index < num_samples; index++) - { - for (u32 indchan = 0; indchan < num_channels; indchan++) - { - const u32 curindex = (index * sample_size) + indchan * (bit_resolution / 8); - microphone_device::variable_byteswap(internal_bufs[0].data() + curindex, tmp_ptr + curindex, bit_resolution / 8); - } - } - break; - case microphone_handler::singstar: - ensure(sample_size == 4); - - // Mixing the 2 mics as if channels - if (input_devices.size() == 2) - { - for (u32 index = 0; index < (num_samples * 4); index += 4) - { - tmp_ptr[index] = internal_bufs[0][(index / 2)]; - tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1]; - tmp_ptr[index + 2] = internal_bufs[1][(index / 2)]; - tmp_ptr[index + 3] = internal_bufs[1][(index / 2) + 1]; - } - } - else - { - for (u32 index = 0; index < (num_samples * 4); index += 4) - { - tmp_ptr[index] = internal_bufs[0][(index / 2)]; - tmp_ptr[index + 1] = internal_bufs[0][(index / 2) + 1]; - tmp_ptr[index + 2] = 0; - tmp_ptr[index + 3] = 0; - } - } - - break; - case microphone_handler::null: - default: ensure(false); break; + return; } - rbuf_dsp.write_bytes(tmp_ptr, num_samples * sample_size); -}; + get_data(num_samples); + + rbuf_dsp.write_bytes(temp_buf.data(), num_samples * sample_size); +} /// Initialization/Shutdown Functions diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h index 00eb7c8032..aec7dd49b3 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.h +++ b/rpcs3/Emu/Cell/Modules/cellMic.h @@ -197,12 +197,12 @@ public: u32 read_bytes(u8* buf, const u32 size) { - ensure(buf); - const u32 to_read = size > m_used ? m_used : size; if (!to_read) return 0; + ensure(buf); + u8* data = m_container.data(); const u32 new_tail = m_tail + to_read; @@ -226,6 +226,11 @@ public: void write_bytes(const u8* buf, const u32 size) { + if (size == 0) + { + return; + } + ensure(size <= Size); const u32 over_size = m_used + size; @@ -280,7 +285,7 @@ public: error_code start_microphone(); error_code stop_microphone(); - std::string get_device_name() const { return device_name.empty() ? "" : device_name.front(); } + std::string get_device_name() const { return devices.empty() ? "" : devices.front().name; } void update_audio(); bool has_data() const; @@ -320,18 +325,24 @@ private: u32 capture_audio(); + void get_data(const u32 num_samples); void get_raw(const u32 num_samples); void get_dsp(const u32 num_samples); microphone_handler device_type = microphone_handler::null; - std::vector device_name; bool mic_registered = false; bool mic_opened = false; bool mic_started = false; - std::vector input_devices; - std::vector> internal_bufs; + struct mic_device + { + std::string name; + ALCdevice* device = nullptr; + std::vector buf; + }; + + std::vector devices; std::vector temp_buf; // Sampling information provided at opening of mic