diff --git a/AUTHORS b/AUTHORS
index b63b43ca0d..2c6aab6891 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -176,6 +176,9 @@ Kaluzhny and released under the GNU GPL terms.
Using Mono.Nat by Alan McGovern, Ben Motmans,
Nicholas Terry distributed under the MIT license.
+Using MP3Sharp by Robert Bruke and Zane Wagner
+licensed under the GNU LGPL Version 3.
+
Using ICSharpCode.SharpZipLib initially by Mike
Krueger and distributed under the GNU GPL terms.
diff --git a/OpenRA.Mods.Common/AudioLoaders/Mp3Loader.cs b/OpenRA.Mods.Common/AudioLoaders/Mp3Loader.cs
new file mode 100644
index 0000000000..03eb81127b
--- /dev/null
+++ b/OpenRA.Mods.Common/AudioLoaders/Mp3Loader.cs
@@ -0,0 +1,60 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
+ * This file is part of OpenRA, which is free software. It is made
+ * available to you under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System.IO;
+using MP3Sharp;
+using OpenRA.Primitives;
+
+namespace OpenRA.Mods.Common.AudioLoaders
+{
+ public class Mp3Loader : ISoundLoader
+ {
+ bool ISoundLoader.TryParseSound(Stream stream, out ISoundFormat sound)
+ {
+ try
+ {
+ sound = new Mp3Format(stream);
+ return true;
+ }
+ catch
+ {
+ // Not a (supported) MP3
+ }
+
+ sound = null;
+ return false;
+ }
+ }
+
+ public sealed class Mp3Format : ISoundFormat
+ {
+ public int Channels { get { return mp3.ChannelCount; } }
+ public int SampleBits { get { return 16; } }
+ public int SampleRate { get { return mp3.Frequency; } }
+ public float LengthInSeconds { get { return mp3.Length * 8f / (2f * Channels * SampleRate); } }
+ public Stream GetPCMInputStream() { return new MP3Stream(Clone(this)); }
+ public void Dispose() { mp3.Dispose(); }
+
+ readonly MP3Stream mp3;
+ readonly Stream stream;
+
+ public Mp3Format(Stream stream)
+ {
+ mp3 = new MP3Stream(stream);
+ this.stream = stream;
+ }
+
+ Stream Clone(Mp3Format cloneFrom)
+ {
+ return SegmentStream.CreateWithoutOwningStream(cloneFrom.stream, 0, (int)cloneFrom.stream.Length);
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 19695eed59..ecd593b519 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -6,6 +6,7 @@
+