diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp index a1ffd914f5..a26050d875 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -258,6 +258,29 @@ inline void microphone_device::variable_byteswap(const void* src, void* dst) } } +inline u32 microphone_device::convert_16_bit_pcm_to_float(const std::vector& buffer, u32 num_bytes) +{ + static_assert((float_buf_size % sizeof(f32)) == 0); + + float_buf.resize(float_buf_size, 0); + const u32 bytes_to_write = static_cast(num_bytes * (sizeof(f32) / sizeof(s16))); + ensure(bytes_to_write <= float_buf.size()); + + const be_t* src = utils::bless>(buffer.data()); + be_t* dst = reinterpret_cast*>(float_buf.data()); + + for (usz i = 0; i < num_bytes / sizeof(s16); i++) + { + const be_t sample = *src++; + + const be_t normalized_sample_be = std::clamp(static_cast(sample) / std::numeric_limits::max(), -1.0f, 1.0f); + + *dst++ = normalized_sample_be; + } + + return bytes_to_write; +} + // Public functions microphone_device::microphone_device(microphone_handler type) @@ -696,7 +719,17 @@ void microphone_device::get_dsp(const u32 num_samples) const u32 bufsize = num_samples * sample_size; ensure(bufsize <= buf.size()); - rbuf_dsp.write_bytes(buf.data(), bufsize); + if (attr_dsptype != 0x01) + { + // Convert 16-bit PCM audio data to 32-bit float (DSP format) + const u32 bufsize_float = convert_16_bit_pcm_to_float(buf, bufsize); + rbuf_dsp.write_bytes(float_buf.data(), bufsize_float); + } + else + { + // The same as device RAW stream format, except that the data byte is always big-endian + rbuf_dsp.write_bytes(buf.data(), bufsize); + } } /// Initialization/Shutdown Functions diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h index b1d4982523..3fbe5fba13 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.h +++ b/rpcs3/Emu/Cell/Modules/cellMic.h @@ -323,6 +323,7 @@ public: private: template 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); u32 capture_audio(); @@ -345,6 +346,7 @@ private: std::vector devices; std::vector temp_buf; + std::vector float_buf; // Sampling information provided at opening of mic u32 raw_samplingrate = 48000; @@ -358,9 +360,10 @@ private: static constexpr u8 bit_resolution = 16; static constexpr usz inbuf_size = 400000; // Default value unknown + static constexpr usz float_buf_size = inbuf_size * (sizeof(f32) / sizeof(s16)); simple_ringbuf rbuf_raw; - simple_ringbuf rbuf_dsp; + simple_ringbuf rbuf_dsp; simple_ringbuf rbuf_aux; };