Skip to content

Commit 88497de

Browse files
committed
-Replaced 'File.ReadAllBytes' with 'ArrayPool<byte>.Shared'
-Optimized WAV header skipping (string comparisons to direct uint32 hex checks)
1 parent 3abd0b1 commit 88497de

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

EXILED/Exiled.API/Features/Audio/WavUtility.cs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Exiled.API.Features.Audio
99
{
1010
using System;
11+
using System.Buffers;
1112
using System.IO;
1213
using System.Runtime.InteropServices;
1314

@@ -25,24 +26,36 @@ public static class WavUtility
2526
/// <returns>An array of floats representing the PCM data.</returns>
2627
public static float[] WavToPcm(string path)
2728
{
28-
byte[] fileBytes = File.ReadAllBytes(path);
29+
using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.Read);
30+
int length = (int)fs.Length;
2931

30-
using MemoryStream ms = new(fileBytes);
31-
using BinaryReader br = new(ms);
32+
byte[] rentedBuffer = ArrayPool<byte>.Shared.Rent(length);
3233

33-
SkipHeader(br);
34+
try
35+
{
36+
int bytesRead = fs.Read(rentedBuffer, 0, length);
37+
38+
using MemoryStream ms = new(rentedBuffer, 0, bytesRead);
39+
using BinaryReader br = new(ms);
3440

35-
int headerOffset = (int)ms.Position;
36-
int dataLength = fileBytes.Length - headerOffset;
41+
SkipHeader(br);
3742

38-
Span<byte> audioDataSpan = fileBytes.AsSpan(headerOffset, dataLength);
39-
Span<short> samples = MemoryMarshal.Cast<byte, short>(audioDataSpan);
43+
int headerOffset = (int)ms.Position;
44+
int dataLength = bytesRead - headerOffset;
4045

41-
float[] pcm = new float[samples.Length];
42-
for (int i = 0; i < samples.Length; i++)
43-
pcm[i] = samples[i] / 32768f;
46+
Span<byte> audioDataSpan = rentedBuffer.AsSpan(headerOffset, dataLength);
47+
Span<short> samples = MemoryMarshal.Cast<byte, short>(audioDataSpan);
4448

45-
return pcm;
49+
float[] pcm = new float[samples.Length];
50+
for (int i = 0; i < samples.Length; i++)
51+
pcm[i] = samples[i] / 32768f;
52+
53+
return pcm;
54+
}
55+
finally
56+
{
57+
ArrayPool<byte>.Shared.Return(rentedBuffer);
58+
}
4659
}
4760

4861
/// <summary>
@@ -55,10 +68,11 @@ public static void SkipHeader(BinaryReader br)
5568

5669
while (true)
5770
{
58-
string chunk = new(br.ReadChars(4));
71+
uint chunk = br.ReadUInt32();
5972
int size = br.ReadInt32();
6073

61-
if (chunk == "fmt ")
74+
// 'fmt ' chunk
75+
if (chunk == 0x20746D66)
6276
{
6377
short format = br.ReadInt16();
6478
short channels = br.ReadInt16();
@@ -72,14 +86,19 @@ public static void SkipHeader(BinaryReader br)
7286

7387
br.BaseStream.Position += size - 16;
7488
}
75-
else if (chunk == "data")
89+
90+
// 'data' chunk
91+
else if (chunk == 0x61746164)
7692
{
7793
return;
7894
}
7995
else
8096
{
8197
br.BaseStream.Position += size;
8298
}
99+
100+
if (br.BaseStream.Position >= br.BaseStream.Length)
101+
throw new InvalidDataException("WAV file does not contain a 'data' chunk. File might be corrupted or empty.");
83102
}
84103
}
85104
}

0 commit comments

Comments
 (0)