diff --git a/Fmod5Sharp/FsbLoader.cs b/Fmod5Sharp/FsbLoader.cs index ac8a149..aa9268c 100644 --- a/Fmod5Sharp/FsbLoader.cs +++ b/Fmod5Sharp/FsbLoader.cs @@ -22,9 +22,8 @@ public static class FsbLoader { 10, 96_000 }, }; - private static FmodSoundBank? LoadInternal(byte[] bankBytes, bool throwIfError) + private static FmodSoundBank? LoadInternal(Stream stream, bool throwIfError) { - using MemoryStream stream = new(bankBytes); using BinaryReader reader = new(stream); FmodAudioHeader header = new(reader); @@ -37,24 +36,26 @@ public static class FsbLoader return null; } - List samples = new(); - - //Remove header from data block. - var bankData = bankBytes.AsSpan((int)(header.SizeOfThisHeader + header.SizeOfNameTable + header.SizeOfSampleHeaders)); + long dataStartOffset = header.SizeOfThisHeader + header.SizeOfNameTable + header.SizeOfSampleHeaders; + List samples = new(header.Samples.Count); for (var i = 0; i < header.Samples.Count; i++) { var sampleMetadata = header.Samples[i]; - var firstByteOfSample = (int)sampleMetadata.DataOffset; - var lastByteOfSample = (int)header.SizeOfData; + var firstByteOfSample = (long)sampleMetadata.DataOffset; + var lastByteOfSample = (long)header.SizeOfData; if (i < header.Samples.Count - 1) { - lastByteOfSample = (int)header.Samples[i + 1].DataOffset; + lastByteOfSample = (long)header.Samples[i + 1].DataOffset; } - var sample = new FmodSample(sampleMetadata, bankData[firstByteOfSample..lastByteOfSample].ToArray()); + byte[] sampleData = new byte[lastByteOfSample - firstByteOfSample]; + stream.Position = dataStartOffset + firstByteOfSample; + stream.Read(sampleData, 0, sampleData.Length); + + var sample = new FmodSample(sampleMetadata, sampleData); if (header.SizeOfNameTable > 0) { @@ -64,7 +65,8 @@ public static class FsbLoader nameOffset += header.SizeOfThisHeader + header.SizeOfSampleHeaders; - sample.Name = bankBytes.ReadNullTerminatedString((int)nameOffset); + stream.Position = nameOffset; + sample.Name = stream.ReadNullTerminatedString(); } samples.Add(sample); @@ -73,13 +75,26 @@ public static class FsbLoader return new FmodSoundBank(header, samples); } + public static bool TryLoadFsbFromStream(Stream stream, out FmodSoundBank? bank) + { + bank = LoadInternal(stream, false); + return bank != null; + } + + public static FmodSoundBank LoadFsbFromStream(Stream stream) + => LoadInternal(stream, true)!; + public static bool TryLoadFsbFromByteArray(byte[] bankBytes, out FmodSoundBank? bank) { - bank = LoadInternal(bankBytes, false); + using var stream = new MemoryStream(bankBytes); + bank = LoadInternal(stream, false); return bank != null; } public static FmodSoundBank LoadFsbFromByteArray(byte[] bankBytes) - => LoadInternal(bankBytes, true)!; + { + using var stream = new MemoryStream(bankBytes); + return LoadInternal(stream, true)!; + } } } \ No newline at end of file diff --git a/Fmod5Sharp/Util/Extensions.cs b/Fmod5Sharp/Util/Extensions.cs index 1d63e0e..34e1925 100644 --- a/Fmod5Sharp/Util/Extensions.cs +++ b/Fmod5Sharp/Util/Extensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; @@ -41,13 +42,14 @@ internal static ulong Bits(this ulong raw, int lowestBit, int numBits) return (raw & mask) >> lowestBit; } - internal static string ReadNullTerminatedString(this byte[] bytes, int startOffset) + internal static string ReadNullTerminatedString(this Stream stream) { - var strLen = bytes.AsSpan(startOffset).IndexOf((byte)0); - if (strLen == -1) - throw new("Could not find null terminator"); - - return Encoding.UTF8.GetString(bytes, startOffset, strLen); + List bytes = new(16); + int b; + while ((b = stream.ReadByte()) > 0) + bytes.Add((byte)b); + + return Encoding.UTF8.GetString(bytes.ToArray()); } } } \ No newline at end of file