static FMOD.RESULT DumpSoundBank(FMOD.System FModSystem, string FSBFileStr)
{
bool Flag = false;
FMOD.RESULT FModResult; // Set our variable we will keep updating with the FMOD Results
Console.WriteLine("File: " + FSBFileStr);
FMOD.Sound FModSound = new Sound(); // Initialize a new FMod Sound object with some standard mode flags
FModResult = FModSystem.createSound(FSBFileStr, FMOD.MODE.SOFTWARE | FMOD.MODE.CREATESTREAM | FMOD.MODE.ACCURATETIME, ref FModSound);
if (FModResult != FMOD.RESULT.OK) {
// Again, if something went wrong, print the error.
Console.WriteLine("ERR CreateSound: " + FMOD.Error.String(FModResult));
} else {
// Otherwise, get the number of sub-sounds within the FSB.
int NumSubSounds = 0;
FModResult = FModSound.getNumSubSounds(ref NumSubSounds);
if (FModResult != FMOD.RESULT.OK) {
Console.WriteLine("ERR GetNumSounds: " + FMOD.Error.String(FModResult));
} else {
Console.WriteLine(" Sounds: " + NumSubSounds);
for (int i = 0; i < NumSubSounds; i++) {
// For each sub-sound in the Sound Bank, create a new one and initialize it like we did above
FMOD.Sound SubSound = new Sound();
FModResult = FModSystem.createSound(FSBFileStr, FMOD.MODE.SOFTWARE | FMOD.MODE.CREATESTREAM | FMOD.MODE.ACCURATETIME, ref SubSound);
if (FModSound.getSubSound(i, ref SubSound) == FMOD.RESULT.OK) { // Get the next sub-sound
StringBuilder SubSoundName = new StringBuilder(256);
if ((SubSound.getName(SubSoundName, 256) == FMOD.RESULT.OK) && (SubSoundName[0] != 0)) { // Get the sub-sound name and put it in a StringBuilder
SubSound.seekData(0); // Seek to the beginning of the sound data
string DirName = Path.GetFileName(FSBFileStr).Replace(".fsb", ""); // Set the subdirectory name to the name of the FSB without the extension.
if ((!Directory.Exists(TargetDir + @"\" + DirName)) && ExtractFSB) {
// Create the subdirectory if it doesn't exist.
Console.WriteLine(" Creating Subdirectory: " + DirName);
Directory.CreateDirectory(TargetDir + @"\" + DirName);
}
Console.WriteLine(" " + String.Format("{0:D" + NumSubSounds.ToString().Length + "}", (i + 1)) + "/" + NumSubSounds + ": " + SubSoundName.ToString()); // Print status
//if (ExtractFSB && SubSoundName.ToString().ToLower().Contains("female1")) {
if (ExtractFSB) {
Flag = true;
// Piece together a new filename in the format of "TargetDir\FSBName\#_SoundName.wav" and open the file.
FileStream SubSoundStream = new FileStream(TargetDir + @"\" + DirName + @"\" + String.Format("{0:D" + NumSubSounds.ToString().Length + "}", (i + 1)) + "_" + SubSoundName.ToString() + ".wav", FileMode.Create, FileAccess.Write);
uint Length = WriteHeader(SubSoundStream, SubSound, FSBFileStr); // Manually create the wave header and write it to the file
do {
byte[] SoundData = new byte[65536]; // Create a max-length buffer for the audio data
uint LenToRead; // Specify the length is at most 65,536, or to the end of the data
if (Length > SoundData.Length) { LenToRead = 65536; } else { LenToRead = Length; }
uint LenRead = LenToRead;
IntPtr BufferPtr = Marshal.AllocHGlobal((int)LenToRead); // Allocate the buffer and get its pointer
// Read the "LenToRead" bytes into the buffer and update LenRead with the number of bytes read
FModResult = SubSound.readData(BufferPtr, LenToRead, ref LenRead);
Marshal.Copy(BufferPtr, SoundData, 0, (int)LenRead); // Copy the data out of unmanaged memory into the SoundData byte[] array
SubSoundStream.Write(SoundData, 0, (int)LenRead); // Write the sound data to the file
Marshal.FreeHGlobal(BufferPtr);
Length -= LenRead; // Subtract what we read from the remaining length of data.
} while ((Length > 0) && (FModResult == FMOD.RESULT.OK)); // As long as we have no errors and still more data to read
long FileSize = SubSoundStream.Position;
SubSoundStream.Seek(4, SeekOrigin.Begin);
SubSoundStream.Write(BitConverter.GetBytes((long)(FileSize - 8)), 0, 4);
SubSoundStream.Close();
} else if (Flag) {
Console.ReadLine();
}
}
}
}
}
FModSound.release();
}
return FModResult;
}