Use spans to improve performance in StreamExts.
Also avoid ReadBytes calls that allocate a buffer by either updating the stream position (if not interested in the bytes), by reusing an input buffer (if interested in the bytes), or using a stackalloc buffer to avoid the allocation (for small reads).
This commit is contained in:
@@ -150,6 +150,8 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
{
|
||||
readonly int outputSize;
|
||||
int dataSize;
|
||||
byte[] inputBuffer;
|
||||
byte[] outputBuffer;
|
||||
|
||||
public WestwoodCompressedAudStream(Stream stream, int outputSize, int dataSize)
|
||||
: base(stream)
|
||||
@@ -167,8 +169,10 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
|
||||
var chunk = AudChunk.Read(baseStream);
|
||||
|
||||
var input = baseStream.ReadBytes(chunk.CompressedSize);
|
||||
var output = new byte[chunk.OutputSize];
|
||||
var input = EnsureArraySize(ref inputBuffer, chunk.CompressedSize);
|
||||
var output = EnsureArraySize(ref outputBuffer, chunk.OutputSize);
|
||||
|
||||
baseStream.ReadBytes(input);
|
||||
WestwoodCompressedReader.DecodeWestwoodCompressedSample(input, output);
|
||||
|
||||
foreach (var b in output)
|
||||
@@ -178,6 +182,13 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
|
||||
return dataSize <= 0;
|
||||
}
|
||||
|
||||
static Span<byte> EnsureArraySize(ref byte[] array, int desiredSize)
|
||||
{
|
||||
if (array == null || array.Length < desiredSize)
|
||||
array = new byte[desiredSize];
|
||||
return array.AsSpan(..desiredSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
Transforms[c + 15] = 1;
|
||||
|
||||
for (var k = 0; k < 12; k++)
|
||||
Transforms[c + ids[k]] = s.ReadFloat();
|
||||
Transforms[c + ids[k]] = s.ReadSingle();
|
||||
|
||||
Array.Copy(Transforms, 16 * (LimbCount * j + i), testMatrix, 0, 16);
|
||||
if (Util.MatrixInverse(testMatrix) == null)
|
||||
|
||||
@@ -199,16 +199,16 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
else if (AudioChannels == 1)
|
||||
{
|
||||
var rawAudio = stream.ReadBytes((int)length);
|
||||
audio1.WriteArray(rawAudio);
|
||||
audio1.Write(rawAudio);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rawAudio = stream.ReadBytes((int)length / 2);
|
||||
audio1.WriteArray(rawAudio);
|
||||
audio1.Write(rawAudio);
|
||||
rawAudio = stream.ReadBytes((int)length / 2);
|
||||
audio2.WriteArray(rawAudio);
|
||||
audio2.Write(rawAudio);
|
||||
if (length % 2 != 0)
|
||||
stream.ReadBytes(2);
|
||||
stream.Position += 2;
|
||||
}
|
||||
|
||||
compressed = type == "SND2";
|
||||
@@ -216,7 +216,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
default:
|
||||
if (length + stream.Position > stream.Length)
|
||||
throw new NotSupportedException($"Vqa uses unknown Subtype: {type}");
|
||||
stream.ReadBytes((int)length);
|
||||
stream.Position += length;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
break;
|
||||
default:
|
||||
// Don't parse sound here.
|
||||
stream.ReadBytes((int)length);
|
||||
stream.Position += length;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -382,8 +382,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
// frame-modifier chunk
|
||||
case "CBP0":
|
||||
case "CBPZ":
|
||||
var bytes = s.ReadBytes(subchunkLength);
|
||||
bytes.CopyTo(cbp, chunkBufferOffset);
|
||||
s.ReadBytes(cbp, chunkBufferOffset, subchunkLength);
|
||||
chunkBufferOffset += subchunkLength;
|
||||
currentChunkBuffer++;
|
||||
cbpIsCompressed = type == "CBPZ";
|
||||
|
||||
@@ -141,12 +141,12 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
{
|
||||
limbDataOffset[i] = s.ReadUInt32();
|
||||
s.Seek(8, SeekOrigin.Current);
|
||||
Limbs[i].Scale = s.ReadFloat();
|
||||
Limbs[i].Scale = s.ReadSingle();
|
||||
s.Seek(48, SeekOrigin.Current);
|
||||
|
||||
Limbs[i].Bounds = new float[6];
|
||||
for (var j = 0; j < 6; j++)
|
||||
Limbs[i].Bounds[j] = s.ReadFloat();
|
||||
Limbs[i].Bounds[j] = s.ReadSingle();
|
||||
Limbs[i].Size = s.ReadBytes(3);
|
||||
Limbs[i].Type = (NormalType)s.ReadUInt8();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user