88namespace 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