Reworked ISoundFormat.LengthInSeconds implementations
This commit is contained in:
committed by
Matthias Mailänder
parent
631297417c
commit
87b92b53a4
@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Cnc.AudioLoaders
|
|||||||
public int Channels => channels;
|
public int Channels => channels;
|
||||||
public int SampleBits => sampleBits;
|
public int SampleBits => sampleBits;
|
||||||
public int SampleRate => sampleRate;
|
public int SampleRate => sampleRate;
|
||||||
public float LengthInSeconds { get; }
|
public float LengthInSeconds => lengthInSeconds;
|
||||||
public Stream GetPCMInputStream() { return audStreamFactory(); }
|
public Stream GetPCMInputStream() { return audStreamFactory(); }
|
||||||
public void Dispose() { sourceStream.Dispose(); }
|
public void Dispose() { sourceStream.Dispose(); }
|
||||||
|
|
||||||
@@ -61,15 +61,14 @@ namespace OpenRA.Mods.Cnc.AudioLoaders
|
|||||||
readonly int channels;
|
readonly int channels;
|
||||||
readonly int sampleBits;
|
readonly int sampleBits;
|
||||||
readonly int sampleRate;
|
readonly int sampleRate;
|
||||||
|
readonly float lengthInSeconds;
|
||||||
|
|
||||||
public AudFormat(Stream stream)
|
public AudFormat(Stream stream)
|
||||||
{
|
{
|
||||||
sourceStream = stream;
|
sourceStream = stream;
|
||||||
|
|
||||||
if (!AudReader.LoadSound(stream, out audStreamFactory, out sampleRate, out sampleBits, out channels))
|
if (!AudReader.LoadSound(stream, out audStreamFactory, out sampleRate, out sampleBits, out channels, out lengthInSeconds))
|
||||||
throw new InvalidDataException();
|
throw new InvalidDataException();
|
||||||
|
|
||||||
LengthInSeconds = AudReader.SoundLength(sourceStream);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Cnc.AudioLoaders
|
|||||||
{
|
{
|
||||||
public int SampleBits => 8;
|
public int SampleBits => 8;
|
||||||
public int Channels => 1;
|
public int Channels => 1;
|
||||||
public int SampleRate { get; private set; }
|
public int SampleRate { get; }
|
||||||
public float LengthInSeconds => (float)totalSamples / SampleRate;
|
public float LengthInSeconds => (float)totalSamples / SampleRate;
|
||||||
public Stream GetPCMInputStream() { return new VocStream(new VocFormat(this)); }
|
public Stream GetPCMInputStream() { return new VocStream(new VocFormat(this)); }
|
||||||
public void Dispose() { stream.Dispose(); }
|
public void Dispose() { stream.Dispose(); }
|
||||||
|
|||||||
@@ -32,28 +32,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
|
|
||||||
public static class AudReader
|
public static class AudReader
|
||||||
{
|
{
|
||||||
public static float SoundLength(Stream s)
|
public static bool LoadSound(Stream s, out Func<Stream> result, out int sampleRate, out int sampleBits, out int channels, out float lengthInSeconds)
|
||||||
{
|
|
||||||
var originalPosition = s.Position;
|
|
||||||
|
|
||||||
var sampleRate = s.ReadUInt16();
|
|
||||||
/*var dataSize = */ s.ReadInt32();
|
|
||||||
var outputSize = s.ReadInt32();
|
|
||||||
var flags = (SoundFlags)s.ReadByte();
|
|
||||||
|
|
||||||
var samples = outputSize;
|
|
||||||
if ((flags & SoundFlags.Stereo) != 0)
|
|
||||||
samples /= 2;
|
|
||||||
|
|
||||||
if ((flags & SoundFlags._16Bit) != 0)
|
|
||||||
samples /= 2;
|
|
||||||
|
|
||||||
s.Seek(originalPosition, SeekOrigin.Begin);
|
|
||||||
|
|
||||||
return (float)samples / sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool LoadSound(Stream s, out Func<Stream> result, out int sampleRate, out int sampleBits, out int channels)
|
|
||||||
{
|
{
|
||||||
result = null;
|
result = null;
|
||||||
var startPosition = s.Position;
|
var startPosition = s.Position;
|
||||||
@@ -62,9 +41,10 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
sampleRate = s.ReadUInt16();
|
sampleRate = s.ReadUInt16();
|
||||||
var dataSize = s.ReadInt32();
|
var dataSize = s.ReadInt32();
|
||||||
var outputSize = s.ReadInt32();
|
var outputSize = s.ReadInt32();
|
||||||
var readFlag = s.ReadByte();
|
var audioFlags = (SoundFlags)s.ReadByte();
|
||||||
sampleBits = (readFlag & (int)SoundFlags._16Bit) == 0 ? 8 : 16;
|
sampleBits = (audioFlags & SoundFlags._16Bit) == 0 ? 8 : 16;
|
||||||
channels = (readFlag & (int)SoundFlags.Stereo) == 0 ? 1 : 2;
|
channels = (audioFlags & SoundFlags.Stereo) == 0 ? 1 : 2;
|
||||||
|
lengthInSeconds = (float)(outputSize * 8) / (channels * sampleBits * sampleRate);
|
||||||
|
|
||||||
var readFormat = s.ReadByte();
|
var readFormat = s.ReadByte();
|
||||||
if (!Enum.IsDefined(typeof(SoundFormat), readFormat))
|
if (!Enum.IsDefined(typeof(SoundFormat), readFormat))
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ namespace OpenRA.Mods.Common.AudioLoaders
|
|||||||
|
|
||||||
public sealed class Mp3Format : ISoundFormat
|
public sealed class Mp3Format : ISoundFormat
|
||||||
{
|
{
|
||||||
public int Channels { get { return mp3.ChannelCount; } }
|
public int Channels => mp3.ChannelCount;
|
||||||
public int SampleBits { get { return 16; } }
|
public int SampleBits => 16;
|
||||||
public int SampleRate { get { return mp3.Frequency; } }
|
public int SampleRate => mp3.Frequency;
|
||||||
public float LengthInSeconds { get; private set; }
|
public float LengthInSeconds { get; }
|
||||||
public Stream GetPCMInputStream() { return new MP3Stream(Clone(this)); }
|
public Stream GetPCMInputStream() { return new MP3Stream(Clone(this)); }
|
||||||
public void Dispose() { mp3.Dispose(); }
|
public void Dispose() { mp3.Dispose(); }
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.AudioLoaders
|
|||||||
public int SampleBits => 16;
|
public int SampleBits => 16;
|
||||||
public int Channels => reader.Channels;
|
public int Channels => reader.Channels;
|
||||||
public int SampleRate => reader.SampleRate;
|
public int SampleRate => reader.SampleRate;
|
||||||
public float LengthInSeconds => (float)reader.TotalTime.TotalSeconds;
|
public float LengthInSeconds { get; }
|
||||||
public Stream GetPCMInputStream() { return new OggStream(new OggFormat(this)); }
|
public Stream GetPCMInputStream() { return new OggStream(new OggFormat(this)); }
|
||||||
public void Dispose() { reader.Dispose(); }
|
public void Dispose() { reader.Dispose(); }
|
||||||
|
|
||||||
@@ -51,6 +51,7 @@ namespace OpenRA.Mods.Common.AudioLoaders
|
|||||||
{
|
{
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
reader = new VorbisReader(stream);
|
reader = new VorbisReader(stream);
|
||||||
|
LengthInSeconds = (float) reader.TotalTime.TotalSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
OggFormat(OggFormat cloneFrom)
|
OggFormat(OggFormat cloneFrom)
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.AudioLoaders
|
|||||||
public int Channels => channels;
|
public int Channels => channels;
|
||||||
public int SampleBits => sampleBits;
|
public int SampleBits => sampleBits;
|
||||||
public int SampleRate => sampleRate;
|
public int SampleRate => sampleRate;
|
||||||
public float LengthInSeconds { get; }
|
public float LengthInSeconds => lengthInSeconds;
|
||||||
public Stream GetPCMInputStream() { return wavStreamFactory(); }
|
public Stream GetPCMInputStream() { return wavStreamFactory(); }
|
||||||
public void Dispose() { sourceStream.Dispose(); }
|
public void Dispose() { sourceStream.Dispose(); }
|
||||||
|
|
||||||
@@ -62,15 +62,14 @@ namespace OpenRA.Mods.Common.AudioLoaders
|
|||||||
readonly short channels;
|
readonly short channels;
|
||||||
readonly int sampleBits;
|
readonly int sampleBits;
|
||||||
readonly int sampleRate;
|
readonly int sampleRate;
|
||||||
|
readonly float lengthInSeconds;
|
||||||
|
|
||||||
public WavFormat(Stream stream)
|
public WavFormat(Stream stream)
|
||||||
{
|
{
|
||||||
sourceStream = stream;
|
sourceStream = stream;
|
||||||
|
|
||||||
if (!WavReader.LoadSound(stream, out wavStreamFactory, out channels, out sampleBits, out sampleRate))
|
if (!WavReader.LoadSound(stream, out wavStreamFactory, out channels, out sampleBits, out sampleRate, out lengthInSeconds))
|
||||||
throw new InvalidDataException();
|
throw new InvalidDataException();
|
||||||
|
|
||||||
LengthInSeconds = WavReader.WaveLength(sourceStream);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,13 @@ namespace OpenRA.Mods.Common.FileFormats
|
|||||||
{
|
{
|
||||||
enum WaveType { Pcm = 0x1, MsAdpcm = 0x2, ImaAdpcm = 0x11 }
|
enum WaveType { Pcm = 0x1, MsAdpcm = 0x2, ImaAdpcm = 0x11 }
|
||||||
|
|
||||||
public static bool LoadSound(Stream s, out Func<Stream> result, out short channels, out int sampleBits, out int sampleRate)
|
public static bool LoadSound(Stream s, out Func<Stream> result, out short channels, out int sampleBits, out int sampleRate, out float lengthInSeconds)
|
||||||
{
|
{
|
||||||
result = null;
|
result = null;
|
||||||
channels = -1;
|
channels = -1;
|
||||||
sampleBits = -1;
|
sampleBits = -1;
|
||||||
sampleRate = -1;
|
sampleRate = -1;
|
||||||
|
lengthInSeconds = -1;
|
||||||
|
|
||||||
var type = s.ReadASCII(4);
|
var type = s.ReadASCII(4);
|
||||||
if (type != "RIFF")
|
if (type != "RIFF")
|
||||||
@@ -65,6 +66,7 @@ namespace OpenRA.Mods.Common.FileFormats
|
|||||||
s.ReadInt32(); // Byte Rate
|
s.ReadInt32(); // Byte Rate
|
||||||
blockAlign = s.ReadInt16();
|
blockAlign = s.ReadInt16();
|
||||||
sampleBits = s.ReadInt16();
|
sampleBits = s.ReadInt16();
|
||||||
|
lengthInSeconds = (float)(s.Length * 8) / (channels * sampleRate * sampleBits);
|
||||||
s.ReadBytes(fmtChunkSize - 16);
|
s.ReadBytes(fmtChunkSize - 16);
|
||||||
break;
|
break;
|
||||||
case "fact":
|
case "fact":
|
||||||
@@ -107,25 +109,6 @@ namespace OpenRA.Mods.Common.FileFormats
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float WaveLength(Stream s)
|
|
||||||
{
|
|
||||||
s.Position = 12;
|
|
||||||
var fmt = s.ReadASCII(4);
|
|
||||||
|
|
||||||
if (fmt != "fmt ")
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
s.Position = 22;
|
|
||||||
var channels = s.ReadInt16();
|
|
||||||
var sampleRate = s.ReadInt32();
|
|
||||||
|
|
||||||
s.Position = 34;
|
|
||||||
var bitsPerSample = s.ReadInt16();
|
|
||||||
var length = s.Length * 8;
|
|
||||||
|
|
||||||
return (float)length / (channels * sampleRate * bitsPerSample);
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class WavStreamImaAdpcm : ReadOnlyAdapterStream
|
sealed class WavStreamImaAdpcm : ReadOnlyAdapterStream
|
||||||
{
|
{
|
||||||
readonly short channels;
|
readonly short channels;
|
||||||
|
|||||||
Reference in New Issue
Block a user