Merge pull request #10482 from Mailaender/ra2-wav
Fixed crashes with Red Alert 2 wav files
This commit is contained in:
@@ -125,12 +125,12 @@ namespace OpenRA.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 readFormat = s.ReadByte();
|
|
||||||
|
|
||||||
|
var readFlag = s.ReadByte();
|
||||||
if (!Enum.IsDefined(typeof(SoundFlags), readFlag))
|
if (!Enum.IsDefined(typeof(SoundFlags), readFlag))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
var readFormat = s.ReadByte();
|
||||||
if (!Enum.IsDefined(typeof(SoundFormat), readFormat))
|
if (!Enum.IsDefined(typeof(SoundFormat), readFormat))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -170,6 +170,7 @@ namespace OpenRA.FileFormats
|
|||||||
out int sampleRate)
|
out int sampleRate)
|
||||||
{
|
{
|
||||||
channels = sampleBits = sampleRate = 0;
|
channels = sampleBits = sampleRate = 0;
|
||||||
|
var position = stream.Position;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -182,11 +183,15 @@ namespace OpenRA.FileFormats
|
|||||||
// If not, it will simply return false so we know we can't use it. If it is, it will start
|
// If not, it will simply return false so we know we can't use it. If it is, it will start
|
||||||
// parsing the data without any further failsafes, which means that it will crash on corrupted files
|
// parsing the data without any further failsafes, which means that it will crash on corrupted files
|
||||||
// (that end prematurely or otherwise don't conform to the specifications despite the headers being OK).
|
// (that end prematurely or otherwise don't conform to the specifications despite the headers being OK).
|
||||||
Log.Write("debug", "Failed to parse AUD file {0}. Error message:".F(fileName));
|
Log.Write("sound", "Failed to parse AUD file {0}. Error message:".F(fileName));
|
||||||
Log.Write("debug", e.ToString());
|
Log.Write("sound", e.ToString());
|
||||||
rawData = null;
|
rawData = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stream.Position = position;
|
||||||
|
}
|
||||||
|
|
||||||
channels = 1;
|
channels = 1;
|
||||||
sampleBits = 16;
|
sampleBits = 16;
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace OpenRA.FileFormats
|
|||||||
{
|
{
|
||||||
bool ISoundLoader.TryParseSound(Stream stream, string fileName, out byte[] rawData, out int channels, out int sampleBits, out int sampleRate)
|
bool ISoundLoader.TryParseSound(Stream stream, string fileName, out byte[] rawData, out int channels, out int sampleBits, out int sampleRate)
|
||||||
{
|
{
|
||||||
|
var position = stream.Position;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var vocStream = new VocStream(stream);
|
var vocStream = new VocStream(stream);
|
||||||
@@ -33,6 +35,10 @@ namespace OpenRA.FileFormats
|
|||||||
channels = sampleBits = sampleRate = 0;
|
channels = sampleBits = sampleRate = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stream.Position = position;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ namespace OpenRA.FileFormats
|
|||||||
Format = s.ReadASCII(4);
|
Format = s.ReadASCII(4);
|
||||||
if (Format != "WAVE")
|
if (Format != "WAVE")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (s.Position < s.Length)
|
while (s.Position < s.Length)
|
||||||
{
|
{
|
||||||
if ((s.Position & 1) == 1)
|
if ((s.Position & 1) == 1)
|
||||||
@@ -57,8 +56,8 @@ namespace OpenRA.FileFormats
|
|||||||
AudioFormat = s.ReadInt16();
|
AudioFormat = s.ReadInt16();
|
||||||
Type = (WaveType)AudioFormat;
|
Type = (WaveType)AudioFormat;
|
||||||
|
|
||||||
if (Type != WaveType.Pcm && Type != WaveType.ImaAdpcm)
|
if (!Enum.IsDefined(typeof(WaveType), Type))
|
||||||
throw new NotSupportedException("Compression type is not supported.");
|
throw new NotSupportedException("Compression type {0} is not supported.".F(AudioFormat));
|
||||||
|
|
||||||
Channels = s.ReadInt16();
|
Channels = s.ReadInt16();
|
||||||
SampleRate = s.ReadInt32();
|
SampleRate = s.ReadInt32();
|
||||||
@@ -69,24 +68,17 @@ namespace OpenRA.FileFormats
|
|||||||
s.ReadBytes(FmtChunkSize - 16);
|
s.ReadBytes(FmtChunkSize - 16);
|
||||||
break;
|
break;
|
||||||
case "fact":
|
case "fact":
|
||||||
{
|
var chunkSize = s.ReadInt32();
|
||||||
var chunkSize = s.ReadInt32();
|
UncompressedSize = s.ReadInt32();
|
||||||
UncompressedSize = s.ReadInt32();
|
s.ReadBytes(chunkSize - 4);
|
||||||
s.ReadBytes(chunkSize - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "data":
|
case "data":
|
||||||
DataSize = s.ReadInt32();
|
DataSize = s.ReadInt32();
|
||||||
RawOutput = s.ReadBytes(DataSize);
|
RawOutput = s.ReadBytes(DataSize);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Ignore unknown chunks
|
var unknownChunkSize = s.ReadInt32();
|
||||||
{
|
s.ReadBytes(unknownChunkSize);
|
||||||
var chunkSize = s.ReadInt32();
|
|
||||||
s.ReadBytes(chunkSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,6 +181,7 @@ namespace OpenRA.FileFormats
|
|||||||
{
|
{
|
||||||
rawData = null;
|
rawData = null;
|
||||||
channels = sampleBits = sampleRate = 0;
|
channels = sampleBits = sampleRate = 0;
|
||||||
|
var position = stream.Position;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -201,10 +194,14 @@ namespace OpenRA.FileFormats
|
|||||||
// If not, it will simply return false so we know we can't use it. If it is, it will start
|
// If not, it will simply return false so we know we can't use it. If it is, it will start
|
||||||
// parsing the data without any further failsafes, which means that it will crash on corrupted files
|
// parsing the data without any further failsafes, which means that it will crash on corrupted files
|
||||||
// (that end prematurely or otherwise don't conform to the specifications despite the headers being OK).
|
// (that end prematurely or otherwise don't conform to the specifications despite the headers being OK).
|
||||||
Log.Write("debug", "Failed to parse WAV file {0}. Error message:".F(fileName));
|
Log.Write("sound", "Failed to parse WAV file {0}. Error message:".F(fileName));
|
||||||
Log.Write("debug", e.ToString());
|
Log.Write("sound", e.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stream.Position = position;
|
||||||
|
}
|
||||||
|
|
||||||
rawData = RawOutput;
|
rawData = RawOutput;
|
||||||
channels = Channels;
|
channels = Channels;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace OpenRA.Primitives
|
|||||||
public Stream Stream2 { get; set; }
|
public Stream Stream2 { get; set; }
|
||||||
|
|
||||||
long VirtualLength { get; set; }
|
long VirtualLength { get; set; }
|
||||||
|
long position;
|
||||||
|
|
||||||
public MergedStream(Stream stream1, Stream stream2)
|
public MergedStream(Stream stream1, Stream stream2)
|
||||||
{
|
{
|
||||||
@@ -35,8 +36,6 @@ namespace OpenRA.Primitives
|
|||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
var position = Position;
|
|
||||||
|
|
||||||
switch (origin)
|
switch (origin)
|
||||||
{
|
{
|
||||||
case SeekOrigin.Begin:
|
case SeekOrigin.Begin:
|
||||||
@@ -52,9 +51,9 @@ namespace OpenRA.Primitives
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (position >= Stream1.Length)
|
if (position >= Stream1.Length)
|
||||||
Position = Stream1.Length + Stream2.Seek(offset - Stream1.Length, SeekOrigin.Begin);
|
position = Stream1.Length + Stream2.Seek(offset - Stream1.Length, SeekOrigin.Begin);
|
||||||
else
|
else
|
||||||
Position = Stream1.Seek(offset, SeekOrigin.Begin);
|
position = Stream1.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
@@ -68,7 +67,7 @@ namespace OpenRA.Primitives
|
|||||||
{
|
{
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
|
|
||||||
if (Position >= Stream1.Length)
|
if (position >= Stream1.Length)
|
||||||
bytesRead = Stream2.Read(buffer, offset, count);
|
bytesRead = Stream2.Read(buffer, offset, count);
|
||||||
else if (count > Stream1.Length)
|
else if (count > Stream1.Length)
|
||||||
{
|
{
|
||||||
@@ -78,14 +77,14 @@ namespace OpenRA.Primitives
|
|||||||
else
|
else
|
||||||
bytesRead = Stream1.Read(buffer, offset, count);
|
bytesRead = Stream1.Read(buffer, offset, count);
|
||||||
|
|
||||||
Position += bytesRead;
|
position += bytesRead;
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (Position >= Stream1.Length)
|
if (position >= Stream1.Length)
|
||||||
Stream2.Write(buffer, offset - (int)Stream1.Length, count);
|
Stream2.Write(buffer, offset - (int)Stream1.Length, count);
|
||||||
else
|
else
|
||||||
Stream1.Write(buffer, offset, count);
|
Stream1.Write(buffer, offset, count);
|
||||||
@@ -111,6 +110,10 @@ namespace OpenRA.Primitives
|
|||||||
get { return VirtualLength; }
|
get { return VirtualLength; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long Position { get; set; }
|
public override long Position
|
||||||
|
{
|
||||||
|
get { return position; }
|
||||||
|
set { Seek(value, SeekOrigin.Begin); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,11 +63,8 @@ namespace OpenRA
|
|||||||
int sampleBits;
|
int sampleBits;
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
foreach (var loader in Game.ModData.SoundLoaders)
|
foreach (var loader in Game.ModData.SoundLoaders)
|
||||||
{
|
|
||||||
stream.Position = 0;
|
|
||||||
if (loader.TryParseSound(stream, filename, out rawData, out channels, out sampleBits, out sampleRate))
|
if (loader.TryParseSound(stream, filename, out rawData, out channels, out sampleBits, out sampleRate))
|
||||||
return soundEngine.AddSoundSourceFromMemory(rawData, channels, sampleBits, sampleRate);
|
return soundEngine.AddSoundSourceFromMemory(rawData, channels, sampleBits, sampleRate);
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidDataException(filename + " is not a valid sound file!");
|
throw new InvalidDataException(filename + " is not a valid sound file!");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user