diff --git a/Sound/Fluidsynth.hs b/Sound/Fluidsynth.hs
--- a/Sound/Fluidsynth.hs
+++ b/Sound/Fluidsynth.hs
@@ -1,7 +1,11 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
 module Sound.Fluidsynth
-    (newSettings
+    (Channel(..)
+    ,Key(..)
+    ,Velocity(..)
+    ,Program(..)
+    ,newSettings
     ,newSynth
     ,newDriver
     ,newPlayer
@@ -10,27 +14,37 @@
     ,playerPlay
     ,playerJoin
     ,synthNoteOn
-    ,synthNoteOff)
+    ,synthNoteOff
+    ,Event()
+    ,eventNoteOn
+    ,eventNoteOff)
 where
 
 import Control.Monad
+import qualified Data.Map as M
+import Data.Maybe
 import Foreign.C.String
 import Foreign.C.Types
 import Foreign.ForeignPtr.Safe
+import Foreign.Ptr
+import System.Directory
 
 import Sound.Fluidsynth.Internal
 
 newtype Settings = Settings (ForeignPtr C'fluid_settings_t)
-newtype Synth = Synth (ForeignPtr C'fluid_synth_t)
+data Synth = Synth (M.Map FilePath CUInt) (ForeignPtr C'fluid_synth_t)
 newtype Driver = Driver (ForeignPtr C'fluid_audio_driver_t)
 newtype Player = Player (ForeignPtr C'fluid_player_t)
+newtype Event = Event (ForeignPtr C'fluid_event_t)
 
 newtype Channel = Channel Int
-    deriving (Num)
+    deriving (Enum, Eq, Integral, Ord, Num, Real)
 newtype Key = Key Int
-    deriving (Num)
+    deriving (Enum, Eq, Integral, Ord, Num, Real)
 newtype Velocity = Velocity Int
-    deriving (Num)
+    deriving (Enum, Eq, Integral, Ord, Num, Real)
+newtype Program = Program Int
+    deriving (Enum, Eq, Integral, Ord, Num, Real)
 
 newSettings :: IO Settings
 newSettings = do
@@ -47,10 +61,10 @@
     withForeignPtr settings $ \ptr -> do
         ptr' <- c'new_fluid_synth ptr
         synth <- newForeignPtr p'delete_fluid_synth ptr'
-        return $! Synth synth
+        return $! Synth M.empty synth
 
 newDriver :: Settings -> Synth -> IO Driver
-newDriver (Settings settings) (Synth synth) = do
+newDriver (Settings settings) (Synth _ synth) = do
     withForeignPtr settings $ \ptr -> do
         withForeignPtr synth $ \ptr' -> do
             ptr'' <- c'new_fluid_audio_driver ptr ptr'
@@ -58,26 +72,50 @@
             return $! Driver driver
 
 newPlayer :: Synth -> IO Player
-newPlayer (Synth synth) = do
+newPlayer (Synth _ synth) = do
     withForeignPtr synth $ \ptr -> do
         ptr' <- c'new_fluid_player ptr
         player <- newForeignPtr p'delete_fluid_player ptr'
         return $! Player player
 
-loadSF :: Synth -> String -> IO ()
-loadSF (Synth synth) path = do
+loadSF :: Synth -> String -> IO Synth
+loadSF (Synth sfmap synth) path = do
+    abspath <- canonicalizePath path
+    let msfid = M.lookup abspath sfmap
     withForeignPtr synth $ \ptr ->
-        withCAString path $ \cstr ->
-            void $ c'fluid_synth_sfload ptr cstr 1
+        withCAString abspath $ \cstr -> case msfid of
+            Just sfid -> do
+                err <- c'fluid_synth_sfreload ptr sfid
+                if err == -1
+                    then error "Couldn't reload soundfont!"
+                    else return $ Synth sfmap synth
+            Nothing -> do
+                sfid <- c'fluid_synth_sfload ptr cstr 1
+                let sfmap' = M.insert abspath (fromIntegral sfid) sfmap
+                if sfid == -1
+                    then error "Couldn't load soundfont!"
+                    else return $ Synth sfmap' synth
 
+unloadSF :: Synth -> String -> IO Synth
+unloadSF (Synth sfmap synth) path = do
+    abspath <- canonicalizePath path
+    let msfid = M.lookup abspath sfmap
+        sfid  = fromMaybe (error "Couldn't unload soundfont!") msfid
+    withForeignPtr synth $ \ptr -> do
+        err <- c'fluid_synth_sfunload ptr sfid 1
+        let sfmap' = M.delete abspath sfmap
+        if err == -1
+            then error "Couldn't unload soundfont!"
+            else return $ Synth sfmap' synth
+
 synthNoteOn :: Synth -> Channel -> Key -> Velocity -> IO ()
-synthNoteOn (Synth synth) (Channel c) (Key k) (Velocity v) =
+synthNoteOn (Synth _ synth) c k v =
     void $ withForeignPtr synth $ \ptr ->
         c'fluid_synth_noteon ptr (fromIntegral c) (fromIntegral k)
             (fromIntegral v)
 
 synthNoteOff :: Synth -> Channel -> Key -> IO ()
-synthNoteOff (Synth synth) (Channel c) (Key k) =
+synthNoteOff (Synth _ synth) c k =
     withForeignPtr synth $ \ptr ->
         void $ c'fluid_synth_noteoff ptr (fromIntegral c) (fromIntegral k)
 
@@ -96,3 +134,47 @@
 playerJoin (Player player) = do
     withForeignPtr player c'fluid_player_join
     return ()
+
+-- | Make an event.
+--
+--   Since the event is unpatterned, it isn't going to be very useful. End
+--   users almost certainly want the patterned event creators.
+newEvent :: IO Event
+newEvent = do
+    ptr <- c'new_fluid_event
+    event <- newForeignPtr p'delete_fluid_event ptr
+    return $! Event event
+
+-- | Make an event and call an action on it.
+--
+--   Just a combinator meant to help write the following bindings.
+withNewEvent :: (Ptr C'fluid_event_t -> IO ()) -> IO Event
+withNewEvent action = do
+    e@(Event event) <- newEvent
+    withForeignPtr event action
+    return e
+
+eventNoteOn :: Channel -> Key -> Velocity -> IO Event
+eventNoteOn c k v = withNewEvent $ \ptr ->
+    c'fluid_event_noteon ptr (fromIntegral c) (fromIntegral k)
+        (fromIntegral v)
+
+eventNoteOff :: Channel -> Key -> IO Event
+eventNoteOff c k = withNewEvent $ \ptr ->
+    c'fluid_event_noteoff ptr (fromIntegral c) (fromIntegral k)
+
+eventPitchSens :: Channel -> Int -> IO Event
+eventPitchSens c amount = withNewEvent $ \ptr ->
+    c'fluid_event_pitch_wheelsens ptr (fromIntegral c) (fromIntegral amount)
+
+eventPitchBend :: Channel -> Int -> IO Event
+eventPitchBend c amount = withNewEvent $ \ptr ->
+    c'fluid_event_pitch_bend ptr (fromIntegral c) (fromIntegral amount)
+
+eventProgramControl :: Channel -> Program -> IO Event
+eventProgramControl c p = withNewEvent $ \ptr ->
+    c'fluid_event_program_change ptr (fromIntegral c) (fromIntegral p)
+
+eventVolume :: Channel -> Int -> IO Event
+eventVolume c amount = withNewEvent $ \ptr ->
+    c'fluid_event_volume ptr (fromIntegral c) (fromIntegral amount)
diff --git a/fluidsynth.cabal b/fluidsynth.cabal
--- a/fluidsynth.cabal
+++ b/fluidsynth.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                fluidsynth
-version:             0.1.0.0
+version:             0.1.1.0
 synopsis:            Haskell bindings to FluidSynth
 description:         Simple Haskell bindings to FluidSynth.
 homepage:            https://github.com/MostAwesomeDude/hsfluidsynth
@@ -22,7 +22,9 @@
 library
   exposed-modules:     Sound.Fluidsynth
   other-modules:       Sound.Fluidsynth.Internal
-  build-depends:       base >= 3 && < 5,
-                       bindings-DSL >= 1.0.6 && < 1.1
+  build-depends:       base >= 3 && < 5
+                     , bindings-DSL >= 1.0.6 && < 1.1
+                     , containers >= 0.4.2.1 && < 0.5
+                     , directory >= 1.2.0.1  && < 1.3
   extra-libraries:     fluidsynth
   extensions:          ForeignFunctionInterface
