Created
April 16, 2023 19:21
-
-
Save GlaireDaggers/51f2062ca25cca4b15a1e91ff6f3c239 to your computer and use it in GitHub Desktop.
Audio manager class from unfinished FNA game using FMOD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
public class AudioManager | |
{ | |
public readonly VESGame game; | |
private FMOD.Studio.System _studioSystem; | |
private FMOD.Studio.Bank _master; | |
private FMOD.Studio.Bank _master_strings; | |
private FMOD.Studio.Bank _music; | |
private FMOD.Studio.Bank _sfx; | |
private FMOD.Studio.EventInstance _song; | |
private GCHandle _masterBankStream; | |
private GCHandle _masterStringsBankStream; | |
private GCHandle _musicBankStream; | |
private GCHandle _sfxBankStream; | |
private FMOD.Studio.BANK_INFO _masterBankData; | |
private FMOD.Studio.BANK_INFO _masterStringsBankData; | |
private FMOD.Studio.BANK_INFO _musicBankData; | |
private FMOD.Studio.BANK_INFO _sfxBankData; | |
public AudioManager(VESGame game) | |
{ | |
this.game = game; | |
AssertFMODResult(FMOD.Studio.System.create(out _studioSystem)); | |
AssertFMODResult(_studioSystem.initialize(32, FMOD.Studio.INITFLAGS.NORMAL, FMOD.INITFLAGS.NORMAL, IntPtr.Zero)); | |
_masterBankData = BankFromStream(game.Resources.Open("content/audio/Master.bank"), out _masterBankStream); | |
_masterStringsBankData = BankFromStream(game.Resources.Open("content/audio/Master.strings.bank"), out _masterStringsBankStream); | |
_musicBankData = BankFromStream(game.Resources.Open("content/audio/Music.bank"), out _musicBankStream); | |
_sfxBankData = BankFromStream(game.Resources.Open("content/audio/SFX.bank"), out _sfxBankStream); | |
// load audio banks | |
AssertFMODResult(_studioSystem.loadBankCustom(_masterBankData, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out _master)); | |
AssertFMODResult(_studioSystem.loadBankCustom(_masterStringsBankData, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out _master_strings)); | |
AssertFMODResult(_studioSystem.loadBankCustom(_musicBankData, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out _music)); | |
AssertFMODResult(_studioSystem.loadBankCustom(_sfxBankData, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out _sfx)); | |
Console.WriteLine("FMOD initialized"); | |
} | |
public void Update() | |
{ | |
AssertFMODResult(_studioSystem.update()); | |
} | |
public void Dispose() | |
{ | |
AssertFMODResult(_studioSystem.release()); | |
((Stream)_masterBankStream.Target).Dispose(); | |
((Stream)_masterStringsBankStream.Target).Dispose(); | |
((Stream)_musicBankStream.Target).Dispose(); | |
((Stream)_sfxBankStream.Target).Dispose(); | |
_masterBankStream.Free(); | |
_masterStringsBankStream.Free(); | |
_musicBankStream.Free(); | |
_sfxBankStream.Free(); | |
} | |
public FMOD.Studio.EventInstance CreateEvent(string path) | |
{ | |
AssertFMODResult(_studioSystem.getEvent(path, out var eventDesc)); | |
AssertFMODResult(eventDesc.createInstance(out var eventInstance)); | |
return eventInstance; | |
} | |
public void PlaySong(string path) | |
{ | |
if (_song.isValid()) | |
{ | |
_song.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); | |
_song.release(); | |
} | |
_song = CreateEvent(path); | |
_song.start(); | |
} | |
private void AssertFMODResult(FMOD.RESULT result) | |
{ | |
Debug.Assert(result == FMOD.RESULT.OK, FMOD.Error.String(result)); | |
} | |
private FMOD.Studio.BANK_INFO BankFromStream(Stream stream, out GCHandle handle) | |
{ | |
handle = GCHandle.Alloc(stream); | |
var bankInfo = new FMOD.Studio.BANK_INFO(); | |
bankInfo.userdata = GCHandle.ToIntPtr(handle); | |
bankInfo.opencallback = OpenFile; | |
bankInfo.closecallback = CloseFile; | |
bankInfo.readcallback = ReadFile; | |
bankInfo.seekcallback = SeekFile; | |
bankInfo.userdatalength = 0; | |
return bankInfo; | |
} | |
private static FMOD.RESULT OpenFile(IntPtr name, ref uint filesize, ref IntPtr handle, IntPtr userdata) | |
{ | |
Stream stream = (Stream)GCHandle.FromIntPtr(userdata).Target; | |
filesize = (uint)stream.Length; | |
return FMOD.RESULT.OK; | |
} | |
private static FMOD.RESULT CloseFile(IntPtr handle, IntPtr userdata) | |
{ | |
//Stream stream = (Stream)GCHandle.FromIntPtr(userdata).Target; | |
//stream.Close(); | |
return FMOD.RESULT.OK; | |
} | |
private static unsafe FMOD.RESULT ReadFile(IntPtr handle, IntPtr buffer, uint sizebytes, ref uint bytesread, IntPtr userdata) | |
{ | |
Stream stream = (Stream)GCHandle.FromIntPtr(userdata).Target; | |
byte[] buf = new byte[sizebytes]; | |
bytesread = (uint)stream.Read(buf, 0, buf.Length); | |
fixed (void* src = buf) | |
{ | |
Buffer.MemoryCopy(src, (void*)buffer, sizebytes, bytesread); | |
} | |
return FMOD.RESULT.OK; | |
} | |
private static FMOD.RESULT SeekFile(IntPtr handle, uint pos, IntPtr userdata) | |
{ | |
Stream stream = (Stream)GCHandle.FromIntPtr(userdata).Target; | |
stream.Seek(pos, SeekOrigin.Begin); | |
return FMOD.RESULT.OK; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment