5 , MultiParamTypeClasses
9 -- | EsounD filtering streams.
10 module Sound.EsounD.Filter
15 import Bindings.EsounD
16 import Control.Exception.Peel
17 import Control.Monad.IO.Class
18 import Control.Monad.IO.Peel
19 import Control.Monad.Trans.Region
20 import Control.Monad.Trans.Region.OnExit
21 import Control.Monad.Unicode
23 import Data.StorableVector as S
24 import Data.StorableVector.Lazy as L
26 import Prelude.Unicode
27 import Sound.EsounD.Streams
28 import Sound.EsounD.Internals
30 import System.IO.SaferFileHandles.Unsafe
33 -- ^ An opaque ESD handle for filtering sound produced by ESD.
35 -- Reading from the stream will give a block of audio frames, which is
36 -- the mixed output from other players and filters. The filter is free
37 -- to process this block as it likes, but must then write an
38 -- identically sized block to the stream. The frames so returned is
39 -- played by the ESD, possibly after applying more filters to it.
40 data Filter fr ch (r ∷ ★ → ★)
44 , fiCloseH ∷ !(FinalizerHandle r)
47 instance Dup (Filter fr ch) where
48 dup fi = do ch' ← dup (fiCloseH fi)
49 return fi { fiCloseH = ch' }
51 instance Stream (Filter fr ch) where
52 streamSampleRate = fiRate
54 instance Frame fr ⇒ ReadableStream (Filter fr Mono) (L.Vector fr) where
59 S.hGet (fiHandle fi) nFrames
61 instance Frame fr ⇒ ReadableStream (Filter fr Stereo) (L.Vector fr, L.Vector fr) where
65 fmap (deinterleave ∘ toLSV) $
66 S.hGet (fiHandle fi) nFrames
68 instance Frame fr ⇒ WritableStream (Filter fr Mono) (L.Vector fr) where
72 do L.hPut (fiHandle fi) v
75 instance Frame fr ⇒ WritableStream (Filter fr Stereo) (L.Vector fr, L.Vector fr) where
79 do L.hPut (fiHandle fi) (interleave l r)
82 -- | Open an ESD handle for filtering sound produced by ESD.
84 -- The new filter will be placed at the head of the list of filters:
85 -- i.e. it will receive data for processing first, and the next filter
86 -- will receive the resultant processed data.
87 openFilter ∷ ∀fr ch s pr.
92 ⇒ Int -- ^ sample rate for the stream.
93 → Maybe HostName -- ^ host to connect to.
94 → Maybe String -- ^ name used to identify this stream to
96 → RegionT s pr (Filter fr ch (RegionT s pr))
97 openFilter rate host name
99 do h ← liftIO openSocket
100 ch ← onExit $ sanitizeIOError $ closeSocket h
108 fmt = frameFmt ((⊥) ∷ fr) .|.
109 channelFmt ((⊥) ∷ ch) .|.
112 openSocket ∷ IO Handle
113 openSocket = withCStrOrNull host $ \hostPtr →
114 withCStrOrNull name $ \namePtr →
121 ( printf "esd_filter_stream(%s, %s, %s, %s) returned an error"