diff --git a/benchmark/Main.hs b/benchmark/Main.hs
new file mode 100644
--- /dev/null
+++ b/benchmark/Main.hs
@@ -0,0 +1,14 @@
+module Main where
+
+import Gauge
+import Gauge.Main (defaultMain)
+
+import Csound.Base
+
+main :: IO ()
+main =
+  defaultMain
+    [ bgroup "drone tests" $ zipWith forDrone [1..] [testDrone, testDrone2, testDrone3]
+    ]
+  where
+    forDrone n fun = bench ("drone: " <> show n) $ nfAppIO (renderCsd . fun) 100
diff --git a/csound-expression.cabal b/csound-expression.cabal
--- a/csound-expression.cabal
+++ b/csound-expression.cabal
@@ -1,6 +1,6 @@
 Name:          csound-expression
-Version:       5.4.3
-cabal-version: >= 1.22
+Version:       5.4.3.1
+cabal-version: 1.12
 License:       BSD3
 License-file:  LICENSE
 Author:	       Anton Kholomiov
@@ -78,18 +78,24 @@
 Library
   Ghc-Options:    -Wall
   Build-Depends:
-        base >= 4.6, base < 5,
+        base >= 4.10, base < 5,
         process,
         data-default,
+        directory,
         Boolean >= 0.1.0,
         colour >= 2.0,
+        filepath,
         transformers >= 0.3,
         containers,
         csound-expression-typed >= 0.2.7,
-        csound-expression-dynamic >= 0.3.8,
+        csound-expression-dynamic >= 0.3.9.1,
         temporal-media >= 0.6.3,
-        csound-expression-opcodes >= 0.0.5.1
+        csound-expression-opcodes >= 0.0.5.1,
+        text
   default-language: Haskell2010
+  default-extensions:
+    ImportQualifiedPost
+    OverloadedStrings
   Hs-Source-Dirs:      src/
   Exposed-Modules:
         Csound.Base
@@ -150,3 +156,15 @@
         Csound.Control.Overload.Outs
         Csound.Control.Overload.MidiInstr
         Csound.Control.Overload.SpecInstr
+
+
+
+benchmark csound-expression-benchmark
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      benchmark
+  main-is:             Main.hs
+  build-depends:       base
+                     , csound-expression
+                     , gauge
+  default-language:    Haskell2010
+
diff --git a/src/Csound/Air/Envelope.hs b/src/Csound/Air/Envelope.hs
--- a/src/Csound/Air/Envelope.hs
+++ b/src/Csound/Air/Envelope.hs
@@ -40,6 +40,7 @@
 
 import Control.Monad
 import Control.Applicative
+import Data.Kind(Type)
 import Data.List(intersperse)
 
 import Temporal.Media hiding (rest)
@@ -793,7 +794,7 @@
 --
 -- As you can see it transforms the whole function. So we don't need for extra parenthesis.
 class HumanizeValue a where
-    type HumanizeValueOut a :: *
+    type HumanizeValueOut a :: Type
     humanVal :: Sig -> a -> HumanizeValueOut a
 
 rndVal :: Sig -> Sig -> Sig -> SE Sig
@@ -843,7 +844,7 @@
 --
 -- As you can see it transforms the whole function. So we don't need for extra parenthesis.
 class HumanizeTime a where
-    type HumanizeTimeOut a :: *
+    type HumanizeTimeOut a :: Type
     humanTime :: Sig -> a -> HumanizeTimeOut a
 
 instance HumanizeTime ([Seq] -> Sig -> Sig) where
@@ -882,7 +883,7 @@
 --
 -- As you can see it transforms the whole function. So we don't need for extra parenthesis.
 class HumanizeValueTime a where
-    type HumanizeValueTimeOut a :: *
+    type HumanizeValueTimeOut a :: Type
     humanValTime :: Sig -> Sig -> a -> HumanizeValueTimeOut a
 
 instance HumanizeValueTime ([Seq] -> Sig -> Sig) where
diff --git a/src/Csound/Air/Fx/FxBox.hs b/src/Csound/Air/Fx/FxBox.hs
--- a/src/Csound/Air/Fx/FxBox.hs
+++ b/src/Csound/Air/Fx/FxBox.hs
@@ -194,6 +194,7 @@
 ) where
 
 import Data.Default
+import Data.Text (Text)
 
 import Csound.Typed
 import Csound.Typed.Opcode(scale, expcurve)
@@ -707,7 +708,7 @@
 ----------------------------------------------------------
 -- UI
 
-setAll :: Double -> [String] -> [(String, Double)]
+setAll :: Double -> [Text] -> [(Text, Double)]
 setAll size names = fmap (\s -> (s, size)) names
 
 
diff --git a/src/Csound/Air/Live.hs b/src/Csound/Air/Live.hs
--- a/src/Csound/Air/Live.hs
+++ b/src/Csound/Air/Live.hs
@@ -37,6 +37,8 @@
 
 import Data.Bool
 import Data.Boolean
+import Data.Text (Text)
+import Data.Text qualified as Text
 import Data.Default
 import qualified Data.Colour.Names as C
 import qualified Data.Colour.SRGB as C
@@ -58,14 +60,14 @@
 -- mixer
 
 -- | Widget that represents a mixer.
-mixer :: (Sigs a) => [(String, SE a)] -> Source a
+mixer :: (Sigs a) => [(Text, SE a)] -> Source a
 mixer = genMixer (ver, hor)
 
 -- | Widget that represents a mixer with horizontal grouping of elements.
-hmixer :: (Sigs a) => [(String, SE a)] -> Source a
+hmixer :: (Sigs a) => [(Text, SE a)] -> Source a
 hmixer = genMixer (hor, ver)
 
-genMixer :: (Sigs a) => ([Gui] -> Gui, [Gui] -> Gui) -> [(String, SE a)] -> Source a
+genMixer :: (Sigs a) => ([Gui] -> Gui, [Gui] -> Gui) -> [(Text, SE a)] -> Source a
 genMixer (parentGui, childGui) as = source $ do
     gTags <- mapM box names
     (gs, vols) <- fmap unzip $ mapM (const $ defSlider "") names
@@ -86,10 +88,10 @@
 
 -- | Transforms the mono signal to the stereo input
 -- for the mixer widget.
-mixMono :: String -> Sig -> (String, SE Sig2)
+mixMono :: Text -> Sig -> (Text, SE Sig2)
 mixMono name asig = (name, return (asig, asig))
 
-defSlider :: String -> Source Sig
+defSlider :: Text -> Source Sig
 defSlider tag = slider tag (linSpan 0 1) 0.5
 
 ----------------------------------------------------------------------
@@ -119,8 +121,8 @@
 --
 -- It's cool to set the color of the widget with @fxColor@ function.
 -- we can make our widgets much more intersting to look at.
--- fxBox :: forall a. (FxUI a, Num  (FxArg a), Tuple (FxArg a)) => String -> a -> Bool -> [(String, Double)] -> Source (Fx (FxArg a))
-fxBox :: forall a. Sigs a => String -> ([Sig] -> Fx a) -> Bool -> [(String, Double)] -> Source (Fx a)
+-- fxBox :: forall a. (FxUI a, Num  (FxArg a), Tuple (FxArg a)) => Text -> a -> Bool -> [(Text, Double)] -> Source (Fx (FxArg a))
+fxBox :: forall a. Sigs a => Text -> ([Sig] -> Fx a) -> Bool -> [(Text, Double)] -> Source (Fx a)
 fxBox name fx onOff args = source $ do
     (gOff0, off) <- toggleSig name onOff
     let gOff = setFontSize 25 gOff0
@@ -148,7 +150,7 @@
 
 -- | Creates an FX-box from the given visual representation.
 -- It inserts a big On/Off button atop of the GUI.
-uiBox :: (Sigs a) => String -> Source (Fx a) -> Bool -> Source (Fx a)
+uiBox :: (Sigs a) => Text -> Source (Fx a) -> Bool -> Source (Fx a)
 uiBox name fx' onOff =
   mapGuiSource (setBorder UpBoxBorder) $ vlift2' uiOnOffSize uiBoxSize go offs fx'
     where
@@ -346,23 +348,23 @@
     [("freq", freq), ("depth", depth)]
 
 -- | The constructor for signal processing functions with no arguments (controlls).
-uiFx :: Sigs a => String -> Fx a -> Bool -> Source (Fx a)
+uiFx :: Sigs a => Text -> Fx a -> Bool -> Source (Fx a)
 uiFx name f isOn = fxBox name (\[] -> f) isOn []
 
 -- | Midi chooser implemented as FX-box.
-uiMidi :: (Sigs a) => [(String, Msg -> SE a)] -> Int -> Source (Fx a)
+uiMidi :: (Sigs a) => [(Text, Msg -> SE a)] -> Int -> Source (Fx a)
 uiMidi xs initVal = sourceColor2 C.forestgreen $ uiBox "Midi" fx True
     where fx = lift1 (\aout arg -> return $ aout + arg) $ vmidiChooser xs initVal
 
 {-
 -- | Patch chooser implemented as FX-box.
-uiPatch :: [(String, Patch2)] -> Int -> Source FxFun
+uiPatch :: [(Text, Patch2)] -> Int -> Source FxFun
 uiPatch xs initVal = sourceColor2 C.forestgreen $ uiBox "Patch" fx True
     where fx = lift1 (\aout arg -> return $ aout + arg) $ vpatchChooser xs initVal
 -}
 
 -- | the widget for mixing in a signal to the signal.
-uiSig :: (Sigs a) => String -> Bool -> Source a -> Source (Fx a)
+uiSig :: (Sigs a) => Text -> Bool -> Source a -> Source (Fx a)
 uiSig name onOff widget = source $ do
     (gs, asig) <- widget
     (gOff0, off) <- toggleSig name onOff
@@ -372,7 +374,7 @@
 
 -- | A mixer widget represented as an effect.
 -- The effect sums the signals with given wieghts.
-uiMix :: (Sigs a) => Bool -> [(String, SE a)] -> Source (Fx a)
+uiMix :: (Sigs a) => Bool -> [(Text, SE a)] -> Source (Fx a)
 uiMix onOff as = sourceColor2 C.blue $ uiSig "Mix" onOff (mixer as)
 
 ----------------------------------------------------------------------
@@ -392,14 +394,14 @@
 expEps :: Fractional a => a
 expEps = 0.00001
 
-linAdsr :: String -> AdsrBound -> AdsrInit -> Source Sig
+linAdsr :: Text -> AdsrBound -> AdsrInit -> Source Sig
 linAdsr = genAdsr $ \a d s r -> linsegr [0, a, 1, d, s] r 0
 
-expAdsr :: String -> AdsrBound -> AdsrInit -> Source Sig
+expAdsr :: Text -> AdsrBound -> AdsrInit -> Source Sig
 expAdsr = genAdsr $ \a d s r -> expsegr [double expEps, a, 1, d, s] r (double expEps)
 
 genAdsr :: (D -> D -> D -> D -> Sig)
-    -> String -> AdsrBound -> AdsrInit -> Source Sig
+    -> Text -> AdsrBound -> AdsrInit -> Source Sig
 genAdsr mkAdsr name b inits = source $ do
     (gatt, att) <- knob "A" (linSpan expEps $ attBound b) (attInit inits)
     (gdec, dec) <- knob "D" (linSpan expEps $ decBound b) (decInit inits)
@@ -411,7 +413,7 @@
 
 -- | A widget with four standard waveforms: pure tone, triangle, square and sawtooth.
 -- The last parameter is a default waveform (it's set at init time).
-classicWaves :: String -> Int -> Source (Sig -> Sig)
+classicWaves :: Text -> Int -> Source (Sig -> Sig)
 classicWaves name initVal = funnyRadio name
     [ ("osc", osc)
     , ("tri", tri)
@@ -435,22 +437,22 @@
 genMidiChooser chooser xs initVal = joinSource $ lift1 midi $ chooser xs initVal
 
 -- | Chooses a midi instrument among several alternatives. It uses the @hradio@ for GUI groupping.
-hmidiChooser :: Sigs a => [(String, Msg -> SE a)] -> Int -> Source a
+hmidiChooser :: Sigs a => [(Text, Msg -> SE a)] -> Int -> Source a
 hmidiChooser = genMidiChooser hinstrChooser
 
 -- | Chooses a midi instrument among several alternatives. It uses the @vradio@ for GUI groupping.
-vmidiChooser :: Sigs a => [(String, Msg -> SE a)] -> Int -> Source a
+vmidiChooser :: Sigs a => [(Text, Msg -> SE a)] -> Int -> Source a
 vmidiChooser = genMidiChooser vinstrChooser
 
 -- | Chooses an instrument among several alternatives. It uses the @hradio@ for GUI groupping.
-hinstrChooser :: (Sigs b) => [(String, a -> SE b)] -> Int -> Source (a -> SE b)
+hinstrChooser :: (Sigs b) => [(Text, a -> SE b)] -> Int -> Source (a -> SE b)
 hinstrChooser = genInstrChooser hradioSig
 
 -- | Chooses an instrument among several alternatives. It uses the @vradio@ for GUI groupping.
-vinstrChooser :: (Sigs b) => [(String, a -> SE b)] -> Int -> Source (a -> SE b)
+vinstrChooser :: (Sigs b) => [(Text, a -> SE b)] -> Int -> Source (a -> SE b)
 vinstrChooser = genInstrChooser vradioSig
 
-genInstrChooser :: (Sigs b) => ([String] -> Int -> Source Sig) -> [(String, a -> SE b)] -> Int -> Source (a -> SE b)
+genInstrChooser :: (Sigs b) => ([Text] -> Int -> Source Sig) -> [(Text, a -> SE b)] -> Int -> Source (a -> SE b)
 genInstrChooser widget xs initVal = lift1 (routeInstr instrs) $ widget names initVal
     where (names, instrs) = unzip xs
         -- go instrId arg = fmap sum $ mapM ( $ arg) $ zipWith (\n instr -> playWhen (sig (int n) ==* instrId) instr) [0 ..] instrs
@@ -462,13 +464,13 @@
 ----------------------------------------------------
 -- effect choosers
 
-hpatchChooser :: (SigSpace a, Sigs a) => [(String, Patch D a)] -> Int -> Source a
+hpatchChooser :: (SigSpace a, Sigs a) => [(Text, Patch D a)] -> Int -> Source a
 hpatchChooser = genPatchChooser hradioSig
 
-vpatchChooser :: (SigSpace a, Sigs a) => [(String, Patch D a)] -> Int -> Source a
+vpatchChooser :: (SigSpace a, Sigs a) => [(Text, Patch D a)] -> Int -> Source a
 vpatchChooser = genPatchChooser vradioSig
 
-genPatchChooser :: (SigSpace a, Sigs a) => ([String] -> Int -> Source Sig) -> [(String, Patch D a)] -> Int -> Source a
+genPatchChooser :: (SigSpace a, Sigs a) => ([Text] -> Int -> Source Sig) -> [(Text, Patch D a)] -> Int -> Source a
 genPatchChooser widget xs initVal = joinSource $ lift1 go $ widget names initVal
     where
         (names, patches) = unzip xs
diff --git a/src/Csound/Air/Looper.hs b/src/Csound/Air/Looper.hs
--- a/src/Csound/Air/Looper.hs
+++ b/src/Csound/Air/Looper.hs
@@ -9,6 +9,8 @@
 import Data.List
 
 import Data.Default
+import Data.Text (Text)
+import Data.Text qualified as Text
 import Data.Boolean hiding (cond)
 import Csound.Typed
 import Csound.Typed.Gui hiding (button)
@@ -111,8 +113,8 @@
     , loopDel  = Nothing
     , loopThrough = Nothing }
 
-type TapControl     = [String] -> Int -> Source Sig
-type FadeControl    = [String -> Source (Evt D)]
+type TapControl     = [Text] -> Int -> Source Sig
+type FadeControl    = [Text -> Source (Evt D)]
 type DelControl     = Source Tick
 type ThroughControl = Source Sig
 
@@ -204,8 +206,8 @@
     through = throughControl
 
     throughDel = hlift2' 6 1 (\a b -> (a, b)) through delControl
-    sw = tapControl (fmap show ids) initInstr
-    sil = hlifts id $ zipWith (\g n -> g (show n)) fadeControl [0 .. length silencer - 1]
+    sw = tapControl (fmap (Text.pack . show) ids) initInstr
+    sil = hlifts id $ zipWith (\g n -> g (Text.pack $ show n)) fadeControl [0 .. length silencer - 1]
 
     maxDel = 3
 
diff --git a/src/Csound/Air/ModArg.hs b/src/Csound/Air/ModArg.hs
--- a/src/Csound/Air/ModArg.hs
+++ b/src/Csound/Air/ModArg.hs
@@ -54,6 +54,8 @@
 
 ) where
 
+import Data.Kind (Type)
+
 import Csound.Typed
 import Csound.Typed.Opcode(gauss, gaussi, jitter, linseg, linsegr, expsegr)
 import Csound.Air.Wave
@@ -509,7 +511,7 @@
 -- modArg1
 
 class ModArg1 a b where
-    type ModArgOut1 a b :: *
+    type ModArgOut1 a b :: Type
     modArg1 :: Sig -> a -> b -> ModArgOut1 a b
 
 --------------------------------------------
@@ -669,7 +671,7 @@
 -- modArg2
 
 class ModArg2 a b where
-    type ModArgOut2 a b :: *
+    type ModArgOut2 a b :: Type
     modArg2 :: Sig -> a -> b -> ModArgOut2 a b
 
 --------------------------------------------
@@ -797,7 +799,7 @@
 -- modArg3
 
 class ModArg3 a b where
-    type ModArgOut3 a b :: *
+    type ModArgOut3 a b :: Type
     modArg3 :: Sig -> a -> b -> ModArgOut3 a b
 
 --------------------------------------------
@@ -893,7 +895,7 @@
 -- modArg4
 
 class ModArg4 a b where
-    type ModArgOut4 a b :: *
+    type ModArgOut4 a b :: Type
     modArg4 :: Sig -> a -> b -> ModArgOut4 a b
 
 --------------------------------------------
diff --git a/src/Csound/Air/Patch.hs b/src/Csound/Air/Patch.hs
--- a/src/Csound/Air/Patch.hs
+++ b/src/Csound/Air/Patch.hs
@@ -62,6 +62,7 @@
 ) where
 
 import Data.Boolean hiding (cond)
+import Data.Text (Text)
 import Data.Default
 import Control.Monad
 import Control.Applicative
@@ -644,16 +645,16 @@
 --
 -- > i "givenName" 1 pitchKey volumeKey     -- note on
 -- > i "givenName" 0 pitchKey volumeKey     -- note off
-patchByNameMidi :: (SigSpace a, Sigs a) => String -> Patch a -> SE a
+patchByNameMidi :: (SigSpace a, Sigs a) => Text -> Patch a -> SE a
 patchByNameMidi = genPatchByNameMidi cpsmidinn cpsmidinn
 
 -- | Triggers patch with Csound API.
 -- It creates a named instruement with given name (second argument).
 -- It behaves like the function @patchByNameMidi@ but we can specify custom temperament.
-patchByNameMidiTemp :: (SigSpace a, Sigs a) => Temp -> String -> Patch a -> SE a
+patchByNameMidiTemp :: (SigSpace a, Sigs a) => Temp -> Text -> Patch a -> SE a
 patchByNameMidiTemp tm = genPatchByNameMidi (cpsmidi'Sig tm) (cpsmidi'D tm)
 
-genPatchByNameMidi :: forall a . (SigSpace a, Sigs a) => (Sig -> Sig) -> (D -> D) -> String -> Patch a -> SE a
+genPatchByNameMidi :: forall a . (SigSpace a, Sigs a) => (Sig -> Sig) -> (D -> D) -> Text -> Patch a -> SE a
 genPatchByNameMidi monoKey2cps polyKey2cps name x = go Nothing x
     where
         go maybeSkin = \case
diff --git a/src/Csound/Air/Seg.hs b/src/Csound/Air/Seg.hs
--- a/src/Csound/Air/Seg.hs
+++ b/src/Csound/Air/Seg.hs
@@ -225,7 +225,7 @@
 
 -- | Takes the first event from the event stream and ignores the rest of the stream.
 take1 :: Evt a -> Evt a
-take1 = fmap fst . filterE ((==* 0) . snd) . accumE (0 :: D) (\a s -> ((a, s), s + 1) )
+take1 = fmap fst . filterE ((==* 0) . snd) . accumE (0 :: Sig) (\a s -> ((a, s), s + 1) )
 
 -----------------------------------------------------------
 -- tick funs with less instrs
diff --git a/src/Csound/Control/Evt.hs b/src/Csound/Control/Evt.hs
--- a/src/Csound/Control/Evt.hs
+++ b/src/Csound/Control/Evt.hs
@@ -123,7 +123,7 @@
 syncBpm dt = sync (dt / 60)
 
 -- | Splits event stream on two streams with predicate.
-partitionE :: (a -> BoolD) -> Evt a -> (Evt a, Evt a)
+partitionE :: (a -> BoolSig) -> Evt a -> (Evt a, Evt a)
 partitionE p evts = (a, b)
     where
         a = filterE p          evts
@@ -131,13 +131,14 @@
 
 -- | Splits a toggle event stream on on-events and off-events.
 splitToggle :: Evt D -> (Evt D, Evt D)
-splitToggle = swap . partitionE (==* 0)
+splitToggle = swap . partitionE ((==* 0) . sig)
 
 -- | Constructs an event stream that contains pairs from the
 -- given pair of signals. Events happens when any signal changes.
 snaps2 :: Sig2 -> Evt (D, D)
 snaps2 (x, y) = snapshot const (x, y) triggerSig
-    where triggerSig = sigToEvt $ changed [x, y]
+  where
+    triggerSig = sigToEvt $ changed [x, y]
 
 ----------------------------------------------------------------------
 -- higher level evt-funs
@@ -151,28 +152,28 @@
 
 -- | Turns an event of indices to the event of the values from the list.
 -- A value is taken with index.
-listAt :: (Tuple a, Arg a) => [a] -> Evt D -> Evt a
+listAt :: (Tuple a, Arg a) => [a] -> Evt Sig -> Evt a
 listAt vals evt
-    | null vals = mempty
-    | otherwise = fmap (atArg vals) $ filterE withinBounds evt
-    where
-        withinBounds x = (x >=* 0) &&* (x `lessThan` len)
-        len = int $ length vals
+  | null vals = mempty
+  | otherwise = fmap (atArg vals) $ filterE withinBounds evt
+  where
+    withinBounds x = (x >=* 0) &&* (x `lessThan` sig len)
+    len = int $ length vals
 
 -- |
 --
 -- > range (xMin, xMax) === cycleE [xMin .. pred xMax]
-range :: (D, D) -> Evt b -> Evt D
-range (xMin, xMax) = iterateE xMin $ \x -> ifB ((x + 1) >=* xMax) xMin (x + 1)
+range :: (D, D) -> Evt b -> Evt Sig
+range (xMin, xMax) = iterateE (sig xMin) $ \x -> ifB ((x + 1) >=* sig xMax) (sig xMin) (x + 1)
 
 -- | An event stream of the integers taken from the given diapason.
-randInts :: (D, D) -> Evt b -> Evt D
-randInts (xMin, xMax) = accumSE (0 :: D) $ const $ \s -> fmap (, s) $ getRnd
-    where getRnd = fmap (int' . readSnap) $ random (sig $ int' xMin) (sig $ int' xMax)
+randInts :: (D, D) -> Evt b -> Evt Sig
+randInts (xMin, xMax) = accumSE (0 :: Sig) $ const $ \s -> fmap (, s) $ getRnd
+    where getRnd = fmap int' $ random (sig $ int' xMin) (sig $ int' xMax)
 
 -- | An event stream of the random values in the interval @(0, 1)@.
 randDs :: Evt b -> Evt D
-randDs = accumSE (0 :: D) $ const $ \s -> fmap (, s) $ fmap readSnap $ random (0::D) 1
+randDs = accumSE (0 ::Sig) $ const $ \s -> fmap (, s) $ fmap readSnap $ random (0::Sig) 1
 
 -- | An event stram of lists of random values in the interval @(0, 1)@.
 -- The first argument is the length of the each list.
@@ -186,7 +187,7 @@
 --
 -- where @prob@ is probability of includinng the element in the output stream.
 randSkip :: Sig -> Evt a -> Evt a
-randSkip d = filterSE (const $ fmap (<=* ir d) $ random (0::D) 1)
+randSkip d = filterSE (const $ fmap (<=*  d) $ random (0::Sig) 1)
 
 -- | Skips elements at random.
 --
@@ -194,7 +195,7 @@
 --
 -- It behaves just like @randSkip@, but probability depends on the value.
 randSkipBy :: (a -> Sig) -> Evt a -> Evt a
-randSkipBy d = filterSE (\x -> fmap (<=* ir (d x)) $ random (0::D) 1)
+randSkipBy d = filterSE (\x -> fmap (<=* d x) $ random (0::Sig) 1)
 
 -- | When something happens on the given event stream resulting
 -- event stream contains an application of some unary function to the
@@ -290,9 +291,9 @@
 -- n'th element from the given list should be included in the resulting stream
 -- if the n'th element from the list equals to one or skipped if the element
 -- equals to zero.
-masked :: (Tuple a, Arg a) => [D] -> Evt a -> Evt a
+masked :: (Tuple a) => [Sig] -> Evt a -> Evt a
 masked ms = filterAccumE 0 $ \a s ->
-    let n  = int $ length ms
+    let n  = sig $ int $ length ms
         s1 = ifB (s + 1 `lessThan` n) (s + 1) 0
     in  (atArg ms s ==* 1, a, s1)
 
@@ -319,27 +320,27 @@
 toTog1 = togGen 0
 
 
-mkRow :: Evt a -> Evt (a, D)
-mkRow = accumE (0 :: D) (\a s -> ((a, s), s + 1) )
+mkRow :: Evt a -> Evt (a, Sig)
+mkRow = accumE (0 :: Sig) (\a s -> ((a, s), s + 1) )
 
-filterRow :: (D -> BoolD) -> Evt a -> Evt a
+filterRow :: (Sig -> BoolSig) -> Evt a -> Evt a
 filterRow p = fmap fst . filterE (p . snd) . mkRow
 
 -- | Takes the ns events from the event stream and ignores the rest of the stream.
 takeE :: Int -> Evt a -> Evt a
-takeE n = filterRow ( `lessThan` int n)
+takeE n = filterRow ( `lessThan` sig (int n))
 
 -- | Drops the ns events from the event stream and leaves the rest of the stream.
 dropE :: Int -> Evt a -> Evt a
-dropE n = filterRow ( >=* int n)
+dropE n = filterRow ( >=* sig (int n))
 
 -- | Takes events while the predicate is true.
-takeWhileE :: (a -> BoolD) -> Evt a -> Evt a
-takeWhileE p = fmap fst . filterE snd . accumE (1 :: D) (\a s -> let s1 = s ==* 1 &&* p a in ((a, s1), ifB s1 1 0))
+takeWhileE :: (a -> BoolSig) -> Evt a -> Evt a
+takeWhileE p = fmap fst . filterE snd . accumE (1 :: Sig) (\a s -> let s1 = s ==* 1 &&* p a in ((a, s1), ifB s1 1 0))
 
 -- | Drops events while the predicate is true.
-dropWhileE :: (a -> BoolD) -> Evt a -> Evt a
-dropWhileE p = fmap fst . filterE (notB . snd) . accumE (1 :: D) (\a s -> let s1 = s ==* 1 &&* p a in ((a, s1), ifB s1 1 0))
+dropWhileE :: (a -> BoolSig) -> Evt a -> Evt a
+dropWhileE p = fmap fst . filterE (notB . snd) . accumE (1 :: Sig) (\a s -> let s1 = s ==* 1 &&* p a in ((a, s1), ifB s1 1 0))
 
 -- | Delays event stream by given amount of seconds
 delEvt :: Arg a => D -> Evt a -> Evt a
diff --git a/src/Csound/Control/Gui.hs b/src/Csound/Control/Gui.hs
--- a/src/Csound/Control/Gui.hs
+++ b/src/Csound/Control/Gui.hs
@@ -87,6 +87,7 @@
     hbind', vbind', happly', vapply', hmapM', vmapM', gridMapM
 ) where
 
+import Data.Text (Text)
 import Control.Monad
 
 import Csound.Typed
@@ -115,10 +116,10 @@
 -- | Creates a window with the given name, size and content
 --
 -- > win name (width, height) gui
-win :: String -> (Int, Int) -> Gui -> SE ()
+win :: Text -> (Int, Int) -> Gui -> SE ()
 win name (x, y) = panelBy name (Just $ Rect 0 0 x y)
 
-keyWin :: String -> (Int, Int) -> Gui -> SE ()
+keyWin :: Text -> (Int, Int) -> Gui -> SE ()
 keyWin name (x, y) = keyPanelBy name (Just $ Rect 0 0 x y)
 
 -- | Hides the SE inside Source.
diff --git a/src/Csound/Control/Gui/Widget.hs b/src/Csound/Control/Gui/Widget.hs
--- a/src/Csound/Control/Gui/Widget.hs
+++ b/src/Csound/Control/Gui/Widget.hs
@@ -63,6 +63,8 @@
 import Csound.Control.SE
 import Csound.Control.Evt(listAt, Tick, snaps2, dropE, devt, loadbang, evtToSig)
 import Csound.Typed.Opcode(changed)
+import Data.Text (Text)
+import Data.Text qualified as Text
 
 --------------------------------------------------------------------
 -- aux widgets
@@ -77,25 +79,25 @@
             where (a, b) = splitAt y qs
 
 -- | A radio button. It takes a list of values with labels.
-radioButton :: Arg a => String -> [(String, a)] -> Int -> Source (Evt a)
+radioButton :: Arg a => Text -> [(Text, a)] -> Int -> Source (Evt a)
 radioButton title as initVal = source $ do
     (g, ind) <- butBank1 "" 1 (length as) (0, initVal)
     gnames   <- mapM box names
-    let val = listAt vals ind
+    let val = listAt vals $ fmap sig ind
     gui <- setTitle title $ padding 0 $ hor [sca 0.15 g, ver gnames]
     return (gui, val)
     where (names, vals) = unzip as
 
 -- | A matrix of values.
-matrixButton :: Arg a => String -> Int -> Int -> [a] -> (Int, Int) -> Source (Evt a)
+matrixButton :: Arg a => Text -> Int -> Int -> [a] -> (Int, Int) -> Source (Evt a)
 matrixButton name xn yn vals initVal = source $ do
     (gui, ind) <- butBank1 name xn yn initVal
-    let val = listAt allVals ind
+    let val = listAt allVals $ fmap sig ind
     return (gui, val)
     where allVals = readMatrix xn yn vals
 
 -- | Radio button that returns functions. Useful for picking a waveform or type of filter.
-funnyRadio :: Tuple b => String -> [(String, a -> b)] -> Int -> Source (a -> b)
+funnyRadio :: Tuple b => Text -> [(Text, a -> b)] -> Int -> Source (a -> b)
 funnyRadio name as initVal = source $ do
     (gui, ind) <- radioButton name (zip names (fmap int [0 ..])) initVal
     contInd <- stepper (sig $ int initVal) $ fmap sig ind
@@ -106,7 +108,7 @@
     where (names, funs) = unzip as
 
 -- | Matrix of functional values.
-funnyMatrix :: Tuple b => String -> Int -> Int -> [(a -> b)] -> (Int, Int) -> Source (a -> b)
+funnyMatrix :: Tuple b => Text -> Int -> Int -> [(a -> b)] -> (Int, Int) -> Source (a -> b)
 funnyMatrix name xn yn funs initVal@(x0, y0) = source $ do
     (gui, ind) <- butBank1 name xn yn initVal
     contInd <- stepper flattenInitVal $ fmap sig ind
@@ -187,7 +189,7 @@
 genNumbers :: ([Gui] -> Gui) -> [Double] -> Source Sig
 genNumbers gx as@(d:_) = source $ do
     ref <- newGlobalCtrlRef (sig $ double d)
-    (gs, evts) <- fmap unzip $ mapM (button . show) as
+    (gs, evts) <- fmap unzip $ mapM (button . Text.pack . show) as
     zipWithM_ (\x e -> runEvt e $ \_ -> writeRef ref (sig $ double x)) as evts
     res <- readRef ref
     return (gx gs, res)
@@ -205,7 +207,7 @@
 -- if names are not important) and list of init values.
 -- It returns a function that takes in indices and produces the signal in
 -- the corresponding cell.
-knobPad :: Int -> Int -> [String] -> [Double] -> Source (Int -> Int -> Sig)
+knobPad :: Int -> Int -> [Text] -> [Double] -> Source (Int -> Int -> Sig)
 knobPad = genPad mkKnob 0.5
     where mkKnob name = knob name uspan
 
@@ -217,7 +219,7 @@
 -- if names are not important) and list of init values (on/off booleans).
 -- It returns a function that takes in indices and produces the event stream in
 -- the corresponding cell.
-togglePad :: Int -> Int -> [String] -> [Bool] -> Source (Int -> Int -> Evt D)
+togglePad :: Int -> Int -> [Text] -> [Bool] -> Source (Int -> Int -> Evt D)
 togglePad = genPad toggle False
 
 -- | The matrix of buttons.
@@ -228,7 +230,7 @@
 -- if names are not important).
 -- It returns a function that takes in indices and produces the event stream in
 -- the corresponding cell.
-buttonPad :: Int -> Int -> [String] -> Source (Int -> Int -> Evt Unit)
+buttonPad :: Int -> Int -> [Text] -> Source (Int -> Int -> Evt Unit)
 buttonPad width height names = genPad mkButton False width height names []
     where mkButton name _ = button name
 
@@ -236,7 +238,7 @@
 -- It takes the constructor of the widget, a default initial value,
 -- the dimensions of the matrix, the list of names and the list of initial values.
 -- It produces the function that maps indices to corresponding values.
-genPad :: (String -> a -> Source b) -> a -> Int -> Int -> [String] -> [a] -> Source (Int -> Int -> b)
+genPad :: (Text -> a -> Source b) -> a -> Int -> Int -> [Text] -> [a] -> Source (Int -> Int -> b)
 genPad mk initVal width height names as = source $ do
     (gui, vals) <- fmap reGroupCol $ mapM mkRow inits
     let f x y = (vals !! y) !! x
@@ -258,25 +260,25 @@
 
 
 -- | Horizontal radio group.
-hradio :: [String] -> Int -> Source (Evt D)
+hradio :: [Text] -> Int -> Source (Evt D)
 hradio = radioGroup hor
 
 -- | Vertical radio group.
-vradio :: [String] -> Int -> Source (Evt D)
+vradio :: [Text] -> Int -> Source (Evt D)
 vradio = radioGroup ver
 
 -- | Horizontal radio group.
-hradioSig :: [String] -> Int -> Source Sig
+hradioSig :: [Text] -> Int -> Source Sig
 hradioSig = radioGroupSig hor
 
 -- | Vertical radio group.
-vradioSig :: [String] -> Int -> Source Sig
+vradioSig :: [Text] -> Int -> Source Sig
 vradioSig = radioGroupSig ver
 
-radioGroup :: ([Gui] -> Gui) -> [String] -> Int -> Source (Evt D)
+radioGroup :: ([Gui] -> Gui) -> [Text] -> Int -> Source (Evt D)
 radioGroup gcat names initVal = mapSource snaps $ radioGroupSig gcat names initVal
 
-radioGroupSig  :: ([Gui] -> Gui) -> [String] -> Int -> Source Sig
+radioGroupSig  :: ([Gui] -> Gui) -> [Text] -> Int -> Source Sig
 radioGroupSig gcat names initVal = source $ do
     (guis, writes, reads) <- fmap unzip3 $ mapM (\(i, tag) -> flip setToggleSig (i == initVal) tag) $ zip [0 ..] names
     curRef <- newGlobalCtrlRef (sig $ int initVal)
@@ -393,18 +395,18 @@
 
 -- | It's like simple @button@, but it can be controlled with external control.
 -- The first argument is for external control.
-button' :: Tick -> String -> Source Tick
+button' :: Tick -> Text -> Source Tick
 button' ctrl name = mapSource (mappend ctrl) $ button name
 
 -- | It's like simple @toggle@, but it can be controlled with external control.
 -- The first argument is for external control.
-toggle' :: Evt D -> String -> Bool -> Source (Evt D)
+toggle' :: Evt D -> Text -> Bool -> Source (Evt D)
 toggle' ctrl name initVal = source $ do
     (gui, output, input) <- setToggle name initVal
     output ctrl
     return $ (gui, mappend ctrl input)
 
-toggleSig' :: Sig -> String -> Bool -> Source Sig
+toggleSig' :: Sig -> Text -> Bool -> Source Sig
 toggleSig' ctrl name initVal =
     ctrlSig (if initVal then 1 else 0) ctrl $ setToggleSig name initVal
 
@@ -420,38 +422,38 @@
 
 -- | It's like simple @knob@, but it can be controlled with external control.
 -- The first argument is for external control.
-knob' :: Sig -> String -> ValSpan -> Double -> Source Sig
+knob' :: Sig -> Text -> ValSpan -> Double -> Source Sig
 knob' ctrl name span initVal = ctrlSig (double initVal) ctrl $ setKnob name span initVal
 
 -- | It's like simple @slider@, but it can be controlled with external control.
 -- The first argument is for external control.
-slider' :: Sig -> String -> ValSpan -> Double -> Source Sig
+slider' :: Sig -> Text -> ValSpan -> Double -> Source Sig
 slider' ctrl name span initVal = ctrlSig (double initVal) ctrl $ setSlider name span initVal
 
 -- | It's like simple @hradioSig@, but it can be controlled with external control.
 -- The first argument is for external control.
-hradioSig' :: Sig -> [String] -> Int -> Source Sig
+hradioSig' :: Sig -> [Text] -> Int -> Source Sig
 hradioSig' = radioGroupSig' hor
 
 -- | It's like simple @vradioSig@, but it can be controlled with external control.
 -- The first argument is for external control.
-vradioSig' :: Sig -> [String] -> Int -> Source Sig
+vradioSig' :: Sig -> [Text] -> Int -> Source Sig
 vradioSig' = radioGroupSig' ver
 
 -- | It's like simple @hradio@, but it can be controlled with external control.
 -- The first argument is for external control.
-hradio' :: Evt D -> [String] -> Int -> Source (Evt D)
+hradio' :: Evt D -> [Text] -> Int -> Source (Evt D)
 hradio' = radioGroup' hor
 
 -- | It's like simple @vradio@, but it can be controlled with external control.
 -- The first argument is for external control.
-vradio' :: Evt D -> [String] -> Int -> Source (Evt D)
+vradio' :: Evt D -> [Text] -> Int -> Source (Evt D)
 vradio' = radioGroup' ver
 
-radioGroup'  :: ([Gui] -> Gui) -> Evt D -> [String] -> Int -> Source (Evt D)
+radioGroup'  :: ([Gui] -> Gui) -> Evt D -> [Text] -> Int -> Source (Evt D)
 radioGroup' gcat ctrl names initVal =  mapSource snaps $ radioGroupSig' gcat (evtToSig (int initVal) ctrl) names initVal
 
-radioGroupSig'  :: ([Gui] -> Gui) -> Sig -> [String] -> Int -> Source Sig
+radioGroupSig'  :: ([Gui] -> Gui) -> Sig -> [Text] -> Int -> Source Sig
 radioGroupSig' gcat ctrl names initVal = source $ do
     (guis, writes, reads) <- fmap unzip3 $ mapM (\(i, tag) -> flip setToggleSig (i == initVal) tag) $ zip [0 ..] names
     curRef <- newGlobalCtrlRef (sig $ int initVal)
diff --git a/src/Csound/Control/Midi.hs b/src/Csound/Control/Midi.hs
--- a/src/Csound/Control/Midi.hs
+++ b/src/Csound/Control/Midi.hs
@@ -28,6 +28,7 @@
 ) where
 
 import Data.Boolean
+import Data.Text (Text)
 
 import Csound.Typed hiding (arg)
 import Csound.Typed.Opcode hiding (initc7)
@@ -232,10 +233,10 @@
 -- > i "givenName" 0 pitchKey volumeKey     -- note off
 --
 -- The output is a pair of signals @(midiVolume, midiPitch)@.
-trigNamedMono :: String -> SE MonoArg
+trigNamedMono :: Text -> SE MonoArg
 trigNamedMono name = namedMonoMsg name
 
-namedAmpCpsSig:: String -> SE (Sig, Sig, Sig)
+namedAmpCpsSig:: Text -> SE (Sig, Sig, Sig)
 namedAmpCpsSig name = do
   ref <- newGlobalCtrlRef ((0, 0) :: (Sig, Sig))
   statusRef <- newGlobalCtrlRef (0 :: Sig)
@@ -276,7 +277,7 @@
     writeRef evtRef $ diff a
 
   evtSig <- readRef evtRef
-  return $ filterE ( >* 0) $ snaps evtSig
+  return $ filterE (( >* 0) . sig) $ snaps evtSig
   where
     instr msg = do
       print' [notnum msg]
@@ -294,7 +295,7 @@
     writeRef evtRef $ diff a
 
   evtSig <- readRef evtRef
-  return $ fmap (const unit) $ filterE ( `lessThan` 0) $ snaps evtSig
+  return $ fmap (const unit) $ filterE (( `lessThan` 0) . sig) $ snaps evtSig
   where
     instr msg = do
       print' [notnum msg]
diff --git a/src/Csound/Control/Overload/MidiInstr.hs b/src/Csound/Control/Overload/MidiInstr.hs
--- a/src/Csound/Control/Overload/MidiInstr.hs
+++ b/src/Csound/Control/Overload/MidiInstr.hs
@@ -3,6 +3,8 @@
     MidiInstr(..), MidiInstrTemp(..)
 ) where
 
+import Data.Kind(Type)
+
 import Csound.Typed
 import Csound.Typed.Opcode
 
@@ -22,7 +24,7 @@
 
 -- | Converts a value to the midi-instrument. It's used with the functions 'Csound.Base.midi', 'Csound.Base.midin'.
 class MidiInstr a where
-    type MidiInstrOut a :: *
+    type MidiInstrOut a :: Type
 
     onMsg :: a -> Msg -> SE (MidiInstrOut a)
 
diff --git a/src/Csound/Control/Overload/Outs.hs b/src/Csound/Control/Overload/Outs.hs
--- a/src/Csound/Control/Overload/Outs.hs
+++ b/src/Csound/Control/Overload/Outs.hs
@@ -6,13 +6,15 @@
     Outs(..), onArg
 ) where
 
+import Data.Kind(Type)
+
 import Csound.Typed
 
 onArg :: Outs b => (a -> b) -> (a -> SE (SigOuts b))
 onArg f = toOuts . f
 
 class Sigs (SigOuts a) => Outs a where
-    type SigOuts a :: *
+    type SigOuts a :: Type
     toOuts :: a -> SE (SigOuts a)
 
 instance Outs Sig where
diff --git a/src/Csound/Control/Overload/SpecInstr.hs b/src/Csound/Control/Overload/SpecInstr.hs
--- a/src/Csound/Control/Overload/SpecInstr.hs
+++ b/src/Csound/Control/Overload/SpecInstr.hs
@@ -4,6 +4,7 @@
 ) where
 
 import Control.Arrow(first, second)
+import Data.Kind(Type)
 
 import Csound.Typed
 
@@ -11,7 +12,7 @@
 -- Drum like instrument has a single argument that 
 -- signifies an amplitude.
 class AmpInstr a where
-    type AmpInstrOut a :: *
+    type AmpInstrOut a :: Type
     onAmp :: a -> D -> SE (AmpInstrOut a)
 
 instance AmpInstr (D -> SE Sig) where
@@ -67,7 +68,7 @@
 -- | Constructs a simple instrument that takes in a tuple of two arguments.
 -- They are amplitude and the frequency (in Hz or cycles per second).
 class CpsInstr a where
-    type CpsInstrOut a :: *
+    type CpsInstrOut a :: Type
     onCps :: a -> (D, D) -> SE (CpsInstrOut a)
 
 instance CpsInstr ((D, D) -> SE Sig) where
diff --git a/src/Csound/IO.hs b/src/Csound/IO.hs
--- a/src/Csound/IO.hs
+++ b/src/Csound/IO.hs
@@ -1,4 +1,4 @@
-{-# Language FlexibleInstances, UndecidableInstances, CPP #-}
+{-# Language ScopedTypeVariables, InstanceSigs, FlexibleInstances, UndecidableInstances, CPP #-}
 -- | Rendering of Csound files and playing the music in real time.
 --
 -- How are we going to get the sound out of Haskell code?
@@ -71,9 +71,13 @@
 --import Control.Concurrent
 import Control.Monad
 
+import Data.Text qualified as Text
 import System.Process
+import System.Directory
+import System.FilePath
 import qualified Control.Exception as E
 
+import Data.Proxy
 import Data.Default
 import Csound.Typed
 import Csound.Control.Gui
@@ -81,8 +85,6 @@
 import Csound.Options(setSilent, setDac, setAdc, setDacBy, setAdcBy, setCabbage)
 import Temporal.Class(Harmony(..))
 
-import qualified Data.List as L
-
 render :: Sigs a => Options -> SE a -> IO String
 render = renderOutBy
 
@@ -96,12 +98,12 @@
 
 class RenderCsd a where
     renderCsdBy :: Options -> a -> IO String
-    csdArity :: a -> CsdArity
+    csdArity :: Proxy a -> CsdArity
 
-hasInputs :: RenderCsd a => a -> Bool
+hasInputs :: RenderCsd a => Proxy a -> Bool
 hasInputs = ( > 0) . csdArity'inputs . csdArity
 
-hasOutputs :: RenderCsd a => a -> Bool
+hasOutputs :: RenderCsd a => Proxy a -> Bool
 hasOutputs = ( > 0) . csdArity'outputs . csdArity
 
 instance {-# OVERLAPPING #-} RenderCsd (SE ()) where
@@ -109,73 +111,50 @@
     csdArity _ = CsdArity 0 0
 
 #if __GLASGOW_HASKELL__ >= 710
-instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd a where
+instance {-# OVERLAPPABLE #-} forall a. Sigs a => RenderCsd a where
   renderCsdBy opt a = render opt (return a)
-  csdArity a = CsdArity 0 (tupleArity a)
+  csdArity _ = CsdArity 0 (tupleArity (Proxy :: Proxy a))
 
-instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (SE a) where
+instance {-# OVERLAPPABLE #-} forall a. Sigs a => RenderCsd (SE a) where
   renderCsdBy opt a = render opt a
-  csdArity a = CsdArity 0 (outArity a)
+  csdArity _ = CsdArity 0 (tupleArity (Proxy :: Proxy a))
 
-instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Source a) where
+instance {-# OVERLAPPABLE #-} forall a. Sigs a => RenderCsd (Source a) where
   renderCsdBy opt a = renderCsdBy opt (fromSource a)
-  csdArity a = CsdArity 0 (tupleArity $ proxySource a)
-      where
+  csdArity _ = CsdArity 0 (tupleArity (Proxy :: Proxy a))
 
-instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Source (SE a)) where
+instance {-# OVERLAPPABLE #-} forall a. Sigs a => RenderCsd (Source (SE a)) where
   renderCsdBy opt a = renderCsdBy opt (fromSourceSE a)
-  csdArity a = CsdArity 0 (tupleArity $ proxySE $ proxySource a)
+  csdArity _ = CsdArity 0 (tupleArity (Proxy :: Proxy a))
 
-instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Sco (Mix a)) where
+instance {-# OVERLAPPABLE #-} forall a. Sigs a => RenderCsd (Sco (Mix a)) where
   renderCsdBy opt a = renderCsdBy opt (mix a)
-  csdArity a = CsdArity 0 (tupleArity $ proxy a)
-    where
-      proxy :: Sco (Mix a) -> a
-      proxy = const undefined
+  csdArity _ = CsdArity 0 (tupleArity (Proxy :: Proxy a))
 
-instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd [Sco (Mix a)] where
+instance {-# OVERLAPPABLE #-} forall a. Sigs a => RenderCsd [Sco (Mix a)] where
   renderCsdBy opt a = renderCsdBy opt (mix $ har a)
-  csdArity a = CsdArity 0 (tupleArity $ proxy a)
-    where
-      proxy :: [Sco (Mix a)] -> a
-      proxy = const undefined
+  csdArity _ = CsdArity 0 (tupleArity $ (Proxy :: Proxy a))
 
 #endif
 
-proxySource :: Source a -> a
-proxySource = const undefined
-
-proxySE :: SE a -> a
-proxySE = const undefined
-
-proxyFun :: (a -> b) -> (a, b)
-proxyFun = const undefined
-
-proxyIn :: (a -> b) -> a
-proxyIn = fst . proxyFun
-
-proxyOut :: (a -> b) -> b
-proxyOut = snd . proxyFun
-
-instance {-# OVERLAPPABLE #-} (Sigs a, Sigs b) => RenderCsd (a -> b) where
+instance {-# OVERLAPPABLE #-} forall a b. (Sigs a, Sigs b) => RenderCsd (a -> b) where
     renderCsdBy opt f = renderEffBy opt (return . f)
-    csdArity a = CsdArity (tupleArity $ proxyIn a) (tupleArity $ proxyOut a)
+    csdArity _ = CsdArity (tupleArity (Proxy :: Proxy a)) (tupleArity (Proxy :: Proxy b))
 
-instance {-# OVERLAPPABLE #-} (Sigs a, Sigs b) => RenderCsd (a -> SE b) where
+instance {-# OVERLAPPABLE #-} forall a b. (Sigs a, Sigs b) => RenderCsd (a -> SE b) where
     renderCsdBy opt f = renderEffBy opt f
-    csdArity a = CsdArity (tupleArity $ proxyIn a) (tupleArity $ proxySE $ proxyOut a)
+    csdArity _ = CsdArity (tupleArity (Proxy :: Proxy a)) (tupleArity (Proxy :: Proxy b))
 
-instance {-# OVERLAPPABLE #-} (Sigs a, Sigs b) => RenderCsd (a -> Source b) where
+instance {-# OVERLAPPABLE #-} forall a b. (Sigs a, Sigs b) => RenderCsd (a -> Source b) where
     renderCsdBy opt f = renderEffBy opt (fromSource . f)
-    csdArity a = CsdArity (tupleArity $ proxyIn a) (tupleArity $ proxySource $ proxyOut a)
-
-instance (Sigs a, Sigs b) => RenderCsd (a -> Source (SE b)) where
+    csdArity _ = CsdArity (tupleArity (Proxy :: Proxy a)) (tupleArity (Proxy :: Proxy b))
+instance forall a b. (Sigs a, Sigs b) => RenderCsd (a -> Source (SE b)) where
     renderCsdBy opt f = renderEffBy opt (fromSourceSE . f)
-    csdArity a = CsdArity (tupleArity $ proxyIn a) (tupleArity $ proxySE $ proxySource $ proxyOut a)
+    csdArity _ = CsdArity (tupleArity (Proxy :: Proxy a)) (tupleArity (Proxy :: Proxy b))
 
-instance {-# OVERLAPPING #-} (Sigs a) => RenderCsd (a -> Source (SE Sig2)) where
+instance {-# OVERLAPPING #-} forall a. (Sigs a) => RenderCsd (a -> Source (SE Sig2)) where
     renderCsdBy opt f = renderEffBy opt (fromSourceSE . f)
-    csdArity a = CsdArity (tupleArity $ proxyIn a) (tupleArity $ proxySE $ proxySource $ proxyOut a)
+    csdArity _ = CsdArity (tupleArity (Proxy :: Proxy a)) (tupleArity (Proxy :: Proxy Sig2))
 
 instance {-# OVERLAPPING #-} RenderCsd (Source ()) where
     renderCsdBy opt src = renderCsdBy opt $ do
@@ -191,24 +170,27 @@
 renderCsd :: RenderCsd a => a -> IO String
 renderCsd = renderCsdBy def
 
+getTmpFile :: IO FilePath
+getTmpFile = (</> "tmp.csd") <$> getTemporaryDirectory
+
 -- | Render Csound file and save it to the give file.
-writeCsd :: RenderCsd a => String -> a -> IO ()
+writeCsd :: RenderCsd a => FilePath -> a -> IO ()
 writeCsd file a = writeFile file =<< renderCsd a
 
 -- | Render Csound file with options and save it to the give file.
-writeCsdBy :: RenderCsd a => Options -> String -> a -> IO ()
+writeCsdBy :: RenderCsd a => Options -> FilePath -> a -> IO ()
 writeCsdBy opt file a = writeFile file =<< renderCsdBy opt a
 
 -- | Render Csound file and save result sound to the wav-file.
-writeSnd :: RenderCsd a => String -> a -> IO ()
+writeSnd :: RenderCsd a => FilePath -> a -> IO ()
 writeSnd = writeSndBy def
 
 -- | Render Csound file with options and save result sound to the wav-file.
-writeSndBy :: RenderCsd a => Options -> String -> a -> IO ()
+writeSndBy :: RenderCsd a => Options -> FilePath -> a -> IO ()
 writeSndBy opt file a = do
+    fileCsd <- getTmpFile
     writeCsdBy opt fileCsd a
     runWithUserInterrupt (postSetup opt) $ unwords ["csound -o", file, fileCsd, logTrace opt]
-    where fileCsd = "tmp.csd"
 
 logTrace :: Options -> String
 logTrace opt
@@ -246,22 +228,23 @@
 dac = dacBy def
 
 -- | 'Csound.Base.dac' with options.
-dacBy :: (RenderCsd a) => Options -> a -> IO ()
+dacBy :: forall a. (RenderCsd a) => Options -> a -> IO ()
 dacBy opt' a = do
-    writeCsdBy opt "tmp.csd" a
-    runWithUserInterrupt (postSetup opt') $ unwords ["csound tmp.csd", logTrace opt']
+    fileCsd <- getTmpFile
+    writeCsdBy opt fileCsd a
+    runWithUserInterrupt (postSetup opt') $ unwords ["csound", fileCsd, logTrace opt']
     where
       opt = mconcat [opt', withDac, withAdc]
 
       withDac
-        | hasJackConnections opt' = setDacBy "null"
-        | hasOutputs a            = setDac
-        | otherwise               = mempty
+        | hasJackConnections opt'       = setDacBy "null"
+        | hasOutputs (Proxy :: Proxy a) = setDac
+        | otherwise                     = mempty
 
       withAdc
-        | hasJackConnections opt' = setAdcBy "null"
-        | hasInputs a             = setAdc
-        | otherwise               = mempty
+        | hasJackConnections opt'      = setAdcBy "null"
+        | hasInputs (Proxy :: Proxy a) = setAdc
+        | otherwise                    = mempty
 
 -- | Output to dac with virtual midi keyboard.
 vdac :: (RenderCsd a) => a -> IO ()
@@ -275,15 +258,16 @@
 setVirtual a = a { csdFlags = (csdFlags a) { rtmidi = Just VirtualMidi, midiRT = m { midiDevice = Just "0" } } }
     where m = midiRT $ csdFlags a
 
--- | Renders to file @tmp.csd@ and invokes the csound on it.
+-- | Renders to file @tmp.csd@ in temporary directory and invokes the csound on it.
 csd :: (RenderCsd a) => a -> IO ()
 csd = csdBy setSilent
 
--- | Renders to file @tmp.csd@ and invokes the csound on it.
+-- | Renders to file @tmp.csd@ in temporary directory and invokes the csound on it.
 csdBy :: (RenderCsd a) => Options -> a -> IO ()
 csdBy options a = do
-    writeCsdBy (setSilent `mappend` options) "tmp.csd" a
-    runWithUserInterrupt (postSetup options) $ unwords ["csound tmp.csd", logTrace options]
+    fileCsd <- getTmpFile
+    writeCsdBy (setSilent `mappend` options) fileCsd a
+    runWithUserInterrupt (postSetup options) $ unwords ["csound", fileCsd, logTrace options]
 
 postSetup :: Options -> IO ()
 postSetup opt = jackConnect opt
@@ -292,13 +276,13 @@
 jackConnect opt
   | Just conns <- csdJackConnect opt = case conns of
                                          [] -> pure ()
-                                         _  -> void $ runCommand $ jackCmd conns
+                                         _  -> void $ runCommand $ Text.unpack $ jackCmd conns
   | otherwise                        = pure ()
   where
     addSleep = ("sleep 0.1; " `mappend` )
 
-    jackCmd = addSleep . L.intercalate ";" . fmap jackConn
-    jackConn (port1, port2) = unwords ["jack_connect", port1, port2]
+    jackCmd = addSleep . Text.intercalate ";" . fmap jackConn
+    jackConn (port1, port2) = Text.unwords ["jack_connect", port1, port2]
 
 hasJackConnections :: Options -> Bool
 hasJackConnections opt
@@ -349,8 +333,9 @@
 -- It invokes the Cabbage command line utility and setts all default cabbage flags.
 runCabbageBy :: (RenderCsd a) => Options -> a -> IO ()
 runCabbageBy opt' a = do
-    writeCsdBy opt "tmp.csd" a
-    runWithUserInterrupt (pure ()) $ "Cabbage tmp.csd"
+    fileCsd <- getTmpFile
+    writeCsdBy opt fileCsd a
+    runWithUserInterrupt (pure ()) $ unwords ["Cabbage", fileCsd]
     where opt = opt' `mappend` setCabbage
 
 ------------------------------
diff --git a/src/Csound/Options.hs b/src/Csound/Options.hs
--- a/src/Csound/Options.hs
+++ b/src/Csound/Options.hs
@@ -39,6 +39,8 @@
 ) where
 
 import Data.Default
+import Data.Text (Text)
+import Data.Text qualified as Text
 import Csound.Typed
 
 -- | Sets sample rate and block size
@@ -61,7 +63,7 @@
     where d' = max 0 $ min 1 $ d
 
 -- | Runs as JACK unit with given name (first argument).
-setJack :: String -> Options
+setJack :: Text -> Options
 setJack name = def { csdFlags = def { rtaudio = Just $ Jack name "input" "output" } }
 
 -- | Defines a header for a Jacko opcodes. The Jacko opcodes allow for greater flexibility
@@ -92,26 +94,26 @@
 setAdc = setAdcBy ""
 
 -- | Set's the input name of the device or file.
-setInput :: String -> Options
+setInput :: Text -> Options
 setInput a = def { csdFlags = def { audioFileOutput = def { input = Just a } } }
 
 -- | Set's the output name of the device or file.
-setOutput :: String -> Options
+setOutput :: Text -> Options
 setOutput a = def { csdFlags = def { audioFileOutput = def { output = Just a } } }
 
 -- | Provides name identifier for dac.
-setDacBy :: String -> Options
+setDacBy :: Text -> Options
 setDacBy port = setOutput name
     where name
-            | null port = "dac"
-            | otherwise = "dac:" ++ port
+            | Text.null port = "dac"
+            | otherwise = "dac:" <> port
 
 -- | Provides name identifier for adc.
-setAdcBy :: String -> Options
+setAdcBy :: Text -> Options
 setAdcBy port = setInput name
     where name
-            | null port = "adc"
-            | otherwise = "adc:" ++ port
+            | Text.null port = "adc"
+            | otherwise = "adc:" <> port
 
 -- | Sets both dac and adc.
 setThru :: Options
@@ -130,7 +132,7 @@
 -- an error occurs and the valid device numbers are printed. When using PortMidi,
 -- you can use '-Ma' to enable all devices. This is also convenient when you
 -- don't have devices as it will not generate an error.
-setMidiDevice :: String -> Options
+setMidiDevice :: Text -> Options
 setMidiDevice a = def { csdFlags = def { midiRT = def { midiDevice = Just a } } }
 
 -- | Sets midi device to all.
@@ -161,5 +163,5 @@
 -- | Defines what ports we should connect after application is launched
 --
 -- It invokes @jack_connect@ for every pair of port-names in the list.
-setJackConnect :: [(String, String)] -> Options
+setJackConnect :: [(Text, Text)] -> Options
 setJackConnect connections = def { csdJackConnect = Just connections }
diff --git a/src/Csound/Tab.hs b/src/Csound/Tab.hs
--- a/src/Csound/Tab.hs
+++ b/src/Csound/Tab.hs
@@ -5,7 +5,7 @@
     -- you are pobably not aware of the fact that for efficiency reasons Csound requires that table size is equal
     -- to power of 2 or power of two plus one which stands for guard point (you do need guard point if your intention is to read the
     -- table once but you don't need the guard point if you read the table in many cycles, then the guard point is the the first point of your table).
-    Tab, noTab,
+    Tab, noTab, isNoTab,
 
     -- * Table querries
 
@@ -193,11 +193,17 @@
 import Data.Default
 import Csound.Typed
 import Data.Maybe
+import Data.Boolean
+import Data.Text (Text)
 
 -- | The default table. It's rendered to @(-1)@ in the Csound.
 noTab :: Tab
 noTab = fromE (-1)
 
+-- | Detects that table is no tab (rebndered as -1)
+isNoTab :: Tab -> BoolD
+isNoTab = fromGE . fmap (==* (-1)) . toGE
+
 {-
 -- | Creates a new table. The Tab could be used while the instrument
 -- is playing. When the instrument is retriggered the new tab is allocated.
@@ -734,7 +740,7 @@
 
                                     -- 261.625565     25.0         1.0             1.0             2.0                 1.0             1.0 0.5 0.0 0.2
 
-plainStringTab :: String -> [Double] -> Tab
+plainStringTab :: Text -> [Double] -> Tab
 plainStringTab genId as = preStringTab def genId (ArgsPlain $ return as)
 
 -- | Creates a table of doubles (It's f-table in Csound).
diff --git a/src/Csound/Types.hs b/src/Csound/Types.hs
--- a/src/Csound/Types.hs
+++ b/src/Csound/Types.hs
@@ -100,6 +100,10 @@
 
     maparrayCopy, slicearrayCopy,
 
+    -- * Pure Arrays (read-only)
+    PureArr, newPureArr, readPureArr,
+    PureArrD, newPureArrD, readPureArrD,
+
     -- ** Spectral opcodes
     SpecArr,
 
@@ -117,12 +121,18 @@
 import Csound.Typed.Control
 
 -- | Gets an init-rate value from the list by index.
-atArg :: (Tuple a, Arg a) => [a] -> D -> a
-atArg as ind = guardedArg (zip (fmap (\x -> int x ==* ind) [0 .. ]) as) (head as)
+atArg :: (Tuple a) => [a] -> Sig -> a
+atArg as ind = readPureArr arr ind
+  where
+    arr = newPureArr as
+-- guardedArg (zip (fmap (\x -> sig (int x) ==* ind) [0 .. ]) as) (head as)
 
 -- | Gets an control/audio-rate value from the list by index.
 atTuple :: (Tuple a) => [a] -> Sig -> a
-atTuple as ind = guardedTuple (zip (fmap (\x -> sig (int x) ==* ind) [0 .. ]) as) (head as)
+atTuple as ind = readPureArr arr ind
+  where
+    arr = newPureArr as
+-- guardedTuple (zip (fmap (\x -> sig (int x) ==* ind) [0 .. ]) as) (head as)
 
 
 whenElseD :: BoolD -> SE () -> SE () -> SE ()
