bindings-portaudio 0.2 → 0.2.1
raw patch · 5 files changed
+69/−70 lines, 5 filesdep ~bindings-DSLPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: bindings-DSL
API changes (from Hackage documentation)
- System.PortAudio: instance GHC.Exception.Exception System.PortAudio.Error
+ System.PortAudio: instance GHC.Base.Semigroup System.PortAudio.StreamCallbackResult
+ System.PortAudio: instance GHC.Base.Semigroup System.PortAudio.StreamFlags
+ System.PortAudio: instance GHC.Exception.Type.Exception System.PortAudio.Error
- Bindings.PortAudio: c'paAL :: (Num a) => a
+ Bindings.PortAudio: c'paAL :: Num a => a
- Bindings.PortAudio: c'paALSA :: (Num a) => a
+ Bindings.PortAudio: c'paALSA :: Num a => a
- Bindings.PortAudio: c'paASIO :: (Num a) => a
+ Bindings.PortAudio: c'paASIO :: Num a => a
- Bindings.PortAudio: c'paAbort :: (Num a) => a
+ Bindings.PortAudio: c'paAbort :: Num a => a
- Bindings.PortAudio: c'paAudioScienceHPI :: (Num a) => a
+ Bindings.PortAudio: c'paAudioScienceHPI :: Num a => a
- Bindings.PortAudio: c'paBadBufferPtr :: (Num a) => a
+ Bindings.PortAudio: c'paBadBufferPtr :: Num a => a
- Bindings.PortAudio: c'paBadIODeviceCombination :: (Num a) => a
+ Bindings.PortAudio: c'paBadIODeviceCombination :: Num a => a
- Bindings.PortAudio: c'paBadStreamPtr :: (Num a) => a
+ Bindings.PortAudio: c'paBadStreamPtr :: Num a => a
- Bindings.PortAudio: c'paBeOS :: (Num a) => a
+ Bindings.PortAudio: c'paBeOS :: Num a => a
- Bindings.PortAudio: c'paBufferTooBig :: (Num a) => a
+ Bindings.PortAudio: c'paBufferTooBig :: Num a => a
- Bindings.PortAudio: c'paBufferTooSmall :: (Num a) => a
+ Bindings.PortAudio: c'paBufferTooSmall :: Num a => a
- Bindings.PortAudio: c'paCanNotReadFromACallbackStream :: (Num a) => a
+ Bindings.PortAudio: c'paCanNotReadFromACallbackStream :: Num a => a
- Bindings.PortAudio: c'paCanNotReadFromAnOutputOnlyStream :: (Num a) => a
+ Bindings.PortAudio: c'paCanNotReadFromAnOutputOnlyStream :: Num a => a
- Bindings.PortAudio: c'paCanNotWriteToACallbackStream :: (Num a) => a
+ Bindings.PortAudio: c'paCanNotWriteToACallbackStream :: Num a => a
- Bindings.PortAudio: c'paCanNotWriteToAnInputOnlyStream :: (Num a) => a
+ Bindings.PortAudio: c'paCanNotWriteToAnInputOnlyStream :: Num a => a
- Bindings.PortAudio: c'paComplete :: (Num a) => a
+ Bindings.PortAudio: c'paComplete :: Num a => a
- Bindings.PortAudio: c'paContinue :: (Num a) => a
+ Bindings.PortAudio: c'paContinue :: Num a => a
- Bindings.PortAudio: c'paCoreAudio :: (Num a) => a
+ Bindings.PortAudio: c'paCoreAudio :: Num a => a
- Bindings.PortAudio: c'paDeviceUnavailable :: (Num a) => a
+ Bindings.PortAudio: c'paDeviceUnavailable :: Num a => a
- Bindings.PortAudio: c'paDirectSound :: (Num a) => a
+ Bindings.PortAudio: c'paDirectSound :: Num a => a
- Bindings.PortAudio: c'paHostApiNotFound :: (Num a) => a
+ Bindings.PortAudio: c'paHostApiNotFound :: Num a => a
- Bindings.PortAudio: c'paInDevelopment :: (Num a) => a
+ Bindings.PortAudio: c'paInDevelopment :: Num a => a
- Bindings.PortAudio: c'paIncompatibleHostApiSpecificStreamInfo :: (Num a) => a
+ Bindings.PortAudio: c'paIncompatibleHostApiSpecificStreamInfo :: Num a => a
- Bindings.PortAudio: c'paIncompatibleStreamHostApi :: (Num a) => a
+ Bindings.PortAudio: c'paIncompatibleStreamHostApi :: Num a => a
- Bindings.PortAudio: c'paInputOverflowed :: (Num a) => a
+ Bindings.PortAudio: c'paInputOverflowed :: Num a => a
- Bindings.PortAudio: c'paInsufficientMemory :: (Num a) => a
+ Bindings.PortAudio: c'paInsufficientMemory :: Num a => a
- Bindings.PortAudio: c'paInternalError :: (Num a) => a
+ Bindings.PortAudio: c'paInternalError :: Num a => a
- Bindings.PortAudio: c'paInvalidChannelCount :: (Num a) => a
+ Bindings.PortAudio: c'paInvalidChannelCount :: Num a => a
- Bindings.PortAudio: c'paInvalidDevice :: (Num a) => a
+ Bindings.PortAudio: c'paInvalidDevice :: Num a => a
- Bindings.PortAudio: c'paInvalidFlag :: (Num a) => a
+ Bindings.PortAudio: c'paInvalidFlag :: Num a => a
- Bindings.PortAudio: c'paInvalidHostApi :: (Num a) => a
+ Bindings.PortAudio: c'paInvalidHostApi :: Num a => a
- Bindings.PortAudio: c'paInvalidSampleRate :: (Num a) => a
+ Bindings.PortAudio: c'paInvalidSampleRate :: Num a => a
- Bindings.PortAudio: c'paJACK :: (Num a) => a
+ Bindings.PortAudio: c'paJACK :: Num a => a
- Bindings.PortAudio: c'paMME :: (Num a) => a
+ Bindings.PortAudio: c'paMME :: Num a => a
- Bindings.PortAudio: c'paNoError :: (Num a) => a
+ Bindings.PortAudio: c'paNoError :: Num a => a
- Bindings.PortAudio: c'paNotInitialized :: (Num a) => a
+ Bindings.PortAudio: c'paNotInitialized :: Num a => a
- Bindings.PortAudio: c'paNullCallback :: (Num a) => a
+ Bindings.PortAudio: c'paNullCallback :: Num a => a
- Bindings.PortAudio: c'paOSS :: (Num a) => a
+ Bindings.PortAudio: c'paOSS :: Num a => a
- Bindings.PortAudio: c'paOutputUnderflowed :: (Num a) => a
+ Bindings.PortAudio: c'paOutputUnderflowed :: Num a => a
- Bindings.PortAudio: c'paSampleFormatNotSupported :: (Num a) => a
+ Bindings.PortAudio: c'paSampleFormatNotSupported :: Num a => a
- Bindings.PortAudio: c'paSoundManager :: (Num a) => a
+ Bindings.PortAudio: c'paSoundManager :: Num a => a
- Bindings.PortAudio: c'paStreamIsNotStopped :: (Num a) => a
+ Bindings.PortAudio: c'paStreamIsNotStopped :: Num a => a
- Bindings.PortAudio: c'paStreamIsStopped :: (Num a) => a
+ Bindings.PortAudio: c'paStreamIsStopped :: Num a => a
- Bindings.PortAudio: c'paTimedOut :: (Num a) => a
+ Bindings.PortAudio: c'paTimedOut :: Num a => a
- Bindings.PortAudio: c'paUnanticipatedHostError :: (Num a) => a
+ Bindings.PortAudio: c'paUnanticipatedHostError :: Num a => a
- Bindings.PortAudio: c'paWASAPI :: (Num a) => a
+ Bindings.PortAudio: c'paWASAPI :: Num a => a
- Bindings.PortAudio: c'paWDMKS :: (Num a) => a
+ Bindings.PortAudio: c'paWDMKS :: Num a => a
- Bindings.PortAudio: mK'PaStreamCallback :: C'PaStreamCallback -> (Ptr () -> Ptr () -> CULong -> Ptr C'PaStreamCallbackTimeInfo -> C'PaStreamCallbackFlags -> Ptr () -> IO C'PaStreamCallbackResult)
+ Bindings.PortAudio: mK'PaStreamCallback :: C'PaStreamCallback -> Ptr () -> Ptr () -> CULong -> Ptr C'PaStreamCallbackTimeInfo -> C'PaStreamCallbackFlags -> Ptr () -> IO C'PaStreamCallbackResult
- Bindings.PortAudio: mK'PaStreamFinishedCallback :: C'PaStreamFinishedCallback -> (Ptr () -> IO ())
+ Bindings.PortAudio: mK'PaStreamFinishedCallback :: C'PaStreamFinishedCallback -> Ptr () -> IO ()
- Bindings.PortAudio: p'PaDeviceInfo'defaultHighInputLatency :: Ptr (C'PaDeviceInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaDeviceInfo'defaultHighInputLatency :: Ptr C'PaDeviceInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaDeviceInfo'defaultHighOutputLatency :: Ptr (C'PaDeviceInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaDeviceInfo'defaultHighOutputLatency :: Ptr C'PaDeviceInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaDeviceInfo'defaultLowInputLatency :: Ptr (C'PaDeviceInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaDeviceInfo'defaultLowInputLatency :: Ptr C'PaDeviceInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaDeviceInfo'defaultLowOutputLatency :: Ptr (C'PaDeviceInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaDeviceInfo'defaultLowOutputLatency :: Ptr C'PaDeviceInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaDeviceInfo'defaultSampleRate :: Ptr (C'PaDeviceInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaDeviceInfo'defaultSampleRate :: Ptr C'PaDeviceInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaDeviceInfo'hostApi :: Ptr (C'PaDeviceInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaDeviceInfo'hostApi :: Ptr C'PaDeviceInfo -> Ptr CInt
- Bindings.PortAudio: p'PaDeviceInfo'maxInputChannels :: Ptr (C'PaDeviceInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaDeviceInfo'maxInputChannels :: Ptr C'PaDeviceInfo -> Ptr CInt
- Bindings.PortAudio: p'PaDeviceInfo'maxOutputChannels :: Ptr (C'PaDeviceInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaDeviceInfo'maxOutputChannels :: Ptr C'PaDeviceInfo -> Ptr CInt
- Bindings.PortAudio: p'PaDeviceInfo'name :: Ptr (C'PaDeviceInfo) -> Ptr (CString)
+ Bindings.PortAudio: p'PaDeviceInfo'name :: Ptr C'PaDeviceInfo -> Ptr CString
- Bindings.PortAudio: p'PaDeviceInfo'structVersion :: Ptr (C'PaDeviceInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaDeviceInfo'structVersion :: Ptr C'PaDeviceInfo -> Ptr CInt
- Bindings.PortAudio: p'PaHostApiInfo'defaultInputDevice :: Ptr (C'PaHostApiInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaHostApiInfo'defaultInputDevice :: Ptr C'PaHostApiInfo -> Ptr CInt
- Bindings.PortAudio: p'PaHostApiInfo'defaultOutputDevice :: Ptr (C'PaHostApiInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaHostApiInfo'defaultOutputDevice :: Ptr C'PaHostApiInfo -> Ptr CInt
- Bindings.PortAudio: p'PaHostApiInfo'deviceCount :: Ptr (C'PaHostApiInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaHostApiInfo'deviceCount :: Ptr C'PaHostApiInfo -> Ptr CInt
- Bindings.PortAudio: p'PaHostApiInfo'name :: Ptr (C'PaHostApiInfo) -> Ptr (CString)
+ Bindings.PortAudio: p'PaHostApiInfo'name :: Ptr C'PaHostApiInfo -> Ptr CString
- Bindings.PortAudio: p'PaHostApiInfo'structVersion :: Ptr (C'PaHostApiInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaHostApiInfo'structVersion :: Ptr C'PaHostApiInfo -> Ptr CInt
- Bindings.PortAudio: p'PaHostApiInfo'type :: Ptr (C'PaHostApiInfo) -> Ptr (C'PaHostApiTypeId)
+ Bindings.PortAudio: p'PaHostApiInfo'type :: Ptr C'PaHostApiInfo -> Ptr C'PaHostApiTypeId
- Bindings.PortAudio: p'PaHostErrorInfo'errorCode :: Ptr (C'PaHostErrorInfo) -> Ptr (CLong)
+ Bindings.PortAudio: p'PaHostErrorInfo'errorCode :: Ptr C'PaHostErrorInfo -> Ptr CLong
- Bindings.PortAudio: p'PaHostErrorInfo'errorText :: Ptr (C'PaHostErrorInfo) -> Ptr (CString)
+ Bindings.PortAudio: p'PaHostErrorInfo'errorText :: Ptr C'PaHostErrorInfo -> Ptr CString
- Bindings.PortAudio: p'PaHostErrorInfo'hostApiType :: Ptr (C'PaHostErrorInfo) -> Ptr (C'PaHostApiTypeId)
+ Bindings.PortAudio: p'PaHostErrorInfo'hostApiType :: Ptr C'PaHostErrorInfo -> Ptr C'PaHostApiTypeId
- Bindings.PortAudio: p'PaStreamCallbackTimeInfo'currentTime :: Ptr (C'PaStreamCallbackTimeInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamCallbackTimeInfo'currentTime :: Ptr C'PaStreamCallbackTimeInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaStreamCallbackTimeInfo'inputBufferAdcTime :: Ptr (C'PaStreamCallbackTimeInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamCallbackTimeInfo'inputBufferAdcTime :: Ptr C'PaStreamCallbackTimeInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaStreamCallbackTimeInfo'outputBufferDacTime :: Ptr (C'PaStreamCallbackTimeInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamCallbackTimeInfo'outputBufferDacTime :: Ptr C'PaStreamCallbackTimeInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaStreamInfo'inputLatency :: Ptr (C'PaStreamInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamInfo'inputLatency :: Ptr C'PaStreamInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaStreamInfo'outputLatency :: Ptr (C'PaStreamInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamInfo'outputLatency :: Ptr C'PaStreamInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaStreamInfo'sampleRate :: Ptr (C'PaStreamInfo) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamInfo'sampleRate :: Ptr C'PaStreamInfo -> Ptr CDouble
- Bindings.PortAudio: p'PaStreamInfo'structVersion :: Ptr (C'PaStreamInfo) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaStreamInfo'structVersion :: Ptr C'PaStreamInfo -> Ptr CInt
- Bindings.PortAudio: p'PaStreamParameters'channelCount :: Ptr (C'PaStreamParameters) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaStreamParameters'channelCount :: Ptr C'PaStreamParameters -> Ptr CInt
- Bindings.PortAudio: p'PaStreamParameters'device :: Ptr (C'PaStreamParameters) -> Ptr (CInt)
+ Bindings.PortAudio: p'PaStreamParameters'device :: Ptr C'PaStreamParameters -> Ptr CInt
- Bindings.PortAudio: p'PaStreamParameters'hostApiSpecificStreamInfo :: Ptr (C'PaStreamParameters) -> Ptr (Ptr ())
+ Bindings.PortAudio: p'PaStreamParameters'hostApiSpecificStreamInfo :: Ptr C'PaStreamParameters -> Ptr (Ptr ())
- Bindings.PortAudio: p'PaStreamParameters'sampleFormat :: Ptr (C'PaStreamParameters) -> Ptr (CULong)
+ Bindings.PortAudio: p'PaStreamParameters'sampleFormat :: Ptr C'PaStreamParameters -> Ptr CULong
- Bindings.PortAudio: p'PaStreamParameters'suggestedLatency :: Ptr (C'PaStreamParameters) -> Ptr (CDouble)
+ Bindings.PortAudio: p'PaStreamParameters'suggestedLatency :: Ptr C'PaStreamParameters -> Ptr CDouble
Files
- CHANGELOG.md +0/−0
- System/PortAudio.hs +17/−14
- bindings-portaudio.cabal +5/−4
- example/example-portaudio.cabal +1/−1
- example/sine.hs +46/−51
+ CHANGELOG.md view
System/PortAudio.hs view
@@ -152,9 +152,11 @@ newtype StreamFlags = StreamFlags CULong +instance Semigroup StreamFlags where+ StreamFlags a <> StreamFlags b = StreamFlags (a .|. b)+ instance Monoid StreamFlags where mempty = StreamFlags 0- StreamFlags a `mappend` StreamFlags b = StreamFlags (a .|. b) clipOff :: StreamFlags clipOff = StreamFlags 0x00000001@@ -168,23 +170,25 @@ primeOutputBuffersUsingStreamCallback :: StreamFlags primeOutputBuffersUsingStreamCallback = StreamFlags 0x00000008 -w :: IO CInt -> IO ()-w n = do+wrap :: IO CInt -> IO ()+wrap n = do r <- n unless (r == 0) $ throwIO $ fromErrorCode r withPortAudio :: IO a -> IO a-withPortAudio = bracket_ (w c'Pa_Initialize) (w c'Pa_Terminate)+withPortAudio = bracket_ (wrap c'Pa_Initialize) (wrap c'Pa_Terminate) data StreamCallbackResult = Continue | Complete | Abort deriving (Show, Eq, Ord, Enum) +instance Semigroup StreamCallbackResult where+ Complete <> x = x+ x <> Complete = x+ Abort <> _ = Abort+ _ <> Abort = Abort+ Continue <> Continue = Continue+ instance Monoid StreamCallbackResult where mempty = Complete- mappend Complete x = x- mappend x Complete = x- mappend Abort _ = Abort- mappend _ Abort = Abort- mappend Continue Continue = Continue data Status = Status { currentTime :: !Double@@ -208,9 +212,8 @@ withStream rate buf paramI paramO (StreamFlags flags) f m = withMaybe paramI $ \pin -> withMaybe paramO $ \pout -> do cb <- mk'PaStreamCallback $ callback f- let opener = do- ps <- malloc- w $ c'Pa_OpenStream ps+ let opener ps = do+ wrap $ c'Pa_OpenStream ps (castPtr pin) (castPtr pout) (CDouble rate)@@ -219,8 +222,8 @@ cb nullPtr peek ps- bracket opener (\s -> w (c'Pa_CloseStream s) >> free s)- $ \s -> bracket_ (w $ c'Pa_StartStream s) (w $ c'Pa_StopStream s) m+ alloca $ \ps -> bracket (opener ps) (wrap . c'Pa_CloseStream)+ $ \s -> bracket_ (wrap $ c'Pa_StartStream s) (wrap $ c'Pa_StopStream s) m data Closed = Closed
bindings-portaudio.cabal view
@@ -1,16 +1,16 @@+cabal-version: 2.4 name: bindings-portaudio-version: 0.2+version: 0.2.1 category: Sound author: Fumiaki Kinoshita <fumiexcel@gmail.com> maintainer: Fumiaki Kinoshita <fumiexcel@gmail.com> -license: BSD3+license: BSD-3-Clause license-file: LICENSE synopsis: Low-level bindings to portaudio library description:-cabal-version: >= 1.10 build-type: Simple extra-source-files:@@ -26,6 +26,7 @@ extra.c LICENSE README.md+ CHANGELOG.md example/*.hs example/example-portaudio.cabal example/LICENSE@@ -63,7 +64,7 @@ hsc2hs build-depends:- base < 5, bindings-DSL == 1.0.*, vector+ base < 5, bindings-DSL ^>= 1.0, vector cc-options: -g
example/example-portaudio.cabal view
@@ -21,7 +21,7 @@ -- other-extensions: build-depends: base >=4.6 && < 5 , bindings-portaudio- , vector >= 0.10 && < 0.12+ , vector >= 0.10 && < 0.13 , linear -- hs-source-dirs: ghc-options: -threaded -Wall -O2
example/sine.hs view
@@ -1,51 +1,46 @@-{-# LANGUAGE ViewPatterns, LambdaCase #-} -import System.PortAudio -import Control.Applicative -import Control.Concurrent -import Control.Monad -import Foreign.C.String -import Foreign.C.Types -import Foreign hiding (void) -import Linear (V2(..)) -import qualified Data.Vector as V -import qualified Data.Vector.Storable.Mutable as MV -import System.Environment -import System.Exit - -period :: Int -period = 128 - -table :: V.Vector Float -table = V.fromList [sin t | i <- [0..period - 1], let t = fromIntegral i / fromIntegral period * 2 * pi] - -callback :: MVar Int -> Status -> input -> MV.IOVector (V2 Float) -> IO StreamCallbackResult -callback phase _ _ o = do - i0 <- takeMVar phase - go i0 0 - putMVar phase $ i0 + n - return Continue - where - n = MV.length o - go :: Int -> Int -> IO () - go i0 i - | i == n = return () - | otherwise = do - let v = table V.! ((i0 + i) `mod` period) - MV.write o i (V2 v v) - go i0 (i + 1) - -main :: IO () -main = getArgs >>= \case - ((read -> rate) : (read -> buf) : _) -> withPortAudio $ do - (_, dev : _) <- getDevices - phase <- newMVar 0 - let output = streamParameters dev 0 - withStream rate buf noConnection output mempty (callback phase) - $ threadDelay $ 1000 * 1000 - _ -> usageExit - -usageExit :: IO () -usageExit = do - pname <- getProgName - putStrLn $ "\nUsage: " ++ pname ++ " <sample rate> <buffer size>\n" - exitSuccess +{-# LANGUAGE ViewPatterns, LambdaCase #-}+import System.PortAudio+import Control.Concurrent+import Linear (V2(..))+import qualified Data.Vector as V+import qualified Data.Vector.Storable.Mutable as MV+import System.Environment+import System.Exit++period :: Int+period = 128++table :: V.Vector Float+table = V.fromList [sin t | i <- [0..period - 1], let t = fromIntegral i / fromIntegral period * 2 * pi]++callback :: MVar Int -> Status -> input -> MV.IOVector (V2 Float) -> IO StreamCallbackResult+callback phase _ _ o = do+ i0 <- takeMVar phase+ go i0 0+ putMVar phase $ i0 + n+ return Continue+ where+ n = MV.length o+ go :: Int -> Int -> IO ()+ go i0 i+ | i == n = return ()+ | otherwise = do+ let v = table V.! ((i0 + i) `mod` period)+ MV.write o i (V2 v v)+ go i0 (i + 1)++main :: IO ()+main = getArgs >>= \case+ ((read -> rate) : (read -> buf) : _) -> withPortAudio $ do+ (_, dev : _) <- getDevices+ phase <- newMVar 0+ let output = streamParameters dev 0+ withStream rate buf noConnection output mempty (callback phase)+ $ threadDelay $ 1000 * 1000+ _ -> usageExit++usageExit :: IO ()+usageExit = do+ pname <- getProgName+ putStrLn $ "\nUsage: " ++ pname ++ " <sample rate> <buffer size>\n"+ exitSuccess