hCsound-0.3.0: src/Sound/Csound/Vector.hs
module Sound.Csound.Vector (
-- * Types
BufferWriteStatus (..)
,CsVector
-- *Input/output functions
-- ** Spin/spout
,unsafeVec2Spin
,vec2Spin
,readSpout
-- ** ibuf/obuf
,unsafeVec2Ibuf
,vec2Ibuf
,readObuf
)
where
import Sound.Csound.Interface
import Data.Vector.Storable (Vector)
import qualified Data.Vector.Storable as V
import Control.Monad
import Control.Monad.IO.Class
import Foreign
type CsVector = V.Vector CsndFlt
-- copy data from first buffer to second
cpPtr :: Storable a => Int -> Ptr a -> Ptr a -> IO ()
cpPtr 0 ibuf obuf = return ()
cpPtr n ibuf obuf = do
x <- peek ibuf
poke obuf x
cpPtr (n-1) (ibuf `advancePtr` 1) (obuf `advancePtr` 1)
-- |Result of a buffer write operation
data BufferWriteStatus =
BufOk
| BufferNotFull Int
| DataRemaining CsVector
deriving (Eq, Show)
-- |Writes a vector to the input buffer. This function doesn't check the
-- length of the buffer before writing.
unsafeVec2Ibuf :: CsVector -> Csound ()
unsafeVec2Ibuf vec = do
ibuf <- getInputBuffer
let (vbuf, off, len) = V.unsafeToForeignPtr vec
liftIO . withForeignPtr vbuf $ \ptr -> cpPtr len (ptr `advancePtr` off) ibuf
-- |Writes a vector to the input buffer. Returns any data remaining in the
-- vector.
vec2Ibuf :: CsVector -> Csound BufferWriteStatus
vec2Ibuf vec = do
isz <- getInputBufferSize
let len = V.length vec
case (len == isz, len > isz) of
(True, _) -> do
unsafeVec2Ibuf vec
return BufOk
(False, True) -> do
unsafeVec2Ibuf $ V.unsafeTake isz vec
return . DataRemaining $ V.unsafeDrop isz vec
(False, False) -> do
unsafeVec2Ibuf vec
return . BufferNotFull $ isz - len
-- |Reads from obuf to a vector.
readObuf :: Csound CsVector
readObuf = do
bufsz <- getOutputBufferSize
fptr <- liftIO $ mallocForeignPtrArray bufsz
obuf <- getOutputBuffer
liftIO $ withForeignPtr fptr (cpPtr bufsz obuf)
return $ V.unsafeFromForeignPtr fptr 0 bufsz
-- ----------------------------------
-- Spin/spout
-- |Writes a vector to the spin buffer. Doesn't check the buffer length
-- before writing.
unsafeVec2Spin :: CsVector -> Csound ()
unsafeVec2Spin vec = do
ibuf <- getSpin
let (vbuf, off, len) = V.unsafeToForeignPtr vec
liftIO . withForeignPtr vbuf $ \ptr -> cpPtr len (ptr `advancePtr` off) ibuf
-- |Writes a vector to Spin. Returns any data remaining in the vector.
vec2Spin :: CsVector -> Csound BufferWriteStatus
vec2Spin vec = do
ik <- getKsmps
inch <- getNchnls
let isz = ik * inch
let len = V.length vec
case (len == isz, len > isz) of
(True, _) -> do
unsafeVec2Spin vec
return BufOk
(False, True) -> do
unsafeVec2Spin $ V.unsafeTake isz vec
return . DataRemaining $ V.unsafeDrop isz vec
(False, False) -> do
unsafeVec2Spin vec
return . BufferNotFull $ isz - len
-- |Reads from Spout to a vector.
readSpout :: Csound CsVector
readSpout = do
ik <- getKsmps
inch <- getNchnls
let bufsz = ik * inch
fptr <- liftIO $ mallocForeignPtrArray bufsz
spout <- getSpout
liftIO $ withForeignPtr fptr (cpPtr bufsz spout)
return $ V.unsafeFromForeignPtr fptr 0 bufsz