mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
WiimoteEmu: Fix wiimote pan setting from keeping center at half volume.
This commit is contained in:
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
// Wiimote internal codes
|
// Wiimote internal codes
|
||||||
|
|
||||||
// Communication channels
|
// Communication channels
|
||||||
|
@ -128,13 +128,19 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RT_WRITE_SPEAKER_DATA:
|
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)
|
if (!m_speaker_mute)
|
||||||
{
|
{
|
||||||
auto sd = reinterpret_cast<const wm_speaker_data*>(sr->data);
|
auto sd = reinterpret_cast<const wm_speaker_data*>(sr->data);
|
||||||
if (sd->length > 20)
|
if (sd->length > ArraySize(sd->data))
|
||||||
PanicAlert("EmuWiimote: bad speaker data length!");
|
{
|
||||||
SpeakerData(sd->data, sd->length);
|
ERROR_LOG(WIIMOTE, "Bad speaker data length: %d", sd->length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SpeakerData(sd->data, sd->length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// No ACK:
|
// No ACK:
|
||||||
return;
|
return;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "AudioCommon/AudioCommon.h"
|
#include "AudioCommon/AudioCommon.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/MathUtil.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||||
@ -70,12 +71,15 @@ void stopdamnwav()
|
|||||||
|
|
||||||
void Wiimote::SpeakerData(const u8* data, int length)
|
void Wiimote::SpeakerData(const u8* data, int length)
|
||||||
{
|
{
|
||||||
|
// TODO: should we still process samples for the decoder state?
|
||||||
if (!SConfig::GetInstance().m_WiimoteEnableSpeaker)
|
if (!SConfig::GetInstance().m_WiimoteEnableSpeaker)
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
|
// Even if volume is zero we process samples to maintain proper decoder state.
|
||||||
|
|
||||||
// TODO consider using static max size instead of new
|
// TODO consider using static max size instead of new
|
||||||
std::unique_ptr<s16[]> samples(new s16[length * 2]);
|
std::unique_ptr<s16[]> samples(new s16[length * 2]);
|
||||||
|
|
||||||
@ -87,7 +91,7 @@ void Wiimote::SpeakerData(const u8* data, int length)
|
|||||||
// 8 bit PCM
|
// 8 bit PCM
|
||||||
for (int i = 0; i < length; ++i)
|
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
|
// 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
|
// Following details from http://wiibrew.org/wiki/Wiimote#Speaker
|
||||||
sample_rate_dividend = 6000000;
|
sample_rate_dividend = 6000000;
|
||||||
|
|
||||||
// 0 - 127
|
|
||||||
// TODO: does it go beyond 127 for format == 0x40?
|
|
||||||
volume_divisor = 0x7F;
|
volume_divisor = 0x7F;
|
||||||
sample_length = (unsigned int)length * 2;
|
sample_length = (unsigned int)length * 2;
|
||||||
}
|
}
|
||||||
@ -119,19 +120,23 @@ void Wiimote::SpeakerData(const u8* data, int length)
|
|||||||
return;
|
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
|
// Speaker Pan
|
||||||
// TODO: fix
|
// GUI clamps pan setting from -127 to 127. Why?
|
||||||
unsigned int vol = (unsigned int)(m_options->numeric_settings[0]->GetValue() * 100);
|
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;
|
float speaker_volume_ratio = (float)m_speaker_logic.reg_data.volume / volume_divisor;
|
||||||
unsigned int left_volume = (unsigned int)((128 + vol) * speaker_volume_ratio);
|
// Sloppy math:
|
||||||
unsigned int right_volume = (unsigned int)((128 - vol) * speaker_volume_ratio);
|
unsigned int left_volume =
|
||||||
|
MathUtil::Clamp<unsigned int>((0xff + (2 * pan)) * speaker_volume_ratio, 0, 0xff);
|
||||||
if (left_volume > 255)
|
unsigned int right_volume =
|
||||||
left_volume = 255;
|
MathUtil::Clamp<unsigned int>((0xff - (2 * pan)) * speaker_volume_ratio, 0, 0xff);
|
||||||
if (right_volume > 255)
|
|
||||||
right_volume = 255;
|
|
||||||
|
|
||||||
g_sound_stream->GetMixer()->SetWiimoteSpeakerVolume(left_volume, right_volume);
|
g_sound_stream->GetMixer()->SetWiimoteSpeakerVolume(left_volume, right_volume);
|
||||||
|
|
||||||
@ -161,4 +166,4 @@ void Wiimote::SpeakerData(const u8* data, int length)
|
|||||||
num++;
|
num++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
} // namespace WiimoteEmu
|
||||||
|
@ -1276,7 +1276,7 @@ void Wiimote::MotionPlusLogic::Update()
|
|||||||
|
|
||||||
// A real wiimote takes about 2 seconds to reach this state:
|
// A real wiimote takes about 2 seconds to reach this state:
|
||||||
reg_data.cert_ready = 0x1a;
|
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
|
// TODO: make sure a motion plus report is sent first after init
|
||||||
@ -1364,7 +1364,7 @@ void Wiimote::MotionPlusLogic::Update()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
PanicAlert("MotionPlus unknown passthrough-mode %d", GetPassthroughMode());
|
PanicAlert("MotionPlus unknown passthrough-mode %d", (int)GetPassthroughMode());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,6 +540,7 @@ private:
|
|||||||
|
|
||||||
static_assert(0x100 == sizeof(reg_data));
|
static_assert(0x100 == sizeof(reg_data));
|
||||||
|
|
||||||
|
// TODO: What actions should reset this state?
|
||||||
ADPCMState adpcm_state;
|
ADPCMState adpcm_state;
|
||||||
|
|
||||||
static const u8 DEVICE_ADDR = 0x51;
|
static const u8 DEVICE_ADDR = 0x51;
|
||||||
@ -564,6 +565,8 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
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);
|
return RawWrite(®_data, addr, count, data_in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user