diff --git a/AUTHORS b/AUTHORS
index 2c6aab6891..b6b06abc98 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -179,6 +179,9 @@ Nicholas Terry distributed under the MIT license.
Using MP3Sharp by Robert Bruke and Zane Wagner
licensed under the GNU LGPL Version 3.
+Using TagLib# by Stephen Shaw licensed under the
+GNU LGPL Version 2.1.
+
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
index 03eb81127b..745330bb43 100644
--- a/OpenRA.Mods.Common/AudioLoaders/Mp3Loader.cs
+++ b/OpenRA.Mods.Common/AudioLoaders/Mp3Loader.cs
@@ -9,6 +9,7 @@
*/
#endregion
+using System;
using System.IO;
using MP3Sharp;
using OpenRA.Primitives;
@@ -39,7 +40,7 @@ namespace OpenRA.Mods.Common.AudioLoaders
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 float LengthInSeconds { get; private set; }
public Stream GetPCMInputStream() { return new MP3Stream(Clone(this)); }
public void Dispose() { mp3.Dispose(); }
@@ -50,11 +51,38 @@ namespace OpenRA.Mods.Common.AudioLoaders
{
mp3 = new MP3Stream(stream);
this.stream = stream;
+
+ // Make a first guess based on the file size and bitrate
+ // This should be fine for constant bitrate files
+ LengthInSeconds = mp3.Length * 8f / (2f * Channels * SampleRate);
+
+ try
+ {
+ // Attempt to parse a more accurate length from the file metadata;
+ LengthInSeconds = (float)new TagLib.Mpeg.AudioFile(new StreamAbstraction(stream)).Properties.Duration.TotalSeconds;
+ }
+ catch { }
}
Stream Clone(Mp3Format cloneFrom)
{
return SegmentStream.CreateWithoutOwningStream(cloneFrom.stream, 0, (int)cloneFrom.stream.Length);
}
+
+ public class StreamAbstraction : TagLib.File.IFileAbstraction
+ {
+ readonly Stream s;
+ public StreamAbstraction(Stream s)
+ {
+ this.s = s;
+ }
+
+ public Stream ReadStream => s;
+
+ public Stream WriteStream => throw new NotImplementedException();
+
+ public void CloseStream(Stream stream) { }
+ public string Name => "";
+ }
}
}
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index ecd593b519..c0f6da3c32 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -7,6 +7,7 @@
+