Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 28 additions & 13 deletions Fmod5Sharp/FsbLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -37,24 +36,26 @@ public static class FsbLoader
return null;
}

List<FmodSample> 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<FmodSample> 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)
{
Expand All @@ -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);
Expand All @@ -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)!;
}
}
}
14 changes: 8 additions & 6 deletions Fmod5Sharp/Util/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

Expand Down Expand Up @@ -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<byte> bytes = new(16);
int b;
while ((b = stream.ReadByte()) > 0)
bytes.Add((byte)b);

return Encoding.UTF8.GetString(bytes.ToArray());
}
}
}