hsndfile 0.5.3 → 0.7.0
raw patch · 6 files changed
+92/−65 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Sound.File.Sndfile: catch :: Exception e => IO a -> (e -> IO a) -> IO a
Files
- ChangeLog.md +18/−9
- Sound/File/Sndfile.hs +7/−6
- Sound/File/Sndfile/Buffer.hs +3/−5
- Sound/File/Sndfile/Exception.hs +3/−12
- Sound/File/Sndfile/Interface.chs +59/−31
- hsndfile.cabal +2/−2
ChangeLog.md view
@@ -1,27 +1,36 @@-### Version 0.5+### v0.7 -* [__USER__] Remove lazy read functions `hGetContentChunks` and `readFileChunks` from library interface. Those functions were implemented incorrectly.+* Read and write signed instead of unsigned integer samples and rename `sf_readf_wordXX` and `sf_writef_wordXX` to `sf_readf_intXX` and `sf_writef_intXX`, respectively+* Add new supported header and sample formats -### Version 0.4+### v0.6 -* [__USER__] Simplified Buffer API: A single type class, **Buffer**, is provided for **ForeignPtr** based I/O. Instances are provided in separate packages, e.g. [hsndfile-vector](http://hackage.haskell.org/package/hsndfile-vector).+* Don't export `Control.Exception.catch` and `Prelude` from `Sound.File.Sndfile` -### Version 0.3.2+### v0.5 -* [__USER__] **hsndfile** has been adapted to compile with GHC 6.10. The only+* Remove lazy read functions `hGetContentChunks` and `readFileChunks` from library interface. Those functions were implemented incorrectly.++### v0.4++* Simplified Buffer API: A single type class, **Buffer**, is provided for **ForeignPtr** based I/O. Instances are provided in separate packages, e.g. [hsndfile-vector](http://hackage.haskell.org/package/hsndfile-vector).++### v0.3.2++* **hsndfile** has been adapted to compile with GHC 6.10. The only visible change is in exception handling: * `Sound.File.Sndfile.Exception.Exception` is now an instance of `Control.Exception.Exception` * The new generalized functions from `Control.Exception.Exception` are used for throwing and handling exceptions -### Version 0.2.0+### v0.2.0 -* [__BUGFIX__] Fix exception throwing Exceptions detected in library code are+* Fix exception throwing Exceptions detected in library code are now actually raised. Exception has been factored into Sound.File.Sndfile.Exception and constructors were added according to the public libsndfile error codes.-* [__BUGFIX__] Fix reading/writing of frames hGetFrames and hPutFrames were+* Fix reading/writing of frames hGetFrames and hPutFrames were using the sample-based library functions. These have been factored into Sound.File.Sndfile.Buffer and the correct functions are being used for the frame-based I/O functions.
Sound/File/Sndfile.hs view
@@ -1,5 +1,8 @@--- | "Sound.File.Sndfile" provides a Haskell interface to the libsndfile library by Erik de Castro Lopo (visit the library's website at <http://www.mega-nerd.com/libsndfile/>).--- The API is modeled after the original /C/ API, but type and function identifiers follow Haskell naming conventions.+-- | "Sound.File.Sndfile" provides a Haskell interface to the libsndfile+-- library by Erik de Castro Lopo (<http://www.mega-nerd.com/libsndfile/>).+--+-- The API is modeled after the original /C/ API, but type and function+-- identifiers follow Haskell naming conventions. module Sound.File.Sndfile ( -- *Types@@ -23,14 +26,12 @@ , hGetContents, readFile , hPutBuffer, writeFile -- *Exception handling- , Exception(..), catch+ , Exception(..) -- *Header string field access , StringType(..), getString, setString-- , module Prelude ) where -import Prelude hiding (catch, readFile, writeFile)+import Prelude hiding (readFile, writeFile) import Sound.File.Sndfile.Buffer import Sound.File.Sndfile.Exception import Sound.File.Sndfile.Interface
Sound/File/Sndfile/Buffer.hs view
@@ -14,7 +14,6 @@ import Control.Monad import Foreign import Prelude hiding (readFile, writeFile)-import Sound.File.Sndfile.Exception (throw) import Sound.File.Sndfile.Interface import Sound.File.Sndfile.Buffer.Sample (Sample(..)) @@ -58,10 +57,9 @@ hPutBuffer h buffer = do (fp, i, n) <- toForeignPtr buffer if n `mod` numChannels /= 0- then throw 0 "hPutBuffer: invalid buffer size (not a multiple of channel count)"- else- withForeignPtr fp $ \ptr ->- hPutBuf h (ptr `advancePtr` i) (n `div` numChannels)+ then error "hPutBuffer: invalid buffer size (not a multiple of channel count)"+ else withForeignPtr fp $ \ptr ->+ hPutBuf h (ptr `advancePtr` i) (n `div` numChannels) where numChannels = channels $ hInfo h
Sound/File/Sndfile/Exception.hs view
@@ -1,10 +1,9 @@ {-# LANGUAGE DeriveDataTypeable #-} module Sound.File.Sndfile.Exception (- Exception(..),- catch, try, throw+ Exception(..)+, fromErrorCode ) where -import Control.Exception (catch, try) import qualified Control.Exception as E import Data.Typeable (Typeable) import Prelude hiding (catch)@@ -22,18 +21,10 @@ instance E.Exception (Exception) --- | Construct 'Exception' from error code and string.+-- | Construct 'Exception' from error code and message. fromErrorCode :: Int -> String -> Exception fromErrorCode 1 = UnrecognisedFormat fromErrorCode 2 = SystemError fromErrorCode 3 = MalformedFile fromErrorCode 4 = UnsupportedEncoding fromErrorCode _ = Exception---- |Catch values of type 'Exception'.--- catch :: IO a -> (Exception -> IO a) -> IO a--- catch = E.catch---- | Throw 'Exception' according to error code and string-throw :: Int -> String -> a-throw code str = E.throw (fromErrorCode code str)
Sound/File/Sndfile/Interface.chs view
@@ -1,10 +1,10 @@ {-# LANGUAGE ForeignFunctionInterface #-} module Sound.File.Sndfile.Interface where +import qualified Control.Exception as E import Control.Monad (liftM, when) import Foreign import Foreign.C- import qualified Sound.File.Sndfile.Exception as E #include <stdint.h>@@ -128,16 +128,17 @@ }; #endc --- |Stream format specification, consisting of header, sample and endianness formats.+-- | Stream format specification, consisting of header, sample and endianness formats. ----- Not all combinations of header, sample and endianness formats are valid; valid combinations can be checked with the 'checkFormat' function.+-- Not all combinations of header, sample and endianness formats are valid;+-- valid combinations 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'.+-- | Default \'empty\' format, useful when opening files for reading with 'ReadMode'. defaultFormat :: Format defaultFormat = Format HeaderFormatNone SampleFormatNone EndianFile @@ -161,7 +162,8 @@ -- ==================================================================== -- Info --- |The 'Info' structure is for passing data between the calling function and the library when opening a stream for reading or writing.+-- | 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@@ -171,7 +173,8 @@ 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'.+-- | Return soundfile duration in seconds computed via the 'Info' fields+-- 'frames' and 'samplerate'. duration :: Info -> Double duration info = (fromIntegral $ frames info) / (fromIntegral $ samplerate info) @@ -179,10 +182,11 @@ 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').+-- | 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.-+-- 'checkFormat' returns 'True' if the parameters are valid and 'False'+-- otherwise. {-# NOINLINE checkFormat #-} checkFormat :: Info -> Bool checkFormat info =@@ -225,7 +229,7 @@ checkHandle handle = do code <- liftM fromIntegral $ {#call unsafe sf_error#} handle when (code /= 0) $- peekCString ({#call pure sf_strerror#} handle) >>= E.throw code+ peekCString ({#call pure sf_strerror#} handle) >>= E.throw . E.fromErrorCode code -- ==================================================================== -- Handle operations@@ -248,13 +252,22 @@ }; #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 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.+-- 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'.+-- 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'.+-- 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 ->@@ -265,18 +278,22 @@ 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.+-- | 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.+-- | 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.+-- | Get header format information associated with file. getFileInfo :: FilePath -> IO Info getFileInfo filePath = do h <- openFile filePath ReadMode defaultInfo@@ -314,22 +331,33 @@ 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.+-- | 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:+-- 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.+-- * '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.+-- * '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.+-- * '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.+-- 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.+-- 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' 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 @@ -338,18 +366,18 @@ -- checkHandle handle -- return n --- |Like 'hSeek', but only the read pointer is modified.+-- | 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.+-- | 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.+-- | Header string field types. {#enum StringType {underscoreToCase} deriving (Eq, Show)#} #c enum StringType@@ -363,7 +391,7 @@ }; #endc --- |The 'getString' function returns the specified string from the stream header in the 'Maybe' monad if it exists and 'Nothing' otherwise.+-- | The 'getString' function returns the specified 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)@@ -372,7 +400,7 @@ else liftM Just $ peekCString =<< (return ptr) --- |The 'setString' function sets the string data associated with the respective 'StringType'.+-- | 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
hsndfile.cabal view
@@ -1,9 +1,9 @@ Name: hsndfile-Version: 0.5.3+Version: 0.7.0 Category: Data, Sound License: LGPL-2.1 License-File: COPYING-Copyright: Stefan Kersten, 2007-2010+Copyright: Stefan Kersten, 2007-2013 Author: Stefan Kersten Maintainer: Stefan Kersten <sk@k-hornz.de> Homepage: http://haskell.org/haskellwiki/Hsndfile