packages feed

sndfile-enumerators 0.8.0 → 0.9.0

raw patch · 13 files changed

+373/−239 lines, 13 filesdep +filepathdep +listlike-instancesdep +vectordep −mutable-iterdep ~iterateePVP ok

version bump matches the API change (PVP)

Dependencies added: filepath, listlike-instances, vector

Dependencies removed: mutable-iter

Dependency ranges changed: iteratee

API changes (from Hackage documentation)

+ Sound.Iteratee.Base: CorruptFileException :: CorruptFileException
+ Sound.Iteratee.Base: MissingFormatException :: MissingFormatException
+ Sound.Iteratee.Base: UnknownFileTypeException :: UnknownFileTypeException
+ Sound.Iteratee.Base: data CorruptFileException
+ Sound.Iteratee.Base: data MissingFormatException
+ Sound.Iteratee.Base: data UnknownFileTypeException
+ Sound.Iteratee.Base: getChannel :: Monad m => Int -> Int -> Enumeratee (Vector Double) (Vector Double) m a
+ Sound.Iteratee.Base: instance Data AudioFormat
+ Sound.Iteratee.Base: instance Data SupportedFileFormat
+ Sound.Iteratee.Base: instance Eq CorruptFileException
+ Sound.Iteratee.Base: instance Eq MissingFormatException
+ Sound.Iteratee.Base: instance Eq UnknownFileTypeException
+ Sound.Iteratee.Base: instance Exception CorruptFileException
+ Sound.Iteratee.Base: instance Exception MissingFormatException
+ Sound.Iteratee.Base: instance Exception UnknownFileTypeException
+ Sound.Iteratee.Base: instance IException CorruptFileException
+ Sound.Iteratee.Base: instance IException MissingFormatException
+ Sound.Iteratee.Base: instance IException UnknownFileTypeException
+ Sound.Iteratee.Base: instance ReadableChunk (Vector Word8) Word8
+ Sound.Iteratee.Base: instance Show CorruptFileException
+ Sound.Iteratee.Base: instance Show MissingFormatException
+ Sound.Iteratee.Base: instance Show UnknownFileTypeException
+ Sound.Iteratee.Base: instance Storable a => NullPoint (Vector a)
+ Sound.Iteratee.Base: instance Storable a => Nullable (Vector a)
+ Sound.Iteratee.Base: instance Typeable AudioFormat
+ Sound.Iteratee.Base: instance Typeable CorruptFileException
+ Sound.Iteratee.Base: instance Typeable MissingFormatException
+ Sound.Iteratee.Base: instance Typeable SupportedFileFormat
+ Sound.Iteratee.Base: instance Typeable UnknownFileTypeException
+ Sound.Iteratee.Codecs.Wave: type WAVEDict = IntMap [WAVEDE]
+ Sound.Iteratee.File: defaultBufSize :: Int
+ Sound.Iteratee.File: enumAudioIteratee :: (MonadCatchIO m, Functor m) => FilePath -> Iteratee (Vector Double) m a -> m (Iteratee (Vector Double) m a)
+ Sound.Iteratee.File: enumAudioIterateeWithFormat :: (MonadCatchIO m, Functor m) => FilePath -> (AudioFormat -> Iteratee (Vector Double) m a) -> m (Iteratee (Vector Double) m a)
+ Sound.Iteratee.File: getAudioInfo :: FilePath -> IO (Maybe AudioFormat)
+ Sound.Iteratee.File: getFormat :: FilePath -> Maybe SupportedFileFormat
+ Sound.Iteratee.File: runAudioIteratee :: FilePath -> Iteratee (Vector Double) AudioMonad a -> IO a
+ Sound.Iteratee.File: tryRunAudioIteratee :: Exception e => FilePath -> Iteratee (Vector Double) AudioMonad a -> IO (Either e a)
+ Sound.Iteratee.Writer: enumAudioFile :: MonadCatchIO m => Int -> FilePath -> Enumerator (Vector Word8) m a
- Sound.Iteratee.Codecs: getWriter :: SupportedFileFormat -> FilePath -> AudioFormat -> MIteratee (IOBuffer r Double) AudioMonad ()
+ Sound.Iteratee.Codecs: getWriter :: SupportedFileFormat -> FilePath -> AudioFormat -> Iteratee (Vector Double) AudioMonad ()
- Sound.Iteratee.Codecs.Raw: readRaw :: (MonadCatchIO m, Functor m) => AudioFormat -> MIteratee (IOB r Double) m a -> MIteratee (IOB r Word8) m a
+ Sound.Iteratee.Codecs.Raw: readRaw :: (MonadCatchIO m, Functor m) => AudioFormat -> Iteratee (Vector Double) m a -> Iteratee (Vector Word8) m a
- Sound.Iteratee.Codecs.Wave: WENBYTE :: (forall a m r. (MonadCatchIO m, Functor m) => MEnumeratorM (IOB r Word8) (IOB r Word8) m a) -> WAVEDEENUM
+ Sound.Iteratee.Codecs.Wave: WENBYTE :: (forall a m. (MonadCatchIO m, Functor m) => MEnumeratorM (Vector Word8) (Vector Word8) m a) -> WAVEDEENUM
- Sound.Iteratee.Codecs.Wave: WENDUB :: (forall a m r. (MonadCatchIO m, Functor m) => MEnumeratorM2 (IOB r Word8) (IOB r Double) m a) -> WAVEDEENUM
+ Sound.Iteratee.Codecs.Wave: WENDUB :: (forall a m. (MonadCatchIO m, Functor m) => MEnumeratorM2 (Vector Word8) (Vector Double) m a) -> WAVEDEENUM
- Sound.Iteratee.Codecs.Wave: dictProcessData :: (MonadCatchIO m, Functor m) => Int -> WAVEDict -> MIteratee (IOB r Double) m a -> MIteratee (IOB r Word8) m (MIteratee (IOB r Double) m a)
+ Sound.Iteratee.Codecs.Wave: dictProcessData :: (MonadCatchIO m, Functor m) => Int -> WAVEDict -> Iteratee (Vector Double) m a -> Iteratee (Vector Word8) m (Iteratee (Vector Double) m a)
- Sound.Iteratee.Codecs.Wave: dictProcessData_ :: (MonadCatchIO m, Functor m) => Int -> WAVEDict -> MIteratee (IOB r Double) m a -> MIteratee (IOB r Word8) m (Maybe a)
+ Sound.Iteratee.Codecs.Wave: dictProcessData_ :: (MonadCatchIO m, Functor m) => Int -> WAVEDict -> Iteratee (Vector Double) m a -> Iteratee (Vector Word8) m (Maybe a)
- Sound.Iteratee.Codecs.Wave: dictReadFirstFormat :: (MonadCatchIO m, Functor m) => WAVEDict -> MIteratee (IOB r Word8) m (Maybe AudioFormat)
+ Sound.Iteratee.Codecs.Wave: dictReadFirstFormat :: (MonadCatchIO m, Functor m) => WAVEDict -> Iteratee (Vector Word8) m (Maybe AudioFormat)
- Sound.Iteratee.Codecs.Wave: dictReadFormat :: (MonadCatchIO m, Functor m) => Int -> WAVEDict -> MIteratee (IOB r Word8) m (Maybe AudioFormat)
+ Sound.Iteratee.Codecs.Wave: dictReadFormat :: (MonadCatchIO m, Functor m) => Int -> WAVEDict -> Iteratee (Vector Word8) m (Maybe AudioFormat)
- Sound.Iteratee.Codecs.Wave: dictReadLastFormat :: (MonadCatchIO m, Functor m) => WAVEDict -> MIteratee (IOB r Word8) m (Maybe AudioFormat)
+ Sound.Iteratee.Codecs.Wave: dictReadLastFormat :: (MonadCatchIO m, Functor m) => WAVEDict -> Iteratee (Vector Word8) m (Maybe AudioFormat)
- Sound.Iteratee.Codecs.Wave: dictSoundInfo :: (MonadCatchIO m, Functor m) => WAVEDict -> MIteratee (IOB r Word8) m (Maybe (AudioFormat, Integer))
+ Sound.Iteratee.Codecs.Wave: dictSoundInfo :: (MonadCatchIO m, Functor m) => WAVEDict -> Iteratee (Vector Word8) m (Maybe (AudioFormat, Integer))
- Sound.Iteratee.Codecs.Wave: readRiff :: MonadCatchIO m => MIteratee (IOB r Word8) m ()
+ Sound.Iteratee.Codecs.Wave: readRiff :: MonadCatchIO m => Iteratee (Vector Word8) m Bool
- Sound.Iteratee.Codecs.Wave: waveReader :: (MonadCatchIO m, Functor m) => MIteratee (IOB r Word8) m (Maybe WAVEDict)
+ Sound.Iteratee.Codecs.Wave: waveReader :: (MonadCatchIO m, Functor m) => Iteratee (Vector Word8) m (Maybe WAVEDict)
- Sound.Iteratee.Codecs.Wave: writeDataChunk :: IOBuffer r Double -> AudioMonad ()
+ Sound.Iteratee.Codecs.Wave: writeDataChunk :: Vector Double -> AudioMonad ()
- Sound.Iteratee.Codecs.Wave: writeWave :: FilePath -> AudioFormat -> MIteratee (IOBuffer r Double) AudioMonad ()
+ Sound.Iteratee.Codecs.Wave: writeWave :: FilePath -> AudioFormat -> Iteratee (Vector Double) AudioMonad ()
- Sound.Iteratee.Writer: fileDriverAudio :: Storable el => (forall r. MIteratee (IOBuffer r el) AudioMonad a) -> FilePath -> IO a
+ Sound.Iteratee.Writer: fileDriverAudio :: Iteratee (Vector Word8) AudioMonad a -> FilePath -> IO a

Files

examples/wave_reader.hs view
@@ -1,59 +1,27 @@ -- Read a wave file and return some information about it.+{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE BangPatterns #-} module Main where  import Prelude as P -import Sound.Iteratee.Codecs.Wave-import Data.MutableIter-import Data.MutableIter.IOBuffer (IOBuffer)-import qualified Data.MutableIter.IOBuffer as IB-import qualified Data.IntMap as IM-import qualified Data.Iteratee as I-import Data.Word (Word8)-import Control.Monad.CatchIO-import Control.Monad.IO.Class-import Control.Monad.Trans.Class-import System+import           Sound.Iteratee+import qualified Data.Vector.Storable as V+import           Data.Iteratee as I+import           Control.Monad.CatchIO+import           System  main :: IO () main = do   args <- getArgs   case args of     [] -> putStrLn "Usage: wave_reader FileName"-    fname:xs -> do+    fname:_ -> do       putStrLn $ "Reading file: " ++ fname-      fileDriverRandom (2^14) (waveReader >>= test) fname-      return ()---- Use the collection of [WAVEDE] returned from waveReader to--- do further processing.  The IntMap has an entry for each type of chunk--- in the wave file.  Read the first format chunk and disply the --- format information, then use the dictProcessData function--- to enumerate over the max_iter iteratee to find the maximum value--- (peak amplitude) in the file.-test :: Maybe (IM.IntMap [WAVEDE])-  -> MIteratee (IOBuffer r Word8) IO ()-test Nothing = liftIO $ putStrLn "No dictionary"-test (Just dict) = do-  fmtm <- dictReadFirstFormat dict-  liftIO . putStrLn $ show fmtm-  maxm <- dictProcessData_ 0 dict max_iter-  liftIO . putStrLn $ show maxm-  return ()---- | As of now (ghc-7.1, mutable-iter-0.6, sndfile-enumerators-0.7)---  ,this version is as fast as max_iter-max_iter2 :: MonadCatchIO m => MIteratee (IOBuffer r Double) m Double-max_iter2 = foldl' (flip (max . abs)) 0+      e <- runAudioIteratee fname maxIter+      print e --- |This version is faster, but lower-level-max_iter :: MIteratee (IOBuffer r Double) IO Double-max_iter = m' 0-  where-    m' !acc = liftI (step acc)-    step acc (I.Chunk buf) = guardNull buf (m' acc) $ do-      val <- lift $ IB.foldl' (flip (max . abs)) acc buf-      m' val-    step acc str = idone acc str+-- | As of now (ghc-7.0.2, mutable-iter-0.6, sndfile-enumerators-0.7)+--  ,this version is as fast as a low-level implementation+maxIter :: MonadCatchIO m => Iteratee (V.Vector Double) m Double+maxIter = foldl' (flip (max . abs)) 0
examples/wave_writer.hs view
@@ -5,14 +5,14 @@  module Main where -import Data.MutableIter-import qualified Data.MutableIter.IOBuffer as IB-import Sound.Iteratee.Codecs.Wave-import Sound.Iteratee+import           Data.Iteratee+import qualified Data.Vector.Storable as V+import           Sound.Iteratee.Codecs.Wave+import           Sound.Iteratee import qualified Data.IntMap as IM-import Data.Word (Word8)-import Control.Monad.Trans-import System+import           Data.Word (Word8)+import           Control.Monad.Trans+import           System  main :: IO () main = do@@ -27,7 +27,7 @@ -- Use the collection of [WAVEDE] returned from waveReader to -- do further processing.  In this case, write out a new file with the -- same format.-writer :: FilePath -> Maybe (IM.IntMap [WAVEDE]) -> MIteratee (IB.IOBuffer r Word8) AudioMonad ()+writer :: FilePath -> Maybe (IM.IntMap [WAVEDE]) -> Iteratee (V.Vector Word8) AudioMonad () writer _ Nothing = liftIO $ putStrLn "No dictionary" writer fp (Just dict) = do   fmtm <- dictReadFirstFormat dict
examples/writer2.hs view
@@ -3,12 +3,12 @@ {-# LANGUAGE BangPatterns, RankNTypes #-} module Main where -import Data.MutableIter-import qualified Data.MutableIter.IOBuffer as IB import Sound.Iteratee.Codecs.Wave import Sound.Iteratee-import qualified Data.Iteratee as I+import           Data.Iteratee as I+import           Data.Iteratee.IO.Handle import qualified Data.IntMap as IM+import qualified Data.Vector.Storable as V import Data.Word (Word8) import Foreign.Storable (Storable) import Control.Monad.Trans@@ -20,14 +20,14 @@  file2Driver :: (MonadCatchIO m, Functor m) =>   (forall r. Maybe (IM.IntMap [WAVEDE])-    -> MIteratee (IB.IOBuffer r Word8) m (MIteratee (IB.IOBuffer r Double) m a))+    -> Iteratee (V.Vector Word8) m (Iteratee (V.Vector Double) m a))   -> FilePath   -> FilePath   -> m a file2Driver i f1 f2 = CIO.bracket   (liftIO $ (openBinaryFile f1 ReadMode >>= \h1 -> openBinaryFile f2 ReadMode >>= \h2 -> return (h1,h2)))   (liftIO . (\(h1, h2) -> hClose h1 >> hClose h2))-  (\(h1,h2) -> (I.run . unwrap) =<< (I.run . unwrap) =<<+  (\(h1,h2) -> (I.run) =<< (I.run) =<<     ( enumHandleRandom defaultChunkLength h1 (waveReader >>= i) >>= \i2 -> enumHandleRandom defaultChunkLength h2 (waveReader >>= \mdict -> i2 >>= embedProc mdict)))  main :: IO ()@@ -42,7 +42,7 @@     _ -> putStrLn "Usage: wave_writer ReadFile1 ReadFile2 WriteFile"  -embedProc :: (MonadCatchIO m, Functor m) => Maybe (IM.IntMap [WAVEDE]) -> MIteratee (IB.IOBuffer r Double) m a -> MIteratee (IB.IOBuffer r Word8) m (MIteratee (IB.IOBuffer r Double) m a)+embedProc :: (MonadCatchIO m, Functor m) => Maybe (IM.IntMap [WAVEDE]) -> Iteratee (V.Vector Double) m a -> Iteratee (V.Vector Word8) m (Iteratee (V.Vector Double) m a) embedProc Nothing i = error "No dictionary" embedProc (Just dict) i = dictProcessData 0 dict i @@ -52,7 +52,7 @@ -- format information, then use the dictProcessData function -- to enumerate over the max_iter iteratee to find the maximum value -- (peak amplitude) in the file.-writer :: FilePath -> Maybe (IM.IntMap [WAVEDE]) -> MIteratee (IB.IOBuffer r Word8) AudioMonad (MIteratee (IB.IOBuffer r Double) AudioMonad ())+writer :: FilePath -> Maybe (IM.IntMap [WAVEDE]) -> Iteratee (V.Vector Word8) AudioMonad (Iteratee (V.Vector Double) AudioMonad ()) writer _ Nothing = error "No Dictionary" writer fp (Just dict) = do   fmtm <- dictReadFirstFormat dict
sndfile-enumerators.cabal view
@@ -1,5 +1,5 @@ Name:		sndfile-enumerators-Version:        0.8.0+Version:        0.9.0 Cabal-Version:  >= 1.2 Description:	encode and decode soundfiles using Iteratees.                 Audio files may be read or written, with classes and @@ -31,22 +31,26 @@  ghc-options:    -Wall    -fexcess-precision+   -O2  build-depends:-   base                      >= 3   && < 5,-   binary                    >= 0.5 && < 0.6,-   containers                >= 0.2 && < 0.5,-   transformers              >= 0.2 && < 0.3,-   iteratee                  >= 0.4 && < 0.9,+   base                      >= 3     && < 5,+   binary                    >= 0.5   && < 0.6,    bytestring                >= 0.9.1 && < 0.10,-   word24                    >= 0.1 && < 0.2,-   mutable-iter              >= 0.1 && < 0.7,-   MonadCatchIO-transformers >= 0.2 && < 0.3+   containers                >= 0.2   && < 0.5,+   iteratee                  >= 0.8.4 && < 0.9,+   filepath                  >= 1.0   && < 2.0,+   listlike-instances        >= 0.1,+   MonadCatchIO-transformers >= 0.2   && < 0.3,+   transformers              >= 0.2   && < 0.3,+   vector                    >= 0.6   && < 0.8,+   word24                    >= 0.1 && < 0.2  exposed-modules:    Sound.Iteratee    Sound.Iteratee.Base    Sound.Iteratee.Codecs    Sound.Iteratee.Codecs.Wave    Sound.Iteratee.Codecs.Raw+   Sound.Iteratee.File    Sound.Iteratee.Writer  other-modules:    Sound.Iteratee.Codecs.WaveWriter
src/Sound/Iteratee.hs view
@@ -1,12 +1,14 @@ module Sound.Iteratee (   module Sound.Iteratee.Base,   module Sound.Iteratee.Writer,-  module Sound.Iteratee.Codecs+  module Sound.Iteratee.Codecs,+  module Sound.Iteratee.File )  where  import Sound.Iteratee.Base import Sound.Iteratee.Codecs+import Sound.Iteratee.File import Sound.Iteratee.Writer 
src/Sound/Iteratee/Base.hs view
@@ -1,3 +1,8 @@+{-# LANGUAGE ScopedTypeVariables+            ,FlexibleInstances+            ,MultiParamTypeClasses+            ,DeriveDataTypeable #-}+ module Sound.Iteratee.Base (   -- * Types   -- ** Internal types@@ -15,16 +20,36 @@   BitDepth,   FrameCount,   -- ** File Format Types-  SupportedFileFormat (..)+  SupportedFileFormat (..),+  -- ** Exceptions+  UnknownFileTypeException (..),+  CorruptFileException (..),+  MissingFormatException (..),+  -- * Audio iteratees+  getChannel )  where  import Prelude as P -import Control.Monad.Trans.State-import System.IO+import           Control.Exception+import           Control.Monad.Trans.State+import           Control.Monad.IO.Class+import           System.IO+import           Data.Data+import           Data.Nullable+import           Data.NullPoint+import           Data.Iteratee as I+import           Data.Iteratee.Base.ReadableChunk+import           Data.Iteratee.Exception ()+import           Data.ListLike.Vector.Storable ()+import qualified Data.Vector.Storable as V+import           Data.Word +import           Foreign.Marshal.Utils+import           Foreign.ForeignPtr+ -- |Information about the AudioStream data AudioStreamState =   WaveState !(Maybe Handle) !(Maybe AudioFormat) !Integer !Integer !Integer -- ^ Handle, format, Total bytes written, data bytes written, data chunklen offset@@ -34,7 +59,7 @@ -- | An enumeration of all file types supported for reading and writing. data SupportedFileFormat = Raw                            | Wave-                           deriving (Show, Enum, Bounded, Eq)+                           deriving (Show, Enum, Bounded, Eq, Data, Typeable)  -- | Common functions for writing audio data class WritableAudio a where@@ -51,7 +76,7 @@   numberOfChannels :: NumChannels, -- ^Number of channels in the audio data   sampleRate :: SampleRate, -- ^Sample rate of the audio data   bitDepth :: BitDepth -- ^Bit depth of the audio data-  } deriving (Show, Eq)+  } deriving (Show, Eq, Data, Typeable)  type NumChannels = Integer type SampleRate  = Integer@@ -62,3 +87,60 @@  defaultChunkLength :: Int defaultChunkLength = 8190++instance V.Storable a => Nullable (V.Vector a) where+  nullC = V.null++instance V.Storable a => NullPoint (V.Vector a) where+  empty = V.empty++instance ReadableChunk (V.Vector Word8) Word8 where+  readFromPtr src blen = liftIO $ do+    fp <- mallocForeignPtrBytes blen+    withForeignPtr fp $ \dest -> copyBytes dest src blen+    return $ V.unsafeFromForeignPtr fp 0 blen++-- | Operate on a single channel of an audio stream.+getChannel ::+  Monad m+  => Int     -- ^ number of channels+  -> Int     -- ^ channel index (1-based)+  -> Enumeratee (V.Vector Double) (V.Vector Double) m a+getChannel 1        m   = \i -> I.drop m >> convStream getChunk i+getChannel numChans chn = unfoldConvStream mkIter chn+ where+  mkIter drp = do+    I.drop drp+    buf <- getChunk+    let tlen = V.length buf+        (nlen,rest) = quotRem tlen numChans+        newbuf = V.generate nlen (\i -> V.unsafeIndex buf (i*numChans))+    return (rest, newbuf)++-- Audio Exceptions++data UnknownFileTypeException =+  UnknownFileTypeException deriving (Eq, Show, Typeable)++instance Exception UnknownFileTypeException where+  toException = iterExceptionToException+  fromException = iterExceptionFromException++instance IException UnknownFileTypeException where++data CorruptFileException = CorruptFileException deriving (Eq, Show, Typeable)++instance Exception CorruptFileException where+  toException = iterExceptionToException+  fromException = iterExceptionFromException++instance IException CorruptFileException where++data MissingFormatException =+  MissingFormatException deriving (Eq, Show, Typeable)++instance Exception MissingFormatException where+  toException = iterExceptionToException+  fromException = iterExceptionFromException++instance IException MissingFormatException where
src/Sound/Iteratee/Codecs.hs view
@@ -12,16 +12,16 @@ import Sound.Iteratee.Base import Sound.Iteratee.Codecs.Wave import Sound.Iteratee.Codecs.Raw+import Data.Iteratee -import Data.MutableIter-import qualified Data.MutableIter.IOBuffer as IB+import qualified Data.Vector.Storable as V  -- |Get a writer iteratee for a SupportedFileFormat getWriter ::   SupportedFileFormat   -> FilePath   -> AudioFormat-  -> MIteratee (IB.IOBuffer r Double) AudioMonad ()+  -> Iteratee (V.Vector Double) AudioMonad () getWriter Wave = writeWave getWriter Raw  = error "No writer defined for Raw format" 
src/Sound/Iteratee/Codecs/Common.hs view
@@ -9,35 +9,33 @@ where  import Sound.Iteratee.Base-import qualified Data.Iteratee as I-import Data.MutableIter as Iter-import qualified Data.MutableIter.IOBuffer as IB+import           Data.Iteratee as I+import qualified Data.Vector.Storable as V import Foreign import Control.Monad (replicateM, liftM) import Control.Monad.CatchIO-import Control.Monad.IO.Class import Data.Char (chr) import Data.Int.Int24 import Data.Word.Word24+import Data.ListLike.Vector.Storable ()  -- ===================================================== -- useful type synonyms -type IOB m el = IOBuffer m el- -- determine host endian-ness be :: IO Bool be = fmap (==1) $ with (1 :: Word16) (\p -> peekByteOff p 1 :: IO Word8)  -- convenience function to read a 4-byte ASCII string-stringRead4 :: MonadCatchIO m => MIteratee (IOB r Word8) m String-stringRead4 = (liftM . map) (chr . fromIntegral) $ replicateM 4 Iter.head+stringRead4 :: MonadCatchIO m => Iteratee (V.Vector Word8) m String+stringRead4 = (liftM . map) (chr . fromIntegral) $ replicateM 4 I.head -unroll8 :: (MonadCatchIO m) => MIteratee (IOB r Word8) m (Maybe (IOB r Word8))+unroll8 :: (MonadCatchIO m) => Iteratee (V.Vector Word8) m (Maybe (V.Vector Word8)) unroll8 = liftI step   where-  step (I.Chunk buf) = guardNull buf (liftI step) $-                         idone (Just buf) (I.Chunk IB.empty)+  step (I.Chunk buf)+    | V.null buf = liftI step+    | otherwise  = idone (Just buf) (I.Chunk V.empty)   step stream        = idone Nothing stream  -- When unrolling to a Word8, use the specialized unroll8 function@@ -45,37 +43,42 @@ {-# RULES "unroll8" forall n. unroller n = unroll8 #-} unroller :: (Storable a, MonadCatchIO m) =>   Int-  -> MIteratee (IOB r Word8) m (Maybe (IOB r a))+  -> Iteratee (V.Vector Word8) m (Maybe (V.Vector a)) unroller wSize = liftI step   where-  step (I.Chunk buf) = guardNull buf (liftI step) $ do-    len <- liftIO $ IB.length buf-    if len < wSize then liftIO (IB.copyBuffer buf) >>= liftI . step'+  step (I.Chunk buf)+   | V.null buf = liftI step+   | otherwise = do+    let len = V.length buf+    if len < wSize+      then liftI $ step' buf       else if len `rem` wSize == 0               then do-                buf' <- liftIO $ convert_vec buf-                idone (Just buf') (I.Chunk IB.empty)+                let buf' = convert_vec buf+                idone (Just buf') (I.Chunk V.empty)               else let newLen = (len `div` wSize) * wSize+                       h      = convert_vec $ V.take newLen buf+                       t      = V.drop newLen buf                    in do-                      (h, t) <- liftIO $ IB.splitAt buf newLen-                      h' <- liftIO $ convert_vec h-                      idone (Just h') (I.Chunk t)+                      idone (Just h) (I.Chunk t)   step stream = idone Nothing stream-  step' i (I.Chunk buf) = guardNull buf (liftI (step' i)) $ do-    l <- liftIO $ IB.length buf-    iLen <- liftIO $ IB.length i-    newbuf <- liftIO $ IB.append i buf+  step' i (I.Chunk buf)+   | V.null buf = liftI (step' i)+   | otherwise = do+    let l    = V.length buf+        iLen = V.length i+        newbuf = i V.++ buf     if l+iLen < wSize then liftI (step' newbuf)        else do-         newLen <- liftIO $ IB.length newbuf-         let newLen' = (newLen `div` wSize) * wSize-         (h,t) <- liftIO $ IB.splitAt newbuf newLen'-         h' <- liftIO $ convert_vec h-         idone (Just h') (I.Chunk t)+         let newLen  = V.length newbuf+             newLen' = (newLen `div` wSize) * wSize+             h       = convert_vec $ V.take newLen' newbuf+             t       = V.drop newLen' newbuf+         idone (Just h) (I.Chunk t)   step' _i stream  = idone Nothing stream-  convert_vec vec  = IB.castBuffer vec >>= hostToLE+  convert_vec = hostToLE -hostToLE :: (Monad m, Storable a) => IOB r a -> m (IOB r a)+hostToLE :: forall a. Storable a => V.Vector Word8 -> V.Vector a hostToLE vec = let be' = unsafePerformIO be in if be'     then error "wrong endian-ness.  Ask the maintainer to implement hostToLE" {-@@ -84,14 +87,10 @@             in             loop wSize fp len off -}-    else return vec-{--    where-      loop _wSize _fp 0 _off = return vec-      loop wSize fp len off  = do-        FFP.withForeignPtr fp (swapBytes wSize . flip FP.plusPtr off)-        loop wSize fp (len - 1) (off + 1)--}+    else let (ptr, offset,len) = V.unsafeToForeignPtr vec+         in V.unsafeFromForeignPtr (castForeignPtr ptr)+                                 offset+                                 (len `quot` sizeOf (undefined :: a))  {- swapBytes :: Int -> ForeignPtr a -> IO ()@@ -131,26 +130,24 @@ -- |Convert Word8s to Doubles convFunc :: (MonadCatchIO m) =>   AudioFormat-  -> ForeignPtr Int-  -> ForeignPtr Double-  -> MIteratee (IOBuffer r Word8) m (IOBuffer r Double)-convFunc (AudioFormat _nc _sr 8) offp bufp = do+  -> Iteratee (V.Vector Word8) m (V.Vector Double)+convFunc (AudioFormat _nc _sr 8) = do   mbuf <- unroll8-  liftIO $ maybe (error "error in convFunc") (IB.mapBuffer-    (normalize 8 . (fromIntegral :: Word8 -> Int8)) offp bufp) mbuf-convFunc (AudioFormat _nc _sr 16) offp bufp = do+  return $ maybe (error "error in convFunc") (V.map+    (normalize 8 . (fromIntegral :: Word8 -> Int8))) mbuf+convFunc (AudioFormat _nc _sr 16) = do   mbuf <- unroller (sizeOf w16)-  liftIO $ maybe (error "error in convFunc") (IB.mapBuffer-    (normalize 16 . (fromIntegral :: Word16 -> Int16)) offp bufp) mbuf-convFunc (AudioFormat _nc _sr 24) offp bufp = do+  return $ maybe (error "error in convFunc") (V.map+    (normalize 16 . (fromIntegral :: Word16 -> Int16))) mbuf+convFunc (AudioFormat _nc _sr 24) = do   mbuf <- unroller (sizeOf w24)-  liftIO $ maybe (error "error in convFunc") (IB.mapBuffer-    (normalize 24 . (fromIntegral :: Word24 -> Int24)) offp bufp) mbuf-convFunc (AudioFormat _nc _sr 32) offp bufp = do+  return $ maybe (error "error in convFunc") (V.map+    (normalize 24 . (fromIntegral :: Word24 -> Int24))) mbuf+convFunc (AudioFormat _nc _sr 32) = do   mbuf <- unroller (sizeOf w32)-  liftIO $ maybe (error "error in convFunc") (IB.mapBuffer-    (normalize 32 . (fromIntegral :: Word32 -> Int32)) offp bufp) mbuf-convFunc _ _ _ = MIteratee $ I.throwErr (I.iterStrExc "Invalid wave bit depth")+  return $ maybe (error "error in convFunc") (V.map+    (normalize 32 . (fromIntegral :: Word32 -> Int32))) mbuf+convFunc _ = I.throwErr (I.iterStrExc "Invalid wave bit depth")   -- ---------------------
src/Sound/Iteratee/Codecs/Raw.hs view
@@ -7,17 +7,12 @@  import Sound.Iteratee.Base import Sound.Iteratee.Codecs.Common-import Data.MutableIter-import qualified Data.MutableIter.IOBuffer as IB+import           Data.Iteratee as I+import qualified Data.Vector.Storable as V  import Data.Word import Control.Monad.CatchIO-import Control.Monad.IO.Class -import Foreign.ForeignPtr--type IOB = IB.IOBuffer- data RawCodec = RawCodec  instance WritableAudio RawCodec where@@ -29,10 +24,8 @@ readRaw ::  (MonadCatchIO m, Functor m) =>   AudioFormat-  -> MIteratee (IOB r Double) m a-  -> MIteratee (IOB r Word8) m a+  -> Iteratee (V.Vector Double) m a+  -> Iteratee (V.Vector Word8) m a readRaw fmt iter_dub = do-  offp <- liftIO $ newFp 0-  bufp <- liftIO $ mallocForeignPtrArray defaultChunkLength-  joinIob . convStream (convFunc fmt offp bufp) $ iter_dub+  joinI . convStream (convFunc fmt) $ iter_dub 
src/Sound/Iteratee/Codecs/Wave.hs view
@@ -3,6 +3,7 @@   -- * Types   -- ** Internal types   WaveCodec (..),+  WAVEDict,   WAVEDE (..),   WAVEDEENUM (..),   -- ** WAVE CHUNK types@@ -42,27 +43,21 @@ import Sound.Iteratee.Base import Sound.Iteratee.Codecs.Common -import qualified Data.MutableIter.IOBuffer as IB-import Data.MutableIter as MI-import Data.MutableIter.Binary+import qualified Data.Vector.Storable as V -import qualified Data.Iteratee as Itr-import Data.Iteratee (throwErr, iterStrExc)+import           Data.Iteratee as I  import qualified Data.IntMap as IM import Data.Word import Data.Char (ord) +import Control.Monad import Control.Monad.CatchIO-import Control.Monad.IO.Class--import Foreign.ForeignPtr+import Control.Monad.IO.Class ()  -- ===================================================== -- WAVE libary code -type IOB = IB.IOBuffer- -- |A WAVE directory is a list associating WAVE chunks with -- a record WAVEDE type WAVEDict = IM.IntMap [WAVEDE]@@ -77,15 +72,15 @@   show a = "Type: " ++ show (wavedeType a) ++ " :: Length: " ++             show (wavedeCount a) -type MEnumeratorM sfrom sto m a = MIteratee sto m a -> MIteratee sfrom m a-type MEnumeratorM2 sfrom sto m a = MIteratee sto m a-                                   -> MIteratee sfrom m (MIteratee sto m a)+type MEnumeratorM sfrom sto m a = Iteratee sto m a -> Iteratee sfrom m a+type MEnumeratorM2 sfrom sto m a = Iteratee sto m a+                                   -> Iteratee sfrom m (Iteratee sto m a)  data WAVEDEENUM =-  WENBYTE  (forall a m r. (MonadCatchIO m, Functor m) =>-              MEnumeratorM (IOB r Word8) (IOB r Word8) m a)-  | WENDUB (forall a m r. (MonadCatchIO m, Functor m) =>-              MEnumeratorM2 (IOB r Word8) (IOB r Double) m a)+  WENBYTE  (forall a m. (MonadCatchIO m, Functor m) =>+              MEnumeratorM (V.Vector Word8) (V.Vector Word8) m a)+  | WENDUB (forall a m. (MonadCatchIO m, Functor m) =>+              MEnumeratorM2 (V.Vector Word8) (V.Vector Double) m a)  -- |Standard WAVE Chunks data WAVECHUNK = WAVEFMT -- ^Format@@ -123,62 +118,65 @@ -- |The library function to read the WAVE dictionary waveReader ::  (MonadCatchIO m, Functor m) =>-   MIteratee (IOB r Word8) m (Maybe WAVEDict)+   Iteratee (V.Vector Word8) m (Maybe WAVEDict) waveReader = do-  readRiff+  isRiff <- readRiff+  when (not isRiff) $ throwErr . iterStrExc $ "Bad RIFF header: "   tot_size <- endianRead4 LSB-  readRiffWave+  isWave <- readRiffWave+  when (not isWave) $ throwErr . iterStrExc $ "Bad WAVE header: "   chunks_m <- findChunks $ fromIntegral tot_size   loadDict $ joinMaybe chunks_m --- |Read the RIFF header of a file.-readRiff :: MonadCatchIO m => MIteratee (IOB r Word8) m ()+-- |Read the RIFF header of a file.  Returns True if the file is a valid RIFF.+readRiff :: MonadCatchIO m => Iteratee (V.Vector Word8) m Bool readRiff = do-  cnt <- heads $ fmap (fromIntegral . ord) "RIFF"+  cnt <- heads . V.fromList $ fmap (fromIntegral . ord) "RIFF"   case cnt of-    4 -> return ()-    _ -> MIteratee . throwErr . iterStrExc $ "Bad RIFF header: "+    4 -> return True+    _ -> return False --- | Read the WAVE part of the RIFF header.-readRiffWave :: MonadCatchIO m => MIteratee (IOB r Word8) m ()+-- | Read the WAVE part of the RIFF header.  Returns True if the file is+--   a valid WAVE, otherwise False.+readRiffWave :: MonadCatchIO m => Iteratee (V.Vector Word8) m Bool readRiffWave = do-  cnt <- heads $ fmap (fromIntegral . ord) "WAVE"+  cnt <- heads . V.fromList $ fmap (fromIntegral . ord) "WAVE"   case cnt of-    4 -> return ()-    _ -> MIteratee . throwErr . iterStrExc $ "Bad RIFF/WAVE header: "+    4 -> return True+    _ -> return False  -- | An internal function to find all the chunks.  It assumes that the -- stream is positioned to read the first chunk. findChunks ::  MonadCatchIO m =>   Int-  -> MIteratee (IOB r Word8) m (Maybe [(Int, WAVECHUNK, Int)])+  -> Iteratee (V.Vector Word8) m (Maybe [(Int, WAVECHUNK, Int)]) findChunks n = findChunks' 12 []   where   findChunks' offset acc = do-    mpad <- MI.peek+    mpad <- I.peek     if (offset `rem` 2 == 1) && (mpad == Just 0)-      then MI.drop 1 >> findChunks'2 offset acc+      then I.drop 1 >> findChunks'2 offset acc       else findChunks'2 offset acc   findChunks'2 offset acc = do     typ <- stringRead4     count <- endianRead4 LSB     case waveChunk typ of-      Nothing -> (MIteratee . throwErr . iterStrExc $+      Nothing -> (throwErr . iterStrExc $         "Bad subchunk descriptor: " ++ show typ)       Just chk -> let newpos = offset + 8 + count in         if newpos >= fromIntegral n           then return . Just . reverse $                (fromIntegral offset, chk, fromIntegral count) : acc           else do-            MIteratee . Itr.seek $ fromIntegral newpos+            I.seek $ fromIntegral newpos             findChunks' newpos $              (fromIntegral offset, chk, fromIntegral count) : acc  loadDict ::  (MonadCatchIO m, Functor m) =>   [(Int, WAVECHUNK, Int)]-  -> MIteratee (IOB r Word8) m (Maybe WAVEDict)+  -> Iteratee (V.Vector Word8) m (Maybe WAVEDict) loadDict = P.foldl read_entry (return (Just IM.empty))   where   read_entry dictM (offset, typ, count) = dictM >>=@@ -201,8 +199,8 @@   -> Int -- ^ Offset   -> WAVECHUNK -- ^ Chunk type   -> Int -- ^ Count-  -> MIteratee (IOB r Word8) m (Maybe WAVEDEENUM)-readValue _dict offset _ 0 = MIteratee . throwErr . iterStrExc $+  -> Iteratee (V.Vector Word8) m (Maybe WAVEDEENUM)+readValue _dict offset _ 0 = throwErr . iterStrExc $   "Zero count in the entry of chunk at: " ++ show offset  readValue dict offset WAVEDATA count = do@@ -210,36 +208,33 @@   case fmt_m of     Just fmt ->       fmt `seq` (return . Just $ WENDUB (\iter_dub -> do-        MIteratee $ Itr.seek (8 + fromIntegral offset)-        offp <- liftIO $ newFp 0-        bufp <- liftIO $ mallocForeignPtrArray defaultChunkLength-        let iter = convStream (convFunc fmt offp bufp) iter_dub-        joinIob . takeUpTo count $ iter)+        I.seek (8 + fromIntegral offset)+        let iter = convStream (convFunc fmt) iter_dub+        joinI . takeUpTo count $ iter)       )-    Nothing ->-      MIteratee . throwErr . iterStrExc $-        "No valid format for data chunk at: " ++ show offset+    Nothing -> throwErr . iterStrExc $+      "No valid format for data chunk at: " ++ show offset  -- return the WaveFormat iteratee readValue _dict offset WAVEFMT count =   return . Just $ WENBYTE $ \iter -> do-    MIteratee $ Itr.seek (8 + fromIntegral offset)-    joinIob $ MI.takeUpTo count iter+    I.seek (8 + fromIntegral offset)+    joinI $ I.takeUpTo count iter  -- for WAVEOTHER, return Word8s and maybe the user can parse them readValue _dict offset (WAVEOTHER _str) count =   return . Just $ WENBYTE $ \iter -> do-    MIteratee $ Itr.seek (8 + fromIntegral offset)-    joinIob $ MI.takeUpTo count iter+    I.seek (8 + fromIntegral offset)+    joinI $ I.takeUpTo count iter  -- |An Iteratee to read a wave format chunk sWaveFormat :: MonadCatchIO m =>-  MIteratee (IOB r Word8) m (Maybe AudioFormat)+  Iteratee (V.Vector Word8) m (Maybe AudioFormat) sWaveFormat = do   f' <- endianRead2 LSB   nc <- endianRead2 LSB   sr <- endianRead4 LSB-  MI.drop 6+  I.drop 6   bd <- endianRead2 LSB   if f' == 1     then return . Just $ AudioFormat (fromIntegral nc)@@ -254,7 +249,7 @@ dictReadFirstFormat ::  (MonadCatchIO m, Functor m) =>   WAVEDict-  -> MIteratee (IOB r Word8) m (Maybe AudioFormat)+  -> Iteratee (V.Vector Word8) m (Maybe AudioFormat) dictReadFirstFormat dict = case IM.lookup (fromEnum WAVEFMT) dict of   Just [] -> return Nothing   Just (WAVEDE _ WAVEFMT (WENBYTE enum) : _xs) -> enum sWaveFormat@@ -265,10 +260,10 @@ dictReadLastFormat ::  (MonadCatchIO m, Functor m) =>   WAVEDict-  -> MIteratee (IOB r Word8) m (Maybe AudioFormat)+  -> Iteratee (V.Vector Word8) m (Maybe AudioFormat) dictReadLastFormat dict = case IM.lookup (fromEnum WAVEFMT) dict of   Just [] -> return Nothing-  Just xs -> let (WAVEDE _ WAVEFMT (WENBYTE enum)) = last xs+  Just xs -> let (WAVEDE _ WAVEFMT (WENBYTE enum)) = P.last xs              in enum sWaveFormat   _ -> return Nothing @@ -277,20 +272,20 @@  (MonadCatchIO m, Functor m) =>   Int -- ^ Index in the format chunk list to read   -> WAVEDict -- ^ Dictionary-  -> MIteratee (IOB r Word8) m (Maybe AudioFormat)+  -> Iteratee (V.Vector Word8) m (Maybe AudioFormat) dictReadFormat ix dict = case IM.lookup (fromEnum WAVEFMT) dict of   Just xs -> let (WAVEDE _ WAVEFMT (WENBYTE enum)) = xs !! ix              in enum sWaveFormat   _ -> return Nothing  -- |Read the specified data chunk from the dictionary, applying the--- data to the specified MIteratee.+-- data to the specified Iteratee. dictProcessData ::  (MonadCatchIO m, Functor m) =>   Int -- ^ Index in the data chunk list to read   -> WAVEDict -- ^ Dictionary-  -> MIteratee (IOB r Double) m a-  -> MIteratee (IOB r Word8) m (MIteratee (IOB r Double) m a)+  -> Iteratee (V.Vector Double) m a+  -> Iteratee (V.Vector Word8) m (Iteratee (V.Vector Double) m a) dictProcessData ix dict iter = case IM.lookup (fromEnum WAVEDATA) dict of   Just xs -> let (WAVEDE _ WAVEDATA (WENDUB enum)) = (!!) xs ix              in (enum iter)@@ -300,11 +295,11 @@  (MonadCatchIO m, Functor m) =>   Int -- ^ Index in the data chunk list to read   -> WAVEDict -- ^ Dictionary-  -> MIteratee (IOB r Double) m a-  -> MIteratee (IOB r Word8) m (Maybe a)+  -> Iteratee (V.Vector Double) m a+  -> Iteratee (V.Vector Word8) m (Maybe a) dictProcessData_ ix dict iter = case IM.lookup (fromEnum WAVEDATA) dict of   Just xs -> let (WAVEDE _ WAVEDATA (WENDUB enum)) = (!!) xs ix-             in fmap Just . joinIob . enum $ iter+             in fmap Just . joinI . enum $ iter   _ -> return Nothing  -- | Get the length of data in a dictionary chunk, in bytes.@@ -332,7 +327,7 @@ dictSoundInfo ::  (MonadCatchIO m, Functor m) =>   WAVEDict-  -> MIteratee (IOB r Word8) m+  -> Iteratee (V.Vector Word8) m       (Maybe (AudioFormat, Integer)) dictSoundInfo dict = do   fmtm <- dictReadFirstFormat dict
src/Sound/Iteratee/Codecs/WaveWriter.hs view
@@ -17,15 +17,13 @@ where  import Sound.Iteratee.Base-import Data.MutableIter-import qualified Data.MutableIter.IOBuffer as IB-import Data.MutableIter.IOBuffer (hPut, mapBuffer)+import Data.Iteratee+import qualified Data.Vector.Storable as V import qualified Data.Iteratee as I import Data.Int.Int24 import qualified Data.ByteString.Lazy as LB import qualified Data.ByteString.Char8 as BC import qualified Data.Binary.Put as P-import Control.Monad import Control.Monad.IO.Class import Control.Monad.Trans.Class import Foreign@@ -53,18 +51,19 @@ writeWave ::   FilePath   -> AudioFormat-  -> MIteratee (IOBuffer r Double) AudioMonad ()+  -> Iteratee (V.Vector Double) AudioMonad () writeWave fp af = do   lift $ openWave fp   lift $ writeFormat af   lift writeDataHeader-  loop+  liftI step   lift closeWave   lift $ put NoState   where-    loop = liftI step-    step (I.Chunk buf) = guardNull buf loop $ lift (writeDataChunk buf) >> loop-    step stream        = idone () stream+    step (I.Chunk buf)+      | V.null buf = liftI step+      | otherwise  = lift (writeDataChunk buf) >> liftI step+    step stream    = idone () stream  -- |Open a wave file for writing openWave :: FilePath -> AudioMonad ()@@ -99,12 +98,12 @@     _                                 -> error "Can't write: not a WAVE file"  -- |Write a data chunk.-writeDataChunk :: IOBuffer r Double -> AudioMonad ()+writeDataChunk :: V.Vector Double -> AudioMonad () writeDataChunk buf = do   as <- get   case as of     WaveState (Just h) (Just af) i i' off -> do-      len <- liftIO . liftM fromIntegral $ getLength af+      let len = fromIntegral $ getLength af       liftIO $ putVec af h buf       put $ WaveState (Just h) (Just af) (i + len) (i' + len) off     WaveState Nothing  _       _ _ _  -> error "Can't write: no file opened"@@ -112,12 +111,13 @@     _                                 -> error "Can't write: not a WAVE file"   where     putVec af h buf' = case bitDepth af of-      8  -> convertVector i8  af buf' >>= hPut h-      16 -> convertVector i16 af buf' >>= hPut h-      24 -> convertVector i24 af buf' >>= hPut h-      32 -> convertVector i32 af buf' >>= hPut h+      8  -> hPut h $ convertVector i8  af buf'+      16 -> hPut h $ convertVector i16 af buf'+      24 -> hPut h $ convertVector i24 af buf'+      32 -> hPut h $ convertVector i32 af buf'       x  -> error $ "Cannot write wave file: unsupported bit depth " ++ show x-    getLength af = liftM (fromIntegral (bitDepth af `div` 8) *) (IB.length buf)+    hPut h v = V.unsafeWith v (\p -> hPutBuf h p (V.length v))+    getLength af = fromIntegral (bitDepth af `div` 8) * V.length buf  i8 :: Int8 i8 = 0@@ -177,13 +177,9 @@   (Integral a, Storable a, Bounded a) =>   a   -> AudioFormat-  -> IOBuffer r Double-  -> IO (IOBuffer r a)-convertVector _ (AudioFormat _nc _sr bd) buf = do-  offp <- newFp 0-  l <- IB.length buf-  obuf <- mallocForeignPtrBytes (l * sizeOf (0::Double))-  mapBuffer (unNormalize bd) offp obuf buf+  -> V.Vector Double+  -> V.Vector a+convertVector _ (AudioFormat _nc _sr bd) = V.map (unNormalize bd)  -- 8 bits are handled separately because (at least in wave) they aren't 2's -- complement negatives.
+ src/Sound/Iteratee/File.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE RankNTypes #-}++module Sound.Iteratee.File (+  getFormat+ ,getAudioInfo+ ,runAudioIteratee+ ,tryRunAudioIteratee+ ,enumAudioIteratee+ ,enumAudioIterateeWithFormat+ ,defaultBufSize+)++where++import           Sound.Iteratee.Base+import           Sound.Iteratee.Codecs+import           Sound.Iteratee.Codecs.Wave ()+import           Sound.Iteratee.Writer+import           Data.Iteratee+import qualified Data.Vector.Storable as V++import           Control.Exception+import           Control.Monad.CatchIO+import           System.FilePath+import           Data.Char++-- | Default buffer size.  The value from Data.Iteratee.IO is generally too+-- small for good performance.+defaultBufSize :: Int+defaultBufSize = 2 ^ (15 :: Int)++-- | get the format from a file name+getFormat :: FilePath -> Maybe SupportedFileFormat+getFormat fp = case ext of+ "wav"  -> Just Wave+ "wave" -> Just Wave+ _      -> Nothing+ where+  ext = map toLower . tail $ takeExtension fp -- drop the initial "."++-- | get audio format information from a file+getAudioInfo :: FilePath -> IO (Maybe AudioFormat)+getAudioInfo fp = case getFormat fp of+  Just Wave -> fileDriverAudio (waveReader >>=+             maybe (return Nothing) dictReadFirstFormat) fp+  Just Raw  -> return Nothing+  _         -> return Nothing -- could try everything and see what matches...+{-# INLINE getAudioInfo #-}++enumAudioIterateeWithFormat ::+  (MonadCatchIO m, Functor m)+  => FilePath+  -> (AudioFormat -> Iteratee (V.Vector Double) m a)+  -> m (Iteratee (V.Vector Double) m a)+enumAudioIterateeWithFormat fp fi = case getFormat fp of+  Just Wave -> run =<< enumAudioFile defaultBufSize fp (waveReader >>= wFn)+  Just Raw  -> return . throwErr $ iterStrExc "Raw format not yet implemented"+  _         -> return . throwErr $ iterStrExc "Raw format not yet implemented"+ where+  wFn = maybe (throwErr $ toException CorruptFileException)+              (\d -> do+                mFmt <- dictReadFirstFormat d+                maybe (throwErr $ toException MissingFormatException)+                      (dictProcessData 0 d . fi) mFmt )+{-# INLINE enumAudioIterateeWithFormat #-}++enumAudioIteratee ::+  (MonadCatchIO m, Functor m)+  => FilePath+  -> Iteratee (V.Vector Double) m a+  -> m (Iteratee (V.Vector Double) m a)+enumAudioIteratee fp i = enumAudioIterateeWithFormat fp (const i)+{-# INLINE enumAudioIteratee #-}++runAudioIteratee ::+  FilePath+  -> Iteratee (V.Vector Double) AudioMonad a+  -> IO a+runAudioIteratee fp i = runAudioMonad $ enumAudioIteratee fp i >>= run+{-# INLINE runAudioIteratee #-}++tryRunAudioIteratee :: Exception e+  => FilePath+  -> Iteratee (V.Vector Double) AudioMonad a+  -> IO (Either e a)+tryRunAudioIteratee fp i = runAudioMonad $ enumAudioIteratee fp i >>= tryRun
src/Sound/Iteratee/Writer.hs view
@@ -5,8 +5,9 @@  module Sound.Iteratee.Writer (   -- * Audio writing functions-  fileDriverAudio,-  runAudioMonad+  fileDriverAudio+  ,runAudioMonad+  ,enumAudioFile )  where@@ -14,9 +15,11 @@ import Sound.Iteratee.Base import Sound.Iteratee.Codecs -import Data.MutableIter--import Foreign.Storable (Storable)+import Data.Iteratee+import Data.Iteratee.IO+import qualified Data.Vector.Storable as V+import Data.Word (Word8)+import Control.Monad.CatchIO  runAudioMonad :: AudioMonad a -> IO a runAudioMonad am = do@@ -25,10 +28,18 @@     NoState     -> return a     WaveState{} -> runWaveAM (put s >> return a) -fileDriverAudio :: (Storable el) =>-  (forall r.  MIteratee (IOBuffer r el) AudioMonad a)+-- | A simplified interface to running an audio iteratee+fileDriverAudio ::+  Iteratee (V.Vector Word8) AudioMonad a   -> FilePath   -> IO a-fileDriverAudio i fp = runAM (fileDriverRandom defaultChunkLength i fp)+fileDriverAudio i fp = runAM (fileDriverRandom i fp)   where     runAM = runAudioMonad++enumAudioFile ::+  MonadCatchIO m+  => Int+  -> FilePath+  -> Enumerator (V.Vector Word8) m a+enumAudioFile = enumFileRandom