module Sound.PortAudio
(
ErrorCode(..),
HostApiTypeId(..),
SampleFormat(..),
HostApiInfo(..),
HostErrorInfo(..),
DeviceInfo(..),
StreamParameters(..),
StreamInfo(..),
PaFloat32, paFloat32,
PaInt32, paInt32,
PaInt16, paInt16,
PaInt8, paInt8,
PaUInt8, paUInt8,
PaTime,
PaStream,
paNullPtr,
HostApiIndex,
DeviceIndex,
paNoDevice,
paUseHostApiSpecificDeviceSpecification,
getVersion,
getVersionText,
withPortAudio,
initialize,
terminate,
withStream,
withDefaultStream,
openDefaultStream,
openStream,
closeStream,
startStream,
stopStream,
abortStream,
readStream,
writeStream,
getStreamInfo,
getStreamTime,
getStreamCpuLoad,
getStreamReadAvailable,
getStreamWriteAvailable,
getHostApiCount,
getDefaultHostApi,
getHostApiInfo,
getDeviceCount,
getDefaultInputDevice,
getDefaultOutputDevice,
getDeviceInfo,
getSampleSize,
hostApiTypeIdToHostApiIndex,
hostApiDeviceIndexToDeviceIndex,
isFormatSupported,
isStreamStopped,
isStreamActive,
paSleep,
chunk,
standardSampleRates
)
where
import Sound.PortAudio.Base
import Sound.PortAudio.Helpers
import Foreign
import Control.Monad.Error
standardSampleRates :: [Double]
standardSampleRates = [8000,
9600,
11025,
12000,
16000,
22050,
24000,
32000,
44100,
48000,
88200,
96000,
192000]
paSleep :: Int -> IO ()
paSleep = paSleep_ffi
class PortAudioFormat a where
toFmt :: a -> SampleFormat
instance PortAudioFormat PaFloat32 where
toFmt _ = PaFloat32
instance PortAudioFormat PaInt32 where
toFmt _ = PaInt32
instance PortAudioFormat PaInt16 where
toFmt _ = PaInt16
instance PortAudioFormat PaInt8 where
toFmt _ = PaInt8
instance PortAudioFormat PaUInt8 where
toFmt _ = PaUInt8
paFloat32 :: PaFloat32
paFloat32 = undefined
paInt32 :: PaInt32
paInt32 = undefined
paInt16 :: PaInt16
paInt16 = undefined
paInt8 :: PaInt8
paInt8 = undefined
paUInt8 :: PaUInt8
paUInt8 = undefined
initialize :: IO (Either String ErrorCode)
initialize = runErrorT initialize'
initialize' :: ErrorT String IO ErrorCode
initialize' = do code <- liftIO $ initialize_ffi
case (toEnum code) of
NoError -> return NoError
otherErr -> throwError $ show otherErr
terminate :: IO (Either String ErrorCode)
terminate = runErrorT terminate'
terminate' :: ErrorT String IO ErrorCode
terminate' = do code <- liftIO $ terminate_ffi
case (toEnum code) of
NoError -> return NoError
otherErr -> throwError $ show otherErr
withPortAudio :: IO a -> IO (Either String a)
withPortAudio a = runErrorT $ withPortAudio' a
withPortAudio' :: IO a -> ErrorT String IO a
withPortAudio' a = do initCode <- initialize'
actRet <- liftIO a
termCode <- terminate'
return actRet
paNoDevice :: DeviceIndex
paNoDevice = (1)
paUseHostApiSpecificDeviceSpecification :: DeviceIndex
paUseHostApiSpecificDeviceSpecification = (2)
getHostApiCount :: IO (Either String Int)
getHostApiCount = runErrorT getHostApiCount'
getHostApiCount' :: ErrorT String IO Int
getHostApiCount' = do c <- liftIO getHostApiCount_ffi
if (c < 0)
then throwError $ show (toEnum c :: ErrorCode)
else return c
getDefaultHostApi :: IO (Either String Int)
getDefaultHostApi = runErrorT getDefaultHostApi'
getDefaultHostApi' :: ErrorT String IO Int
getDefaultHostApi' = do c <- liftIO getDefaultHostApi_ffi
if (c < 0)
then throwError $ show (toEnum c :: ErrorCode)
else return c
getHostApiInfo :: HostApiIndex -> IO (Maybe HostApiInfo)
getHostApiInfo = getHostApiInfo_ffi
hostApiTypeIdToHostApiIndex :: HostApiTypeId -> IO HostApiIndex
hostApiTypeIdToHostApiIndex = hostApiTypeIdToHostApiIndex_ffi
hostApiDeviceIndexToDeviceIndex :: HostApiIndex -> Int -> IO DeviceIndex
hostApiDeviceIndexToDeviceIndex = hostApiDeviceIndexToDeviceIndex_ffi
getDeviceCount :: IO (Either ErrorCode DeviceIndex)
getDeviceCount = do c <- getDeviceCount_ffi
return $ if (c < 0)
then (Left (toEnum c :: ErrorCode))
else (Right c)
getDefaultInputDevice :: IO (Maybe DeviceIndex)
getDefaultInputDevice = do d <- getDefaultInputDevice_ffi
return $ case d of
(1) -> Nothing
dev -> Just dev
getDefaultOutputDevice :: IO (Maybe DeviceIndex)
getDefaultOutputDevice = do d <- getDefaultOutputDevice_ffi
return $ case d of
(1) -> Nothing
dev -> Just dev
getDeviceInfo :: DeviceIndex -> IO (Maybe DeviceInfo)
getDeviceInfo = getDeviceInfo_ffi
isFormatSupported :: (Maybe StreamParameters)
-> (Maybe StreamParameters)
-> Double
-> IO (Either String Int)
isFormatSupported s1 s2 sr = runErrorT $ isFormatSupported' s1 s2 sr
isFormatSupported' :: (Maybe StreamParameters) -> (Maybe StreamParameters) -> Double -> ErrorT String IO Int
isFormatSupported' s1 s2 sr = do s <- liftIO $ isFormatSupported_ffi s1 s2 sr
if (0 == s)
then return 0
else throwError $ show (toEnum s :: ErrorCode)
openStream :: Maybe StreamParameters
-> Maybe StreamParameters
-> Double
-> Int
-> IO (Either String (PaStream a))
openStream isp osp sr fpb = runErrorT $ openStream' isp osp sr fpb
openStream' :: Maybe StreamParameters
-> Maybe StreamParameters
-> Double
-> Int
-> ErrorT String IO (PaStream a)
openStream' isp osp sr fpb =
do (ec,s) <- liftIO $ openStream_ffi isp osp sr fpb 0 nullPtr nullPtr
let errCode = toEnum ec
case errCode of
NoError -> return s
err -> throwError $ show err
openDefaultStream :: (PortAudioFormat a)
=> Int
-> Int
-> a
-> Double
-> Int
-> IO (Either String (PaStream a))
openDefaultStream nic noc sf sr fpb = runErrorT $ openDefaultStream' nic noc sf sr fpb
openDefaultStream' :: (PortAudioFormat a) => Int -> Int -> a -> Double -> Int
-> ErrorT String IO (PaStream a)
openDefaultStream' nic noc sf sr fpb = do
(ec,s) <- liftIO $ openDefaultStream_ffi nic noc (toFmt sf) sr fpb nullPtr nullPtr
let errCode = toEnum ec
case errCode of
NoError -> return s
err -> throwError $ show err
streamToError :: (PaStream a -> IO Int) -> PaStream a -> ErrorT String IO ErrorCode
streamToError a s = do r <- liftIO $ a s
return (toEnum r)
closeStream :: PaStream a -> IO (Either String ErrorCode)
closeStream s = runErrorT $ closeStream' s
closeStream' :: PaStream a -> ErrorT String IO ErrorCode
closeStream' = streamToError closeStream_ffi
startStream :: PaStream a -> IO (Either String ErrorCode)
startStream s = runErrorT $ startStream' s
startStream' :: PaStream a -> ErrorT String IO ErrorCode
startStream' = streamToError startStream_ffi
stopStream :: PaStream a -> IO (Either String ErrorCode)
stopStream s = runErrorT $ stopStream' s
stopStream' :: PaStream a -> ErrorT String IO ErrorCode
stopStream' = streamToError stopStream_ffi
abortStream :: PaStream a -> IO (Either String ErrorCode)
abortStream s = runErrorT $ abortStream' s
abortStream' :: PaStream a -> ErrorT String IO ErrorCode
abortStream' = streamToError abortStream_ffi
withDefaultStream :: (PortAudioFormat a)
=> Int
-> Int
-> a
-> Double
-> Int
-> (PaStream a -> (Int, Int, Double, Int) -> IO b)
-> IO (Either String b)
withDefaultStream nic noc sf sr fpb a = runErrorT $ withDefaultStream' nic noc sf sr fpb a
withDefaultStream' :: (PortAudioFormat a)
=> Int
-> Int
-> a
-> Double
-> Int
-> (PaStream a -> (Int, Int, Double, Int) -> IO b)
-> ErrorT String IO b
withDefaultStream' nic noc sf sr fpb a = do
ds <- openDefaultStream' nic noc sf sr fpb
start <- startStream' ds
r <- liftIO $ a ds (nic, noc, sr, fpb)
stop <- stopStream' ds
cs <- closeStream' ds
return r
withStream :: (PaStream a -> IO a) -> PaStream a -> IO (Either String a)
withStream f s = runErrorT $ withStream' f s
withStream' :: (PaStream a -> IO a) -> PaStream a -> ErrorT String IO a
withStream' a s = do start <- startStream' s
r <- liftIO $ a s
stop <- stopStream' s
return r
isStreamStopped :: PaStream a -> IO (Either String Bool)
isStreamStopped s = do r <- isStreamStopped_ffi s
return $ case r of
0 -> (Right False)
1 -> (Right True)
e -> fail $ show (toEnum e :: ErrorCode)
isStreamActive :: PaStream a -> IO (Either String Bool)
isStreamActive s = do r <- isStreamActive_ffi s
return $ case r of
0 -> (Right False)
1 -> (Right True)
e -> fail $ show (toEnum e :: ErrorCode)
getStreamInfo :: PaStream a -> IO (Maybe StreamInfo)
getStreamInfo = getStreamInfo_ffi
getStreamTime :: PaStream a -> IO (Maybe PaTime)
getStreamTime s = do r <- getStreamTime_ffi s
return $ case r of
0.0 -> Nothing
t -> (Just t)
getStreamCpuLoad :: PaStream a -> IO Double
getStreamCpuLoad s = getStreamCpuLoad_ffi s
type PaFloat32 = Float
type PaInt32 = Int32
type PaInt24 = Int32
type PaInt16 = Int16
type PaInt8 = Int8
type PaUInt8 = Word8
readStream :: (Storable a)
=> PaStream a
-> Int
-> Int
-> IO (Either String [[a]])
readStream s c f = runErrorT $ readStream' s c f
readStream' :: (Storable a) => PaStream a -> Int -> Int -> ErrorT String IO [[a]]
readStream' str chns frms = do
let len = frms * chns
withPtr act ptr = do err <- act ptr
case (toEnum err) of
NoError -> peekArray len ptr >>= return . Right . chunk chns
err -> return (Left err)
r <- liftIO $ allocaArray len (withPtr (\ptr -> readStream_ffi str (castPtr ptr) len))
case r of
(Left err) -> throwError (show err)
(Right v) -> return v
writeStream :: (Storable a) => PaStream a
-> [[a]]
-> Int
-> IO (Either String ErrorCode)
writeStream s l f = runErrorT $ writeStream' s l f
writeStream' :: (Storable a) => PaStream a -> [[a]] -> Int -> ErrorT String IO ErrorCode
writeStream' str frames numFrames = do
r <- liftIO $ (withArray . concat) frames (\ptr -> writeStream_ffi str (castPtr ptr) (length frames))
return (toEnum r)
getStreamReadAvailable :: PaStream a -> IO (Either String Int)
getStreamReadAvailable s = do r <- getStreamReadAvailable_ffi s
return $ if (r >= 0) then (Right r)
else fail $ show $ (toEnum r :: ErrorCode)
getStreamWriteAvailable :: PaStream a -> IO (Either String Int)
getStreamWriteAvailable s = do r <- getStreamWriteAvailable_ffi s
return $ if (r >= 0) then (Right r)
else fail $ show $ (toEnum r :: ErrorCode)
getSampleSize :: SampleFormat -> IO (Either String Int)
getSampleSize f = do r <- getSampleSize_ffi f
return $ if (r < 0) then fail $ show (toEnum r :: ErrorCode)
else (Right r)