diff --git a/csound-expression.cabal b/csound-expression.cabal
--- a/csound-expression.cabal
+++ b/csound-expression.cabal
@@ -1,5 +1,5 @@
 Name:          csound-expression
-Version:       4.1.0
+Version:       4.2.0
 Cabal-Version: >= 1.6
 License:       BSD3
 License-file:  LICENSE
@@ -41,6 +41,7 @@
     examples/Gm.hs
     examples/Tibetan.hs
     examples/Wind.hs
+    examples/Live.hs
 
     examples/Midi.hs
     examples/Events.hs
@@ -66,13 +67,21 @@
 Library
   Ghc-Options:    -Wall
   Build-Depends:
-        base >= 4, base < 5, process, data-default, Boolean >= 0.1.0,
-        csound-expression-typed >= 0.0.5.4, csound-expression-opcodes >= 0.0.1
+        base >= 4, base < 5, process, data-default, Boolean >= 0.1.0, colour >= 2.0,
+        csound-expression-typed >= 0.0.6.0, csound-expression-opcodes >= 0.0.1
   Hs-Source-Dirs:      src/
   Exposed-Modules:
         Csound.Base
 
         Csound.Air
+        Csound.Air.Wave
+        Csound.Air.Envelope
+        Csound.Air.Filter
+        Csound.Air.Wav
+        Csound.Air.Spec
+        Csound.Air.Fx
+        Csound.Air.Live
+        Csound.Air.Misc
 
         Csound.Types
         Csound.Tab
diff --git a/examples/Live.hs b/examples/Live.hs
new file mode 100644
--- /dev/null
+++ b/examples/Live.hs
@@ -0,0 +1,64 @@
+module Main where
+
+import Csound.Base
+import Csound.Sam
+
+main = main4
+
+a1 = infSig1 $ osc 220
+a2 = infSig1 $ osc 330
+a3 = infSig1 $ osc 440
+
+main1 = dac $ do
+	(g, sam) <- tog 4 [("220", a1), ("330", a2)]
+	panel g
+	mul 0.5 $ runSam 120 sam
+
+-----------------------------
+
+b1 = infSig1 $ sqr 220
+b2 = infSig1 $ sqr 330
+b3 = infSig1 $ sqr 440
+
+c1 = infSig1 $ tri 220
+c2 = infSig1 $ tri 330
+c3 = infSig1 $ tri 440
+
+main2 = dac $ do
+	(g, sam) <- live 4 ["triangle", "square"] 
+		[ c1, b1
+		, c2, b3
+		, c3, b3]
+	panel g
+	mul 0.3 $ runSam 120 sam
+
+-----------------------------
+
+main3 = dac $ do
+	(g, res) <- mixer $ fmap (\x -> mixMono (show x) (osc $ sig $ int x)) [220, 330, 440]
+	win "mixer" (600, 300) g
+	return $ mul 0.5 $ res
+
+-----------------------------
+
+run = runSam 120
+
+main4 = dac $ do
+	(g1, sam1) <- tog 4 [("220", a1), ("330", a2)]
+	(g2, sam2) <- sim 4 [("220", a1), ("330", a2)]
+	(g3, res)  <- mixer [("tog", run sam1), ("sim", run sam2)]
+	win "main" (600, 400) $ ver [sca 0.6 $ hor [g1, g2], g3]
+	return res
+
+-----------------------------
+
+main5 = dac $ do
+	(gui, fx) <- fxHor 
+		[ uiFilter False 0.5 0.5 0.5
+		, uiChorus False 0.5 0.5 0.5 0.5		
+		, uiPhaser False 0.5 0.5 0.5 0.5 0.5		
+		, uiReverb True  0.5 0.5
+		, uiGain   True  0.5 
+		]
+	win "main" (900, 400) gui
+	fx $ fromMono $ saw 110
diff --git a/src/Csound/Air.hs b/src/Csound/Air.hs
--- a/src/Csound/Air.hs
+++ b/src/Csound/Air.hs
@@ -1,975 +1,35 @@
-module Csound.Air (        
-    -- * Basic waveforms
-    -- | Basic waveforms that are used most often. A waveform function take in a time varied frequency (in Hz).
-
-    -- ** Bipolar
-    osc, oscBy, saw, isaw, pulse, sqr, tri, blosc,
-
-    -- ** Unipolar
-    unipolar, bipolar, on, uon, uosc, uoscBy, usaw, uisaw, upulse, usqr, utri, ublosc,
-
-    -- * Noise
-    rndh, urndh, rndi, urndi, white, pink,
-
-    -- * Envelopes
-
-    leg, xeg,
-
-    -- ** Relative duration
-    onIdur, lindur, expdur, linendur,
-    onDur, lindurBy, expdurBy, linendurBy,
-    once, onceBy, several, 
-    -- ** Looping envelopes
-    oscLins, oscElins, oscExps, oscEexps, oscLine, 
-    -- ** Faders
-    fadeIn, fadeOut, fades, expFadeIn, expFadeOut, expFades,
-
-    -- * Low frequency oscillators
-    Lfo, lfo,
-
-    -- * Filters
-    -- | Arguemnts are inversed to get most out of curruing. First come parameters and the last one is the signal.
-    
-    -- ** Simple filters
-    lp, hp, bp, br, alp,
-    
-    -- ** Butterworth filters
-    blp, bhp, bbp, bbr,
-
-    -- ** Specific filters
-    mlp,
-
-    -- * Sound files playback
-    
-    -- ** Stereo
-    readSnd, loopSnd, loopSndBy, 
-    readWav, loopWav, readSegWav, 
-    tempoLoopWav, tempoReadWav,
-    
-    -- ** Mono
-    readSnd1, loopSnd1, loopSndBy1, 
-    readWav1, loopWav1, readSegWav1,
-    tempoLoopWav1, tempoReadWav1,
-    
-    -- ** Read sound with RAM
-    -- 
-    -- Loads the sample in the table and plays it back from RAM. The sample should be short. The size of the table is limited.
-    -- It's up to 6 minutes for 44100 sample rate, 5 minutes for 48000 and 2.8 minutes for 96000.
-    LoopMode(..), ramSnd, ramSnd1, 
-
-    -- * Writing sound files
-    SampleFormat(..),
-    writeSigs, writeWav, writeAiff, writeWav1, writeAiff1,
-
-    -- ** Utility
-    lengthSnd, segments,
-
-    -- * Signal manipulation
-    takeSnd, delaySnd, segmentSnd, repeatSnd, toMono,
-
-    -- * Spectral functions
-    toSpec, fromSpec, mapSpec, scaleSpec, addSpec, scalePitch,
-
-    -- * Patterns
-    mean, vibrate, randomPitch, chorusPitch, resons, resonsBy, modes, dryWet,    
-
-    -- ** List functions
-    odds, evens,
-
-    -- * Widgets
-    AdsrBound(..), AdsrInit(..),
-    linAdsr, expAdsr, 
-    classicWaves,
-    masterVolume, masterVolumeKnob,
+-- | The vital tools.
+module Csound.Air (      
+    -- | The basic sound waves: pure sine, sawtooth, square, triangle, LFOs.
+    module Csound.Air.Wave,
 
-    -- Effects
-    
-    -- ** Reverbs
-    reverbsc1, rever1, rever2, reverTime,
-    smallRoom, smallHall, largeHall, magicCave,
-    smallRoom2, smallHall2, largeHall2, magicCave2,
+    -- | Envelope generators.
+    module Csound.Air.Envelope,  
 
-    -- ** Delays
-    echo, fdelay, fvdelay, fvdelays, funDelays,
+    -- | Filters
+    module Csound.Air.Filter,      
 
-    -- ** Distortion
-    distortion,
+    -- | Sound file playback
+    module Csound.Air.Wav,
 
-    -- ** Chorus
-    chorus,
+    -- | Spectral Processing
+    module Csound.Air.Spec, 
 
-    -- ** Flanger
-    flange,
+    -- | Effects: reverbs, choruses, delays etc.
+    module Csound.Air.Fx,  
 
-    -- ** Phase
-    phase1, harmPhase, powerPhase
+    -- | Widgets to make live performances.
+    module Csound.Air.Live,  
 
+    -- | Other usefull stuff.
+    module Csound.Air.Misc
 ) where
 
-import Data.List(intersperse, isSuffixOf)
-import Data.Boolean
-
-import Csound.Typed
-import Csound.Typed.Opcode hiding (display, lfo)
-import Csound.Typed.Gui
-import Csound.Control.Gui(funnyRadio)
-import Csound.Control.Evt(metroE, eventList)
-import Csound.Control.Instr(withDur, sched)
-
-import Csound.Types(Sig2)
-import Csound.Tab(sine, sines4, mp3s, wavs)
-import Csound.SigSpace(mapSig)
-
--------------------------------------------------------------------
--- waveforms
-
--- | A pure tone (sine wave).
-osc :: Sig -> Sig
-osc cps = oscil3 1 cps sine
-
--- | An oscillator with user provided waveform.
-oscBy :: Tab -> Sig -> Sig
-oscBy tb cps = oscil3 1 cps tb
-
--- unipolar waveforms
-
--- | Turns a bipolar sound (ranges from -1 to 1) to unipolar (ranges from 0 to 1)
-unipolar :: Sig -> Sig
-unipolar a = 0.5 + 0.5 * a
-
--- | Turns an unipolar sound (ranges from 0 to 1) to bipolar (ranges from -1 to 1)
-bipolar :: Sig -> Sig
-bipolar a = 2 * a - 1
-
--- | Unipolar pure tone.
-uosc :: Sig -> Sig
-uosc = unipolar . osc
-
--- | Unipolar 'Csound.Air.oscBy'.
-uoscBy :: Tab -> Sig -> Sig
-uoscBy tb = unipolar . oscBy tb
-
--- | Unipolar sawtooth.
-usaw :: Sig -> Sig
-usaw = unipolar . saw
-
--- | Unipolar integrated sawtooth.
-uisaw :: Sig -> Sig
-uisaw = unipolar . isaw
-
--- | Unipolar square wave.
-usqr :: Sig -> Sig
-usqr = unipolar . sqr
-
--- | Unipolar triangle wave.
-utri :: Sig -> Sig
-utri = unipolar . tri
-
--- | Unipolar pulse.
-upulse :: Sig -> Sig
-upulse = unipolar . pulse
-
--- | Unipolar band-limited oscillator.
-ublosc :: Tab -> Sig -> Sig
-ublosc tb = unipolar . blosc tb
-
--- rescaling
-
--- | Rescaling of the bipolar signal (-1, 1) -> (a, b)
--- 
--- > on a b biSig
-on :: Sig -> Sig -> Sig -> Sig
-on a b x = uon a b $ unipolar x 
-
--- | Rescaling of the unipolar signal (0, 1) -> (a, b)
--- 
--- > on a b uniSig
-uon :: Sig -> Sig -> Sig -> Sig
-uon a b x = a + (b - a) * x
-
---------------------------------------------------------------------------
--- noise
-
--- | Constant random signal. It updates random numbers with given frequency.
---
--- > constRnd freq 
-rndh :: Sig -> SE Sig
-rndh = randh 1
-
--- | Linear random signal. It updates random numbers with given frequency.
---
--- > rndi freq 
-rndi :: Sig -> SE Sig
-rndi = randi 1
-
--- | Unipolar @rndh@
-urndh :: Sig -> SE Sig
-urndh = fmap unipolar . rndh
-
--- | Unipolar @rndi@
-urndi :: Sig -> SE Sig
-urndi = fmap unipolar . rndi
-
--- | White noise.
-white :: SE Sig 
-white = noise 1 0
-
--- | Pink noise.
-pink :: SE Sig
-pink = pinkish 1
-
---------------------------------------------------------------------------
--- envelopes
-
--- | Linear adsr envelope generator with release
---
--- > leg attack decay sustain release
-leg :: D -> D -> D -> D -> Sig
-leg = madsr
-
--- | Exponential adsr envelope generator with release
---
--- > xeg attack decay sustain release
-xeg :: D -> D -> D -> D -> Sig
-xeg a d s r = mxadsr a d (s + 0.00001) r
-
--- | Makes time intervals relative to the note's duration. So that:
---
--- > onIdur [a, t1, b, t2, c]
---
--- becomes: 
---
--- > [a, t1 * idur, b, t2 * idur, c]
-onIdur :: [D] -> [D]
-onIdur = onDur idur
-
--- | Makes time intervals relative to the note's duration. So that:
---
--- > onDur dt [a, t1, b, t2, c]
---
--- becomes: 
---
--- > [a, t1 * dt, b, t2 * dt, c]
-onDur :: D -> [D] -> [D]
-onDur dur xs = case xs of
-    a:b:as -> a : b * dur : onDur dur as
-    _ -> xs
-
--- | The opcode 'Csound.Opcode.linseg' with time intervals 
--- relative to the total duration of the note.
-lindur :: [D] -> Sig
-lindur = linseg . onIdur
-
--- | The opcode 'Csound.Opcode.expseg' with time intervals 
--- relative to the total duration of the note.
-expdur :: [D] -> Sig
-expdur = expseg . onIdur
-
--- | The opcode 'Csound.Opcode.linseg' with time intervals 
--- relative to the total duration of the note given by the user.
-lindurBy :: D -> [D] -> Sig
-lindurBy dt = linseg . onDur dt
-
--- | The opcode 'Csound.Opcode.expseg' with time intervals 
--- relative to the total duration of the note given by the user.
-expdurBy :: D -> [D] -> Sig
-expdurBy dt = expseg . onDur dt
-
--- | The opcode 'Csound.Opcode.linen' with time intervals relative to the total duration of the note. Total time is set to the value of idur.
---
--- > linendur asig rise decay
-linendur :: Sig -> D -> D -> Sig
-linendur = linendurBy idur
-
--- | The opcode 'Csound.Opcode.linen' with time intervals relative to the total duration of the note. Total time is set to the value of
--- the first argument.
---
--- > linendurBy dt asig rise decay
-linendurBy :: D -> Sig -> D -> D -> Sig
-linendurBy dt asig ris dec = linen asig (ris * dt) dt (dec * dt)
-
-        
--- | Fades in with the given attack time.
-fadeIn :: D -> Sig
-fadeIn att = linseg [0, att, 1]
-
--- | Fades out with the given attack time.
-fadeOut :: D -> Sig
-fadeOut dec = linsegr [1] dec 0
-        
--- | Fades in by exponent with the given attack time.
-expFadeIn :: D -> Sig
-expFadeIn att = expseg [0.0001, att, 1]
-
--- | Fades out by exponent with the given attack time.
-expFadeOut :: D -> Sig
-expFadeOut dec = expsegr [1] dec 0.0001
-
--- | A combination of fade in and fade out.
---
--- > fades attackDuration decayDuration
-fades :: D -> D -> Sig
-fades att dec = fadeIn att * fadeOut dec
-
--- | A combination of exponential fade in and fade out.
---
--- > expFades attackDuration decayDuration
-expFades :: D -> D -> Sig
-expFades att dec = expFadeIn att * expFadeOut dec
-
---------------------------------------------------------------------------
--- lfo
-
--- | Low frequency oscillator
-type Lfo = Sig
-
--- | Low frequency oscillator
---
--- > lfo shape depth rate
-lfo :: (Sig -> Sig) -> Sig -> Sig -> Sig
-lfo shape depth rate = depth * shape rate
-
---------------------------------------------------------------------------
--- filters
-
--- | Low-pass filter.
---
--- > lp cutoff resonance sig
-lp :: Sig -> Sig -> Sig -> Sig
-lp cf q a = bqrez a cf q
-
--- | High-pass filter.
---
--- > hp cutoff resonance sig
-hp :: Sig -> Sig -> Sig -> Sig
-hp cf q a = bqrez a cf q `withD` 1
-
--- | Band-pass filter.
---
--- > bp cutoff resonance sig
-bp :: Sig -> Sig -> Sig -> Sig
-bp cf q a = bqrez a cf q `withD` 2
-
--- | Band-reject filter.
---
--- > br cutoff resonance sig
-br :: Sig -> Sig -> Sig -> Sig
-br cf q a = bqrez a cf q `withD` 3
-
--- | All-pass filter.
---
--- > alp cutoff resonance sig
-alp :: Sig -> Sig -> Sig -> Sig
-alp cf q a = bqrez a cf q `withD` 4
-
--- Butterworth filters
-
--- | High-pass filter.
---
--- > bhp cutoff sig
-bhp :: Sig -> Sig -> Sig
-bhp = flip buthp
-
--- | Low-pass filter.
---
--- > blp cutoff sig
-blp :: Sig -> Sig -> Sig
-blp = flip butlp
-
--- | Band-pass filter.
---
--- > bbp cutoff bandwidth sig
-bbp :: Sig -> Sig -> Sig -> Sig
-bbp freq band a = butbp a freq band
-
--- | Band-regect filter.
---
--- > bbr cutoff bandwidth sig
-bbr :: Sig -> Sig -> Sig -> Sig 
-bbr freq band a = butbr a freq band
-
-
--- | Moog's low-pass filter.
---
--- > mlp centerFrequency qResonance signal
-mlp :: Sig -> Sig -> Sig -> Sig
-mlp cf q asig = moogladder asig cf q
-
-
---------------------------------------------------------------------------
--- Signal manipulation
-
--- | Takes only given amount (in seconds) from the signal (the rest is silence).
-takeSnd :: Sigs a => D -> a -> a
-takeSnd dt asig = trigs (const $ return asig) $ eventList [(0, dt, unit)]
-
--- | Delays signals by the given amount (in seconds).
-delaySnd :: Sigs a => D -> a -> a
-delaySnd dt asig = trigs (const $ return asig) $ eventList [(dt, -1, unit)]
-
--- | Delays a signal by the first argument and takes only second argument amount
--- of signal (everything is measured in seconds).
-segmentSnd ::Sigs a => D -> D -> a -> a
-segmentSnd del dur asig = trigs (const $ return asig) $ eventList [(del, dur, unit)]
-
--- | Repeats the signal with the given period.
-repeatSnd :: Sigs a => D -> a -> a
-repeatSnd dt asig = sched (const $ return asig) $ segments dt
-
---------------------------------------------------------------------------
--- sound files playback
-
-isMp3 :: String -> Bool
-isMp3 name = ".mp3" `isSuffixOf` name
-
--- | Converts stereosignal to mono with function mean.
-toMono :: (Sig, Sig) -> Sig
-toMono (a, b) = 0.5 * a + 0.5 * b
-
--- | Length in seconds of the sound file.
-lengthSnd :: String -> D
-lengthSnd fileName
-    | isMp3 fileName	= mp3len $ text fileName
-    | otherwise			= filelen $ text fileName
-
--- | Produces repeating segments with the given time in seconds.
-segments :: D -> Evt (D, Unit)
-segments dt = withDur dt $ metroE (sig $ recip dt)
-
--- Stereo
-
--- | Reads stereo signal from the sound-file (wav or mp3 or aiff).
-readSnd :: String -> (Sig, Sig)
-readSnd fileName
-	| isMp3 fileName = mp3in (text fileName)		
-	| otherwise      = diskin2 (text fileName) 1
-
--- | Reads stereo signal from the sound-file (wav or mp3 or aiff)
--- and loops it with the given period (in seconds).
-loopSndBy :: D -> String -> (Sig, Sig)
-loopSndBy dt fileName = repeatSnd dt $ readSnd fileName
-
--- | Reads stereo signal from the sound-file (wav or mp3 or aiff)
--- and loops it with the file length.
-loopSnd :: String -> (Sig, Sig)
-loopSnd fileName = loopSndBy (lengthSnd fileName) fileName
-
--- | Reads the wav file with the given speed (if speed is 1 it's a norma playback).
--- We can use negative speed to read file in reverse.
-readWav :: Sig -> String -> (Sig, Sig)
-readWav speed fileName = diskin2 (text fileName) speed
-
--- | Reads th wav file and loops over it.
-loopWav :: Sig -> String -> (Sig, Sig)
-loopWav speed fileName = flip withDs [0, 1] $ ar2 $ diskin2 (text fileName) speed
-
--- | Reads a segment from wav file. 
-readSegWav :: D -> D -> Sig -> String -> (Sig, Sig)
-readSegWav start end speed fileName = takeSnd (end - start) $ diskin2 (text fileName) speed `withDs` [start, 1]
-
--- | Reads the wav file with the given speed (if speed is 1 it's a norma playback).
--- We can use negative speed to read file in reverse. Scales the tempo with first argument.
-tempoReadWav :: Sig -> String -> (Sig, Sig)
-tempoReadWav speed fileName = mapSig (scaleSpec (1 / abs speed)) $ diskin2 (text fileName) speed
-
--- | Reads th wav file and loops over it. Scales the tempo with first argument.
-tempoLoopWav :: Sig -> String -> (Sig, Sig)
-tempoLoopWav speed fileName = mapSig (scaleSpec (1 / abs speed)) $ flip withDs [0, 1] $ ar2 $ diskin2 (text fileName) speed
-
--- Mono
-
--- | The mono variant of the function @readSnd@.
-readSnd1 :: String -> Sig
-readSnd1 fileName 
-    | isMp3 fileName = toMono $ readSnd fileName
-    | otherwise      = diskin2 (text fileName) 1
-
--- | The mono variant of the function @loopSndBy@.
-loopSndBy1 :: D -> String -> Sig
-loopSndBy1 dt fileName = repeatSnd dt $ readSnd1 fileName
-
--- | The mono variant of the function @loopSnd@.
-loopSnd1 :: String -> Sig
-loopSnd1 fileName = loopSndBy1 (lengthSnd fileName) fileName
-
--- | The mono variant of the function @readWav@.
-readWav1 :: Sig -> String -> Sig
-readWav1 speed fileName = diskin2 (text fileName) speed
-
--- | The mono variant of the function @loopWav@.
-loopWav1 :: Sig -> String -> Sig
-loopWav1 speed fileName = flip withDs [0, 1] $ diskin2 (text fileName) speed
-
--- | Reads a segment from wav file.
-readSegWav1 :: D -> D -> Sig -> String -> Sig
-readSegWav1 start end speed fileName = takeSnd (end - start) $ diskin2 (text fileName) speed `withDs` [start, 1]
-
--- | Reads the mono wav file with the given speed (if speed is 1 it's a norma playback).
--- We can use negative speed to read file in reverse. Scales the tempo with first argument.
-tempoReadWav1 :: Sig -> String -> Sig
-tempoReadWav1 speed fileName = scaleSpec (1 / abs speed) $ readWav1 speed fileName
-
--- | Reads th mono wav file and loops over it. Scales the tempo with first argument.
-tempoLoopWav1 :: Sig -> String -> Sig
-tempoLoopWav1 speed fileName = scaleSpec (1 / abs speed) $ loopWav1 speed fileName
-
---------------------------------------------------------------------------
--- With RAM
-
-data LoopMode = Once | Loop | Bounce
-    deriving (Show, Eq, Enum)
-
--- | Loads the sample in the table. The sample should be short. The size of the table is limited.
--- It's up to 6 minutes for 
-ramSnd :: LoopMode -> Sig -> String -> Sig2
-ramSnd loopMode speed file = loscil3 1 speed t `withDs` [1, int $ fromEnum loopMode]
-    where t 
-            | isMp3 file = mp3s file 0
-            | otherwise  = wavs file 0 0
-
-ramSnd1 :: LoopMode -> Sig -> String -> Sig
-ramSnd1 loopMode speed file 
-    | isMp3 file = (\(aleft, aright) -> 0.5 * (aleft + aright)) $ loscil3 1 speed (mp3s file 0) `withDs` [1, int $ fromEnum loopMode]
-    | otherwise  = loscil3 1 speed (wavs file 0 1) `withDs` [1, int $ fromEnum loopMode]
-
---------------------------------------------------------------------------
--- writing sound files
-
--- | The sample format.
-data SampleFormat 
-    = NoHeaderFloat32       -- ^ 32-bit floating point samples without header
-    | NoHeaderInt16         -- ^ 16-bit integers without header
-    | HeaderInt16           -- ^ 16-bit integers with a header. The header type depends on the render (-o) format
-    | UlawSamples           -- ^  u-law samples with a header
-    | Int16                 -- ^ 16-bit integers with a header
-    | Int32                 -- ^ 32-bit integers with a header 
-    | Float32               -- ^ 32-bit floats with a header
-    | Uint8                 -- ^ 8-bit unsigned integers with a header
-    | Int24                 -- ^ 24-bit integers with a header
-    | Float64               -- ^ 64-bit floats with a header
-    deriving (Eq, Ord, Enum)
-
--- | Writes a sound signal to the file with the given format.
--- It supports only four formats: Wav, Aiff, Raw and Ircam.
-writeSigs :: FormatType -> SampleFormat -> String -> [Sig] -> SE ()
-writeSigs fmt sample file = fout (text file) formatToInt 
-    where 
-        formatToInt = int $ formatTypeToInt fmt * 10 + fromEnum sample
-
-        formatTypeToInt :: FormatType -> Int
-        formatTypeToInt x = case x of
-            Wav   -> 1
-            Aiff  -> 2
-            Raw   -> 3
-            Ircam -> 4
-            _     -> error $ "Format " ++ (show x) ++ " is not supported in the writeSnd."
-
--- | Writes wav files.
-writeWav :: String -> (Sig, Sig) -> SE ()
-writeWav file = writeSigs Wav Int16 file . \(a, b) -> [a, b]
-
--- | Writes aiff files.
-writeAiff :: String -> (Sig, Sig) -> SE ()
-writeAiff file = writeSigs Aiff Int16 file . \(a, b) -> [a, b]
-
--- | Writes mono signals to wav files.
-writeWav1 :: String -> Sig -> SE ()
-writeWav1 file = writeWav file . \x -> (x, x)
-
--- | Writes mono signals to aiff files.
-writeAiff1 :: String -> Sig -> SE ()
-writeAiff1 file = writeAiff file . \x -> (x, x)
-
---------------------------------------------------------------------------
--- spectral functions
-
--- | Converts signal to spectrum.
-toSpec :: Sig -> Spec
-toSpec asig = pvsanal asig 1024 256 1024 1
-
--- | Converts spectrum to signal.
-fromSpec :: Spec -> Sig
-fromSpec = pvsynth
-
--- | Applies a transformation to the spectrum of the signal.
-mapSpec :: (Spec -> Spec) -> Sig -> Sig
-mapSpec f = fromSpec . f . toSpec
-
--- | Scales all frequencies. Usefull for transposition. 
--- For example, we can transpose a signal by the given amount of semitones: 
---
--- > scaleSpec (semitone 1) asig
-scaleSpec :: Sig -> Sig -> Sig
-scaleSpec k = mapSpec $ \x -> pvscale x k
-
--- | Adds given amount of Hz to all frequencies.
---
--- > addSpec hz asig
-addSpec :: Sig -> Sig -> Sig
-addSpec hz = mapSpec $ \x -> pvshift x hz 0
-
--- | Scales frequency in semitones.
-scalePitch :: Sig -> Sig -> Sig
-scalePitch n = scaleSpec (semitone n)
-
---------------------------------------------------------------------------
--- patterns
-
--- | Selects odd elements from the list.
-odds :: [a] -> [a]
-odds as = fmap snd $ filter fst $ zip (cycle [True, False]) as 
-
--- | Selects even elements from the list.
-evens :: [a] -> [a]
-evens as 
-    | null as   = []
-    | otherwise = odds $ tail as
-
--- | Reads table once during the note length. 
-once :: Tab -> Sig
-once = onceBy idur
-
--- | Reads table once during a given period of time. 
-onceBy :: D -> Tab -> Sig
-onceBy dt tb = kr $ oscBy tb (1 / sig dt) 
-
--- | Reads table several times during the note length.  
-several :: Tab -> Sig -> Sig
-several tb rate = kr $ oscil3 1 (rate / sig idur) tb
-
--- | Loops over line segments with the given rate.
---
--- > oscLins [a, durA, b, durB, c, durC ..] cps
---
--- where 
---
--- * @a@, @b@, @c@ ... -- values
---
--- * durA, durB, durC -- durations of the segments relative to the current frequency.
-oscLins :: [D] -> Sig -> Sig
-oscLins points cps = loopseg cps 0 0 (fmap sig points) 
-
--- | Loops over equally spaced line segments with the given rate.
---
--- > oscElins [a, b, c] === oscLins [a, 1, b, 1, c]
-oscElins :: [D] -> Sig -> Sig
-oscElins points = oscLins (intersperse 1 points)
-
--- | 
---
--- > oscLine a b cps
---
--- Goes from @a@ to @b@ and back by line segments. One period is equal to @2\/cps@ so that one period is passed by @1\/cps@ seconds.
-oscLine :: D -> D -> Sig -> Sig
-oscLine a b cps = oscElins [a, b, a] (cps / 2)
-
--- | Loops over exponential segments with the given rate.
---
--- > oscLins [a, durA, typeA, b, durB, typeB, c, durC, typeC ..] cps
---
--- where 
---
--- * @a@, @b@, @c@ ... -- values
---
--- * durA, durB, durC -- durations of the segments relative to the current frequency.
---
--- * typeA, typeB, typeC, ... -- shape of the envelope. If the value is 0 then the shap eis linear; otherwise it is an concave exponential (positive type) or a convex exponential (negative type).
-oscExps :: [D] -> Sig -> Sig
-oscExps points cps = looptseg cps 0 (fmap sig points)
-
--- | Loops over equally spaced exponential segments with the given rate.
---
--- > oscLins [a, typeA, b, typeB, c, typeC ..] === oscLins [a, 1, typeA, b, 1, typeB, c, 1, typeC ..]
-oscEexps :: [D] -> Sig -> Sig
-oscEexps points = oscExps (insertOnes points)
-    where insertOnes xs = case xs of
-            a:b:as  -> a:1:b:insertOnes as
-            _       -> xs
-
--- | Mean value.
-mean :: Fractional a => [a] -> a
-mean xs = sum xs / (fromIntegral $ length xs)
-
-
--- | Adds vibrato to the sound unit. Sound units is a function that takes in a frequency. 
-vibrate :: Sig -> Sig -> (Sig -> a) -> (Sig -> a)
-vibrate vibDepth vibRate f cps = f (cps * (1 + kvib))
-    where kvib = vibDepth * kr (osc vibRate) 
-
--- | Adds a random vibrato to the sound unit. Sound units is a function that takes in a frequency. 
-randomPitch :: Sig -> Sig -> (Sig -> a) -> (Sig -> SE a)
-randomPitch rndAmp rndCps f cps = fmap go $ randh (cps * rndAmp) rndCps
-    where go krand = f (cps + krand)
-
-
--- | Chorus takes a number of copies, chorus width and wave shape.
-chorusPitch :: Int -> Sig -> (Sig -> Sig) -> Sig -> Sig
-chorusPitch n wid = phi dts
-    where
-        phi :: [Sig] -> (Sig -> Sig) -> Sig -> Sig
-        phi ks f = \cps -> mean $ fmap (f . (+ cps)) ks
-
-        dts = fmap (\x -> - wid + fromIntegral x * dt) [0 .. n-1] 
-
-        dt = 2 * wid / fromIntegral n
-
--- | Applies a resonator to the signals. A resonator is
--- a list of band pass filters. A list contains the parameters for the filters:
---
--- > [(centerFrequency, bandWidth)]
-resons :: [(Sig, Sig)] -> Sig -> Sig
-resons = resonsBy bp
-
--- | A resonator with user defined band pass filter.
--- Warning: a filter takes in a center frequency, band width and the signal.
--- The signal comes last (this order is not standard in the Csound but it's more
--- convinient to use with Haskell).
-resonsBy :: (cps -> bw -> Sig -> Sig) -> [(cps, bw)] -> Sig -> Sig
-resonsBy filt ps asig = mean $ fmap (( $ asig) . uncurry filt) ps
-
--- | Mixes dry and wet signals. 
---
--- > dryWet ratio effect asig
---
--- * @ratio@ - of dry signal to wet
---
--- * @effect@ - means to wet the signal
---
--- * @asig@ -- processed signal
-dryWet :: Sig -> (Sig -> Sig) -> Sig -> Sig
-dryWet k ef asig = k * asig + (1 - k) * ef asig
-
-
--- | Chain of mass-spring-damping filters.
---
--- > modes params baseCps exciter 
---
--- * params - a list of pairs @(resonantFrequencyRatio, filterQuality)@
---
--- * @baseCps@ - base frequency of the resonator
---
--- * exciter - an impulse that starts a resonator.
-modes :: [(Sig, Sig)] -> Sig -> Sig -> Sig
-modes = relResonsBy (\cf q asig -> mode asig cf q)
-
-relResonsBy :: (Sig -> a -> Sig -> Sig) -> [(Sig, a)] -> Sig -> Sig -> Sig
-relResonsBy resonator ms baseCps apulse = (recip normFactor * ) $ sum $ fmap (\(cf, q) -> harm cf q apulse) ms
-    where 
-        -- limit modal frequency to prevent explosions by 
-        -- skipping if the maximum value is exceeded (with a little headroom)
-        gate :: Sig -> Sig
-        gate cps = ifB (sig getSampleRate >* pi * cps) 1 0        
-
-        normFactor = sum $ fmap (gate . (* baseCps) . fst) ms
-
-                                    -- an ugly hack to make filter stable for forbidden values)
-        harm cf q x = g * resonator (1 - g + g * cps) q x
-            where cps = cf * baseCps
-                  g   = gate cps  
-
-
-
--- | Mono version of the cool reverberation opcode reverbsc.
---
--- > reverbsc1 asig feedbackLevel cutOffFreq
-reverbsc1 :: Sig -> Sig -> Sig -> Sig
-reverbsc1 x k co = 0.5 * (a + b)
-    where (a, b) = ar2 $ reverbsc x x k co
-
-
-----------------------------------------------------------------------
--- Widgets
-
-data AdsrBound = AdsrBound
-    { attBound  :: Double
-    , decBound  :: Double
-    , relBound  :: Double }
-
-data AdsrInit = AdsrInit
-    { attInit   :: Double
-    , decInit   :: Double
-    , susInit   :: Double
-    , relInit   :: Double }
-
-expEps :: Fractional a => a
-expEps = 0.00001
-
-linAdsr :: String -> 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 = 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
-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)
-    (gsus, sus) <- knob "S" (linSpan expEps 1)       (susInit inits) 
-    (grel, rel) <- knob "R" (linSpan expEps $ relBound b) (relInit inits)
-    let val   = mkAdsr (ir att) (ir dec) (ir sus) (ir rel)
-    gui <- setTitle name $ hor [gatt, gdec, gsus, grel]
-    return (gui, val)
-
--- | 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 name initVal = funnyRadio name 
-    [ ("osc", osc)
-    , ("tri", tri)
-    , ("sqr", sqr)
-    , ("saw", saw)]
-    initVal
-
--- | Slider for master volume
-masterVolume :: Source Sig
-masterVolume = slider "master" uspan 0.5
-
--- | Knob for master volume
-masterVolumeKnob :: Source Sig
-masterVolumeKnob = knob "master" uspan 0.5
-
----------------------------------------------------------------------------
--- Reverbs
-
--- | Reverb with given time.
-reverTime :: Sig -> Sig -> Sig
-reverTime dt a =  nreverb a dt 0.3 
-
--- | Mono reverb (based on reverbsc)
---
--- > rever1 feedback asig
-rever1 :: Sig -> Sig -> (Sig, Sig)
-rever1 fbk a = reverbsc a a fbk 12000
-
--- | Mono reverb (based on reverbsc)
---
--- > rever2 feedback asigLeft asigRight
-rever2 :: Sig -> Sig2 -> Sig2
-rever2 fbk (a1, a2) = (a1 + wa1, a2 + wa2)
-	where (wa1, wa2) = reverbsc a1 a2 fbk 12000
-
--- | Mono reverb for small room.
-smallRoom :: Sig -> (Sig, Sig)
-smallRoom = rever1 0.6
-
--- | Mono reverb for small hall.
-smallHall :: Sig -> (Sig, Sig)
-smallHall = rever1 0.8
-
--- | Mono reverb for large hall.
-largeHall :: Sig -> (Sig, Sig)
-largeHall = rever1 0.9
-
--- | The magic cave reverb (mono).
-magicCave :: Sig -> (Sig, Sig)
-magicCave = rever1 0.99
-
--- | Stereo reverb for small room.
-smallRoom2 :: Sig2 -> Sig2
-smallRoom2 = rever2 0.6
-
--- | Stereo reverb for small hall.
-smallHall2 :: Sig2 -> Sig2
-smallHall2 = rever2 0.8
-
--- | Stereo reverb for large hall.
-largeHall2 :: Sig2 -> Sig2
-largeHall2 = rever2 0.9
-
--- | The magic cave reverb (stereo).
-magicCave2 :: Sig2 -> Sig2
-magicCave2 = rever2 0.99
-
--- Delays
-
--- | The simplest delay with feedback. Arguments are: delay length and decay ratio.
---
--- > echo delayLength ratio
-echo :: D -> Sig -> Sig -> SE Sig
-echo len fb = fdelay len fb 1
-
--- | Delay with feedback. 
---
--- > fdelay maxDelayLength delayLength decayRatio
-fdelay :: D -> Sig -> Sig -> Sig -> SE Sig
-fdelay len = fvdelay len (sig len)
-
-
--- | Delay with feedback. 
---
--- > fdelay maxDelayLength delayLength feedbackLevel decayRatio
-fvdelay :: D -> Sig -> Sig -> Sig -> Sig -> SE Sig
-fvdelay len dt fb mx a = do
-	_ <- delayr len
-	aDel <- deltap3 dt
-	delayw $ a + fb * aDel
-	return $ a + (aDel * mx)
-
--- | Multitap delay. Arguments are: max delay length, list of pairs @(delayLength, decayRatio)@,
--- balance of mixed signal with processed signal.
---
--- > fdelay maxDelayLength  delays balance asig
-fvdelays :: D -> [(Sig, Sig)] -> Sig -> Sig -> SE Sig
-fvdelays len dtArgs mx a = funDelays len (zip dts fs) mx a
-	where 
-		(dts, fbks) = unzip dtArgs
-		fs = map (*) fbks
-
-
--- | Generic multitap delay. It's just like @fvdelays@ but instead of constant feedbackLevel 
--- it expects a function for processing a delayed signal on the tap.
---
--- > fdelay maxDelayLength  delays balance asig
-funDelays :: D -> [(Sig, Sig -> Sig)] -> Sig -> Sig -> SE Sig
-funDelays len dtArgs mx a = do
-	_ <- delayr len
-	aDels <- mapM deltap3 dts
-	delayw $ a + sum (zipWith ($) fs aDels)
-	return $ a + mx * sum aDels 
-	where (dts, fs) = unzip dtArgs
-
--- Distortion
-
--- | Distortion. 
---
--- > distort distLevel asig
-distortion :: Sig -> Sig -> Sig
-distortion pre asig = distort1 asig pre 0.5 0 0 `withD` 1
-
--- Chorus
-
--- | Chorus.
---
--- > chorus depth rate balance asig
-chorus :: Sig -> Sig -> Sig -> Sig -> SE Sig
-chorus depth rate mx asig = do
-	_ <- delayr 1.2
-	adelSig <- deltap3 (0.03 * depth * oscBy fn (3 * rate) + 0.01)
-	delayw asig
-	return $ ntrpol asig adelSig mx
-	where fn = sines4 [(0.5, 1, 180, 1)] -- U-shape parabola
-
--- Flanger
-
--- | Flanger. Lfo depth ranges in 0 to 1.
---
--- flanger lfo feedback balance asig
-flange :: Lfo -> Sig -> Sig -> Sig -> Sig
-flange alfo fbk mx asig = ntrpol asig (flanger asig ulfo fbk) mx
-	where ulfo = 0.0001 + 0.02 * unipolar alfo
-
--- Phaser
-
--- | First order phaser.
-phase1 :: Sig -> Lfo -> Sig -> Sig -> Sig -> Sig
-phase1 ord alfo fbk mx asig = ntrpol asig (phaser1 asig (20 + unipolar alfo) ord fbk) mx  
-
--- | Second order phaser. Sweeping gaps in the timbre are placed harmonicaly
-harmPhase :: Sig -> Lfo -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
-harmPhase ord alfo q sep fbk mx asig = ntrpol asig (phaser2 asig (20 + unipolar alfo) q ord 1 sep fbk) mx
-
--- | Second order phaser. Sweeping gaps in the timbre are placed by powers of the base frequency.
-powerPhase :: Sig -> Lfo -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
-powerPhase ord alfo q sep fbk mx asig = ntrpol asig (phaser2 asig (20 + unipolar alfo) q ord 2 sep fbk) mx
-
+import Csound.Air.Wave
+import Csound.Air.Envelope
+import Csound.Air.Filter
+import Csound.Air.Wav
+import Csound.Air.Spec
+import Csound.Air.Fx
+import Csound.Air.Live
+import Csound.Air.Misc
diff --git a/src/Csound/Air/Envelope.hs b/src/Csound/Air/Envelope.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Envelope.hs
@@ -0,0 +1,163 @@
+-- | Envelopes
+module Csound.Air.Envelope (
+    leg, xeg,
+    -- * Relative duration
+    onIdur, lindur, expdur, linendur,
+    onDur, lindurBy, expdurBy, linendurBy,    
+    -- * Looping envelopes
+    oscLins, oscElins, oscExps, oscEexps, oscLine, 
+    -- * Faders
+    fadeIn, fadeOut, fades, expFadeIn, expFadeOut, expFades,
+) where
+
+import Data.List(intersperse)
+
+import Csound.Typed
+import Csound.Typed.Opcode
+import Csound.Air.Misc
+
+-- | Linear adsr envelope generator with release
+--
+-- > leg attack decay sustain release
+leg :: D -> D -> D -> D -> Sig
+leg = madsr
+
+-- | Exponential adsr envelope generator with release
+--
+-- > xeg attack decay sustain release
+xeg :: D -> D -> D -> D -> Sig
+xeg a d s r = mxadsr a d (s + 0.00001) r
+
+-- | Makes time intervals relative to the note's duration. So that:
+--
+-- > onIdur [a, t1, b, t2, c]
+--
+-- becomes: 
+--
+-- > [a, t1 * idur, b, t2 * idur, c]
+onIdur :: [D] -> [D]
+onIdur = onDur idur
+
+-- | Makes time intervals relative to the note's duration. So that:
+--
+-- > onDur dt [a, t1, b, t2, c]
+--
+-- becomes: 
+--
+-- > [a, t1 * dt, b, t2 * dt, c]
+onDur :: D -> [D] -> [D]
+onDur dur xs = case xs of
+    a:b:as -> a : b * dur : onDur dur as
+    _ -> xs
+
+-- | The opcode 'Csound.Opcode.linseg' with time intervals 
+-- relative to the total duration of the note.
+lindur :: [D] -> Sig
+lindur = linseg . onIdur
+
+-- | The opcode 'Csound.Opcode.expseg' with time intervals 
+-- relative to the total duration of the note.
+expdur :: [D] -> Sig
+expdur = expseg . onIdur
+
+-- | The opcode 'Csound.Opcode.linseg' with time intervals 
+-- relative to the total duration of the note given by the user.
+lindurBy :: D -> [D] -> Sig
+lindurBy dt = linseg . onDur dt
+
+-- | The opcode 'Csound.Opcode.expseg' with time intervals 
+-- relative to the total duration of the note given by the user.
+expdurBy :: D -> [D] -> Sig
+expdurBy dt = expseg . onDur dt
+
+-- | The opcode 'Csound.Opcode.linen' with time intervals relative to the total duration of the note. Total time is set to the value of idur.
+--
+-- > linendur asig rise decay
+linendur :: Sig -> D -> D -> Sig
+linendur = linendurBy idur
+
+-- | The opcode 'Csound.Opcode.linen' with time intervals relative to the total duration of the note. Total time is set to the value of
+-- the first argument.
+--
+-- > linendurBy dt asig rise decay
+linendurBy :: D -> Sig -> D -> D -> Sig
+linendurBy dt asig ris dec = linen asig (ris * dt) dt (dec * dt)
+
+        
+-- | Fades in with the given attack time.
+fadeIn :: D -> Sig
+fadeIn att = linseg [0, att, 1]
+
+-- | Fades out with the given attack time.
+fadeOut :: D -> Sig
+fadeOut dec = linsegr [1] dec 0
+        
+-- | Fades in by exponent with the given attack time.
+expFadeIn :: D -> Sig
+expFadeIn att = expseg [0.0001, att, 1]
+
+-- | Fades out by exponent with the given attack time.
+expFadeOut :: D -> Sig
+expFadeOut dec = expsegr [1] dec 0.0001
+
+-- | A combination of fade in and fade out.
+--
+-- > fades attackDuration decayDuration
+fades :: D -> D -> Sig
+fades att dec = fadeIn att * fadeOut dec
+
+-- | A combination of exponential fade in and fade out.
+--
+-- > expFades attackDuration decayDuration
+expFades :: D -> D -> Sig
+expFades att dec = expFadeIn att * expFadeOut dec
+
+
+-- | Loops over line segments with the given rate.
+--
+-- > oscLins [a, durA, b, durB, c, durC ..] cps
+--
+-- where 
+--
+-- * @a@, @b@, @c@ ... -- values
+--
+-- * durA, durB, durC -- durations of the segments relative to the current frequency.
+oscLins :: [D] -> Sig -> Sig
+oscLins points cps = loopseg cps 0 0 (fmap sig points) 
+
+-- | Loops over equally spaced line segments with the given rate.
+--
+-- > oscElins [a, b, c] === oscLins [a, 1, b, 1, c]
+oscElins :: [D] -> Sig -> Sig
+oscElins points = oscLins (intersperse 1 points)
+
+-- | 
+--
+-- > oscLine a b cps
+--
+-- Goes from @a@ to @b@ and back by line segments. One period is equal to @2\/cps@ so that one period is passed by @1\/cps@ seconds.
+oscLine :: D -> D -> Sig -> Sig
+oscLine a b cps = oscElins [a, b, a] (cps / 2)
+
+-- | Loops over exponential segments with the given rate.
+--
+-- > oscLins [a, durA, typeA, b, durB, typeB, c, durC, typeC ..] cps
+--
+-- where 
+--
+-- * @a@, @b@, @c@ ... -- values
+--
+-- * durA, durB, durC -- durations of the segments relative to the current frequency.
+--
+-- * typeA, typeB, typeC, ... -- shape of the envelope. If the value is 0 then the shap eis linear; otherwise it is an concave exponential (positive type) or a convex exponential (negative type).
+oscExps :: [D] -> Sig -> Sig
+oscExps points cps = looptseg cps 0 (fmap sig points)
+
+-- | Loops over equally spaced exponential segments with the given rate.
+--
+-- > oscLins [a, typeA, b, typeB, c, typeC ..] === oscLins [a, 1, typeA, b, 1, typeB, c, 1, typeC ..]
+oscEexps :: [D] -> Sig -> Sig
+oscEexps points = oscExps (insertOnes points)
+    where insertOnes xs = case xs of
+            a:b:as  -> a:1:b:insertOnes as
+            _       -> xs
diff --git a/src/Csound/Air/Filter.hs b/src/Csound/Air/Filter.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Filter.hs
@@ -0,0 +1,79 @@
+-- | Filters
+module Csound.Air.Filter(
+    -- | Arguemnts are inversed to get most out of curruing. First come parameters and the last one is the signal.
+    
+    -- * Simple filters
+    lp, hp, bp, br, alp,
+    
+    -- * Butterworth filters
+    blp, bhp, bbp, bbr,
+
+    -- * Specific filters
+    mlp
+) where
+
+import Csound.Typed
+import Csound.Typed.Opcode
+
+-- | Low-pass filter.
+--
+-- > lp cutoff resonance sig
+lp :: Sig -> Sig -> Sig -> Sig
+lp cf q a = bqrez a cf q
+
+-- | High-pass filter.
+--
+-- > hp cutoff resonance sig
+hp :: Sig -> Sig -> Sig -> Sig
+hp cf q a = bqrez a cf q `withD` 1
+
+-- | Band-pass filter.
+--
+-- > bp cutoff resonance sig
+bp :: Sig -> Sig -> Sig -> Sig
+bp cf q a = bqrez a cf q `withD` 2
+
+-- | Band-reject filter.
+--
+-- > br cutoff resonance sig
+br :: Sig -> Sig -> Sig -> Sig
+br cf q a = bqrez a cf q `withD` 3
+
+-- | All-pass filter.
+--
+-- > alp cutoff resonance sig
+alp :: Sig -> Sig -> Sig -> Sig
+alp cf q a = bqrez a cf q `withD` 4
+
+-- Butterworth filters
+
+-- | High-pass filter.
+--
+-- > bhp cutoff sig
+bhp :: Sig -> Sig -> Sig
+bhp = flip buthp
+
+-- | Low-pass filter.
+--
+-- > blp cutoff sig
+blp :: Sig -> Sig -> Sig
+blp = flip butlp
+
+-- | Band-pass filter.
+--
+-- > bbp cutoff bandwidth sig
+bbp :: Sig -> Sig -> Sig -> Sig
+bbp freq band a = butbp a freq band
+
+-- | Band-regect filter.
+--
+-- > bbr cutoff bandwidth sig
+bbr :: Sig -> Sig -> Sig -> Sig 
+bbr freq band a = butbr a freq band
+
+
+-- | Moog's low-pass filter.
+--
+-- > mlp centerFrequency qResonance signal
+mlp :: Sig -> Sig -> Sig -> Sig
+mlp cf q asig = moogladder asig cf q
diff --git a/src/Csound/Air/Fx.hs b/src/Csound/Air/Fx.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Fx.hs
@@ -0,0 +1,427 @@
+-- | Effects
+module Csound.Air.Fx(    
+    -- * Reverbs
+    reverbsc1, rever1, rever2, reverTime,
+    smallRoom, smallHall, largeHall, magicCave,
+    smallRoom2, smallHall2, largeHall2, magicCave2,
+
+    -- * Delays
+    echo, fdelay, fvdelay, fvdelays, funDelays,
+
+    -- * Distortion
+    distortion,
+
+    -- * Chorus
+    chorus,
+
+    -- * Flanger
+    flange,
+
+    -- * Phase
+    phase1, harmPhase, powerPhase,
+
+    -- * Effects with unit parameters
+    fxDistort, fxDistort2, stChorus2, fxPhaser, fxPhaser2,
+    fxFlanger, fxFlanger2, analogDelay, analogDelay2, fxEcho, fxEcho2,
+    fxFilter, fxFilter2,
+    fxWhite, fxWhite2, fxPink, fxPink2, equalizer, equalizer2, eq4, eq7,
+    fxGain 
+
+) where
+
+import Csound.Typed
+import Csound.Tab(sines4, startEnds, setSize, elins)
+import Csound.Typed.Opcode
+import Csound.Types(Sig2)
+import Csound.SigSpace
+
+import Csound.Air.Wave(Lfo, unipolar, oscBy, utri, white, pink)
+import Csound.Air.Filter
+import Csound.Air.Misc(mean)
+
+-- | Mono version of the cool reverberation opcode reverbsc.
+--
+-- > reverbsc1 asig feedbackLevel cutOffFreq
+reverbsc1 :: Sig -> Sig -> Sig -> Sig
+reverbsc1 x k co = 0.5 * (a + b)
+    where (a, b) = ar2 $ reverbsc x x k co
+
+
+---------------------------------------------------------------------------
+-- Reverbs
+
+-- | Reverb with given time.
+reverTime :: Sig -> Sig -> Sig
+reverTime dt a =  nreverb a dt 0.3 
+
+-- | Mono reverb (based on reverbsc)
+--
+-- > rever1 feedback asig
+rever1 :: Sig -> Sig -> (Sig, Sig)
+rever1 fbk a = reverbsc a a fbk 12000
+
+-- | Mono reverb (based on reverbsc)
+--
+-- > rever2 feedback asigLeft asigRight
+rever2 :: Sig -> Sig2 -> Sig2
+rever2 fbk (a1, a2) = (a1 + wa1, a2 + wa2)
+    where (wa1, wa2) = reverbsc a1 a2 fbk 12000
+
+-- | Mono reverb for small room.
+smallRoom :: Sig -> (Sig, Sig)
+smallRoom = rever1 0.6
+
+-- | Mono reverb for small hall.
+smallHall :: Sig -> (Sig, Sig)
+smallHall = rever1 0.8
+
+-- | Mono reverb for large hall.
+largeHall :: Sig -> (Sig, Sig)
+largeHall = rever1 0.9
+
+-- | The magic cave reverb (mono).
+magicCave :: Sig -> (Sig, Sig)
+magicCave = rever1 0.99
+
+-- | Stereo reverb for small room.
+smallRoom2 :: Sig2 -> Sig2
+smallRoom2 = rever2 0.6
+
+-- | Stereo reverb for small hall.
+smallHall2 :: Sig2 -> Sig2
+smallHall2 = rever2 0.8
+
+-- | Stereo reverb for large hall.
+largeHall2 :: Sig2 -> Sig2
+largeHall2 = rever2 0.9
+
+-- | The magic cave reverb (stereo).
+magicCave2 :: Sig2 -> Sig2
+magicCave2 = rever2 0.99
+
+-- Delays
+
+-- | The simplest delay with feedback. Arguments are: delay length and decay ratio.
+--
+-- > echo delayLength ratio
+echo :: D -> Sig -> Sig -> SE Sig
+echo len fb = fdelay len fb 1
+
+-- | Delay with feedback. 
+--
+-- > fdelay delayLength decayRatio balance
+fdelay :: D -> Sig -> Sig -> Sig -> SE Sig
+fdelay len = fvdelay len (sig len)
+
+-- | Delay with feedback. 
+--
+-- > fdelay maxDelayLength delayLength feedback balance
+fvdelay :: D -> Sig -> Sig -> Sig -> Sig -> SE Sig
+fvdelay len dt fb mx a = do
+    _ <- delayr len
+    aDel <- deltap3 dt
+    delayw $ a + fb * aDel
+    return $ a + (aDel * mx)
+
+-- | Multitap delay. Arguments are: max delay length, list of pairs @(delayLength, decayRatio)@,
+-- balance of mixed signal with processed signal.
+--
+-- > fdelay maxDelayLength  delays balance asig
+fvdelays :: D -> [(Sig, Sig)] -> Sig -> Sig -> SE Sig
+fvdelays len dtArgs mx a = funDelays len (zip dts fs) mx a
+    where 
+        (dts, fbks) = unzip dtArgs
+        fs = map (*) fbks
+
+
+-- | Generic multitap delay. It's just like @fvdelays@ but instead of constant feedbackLevel 
+-- it expects a function for processing a delayed signal on the tap.
+--
+-- > fdelay maxDelayLength  delays balance asig
+funDelays :: D -> [(Sig, Sig -> Sig)] -> Sig -> Sig -> SE Sig
+funDelays len dtArgs mx a = do
+    _ <- delayr len
+    aDels <- mapM deltap3 dts
+    delayw $ a + sum (zipWith ($) fs aDels)
+    return $ a + mx * sum aDels 
+    where (dts, fs) = unzip dtArgs
+
+-- Distortion
+
+-- | Distortion. 
+--
+-- > distort distLevel asig
+distortion :: Sig -> Sig -> Sig
+distortion pre asig = distort1 asig pre 0.5 0 0 `withD` 1
+
+-- Chorus
+
+-- | Chorus.
+--
+-- > chorus depth rate balance asig
+chorus :: Sig -> Sig -> Sig -> Sig -> SE Sig
+chorus depth rate mx asig = do
+    _ <- delayr 1.2
+    adelSig <- deltap3 (0.03 * depth * oscBy fn (3 * rate) + 0.01)
+    delayw asig
+    return $ ntrpol asig adelSig mx
+    where fn = sines4 [(0.5, 1, 180, 1)] -- U-shape parabola
+
+-- Flanger
+
+-- | Flanger. Lfo depth ranges in 0 to 1.
+--
+-- flanger lfo feedback balance asig
+flange :: Lfo -> Sig -> Sig -> Sig -> Sig
+flange alfo fbk mx asig = ntrpol asig (flanger asig ulfo fbk) mx
+    where ulfo = 0.0001 + 0.02 * unipolar alfo
+
+-- Phaser
+
+-- | First order phaser.
+phase1 :: Sig -> Lfo -> Sig -> Sig -> Sig -> Sig
+phase1 ord alfo fbk mx asig = ntrpol asig (phaser1 asig (20 + unipolar alfo) ord fbk) mx  
+
+-- | Second order phaser. Sweeping gaps in the timbre are placed harmonicaly
+harmPhase :: Sig -> Lfo -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
+harmPhase ord alfo q sep fbk mx asig = ntrpol asig (phaser2 asig (20 + unipolar alfo) q ord 1 sep fbk) mx
+
+-- | Second order phaser. Sweeping gaps in the timbre are placed by powers of the base frequency.
+powerPhase :: Sig -> Lfo -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
+powerPhase ord alfo q sep fbk mx asig = ntrpol asig (phaser2 asig (20 + unipolar alfo) q ord 2 sep fbk) mx
+
+
+-----------------------------------------------------------------
+-- new effects
+
+expScale :: Sig -> (Sig, Sig) -> Sig -> Sig
+expScale steep (min, max) a = scale (expcurve a steep) max min
+
+logScale :: Sig -> (Sig, Sig) -> Sig -> Sig
+logScale steep (min, max) a = scale (logcurve a steep) max min
+
+dryWetMix :: Sig -> (Sig, Sig)
+dryWetMix kmix = (kDry, kWet) 
+    where
+        iWet = setSize 1024 $ elins [0, 1, 1]
+        iDry = setSize 1024 $ elins [1, 1, 0]
+        kWet = kr $ table kmix iWet `withD` 1
+        kDry = kr $ table kmix iDry `withD` 1
+
+fxWet :: (Num a, SigSpace a) => Sig -> a -> a -> a
+fxWet mix ain aout = mul dry ain + mul wet aout
+    where (dry, wet) = dryWetMix mix
+
+-- Distortion 
+
+-- | Distortion
+--
+-- > fxDistort level drive tone sigIn
+fxDistort :: Sig -> Sig -> Sig -> Sig -> Sig
+fxDistort klevel kdrive ktone ain = aout * (scale klevel 0.8 0) * kGainComp1
+    where
+        aout = blp kLPF $ distort1 ain kpregain kpostgain 0 0
+
+        drive = expScale 8 (0.01, 0.4) kdrive
+        kGainComp1 = logScale 700 (5,1) ktone
+
+        kpregain = 100 * drive
+        kpostgain = 0.5 * ((1 - drive) * 0.4 + 0.6)
+
+        kLPF = logScale 700 (200, 12000) ktone
+
+-- | Stereo distortion.
+fxDistort2 :: Sig -> Sig -> Sig -> Sig2 -> Sig2
+fxDistort2 klevel kdrive ktone (al, ar) = (fx al, fx ar)
+    where fx = fxDistort klevel kdrive ktone
+
+-- Stereo chorus
+
+
+-- | Stereo chorus.
+--
+-- > stChorus2 mix rate depth width sigIn
+stChorus2 :: Sig -> Sig -> Sig -> Sig -> Sig2 -> Sig2
+stChorus2 kmix krate' kdepth kwidth (al, ar) = fxWet kmix (al, ar) (aoutL, aoutR)
+    where 
+        krate = expScale 20 (0.001, 7) krate'
+        ilfoshape = setSize 131072 $ sines4 [(1, 0.5, 0, 0.5)]
+        kporttime = linseg  [0, 0.001, 0.02]
+        kChoDepth = interp $ portk  (kdepth*0.01) kporttime
+        amodL = osciliktp   krate ilfoshape 0
+        amodR = osciliktp   krate ilfoshape (kwidth*0.5)
+        vdel mod x = vdelay x (mod * kChoDepth * 1000) (1.2 * 1000)
+        aChoL = vdel amodL al
+        aChoR = vdel amodR ar
+        aoutL = 0.6 * (aChoL + al)
+        aoutR = 0.6 * (aChoR + ar)
+
+-- Phaser
+
+-- | Phaser
+--
+-- > fxPhaser mix rate depth freq feedback sigIn
+fxPhaser :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
+fxPhaser kmix fb krate' kdepth kfreq ain = fxWet kmix ain aout
+    where       
+        krate = expScale 10 (0.01, 14) krate'
+        klfo  = kdepth * utri krate
+        aout  = phaser1 ain (cpsoct $ klfo + kfreq) 8 fb        
+
+-- | Stereo phaser.
+fxPhaser2 :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig2 -> Sig2
+fxPhaser2 kmix fb krate kdepth kfreq (al, ar) = (fx al, fx ar)
+    where fx = fxPhaser kmix fb krate kdepth kfreq  
+
+-- Flanger
+
+-- | Flanger
+--
+-- > fxFlanger mix feedback rate depth delay sigIn
+fxFlanger :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig -> Sig
+fxFlanger kmix kfback krate' kdepth kdelay' ain = fxWet kmix ain aout
+    where
+        krate = expScale 50 (0.001, 14) krate'
+        kdelay = expScale 200 (0.0001, 0.1) kdelay'
+        ilfoshape = setSize 131072 $ sines4 [(0.5, 1, 180, 1)]
+        kporttime = linseg  [0, 0.001, 0.1]
+        adlt = interp $ portk kdelay kporttime
+        kdep = portk (kdepth*0.01) kporttime 
+        amod = oscili kdep krate ilfoshape      
+        adelsig = flanger ain (adlt + amod) kfback `withD` 1.2
+        aout = mean [ain, adelsig]
+
+-- | Stereo flanger
+fxFlanger2 :: Sig -> Sig -> Sig -> Sig -> Sig -> Sig2 -> Sig2
+fxFlanger2 kmix kfback krate kdepth kdelay  (al ,ar) = (fx al, fx ar)
+    where fx = fxFlanger kmix kfback krate kdepth kdelay
+
+-- Analog delay
+
+-- | Analog delay.
+--
+-- > analogDelay mix feedback time tone sigIn
+analogDelay :: Sig -> Sig -> Sig -> Sig -> Sig -> SE Sig
+analogDelay kmix kfback ktime  ktone'  ain = do
+    aBuffer <- delayr 5
+    atap <- deltap3 aTime
+    let atap1 = tone (clip atap 0 1) kTone
+    delayw $ ain + atap1*kfback
+    return $ ain*kDry + atap1 * kWet
+    where
+        ktone = expScale 4 (100, 12000) ktone'
+        (kDry, kWet) = dryWetMix kmix
+        kporttime = linseg [0,0.001,0.1]
+        kTime = portk   ktime  (kporttime*3)
+        kTone = portk   ktone kporttime
+        aTime = interp  kTime
+
+-- | Stereo analog delay.
+analogDelay2 :: Sig -> Sig -> Sig -> Sig -> Sig2 -> SE Sig2
+analogDelay2 kmix kfback ktime ktone  = bindSig fx
+    where fx = analogDelay kmix kfback ktime ktone 
+
+-- Filter
+
+-- | Filter effect (a pair of butterworth low and high pass filters).
+--
+-- > fxFilter lowPassfFreq highPassFreq gain 
+fxFilter :: Sig -> Sig -> Sig -> Sig -> Sig
+fxFilter kLPF' kHPF' kgain' ain = mul kgain $ app (blp kLPF) $ app (bhp kHPF) $ ain 
+    where 
+        app f = f . f
+        kLPF = scaleFreq kLPF' 
+        kHPF = scaleFreq kHPF' 
+        kgain = scale kgain' 20 0
+        scaleFreq x = expScale 4 (20, 20000) x
+
+-- | Stereo filter effect (a pair of butterworth low and high pass filters).
+fxFilter2 :: Sig -> Sig -> Sig -> Sig2 -> Sig2
+fxFilter2 kLPF kHPF kgain (al, ar) = (fx al, fx ar)
+    where fx = fxFilter kLPF kHPF kgain
+
+-- Equalizer
+
+-- | Equalizer
+--
+-- > equalizer gainsAndFrequencies gain sigIn
+equalizer :: [(Sig, Sig)] -> Sig -> Sig -> Sig
+equalizer fs gain ain0 = case fs of
+    []   -> ain
+    x:[] -> g 0 x ain
+    x:y:[] -> mean [g 1 x ain, g 2 y ain]
+    x:xs -> mean $ (g 1 x ain : ) $ (fmap (\y -> g 0 y ain) (init xs)) ++ [g 2 (last xs) ain]
+    where
+        iQ = 1
+        iEQcurve = skipNorm $ setSize 4096 $ startEnds [1/64,4096,7.9,64]
+        iGainCurve = skipNorm $ setSize 4096 $ startEnds [0.5,4096,3,4]
+        g ty (gain, freq) asig = pareq  asig freq (table gain iEQcurve `withD` 1) iQ `withD` ty
+        kgain = table gain iGainCurve `withD` 1
+        ain = kgain * ain0
+
+-- | Stereo equalizer.
+equalizer2 :: [(Sig, Sig)] -> Sig -> Sig2 -> Sig2
+equalizer2 fs gain (al, ar) = (fx al, fx ar)
+    where fx = equalizer fs gain
+
+-- | Equalizer with frequencies: 100, 200, 400, 800, 1600, 3200, 6400
+eq7 :: [Sig] -> Sig -> Sig2 -> Sig2
+eq7 gs = equalizer2 (zip gs $ fmap (100 * ) [1, 2, 4, 8, 16, 32, 64])
+
+-- | Equalizer with frequencies: 100, 400, 1600, 6400
+eq4 :: [Sig] -> Sig -> Sig2 -> Sig2
+eq4 gs = equalizer2 (zip gs $ fmap (100 * ) [1, 4, 16, 64])
+
+-- | Gain
+--
+-- > fxGain gain sigIn
+fxGain :: Sig -> Sig2 -> Sig2
+fxGain = mul
+
+
+-- Noise
+
+-- | Adds filtered white noize to the signal
+--
+-- > fxWhite lfoFreq depth sigIn
+fxWhite :: Sig -> Sig -> Sig -> SE Sig
+fxWhite freq depth ain = do
+    noise <- white
+    return $ ain + 0.5 * depth * blp cps noise
+    where cps = expScale 4 (20, 20000) freq
+
+-- | Adds filtered white noize to the stereo signal
+fxWhite2 ::Sig -> Sig -> Sig2 -> SE Sig2
+fxWhite2 freq depth = bindSig fx 
+    where fx = fxWhite freq depth
+
+-- | Adds filtered pink noize to the signal
+--
+-- > fxWhite lfoFreq depth sigIn
+fxPink :: Sig -> Sig -> Sig -> SE Sig
+fxPink freq depth ain = do
+    noise <- pink
+    return $ ain + 0.5 * depth * blp cps noise
+    where cps = expScale 4 (20, 20000) freq
+
+-- | Adds filtered pink noize to the stereo signal
+fxPink2 ::Sig -> Sig -> Sig2 -> SE Sig2
+fxPink2 freq depth = bindSig fx 
+    where fx = fxPink freq depth
+
+-- Echo
+
+-- | Simplified delay
+--
+-- > fxEcho maxDelayLength delTime feedback sigIn
+fxEcho :: D -> Sig -> Sig -> Sig -> SE Sig
+fxEcho maxLen ktime fback = fvdelay (5 * maxLen) (sig maxLen * 0.95 * kTime) fback 1  
+    where
+        kporttime = linseg [0,0.001,0.1]
+        kTime = portk   ktime  (kporttime*3)
+
+-- | Simplified stereo delay.
+fxEcho2 :: D -> Sig -> Sig -> Sig2 -> SE Sig2
+fxEcho2 maxLen ktime fback = bindSig fx
+    where fx = fxEcho maxLen ktime fback
+
diff --git a/src/Csound/Air/Live.hs b/src/Csound/Air/Live.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Live.hs
@@ -0,0 +1,356 @@
+{-# Language TypeSynonymInstances, FlexibleInstances #-}
+-- | UIs for live performances
+module Csound.Air.Live (
+    -- * Mixer
+    mixer, hmixer, mixMono,
+
+    -- * Effects
+    FxFun, FxUI(..), fxBox,
+    fxColor, fxVer, fxHor, fxSca, fxApp,
+
+    -- ** Fx units
+    uiDistort, uiChorus, uiFlanger, uiPhaser, uiDelay, uiEcho,
+    uiFilter, uiReverb, uiGain, uiWhite, uiPink, uiFx, uiRoom,
+    uiHall, uiCave, uiSig, uiMix,
+
+     -- * Static widgets
+    AdsrBound(..), AdsrInit(..),
+    linAdsr, expAdsr, 
+    classicWaves,
+    masterVolume, masterVolumeKnob
+) where
+
+import Control.Monad
+
+import Data.Colour
+import Data.Boolean
+import qualified Data.Colour.Names as C
+
+import Csound.Typed
+import Csound.Typed.Gui
+import Csound.Control.Gui(funnyRadio, mapSource)
+import Csound.Typed.Opcode hiding (space)
+import Csound.Types(Sig2)
+import Csound.SigSpace
+import Csound.Air.Wave
+import Csound.Air.Fx
+import Csound.Air.Misc
+
+----------------------------------------------------------------------
+-- mixer
+
+-- | The stereo signal processing function.
+type FxFun = Sig2 -> SE Sig2
+
+instance SigSpace FxFun where
+    mapSig f g = fmap (mapSig f) . g 
+
+
+-- | Widget that represents a mixer.
+mixer :: [(String, SE Sig2)] -> Source Sig2
+mixer = genMixer (ver, hor)
+
+-- | Widget that represents a mixer with horizontal grouping of elements.
+hmixer :: [(String, SE Sig2)] -> Source Sig2
+hmixer = genMixer (hor, ver)
+
+genMixer :: ([Gui] -> Gui, [Gui] -> Gui) -> [(String, SE Sig2)] -> Source Sig2
+genMixer (parentGui, childGui) as = source $ do
+    gTags <- mapM box names
+    (gs, vols) <- fmap unzip $ mapM (const $ defSlider "") names
+    (gMutes, mutes) <- fmap unzip $ mapM (const $ toggleSig "" False) names
+
+    gMasterTag <- box "master"
+    (gMaster, masterVol) <- defSlider ""
+    (gMasterMute, masterMute) <- toggleSig "" False 
+    let g = parentGui $ zipWith3 (\tag slid mute -> childGui [sca 0.8 tag, sca 8 slid, sca 1.1 mute]) 
+                        (gMasterTag : gTags) (gMaster : gs) (gMasterMute : gMutes)
+        muteVols = zipWith appMute mutes vols
+        masterMuteVol = appMute masterMute masterVol
+    res <- mul masterMuteVol $ mean $ zipWith mul muteVols sigs
+    return (g, res)
+    where 
+        (names, sigs) = unzip as
+        appMute mute vol = (port (1 - mute) 0.05) * vol
+
+-- | Transforms the mono signal to the stereo input
+-- for the mixer widget.
+mixMono :: String -> Sig -> (String, SE Sig2)
+mixMono name asig = (name, return (asig, asig))
+
+defSlider :: String -> Source Sig
+defSlider tag = slider tag (linSpan 0 1) 0.5
+
+----------------------------------------------------------------------
+-- effects
+
+class FxUI a where
+    applyFxArgs :: a -> [Sig] -> Sig2 -> SE Sig2
+    arityFx :: a -> Int
+
+instance FxUI (Sig2 -> Sig2) where
+    applyFxArgs f _ x = return $ f x
+    arityFx = const 0
+
+instance FxUI FxFun where
+    applyFxArgs f _ x = f x
+    arityFx = const 0
+
+instance FxUI a => FxUI (Sig -> a) where
+    applyFxArgs f (a:as) x = applyFxArgs (f a) as x
+    arityFx f = 1 + arityFx (proxy f)
+        where 
+            proxy :: (a -> b) -> b
+            proxy _ = undefined
+
+-- | Creates a widget that represents a stereo signal processing function.
+-- The parameters of the widget are updated with sliders.
+-- For example let's create a simple gain widget. It can be encoded like this:
+--
+-- > uiGain :: Bool -> Double -> Source FxFun
+-- > uiGain isOn gain = fxBox "Gain" fx isOn [("gain", gain)]
+-- >    where 
+-- >        fx :: Sig -> Sig2 -> Sig2
+-- >        fx = mul
+--
+-- Let's look at the arguments of the function
+--
+-- > fxBox name fx isOn args
+--
+-- * @name@ -- is the name of the widget
+--
+-- * @fx@ -- is signal processing function (see the class @FxUI@). 
+--
+-- * @isOn@ -- whether widget in the active state
+-- 
+-- * @args@ -- list of initial values for arguments and names of the arguments.
+--
+-- 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 :: FxUI a => String -> a -> Bool -> [(String, Double)] -> Source FxFun
+fxBox name fx onOff args = source $ do
+    (gOff0, off) <- toggleSig name onOff
+    let gOff = setFontSize 25 gOff0
+    offRef <- newGlobalSERef (0 :: Sig)
+    writeSERef offRef off
+    let (names, initVals) = unzip $ take (arityFx fx) args  
+    (gs, as)  <- fmap unzip $ mapM (\(name, initVal) -> slider name (linSpan 0 1) initVal) $ zip names initVals 
+    let f x = do
+        ref <- newSERef (0 :: Sig, 0 :: Sig)
+        goff <- readSERef offRef
+        writeSERef ref x        
+        when1 (goff ==* 1) $ do
+            x2 <- readSERef ref
+            writeSERef ref =<< applyFxArgs fx as x2
+        res <- readSERef ref        
+        return res  
+    let gui = setBorder UpBoxBorder $ go (length names) gOff gs
+    return (gui, f)
+    where 
+        go n gOff gs
+            | n == 0 = gOff
+            | n < 4  = f (gs ++ replicate (4 - n) space)
+            | otherwise = f gs
+            where f xs = uiGroupGui gOff (ver xs)
+
+uiGroupGui :: Gui -> Gui -> Gui 
+uiGroupGui a b =ver [sca 1.7 a, sca 8 b]
+
+sourceColor2 :: Color -> Source a -> Source a
+sourceColor2 col a = source $ do
+    (g, x) <- a
+    return (setColor2 col g, x)
+
+-- | Colors the source widgets.
+fxColor :: Color -> Source a -> Source a
+fxColor = sourceColor2
+
+-- combine effects
+
+fxGroup :: ([Gui] -> Gui) -> [Source FxFun] -> Source FxFun
+fxGroup guiGroup as = do
+    (gs, fs) <- fmap unzip $ sequence as    
+    return (guiGroup gs, foldl (\a b -> a >=> b) return fs)
+
+-- | Scales the gui for signal processing widgets.
+fxSca :: Double -> Source FxFun -> Source FxFun
+fxSca d a = fxGroup (\xs -> sca d $ head xs) [a]
+
+-- | Groups the signal processing widgets. 
+-- The functions are composed the visuals are
+-- grouped  horizontaly.
+fxHor :: [Source FxFun] -> Source FxFun
+fxHor = fxGroup hor
+
+-- | Groups the signal processing widgets. 
+-- The functions are composed the visuals are
+-- grouped  verticaly.
+fxVer :: [Source FxFun] -> Source FxFun
+fxVer = fxGroup ver
+
+-- | Applies a function to a signal processing function.
+fxApp :: FxFun -> Source FxFun -> Source FxFun 
+fxApp f = mapSource (>=> f)
+
+-- | The distortion widget. The arguments are
+--
+-- > uiDistort isOn levelOfDistortion drive tone
+uiDistort :: Bool -> Double -> Double -> Double -> Source FxFun
+uiDistort isOn level drive tone = sourceColor2 C.red $ fxBox "Distortion" fxDistort2 isOn 
+    [("level", level), ("drive", drive), ("tone", tone)]
+
+-- | The chorus widget. The arguments are
+--
+-- > uiChorus isOn mix rate depth width 
+uiChorus :: Bool -> Double -> Double -> Double -> Double -> Source FxFun
+uiChorus isOn mix rate depth width = sourceColor2 C.coral $ fxBox "Chorus" stChorus2 isOn
+    [("mix",mix), ("rate",rate), ("depth",depth), ("width",width)]
+
+-- | The flanger widget. The arguments are
+--
+-- > uiFlanger isOn mix feedback rate depth delay
+uiFlanger :: Bool -> Double -> Double -> Double -> Double -> Double -> Source FxFun
+uiFlanger isOn mix fback rate depth delay = sourceColor2 C.indigo $ fxBox "Flanger" fxFlanger2 isOn
+    [("mix", mix), ("fback", fback), ("rate",rate), ("depth",depth), ("delay",delay)]   
+
+-- | The phaser widget. The arguments are
+--
+-- > uiPhaser isOn mix feedback rate depth frequency
+uiPhaser :: Bool -> Double -> Double -> Double -> Double -> Double -> Source FxFun
+uiPhaser isOn mix fback rate depth freq = sourceColor2 C.orange $ fxBox "Phaser" fxPhaser2 isOn
+    [("mix", mix), ("fback", fback), ("rate",rate), ("depth",depth), ("freq", freq)]
+
+-- | The delay widget. The arguments are
+--
+-- > uiDelay isOn mix feedback delayTime tone
+uiDelay :: Bool -> Double -> Double -> Double -> Double -> Source FxFun
+uiDelay isOn mix fback time tone = sourceColor2 C.dodgerblue $ fxBox "Delay" analogDelay2 isOn
+    [("mix",mix), ("fback",fback), ("time",time), ("tone",tone)]
+
+-- | The simplified delay widget. The arguments are
+--
+-- > uiEcho isOn maxDelayTime delayTime feedback
+uiEcho :: Bool -> D -> Double -> Double -> Source FxFun
+uiEcho isOn maxDelTime time fback = sourceColor2 C.deepskyblue $ fxBox "Echo" (fxEcho2 maxDelTime) isOn
+    [("time", time), ("fback", fback)]
+
+-- | The pair of low and high pass filters
+--
+-- > uiFilter isOn lowPassfrequency highPassFrequency gain
+uiFilter :: Bool -> Double -> Double -> Double -> Source FxFun
+uiFilter isOn lpf hpf gain = fxBox "Filter" fxFilter2 isOn
+    [("lpf",lpf), ("hpf",hpf), ("gain",gain)]
+
+-- | The reverb widget. The arguments are:
+--
+-- > uiReverb mix depth
+uiReverb :: Bool -> Double -> Double -> Source FxFun
+uiReverb isOn mix depth = sourceColor2 C.forestgreen $ fxBox "Reverb" (\mix depth asig -> mul (1 - mix) asig + mul mix (rever2 depth asig)) isOn
+    [("mix", mix), ("depth", depth)]
+
+-- | The gain widget. The arguments are
+--
+-- > uiGain isOn amountOfGain
+uiGain :: Bool -> Double -> Source FxFun
+uiGain isOn gain = sourceColor2 C.black $ fxBox "Gain" fxGain isOn [("gain", gain)]
+
+-- | The filtered white noize widget. The arguments are
+--
+-- > uiWhite isOn centerFreqOfFilter amountOfNoize 
+uiWhite :: Bool -> Double -> Double -> Source FxFun
+uiWhite isOn freq depth = sourceColor2 C.dimgray $ fxBox "White" fxWhite2 isOn 
+    [("freq", freq), ("depth", depth)]
+
+-- | The filtered pink noize widget. The arguments are
+--
+-- > uiPink isOn centerFreqOfFilter amountOfNoize 
+uiPink :: Bool -> Double -> Double -> Source FxFun
+uiPink isOn freq depth = sourceColor2 C.deeppink $ fxBox "Pink" fxPink2 isOn
+    [("freq", freq), ("depth", depth)]
+
+-- | The constructor for signal processing functions with no arguments (controlls).
+uiFx :: FxUI a => String -> a -> Bool -> Source FxFun
+uiFx name f isOn = fxBox name f isOn [] 
+
+-- | The reverb for room.
+uiRoom :: Bool -> Source FxFun
+uiRoom isOn = sourceColor2 C.limegreen $ uiFx "Room" smallRoom2 isOn
+
+-- | The reverb for hall.
+uiHall :: Bool -> Source FxFun
+uiHall isOn = sourceColor2 C.mediumseagreen $ uiFx "Hall" largeHall2 isOn
+
+-- | The reverb for magic cave.
+uiCave :: Bool -> Source FxFun
+uiCave isOn = sourceColor2 C.darkviolet $ uiFx "Cave" magicCave2 isOn
+
+-- | The widget for selecting a midi instrument. 
+uiMidi :: Bool -> [(String, Msg -> SE Sig2)] -> Source FxFun
+uiMidi isOn as = sourceColor2 C.forestgreen $ undefined
+
+-- | the widget for mixing in a signal to the signal.
+uiSig :: String -> Bool -> Source Sig2 -> Source FxFun
+uiSig name onOff widget = source $ do
+    (gs, asig) <- widget
+    (gOff0, off) <- toggleSig name onOff
+    let gOff = setFontSize 25 gOff0     
+        f x = return $ x + mul (portk off 0.05) asig  
+    return (setBorder UpBoxBorder $ uiGroupGui gOff gs, f)
+
+-- | A mixer widget represented as an effect.
+-- The effect sums the signals with given wieghts.
+uiMix :: Bool -> [(String, SE Sig2)] -> Source FxFun
+uiMix onOff as = sourceColor2 C.blue $ uiSig "Mix" onOff (mixer as)
+
+----------------------------------------------------------------------
+-- Widgets
+
+data AdsrBound = AdsrBound
+    { attBound  :: Double
+    , decBound  :: Double
+    , relBound  :: Double }
+
+data AdsrInit = AdsrInit
+    { attInit   :: Double
+    , decInit   :: Double
+    , susInit   :: Double
+    , relInit   :: Double }
+
+expEps :: Fractional a => a
+expEps = 0.00001
+
+linAdsr :: String -> 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 = 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
+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)
+    (gsus, sus) <- knob "S" (linSpan expEps 1)       (susInit inits) 
+    (grel, rel) <- knob "R" (linSpan expEps $ relBound b) (relInit inits)
+    let val   = mkAdsr (ir att) (ir dec) (ir sus) (ir rel)
+    gui <- setTitle name $ hor [gatt, gdec, gsus, grel]
+    return (gui, val)
+
+-- | 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 name initVal = funnyRadio name 
+    [ ("osc", osc)
+    , ("tri", tri)
+    , ("sqr", sqr)
+    , ("saw", saw)]
+    initVal
+
+-- | Slider for master volume
+masterVolume :: Source Sig
+masterVolume = slider "master" uspan 0.5
+
+-- | Knob for master volume
+masterVolumeKnob :: Source Sig
+masterVolumeKnob = knob "master" uspan 0.5
+
diff --git a/src/Csound/Air/Misc.hs b/src/Csound/Air/Misc.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Misc.hs
@@ -0,0 +1,123 @@
+-- | Patterns
+module Csound.Air.Misc(
+    mean, vibrate, randomPitch, chorusPitch, resons, resonsBy, modes, dryWet, 
+    once, onceBy, several, fromMono,
+    -- * List functions
+    odds, evens
+) where
+
+import Data.Boolean
+
+import Csound.Typed
+import Csound.Typed.Opcode
+import Csound.Air.Wave
+import Csound.Air.Filter
+
+--------------------------------------------------------------------------
+-- patterns
+
+-- | Selects odd elements from the list.
+odds :: [a] -> [a]
+odds as = fmap snd $ filter fst $ zip (cycle [True, False]) as 
+
+-- | Selects even elements from the list.
+evens :: [a] -> [a]
+evens as 
+    | null as   = []
+    | otherwise = odds $ tail as
+
+-- | Reads table once during the note length. 
+once :: Tab -> Sig
+once = onceBy idur
+
+-- | Reads table once during a given period of time. 
+onceBy :: D -> Tab -> Sig
+onceBy dt tb = kr $ oscBy tb (1 / sig dt) 
+
+-- | Reads table several times during the note length.  
+several :: Tab -> Sig -> Sig
+several tb rate = kr $ oscil3 1 (rate / sig idur) tb
+
+-- | Mean value.
+mean :: Fractional a => [a] -> a
+mean xs = sum xs / (fromIntegral $ length xs)
+
+-- | Adds vibrato to the sound unit. Sound units is a function that takes in a frequency. 
+vibrate :: Sig -> Sig -> (Sig -> a) -> (Sig -> a)
+vibrate vibDepth vibRate f cps = f (cps * (1 + kvib))
+    where kvib = vibDepth * kr (osc vibRate) 
+
+-- | Adds a random vibrato to the sound unit. Sound units is a function that takes in a frequency. 
+randomPitch :: Sig -> Sig -> (Sig -> a) -> (Sig -> SE a)
+randomPitch rndAmp rndCps f cps = fmap go $ randh (cps * rndAmp) rndCps
+    where go krand = f (cps + krand)
+
+-- | Chorus takes a number of copies, chorus width and wave shape.
+chorusPitch :: Int -> Sig -> (Sig -> Sig) -> Sig -> Sig
+chorusPitch n wid = phi dts
+    where
+        phi :: [Sig] -> (Sig -> Sig) -> Sig -> Sig
+        phi ks f = \cps -> mean $ fmap (f . (+ cps)) ks
+
+        dts = fmap (\x -> - wid + fromIntegral x * dt) [0 .. n-1] 
+
+        dt = 2 * wid / fromIntegral n
+
+
+-- | Applies a resonator to the signals. A resonator is
+-- a list of band pass filters. A list contains the parameters for the filters:
+--
+-- > [(centerFrequency, bandWidth)]
+resons :: [(Sig, Sig)] -> Sig -> Sig
+resons = resonsBy bp
+
+-- | A resonator with user defined band pass filter.
+-- Warning: a filter takes in a center frequency, band width and the signal.
+-- The signal comes last (this order is not standard in the Csound but it's more
+-- convinient to use with Haskell).
+resonsBy :: (cps -> bw -> Sig -> Sig) -> [(cps, bw)] -> Sig -> Sig
+resonsBy filt ps asig = mean $ fmap (( $ asig) . uncurry filt) ps
+
+-- | Mixes dry and wet signals. 
+--
+-- > dryWet ratio effect asig
+--
+-- * @ratio@ - of dry signal to wet
+--
+-- * @effect@ - means to wet the signal
+--
+-- * @asig@ -- processed signal
+dryWet :: Sig -> (Sig -> Sig) -> Sig -> Sig
+dryWet k ef asig = k * asig + (1 - k) * ef asig
+
+
+-- | Chain of mass-spring-damping filters.
+--
+-- > modes params baseCps exciter 
+--
+-- * params - a list of pairs @(resonantFrequencyRatio, filterQuality)@
+--
+-- * @baseCps@ - base frequency of the resonator
+--
+-- * exciter - an impulse that starts a resonator.
+modes :: [(Sig, Sig)] -> Sig -> Sig -> Sig
+modes = relResonsBy (\cf q asig -> mode asig cf q)
+
+relResonsBy :: (Sig -> a -> Sig -> Sig) -> [(Sig, a)] -> Sig -> Sig -> Sig
+relResonsBy resonator ms baseCps apulse = (recip normFactor * ) $ sum $ fmap (\(cf, q) -> harm cf q apulse) ms
+    where 
+        -- limit modal frequency to prevent explosions by 
+        -- skipping if the maximum value is exceeded (with a little headroom)
+        gate :: Sig -> Sig
+        gate cps = ifB (sig getSampleRate >* pi * cps) 1 0        
+
+        normFactor = sum $ fmap (gate . (* baseCps) . fst) ms
+
+                                    -- an ugly hack to make filter stable for forbidden values)
+        harm cf q x = g * resonator (1 - g + g * cps) q x
+            where cps = cf * baseCps
+                  g   = gate cps
+
+-- | Doubles the mono signal to get the stereo signal.
+fromMono :: Sig -> (Sig, Sig)
+fromMono a = (a, a)
diff --git a/src/Csound/Air/Spec.hs b/src/Csound/Air/Spec.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Spec.hs
@@ -0,0 +1,40 @@
+ -- | Spectral functions
+ module Csound.Air.Spec( 	
+    toSpec, fromSpec, mapSpec, scaleSpec, addSpec, scalePitch
+) where
+
+import Csound.Typed
+import Csound.Typed.Opcode
+
+--------------------------------------------------------------------------
+-- spectral functions
+
+-- | Converts signal to spectrum.
+toSpec :: Sig -> Spec
+toSpec asig = pvsanal asig 1024 256 1024 1
+
+-- | Converts spectrum to signal.
+fromSpec :: Spec -> Sig
+fromSpec = pvsynth
+
+-- | Applies a transformation to the spectrum of the signal.
+mapSpec :: (Spec -> Spec) -> Sig -> Sig
+mapSpec f = fromSpec . f . toSpec
+
+-- | Scales all frequencies. Usefull for transposition. 
+-- For example, we can transpose a signal by the given amount of semitones: 
+--
+-- > scaleSpec (semitone 1) asig
+scaleSpec :: Sig -> Sig -> Sig
+scaleSpec k = mapSpec $ \x -> pvscale x k
+
+-- | Adds given amount of Hz to all frequencies.
+--
+-- > addSpec hz asig
+addSpec :: Sig -> Sig -> Sig
+addSpec hz = mapSpec $ \x -> pvshift x hz 0
+
+-- | Scales frequency in semitones.
+scalePitch :: Sig -> Sig -> Sig
+scalePitch n = scaleSpec (semitone n)
+
diff --git a/src/Csound/Air/Wav.hs b/src/Csound/Air/Wav.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Wav.hs
@@ -0,0 +1,226 @@
+ -- | Sound file playback
+module Csound.Air.Wav(
+    -- * Stereo
+    readSnd, loopSnd, loopSndBy, 
+    readWav, loopWav, readSegWav, 
+    tempoLoopWav, tempoReadWav,
+    
+    -- * Mono
+    readSnd1, loopSnd1, loopSndBy1, 
+    readWav1, loopWav1, readSegWav1,
+    tempoLoopWav1, tempoReadWav1,
+    
+    -- * Read sound with RAM
+    -- 
+    -- Loads the sample in the table and plays it back from RAM. The sample should be short. The size of the table is limited.
+    -- It's up to 6 minutes for 44100 sample rate, 5 minutes for 48000 and 2.8 minutes for 96000.
+    LoopMode(..), ramSnd, ramSnd1, 
+
+    -- * Writing sound files
+    SampleFormat(..),
+    writeSigs, writeWav, writeAiff, writeWav1, writeAiff1,
+
+    -- * Utility
+    lengthSnd, segments,
+
+    -- * Signal manipulation
+    takeSnd, delaySnd, segmentSnd, repeatSnd, toMono
+) where
+
+import Data.List(isSuffixOf)
+
+import Csound.Typed
+import Csound.Typed.Opcode
+import Csound.Tab(mp3s, wavs)
+import Csound.Control.Instr(withDur, sched)
+
+import Csound.SigSpace(mapSig)
+import Csound.Types(Sig2)
+import Csound.Control.Evt(metroE, eventList)
+
+import Csound.Air.Spec
+
+--------------------------------------------------------------------------
+-- Signal manipulation
+
+-- | Takes only given amount (in seconds) from the signal (the rest is silence).
+takeSnd :: Sigs a => D -> a -> a
+takeSnd dt asig = trigs (const $ return asig) $ eventList [(0, dt, unit)]
+
+-- | Delays signals by the given amount (in seconds).
+delaySnd :: Sigs a => D -> a -> a
+delaySnd dt asig = trigs (const $ return asig) $ eventList [(dt, -1, unit)]
+
+-- | Delays a signal by the first argument and takes only second argument amount
+-- of signal (everything is measured in seconds).
+segmentSnd ::Sigs a => D -> D -> a -> a
+segmentSnd del dur asig = trigs (const $ return asig) $ eventList [(del, dur, unit)]
+
+-- | Repeats the signal with the given period.
+repeatSnd :: Sigs a => D -> a -> a
+repeatSnd dt asig = sched (const $ return asig) $ segments dt
+
+--------------------------------------------------------------------------
+-- sound files playback
+
+isMp3 :: String -> Bool
+isMp3 name = ".mp3" `isSuffixOf` name
+
+-- | Converts stereosignal to mono with function mean.
+toMono :: (Sig, Sig) -> Sig
+toMono (a, b) = 0.5 * a + 0.5 * b
+
+-- | Length in seconds of the sound file.
+lengthSnd :: String -> D
+lengthSnd fileName
+    | isMp3 fileName    = mp3len $ text fileName
+    | otherwise         = filelen $ text fileName
+
+-- | Produces repeating segments with the given time in seconds.
+segments :: D -> Evt (D, Unit)
+segments dt = withDur dt $ metroE (sig $ recip dt)
+
+-- Stereo
+
+-- | Reads stereo signal from the sound-file (wav or mp3 or aiff).
+readSnd :: String -> (Sig, Sig)
+readSnd fileName
+    | isMp3 fileName = mp3in (text fileName)        
+    | otherwise      = diskin2 (text fileName) 1
+
+-- | Reads stereo signal from the sound-file (wav or mp3 or aiff)
+-- and loops it with the given period (in seconds).
+loopSndBy :: D -> String -> (Sig, Sig)
+loopSndBy dt fileName = repeatSnd dt $ readSnd fileName
+
+-- | Reads stereo signal from the sound-file (wav or mp3 or aiff)
+-- and loops it with the file length.
+loopSnd :: String -> (Sig, Sig)
+loopSnd fileName = loopSndBy (lengthSnd fileName) fileName
+
+-- | Reads the wav file with the given speed (if speed is 1 it's a norma playback).
+-- We can use negative speed to read file in reverse.
+readWav :: Sig -> String -> (Sig, Sig)
+readWav speed fileName = diskin2 (text fileName) speed
+
+-- | Reads th wav file and loops over it.
+loopWav :: Sig -> String -> (Sig, Sig)
+loopWav speed fileName = flip withDs [0, 1] $ ar2 $ diskin2 (text fileName) speed
+
+-- | Reads a segment from wav file. 
+readSegWav :: D -> D -> Sig -> String -> (Sig, Sig)
+readSegWav start end speed fileName = takeSnd (end - start) $ diskin2 (text fileName) speed `withDs` [start, 1]
+
+-- | Reads the wav file with the given speed (if speed is 1 it's a norma playback).
+-- We can use negative speed to read file in reverse. Scales the tempo with first argument.
+tempoReadWav :: Sig -> String -> (Sig, Sig)
+tempoReadWav speed fileName = mapSig (scaleSpec (1 / abs speed)) $ diskin2 (text fileName) speed
+
+-- | Reads th wav file and loops over it. Scales the tempo with first argument.
+tempoLoopWav :: Sig -> String -> (Sig, Sig)
+tempoLoopWav speed fileName = mapSig (scaleSpec (1 / abs speed)) $ flip withDs [0, 1] $ ar2 $ diskin2 (text fileName) speed
+
+-- Mono
+
+-- | The mono variant of the function @readSnd@.
+readSnd1 :: String -> Sig
+readSnd1 fileName 
+    | isMp3 fileName = toMono $ readSnd fileName
+    | otherwise      = diskin2 (text fileName) 1
+
+-- | The mono variant of the function @loopSndBy@.
+loopSndBy1 :: D -> String -> Sig
+loopSndBy1 dt fileName = repeatSnd dt $ readSnd1 fileName
+
+-- | The mono variant of the function @loopSnd@.
+loopSnd1 :: String -> Sig
+loopSnd1 fileName = loopSndBy1 (lengthSnd fileName) fileName
+
+-- | The mono variant of the function @readWav@.
+readWav1 :: Sig -> String -> Sig
+readWav1 speed fileName = diskin2 (text fileName) speed
+
+-- | The mono variant of the function @loopWav@.
+loopWav1 :: Sig -> String -> Sig
+loopWav1 speed fileName = flip withDs [0, 1] $ diskin2 (text fileName) speed
+
+-- | Reads a segment from wav file.
+readSegWav1 :: D -> D -> Sig -> String -> Sig
+readSegWav1 start end speed fileName = takeSnd (end - start) $ diskin2 (text fileName) speed `withDs` [start, 1]
+
+-- | Reads the mono wav file with the given speed (if speed is 1 it's a norma playback).
+-- We can use negative speed to read file in reverse. Scales the tempo with first argument.
+tempoReadWav1 :: Sig -> String -> Sig
+tempoReadWav1 speed fileName = scaleSpec (1 / abs speed) $ readWav1 speed fileName
+
+-- | Reads th mono wav file and loops over it. Scales the tempo with first argument.
+tempoLoopWav1 :: Sig -> String -> Sig
+tempoLoopWav1 speed fileName = scaleSpec (1 / abs speed) $ loopWav1 speed fileName
+
+--------------------------------------------------------------------------
+-- With RAM
+
+data LoopMode = Once | Loop | Bounce
+    deriving (Show, Eq, Enum)
+
+-- | Loads the sample in the table. The sample should be short. The size of the table is limited.
+-- It's up to 6 minutes for 
+ramSnd :: LoopMode -> Sig -> String -> Sig2
+ramSnd loopMode speed file = loscil3 1 speed t `withDs` [1, int $ fromEnum loopMode]
+    where t 
+            | isMp3 file = mp3s file 0
+            | otherwise  = wavs file 0 0
+
+ramSnd1 :: LoopMode -> Sig -> String -> Sig
+ramSnd1 loopMode speed file 
+    | isMp3 file = (\(aleft, aright) -> 0.5 * (aleft + aright)) $ loscil3 1 speed (mp3s file 0) `withDs` [1, int $ fromEnum loopMode]
+    | otherwise  = loscil3 1 speed (wavs file 0 1) `withDs` [1, int $ fromEnum loopMode]
+
+--------------------------------------------------------------------------
+-- writing sound files
+
+-- | The sample format.
+data SampleFormat 
+    = NoHeaderFloat32       -- ^ 32-bit floating point samples without header
+    | NoHeaderInt16         -- ^ 16-bit integers without header
+    | HeaderInt16           -- ^ 16-bit integers with a header. The header type depends on the render (-o) format
+    | UlawSamples           -- ^  u-law samples with a header
+    | Int16                 -- ^ 16-bit integers with a header
+    | Int32                 -- ^ 32-bit integers with a header 
+    | Float32               -- ^ 32-bit floats with a header
+    | Uint8                 -- ^ 8-bit unsigned integers with a header
+    | Int24                 -- ^ 24-bit integers with a header
+    | Float64               -- ^ 64-bit floats with a header
+    deriving (Eq, Ord, Enum)
+
+-- | Writes a sound signal to the file with the given format.
+-- It supports only four formats: Wav, Aiff, Raw and Ircam.
+writeSigs :: FormatType -> SampleFormat -> String -> [Sig] -> SE ()
+writeSigs fmt sample file = fout (text file) formatToInt 
+    where 
+        formatToInt = int $ formatTypeToInt fmt * 10 + fromEnum sample
+
+        formatTypeToInt :: FormatType -> Int
+        formatTypeToInt x = case x of
+            Wav   -> 1
+            Aiff  -> 2
+            Raw   -> 3
+            Ircam -> 4
+            _     -> error $ "Format " ++ (show x) ++ " is not supported in the writeSnd."
+
+-- | Writes wav files.
+writeWav :: String -> (Sig, Sig) -> SE ()
+writeWav file = writeSigs Wav Int16 file . \(a, b) -> [a, b]
+
+-- | Writes aiff files.
+writeAiff :: String -> (Sig, Sig) -> SE ()
+writeAiff file = writeSigs Aiff Int16 file . \(a, b) -> [a, b]
+
+-- | Writes mono signals to wav files.
+writeWav1 :: String -> Sig -> SE ()
+writeWav1 file = writeWav file . \x -> (x, x)
+
+-- | Writes mono signals to aiff files.
+writeAiff1 :: String -> Sig -> SE ()
+writeAiff1 file = writeAiff file . \x -> (x, x)
+
diff --git a/src/Csound/Air/Wave.hs b/src/Csound/Air/Wave.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Air/Wave.hs
@@ -0,0 +1,128 @@
+-- | Basic waveforms that are used most often. 
+-- A waveform function takes in a time varied frequency (in Hz).
+module Csound.Air.Wave (
+	 -- * Bipolar
+    osc, oscBy, saw, isaw, pulse, sqr, tri, blosc,
+
+    -- * Unipolar
+    unipolar, bipolar, on, uon, uosc, uoscBy, usaw, uisaw, upulse, usqr, utri, ublosc,
+
+    -- * Noise
+    rndh, urndh, rndi, urndi, white, pink,
+
+    -- * Low frequency oscillators
+    Lfo, lfo
+) where
+
+import Csound.Typed
+import Csound.Typed.Opcode hiding (lfo)
+import Csound.Tab(sine, sines4)
+
+-- | A pure tone (sine wave).
+osc :: Sig -> Sig
+osc cps = oscil3 1 cps sine
+
+-- | An oscillator with user provided waveform.
+oscBy :: Tab -> Sig -> Sig
+oscBy tb cps = oscil3 1 cps tb
+
+-- unipolar waveforms
+
+-- | Turns a bipolar sound (ranges from -1 to 1) to unipolar (ranges from 0 to 1)
+unipolar :: Sig -> Sig
+unipolar a = 0.5 + 0.5 * a
+
+-- | Turns an unipolar sound (ranges from 0 to 1) to bipolar (ranges from -1 to 1)
+bipolar :: Sig -> Sig
+bipolar a = 2 * a - 1
+
+-- | Unipolar pure tone.
+uosc :: Sig -> Sig
+uosc = unipolar . osc
+
+-- | Unipolar 'Csound.Air.oscBy'.
+uoscBy :: Tab -> Sig -> Sig
+uoscBy tb = unipolar . oscBy tb
+
+-- | Unipolar sawtooth.
+usaw :: Sig -> Sig
+usaw = unipolar . saw
+
+-- | Unipolar integrated sawtooth.
+uisaw :: Sig -> Sig
+uisaw = unipolar . isaw
+
+-- | Unipolar square wave.
+usqr :: Sig -> Sig
+usqr = unipolar . sqr
+
+-- | Unipolar triangle wave.
+utri :: Sig -> Sig
+utri = unipolar . tri
+
+-- | Unipolar pulse.
+upulse :: Sig -> Sig
+upulse = unipolar . pulse
+
+-- | Unipolar band-limited oscillator.
+ublosc :: Tab -> Sig -> Sig
+ublosc tb = unipolar . blosc tb
+
+-- rescaling
+
+-- | Rescaling of the bipolar signal (-1, 1) -> (a, b)
+-- 
+-- > on a b biSig
+on :: Sig -> Sig -> Sig -> Sig
+on a b x = uon a b $ unipolar x 
+
+-- | Rescaling of the unipolar signal (0, 1) -> (a, b)
+-- 
+-- > on a b uniSig
+uon :: Sig -> Sig -> Sig -> Sig
+uon a b x = a + (b - a) * x
+
+--------------------------------------------------------------------------
+-- noise
+
+-- | Constant random signal. It updates random numbers with given frequency.
+--
+-- > constRnd freq 
+rndh :: Sig -> SE Sig
+rndh = randh 1
+
+-- | Linear random signal. It updates random numbers with given frequency.
+--
+-- > rndi freq 
+rndi :: Sig -> SE Sig
+rndi = randi 1
+
+-- | Unipolar @rndh@
+urndh :: Sig -> SE Sig
+urndh = fmap unipolar . rndh
+
+-- | Unipolar @rndi@
+urndi :: Sig -> SE Sig
+urndi = fmap unipolar . rndi
+
+-- | White noise.
+white :: SE Sig 
+white = noise 1 0
+
+-- | Pink noise.
+pink :: SE Sig
+pink = pinkish 1
+
+--------------------------------------------------------------------------
+-- lfo
+
+-- | Low frequency oscillator
+type Lfo = Sig
+
+-- | Low frequency oscillator
+--
+-- > lfo shape depth rate
+lfo :: (Sig -> Sig) -> Sig -> Sig -> Sig
+lfo shape depth rate = depth * shape rate
+
+
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
@@ -1,3 +1,4 @@
+{-# Language TypeSynonymInstances, FlexibleInstances #-}
 -- | GUI (Graphical User Interface) elements are handy to change 
 -- the parameters of the sound in real time. It includes sliders, 
 -- knobs, rollers, buttons and other widgets. 
@@ -49,13 +50,14 @@
     -- * Gui
     Gui, 
     Widget, Input, Output, Inner,
-    Sink, Source, Display,
-    widget, sink, source, display,
-    mapSource,
-    
+    Sink, Source, Display, SinkSource,
+    widget, sink, source, display, sinkSource,
+    mapSource, mapGuiSource, 
+    mhor, mver, msca,
+
     -- * Panels
-    panel, panels, panelBy,
-    keyPanel, keyPanels, keyPanelBy,
+    panel, win, panels, panelBy,
+    keyPanel, keyWin, keyPanels, keyPanelBy,
 
     -- * Re-exports
     module Csound.Control.Gui.Layout,
@@ -63,7 +65,7 @@
     module Csound.Control.Gui.Widget
 ) where
 
-import Control.Arrow(second)
+import Csound.Typed
 
 import Csound.Typed.Gui
 
@@ -71,7 +73,16 @@
 import Csound.Control.Gui.Props
 import Csound.Control.Gui.Widget
 
+import Csound.SigSpace(SigSpace(..))
 
--- | Maps over the value of the source-widget.
-mapSource :: (a -> b) -> Source a -> Source b
-mapSource f = fmap (second f)
+-- | Creates a window with the given name, size and content
+--
+-- > win name (width, height) gui
+win :: String -> (Int, Int) -> Gui -> SE ()
+win name (x, y) = panelBy name (Just $ Rect 0 0 x y)
+
+keyWin :: String -> (Int, Int) -> Gui -> SE ()
+keyWin name (x, y) = keyPanelBy name (Just $ Rect 0 0 x y)
+
+instance SigSpace a => SigSpace (Source a) where
+    mapSig f = mapSource (mapSig f)
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
@@ -21,6 +21,7 @@
     butBank1, butBankSig1, 
     radioButton, matrixButton, funnyRadio, funnyMatrix,
     setNumeric, meter,
+    setToggle, setToggleSig,
     -- * Transformers
     setTitle,
     -- * Keyboard
diff --git a/src/Csound/Control/SE.hs b/src/Csound/Control/SE.hs
--- a/src/Csound/Control/SE.hs
+++ b/src/Csound/Control/SE.hs
@@ -1,5 +1,5 @@
 module Csound.Control.SE(
-    SE, SERef(..), newSERef, sensorsSE, newGlobalSERef, globalSensorsSE
+    SE, SERef, writeSERef, readSERef, newSERef, sensorsSE, newGlobalSERef, globalSensorsSE
 ) where
 
 import Csound.Typed.Control
diff --git a/src/Csound/IO.hs b/src/Csound/IO.hs
--- a/src/Csound/IO.hs
+++ b/src/Csound/IO.hs
@@ -39,7 +39,7 @@
 ) where
 
 import System.Process
-import Control.Exception
+import qualified Control.Exception as E
 
 import Data.Monoid
 import Data.Default
@@ -226,10 +226,10 @@
 runWithUserInterrupt :: String -> IO ()
 runWithUserInterrupt cmd = do
     pid <- runCommand cmd
-    catch (waitForProcess pid >> return ()) (onUserInterrupt pid)
+    E.catch (waitForProcess pid >> return ()) (onUserInterrupt pid)
     where
-        onUserInterrupt :: ProcessHandle -> AsyncException -> IO ()
+        onUserInterrupt :: ProcessHandle -> E.AsyncException -> IO ()
         onUserInterrupt pid x = case x of 
-            UserInterrupt -> terminateProcess pid >> throw x
-            e             -> throw e
+            E.UserInterrupt -> terminateProcess pid >> E.throw x
+            e               -> E.throw e
 
diff --git a/src/Csound/SigSpace.hs b/src/Csound/SigSpace.hs
--- a/src/Csound/SigSpace.hs
+++ b/src/Csound/SigSpace.hs
@@ -12,7 +12,7 @@
 import Csound.Typed.Opcode(pvscross)
 
 -- | A class for easy way to process the outputs of the instruments.
-class Num a => SigSpace a where
+class SigSpace a where
     mapSig  :: (Sig -> Sig)    -> a -> a
 
 -- | A class for easy way to process the outputs of the instruments.
@@ -28,7 +28,7 @@
 -- > cfd coeff sig1 sig2
 --
 -- If coeff equals 0 then we get the first signal and if it equals 1 we get the second signal.
-cfd :: SigSpace a => Sig -> a -> a -> a
+cfd :: (Num a, SigSpace a) => Sig -> a -> a -> a
 cfd coeff a b = (1 - coeff) `mul` a + coeff `mul` b
   
 genCfds :: a -> (Sig -> a -> a -> a) -> [Sig] -> [a] -> a
@@ -40,7 +40,7 @@
 -- | Generic crossfade for n coefficients and n+1 signals.
 --
 -- > cfds coeffs sigs
-cfds :: SigSpace a => [Sig] -> [a] -> a
+cfds :: (Num a, SigSpace a) => [Sig] -> [a] -> a
 cfds = genCfds 0 cfd
 
 -- | Spectral crossfade.
@@ -52,7 +52,7 @@
 cfdsSpec = genCfds undefined cfdSpec
 
 -- | Weighted sum.
-wsum :: SigSpace a => [(Sig, a)] -> a
+wsum :: (Num a, SigSpace a) => [(Sig, a)] -> a
 wsum = sum . fmap (uncurry mul)
 
 instance SigSpace Sig   where  mapSig = id
