mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-22 22:00:39 -06:00
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:
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user