module Termtab.Audio (
AudioEngine,
startAudioEngine,
stopAudioEngine,
withAudioEngine,
engineNoteOn,
engineNoteOff,
engineProgramChange,
module Termtab.Audio.Types,
) where
import Control.Exception (bracket)
import Termtab.Audio.FluidSynth qualified as FS
import Termtab.Audio.Types
import Termtab.Types (MidiChannel, MidiProgram, Pitch, Velocity)
newtype AudioEngine = AudioEngine
{ AudioEngine -> BackendHandle
aeBackend :: BackendHandle
}
newtype BackendHandle = FluidSynthHandle FS.FluidSynthEngine
startAudioEngine :: BackendType -> AudioConfig -> IO AudioEngine
startAudioEngine :: BackendType -> AudioConfig -> IO AudioEngine
startAudioEngine BackendType
BackendFluidSynth AudioConfig
cfg = do
engine <- AudioConfig -> IO FluidSynthEngine
FS.initFluidSynth AudioConfig
cfg
return AudioEngine{aeBackend = FluidSynthHandle engine}
startAudioEngine BackendType
BackendPortMidi AudioConfig
_ =
[Char] -> IO AudioEngine
forall a. HasCallStack => [Char] -> a
error [Char]
"PortMidi backend not yet implemented"
stopAudioEngine :: AudioEngine -> IO ()
stopAudioEngine :: AudioEngine -> IO ()
stopAudioEngine AudioEngine
engine =
case AudioEngine -> BackendHandle
aeBackend AudioEngine
engine of
FluidSynthHandle FluidSynthEngine
fs -> FluidSynthEngine -> IO ()
FS.shutdownFluidSynth FluidSynthEngine
fs
withAudioEngine :: BackendType -> AudioConfig -> (AudioEngine -> IO a) -> IO a
withAudioEngine :: forall a.
BackendType -> AudioConfig -> (AudioEngine -> IO a) -> IO a
withAudioEngine BackendType
backend AudioConfig
cfg =
IO AudioEngine
-> (AudioEngine -> IO ()) -> (AudioEngine -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (BackendType -> AudioConfig -> IO AudioEngine
startAudioEngine BackendType
backend AudioConfig
cfg) AudioEngine -> IO ()
stopAudioEngine
engineNoteOn :: AudioEngine -> MidiChannel -> Pitch -> Velocity -> IO ()
engineNoteOn :: AudioEngine -> MidiChannel -> Pitch -> Velocity -> IO ()
engineNoteOn AudioEngine
engine = case AudioEngine -> BackendHandle
aeBackend AudioEngine
engine of
FluidSynthHandle FluidSynthEngine
fs -> FluidSynthEngine -> MidiChannel -> Pitch -> Velocity -> IO ()
FS.noteOn FluidSynthEngine
fs
engineNoteOff :: AudioEngine -> MidiChannel -> Pitch -> IO ()
engineNoteOff :: AudioEngine -> MidiChannel -> Pitch -> IO ()
engineNoteOff AudioEngine
engine = case AudioEngine -> BackendHandle
aeBackend AudioEngine
engine of
FluidSynthHandle FluidSynthEngine
fs -> FluidSynthEngine -> MidiChannel -> Pitch -> IO ()
FS.noteOff FluidSynthEngine
fs
engineProgramChange :: AudioEngine -> MidiChannel -> MidiProgram -> IO ()
engineProgramChange :: AudioEngine -> MidiChannel -> MidiProgram -> IO ()
engineProgramChange AudioEngine
engine = case AudioEngine -> BackendHandle
aeBackend AudioEngine
engine of
FluidSynthHandle FluidSynthEngine
fs -> FluidSynthEngine -> MidiChannel -> MidiProgram -> IO ()
FS.programChange FluidSynthEngine
fs