diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h
index 742f877fa2..eb1d4cdcf2 100644
--- a/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h
+++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h
@@ -149,11 +149,12 @@ static_assert(sizeof(OutputReportReadData) == 6, "Wrong size");
 struct OutputReportSpeakerData
 {
   static constexpr OutputReportID REPORT_ID = OutputReportID::SpeakerData;
+  static constexpr size_t DATA_SIZE = 20;
 
   u8 rumble : 1;
   u8 : 2;
   u8 length : 5;
-  u8 data[20];
+  std::array<u8, DATA_SIZE> data;
 };
 static_assert(sizeof(OutputReportSpeakerData) == 21, "Wrong size");
 
diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
index 7c3202cc0b..46a4c417d8 100644
--- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
@@ -390,7 +390,7 @@ void Wiimote::HandleSpeakerData(const WiimoteCommon::OutputReportSpeakerData& rp
     {
       // Speaker data reports result in a write to the speaker hardware at offset 0x00.
       m_i2c_bus.BusWrite(SpeakerLogic::I2C_ADDR, SpeakerLogic::SPEAKER_DATA_OFFSET, rpt.length,
-                         rpt.data);
+                         std::data(rpt.data));
     }
   }
 
diff --git a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp
index f42a76ef6b..3b308891c6 100644
--- a/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp
+++ b/Source/Core/Core/HW/WiimoteEmu/Speaker.cpp
@@ -3,14 +3,17 @@
 
 #include "Core/HW/WiimoteEmu/Speaker.h"
 
-#include <memory>
+#include <cassert>
 
 #include "AudioCommon/AudioCommon.h"
+
 #include "Common/CommonTypes.h"
 #include "Common/Logging/Log.h"
+
 #include "Core/ConfigManager.h"
 #include "Core/HW/WiimoteEmu/WiimoteEmu.h"
 #include "Core/System.h"
+
 #include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
 #include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
 
@@ -62,8 +65,9 @@ void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan)
 
   // 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<s16[]> samples(new s16[length * 2]);
+  // Potentially 40 resulting samples.
+  std::array<s16, WiimoteCommon::OutputReportSpeakerData::DATA_SIZE * 2> samples;
+  assert(length * 2 <= samples.size());
 
   unsigned int sample_rate_dividend, sample_length;
   u8 volume_divisor;
@@ -130,7 +134,7 @@ void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan)
   // ADPCM sample rate is thought to be x2.(3000 x2 = 6000).
   const unsigned int sample_rate = sample_rate_dividend / reg_data.sample_rate;
   sound_stream->GetMixer()->PushWiimoteSpeakerSamples(
-      samples.get(), sample_length, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / (sample_rate * 2));
+      samples.data(), sample_length, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / (sample_rate * 2));
 }
 
 void SpeakerLogic::Reset()