diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h index 833a664bdfb6..a72776dbcd97 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h @@ -4,6 +4,8 @@ #pragma once +#include "Common/CommonTypes.h" + // Wiimote internal codes // Communication channels diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index 278858d5f4b3..25f0726dedbc 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -128,13 +128,19 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) break; case RT_WRITE_SPEAKER_DATA: - // Not sure if speaker mute stops the bus write on real hardware, but it's not that important + // TODO: Does speaker mute stop speaker data processing? + // (important to keep decoder in proper state) if (!m_speaker_mute) { auto sd = reinterpret_cast(sr->data); - if (sd->length > 20) - PanicAlert("EmuWiimote: bad speaker data length!"); - SpeakerData(sd->data, sd->length); + if (sd->length > ArraySize(sd->data)) + { + ERROR_LOG(WIIMOTE, "Bad speaker data length: %d", sd->length); + } + else + { + SpeakerData(sd->data, sd->length); + } } // No ACK: return; diff --git a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp index 2f81af1a0fee..4f99a92ee70e 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp @@ -7,6 +7,7 @@ #include "AudioCommon/AudioCommon.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" +#include "Common/MathUtil.h" #include "Core/ConfigManager.h" #include "Core/HW/WiimoteEmu/WiimoteEmu.h" #include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" @@ -70,12 +71,15 @@ void stopdamnwav() void Wiimote::SpeakerData(const u8* data, int length) { + // TODO: should we still process samples for the decoder state? if (!SConfig::GetInstance().m_WiimoteEnableSpeaker) return; - if (m_speaker_logic.reg_data.volume == 0 || m_speaker_logic.reg_data.sample_rate == 0 || - length == 0) + + if (m_speaker_logic.reg_data.sample_rate == 0 || length == 0) return; + // Even if volume is zero we process samples to maintain proper decoder state. + // TODO consider using static max size instead of new std::unique_ptr samples(new s16[length * 2]); @@ -87,7 +91,7 @@ void Wiimote::SpeakerData(const u8* data, int length) // 8 bit PCM for (int i = 0; i < length; ++i) { - samples[i] = ((s16)(s8)data[i]) << 8; + samples[i] = ((s16)(s8)data[i]) * 0x100; } // Following details from http://wiibrew.org/wiki/Wiimote#Speaker @@ -107,9 +111,6 @@ void Wiimote::SpeakerData(const u8* data, int length) // Following details from http://wiibrew.org/wiki/Wiimote#Speaker sample_rate_dividend = 6000000; - - // 0 - 127 - // TODO: does it go beyond 127 for format == 0x40? volume_divisor = 0x7F; sample_length = (unsigned int)length * 2; } @@ -119,19 +120,23 @@ void Wiimote::SpeakerData(const u8* data, int length) return; } + if (m_speaker_logic.reg_data.volume > volume_divisor) + { + DEBUG_LOG(IOS_WIIMOTE, "Wiimote volume is higher than suspected maximum!"); + volume_divisor = m_speaker_logic.reg_data.volume; + } + // Speaker Pan - // TODO: fix - unsigned int vol = (unsigned int)(m_options->numeric_settings[0]->GetValue() * 100); + // GUI clamps pan setting from -127 to 127. Why? + const auto pan = (unsigned int)(m_options->numeric_settings[0]->GetValue() * 100); - unsigned int sample_rate = sample_rate_dividend / m_speaker_logic.reg_data.sample_rate; + const unsigned int sample_rate = sample_rate_dividend / m_speaker_logic.reg_data.sample_rate; float speaker_volume_ratio = (float)m_speaker_logic.reg_data.volume / volume_divisor; - unsigned int left_volume = (unsigned int)((128 + vol) * speaker_volume_ratio); - unsigned int right_volume = (unsigned int)((128 - vol) * speaker_volume_ratio); - - if (left_volume > 255) - left_volume = 255; - if (right_volume > 255) - right_volume = 255; + // Sloppy math: + unsigned int left_volume = + MathUtil::Clamp((0xff + (2 * pan)) * speaker_volume_ratio, 0, 0xff); + unsigned int right_volume = + MathUtil::Clamp((0xff - (2 * pan)) * speaker_volume_ratio, 0, 0xff); g_sound_stream->GetMixer()->SetWiimoteSpeakerVolume(left_volume, right_volume); @@ -161,4 +166,4 @@ void Wiimote::SpeakerData(const u8* data, int length) num++; #endif } -} +} // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index 021d34c0a9cc..603f3cb7bac7 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -1276,7 +1276,7 @@ void Wiimote::MotionPlusLogic::Update() // A real wiimote takes about 2 seconds to reach this state: reg_data.cert_ready = 0x1a; - INFO_LOG(WIIMOTE, "M+ cert 2 ready!", reg_data.cert_ready); + INFO_LOG(WIIMOTE, "M+ cert 2 ready!"); } // TODO: make sure a motion plus report is sent first after init @@ -1364,7 +1364,7 @@ void Wiimote::MotionPlusLogic::Update() break; } default: - PanicAlert("MotionPlus unknown passthrough-mode %d", GetPassthroughMode()); + PanicAlert("MotionPlus unknown passthrough-mode %d", (int)GetPassthroughMode()); break; } } diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index bee711cb875a..ebb1c973979f 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -540,6 +540,7 @@ class Wiimote : public ControllerEmu::EmulatedController static_assert(0x100 == sizeof(reg_data)); + // TODO: What actions should reset this state? ADPCMState adpcm_state; static const u8 DEVICE_ADDR = 0x51; @@ -564,6 +565,8 @@ class Wiimote : public ControllerEmu::EmulatedController } else { + // TODO: Does writing immediately change the decoder config even when active + // or does a write to 0x08 activate the new configuration or something? return RawWrite(®_data, addr, count, data_in); } }