From 8abe9622fd125f86e95d1ba62f6f2b16ff93791f Mon Sep 17 00:00:00 2001
From: skidau <skidau@gmail.com>
Date: Sat, 6 Sep 2014 01:23:54 +1000
Subject: [PATCH] Route the wiimote speaker to the sound mixer (the host
 system's speakers). Emulated Wiimote speaker sounds will go to the host
 system's speakers. Real Wiimotes will continue to use their own speaker for
 Wiimote speaker sounds. All Wiimote speaker sound can be disabled by
 unchecking the "Enable Speaker Data" option.

Each emulated Wiimote can have its speaker routed from left to right via the "Speaker Pan" setting in the emulated wiimote settings dialog.  Use any value from -127 for leftmost to 127 for rightmost with 0 being the centre.

Added code in the InputConfig to use a spin control for non-boolean values.

Defaulted the setting of "Enable Speaker Data" to disabled.
---
 Source/Core/AudioCommon/Mixer.cpp             | 13 ++-------
 Source/Core/AudioCommon/Mixer.h               |  2 +-
 Source/Core/Core/ConfigManager.cpp            |  2 +-
 Source/Core/Core/HW/WiimoteEmu/Speaker.cpp    | 16 ++++++++---
 Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp |  1 +
 Source/Core/DolphinWX/InputConfigDiag.cpp     | 28 +++++++++++++------
 6 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp
index 0a71fbd98b..a7984579ca 100644
--- a/Source/Core/AudioCommon/Mixer.cpp
+++ b/Source/Core/AudioCommon/Mixer.cpp
@@ -168,7 +168,7 @@ void CMixer::PushStreamingSamples(const short *samples, unsigned int num_samples
 	m_streaming_mixer.PushSamples(samples, num_samples);
 }
 
-void CMixer::PushWiimoteSpeakerSamples(const short *samples, unsigned int num_samples, unsigned int sample_rate, const u8 wiimote_index)
+void CMixer::PushWiimoteSpeakerSamples(const short *samples, unsigned int num_samples, unsigned int sample_rate)
 {
 	short samples_stereo[MAX_SAMPLES * 2];
 
@@ -178,15 +178,8 @@ void CMixer::PushWiimoteSpeakerSamples(const short *samples, unsigned int num_sa
 
 		for (unsigned int i = 0; i < num_samples; ++i)
 		{
-			// Position the Wiimotes as follow
-			// Wiimote 0 = Center
-			// Wiimote 1 = Left
-			// Wiimote 2 = Right
-			// Wiimote 3 = Center
-			if (wiimote_index != 2)
-				samples_stereo[i * 2] = Common::swap16(samples[i]);
-			if (wiimote_index != 1)
-				samples_stereo[i * 2 + 1] = Common::swap16(samples[i]);
+			samples_stereo[i * 2] = Common::swap16(samples[i]);
+			samples_stereo[i * 2 + 1] = Common::swap16(samples[i]);
 		}
 
 		m_wiimote_speaker_mixer.PushSamples(samples_stereo, num_samples);
diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h
index f12066d22f..e3272af070 100644
--- a/Source/Core/AudioCommon/Mixer.h
+++ b/Source/Core/AudioCommon/Mixer.h
@@ -40,7 +40,7 @@ public:
 	// Called from main thread
 	virtual void PushSamples(const short* samples, unsigned int num_samples);
 	virtual void PushStreamingSamples(const short* samples, unsigned int num_samples);
-	virtual void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples, unsigned int sample_rate, const u8 wiimote_index);
+	virtual void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples, unsigned int sample_rate);
 	unsigned int GetSampleRate() const { return m_sampleRate; }
 
 	void SetDMAInputSampleRate(unsigned int rate);
diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp
index 45770e961c..1b2975bd42 100644
--- a/Source/Core/Core/ConfigManager.cpp
+++ b/Source/Core/Core/ConfigManager.cpp
@@ -521,7 +521,7 @@ void SConfig::LoadCoreSettings(IniFile& ini)
 	core->Get("WiiSDCard",                 &m_WiiSDCard,                                   false);
 	core->Get("WiiKeyboard",               &m_WiiKeyboard,                                 false);
 	core->Get("WiimoteContinuousScanning", &m_WiimoteContinuousScanning,                   false);
-	core->Get("WiimoteEnableSpeaker",      &m_WiimoteEnableSpeaker,                        true);
+	core->Get("WiimoteEnableSpeaker",      &m_WiimoteEnableSpeaker,                        false);
 	core->Get("RunCompareServer",          &m_LocalCoreStartupParameter.bRunCompareServer, false);
 	core->Get("RunCompareClient",          &m_LocalCoreStartupParameter.bRunCompareClient, false);
 	core->Get("MMU",                       &m_LocalCoreStartupParameter.bMMU,              false);
diff --git a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp
index a0e374cf23..2dd6b2d0e1 100644
--- a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp
@@ -78,8 +78,12 @@ void Wiimote::SpeakerData(wm_speaker_data* sd)
 		{
 			samples[i] = (s16)(s8)sd->data[i];
 		}
-		soundStream->GetMixer()->SetWiimoteSpeakerVolume(256, 256);
-		soundStream->GetMixer()->PushWiimoteSpeakerSamples(samples, sd->length, 1500, m_index);
+
+		// Speaker Pan
+		unsigned int vol = (unsigned int)(m_options->settings[4]->GetValue() * 100);
+		soundStream->GetMixer()->SetWiimoteSpeakerVolume(128 + vol, 128 - vol);
+
+		soundStream->GetMixer()->PushWiimoteSpeakerSamples(samples, sd->length, 1500);
 	}
 	else if (m_reg_speaker.format == 0x00)
 	{
@@ -89,8 +93,12 @@ void Wiimote::SpeakerData(wm_speaker_data* sd)
 			samples[i * 2] = adpcm_yamaha_expand_nibble(m_adpcm_state, (sd->data[i] >> 4) & 0xf);
 			samples[i * 2 + 1] = adpcm_yamaha_expand_nibble(m_adpcm_state, sd->data[i] & 0xf);
 		}
-		soundStream->GetMixer()->SetWiimoteSpeakerVolume(256, 256);
-		soundStream->GetMixer()->PushWiimoteSpeakerSamples(samples, sd->length, 3000, m_index);
+
+		// Speaker Pan
+		unsigned int vol = (unsigned int)(m_options->settings[4]->GetValue() * 100);
+		soundStream->GetMixer()->SetWiimoteSpeakerVolume(128 + vol, 128 - vol);
+
+		soundStream->GetMixer()->PushWiimoteSpeakerSamples(samples, sd->length, 3000);
 	}
 
 #ifdef WIIMOTE_SPEAKER_DUMP
diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
index 9dca20802a..c0bd342e8e 100644
--- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
@@ -309,6 +309,7 @@ Wiimote::Wiimote( const unsigned int index )
 	m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Sideways Wiimote"), false));
 	m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Upright Wiimote"), false));
 	m_options->settings.emplace_back(new ControlGroup::IterateUI(_trans("Iterative Input")));
+	m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Speaker Pan"), 0, -127, 127));
 
 	// TODO: This value should probably be re-read if SYSCONF gets changed
 	m_sensor_bar_on_top = SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.BAR") != 0;
diff --git a/Source/Core/DolphinWX/InputConfigDiag.cpp b/Source/Core/DolphinWX/InputConfigDiag.cpp
index 378b8729a0..010732eb79 100644
--- a/Source/Core/DolphinWX/InputConfigDiag.cpp
+++ b/Source/Core/DolphinWX/InputConfigDiag.cpp
@@ -911,19 +911,31 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
 			//options
 			for (auto& groupSetting : group->settings)
 			{
-				PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, groupSetting.get());
-				if (groupSetting.get()->is_iterate == true)
+				if (groupSetting.get()->high == 100)
 				{
-					setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSettingUI, eventsink);
-					groupSetting.get()->value = 0;
+					PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, groupSetting.get());
+					if (groupSetting.get()->is_iterate == true)
+					{
+						setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSettingUI, eventsink);
+						groupSetting.get()->value = 0;
+					}
+					else
+					{
+						setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSetting, eventsink);
+					}
+					options.push_back(setting_cbox);
+					Add(setting_cbox->wxcontrol, 0, wxALL | wxLEFT, 5);
 				}
 				else
 				{
-					setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSetting, eventsink);
+					PadSettingSpin* setting = new PadSettingSpin(parent, groupSetting.get());
+					setting->wxcontrol->Bind(wxEVT_SPINCTRL, &GamepadPage::AdjustSetting, eventsink);
+					options.push_back(setting);
+					wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
+					szr->Add(new wxStaticText(parent, -1, wxGetTranslation(StrToWxStr(groupSetting->name))), 0, wxCENTER | wxRIGHT, 3);
+					szr->Add(setting->wxcontrol, 0, wxRIGHT, 3);
+					Add(szr, 0, wxALL | wxCENTER, 3);
 				}
-				options.push_back(setting_cbox);
-
-				Add(setting_cbox->wxcontrol, 0, wxALL|wxLEFT, 5);
 			}
 		}
 		break;