diff --git a/C2HS.hs b/C2HS.hs
new file mode 100644
--- /dev/null
+++ b/C2HS.hs
@@ -0,0 +1,220 @@
+--  C->Haskell Compiler: Marshalling library
+--
+--  Copyright (c) [1999...2005] Manuel M T Chakravarty
+--
+--  Redistribution and use in source and binary forms, with or without
+--  modification, are permitted provided that the following conditions are met:
+-- 
+--  1. Redistributions of source code must retain the above copyright notice,
+--     this list of conditions and the following disclaimer. 
+--  2. Redistributions in binary form must reproduce the above copyright
+--     notice, this list of conditions and the following disclaimer in the
+--     documentation and/or other materials provided with the distribution. 
+--  3. The name of the author may not be used to endorse or promote products
+--     derived from this software without specific prior written permission. 
+--
+--  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+--  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+--  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+--  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+--  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+--  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+--  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+--  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+--  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+--  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+--- Description ---------------------------------------------------------------
+--
+--  Language: Haskell 98
+--
+--  This module provides the marshaling routines for Haskell files produced by 
+--  C->Haskell for binding to C library interfaces.  It exports all of the
+--  low-level FFI (language-independent plus the C-specific parts) together
+--  with the C->HS-specific higher-level marshalling routines.
+--
+
+module C2HS (
+
+  -- * Re-export the language-independent component of the FFI 
+  module Foreign,
+
+  -- * Re-export the C language component of the FFI
+  module CForeign,
+
+  -- * Composite marshalling functions
+  withCStringLenIntConv, peekCStringLenIntConv, withIntConv, withFloatConv,
+  peekIntConv, peekFloatConv, withBool, peekBool, withEnum, peekEnum,
+
+  -- * Conditional results using 'Maybe'
+  nothingIf, nothingIfNull,
+
+  -- * Bit masks
+  combineBitMasks, containsBitMask, extractBitMasks,
+
+  -- * Conversion between C and Haskell types
+  cIntConv, cFloatConv, cToBool, cFromBool, cToEnum, cFromEnum
+) where 
+
+
+import Foreign
+       hiding       (Word)
+		    -- Should also hide the Foreign.Marshal.Pool exports in
+		    -- compilers that export them
+import CForeign
+
+import Monad        (when, liftM)
+
+
+-- Composite marshalling functions
+-- -------------------------------
+
+-- Strings with explicit length
+--
+withCStringLenIntConv s f    = withCStringLen s $ \(p, n) -> f (p, cIntConv n)
+peekCStringLenIntConv (s, n) = peekCStringLen (s, cIntConv n)
+
+-- Marshalling of numerals
+--
+
+withIntConv   :: (Storable b, Integral a, Integral b) 
+	      => a -> (Ptr b -> IO c) -> IO c
+withIntConv    = with . cIntConv
+
+withFloatConv :: (Storable b, RealFloat a, RealFloat b) 
+	      => a -> (Ptr b -> IO c) -> IO c
+withFloatConv  = with . cFloatConv
+
+peekIntConv   :: (Storable a, Integral a, Integral b) 
+	      => Ptr a -> IO b
+peekIntConv    = liftM cIntConv . peek
+
+peekFloatConv :: (Storable a, RealFloat a, RealFloat b) 
+	      => Ptr a -> IO b
+peekFloatConv  = liftM cFloatConv . peek
+
+-- Passing Booleans by reference
+--
+
+withBool :: (Integral a, Storable a) => Bool -> (Ptr a -> IO b) -> IO b
+withBool  = with . fromBool
+
+peekBool :: (Integral a, Storable a) => Ptr a -> IO Bool
+peekBool  = liftM toBool . peek
+
+
+-- Passing enums by reference
+--
+
+withEnum :: (Enum a, Integral b, Storable b) => a -> (Ptr b -> IO c) -> IO c
+withEnum  = with . cFromEnum
+
+peekEnum :: (Enum a, Integral b, Storable b) => Ptr b -> IO a
+peekEnum  = liftM cToEnum . peek
+
+
+-- Storing of 'Maybe' values
+-- -------------------------
+
+instance Storable a => Storable (Maybe a) where
+  sizeOf    _ = sizeOf    (undefined :: Ptr ())
+  alignment _ = alignment (undefined :: Ptr ())
+
+  peek p = do
+	     ptr <- peek (castPtr p)
+	     if ptr == nullPtr
+	       then return Nothing
+	       else liftM Just $ peek ptr
+
+  poke p v = do
+	       ptr <- case v of
+		        Nothing -> return nullPtr
+			Just v' -> new v'
+               poke (castPtr p) ptr
+
+
+-- Conditional results using 'Maybe'
+-- ---------------------------------
+
+-- Wrap the result into a 'Maybe' type.
+--
+-- * the predicate determines when the result is considered to be non-existing,
+--   ie, it is represented by `Nothing'
+--
+-- * the second argument allows to map a result wrapped into `Just' to some
+--   other domain
+--
+nothingIf       :: (a -> Bool) -> (a -> b) -> a -> Maybe b
+nothingIf p f x  = if p x then Nothing else Just $ f x
+
+-- |Instance for special casing null pointers.
+--
+nothingIfNull :: (Ptr a -> b) -> Ptr a -> Maybe b
+nothingIfNull  = nothingIf (== nullPtr)
+
+
+-- Support for bit masks
+-- ---------------------
+
+-- Given a list of enumeration values that represent bit masks, combine these
+-- masks using bitwise disjunction.
+--
+combineBitMasks :: (Enum a, Bits b) => [a] -> b
+combineBitMasks = foldl (.|.) 0 . map (fromIntegral . fromEnum)
+
+-- Tests whether the given bit mask is contained in the given bit pattern
+-- (i.e., all bits set in the mask are also set in the pattern).
+--
+containsBitMask :: (Bits a, Enum b) => a -> b -> Bool
+bits `containsBitMask` bm = let bm' = fromIntegral . fromEnum $ bm
+			    in
+			    bm' .&. bits == bm'
+
+-- |Given a bit pattern, yield all bit masks that it contains.
+--
+-- * This does *not* attempt to compute a minimal set of bit masks that when
+--   combined yield the bit pattern, instead all contained bit masks are
+--   produced.
+--
+extractBitMasks :: (Bits a, Enum b, Bounded b) => a -> [b]
+extractBitMasks bits = 
+  [bm | bm <- [minBound..maxBound], bits `containsBitMask` bm]
+
+
+-- Conversion routines
+-- -------------------
+
+-- |Integral conversion
+--
+cIntConv :: (Integral a, Integral b) => a -> b
+cIntConv  = fromIntegral
+
+-- |Floating conversion
+--
+cFloatConv :: (RealFloat a, RealFloat b) => a -> b
+cFloatConv  = realToFrac
+-- As this conversion by default goes via `Rational', it can be very slow...
+{-# RULES 
+  "cFloatConv/Float->Float"   forall (x::Float).  cFloatConv x = x;
+  "cFloatConv/Double->Double" forall (x::Double). cFloatConv x = x
+ #-}
+
+-- |Obtain C value from Haskell 'Bool'.
+--
+cFromBool :: Num a => Bool -> a
+cFromBool  = fromBool
+
+-- |Obtain Haskell 'Bool' from C value.
+--
+cToBool :: Num a => a -> Bool
+cToBool  = toBool
+
+-- |Convert a C enumeration to Haskell.
+--
+cToEnum :: (Integral i, Enum e) => i -> e
+cToEnum  = toEnum . cIntConv
+
+-- |Convert a Haskell enumeration to C.
+--
+cFromEnum :: (Enum e, Integral i) => e -> i
+cFromEnum  = cIntConv . fromEnum
diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+#!/usr/bin/env runhaskell
+
+import Distribution.Simple
+main = defaultMain
diff --git a/Sound/File/Sndfile.hs b/Sound/File/Sndfile.hs
new file mode 100644
--- /dev/null
+++ b/Sound/File/Sndfile.hs
@@ -0,0 +1,36 @@
+-- | "Sound.File.Sndfile" provides a Haskell interface to the ubiquitous
+-- libsndfile library by Erik de Castro Lopo (visit the author's website at
+-- <http://www.mega-nerd.com/libsndfile/>).
+
+module Sound.File.Sndfile
+(
+    -- *Types
+    Count, Index,
+    -- *Stream format
+    Format(..),
+    HeaderFormat(..),
+    SampleFormat(..),
+    EndianFormat(..),
+    defaultFormat,
+    -- *Stream info
+    Info(..), duration, defaultInfo, checkFormat,
+    -- *Stream handle operations
+    Handle, hInfo, hIsSeekable,
+    IOMode(..), openFile, getFileInfo, hFlush, hClose,
+    SeekMode(..), hSeek, hSeekRead, hSeekWrite,
+    -- *I\/O functions
+    MBuffer(..), interact,
+    --IBuffer(..),
+    -- *Exception handling
+    Exception, errorString, catch,
+    -- *Header string field access
+    StringType(..), getString, setString
+) where
+
+import Prelude hiding (catch, interact)
+import Sound.File.Sndfile.Buffer
+import Sound.File.Sndfile.Buffer.Storable ()
+import Sound.File.Sndfile.Buffer.IOCArray ()
+import Sound.File.Sndfile.Interface
+
+-- EOF
diff --git a/Sound/File/Sndfile/Buffer.hs b/Sound/File/Sndfile/Buffer.hs
new file mode 100644
--- /dev/null
+++ b/Sound/File/Sndfile/Buffer.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+module Sound.File.Sndfile.Buffer
+(
+    MBuffer(..),
+    checkSampleBounds, checkFrameBounds,
+    interact
+) where
+
+import C2HS
+import Control.Monad (liftM, when)
+import Data.Array.Base (unsafeRead, unsafeWrite)
+import Data.Array.MArray (Ix, MArray, getBounds)
+--import Data.Array.IArray (IArray)
+import Data.Ix (rangeSize)
+import Prelude hiding (interact)
+import Sound.File.Sndfile.Interface
+
+checkSampleBounds :: (Monad m) => Count -> Int -> Count -> m ()
+checkSampleBounds size channels count
+    | (count `mod` channels) /= 0 = throw (Exception ("invalid channel/count combination " ++ (show count)))
+    | (count < 0) || (count > size) = throw (Exception "index out of bounds")
+    | otherwise = return ()
+
+checkFrameBounds :: (Monad m) => Count -> Int -> Count -> m ()
+checkFrameBounds size channels count
+    | (size `mod` channels) /= 0 = throw (Exception "invalid buffer size")
+    | (count < 0) || (count > (size `quot` channels)) = throw (Exception "index out of bounds")
+    | otherwise = return ()
+
+-- |The class MBuffer is used for polymorphic I\/O on a 'Handle', and is
+-- parameterized on the mutable array type, the element type and the monad
+-- results are returned in.
+--
+-- It is important to note that the data type used by the calling program and
+-- the data format of the file do not need to be the same. For instance, it is
+-- possible to open a 16 bit PCM encoded WAV file and read the data in
+-- floating point format. The library seamlessly converts between the two
+-- formats on-the-fly; the Haskell interface only supports reading and writing
+-- 'Double' or 'Float' values.
+--
+-- When converting between integer data and floating point data, the following
+-- rules apply: The default behaviour when reading floating point data
+-- ('hGetSamples' or 'hGetFrames') from a file with integer data is
+-- normalisation. Regardless of whether data in the file is 8, 16, 24 or 32
+-- bit wide, the data will be read as floating point data in the range
+-- [-1.0, 1.0]. Similarly, data in the range [-1.0, 1.0] will be written to an
+-- integer PCM file so that a data value of 1.0 will be the largest allowable
+-- integer for the given bit width. This normalisation can be turned on or off
+-- using the command interface [TODO: implementation missing in Haskell].
+--
+-- 'hGetSamples' and 'hGetFrames' return the number of items read. Unless the
+-- end of the file was reached during the read, the return value should equal
+-- the number of items requested. Attempts to read beyond the end of the file
+-- will not result in an error but will cause the read functions to return
+-- less than the number of items requested or 0 if already at the end of the
+-- file.
+class (MArray a e m) => MBuffer a e m where
+    -- |Fill the destination array with the requested number of items. The 'count'
+    -- parameter must be an integer product of the number of channels or an error
+    -- will occur.
+    hGetSamples :: Handle -> a Index e -> Count -> m Count
+    -- |Fill the destination array with the requested number of frames of data.
+    -- The array must be large enough to hold the product of frames and the number
+    -- of channels or an error will occur.
+    hGetFrames  :: Handle -> a Index e -> Count -> m Count
+    -- |Write 'count' samples from the source array to the stream. The 'count'
+    -- parameter must be an integer product of the number of channels or an error
+    -- will occur.
+    --
+    -- 'hPutSamples' returns the number of items written (which should be the same
+    -- as the 'count' parameter).
+    hPutSamples :: Handle -> a Index e -> Count -> m Count
+    -- |Write 'count' frames from the source array to the stream.
+    -- The array must be large enough to hold the product of frames and the number
+    -- of channels or an error will occur.
+    --
+    -- 'hPutFrames' returns the number of frames written (which should be the same
+    -- as the 'count' parameter).
+    hPutFrames  :: Handle -> a Index e -> Count -> m Count
+
+modifyArray :: (MArray a e m, Ix i) => (e -> e) -> a i e -> Int -> Int -> m ()
+modifyArray f a i n
+    | i >= n = return ()
+    | otherwise = do
+        e <- unsafeRead a i
+        unsafeWrite a i (f e)
+        modifyArray f a (i+1) n
+
+interact :: (MBuffer a e m) => (e -> e) -> a Index e -> Handle -> Handle -> m ()
+interact f buffer hIn hOut = do
+    s <- liftM rangeSize $ getBounds buffer
+    n <- hGetSamples hIn buffer s
+    when (n > 0) $ do
+        modifyArray f buffer 0 n
+        hPutSamples hOut buffer n
+        interact f buffer hIn hOut
+
+-- EOF
diff --git a/Sound/File/Sndfile/Buffer/IOCArray.hs b/Sound/File/Sndfile/Buffer/IOCArray.hs
new file mode 100644
--- /dev/null
+++ b/Sound/File/Sndfile/Buffer/IOCArray.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# OPTIONS_GHC -fglasgow-exts #-}
+
+module Sound.File.Sndfile.Buffer.IOCArray where
+
+import C2HS
+import Control.Monad (liftM)
+import Data.Array.IOCArray
+import Sound.File.Sndfile.Buffer
+import Sound.File.Sndfile.Interface
+
+type IOFunc a = HandlePtr -> Ptr a -> CLLong -> IO CLLong
+
+{-# INLINE hIO #-}
+hIO :: (Storable a) =>
+           (Count -> Int -> Count -> IO ())
+        -> IOFunc a
+        -> Handle -> (IOCArray Index a) -> Count
+        -> IO Count
+hIO checkBounds ioFunc (Handle info handle) buffer count = do
+    size <- liftM rangeSize $ getBounds buffer
+    checkBounds size (channels info) count
+    result <- withIOCArray buffer $
+                \ptr -> liftM fromIntegral $ ioFunc handle ptr (cIntConv count)
+    checkHandle handle
+    touchIOCArray buffer
+    return $ cIntConv result
+
+foreign import ccall unsafe "sf_read_double"  sf_read_double  :: IOFunc Double
+foreign import ccall unsafe "sf_write_double" sf_write_double :: IOFunc Double
+
+instance MBuffer IOCArray Double IO where
+    hGetSamples = hIO checkSampleBounds sf_read_double
+    hGetFrames  = hIO checkFrameBounds  sf_read_double
+    hPutSamples = hIO checkSampleBounds sf_write_double
+    hPutFrames  = hIO checkFrameBounds  sf_write_double
+
+foreign import ccall unsafe "sf_read_float"  sf_read_float  :: IOFunc Float
+foreign import ccall unsafe "sf_write_float" sf_write_float :: IOFunc Float
+
+instance MBuffer IOCArray Float IO where
+    hGetSamples = hIO checkSampleBounds sf_read_float
+    hGetFrames  = hIO checkFrameBounds  sf_read_float
+    hPutSamples = hIO checkSampleBounds sf_write_float
+    hPutFrames  = hIO checkFrameBounds  sf_write_float
+
+-- EOF
diff --git a/Sound/File/Sndfile/Buffer/Storable.hs b/Sound/File/Sndfile/Buffer/Storable.hs
new file mode 100644
--- /dev/null
+++ b/Sound/File/Sndfile/Buffer/Storable.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# OPTIONS_GHC -fglasgow-exts #-}
+
+module Sound.File.Sndfile.Buffer.Storable where
+
+import C2HS
+import Control.Monad (liftM)
+import Data.Array.Storable
+import Sound.File.Sndfile.Buffer
+import Sound.File.Sndfile.Interface
+
+type IOFunc a = HandlePtr -> Ptr a -> CLLong -> IO CLLong
+
+{-# INLINE hIO #-}
+hIO :: (Storable a) =>
+           (Count -> Int -> Count -> IO ())
+        -> IOFunc a
+        -> Handle -> (StorableArray Index a) -> Count
+        -> IO Count
+hIO checkBounds ioFunc (Handle info handle) buffer count = do
+    size <- liftM rangeSize $ getBounds buffer
+    checkBounds size (channels info) count
+    result <- withStorableArray buffer $
+                \ptr -> liftM fromIntegral $ ioFunc handle ptr (cIntConv count)
+    checkHandle handle
+    touchStorableArray buffer
+    return $ cIntConv result
+
+foreign import ccall unsafe "sf_read_double"  sf_read_double  :: IOFunc Double
+foreign import ccall unsafe "sf_write_double" sf_write_double :: IOFunc Double
+
+instance MBuffer StorableArray Double IO where
+    hGetSamples = hIO checkSampleBounds sf_read_double
+    hGetFrames  = hIO checkFrameBounds  sf_read_double
+    hPutSamples = hIO checkSampleBounds sf_write_double
+    hPutFrames  = hIO checkFrameBounds  sf_write_double
+
+foreign import ccall unsafe "sf_read_float"  sf_read_float  :: IOFunc Float
+foreign import ccall unsafe "sf_write_float" sf_write_float :: IOFunc Float
+
+instance MBuffer StorableArray Float IO where
+    hGetSamples = hIO checkSampleBounds sf_read_float
+    hGetFrames  = hIO checkFrameBounds  sf_read_float
+    hPutSamples = hIO checkSampleBounds sf_write_float
+    hPutFrames  = hIO checkFrameBounds  sf_write_float
+
+-- EOF
diff --git a/Sound/File/Sndfile/Interface.chs b/Sound/File/Sndfile/Interface.chs
new file mode 100644
--- /dev/null
+++ b/Sound/File/Sndfile/Interface.chs
@@ -0,0 +1,428 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# OPTIONS_GHC -fglasgow-exts #-}
+
+module Sound.File.Sndfile.Interface where
+
+import C2HS
+import Control.Monad (liftM, when)
+import Control.Exception (catchDyn, throwDyn)
+import Data.Bits
+import Data.Int (Int64)
+import Data.Typeable (Typeable)
+import Prelude hiding (catch)
+import System.IO.Unsafe (unsafePerformIO)
+
+#include <sndfile.h>
+
+{#context lib="libsndfile" prefix="sf"#}
+
+-- ====================================================================
+-- Basic types
+
+type Count = Int -- ^ Type for expressing sample counts.
+type Index = Int -- ^ Type for expressing sample indices.
+
+-- ====================================================================
+-- Format
+
+-- | Header format.
+{#enum HeaderFormat {underscoreToCase} deriving (Eq, Show)#}
+#c
+enum HeaderFormat
+{
+    HEADER_FORMAT_NONE  = 0,
+
+    HEADER_FORMAT_WAV   = SF_FORMAT_WAV,
+    HEADER_FORMAT_AIFF  = SF_FORMAT_AIFF,
+    HEADER_FORMAT_AU    = SF_FORMAT_AU,
+    HEADER_FORMAT_RAW   = SF_FORMAT_RAW,
+    HEADER_FORMAT_PAF   = SF_FORMAT_PAF,
+    HEADER_FORMAT_SVX   = SF_FORMAT_SVX,
+    HEADER_FORMAT_NIST  = SF_FORMAT_NIST,
+    HEADER_FORMAT_VOC   = SF_FORMAT_VOC,
+    HEADER_FORMAT_IRCAM = SF_FORMAT_IRCAM,
+    HEADER_FORMAT_W64   = SF_FORMAT_W64,
+    HEADER_FORMAT_MAT4  = SF_FORMAT_MAT4,
+    HEADER_FORMAT_MAT5  = SF_FORMAT_MAT5,
+    HEADER_FORMAT_PVF   = SF_FORMAT_PVF,
+    HEADER_FORMAT_XI    = SF_FORMAT_XI,
+    HEADER_FORMAT_HTK   = SF_FORMAT_HTK,
+    HEADER_FORMAT_SDS   = SF_FORMAT_SDS,
+    HEADER_FORMAT_AVR   = SF_FORMAT_AVR,
+    HEADER_FORMAT_WAVEX = SF_FORMAT_WAVEX,
+    HEADER_FORMAT_SD2   = SF_FORMAT_SD2,
+    HEADER_FORMAT_FLAC  = SF_FORMAT_FLAC,
+    HEADER_FORMAT_CAF   = SF_FORMAT_CAF
+};
+#endc
+
+-- | Sample format.
+{#enum SampleFormat {underscoreToCase} deriving (Eq, Show)#}
+#c
+enum SampleFormat
+{
+    SAMPLE_FORMAT_NONE              = 0,
+
+    SAMPLE_FORMAT_PCM_S8            = SF_FORMAT_PCM_S8,
+    SAMPLE_FORMAT_PCM_16            = SF_FORMAT_PCM_16,
+    SAMPLE_FORMAT_PCM_24            = SF_FORMAT_PCM_24,
+    SAMPLE_FORMAT_PCM_32            = SF_FORMAT_PCM_32,
+                                    
+    SAMPLE_FORMAT_PCM_U8            = SF_FORMAT_PCM_U8,
+                                    
+    SAMPLE_FORMAT_FLOAT             = SF_FORMAT_FLOAT,
+    SAMPLE_FORMAT_DOUBLE            = SF_FORMAT_DOUBLE,
+                                    
+    SAMPLE_FORMAT_ULAW              = SF_FORMAT_ULAW,
+    SAMPLE_FORMAT_ALAW              = SF_FORMAT_ALAW,
+    SAMPLE_FORMAT_IMA_ADPCM         = SF_FORMAT_IMA_ADPCM,
+    SAMPLE_FORMAT_MS_ADPCM          = SF_FORMAT_MS_ADPCM,
+                                    
+    SAMPLE_FORMAT_GSM610            = SF_FORMAT_GSM610,
+    SAMPLE_FORMAT_VOX_ADPCM         = SF_FORMAT_VOX_ADPCM,
+                                    
+    SAMPLE_FORMAT_G721_32           = SF_FORMAT_G721_32,
+    SAMPLE_FORMAT_G723_24           = SF_FORMAT_G723_24,
+    SAMPLE_FORMAT_G723_40           = SF_FORMAT_G723_40,
+                                    
+    SAMPLE_FORMAT_DWVW_12           = SF_FORMAT_DWVW_12,
+    SAMPLE_FORMAT_DWVW_16           = SF_FORMAT_DWVW_16,
+    SAMPLE_FORMAT_DWVW_24           = SF_FORMAT_DWVW_24,
+    SAMPLE_FORMAT_DWVW_N            = SF_FORMAT_DWVW_N,
+                             
+    SAMPLE_FORMAT_FORMAT_DPCM_8     = SF_FORMAT_DPCM_8,
+    SAMPLE_FORMAT_FORMAT_DPCM_16    = SF_FORMAT_DPCM_16
+};
+#endc
+
+-- | Endianness.
+{#enum EndianFormat {underscoreToCase} deriving (Eq, Show)#}
+#c
+enum EndianFormat
+{
+    ENDIAN_FILE     = SF_ENDIAN_FILE,
+    ENDIAN_LITTLE   = SF_ENDIAN_LITTLE,
+    ENDIAN_BIG      = SF_ENDIAN_BIG,
+    ENDIAN_CPU      = SF_ENDIAN_CPU
+};
+#endc
+
+-- only used internally
+{#enum FormatMask {underscoreToCase} deriving (Eq)#}
+#c
+enum FormatMask
+{
+    FORMAT_SUB_MASK     = SF_FORMAT_SUBMASK,
+    FORMAT_TYPE_MASK    = SF_FORMAT_TYPEMASK,
+    FORMAT_END_MASK     = SF_FORMAT_ENDMASK
+};
+#endc
+
+-- |Stream format specification, consisting of header, sample and endianness
+-- formats.
+--
+-- Not all combinations of header, sample and endianness formats are valid;
+-- valid combinamtions can be checked with the 'checkFormat' function.
+data Format = Format {
+    headerFormat :: HeaderFormat,
+    sampleFormat :: SampleFormat,
+    endianFormat :: EndianFormat
+} deriving (Eq, Show)
+
+-- |Default \'empty\' format, useful when opening files for reading with 'ReadMode'.
+defaultFormat :: Format
+defaultFormat = Format HeaderFormatNone SampleFormatNone EndianFile
+
+-- Convert CInt to Format
+hsFormat :: CInt -> Format
+hsFormat i =
+   let hf = cToEnum (i .&. (cFromEnum FormatTypeMask) .&. complement (cFromEnum FormatEndMask))
+       sf = cToEnum (i .&. (cFromEnum FormatSubMask))
+       ef = cToEnum (i .&. (cFromEnum FormatEndMask))
+   in
+       Format {
+           headerFormat = hf,
+           sampleFormat = sf,
+           endianFormat = ef
+       }
+
+-- Convert Format to CInt
+cFormat :: Format -> CInt
+cFormat (Format hf sf ef) = (cFromEnum hf) .|. (cFromEnum sf) .|. (cFromEnum ef)
+
+-- ====================================================================
+-- Info
+
+-- |The 'Info' structure is for passing data between the calling function and
+-- the library when opening a stream for reading or writing.
+data Info = Info {
+    frames :: Count,    -- ^Number of frames in file
+    samplerate :: Int,  -- ^Audio sample rate
+    channels :: Int,    -- ^Number of channels
+    format :: Format,   -- ^Header and sample format
+    sections :: Int,    -- ^Number of sections
+    seekable :: Bool    -- ^'True' when stream is seekable (e.g. local files)
+} deriving (Eq, Show)
+
+-- |Return soundfile duration in seconds computed via the 'Info' fields
+-- 'frames' and 'samplerate'.
+duration :: Info -> Double
+duration info = (fromIntegral $ frames info) / (fromIntegral $ samplerate info)
+
+-- |Default \'empty\' info, useful when opening files for reading with 'ReadMode'.
+defaultInfo :: Info
+defaultInfo   = Info 0 0 0 defaultFormat 0 False
+
+-- |This function allows the caller to check if a set of parameters in the
+-- 'Info' struct is valid before calling 'openFile' ('WriteMode').
+--
+-- 'checkFormat' returns 'True' if the parameters are valid and 'False' otherwise.
+
+{-# NOINLINE checkFormat #-}
+checkFormat :: Info -> Bool
+checkFormat info =
+    unsafePerformIO (with info (liftM cToBool . {#call unsafe sf_format_check#} . castPtr))
+
+-- Storable instance for Info
+instance Storable (Info) where
+    alignment _ = alignment (undefined :: CInt) -- hmm
+    sizeOf _ = {#sizeof INFO#}
+    -- Unmarshall Info from C representation
+    peek ptr = do
+        frames     <- liftM fromIntegral $ {#get SF_INFO.frames#} ptr
+        samplerate <- liftM fromIntegral $ {#get SF_INFO.samplerate#} ptr
+        channels   <- liftM fromIntegral $ {#get SF_INFO.channels#} ptr
+        format     <- liftM hsFormat     $ {#get SF_INFO.format#} ptr
+        sections   <- liftM fromIntegral $ {#get SF_INFO.sections#} ptr
+        seekable   <- liftM toBool       $ {#get SF_INFO.seekable#} ptr
+        return $ Info {
+            frames = frames,
+            samplerate = samplerate,
+            channels = channels,
+            format = format,
+            sections = sections,
+            seekable = seekable
+        }
+    -- Marshall Info to C representation
+    poke ptr info =
+        do
+            {#set SF_INFO.frames#} ptr     $ fromIntegral $ frames info
+            {#set SF_INFO.samplerate#} ptr $ fromIntegral $ samplerate info
+            {#set SF_INFO.channels#} ptr   $ fromIntegral $ channels info
+            {#set SF_INFO.format#} ptr     $ cFormat      $ format info
+            {#set SF_INFO.sections#} ptr   $ fromIntegral $ sections info
+            {#set SF_INFO.seekable#} ptr   $ fromBool     $ seekable info
+
+-- ====================================================================
+-- Exceptions
+
+-- |Values of type 'Exception' are thrown by the library when an error occurs.
+--
+-- Use 'catch' to catch only exceptions of this type.
+data Exception = Exception String deriving (Typeable, Show)
+
+-- |Return the error string associated with the 'Exception'.
+errorString :: Exception -> String
+errorString (Exception s) = s
+
+-- |Catch values of type 'Exception'.
+catch :: IO a -> (Exception -> IO a) -> IO a
+catch = catchDyn
+
+throw :: Exception -> a
+throw = throwDyn
+
+raiseError :: Handle -> IO ()
+raiseError handle = liftM (throw . Exception) $ (peekCString $ {#call pure sf_strerror#} (hPtr handle))
+
+checkHandle :: HandlePtr -> IO HandlePtr
+checkHandle handle = do
+    code <- liftM fromIntegral $ {#call unsafe sf_error#} handle
+    when (code /= 0) $ raiseError (Handle defaultInfo handle)
+    return handle
+
+-- ====================================================================
+-- Handle operations
+
+-- | Abstract file handle.
+data Handle = Handle {
+    hInfo :: Info,      -- ^Return the stream 'Info' associated with the 'Handle'.
+    hPtr :: HandlePtr
+}
+type HandlePtr = Ptr ()
+
+-- | I\/O mode.
+{#enum IOMode {} deriving (Eq, Show)#}
+#c
+enum IOMode
+{
+    ReadMode        = SFM_READ,
+    WriteMode       = SFM_WRITE,
+    ReadWriteMode   = SFM_RDWR
+};
+#endc
+
+-- |When opening a file for read ('ReadMode'), the format field should be set
+-- to 'defaultFormat' before calling 'openFile'. The only exception to this is
+-- the case of RAW files, where the caller has to set the samplerate, channels
+-- and format fields to valid values. All other fields of the structure are
+-- filled in by the library.
+--
+-- When opening a file for write ('WriteMode'), the caller must fill in the
+-- structure members samplerate, channels, and format.
+--
+-- Every call to 'openFile' should be matched with a call to 'hClose' to free
+-- up memory allocated during the call to 'openFile'.
+--
+-- On success, the 'openFile' function returns a 'Handle' which should be
+-- passed as the first parameter to all subsequent libsndfile calls dealing
+-- with that audio stream. On fail, the 'openFile' function signals an
+-- 'Exception'.
+openFile :: FilePath -> IOMode -> Info -> IO Handle
+openFile filePath ioMode info =
+    withCString filePath (\cFilePath ->
+        with info (\cInfo -> do
+            cHandle <- {#call unsafe sf_open#}
+                            cFilePath (cFromEnum ioMode) (castPtr cInfo)
+                            >>= checkHandle
+            newInfo <- peek cInfo
+            return $ Handle newInfo cHandle))
+
+-- |The 'hClose' function closes the stream, deallocates its internal buffers
+-- and returns () on success or signals an 'Exception' otherwise.
+hClose :: Handle -> IO ()
+hClose handle = do
+    {#call unsafe sf_close#} $ hPtr handle
+    checkHandle nullPtr
+    return ()
+
+-- |If the stream is opened with 'WriteMode' or 'ReadWriteMode', call the
+-- operating system\'s function to force the writing of all file cache buffers
+-- to disk. If the file is opened with 'ReadMode' no action is taken.
+hFlush :: Handle -> IO ()
+hFlush (Handle _ handle) = {#call unsafe sf_write_sync#} handle
+
+-- |Get header format information associated with file.
+getFileInfo :: FilePath -> IO Info
+getFileInfo filePath = do
+    h <- openFile filePath ReadMode defaultInfo
+    let info = hInfo h
+    hClose h
+    return info
+
+-- ====================================================================
+-- seeking
+
+hIsSeekable :: Handle -> IO Bool
+hIsSeekable = return . seekable . hInfo
+
+{#enum SeekMode {} deriving (Eq, Show)#}
+#c
+enum SeekMode
+{
+    AbsoluteSeek    = SEEK_SET,
+    RelativeSeek    = SEEK_CUR,
+    SeekFromEnd     = SEEK_END
+};
+#endc
+
+-- Helper function for seeking, modifying either the read pointer, the write
+-- pointer, or both.
+{-# INLINE hSeek' #-}
+hSeek' :: Maybe IOMode -> Handle -> SeekMode -> Count -> IO Count
+hSeek' ioMode (Handle _ handle) seekMode frames = do
+    n <- liftM fromIntegral $
+            {#call unsafe sf_seek#}
+                handle
+                (cIntConv frames)
+                ((cFromEnum seekMode) .|. (case ioMode of
+                                                Nothing -> 0
+                                                Just m -> cFromEnum m))
+    checkHandle handle
+    return n
+
+-- |The file seek functions work much like 'System.IO.hseek' with the
+-- exception that the non-audio data is ignored and the seek only moves within
+-- the audio data section of the file. In addition, seeks are defined in
+-- number of (multichannel) frames. Therefore, a seek in a stereo file from
+-- the current position forward with an offset of 1 would skip forward by one
+-- sample of both channels.
+--
+-- like lseek(), the whence parameter can be any one of the following three
+-- values:
+--
+-- * 'AbsoluteSeek' - The offset is set to the start of the audio data plus
+--   offset (multichannel) frames.
+--
+-- * 'RelativeSeek' - The offset is set to its current location plus offset
+--   (multichannel) frames.
+--
+-- * 'SeekFromEnd' - The offset is set to the end of the data plus offset
+--   (multichannel) frames.
+--
+-- Internally, libsndfile keeps track of the read and write locations using
+-- separate read and write pointers. If a file has been opened with a mode of
+-- 'ReadWriteMode', calling either 'hSeekRead' or 'hSeekWrite' allows the read
+-- and write pointers to be modified separately. 'hSeek' modifies both the
+-- read and the write pointer.
+--         
+-- Note that the frames offset can be negative and in fact should be when
+-- SeekFromEnd is used for the whence parameter.
+--         
+-- 'hSeek' will return the offset in (multichannel) frames from the start of
+-- the audio data, or signal an error when an attempt is made to seek beyond
+-- the start or end of the file.
+
+hSeek :: Handle -> SeekMode -> Count -> IO Count
+hSeek = hSeek' Nothing
+
+--hSeek (Handle _ handle) seekMode frames = do
+--    n <- liftM fromIntegral $ {#call unsafe sf_seek#} handle (cIntConv frames) (cFromEnum seekMode)
+--    checkHandle handle
+--    return n
+
+-- |Like 'hSeek', but only the read pointer is modified.
+hSeekRead :: Handle -> SeekMode -> Count -> IO Count
+hSeekRead = hSeek' (Just ReadMode)
+
+-- |Like 'hSeek', but only the write pointer is modified.
+hSeekWrite :: Handle -> SeekMode -> Count -> IO Count
+hSeekWrite = hSeek' (Just WriteMode)
+
+-- ====================================================================
+-- string access
+
+-- |Header string field types.
+{#enum StringType {underscoreToCase} deriving (Eq, Show)#}
+#c
+enum StringType
+{
+    STR_TITLE       = SF_STR_TITLE,
+    STR_COPYRIGHT   = SF_STR_COPYRIGHT,
+    STR_SOFTWARE    = SF_STR_SOFTWARE,
+    STR_ARTIST      = SF_STR_ARTIST,
+    STR_COMMENT     = SF_STR_COMMENT,
+    STR_DATE        = SF_STR_DATE
+};
+#endc
+
+-- |The 'getString' function returns the specificed string from the stream
+-- header in the 'Maybe' monad if it exists and 'Nothing' otherwise.
+getString :: Handle -> StringType -> IO (Maybe String)
+getString (Handle _ handle) t = do
+    ptr <- {#call unsafe sf_get_string#} handle (cFromEnum t)
+    if ptr == (nullPtr :: Ptr CChar)
+        then return Nothing
+        else liftM Just $ peekCString =<< (return ptr)
+
+
+-- |The 'setString' function sets the string data associated with the
+-- respective 'StringType'.
+setString :: Handle -> StringType -> String -> IO ()
+setString (Handle _ handle) t s =
+    withCString s (\cs -> do
+        {#call unsafe sf_set_string#} handle (cFromEnum t) cs
+        checkHandle handle
+        return ())
+
+-- EOF
diff --git a/hsndfile.cabal b/hsndfile.cabal
new file mode 100644
--- /dev/null
+++ b/hsndfile.cabal
@@ -0,0 +1,27 @@
+Name:                   hsndfile
+Version:                0.1.1
+Category:		Sound
+License:                GPL
+License-File:           COPYING
+Copyright:              Stefan Kersten, 2007-2008
+Author:                 Stefan Kersten
+Maintainer:             Stefan Kersten <sk@k-hornz.de>
+Stability:              Experimental
+Homepage:               http://darcs.k-hornz.de/cgi-bin/darcsweb.cgi?r=hsndfile;a=summary
+Synopsis:               Haskell bindings for libsndfile
+Description:            Haskell bindings for libsndfile.
+                        .
+                        Libsndfile is a comprehensive C library for reading
+                        and writing a large number of soundfile formats:
+                        <http://www.mega-nerd.com/libsndfile/>.
+Tested-With:            GHC
+Build-Type:		Simple
+Build-Depends:          array, base, carray, haskell98
+Exposed-Modules:        Sound.File.Sndfile
+Other-Modules:          C2HS,
+		        Sound.File.Sndfile.Buffer,
+		        Sound.File.Sndfile.Buffer.IOCArray,
+		        Sound.File.Sndfile.Buffer.Storable,
+		        Sound.File.Sndfile.Interface
+Ghc-Options:            -Wall
+Extra-Libraries:        sndfile
