IOS/USB: Only sample Wii Speak data when necessary

Skip data when HLE Wii Speak is not connected

Lock microphone buffer less frequently
This commit is contained in:
Sepalani
2024-05-12 15:48:11 +04:00
parent f5dd80bb5b
commit a85ffc116e
4 changed files with 40 additions and 18 deletions

View File

@ -15,6 +15,9 @@
#include "Common/ScopeGuard.h" #include "Common/ScopeGuard.h"
#include "Common/Swap.h" #include "Common/Swap.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/IOS/USB/Emulated/WiiSpeak.h"
#include "Core/System.h"
#ifdef _WIN32 #ifdef _WIN32
#include <Objbase.h> #include <Objbase.h>
@ -22,7 +25,7 @@
namespace IOS::HLE::USB namespace IOS::HLE::USB
{ {
Microphone::Microphone() Microphone::Microphone(const WiiSpeakState& sampler) : m_sampler(sampler)
{ {
#if defined(_WIN32) && defined(HAVE_CUBEB) #if defined(_WIN32) && defined(HAVE_CUBEB)
m_work_queue.PushBlocking([this] { m_work_queue.PushBlocking([this] {
@ -175,6 +178,15 @@ void Microphone::StreamStop()
long Microphone::CubebDataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, long Microphone::CubebDataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer,
void* /*output_buffer*/, long nframes) void* /*output_buffer*/, long nframes)
{ {
// Skip data when core isn't running
if (Core::GetState(Core::System::GetInstance()) != Core::State::Running)
return nframes;
// Skip data when HLE Wii Speak is not connected
// TODO: Update cubeb and use cubeb_stream_set_input_mute
if (!Config::Get(Config::MAIN_WII_SPEAK_CONNECTED))
return nframes;
auto* mic = static_cast<Microphone*>(user_data); auto* mic = static_cast<Microphone*>(user_data);
return mic->DataCallback(static_cast<const s16*>(input_buffer), nframes); return mic->DataCallback(static_cast<const s16*>(input_buffer), nframes);
} }
@ -183,6 +195,10 @@ long Microphone::DataCallback(const s16* input_buffer, long nframes)
{ {
std::lock_guard lock(m_ring_lock); std::lock_guard lock(m_ring_lock);
// Skip data if sampling is off or mute is on
if (!m_sampler.sample_on || m_sampler.mute)
return nframes;
const s16* buff_in = static_cast<const s16*>(input_buffer); const s16* buff_in = static_cast<const s16*>(input_buffer);
for (long i = 0; i < nframes; i++) for (long i = 0; i < nframes; i++)
{ {
@ -229,9 +245,9 @@ void Microphone::ReadIntoBuffer(u8* dst, u32 size)
} }
} }
bool Microphone::HasData() const bool Microphone::HasData(u32 sample_count = BUFF_SIZE_SAMPLES) const
{ {
std::lock_guard lock(m_ring_lock); std::lock_guard lock(m_ring_lock);
return m_samples_avail > 0 && Config::Get(Config::MAIN_WII_SPEAK_CONNECTED); return m_samples_avail >= sample_count;
} }
} // namespace IOS::HLE::USB } // namespace IOS::HLE::USB

View File

@ -19,13 +19,15 @@ struct cubeb_stream;
namespace IOS::HLE::USB namespace IOS::HLE::USB
{ {
struct WiiSpeakState;
class Microphone final class Microphone final
{ {
public: public:
Microphone(); Microphone(const WiiSpeakState& sampler);
~Microphone(); ~Microphone();
bool HasData() const; bool HasData(u32 sample_count) const;
void ReadIntoBuffer(u8* dst, u32 size); void ReadIntoBuffer(u8* dst, u32 size);
private: private:
@ -53,6 +55,8 @@ private:
mutable std::mutex m_ring_lock; mutable std::mutex m_ring_lock;
const WiiSpeakState& m_sampler;
#ifdef HAVE_CUBEB #ifdef HAVE_CUBEB
std::shared_ptr<cubeb> m_cubeb_ctx = nullptr; std::shared_ptr<cubeb> m_cubeb_ctx = nullptr;
cubeb_stream* m_cubeb_stream = nullptr; cubeb_stream* m_cubeb_stream = nullptr;

View File

@ -43,7 +43,7 @@ bool WiiSpeak::Attach()
DEBUG_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Opening device", m_vid, m_pid); DEBUG_LOG_FMT(IOS_USB, "[{:04x}:{:04x}] Opening device", m_vid, m_pid);
if (!m_microphone) if (!m_microphone)
m_microphone = std::make_unique<Microphone>(); m_microphone = std::make_unique<Microphone>(m_sampler);
m_device_attached = true; m_device_attached = true;
return true; return true;
} }
@ -178,7 +178,7 @@ int WiiSpeak::SubmitTransfer(std::unique_ptr<IsoMessage> cmd)
{ {
case ENDPOINT_AUDIO_IN: case ENDPOINT_AUDIO_IN:
// Transfer: Wii Speak -> Wii // Transfer: Wii Speak -> Wii
if (m_microphone && m_microphone->HasData()) if (m_microphone && m_microphone->HasData(cmd->length / sizeof(s16)))
m_microphone->ReadIntoBuffer(packets, cmd->length); m_microphone->ReadIntoBuffer(packets, cmd->length);
break; break;
case ENDPOINT_AUDIO_OUT: case ENDPOINT_AUDIO_OUT:

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <atomic>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -12,6 +13,17 @@
namespace IOS::HLE::USB namespace IOS::HLE::USB
{ {
struct WiiSpeakState
{
// Use atomic for members concurrently used by the data callback
std::atomic<bool> sample_on;
std::atomic<bool> mute;
int freq;
int gain;
bool ec_reset;
bool sp_on;
};
class WiiSpeak final : public Device class WiiSpeak final : public Device
{ {
public: public:
@ -34,17 +46,7 @@ public:
int SubmitTransfer(std::unique_ptr<IsoMessage> message) override; int SubmitTransfer(std::unique_ptr<IsoMessage> message) override;
private: private:
struct WSState WiiSpeakState m_sampler{};
{
bool sample_on;
bool mute;
int freq;
int gain;
bool ec_reset;
bool sp_on;
};
WSState m_sampler{};
enum Registers enum Registers
{ {