Reworked ISoundFormat.LengthInSeconds implementations

This commit is contained in:
penev92
2022-01-04 23:13:56 +02:00
committed by Matthias Mailänder
parent 631297417c
commit 87b92b53a4
7 changed files with 21 additions and 59 deletions

View File

@@ -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);
} }
} }
} }

View File

@@ -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(); }

View File

@@ -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))

View File

@@ -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(); }

View File

@@ -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)

View File

@@ -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);
} }
} }
} }

View File

@@ -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;