module Sound.Iteratee.Base (
AudioStreamState (..),
WritableAudio (..),
AudioMonad,
module Control.Monad.Trans.State,
defaultChunkLength,
AudioFormat (..),
SupportedBitDepths (..),
NumChannels,
SampleRate,
BitDepth,
FrameCount,
SupportedFileFormat (..),
UnknownFileTypeException (..),
CorruptFileException (..),
MissingFormatException (..),
getChannel
)
where
import Prelude as P
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
data AudioStreamState =
WaveState !(Maybe Handle) !(Maybe AudioFormat) !Integer !Integer !Integer
| NoState
deriving (Eq, Show)
data SupportedFileFormat = Raw
| Wave
deriving (Show, Enum, Bounded, Eq, Data, Typeable)
class WritableAudio a where
emptyState :: a -> AudioStreamState
initState :: a -> Handle -> AudioStreamState
supportedBitDepths :: a -> SupportedBitDepths
fileType :: a -> SupportedFileFormat
type AudioMonad = StateT AudioStreamState IO
data AudioFormat = AudioFormat {
numberOfChannels :: NumChannels,
sampleRate :: SampleRate,
bitDepth :: BitDepth
} deriving (Show, Eq, Data, Typeable)
type NumChannels = Integer
type SampleRate = Integer
type BitDepth = Integer
type FrameCount = Integer
data SupportedBitDepths = Any | Supported [BitDepth]
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
getChannel ::
Monad m
=> Int
-> Int
-> 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)
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