csound-expression 5.3.1 → 5.3.2
raw patch · 31 files changed
+662/−465 lines, 31 filesdep ~csound-expression-dynamicdep ~csound-expression-typeddep ~temporal-mediaPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: csound-expression-dynamic, csound-expression-typed, temporal-media
API changes (from Hackage documentation)
- Csound.Control.Gui: Display :: SE Gui -> Display
- Csound.Control.Gui: Sink :: SE (Gui, Output a) -> Sink a
- Csound.Control.Gui: SinkSource :: SE (Gui, Output a, Input a) -> SinkSource a
- Csound.Control.Gui: Source :: SE (Gui, Input a) -> Source a
- Csound.Control.Gui: [unDisplay] :: Display -> SE Gui
- Csound.Control.Gui: [unSinkSource] :: SinkSource a -> SE (Gui, Output a, Input a)
- Csound.Control.Gui: [unSink] :: Sink a -> SE (Gui, Output a)
- Csound.Control.Gui: [unSource] :: Source a -> SE (Gui, Input a)
- Csound.Control.Gui: newtype Display :: *
- Csound.Control.Gui: newtype Sink a :: * -> *
- Csound.Control.Gui: newtype SinkSource a :: * -> *
- Csound.Control.Gui: newtype Source a :: * -> *
+ Csound.Air.Fx.FxBox: ambiGuitar :: ThreshSig -> DelayTime -> Feedback -> ToneSig -> DriveSig -> Sig -> SE Sig
+ Csound.Air.Misc: ambiEnv :: Sig -> Sig -> SE Sig
+ Csound.Air.Misc: attackTrig :: Sig -> Sig -> SE (Evt Unit)
+ Csound.Air.Misc: attackTrigSig :: Sig -> Sig -> SE Sig
+ Csound.Air.Wave: brown :: SE Sig
+ Csound.Control.Gui: type Display = SE Gui
+ Csound.Control.Gui: type Sink a = SE (Gui, Output a)
+ Csound.Control.Gui: type SinkSource a = SE (Gui, Output a, Input a)
+ Csound.Control.Gui: type Source a = SE (Gui, Input a)
+ Csound.Control.Osc: data OscRef :: *
+ Csound.Types: getBpm :: Sig
+ Csound.Types: setBpm :: Sig -> SE ()
+ Csound.Types: syn :: Sig -> Sig
+ Csound.Types: takt :: Sig -> Sig
- Csound.Air.Fx: tapeEcho :: Int -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> Sig -> SE Sig
+ Csound.Air.Fx: tapeEcho :: D -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> Sig -> Sig
- Csound.Air.Fx.FxBox: magnus :: Sigs a => Int -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> a -> SE a
+ Csound.Air.Fx.FxBox: magnus :: Sigs a => D -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> a -> a
- Csound.Air.Sampler: charTap :: Sigs a => D -> String -> a -> a
+ Csound.Air.Sampler: charTap :: Sigs a => Sig -> String -> a -> a
- Csound.Air.Sampler: evtTap :: (Sigs a) => D -> Tick -> a -> a
+ Csound.Air.Sampler: evtTap :: (Sigs a) => Sig -> Tick -> a -> a
- Csound.Air.Sampler: midiTap :: (SigSpace a, Sigs a) => MidiChn -> D -> Int -> a -> SE a
+ Csound.Air.Sampler: midiTap :: (SigSpace a, Sigs a) => MidiChn -> Sig -> Int -> a -> SE a
- Csound.Air.Sampler: midiTapBy :: (SigSpace a, Sigs a) => MidiTrigFun a -> MidiChn -> D -> Int -> a -> SE a
+ Csound.Air.Sampler: midiTapBy :: (SigSpace a, Sigs a) => MidiTrigFun a -> MidiChn -> Sig -> Int -> a -> SE a
- Csound.Air.Sampler: syncCharTap :: Sigs a => Sig -> D -> String -> a -> a
+ Csound.Air.Sampler: syncCharTap :: Sigs a => Sig -> Sig -> String -> a -> a
- Csound.Air.Sampler: syncEvtTap :: (Sigs a) => Sig -> D -> Tick -> a -> a
+ Csound.Air.Sampler: syncEvtTap :: (Sigs a) => Sig -> Sig -> Tick -> a -> a
- Csound.Air.Seg: constDel :: Num a => D -> Seg a -> Seg a
+ Csound.Air.Seg: constDel :: Num a => Sig -> Seg a -> Seg a
- Csound.Air.Seg: constLim :: D -> Seg a -> Seg a
+ Csound.Air.Seg: constLim :: Sig -> Seg a -> Seg a
- Csound.Air.Seg: constRest :: Num a => D -> Seg a
+ Csound.Air.Seg: constRest :: Num a => Sig -> Seg a
- Csound.Air.Wav: afterSnd :: (Num b, Sigs b) => D -> b -> b -> b
+ Csound.Air.Wav: afterSnd :: (Num b, Sigs b) => Sig -> b -> b -> b
- Csound.Air.Wav: delaySnd :: Sigs a => D -> a -> a
+ Csound.Air.Wav: delaySnd :: Sigs a => Sig -> a -> a
- Csound.Air.Wav: lineSnd :: (Num a, Sigs a) => D -> [a] -> a
+ Csound.Air.Wav: lineSnd :: (Num a, Sigs a) => Sig -> [a] -> a
- Csound.Air.Wav: loopLineSnd :: (Num a, Sigs a) => D -> [a] -> a
+ Csound.Air.Wav: loopLineSnd :: (Num a, Sigs a) => Sig -> [a] -> a
- Csound.Air.Wav: loopSndBy :: D -> String -> (Sig, Sig)
+ Csound.Air.Wav: loopSndBy :: Sig -> String -> (Sig, Sig)
- Csound.Air.Wav: loopSndBy1 :: D -> String -> Sig
+ Csound.Air.Wav: loopSndBy1 :: Sig -> String -> Sig
- Csound.Air.Wav: repeatSnd :: Sigs a => D -> a -> a
+ Csound.Air.Wav: repeatSnd :: Sigs a => Sig -> a -> a
- Csound.Air.Wav: segmentSnd :: Sigs a => D -> D -> a -> a
+ Csound.Air.Wav: segmentSnd :: Sigs a => Sig -> Sig -> a -> a
- Csound.Air.Wav: segments :: D -> Evt (Sco Unit)
+ Csound.Air.Wav: segments :: Sig -> Evt (Sco Unit)
- Csound.Air.Wav: takeSnd :: Sigs a => D -> a -> a
+ Csound.Air.Wav: takeSnd :: Sigs a => Sig -> a -> a
- Csound.Control.Evt: eventList :: [(D, D, a)] -> Evt (Sco a)
+ Csound.Control.Evt: eventList :: [(Sig, Sig, a)] -> Evt (Sco a)
- Csound.Control.Instr: type Sco a = Track D a
+ Csound.Control.Instr: type Sco a = Track Sig a
- Csound.Control.Instr: withDur :: D -> Evt a -> Evt (Sco a)
+ Csound.Control.Instr: withDur :: Sig -> Evt a -> Evt (Sco a)
Files
- csound-expression.cabal +3/−3
- examples/Color.hs +31/−31
- examples/DubBass.hs +7/−7
- examples/Gui/Button.hs +3/−3
- examples/Gui/EnvelopeAndHarmonics.hs +3/−3
- examples/Gui/Harmonics.hs +2/−2
- examples/Gui/Key.hs +7/−7
- examples/Heartbeat.hs +22/−22
- examples/Live.hs +5/−5
- examples/Midi.hs +6/−6
- examples/Tibetan.hs +28/−28
- examples/Wind.hs +5/−5
- src/Csound/Air/Envelope.hs +50/−49
- src/Csound/Air/Fx.hs +5/−33
- src/Csound/Air/Fx/FxBox.hs +41/−6
- src/Csound/Air/Live.hs +20/−20
- src/Csound/Air/Looper.hs +5/−5
- src/Csound/Air/Misc.hs +131/−47
- src/Csound/Air/Sampler.hs +35/−35
- src/Csound/Air/Seg.hs +29/−29
- src/Csound/Air/Wav.hs +16/−16
- src/Csound/Air/Wave.hs +5/−1
- src/Csound/Base.hs +5/−5
- src/Csound/Control/Evt.hs +1/−1
- src/Csound/Control/Gui.hs +21/−21
- src/Csound/Control/Gui/Widget.hs +11/−11
- src/Csound/Control/Instr.hs +38/−38
- src/Csound/Control/Osc.hs +2/−2
- src/Csound/IO.hs +74/−11
- src/Csound/Options.hs +38/−12
- src/Csound/Types.hs +13/−1
csound-expression.cabal view
@@ -1,5 +1,5 @@ Name: csound-expression-Version: 5.3.1+Version: 5.3.2 Cabal-Version: >= 1.6 License: BSD3 License-file: LICENSE@@ -33,7 +33,7 @@ * Thanks a lot to all who patiently answered my questions and provided skillful solutions, encouragement and ideas: .- Iain McCurdy, Victor Lazzarini, Rory Walsh, Steven Yi, John Ffitch, Joachim Heintz, Peter Burgess, Dr. Richard Boulanger, Michael Gogins, Oeyvind Brandtsegg,+ Iain McCurdy, Victor Lazzarini, Rory Walsh, Steven Yi, John Ffitch, Jon Downing, Joachim Heintz, Peter Burgess, Dr. Richard Boulanger, Michael Gogins, Oeyvind Brandtsegg, Richard Dobson, Partev Barr Sarkissian, Dave Phillips, Guillermo Senna, Art Hunkins, Ben McAllister, Michael Rhoades, Gleb Rogozinsky, Eugene Cherny, Brian Merchant, Wolf Peuker, Hlöðver Sigurðsson, Aaron Krister Johnson, Andy Fillebrown and friends :) @@ -79,7 +79,7 @@ Ghc-Options: -Wall Build-Depends: base >= 4, base < 5, process, data-default, Boolean >= 0.1.0, colour >= 2.0, transformers >= 0.3, containers,- csound-expression-typed >= 0.2.1.0, csound-expression-dynamic >= 0.3.2, temporal-media >= 0.6.1,+ csound-expression-typed >= 0.2.2.0, csound-expression-dynamic >= 0.3.3, temporal-media >= 0.6.3, csound-expression-opcodes >= 0.0.4.0 Hs-Source-Dirs: src/ Exposed-Modules:
examples/Color.hs view
@@ -17,12 +17,12 @@ k1 = (0.1 * ) $ once $ lins [0.00001, 30, 1, 50, 0.5, 100, 0.00001] -- k1 = expseg [0.0001, 0.03, amp * 0.7, idur - 0.03, 0.001] -- * linseg [1, 0.03, 1, idur - 0.03, 3]- k10 = linseg [2.25, 0.03, 3, idur - 0.03, 2] + k10 = linseg [2.25, 0.03, 3, idur - 0.03, 2] a1 = gbuzz k1 (sig cps) k10 0 35 (sines3 [(1, 1, 90)])- a2 = reson' a1 500 50 - a3 = reson' a2 150 100 - a4 = reson' a3 3500 150 - a5 = reson' a4 3500 150 + a2 = reson' a1 500 50+ a3 = reson' a2 150 100+ a4 = reson' a3 3500 150+ a5 = reson' a4 3500 150 a6 = balance a5 a1 reson' a b c = reson a b c `withD` 1 @@ -34,19 +34,19 @@ env = linen (sig amp) rise idur dec osc' tab k ph = oscBy tab (sig $ cps * k) `withD` ph osc1 = osc' sine- osc2 = osc' $ sines [1, 0, 0.9, 0, 0.8, 0, 0.7, 0, 0.6, 0, 0.5, 0, 0.4, 0, 0.3, 0, 0.2, 0, 0.1] - asum = env * mean + osc2 = osc' $ sines [1, 0, 0.9, 0, 0.8, 0, 0.7, 0, 0.6, 0, 0.5, 0, 0.4, 0, 0.3, 0, 0.2, 0, 0.1]+ asum = env * mean [ osc1 1 0 , osc2 1.008 0.02 , osc1 0.992 0.04 , osc2 2 0.06 , osc2 1 0.08 , osc1 1 0.01 ]- kosc1 = 0.5 * once sine + kosc1 = 0.5 * once sine kosc2 = 0.5 * once sine `withD` 0.4 kosc3 = 1.0 * once sine `withD` 0.8 - afilt = sum + afilt = sum [ butbp asum kosc1 1000 , butbp asum kosc2 300 , butbp asum kosc3 20 ]@@ -55,15 +55,15 @@ blurp amp = do cps <- acps- return $ 0.1 * sig amp * osc cps + return $ 0.1 * sig amp * osc cps where dec = linseg [11, idur * 0.75, 11, idur * 0.25, 0] kgate = kr $ oscil 1 dec (elins [1, 0, 0]) anoise = noise 11000 0.99 acps = fmap (flip samphold kgate) anoise- -wind (amp, bandRise, bandDec, freqRise, freqDec, pan, winds) = ++wind (amp, bandRise, bandDec, freqRise, freqDec, pan, winds) = fmap fromRnd $ rand (sig $ amp / 400) where valu1 = 100@@ -72,19 +72,19 @@ ramp a b = linseg [a, idur, b] fromRnd a = (sig pan * aout, (1 - sig pan) * aout ) where- a2 = butbp a (ramp freqRise freqDec) (ramp bandRise bandDec) + a2 = butbp a (ramp freqRise freqDec) (ramp bandRise bandDec) a3 = butbp a2 (ramp (freqRise - valu1) (freqDec + valu2)) (ramp (bandRise + valu1) (bandDec - valu2))- + aout = (a2 + a3) * linseg [0, idur * winds, 1, idur * winde, 0] noiz (amp, cps) = fmap a2 k2- where + where k1 = linseg [1, 0.05, 100, 0.2, 100, 2, 1, idur, 1]- k2 = fmap ( `withD` 1) $ rand 500 + k2 = fmap ( `withD` 1) $ rand 500 buzz' kamp kcps = buzz kamp (sig $ kcps * cps) k1 sine- + a1 = mean $ zipWith buzz' [0.3, 1, 1] [1, 0.5, 0.501] a2 k = 0.5 * a1 * sig amp * osc k @@ -97,27 +97,27 @@ ares a = reson (a * osc (sig cps)) 100 100 `withD` 2 -ivory (amp, cps, vibRate, glisDur, cpsCoeff) = sig amp * mean +ivory (amp, cps, vibRate, glisDur, cpsCoeff) = sig amp * mean -- vibrato env amplitude env freq bias phase vibrato coeff wave [ alg (linseg [0, idur, 5]) (lincone 0 0.7 1 0.3 0) 0 0 1 sine , alg (lincone 0 0.6 6 0.4 0) (lincone 0 0.9 1 0.1 0) 0.009 0.2 0.9 (sines [10, 9 .. 1]) , alg (lincone 9 0.7 1 0.3 1) (linenIdur 0.5 0.333) 0.007 0.3 1.2 (sines [10, 0, 9, 0, 8, 0, 7, 0, 6, 0, 5])- , alg (expcone 1 0.4 3 0.6 0.02) - (expcone 0.0001 0.8 1 0.2 0.0001) 0.005 0.5 0.97 (sines [10, 10, 9, 0, 0, 0, 3, 2, 0, 0, 1]) - , alg (expcone 1 0.4 3 0.6 0.02) + , alg (expcone 1 0.4 3 0.6 0.02)+ (expcone 0.0001 0.8 1 0.2 0.0001) 0.005 0.5 0.97 (sines [10, 10, 9, 0, 0, 0, 3, 2, 0, 0, 1])+ , alg (expcone 1 0.4 3 0.6 0.02) (expdur [0.001, 0.5, 1, 0.1, 0.6, 0.2, 0.97, 0.2, 0.001]) 0.003 0.8 0.99 (sines [10, 0, 0, 0, 5, 0, 0, 0, 0, 0, 3])- , alg (expcone 4 0.91 1 0.09 1) + , alg (expcone 4 0.91 1 0.09 1) (expdur [0.001, 0.6, 1, 0.2, 0.8, 0.1, 0.98, 0.1, 0.001]) 0.001 1.3 1.4 (sines [10, 0, 0, 0, 0, 3, 1]) ] where- alg :: Sig -> Sig -> D -> D -> D -> Tab -> Sig - alg vibrEnv ampEnv cpsBias phsBias vibrCoeff wave = + alg :: Sig -> Sig -> D -> D -> D -> Tab -> Sig+ alg vibrEnv ampEnv cpsBias phsBias vibrCoeff wave = ampEnv * (oscBy wave ((sig (cps + cpsBias) + vibr) * glis) `withD` phsBias) where glis = expseg [1, glisDur, 1, idur - glisDur, cpsCoeff] vibr = vibrEnv * osc (sig $ vibRate * vibrCoeff)- + cone a x1 b x2 c = [a, x1 * idur, b, x2 * idur, c] lincone a x1 b x2 c = linseg $ cone a x1 b x2 c expcone a x1 b x2 c = expseg $ cone a x1 b x2 c@@ -126,7 +126,7 @@ -- snow flakes blue (amp, cps, lfoCps, harmNum, sweepRate) = fmap aout k1- where + where k1 = randi 1 50 k2 = lindur [0, 0.5, 1, 0.5, 0] k3 = lindur [0.005, 0.71, 0.015, 0.29, 0.01]@@ -137,18 +137,18 @@ kenv = expdur [0.001, 0.01, amp, 0.99, 0.001] aout k = gbuzz kenv (sig cps + k3) k5 ksweep k (sines3 [(1, 1, 90)]) -i2 t0 dt amp cps lfoCps harmNum sweepRate = +i2 t0 dt amp cps lfoCps harmNum sweepRate = t0 +| (dt *| temp (amp, cps, lfoCps, harmNum, sweepRate)) -blueSco = sco blue $ har +blueSco = sco blue $ har [ i2 0 4 0.5 440 23 10 0.72 , i2 0 4 0.5 330 20 6 0.66 ] -- 4pok-black (amp, cps, filterSweepStart, filterSweepEnd, bandWidth) = +black (amp, cps, filterSweepStart, filterSweepEnd, bandWidth) = fmap aout $ rand 1- where + where k1 = expdur [filterSweepStart, 1, filterSweepEnd] a1 noise = reson noise k1 (k1 / sig bandWidth) `withD` 1 k3 = expdur [0.001, 0.001, amp, 0.999, 0.001]@@ -158,7 +158,7 @@ i4 t0 dt amp cps filt0 filt1 bw = t0 +| (dt *| temp (amp, cps, filt0, filt1, bw)) -blackSco = str 1.5 $ sco black $ har +blackSco = str 1.5 $ sco black $ har [ i4 0 1 0.7 220 6000 30 10 , i4 0 1 0.7 330 8000 20 6 ]
examples/DubBass.hs view
@@ -20,15 +20,15 @@ spb = dspb dspb = 0.45 -instr (coeff, cps) = return $ wobbly (sig spb) (sig coeff) (sig $ cpspch cps)+instr (coeff, cps) = return $ wobbly spb (sig coeff) (sig $ cpspch cps) -main = dac $ mix $ str (dspb * 2) $ loopBy 2 $ sco instr $ melMap temp $ +main = dac $ mix $ str (dspb * 2) $ loopBy 2 $ sco instr $ melMap temp $ [ (2, 6.04) , (1/3, 7.04) , (2, 6.04) , (1/1.5, 7.07)- + , (2, 5.09) , (1, 6.09) , (1/1.5, 5.09)@@ -37,13 +37,13 @@ , (1, 6.04) , (1/3, 7.04) , (2, 6.04)- , (1/1.5, 7.07) - + , (1/1.5, 7.07)+ , (2, 6.09) , (1, 7.09) , (1/1.5, 6.11)- , (1/3, 6.07) - + , (1/3, 6.07)+ , (2, 6.04) , (1/3, 7.04) , (2, 6.04)
examples/Gui/Button.hs view
@@ -9,7 +9,7 @@ appGui = dac $ vlift3 f masterVolume (toggle "play" False) (button "Hi!") where f vol evt1 evt2 = vol * sum [sig1, sig2]- where + where (evtOn, evtOff) = splitToggle evt1 instr cps _ = return $ fades 0.5 0.5 * osc cps sig1 = schedUntil (instr 440) evtOn evtOff@@ -17,7 +17,7 @@ -- | Monadic style guis-monadGui = dac $ do +monadGui = dac $ do -- Let's create a toggle button with label "play". -- The toggle button emmits ones and zeros. (gbut1, evt1) <- toggle "play" False@@ -45,4 +45,4 @@ -- Sends the sum to the output scaled with given master volume. return $ vol * sum [sig1, sig2]- +
examples/Gui/EnvelopeAndHarmonics.hs view
@@ -7,14 +7,14 @@ main = dac $ do -- Creates a bank of 15 sliders. We specify the label- -- and initial values for slider (0 is minimum and 1 is maximum + -- and initial values for slider (0 is minimum and 1 is maximum -- for each slider. (gharms, ks) <- sliderBank "harmonics" (1 : replicate 14 0) -- We create an Adsr envelope (see example Envelope.hs) (gadsr, env) <- linAdsr "amplitude envelope" (AdsrBound 1 1 3) (AdsrInit 0.1 0.1 0.5 0.1) -- Creates a master volume slider (gvol, vol) <- masterVolume- (gcps, cps) <- slider "frequency" (expSpan 50 1000) 220 + (gcps, cps) <- slider "frequency" (expSpan 50 1000) 220 -- Places everything on window. Elements are aligned vertically. -- The volume slider is smaller than the ADSR-envelope. The element@@ -22,7 +22,7 @@ -- (it's short for scale) panel $ ver [sca 0.1 gvol, sca 0.1 gcps, sca 0.25 gadsr, gharms] - -- Let's create a simple instrument with the custom harmonics + -- Let's create a simple instrument with the custom harmonics -- and amplitude envelope. let instr = env * harms ks cps return $ mul vol $ sched (const $ return instr) $ withDur 1 $ metro 0.5
examples/Gui/Harmonics.hs view
@@ -1,7 +1,7 @@ -- Experiments with harmonics. module Harmonics where -import Csound.Base +import Csound.Base -- a sum of pure tones that form a hormanic series. harms :: [Sig] -> Sig -> Sig@@ -13,7 +13,7 @@ (g, ks) <- sliderBank "Harmonics" (1 : replicate 13 0) (gv, v) <- masterVolume (gcps, cps) <- slider "frequency" (expSpan 50 1000) 220- + -- A simple instrument that plays a harmonic series -- with the given coefficients. let instr = onMsg $ harms ks
examples/Gui/Key.hs view
@@ -3,16 +3,16 @@ import Csound.Base -main = dac $ do - -- a pure tone instrument that plays a single frequency +main = dac $ do+ -- a pure tone instrument that plays a single frequency let instr x = const $ return $ osc x -- triggers the instrument with frequency on the give event stream -- and holds the note wile second stream is silent. asig cps evtOn evtOff = schedUntil (instr cps) evtOn evtOff- - mean [ asig 330 (charOn 's') (charOff 's') ++ mean [ asig 330 (charOn 's') (charOff 's') , asig 440 (charOn 'a') (charOff 'a') ]- --- Due to inner limitation only one keyboard event can be --- registered at one control cycle. So if you press ++-- Due to inner limitation only one keyboard event can be+-- registered at one control cycle. So if you press -- the two buttons at the same time only one event will be registered.
examples/Heartbeat.hs view
@@ -4,7 +4,7 @@ import Csound.Base linenIdur :: Sig -> D -> D -> Sig-linenIdur a rise dec = linen a (idur * rise) idur (idur * dec) +linenIdur a rise dec = linen a (idur * rise) idur (idur * dec) -------------------------------------- @@ -14,7 +14,7 @@ kpan = 0.5 * (1 + osc (5 * sig idur)) a2 = fof a1 (a1 + sig cps) (a1 * sig amp / 50) k1 200 0.003 0.017 0.005 20 f1 f2 cps arev = reverb2 a2 5 1- a3 = 0.2 * (a2 + arev) + a3 = 0.2 * (a2 + arev) f1 = sines [1] -- SINE WAVE f2 = sines [1, 0.5, 0.3, 0.25, 0.2, 0.167, 0.14, 0.111] -- SAWTOOTH @@ -23,20 +23,20 @@ heartbeat amp = phi amp 0.0024 f12 + phi amp 0.0078 f13 where phi amp dec tab = oscili (sig amp * linseg [1, idur, dec]) 4 tab f12 = sines2 [(10, 1), (16, 1.5), (22, 2), (23, 1.5)]- f13 = sines2 [(25, 1), (29, 0.5), (32, 0.2)] + f13 = sines2 [(25, 1), (29, 0.5), (32, 0.2)] monoPluck :: D -> D -> D -> D -> Sig-monoPluck amp cps pick plk = a3 - where repluck' freq a = repluck plk (sig amp) freq (sig pick) 0.5 a +monoPluck amp cps pick plk = a3+ where repluck' freq a = repluck plk (sig amp) freq (sig pick) 0.5 a a1 = 0.5 * (- repluck' (cps - 1) (osc $ sig $ cps - 2) + repluck' (cps - 1) (osc $ sig $ cps - 2) + repluck' (cps + 1) (osc $ sig $ cps + 2)) a2 = linenIdur (a1/2) 0.2 0.8 arev = reverb2 a2 1.5 1 a3 = (a2 + 0.6 * arev) / 1.6- + chorusel amp cps rise dec = (ar1, ar2) where k1 = linen (sig amp) rise idur dec k2 = linseg [1, idur, 0]@@ -56,21 +56,21 @@ (0.25, 0, saw), (-0.8, k4, saw), (0.8, k4, f9)]- + ars = zipWith3 (\a k d -> withInits (areson a k d) (1::D)) as (k2:(k2*k3):repeat k2) (fmap (sig . double) $ [10, 20 .. 80] ++ [50, 60 .. 80])- meanArs = (/ 5.5) . sum . fmap (ars !!) + meanArs = (/ 5.5) . sum . fmap (ars !!) asig1 = meanArs [0, 3, 5, 7, 8] asig2 = meanArs [1, 2, 4, 6, 9]- asig3 = 0.5 * (ars !! 10 + ars !! 11) - + asig3 = 0.5 * (ars !! 10 + ars !! 11)+ ar1 = 0.5 * (asig1 + asig3)- ar2 = 0.5 * (asig2 + asig3) - - f9 phs = oscil 1 phs $ sines + ar2 = 0.5 * (asig2 + asig3)++ f9 phs = oscil 1 phs $ sines [ 0.28, 1, 0.74, 0.66, 0.78, 0.48, 0.05, 0.33, 0.12 , 0.08, 0.01, 0.54, 0.19, 0.08, 0.05, 0.16, 0.01- , 0.11, 0.3, 0.02, 0.2] - + , 0.11, 0.3, 0.02, 0.2]+ instr1 :: D -> Sig2 instr1 amp = (a, a) where a = 0.8 * heartbeat amp@@ -87,12 +87,12 @@ scoBeat = sco (onArg instr1) $ del 2 $ loopBy 32 $ mel [0.25 *| melTemp [0.5, 0.3], rest 1.5] -scoPluck = sco (onArg instrPluck) $ del 8 $ mel $ take n $ zipWith (\amp pan -> 0.5 *| temp (amp, pan)) +scoPluck = sco (onArg instrPluck) $ del 8 $ mel $ take n $ zipWith (\amp pan -> 0.5 *| temp (amp, pan)) (fmap double $ [0, (v/40) .. v] ++ repeat v) (cycle [0.2, 0.8]) where v = 0.6 dur = 65 n = floor $ (dur - 8)/0.5- + scoChorusel = sco (onArg instrChorusel) $ har $ unroll =<< [ (0, 15, (0.4, [7, 7.07, 6, 8], 10, 5)), (18, 17, (0.27, [6, 7, 7.07, 8.02, 8.03, 5], 9, 6)),@@ -101,13 +101,13 @@ (48, 7, (0.35, [7.05], 3.5, 3.5)), (55, 10, (0.35, [7, 8, 7.07, 6], 5, 8))] where unroll (t, dur, (amp, cps, rise, dec)) = [del t $ str dur $ temp (amp, c, rise, dec) | c <- cps]- + scoCrackle = sco (onArg instrCrackle) $ har [ str 8 $ temp 100,- del 13 $ str 5 $ temp 50] - + del 13 $ str 5 $ temp 50]+ main = dac $ mix $ har [- scoBeat, + scoBeat, scoChorusel, scoPluck, rest 0
examples/Live.hs view
@@ -25,7 +25,7 @@ c3 = infSig1 $ tri 440 main2 = dac $ do- (g, sam) <- live 4 ["triangle", "square"] + (g, sam) <- live 4 ["triangle", "square"] [ c1, b1 , c2, b3 , c3, b3]@@ -53,12 +53,12 @@ ----------------------------- main5 = dac $ do- (gui, fx) <- fxHor + (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 + , uiChorus False 0.5 0.5 0.5 0.5+ , uiPhaser False 0.5 0.5 0.5 0.5 , uiReverb True 0.5 0.5- , uiGain True 0.5 + , uiGain 0.5 ] win "main" (900, 400) gui fx $ fromMono $ saw 110
examples/Midi.hs view
@@ -1,23 +1,23 @@ module Main where- + -- imports everything import Csound.Base --- Let's define a simple sound unit that +-- Let's define a simple sound unit that -- reads in cycles the table that contains a single sine partial. -- oscil1 is the standard oscillator with linear interpolation. -- 1 - means the amplitude, cps - is cycles per second and the last argument--- is the table that we want to read. +-- is the table that we want to read. myOsc :: Sig -> Sig myOsc cps = oscili 1 cps (sines [1]) -- Let's define a simple instrument that plays a sound on the specified frequency.--- We use @sig@ to convert a constant value to signal and then plug it in the osc unit. +-- We use @sig@ to convert a constant value to signal and then plug it in the osc unit. -- We make it a bit quieter by multiplying with 0.5. pureTone :: (D, D) -> Sig-pureTone (amp, cps) = 0.4 * sig amp * fades 0.2 1.5 * (myOsc $ sig cps) +pureTone (amp, cps) = 0.4 * sig amp * fades 0.2 1.5 * (myOsc $ sig cps) --- Renders generated csd-file to the "tmp.csd" and runs it with flags +-- Renders generated csd-file to the "tmp.csd" and runs it with flags -- for real time output and listening for the midi events from all devices. main :: IO () main = vdac $ midi $ onMsg pureTone
examples/Tibetan.hs view
@@ -1,10 +1,10 @@ {- | Example requires the package `random` to be installed -This remarkable tibetan harmonic chant like effect is created by nine sinusoidal -oscillators, whose frequencies are almost identical: separated by a fraction of -1 Hz from each other. Thus for each component, amplitude modulation leads to its -enhancement or cancelling out in turn. In his composition 'Mutations', Risset -gives the instrument two different envelopes: one with sharp rise and one is a +This remarkable tibetan harmonic chant like effect is created by nine sinusoidal+oscillators, whose frequencies are almost identical: separated by a fraction of+1 Hz from each other. Thus for each component, amplitude modulation leads to its+enhancement or cancelling out in turn. In his composition 'Mutations', Risset+gives the instrument two different envelopes: one with sharp rise and one is a more gradual rise. -} module Tibetan where@@ -28,7 +28,7 @@ pureTibetan :: (D, D, D, D, D) -> Sig pureTibetan (amp, cps, off, rise, dec) = mean $ fmap partial $ 0 : offs ++ (fmap negate offs) where offs = fmap int [1 .. 4]- partial rat = linen (sig amp) rise idur dec * oscBy wave (sig $ cps + off * rat) + partial rat = linen (sig amp) rise idur dec * oscBy wave (sig $ cps + off * rat) wave = ifB (cps `lessThan` 230) (waveBy 5) (ifB (cps `lessThan` 350) (waveBy 3) (waveBy 1)) waveBy n = sines $ [0.3, 0, 0, 0] ++ replicate n 0.1 @@ -57,16 +57,16 @@ r = Repeat w = Wait -instance Num Act where +instance Num Act where fromInteger = Tone . fromInteger -type N = (D, D, D, D, D, D)+type N = (Sig, Sig, D, D, D, D) -data St = St +data St = St { stRepeat :: Int , stWait :: Double- , stSpan :: (Double, Double) + , stSpan :: (Double, Double) , stRnds :: [Double] } -- constants@@ -88,12 +88,12 @@ turtle :: Act -> State St [N] turtle x = case x of Repeat n -> updateSt $ \s -> s{ stRepeat = n }- Wait n -> updateSt $ \s -> s{ stWait = n } + Wait n -> updateSt $ \s -> s{ stWait = n } -- tones Tone t -> state (getNotes t) getNotes :: Int -> St -> ([N], St)-getNotes k st = (notes, st') +getNotes k st = (notes, st') where t0s = startTimes (offsetStartTime (stWait st) $ stSpan st) durStep dts = durs noteLength cpss = freqs (ts !! (k - 1))@@ -102,8 +102,8 @@ decs = decays dec riss = rises rise - notes = take (stRepeat st) $ getZipList $ (\t0 dt amp cps ris dec -> - (double t0, double dt, double amp, double cps, double ris, double dec)) <$>+ notes = take (stRepeat st) $ getZipList $ (\t0 dt amp cps ris dec ->+ (sig $ double t0, sig $ double dt, double amp, double cps, double ris, double dec)) <$> ZipList t0s <*> ZipList dts <*> ZipList amps <*> ZipList cpss <*> ZipList decs <*> ZipList riss st' = st{ stSpan = getSpan (stRepeat st) t0s dts }@@ -125,7 +125,7 @@ freqs k = fmap (* base) octs where octs = cycle [1, 0.5, 2, 1, 2, 1, 1, 0.5]- base = k * baseTone + base = k * baseTone cps2amp a = 0.5 * full a where full x@@ -138,17 +138,17 @@ run :: [Act] -> IO [N] run as = fmap concat $ fmap (evalState (mapM turtle as)) initSt where initSt = fmap (St initRepeat initWait initSpan) $ fmap (randomRs (0, 1)) newStdGen- + acts :: [Act] acts = concat $ replicate 1 $ [1, 1, 5, 2, 5, 7, 5, 1, 1, 3, 5, 3, 1, 1, 5, 1 ] - -note (start, dur, amp, cps, rise, dec) = del start $ str dur $ ++note (start, dur, amp, cps, rise, dec) = del start $ str dur $ temp (amp, cps, rise, dec) globalEffect = eff (bindSig $ return . blp 5000 . (0.3 * )) . eff rever -res2 ns = har [res ns, del 13 $ res ns] +res2 ns = har [res ns, del 13 $ res ns] res ns = sco tibetan $ har $ fmap note ns @@ -193,25 +193,25 @@ starChord = [0, 1, 2, 4, 7] starSco = sco blue $- flip evalState starParams $ traverse addParam $ + flip evalState starParams $ traverse addParam $ har $ zipWith3 phi starInitDelays starPeriods starChord- where phi dt period note = del dt $ loopBy 50 $ har [4 *| temp (double $ id2cps 2 note), rest period] + where phi dt period note = del dt $ loopBy 50 $ har [4 *| temp (double $ id2cps 2 note), rest period] - addParam cps = state $ \((amp, lfo, harm, sweep) : params) -> - ((amp, cps, lfo, harm, sweep), params) - + addParam cps = state $ \((amp, lfo, harm, sweep) : params) ->+ ((amp, cps, lfo, harm, sweep), params) + ------------------------------------------------------------ main = do notes <- run acts- dac $ mix $ har + dac $ mix $ har [ introBlurp- , del (introDur * 0.70) $ har - [ globalEffect $ har + , del (introDur * 0.70) $ har+ [ globalEffect $ har [ res2 notes , del starTotalDelay $ starSco , del (2 * starTotalDelay) $ starSco] , blurpSco ]]- +
examples/Wind.hs view
@@ -7,7 +7,7 @@ -- orchestra -- | An instrument that implements a wind sound.-wind (amp, bandRise, bandDec, freqRise, freqDec, pan, winds) = +wind (amp, bandRise, bandDec, freqRise, freqDec, pan, winds) = fmap fromRnd $ rand (sig $ amp / 400) where valu1 = 100@@ -16,10 +16,10 @@ ramp a b = linseg [a, idur, b] fromRnd a = (sig pan * aout, (1 - sig pan) * aout ) where- a2 = butbp a (ramp freqRise freqDec) (ramp bandRise bandDec) + a2 = butbp a (ramp freqRise freqDec) (ramp bandRise bandDec) a3 = butbp a2 (ramp (freqRise - valu1) (freqDec + valu2)) (ramp (bandRise + valu1) (bandDec - valu2))- + aout = (a2 + a3) * linseg [0, idur * winds, 1, idur * winde, 0] -------------------------------------------------------------@@ -27,7 +27,7 @@ -- | This example shows the flexibility of the Haskell. Here we can -- write the scores in the manner of the native Csound style.-i21 t0 dt amp bandRise bandDec freqRise freqDec pan winds = +i21 t0 dt amp bandRise bandDec freqRise freqDec pan winds = del t0 $ dt *| temp (amp, bandRise, bandDec, freqRise, freqDec, pan, winds) windRes :: Sco (Mix Sig2)@@ -55,7 +55,7 @@ , i21 40 15 70 500 0 555 111 0 0.4 , i21 44 10 74 600 0 444 111 0.5 0.6 , i21 48 8 77 500 0 333 111 0.7 0.7- , i21 48.5 9 76 500 0 222 111 0.9 0.9 + , i21 48.5 9 76 500 0 222 111 0.9 0.9 , i21 50 12 72 500 0 666 222 0.1 0.6 , i21 55 15 74 500 0 333 333 0.5 0.7
src/Csound/Air/Envelope.hs view
@@ -7,24 +7,24 @@ adsr140, trigTab, -- * Relative duration onIdur, lindur, expdur, linendur,- onDur, lindurBy, expdurBy, linendurBy, + onDur, lindurBy, expdurBy, linendurBy, -- * Faders fadeIn, fadeOut, fades, expFadeIn, expFadeOut, expFades, slope, expSlope, - -- * Humanize + -- * Humanize HumanizeValue(..), HumanizeTime(..), HumanizeValueTime(..), hval, htime, hvalTime, - -- * Looping envelopes + -- * Looping envelopes -- ** Simple lpshold, loopseg, loopxseg, lpsholdBy, loopsegBy, loopxsegBy, holdSeq, linSeq, expSeq,- linloop, exploop, sah, stepSeq, + linloop, exploop, sah, stepSeq, constSeq, triSeq, sqrSeq, sawSeq, isawSeq, xsawSeq, ixsawSeq, isqrSeq, xtriSeq, pwSeq, ipwSeq, rampSeq, irampSeq, xrampSeq, ixrampSeq,- adsrSeq, xadsrSeq, adsrSeq_, xadsrSeq_, + adsrSeq, xadsrSeq, adsrSeq_, xadsrSeq_, -- ** Complex Seq, toSeq, onBeat, onBeats,@@ -70,7 +70,7 @@ -- -- > onIdur [a, t1, b, t2, c] ----- becomes: +-- becomes: -- -- > [a, t1 * idur, b, t2 * idur, c] onIdur :: [D] -> [D]@@ -80,7 +80,7 @@ -- -- > onDur dt [a, t1, b, t2, c] ----- becomes: +-- becomes: -- -- > [a, t1 * dt, b, t2 * dt, c] onDur :: D -> [D] -> [D]@@ -88,22 +88,22 @@ a:b:as -> a : b * dur : onDur dur as _ -> xs --- | The opcode 'Csound.Opcode.linseg' with time intervals +-- | 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 +-- | 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 +-- | 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 +-- | 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@@ -121,7 +121,7 @@ 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]@@ -137,7 +137,7 @@ slope :: D -> D -> Sig slope dt1 dt2 = linseg [0, dt1, 0, dt2, 1 ] --- | Exponential slope (See the function @slope@). +-- | Exponential slope (See the function @slope@). expSlope :: D -> D -> Sig expSlope dt1 dt2 = linseg [0.001, dt1, 0.001, dt2, 1 ] @@ -179,7 +179,7 @@ -- The period of the repetition equals to the sum of all durations. sah :: [Sig] -> Sig sah as = stepSeq as (1 / period)- where + where period = sumDts as sumDts xs = case xs of@@ -211,7 +211,7 @@ -- | Sample and hold sequence. It outputs the looping sequence of constan elements. constSeq :: [Sig] -> Sig -> Sig-constSeq = genSeq stepSeq id +constSeq = genSeq stepSeq id -- | Step sequencer with unipolar triangle. triSeq :: [Sig] -> Sig -> Sig@@ -277,18 +277,18 @@ sawList xs = case xs of- [] -> [] + [] -> [] [a] -> a : 1 : 0 : [] a:rest -> a : 1 : 0 : 0 : sawList rest- + isawList xs = case xs of- [] -> [] + [] -> [] [a] -> 0 : 1 : a : [] a:rest -> 0 : 1 : a : 0 : isawList rest triList xs = case xs of [] -> [0, 0]- a:rest -> 0 : 1 : a : 1 : triList rest + a:rest -> 0 : 1 : a : 1 : triList rest pwList k xs = case xs of [] -> []@@ -301,16 +301,16 @@ rampList a1 duty xs = case xs of [] -> [] [a] -> 0.5 * a : d1 : a : d1 : 0.5 * a : d2 : 0 : d2 : 0.5 * a1 : []- a:as -> 0.5 * a : d1 : a : d1 : 0.5 * a : d2 : 0 : d2 : rampList a1 duty as - where + a:as -> 0.5 * a : d1 : a : d1 : 0.5 * a : d2 : 0 : d2 : rampList a1 duty as+ where d1 = duty / 2 d2 = (1 - duty) / 2 irampList a1 duty xs = case xs of [] -> [] [a] -> 0.5 * a : d1 : 0 : d1 : 0.5 * a : d2 : a : d2 : 0.5 * a1 : []- a:as -> 0.5 * a : d1 : 0 : d1 : 0.5 * a : d2 : a : d2 : rampList a1 duty as - where + a:as -> 0.5 * a : d1 : 0 : d1 : 0.5 * a : d2 : a : d2 : rampList a1 duty as+ where d1 = duty / 2 d2 = (1 - duty) / 2 @@ -325,7 +325,7 @@ intersperseEnd val end xs = case xs of [] -> end [a] -> a : end- a:as -> a : val : intersperseEnd val end as + a:as -> a : val : intersperseEnd val end as ------------------------------------------------------------------ @@ -342,7 +342,7 @@ -- It's a list of values and durations. The durations are relative -- to the period of repetition. The period is specified with the second argument. -- The second argument is the frequency of repetition measured in Hz.--- +-- -- > lpshold valDurs frequency lpshold :: [Sig] -> Sig -> Sig lpshold as cps = smooth $ C.lpshold cps 0 0 as@@ -354,7 +354,7 @@ -- It's a list of values and durations. The durations are relative -- to the period of repetition. The period is specified with the second argument. -- The second argument is the frequency of repetition measured in Hz.--- +-- -- > loopseg valDurs frequency loopseg :: [Sig] -> Sig -> Sig loopseg as cps = smooth $ C.loopseg cps 0 0 (fixEnd as)@@ -366,7 +366,7 @@ -- It's a list of values and durations. The durations are relative -- to the period of repetition. The period is specified with the second argument. -- The second argument is the frequency of repetition measured in Hz.--- +-- -- > loopxseg valDurs frequency loopxseg :: [Sig] -> Sig -> Sig loopxseg as cps = smooth $ C.loopxseg cps 0 0 (fixEnd as)@@ -387,7 +387,7 @@ -- -- > xadsrSeq attack decay sustain release weights frequency ----- The sum of attack, decay, sustain and release time durations +-- The sum of attack, decay, sustain and release time durations -- should be equal to one. adsrSeq :: Sig -> Sig -> Sig -> Sig -> [Sig] -> Sig -> Sig adsrSeq a d s r = linSeq (adsrList a d s r)@@ -397,7 +397,7 @@ -- -- > xadsrSeq attack decay sustain release weights frequency ----- The sum of attack, decay, sustain and release time durations +-- The sum of attack, decay, sustain and release time durations -- should be equal to one. xadsrSeq :: Sig -> Sig -> Sig -> Sig -> [Sig] -> Sig -> Sig xadsrSeq a d s r = expSeq (adsrList a d s r)@@ -406,7 +406,7 @@ -- -- > adsrSeq attack decay sustain release rest weights frequency ----- The sum of attack, decay, sustain, release and rest time durations +-- The sum of attack, decay, sustain, release and rest time durations -- should be equal to one. adsrSeq_ :: Sig -> Sig -> Sig -> Sig -> Sig -> [Sig] -> Sig -> Sig adsrSeq_ a d s r rest = linSeq (adsrList_ a d s r rest)@@ -416,7 +416,7 @@ -- -- > xadsrSeq_ attack decay sustain release rest weights frequency ----- The sum of attack, decay, sustain, release and rest time durations +-- The sum of attack, decay, sustain, release and rest time durations -- should be equal to one. xadsrSeq_ :: Sig -> Sig -> Sig -> Sig -> Sig -> [Sig] -> Sig -> Sig xadsrSeq_ a d s r rest = expSeq (adsrList_ a d s r rest)@@ -477,18 +477,18 @@ genSegSeq :: ([Sig] -> Sig -> Sig) -> [Sig] -> [Sig] -> Sig -> Sig genSegSeq mkSeg shape weights cps = mkSeg (groupSegs $ fmap (scaleVals shape) weights) (cps / len)- where + where len = sig $ int $ length weights scaleVals xs k = case xs of [] -> [] [a] -> [a * k]- a:da:rest -> (a * k) : da : scaleVals rest k + a:da:rest -> (a * k) : da : scaleVals rest k groupSegs :: [[Sig]] -> [Sig] groupSegs as = concat $ intersperse [0] as --- | The seq is a type for step sequencers. +-- | The seq is a type for step sequencers. -- The step sequencer is a monophonic control signal. -- Most often step sequencer is a looping segment of -- some values. It's used to create bas lines or conrtrol the frequency of@@ -501,8 +501,8 @@ -- -- each pair defines a segment of height valN that lasts for durN. -- The sequence is repeated with the given frequency. Each segment--- has certain shape. It can be a constant or line segment or --- fragment of square wave or fragment of an adsr envelope. +-- has certain shape. It can be a constant or line segment or+-- fragment of square wave or fragment of an adsr envelope. -- There are many predefined functions. -- -- With Seq we can construct control signals in very flexible way.@@ -520,7 +520,7 @@ newtype Seq = Seq { unSeq :: [Seq1] } data Seq1 = Rest {- seq1Dur :: Sig } + seq1Dur :: Sig } | Seq1 { seq1Dur :: Sig , seq1Val :: Sig@@ -538,13 +538,13 @@ del t a = mel [rest t, a] instance Melody Seq where- mel as = Seq $ as >>= unSeq + mel as = Seq $ as >>= unSeq instance Stretch Seq where str t (Seq as) = Seq $ fmap (updateDur t) as where updateDur k a = a { seq1Dur = k * seq1Dur a } --- | Creates a +-- | Creates a toSeq :: Sig -> Seq toSeq a = Seq [Seq1 1 a] @@ -692,14 +692,14 @@ renderSeq0 :: (Sig -> Sig -> [Sig]) -> Seq -> [Sig] renderSeq0 f (Seq as) = as >>= phi- where + where phi x = case x of Seq1 dt val -> f dt val Rest dt -> [0, dt] renderSeq1 :: (Sig -> Sig -> [Sig]) -> Seq -> [Sig] renderSeq1 f (Seq as) = as >>= phi- where + where phi x = case x of Seq1 dt val -> f dt val Rest dt -> [0, dt, 0, 0]@@ -708,12 +708,12 @@ genSeqPat :: (Int -> [Double]) -> [Int] -> Seq genSeqPat g ns = mel (ns >>= f)- where f n + where f n | n <= 0 = [] | n == 1 = [1] | otherwise = fmap (toSeq . sig . double) $ g n --- | Function for creation of accented beats. +-- | Function for creation of accented beats. -- The steady beat pattern of accents is repeated. -- The first argument describes the list of integers. -- Each integer is a main beat and the length of the beat.@@ -722,7 +722,7 @@ -- > dac $ mul (seqSaw [seqPat [3, 3, 2]] 1) white seqPat :: [Int] -> Seq seqPat ns = mel (ns >>= f)- where f n + where f n | n <= 0 = [] | n == 1 = [1] | otherwise = [1, rest $ sig $ int $ n - 1]@@ -736,7 +736,7 @@ -- > dac $ mul (seqSaw [seqDesc [3, 3, 2]] 1) white seqDesc :: [Int] -> Seq seqDesc = genSeqPat rowDesc- + -- | It's like @seqPat@ but inplace of rests it fills the gaps with -- segments ascending in value. --@@ -771,7 +771,7 @@ -- so that all values are sumed with some random value. The amplitude of the -- random value is given with the first argument. ----- It can transform linseg, expseg, sequence producers and simplified sequence producers. +-- It can transform linseg, expseg, sequence producers and simplified sequence producers. -- -- An example: --@@ -821,7 +821,7 @@ -- so that all durations are sumed with some random value. The amplitude of the -- random value is given with the first argument. ----- It can transform linseg, expseg, sequence producers and simplified sequence producers. +-- It can transform linseg, expseg, sequence producers and simplified sequence producers. -- -- An example: --@@ -860,7 +860,7 @@ -- so that all values and durations are sumed with some random value. The amplitude of the -- random value is given with the first two arguments. ----- It can transform linseg, expseg, sequence producers and simplified sequence producers. +-- It can transform linseg, expseg, sequence producers and simplified sequence producers. -- -- An example: --@@ -902,7 +902,7 @@ -- -- > trigTab table dur trigger trigTab :: Tab -> Sig -> Sig -> Sig-trigTab ifn kdur ktrig = +trigTab ifn kdur ktrig = tablei (lineto ktrig (kdur * delay1 ktrig)) ifn `withD` 1 @@ -912,3 +912,4 @@ -- > trigTabEvt table dur trigger trigTabEvt :: Tab -> Sig -> Evt a -> Sig trigTabEvt ifn kdur ktrig = trigTab ifn kdur (evtToTrig ktrig)+
src/Csound/Air/Fx.hs view
@@ -55,12 +55,11 @@ fxRingModulator, , -} fxCompress, - -- Eq+ -- * Eq audaciousEq, -- * Misc trackerSplice, pitchShifterDelay- ) where import Data.Boolean@@ -76,11 +75,11 @@ import Csound.Air.Filter import Csound.Typed.Plugins hiding(pitchShifterDelay, fxAnalogDelay, fxDistortion, fxEnvelopeFollower, fxFlanger, fxFreqShifter, fxLoFi,- fxPanTrem, fxPhaser, fxPitchShifter, fxReverse, fxRingModulator, fxChorus2)+ fxPanTrem, fxPhaser, fxPitchShifter, fxReverse, fxRingModulator, fxChorus2, tapeEcho) import qualified Csound.Typed.Plugins as P(pitchShifterDelay, fxAnalogDelay, fxDistortion, fxEnvelopeFollower, fxFlanger, fxFreqShifter, fxLoFi,- fxPanTrem, fxPhaser, fxPitchShifter, fxReverse, fxRingModulator, fxChorus2, fxPingPong, tapeRead, tapeWrite)+ fxPanTrem, fxPhaser, fxPitchShifter, fxReverse, fxRingModulator, fxChorus2, fxPingPong, tapeRead, tapeWrite, tapeEcho) -- | Mono version of the cool reverberation opcode reverbsc. --@@ -867,23 +866,6 @@ ------------------------------- -- tape echo -{-}-opcode TapeEcho4, a, akkkkk- aIn, kDelay, kEchoGain, kFbGain, kTone, kRandomSpread xin-- aDummy delayr 16- aEcho1 tapeRead aIn, kDelay, kRandomSpread- aEcho2 tapeRead aIn, (kDelay * 2), kRandomSpread- aEcho3 tapeRead aIn, (kDelay * 4), kRandomSpread- aEcho4 tapeRead aIn, (kDelay * 8), kRandomSpread- aOut = aIn + kEchoGain * aEcho1 + 0.5 * kEchoGain * aEcho2 + 0.25 * kEchoGain * aEcho3 + 0.2 * kEchoGain * aEcho4-- aOut tone aOut, kTone- tapeWrite aIn, aOut, kFbGain- xout aOut-endop--}- type EchoGain = Sig type RandomSpreadSig = Sig @@ -896,19 +878,9 @@ -- * echo gain -- * tone - normalized center frequency of the filter (0 to 1) -- * randomSpread - quality of the tape (the higher - the worser)-tapeEcho :: Int -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> Sig -> SE Sig-tapeEcho n dt fb echoGain ktoneNorm spread ain = do- aDummy <- delayr minDt- aout <- fmap ((\echoes -> tone (ain + echoGain * echoes) ktone) . sum . zipWith (*) halves) $- mapM (\step -> tapeRead ain (dt * step) spread) doubles- tapeWrite ain aout fb- return aout+tapeEcho :: D -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> Sig -> Sig+tapeEcho n dt fb echoGain ktoneNorm spread ain = P.tapeEcho n dt echoGain fb ktone spread ain where- halves = take n $ iterate ( / 2) 1- doubles = take n $ iterate ( * 2) 1-- minDt = int $ 16 `max` (n * 4)- ktone = fromNormTone ktoneNorm fromNormTone :: Sig -> Sig
src/Csound/Air/Fx/FxBox.hs view
@@ -181,12 +181,16 @@ uiCrusher, -- ** Ring modulation- uiRingo', uiRingo1, uiRingo2, uiRingo3, uiRingo4, uiRingo5+ uiRingo', uiRingo1, uiRingo2, uiRingo3, uiRingo4, uiRingo5, -- ** Compressor -- | TODO + -- * Misc++ -- ** Ambi guitar+ ambiGuitar ) where import Data.Default@@ -211,7 +215,7 @@ import Csound.Air.Live(fxBox, fxColor) import Csound.Air.Wav(toMono)-import Csound.Air.Misc(fromMono)+import Csound.Air.Misc(fromMono, ambiEnv, saturator) import qualified Data.Colour as C import qualified Data.Colour.SRGB as C@@ -468,9 +472,17 @@ adele4m = adeleByM size4 adele5m = adeleByM size5 --- Tape echo-magnus :: Sigs a => Int -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> a -> SE a-magnus size delt fb echoGain ktone randomSpread = bindSig (tapeEcho size delt fb echoGain ktone randomSpread)+-- | magnus - simulates magnetic tape echo/delay+--+-- > magnus size feedback echoGain tone randomSpread ain+--+-- * size - how many heads in the tape+-- * feedback+-- * echo gain+-- * tone - normalized center frequency of the filter (0 to 1)+-- * randomSpread - quality of the tape (the higher - the worser)+magnus :: Sigs a => D -> DelayTime -> Feedback -> EchoGain -> ToneSig -> RandomSpreadSig -> a -> a+magnus size delt fb echoGain ktone randomSpread = mapSig (tapeEcho size delt fb echoGain ktone randomSpread) -- Ping Pong delay @@ -779,7 +791,7 @@ uiMagnus :: Sigs a => Int -> Double -> Double -> Double -> Double -> Double -> Source (Fx a) uiMagnus size initDelayTime initFeedback initEchoGain initTone initSpread = mapSource bindSig $ paintTo adeleColor $ fxBox "Tape echo" fx True [("del time", initDelayTime), ("fbk", initFeedback), ("echo gain", initEchoGain), ("tone", initTone), ("tape qty", initSpread)] where- fx [delayTime, feedback, echoGain, tone, spread] = magnus size delayTime feedback echoGain tone spread+ fx [delayTime, feedback, echoGain, tone, spread] = return . magnus (int size) delayTime feedback echoGain tone spread -- Ping-pong delay @@ -1180,4 +1192,27 @@ uiCave4m = uiMonoCave size4 uiCave5m = uiMonoCave size5 +type ThreshSig = Sig +-------------------------------------+-- ambient guitar++-- | Ambient guitar patch. It uses @ambiEnv@ with stack of delays and a bit of compression and distortion.+-- No reverb is added. The reverb is for user to add.+--+-- > ambiGuitar thresh delayTime feedback tone driveLevel sig+--+-- For thresh try out values like 0.01, 0.02+--+-- Example, we read guitar input from soundcard first input,+-- apply ambient guitar effect and a bit of reverb:+--+-- > main = dac proc+-- >+-- > proc :: Sig2 -> SE Sig2+-- > proc (x, _) = hall 0.25 $ ambiGuitar 0.02 1 0.7 0.4 0.1 x+ambiGuitar :: ThreshSig -> DelayTime -> Feedback -> ToneSig -> DriveSig -> Sig -> SE Sig+ambiGuitar thresh dt fbk toneSig drv ain = do+ envSig <- ambiEnv thresh ain+ return $ ( adele 0.35 dt fbk toneSig . adele 0.5 (dt / 4) (fbk * 1.25) toneSig .+ saturator 0.3 . tort drv 0.25) envSig
src/Csound/Air/Live.hs view
@@ -61,13 +61,13 @@ genMixer :: (Sigs a) => ([Gui] -> Gui, [Gui] -> Gui) -> [(String, SE a)] -> Source a genMixer (parentGui, childGui) as = source $ do- gTags <- mapM (unDisplay . box) names- (gs, vols) <- fmap unzip $ mapM (const $ unSource $ defSlider "") names- (gMutes, mutes) <- fmap unzip $ mapM (const $ unSource $ toggleSig "" False) names+ gTags <- mapM box names+ (gs, vols) <- fmap unzip $ mapM (const $ defSlider "") names+ (gMutes, mutes) <- fmap unzip $ mapM (const $ toggleSig "" False) names - gMasterTag <- unDisplay $ box "master"- (gMaster, masterVol) <- unSource $ defSlider ""- (gMasterMute, masterMute) <- unSource $ toggleSig "" False+ 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@@ -116,12 +116,12 @@ -- 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 name fx onOff args = source $ do- (gOff0, off) <- unSource $ toggleSig name onOff+ (gOff0, off) <- toggleSig name onOff let gOff = setFontSize 25 gOff0 offRef <- newGlobalRef (0 :: Sig) writeRef offRef off let (names, initVals) = unzip args- (gs, as) <- fmap unzip $ mapM (\(name, initVal) -> unSource $ slider name (linSpan 0 1) initVal) $ zip names initVals+ (gs, as) <- fmap unzip $ mapM (\(name, initVal) -> slider name (linSpan 0 1) initVal) $ zip names initVals let f x = do ref <- newRef (0 :: a) goff <- readRef offRef@@ -155,7 +155,7 @@ uiGroupGui a b =ver [sca uiOnOffSize a, sca uiBoxSize b] sourceColor2 :: Color -> Source a -> Source a-sourceColor2 col (Source a) = source $ do+sourceColor2 col a = source $ do (g, x) <- a return (setColor2 col g, x) @@ -166,22 +166,22 @@ -- combine effects fxGroupMS :: ([Gui] -> Gui) -> [Source Fx1] -> Maybe (Source (Sig -> SE Sig2)) -> [Source Fx2] -> Source (Sig -> SE Sig2)-fxGroupMS guiGroup as bridge bs = Source $ do+fxGroupMS guiGroup as bridge bs = do (gsA, fA) <- getChain as (gsB, fB) <- getChain bs case bridge of Nothing -> return $ (guiGroup $ gsA ++ gsB, fA >=> fB . fromMono) Just widget -> do- (gBridge, fBridge) <- unSource widget+ (gBridge, fBridge) <- widget return $ (guiGroup $ gsA ++ gBridge : gsB, fA >=> fBridge >=> fB) where getChain xs = do- (gs, fs) <- fmap unzip $ sequence $ fmap unSource xs+ (gs, fs) <- fmap unzip $ sequence xs return (gs, foldl (\a b -> a >=> b) return fs) fxGroup :: ([Gui] -> Gui) -> [Source (Fx a)] -> Source (Fx a)-fxGroup guiGroup as = Source $ do- (gs, fs) <- fmap unzip $ sequence $ fmap unSource as+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.@@ -343,8 +343,8 @@ -- | the widget for mixing in a signal to the signal. uiSig :: (Sigs a) => String -> Bool -> Source a -> Source (Fx a) uiSig name onOff widget = source $ do- (gs, asig) <- unSource widget- (gOff0, off) <- unSource $ toggleSig name onOff+ (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)@@ -380,10 +380,10 @@ genAdsr :: (D -> D -> D -> D -> Sig) -> String -> AdsrBound -> AdsrInit -> Source Sig genAdsr mkAdsr name b inits = source $ do- (gatt, att) <- unSource $ knob "A" (linSpan expEps $ attBound b) (attInit inits)- (gdec, dec) <- unSource $ knob "D" (linSpan expEps $ decBound b) (decInit inits)- (gsus, sus) <- unSource $ knob "S" (linSpan expEps 1) (susInit inits)- (grel, rel) <- unSource $ knob "R" (linSpan expEps $ relBound b) (relInit inits)+ (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)
src/Csound/Air/Looper.hs view
@@ -166,14 +166,14 @@ , (\f -> f "through" False) $ maybe toggleSig (toggleSig' . evtToSig (-1)) (loopThrough a)) genLoop :: forall a. (BoolSig -> a -> SE Sig2) -> LoopSpec -> D -> [D] -> [a] -> Source Sig2-genLoop playInstr spec dtBpm times' instrs = Source $ do- (preFxKnobGui, preFxKnobWrite, preFxKnobRead) <- unSinkSource $ setKnob "pre" (linSpan 0 1) 0.5- (postFxKnobGui, postFxKnobWrite, postFxKnobRead) <- unSinkSource $ setKnob "post" (linSpan 0 1) 0.5- (mixKnobGui, mixKnobWrite, mixKnobRead) <- unSinkSource $ setKnob "mix" (linSpan 0 1) 0.5+genLoop playInstr spec dtBpm times' instrs = do+ (preFxKnobGui, preFxKnobWrite, preFxKnobRead) <- setKnob "pre" (linSpan 0 1) 0.5+ (postFxKnobGui, postFxKnobWrite, postFxKnobRead) <- setKnob "post" (linSpan 0 1) 0.5+ (mixKnobGui, mixKnobWrite, mixKnobRead) <- setKnob "mix" (linSpan 0 1) 0.5 let knobGuis = ver [mixKnobGui, preFxKnobGui, postFxKnobGui] - unSource $ mapGuiSource (\gs -> hor [knobGuis, sca 12 gs]) $ joinSource $ vlift3 (\(thr, delEvt) x sils -> do+ mapGuiSource (\gs -> hor [knobGuis, sca 12 gs]) $ joinSource $ vlift3 (\(thr, delEvt) x sils -> do -- knobs mixCoeffs <- tabSigs mixKnobWrite mixKnobRead x initMixVals preCoeffs <- tabSigs preFxKnobWrite preFxKnobRead x initPreVals
src/Csound/Air/Misc.hs view
@@ -1,12 +1,12 @@ {-# Language FlexibleContexts #-} -- | Patterns module Csound.Air.Misc(- mean, vibrate, randomPitch, chorusPitch, resons, resonsBy, modes, dryWet, + mean, vibrate, randomPitch, chorusPitch, resons, resonsBy, modes, dryWet, once, onceBy, several, fromMono, -- * List functions odds, evens, -- * Random functions- rndPan, rndPan2, rndVol, gaussVol, + rndPan, rndPan2, rndVol, gaussVol, -- * Choose signals selector, -- * Saving to file@@ -27,21 +27,28 @@ -- * Function composition funSeq, funPar, - -- * Metronome + -- * Metronome ticks, nticks, ticks2, nticks2, ticks3, nticks3, ticks4, nticks4, -- * Drone- testDrone, testDrone2, testDrone3, testDrone4+ testDrone, testDrone2, testDrone3, testDrone4,++ -- * Attack detection+ attackTrig,+ attackTrigSig,++ -- * Ambient guitar FX+ ambiEnv ) where import Control.Monad import Data.Boolean import Data.Default -import Csound.Dynamic hiding (int)+import Csound.Dynamic hiding (int, when1) import Csound.Typed import Csound.Typed.Opcode hiding (metro)@@ -63,23 +70,23 @@ -- | Selects odd elements from the list. odds :: [a] -> [a]-odds as = fmap snd $ filter fst $ zip (cycle [True, False]) as +odds as = fmap snd $ filter fst $ zip (cycle [True, False]) as -- | Selects even elements from the list. evens :: [a] -> [a]-evens as +evens as | null as = [] | otherwise = odds $ tail as --- | Reads table once during the note length. +-- | Reads table once during the note length. once :: Tab -> Sig once = onceBy idur --- | Reads table once during a given period of time. +-- | Reads table once during a given period of time. onceBy :: D -> Tab -> Sig-onceBy dt tb = kr $ oscBy tb (1 / sig dt) +onceBy dt tb = kr $ oscBy tb (1 / sig dt) --- | Reads table several times during the note length. +-- | Reads table several times during the note length. several :: Tab -> Sig -> Sig several tb rate = kr $ oscil3 1 (rate / sig idur) tb @@ -87,12 +94,12 @@ 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. +-- | 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) + where kvib = vibDepth * kr (osc vibRate) --- | Adds a random vibrato to the sound unit. Sound units is a function that takes in a frequency. +-- | 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)@@ -104,7 +111,7 @@ 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] + dts = fmap (\x -> - wid + fromIntegral x * dt) [0 .. n-1] dt = 2 * wid / fromIntegral n @@ -123,7 +130,7 @@ resonsBy :: (cps -> bw -> Sig -> Sig) -> [(cps, bw)] -> Sig -> Sig resonsBy filt ps asig = mean $ fmap (( $ asig) . uncurry filt) ps --- | Mixes dry and wet signals. +-- | Mixes dry and wet signals. -- -- > dryWet ratio effect asig --@@ -138,7 +145,7 @@ -- | Chain of mass-spring-damping filters. ----- > modes params baseCps exciter +-- > modes params baseCps exciter -- -- * params - a list of pairs @(resonantFrequencyRatio, filterQuality)@ --@@ -150,11 +157,11 @@ 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 + 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 + gate cps = ifB (sig getSampleRate >* pi * cps) 1 0 normFactor = sum $ fmap (gate . (* baseCps) . fst) ms @@ -174,11 +181,11 @@ -- | Random panning rndPan :: Sig -> SE Sig2-rndPan a = do +rndPan a = do fmap (pan2 a . sig) (rnd (1 :: D)) -- | Random volume (with gauss distribution)--- +-- -- > gaussVol radiusOfDistribution gaussVol :: SigSpace a => D -> a -> SE a gaussVol k a = do@@ -186,7 +193,7 @@ return $ mul (sig $ level + 1) a -- | Random volume--- +-- -- > gaussVol (minVolume, maxVolume) rndVol :: SigSpace a => (D, D) -> a -> SE a rndVol (kMin, kMax) a = do@@ -207,16 +214,16 @@ selector as k = sum $ zipWith choice [0..] as where choice n a = mul (port (ifB (sig (int n) ==* k) 1 0) 0.02) a --- | Creates running arpeggios. +-- | Creates running arpeggios. -- -- > arpeggiBy ampWeights pitches instrument cps -- -- It plays an instrument with fast sequence of notes. We can specify -- the pitches and amplitude weights of the notes as well as frequency of repetition. arpeggi :: SigSpace a => [Sig] -> [Sig] -> (Sig -> a) -> Sig -> a-arpeggi = arpBy triSeq sqrSeq +arpeggi = arpBy triSeq sqrSeq --- | Creates running arpeggios. +-- | Creates running arpeggios. -- -- > arpeggiBy ampWave pitchwave ampWeights pitches instrument cps --@@ -271,7 +278,7 @@ rndVal :: D -> D -> D -> SE D rndVal total amount x = do- k <- birnd amount + k <- birnd amount return $ x + k * total rndDur amt x = rndVal x amt x@@ -283,11 +290,11 @@ dur <- rndDur' tune <- rndTune' cps <- rndCps'- return $ spec - { trDur = dur + return $ spec+ { trDur = dur , trTune = tune , trCps = cps }- where + where rndDur' = (maybe return rndDur $ (trRnd spec)) $ trDur spec rndTune' = (maybe return rndTune $ (trRnd spec)) $ trTune spec rndCps' = (maybe return rndCps $ (trRnd spec)) $ trCps spec@@ -316,7 +323,7 @@ nticks4 = nticks' highConga' nticks' :: (TrSpec -> SE Sig) -> [Int] -> Sig -> Sig-nticks' drum ns = genTicks drum (cycleE $ ns >>= getAccent) +nticks' drum ns = genTicks drum (cycleE $ ns >>= getAccent) -- | Metronome. --@@ -334,13 +341,13 @@ ticks4 = ticks' highConga' ticks' :: (TrSpec -> SE Sig) -> Int -> Sig -> Sig-ticks' drum n +ticks' drum n | n <= 1 = genTicks drum (devt 0.5) | otherwise = genTicks drum (cycleE $ getAccent n) genTicks :: (TrSpec -> SE Sig) -> (Tick -> Evt D) -> Sig -> Sig-genTicks drum f x = mul 3 $ mlp 4000 0.1 $ - sched (\amp -> mul (sig amp) $ drum (TrSpec (amp + 1) 0 (1200 * (amp + 0.5)) (Just 0.05))) $ +genTicks drum f x = mul 3 $ mlp 4000 0.1 $+ sched (\amp -> mul (sig amp) $ drum (TrSpec (amp + 1) 0 (1200 * (amp + 0.5)) (Just 0.05))) $ withDur 0.5 $ f $ metro (x / 60) rimShot' spec = pureRimShot' =<< rndSpec spec@@ -357,7 +364,7 @@ -- ring aenv1 = expsega [1,fullDur,0.001]- ifrq1 = sig $ cps * octave tune + ifrq1 = sig $ cps * octave tune aring = mul (0.5 * (aenv1 - 0.001)) $ at (bbp ifrq1 (ifrq1 * 8)) $ rndOscBy tabTR808RimShot ifrq1 -- noise@@ -418,7 +425,7 @@ testDrone3 cps = atNote (deepPad caveOvertonePad) (0.8, cps) testDrone4 cps = atNote (deepPad pwEnsemble) (0.8, cps) -pwEnsemble = withSmallHall $ polySynt $ at fromMono . mul 0.55 . onCps impPwEnsemble +pwEnsemble = withSmallHall $ polySynt $ at fromMono . mul 0.55 . onCps impPwEnsemble nightPad = withLargeHall $ polySynt $ mul 0.48 . at fromMono . onCps (mul (fadeOut 1) . impNightPad 0.5) data RazorPad = RazorPad { razorPadSpeed :: Sig }@@ -427,12 +434,12 @@ def = RazorPad 0.5 razorPad = razorPad' def-razorPad' (RazorPad speed) = withLargeHall' 0.35 $ polySynt $ at fromMono . mul 0.6 . onCps (uncurry $ impRazorPad speed) +razorPad' (RazorPad speed) = withLargeHall' 0.35 $ polySynt $ at fromMono . mul 0.6 . onCps (uncurry $ impRazorPad speed) overtonePad = withLargeHall' 0.35 $ polySynt overtoneInstr- + overtoneInstr :: CsdNote D -> SE Sig2-overtoneInstr = mul 0.65 . at fromMono . mixAt 0.25 (mlp 1500 0.1) . onCps (\cps -> mul (fades 0.25 1.2) (tibetan 11 0.012 cps) + mul (fades 0.25 1) (tibetan 13 0.015 (cps * 0.5))) +overtoneInstr = mul 0.65 . at fromMono . mixAt 0.25 (mlp 1500 0.1) . onCps (\cps -> mul (fades 0.25 1.2) (tibetan 11 0.012 cps) + mul (fades 0.25 1) (tibetan 13 0.015 (cps * 0.5))) caveOvertonePad = FxChain (fx1 0.2 (magicCave2 . mul 0.8)) $ polySynt overtoneInstr @@ -452,7 +459,7 @@ -- * n - the number of sinusoids (the best is 9) -- -- * off - frequency step of the harmonics ~ (0.01, 0.03)--- +-- -- * cps - the frequency of the note tibetan :: Int -> Sig -> D -> Sig tibetan n off cps = chorusPitch n (2 * off * fromIntegral n) (oscBy wave) (sig cps)@@ -464,7 +471,7 @@ genRazor filter speed amp cps = mul amp $ do a1 <- ampSpline 0.01- a2 <- ampSpline 0.02 + a2 <- ampSpline 0.02 return $ filter (1000 + 2 * cps + 500 * amp) 0.1 $ mean [ fosc 1 3 (a1 * uosc (speed)) cps@@ -473,12 +480,12 @@ where ampSpline c = rspline ( amp) (3.5 + amp) ((speed / 4) * (c - 0.1)) ((speed / 4) * (c + 0.1)) --- | +-- | -- > nightPad fadeInTime cps impNightPad :: D -> Sig -> Sig impNightPad dt = (fadeIn dt * ) . stringPad 1 --- | +-- | -- -- > stringPad amplitude cps stringPad :: Sig -> Sig -> Sig@@ -519,15 +526,15 @@ -- -- > wshaper table amount asig ----- wave shaper transforms the input signal with the table. --- The amount of transformation scales the signal from 0 to 1. +-- wave shaper transforms the input signal with the table.+-- The amount of transformation scales the signal from 0 to 1. -- the amount is ratio of scaling. It expects the values from the interval [0, 1].--- +-- wshaper :: Tab -> Sig -> Sig -> Sig wshaper t amt asig = tablei (10 * amt * asig / 20) t `withDs` [1, 0.5] -- | Wave shaper with sigmoid.--- +-- -- > genSaturator sigmoidRadius amount asig -- -- * sigmoid radius is 5 to 100.@@ -560,3 +567,80 @@ hardSaturator2 :: Sig -> Sig -> Sig hardSaturator2 = genSaturator 6.5 ++-----------------------------------------+-- attack detection++-- | Detects attacks in the signal. Outputs event stream of attack events.+--+-- > attackTrig threshold sigIn+--+-- threshhold cnmtrols the sensitivity of attack detection.+-- Try out different values in [0, 0.2]+attackTrig :: Sig -> Sig -> SE (Evt Unit)+attackTrig thresh ain = fmap sigToEvt $ attackTrigSig thresh ain++-- | Detects attacks in the signal. Outputs trigger-signal+-- where 1 is when attack happens and 0 otherwise.+attackTrigSig :: Sig -> Sig -> SE Sig+attackTrigSig thresh x = do+ kTime <- newCtrlRef (iWait + 1)+ kTrig <- newCtrlRef 0++ writeRef kTrig 0+ timeVal <- readRef kTime++ when1 (da >* thresh &&* timeVal >* iWait) $ do+ printk 0 timeVal+ writeRef kTrig 1+ writeRef kTime 0++ modifyRef kTime (+1)++ readRef kTrig+ where+ da = diffSig 0.01 $ rms x+ iWait :: Sig+ iWait = 100++ diffSig :: D -> Sig -> Sig+ diffSig dt x = x - delaySig dt x+++------------------------------+-- ambient envelope++-- | Make smooth attacks for the input guitar or piano-like sounds.+-- It simulates automatic volume control pedal. It detects striken attacks+-- and makes them sound more PAD-like.+--+-- first argument is threshold that controls sensitivity of attack detection.+-- The values like ~ 0.01, 0.02 is good start.+--+-- To use it with guitar it's good to add a bit of distortion and compression+-- to the signal to make it brighter and then to apply several delays to prolong the sustain+-- and release phases. And it's good to add some reverb at the end.+--+-- Here is an example of how to make ambient guitar with this effect:+--+-- > main = dac proc+-- >+-- > -- | Let's assume we read guitar from the first input of sound card+-- > proc :: Sig2 -> SE Sig2+-- > proc (x, _) = mul 1 $ hall 0.25 $+-- > fmap ( fromMono . (adele 0.35 1 0.65 0.34) . (adele 0.35 0.25 0.75 0.34) .+-- > saturator 0.3 . tort 0.1 0.25 .+-- > magnus 2 0.25 1.1 0.6 0.4 1.8) $+-- > ambiEnv 0.02 x+-- >+--+-- So I've added a tape echo with magnus,+-- then goes combo of saturator (compressor) and tort (distortion)+-- then goes a couple of delays (adele)+-- and the last part is sweet reverb (hall).+ambiEnv :: Sig -> Sig -> SE Sig+ambiEnv thresh ain = do+ attacks <- attackTrigSig thresh ain+ return $ delaySig 0.1 (env attacks) * ain+ where+ env tr = adsr140 (rms ain - 0.05) tr 4 1 1 3
src/Csound/Air/Sampler.hs view
@@ -14,7 +14,7 @@ syncCharTrig, syncCharTap, syncCharPush,syncCharToggle, syncCharGroup, syncCharCycle, -- * Midi sampler- midiTrig, midiTap, midiPush, midiToggle, midiGroup, + midiTrig, midiTap, midiPush, midiToggle, midiGroup, -- * Generic functions midiTrigBy, midiTapBy, midiPushBy, midiToggleBy, midiGroupBy,@@ -25,7 +25,7 @@ -- * Misc -- | Keyboard char columns- keyColumn1, keyColumn2, keyColumn3, keyColumn4, keyColumn5, + keyColumn1, keyColumn2, keyColumn3, keyColumn4, keyColumn5, keyColumn6, keyColumn7, keyColumn8, keyColumn9, keyColumn0, keyColumns @@ -51,7 +51,7 @@ evtTrig minitVal x st a = case minitVal of Nothing -> ons Just v0 -> ons + offs v0 + first v0- where + where ons = evtTrigNoInit x st a offs v = evtTrigNoInit st x v first v = evtTrigger loadbang x v@@ -59,7 +59,7 @@ evtTrigNoInit x st a = runSeg $ loop $ lim st $ del x $ loop (lim x $ toSeg a) syncEvtTrig :: (Sigs a) => Sig -> Maybe a -> Tick -> Tick -> a -> a-syncEvtTrig bpm minitVal x st a = evtTrig minitVal (syncBpm bpm x) (syncBpm bpm st) a +syncEvtTrig bpm minitVal x st a = evtTrig minitVal (syncBpm bpm x) (syncBpm bpm st) a -- | Toggles the signal with event stream. evtToggle :: (Sigs a) => Maybe a -> Tick -> a -> a@@ -73,21 +73,21 @@ -- every note is held to infinity and it continues to produce zeroes. -- No it's not every sequence note triggers it -- but it's best to limit them anyway-evtTap :: (Sigs a) => D -> Tick -> a -> a+evtTap :: (Sigs a) => Sig -> Tick -> a -> a evtTap dt x a = runSeg $ del x $ loop $ lim x $ toSeg $ takeSnd dt a -syncEvtTap :: (Sigs a) => Sig -> D -> Tick -> a -> a+syncEvtTap :: (Sigs a) => Sig -> Sig -> Tick -> a -> a syncEvtTap bpm dt x = evtTap dt (syncBpm bpm x) -- | Plays a list signals. It triggers the signal with event stream and silences -- all the rest in the list so that only one signal is playing. We can create simple -- costum monosynthes with this function. The last event stream stops all signals. evtGroup :: (Sigs a) => Maybe a -> [(Tick, a)] -> Tick -> a-evtGroup initVal as stop = sum $ fmap (\(a, b, c) -> evtTrig initVal a (mappend b stop) c) +evtGroup initVal as stop = sum $ fmap (\(a, b, c) -> evtTrig initVal a (mappend b stop) c) $ zipWith (\n (a, sam) -> (a, mconcat $ fmap snd $ filter ((/= n) . fst) allEvts, sam)) [(0 :: Int)..] as- where + where allEvts :: [(Int, Tick)]- allEvts = zip [0 ..] (fmap fst as) + allEvts = zip [0 ..] (fmap fst as) syncEvtGroup :: (Sigs a) => Sig -> Maybe a -> [(Tick, a)] -> Tick -> a syncEvtGroup bpm initVal as stop = evtGroup initVal (fmap (\(e, a) -> (syncBpm bpm e, a)) as) (syncBpm bpm stop)@@ -96,8 +96,8 @@ evtCycle :: (Sigs a) => Maybe a -> Tick -> Tick -> [a] -> a evtCycle minitVal start stop sigs = case minitVal of Nothing -> ons- Just _ -> ons + offs - where + Just _ -> ons + offs+ where ons = evtCycleNoInit start stop sigs offs = evtGroup minitVal [(start, 0)] stop @@ -117,7 +117,7 @@ Nothing -> ons Just initVal -> ons + offs initVal + first initVal where- ons = charTrigNoInit starts stops asig + ons = charTrigNoInit starts stops asig offs initVal = charTrigNoInit stops starts initVal first initVal = evtTrigger loadbang (strOn starts) initVal @@ -125,13 +125,13 @@ -- | Triggers a signal when one of the chars from the first string is pressed. -- Stops signal from playing when one of the chars from the second string is pressed.--- Synchronizes the signal with bpm (first argument). +-- Synchronizes the signal with bpm (first argument). syncCharTrig :: (Sigs a) => Sig -> Maybe a -> String -> String -> a -> a syncCharTrig bpm minitVal starts stops asig = case minitVal of Nothing -> ons Just initVal -> ons + offs initVal + first initVal where- ons = charTrigNoInit starts stops asig + ons = charTrigNoInit starts stops asig offs initVal = charTrigNoInit stops starts initVal first initVal = syncEvtTrigger bpm loadbang (strOn starts) initVal @@ -152,7 +152,7 @@ genCharPush trig minitVal ch asig = case minitVal of Nothing -> ons Just v0 -> ons + offs v0 + first v0- where + where ons = trig (charOn ch) (charOff ch) asig offs v = trig (charOff ch) (charOn ch) v first v = trig loadbang (charOn ch) v@@ -168,12 +168,12 @@ -- | Toggles the signal when key is pressed. genCharToggle :: (Sigs a) => (Tick -> Tick) -> Maybe a -> Char -> a -> a-genCharToggle needSync minitVal key asig = retrig (togInstr minitVal asig) - $ accumE (1 :: D) (\_ s -> (s, mod' (s + 1) 2)) +genCharToggle needSync minitVal key asig = retrig (togInstr minitVal asig)+ $ accumE (1 :: D) (\_ s -> (s, mod' (s + 1) 2)) $ needSync $ charOn key- where + where togInstr mv0 asig isPlay = do- ref <- newRef 0 + ref <- newRef 0 case mv0 of Nothing -> return () Just v0 -> writeRef ref v0@@ -185,10 +185,10 @@ -- every note is held to infinity and it continues to produce zeroes. -- No it's not every sequence note triggers it -- but it's best to limit them anyway-charTap :: Sigs a => D -> String -> a -> a+charTap :: Sigs a => Sig -> String -> a -> a charTap stop starts = evtTap stop (strOn starts) -syncCharTap :: Sigs a => Sig -> D -> String -> a -> a+syncCharTap :: Sigs a => Sig -> Sig -> String -> a -> a syncCharTap bpm stop starts = syncEvtTap bpm stop (strOn starts) -- | Plays a list of signals when corresponding key is pressed.@@ -212,10 +212,10 @@ offs initVal = charGroupNoInit (fmap (\ch -> (ch, initVal)) stop) onKeys first initVal = trig loadbang (mconcat $ fmap charOn onKeys) initVal - onKeys = fmap fst as - + onKeys = fmap fst as+ charGroupNoInit as stop = sum $ fmap f as- where + where allKeys = fmap fst as ++ stop f (key, asig) = trig ons offs asig where@@ -223,13 +223,13 @@ offs = strOn allKeys -- | Plays signals one after another when key is pressed.--- Stops the group from playing when the char from the last +-- Stops the group from playing when the char from the last -- argument is pressed. charCycle :: Sigs a => (Maybe a) -> Char -> String -> [a] -> a charCycle initVal start stops sigs = evtCycle initVal (charOn start) (strOn stops) sigs -- | Plays signals one after another when key is pressed.--- Stops the group from playing when the char from the last +-- Stops the group from playing when the char from the last -- argument is pressed. Events are syncronised with BPM (first argument). syncCharCycle :: Sigs a => Sig -> Maybe a -> Char -> String -> [a] -> a syncCharCycle bpm initVal start stops sigs = syncEvtCycle bpm initVal (charOn start) (strOn stops) sigs@@ -273,7 +273,7 @@ -- | Plays a signal when the key is pressed. Retriggers the signal when the key is pressed again. -- Turns off the signal after specified duration (n seconds). -- The key is an integer midi code. The C1 is 60 and the A1 is 69.-midiTap :: (SigSpace a, Sigs a) => MidiChn -> D -> Int -> a -> SE a+midiTap :: (SigSpace a, Sigs a) => MidiChn -> Sig -> Int -> a -> SE a midiTap = midiTapBy midiAmpInstr -- | Plyas a signal while the key is pressed.@@ -281,14 +281,14 @@ midiPush :: (SigSpace a, Sigs a) => MidiChn -> Int -> a -> SE a midiPush = midiPushBy midiAmpInstr --- | Plays and stops a signal in the toggle mode. +-- | Plays and stops a signal in the toggle mode. -- The key is an integer midi code. The C1 is 60 and the A1 is 69. midiToggle :: (SigSpace a, Sigs a) => MidiChn -> Int -> a -> SE a midiToggle = midiToggleBy midiAmpInstr --- | Plays a set of signals on the list of keys. When certain +-- | Plays a set of signals on the list of keys. When certain -- key is pressed the corresponding signal starts to play and all--- the rest are stopped. +-- the rest are stopped. -- -- -- The key is an integer midi code. The C1 is 60 and the A1 is 69. midiGroup :: (SigSpace a, Sigs a) => MidiChn -> [(Int, a)] -> SE a@@ -303,7 +303,7 @@ -- | The generic midiTap. We can specify the midi function. -- The midi function takes in a signal and a volume of the pressed key (it ranges from 0 to 1). -- It produces some output. The default is scaling the signal with the amplitude.-midiTapBy :: (SigSpace a, Sigs a) => MidiTrigFun a -> MidiChn -> D -> Int -> a -> SE a+midiTapBy :: (SigSpace a, Sigs a) => MidiTrigFun a -> MidiChn -> Sig -> Int -> a -> SE a midiTapBy midiInstr midiChn dt key asig = midiTrigBy midiInstr midiChn key (takeSnd dt asig) -- | The generic midiPush. We can specify the midi function.@@ -313,15 +313,15 @@ midiPushBy midiInstr midiChn key asig = do ons <- midiKeyOn midiChn (int key) offs <- midiKeyOff midiChn (int key)- return $ midiEvtTriggerBy midiInstr ons offs asig + return $ midiEvtTriggerBy midiInstr ons offs asig -- | The generic midiToggle. We can specify the midi function. -- The midi function takes in a signal and a volume of the pressed key (it ranges from 0 to 1). -- It produces some output. The default is scaling the signal with the amplitude. midiToggleBy :: (SigSpace a, Sigs a) => MidiTrigFun a -> MidiChn -> Int -> a -> SE a-midiToggleBy midiInstr midiChn key asig = fmap (\evt -> retrig (togMidiInstr asig) evt) +midiToggleBy midiInstr midiChn key asig = fmap (\evt -> retrig (togMidiInstr asig) evt) (fmap (accumE (1 :: D) (\a s -> ((a, s), mod' (s + 1) 2))) $ midiKeyOn midiChn $ int key)- where + where togMidiInstr asig (amp, isPlay) = do ref <- newRef 0 when1 (sig isPlay ==* 1) $ do@@ -333,7 +333,7 @@ -- It produces some output. The default is scaling the signal with the amplitude. midiGroupBy :: (SigSpace a, Sigs a) => MidiTrigFun a -> MidiChn -> [(Int, a)] -> SE a midiGroupBy midiInstr midiChn as = fmap sum $ mapM f as- where + where allKeys = fmap fst as f (key, asig) = do ons <- midiKeyOn midiChn (int key)
src/Csound/Air/Seg.hs view
@@ -1,6 +1,6 @@ {-# Language TypeFamilies #-} module Csound.Air.Seg (- Seg, toSeg, runSeg, + Seg, toSeg, runSeg, constLim, constDel, constRest, limSnd ) where @@ -16,20 +16,20 @@ import Csound.Air.Wav hiding (Loop) --- | A segment of the signal. +-- | A segment of the signal. -- The signal segment is a limited span of signal in time. -- The time can be measured in seconds or in events! -- The time span which is measured in events is the first--- occurence of the event in the event stream. +-- occurence of the event in the event stream. -- -- There are handy functions for scheduling the signal segments. -- we can delay the segment or loop over it or limit it with tme interval -- or play a sequence of segments. The main feature of the segments is the--- ability to schedule the signals with event streams (like button clicks or midi-events). -data Seg a +-- ability to schedule the signals with event streams (like button clicks or midi-events).+data Seg a = Unlim a | Lim Tick (Seg a)- | ConstLim D (Seg a)+ | ConstLim Sig (Seg a) | Seq [Seg a] | Par [Seg a] | Loop (Seg a)@@ -51,7 +51,7 @@ instance Sigs a => Melody (Seg a) where mel = sflow -instance Sigs a => Harmony (Seg a) where +instance Sigs a => Harmony (Seg a) where har = spar instance Sigs a => Compose (Seg a) where@@ -83,7 +83,7 @@ _ -> Lim da x -- | Limits the length of the segment with constant length in seconds.-constLim :: D -> Seg a -> Seg a+constLim :: Sig -> Seg a -> Seg a constLim da x = case x of Par as -> Par (fmap (constLim da) as) _ -> ConstLim da x@@ -91,7 +91,7 @@ -- | Plays the sequence of segments one ofter another. sflow :: [Seg a] -> Seg a sflow as = Seq $ flatten =<< as- where + where flatten x = case x of Seq as -> as _ -> [x]@@ -100,7 +100,7 @@ -- the total length equals to the biggest length of all segments. spar :: [Seg a] -> Seg a spar as = Par $ flatten =<< as- where + where flatten x = case x of Par as -> as _ -> [x]@@ -126,15 +126,15 @@ Unlim a -> a Lim dt (Unlim a) -> elim dt a- Lim dt (Seq as) -> uncurry (evtLoopOnce (Just dt)) (getEvtAndSig $ rmTailAfterUnlim as) + Lim dt (Seq as) -> uncurry (evtLoopOnce (Just dt)) (getEvtAndSig $ rmTailAfterUnlim as) Lim dt (Loop (Seq as)) -> uncurry (evtLoop (Just dt)) (getEvtAndSig $ rmTailAfterUnlim as) Lim dt (Loop a) -> elim dt (runSeg (Loop a)) Lim dt a -> elim dt (runSeg a) ConstLim dt (Unlim a) -> takeSnd dt a- ConstLim dt (Seq as) -> uncurry (evtLoopOnce (Just $ impulseE dt)) (getEvtAndSig $ rmTailAfterUnlim as) - ConstLim dt (Loop (Seq as)) -> uncurry (evtLoop (Just $ impulseE dt)) (getEvtAndSig $ rmTailAfterUnlim as)+ ConstLim dt (Seq as) -> uncurry (evtLoopOnce (Just $ impulseE $ ir dt)) (getEvtAndSig $ rmTailAfterUnlim as)+ ConstLim dt (Loop (Seq as)) -> uncurry (evtLoop (Just $ impulseE $ ir dt)) (getEvtAndSig $ rmTailAfterUnlim as) ConstLim dt (Loop a) -> takeSnd dt (runSeg (Loop a)) ConstLim dt a -> takeSnd dt (runSeg a) @@ -146,18 +146,18 @@ Par as -> maybeElim (getDur x) $ sum $ fmap (\a -> maybeElim (getDur a) $ runSeg a) as -getDur :: Seg a -> Maybe (Either D Tick)+getDur :: Seg a -> Maybe (Either Sig Tick) getDur x = case x of Unlim _ -> Nothing- Loop _ -> Nothing + Loop _ -> Nothing Lim dt _ -> Just $ Right dt ConstLim dt _ -> Just $ Left dt Seq as -> fromListT sum aftT' as Par as -> fromListT (foldl1 maxB) simT' as- where - fromListT g f as + where+ fromListT g f as | all isJust ds = Just $ phi g f $ fmap fromJust ds- | otherwise = Nothing + | otherwise = Nothing where ds = fmap getDur as phi g f xs@@ -169,21 +169,21 @@ Left d -> Just d _ -> Nothing - toEvt = either impulseE id+ toEvt = either (impulseE . ir) id getEvtAndSig :: (Num a, Sigs a) => [Seg a] -> ([SE a], [Tick]) getEvtAndSig as = unzip $ fmap (\x -> (return (runSeg x), getTick $ getDur x)) as- where getTick = maybe mempty (either impulseE id)+ where getTick = maybe mempty (either (impulseE . ir) id) rmTailAfterUnlim :: [Seg a] -> [Seg a]-rmTailAfterUnlim = takeByIncludeLast isUnlim - where +rmTailAfterUnlim = takeByIncludeLast isUnlim+ where isUnlim x = case x of Unlim _ -> True Loop _ -> True Par as -> any isUnlim as- _ -> False + _ -> False takeByIncludeLast :: (a -> Bool) -> [a] -> [a] takeByIncludeLast f xs = case xs of@@ -202,11 +202,11 @@ sdel dt a = sflow [srest dt, a] -- | A pause. Plays nothing for the given time interval in seconds.-constRest :: Num a => D -> Seg a+constRest :: Num a => Sig -> Seg a constRest dt = constLim dt $ toSeg 0 -- | Delays a segment by a given time interval in seconds.-constDel :: Num a => D -> Seg a -> Seg a+constDel :: Num a => Sig -> Seg a -> Seg a constDel dt a = sflow [constRest dt, a] -----------------------------------------------------------@@ -214,10 +214,10 @@ elim :: Sigs a => Tick -> a -> a elim dt asig = schedUntil (const $ return $ asig) (impulseE 0) dt -maybeElim :: (Num a, Sigs a) => Maybe (Either D Tick) -> a -> a+maybeElim :: (Num a, Sigs a) => Maybe (Either Sig Tick) -> a -> a maybeElim mdt a = case mdt of Nothing -> a- Just x -> case x of + Just x -> case x of Left d -> takeSnd d a Right t -> elim t a @@ -230,7 +230,7 @@ aftT' :: [Tick] -> Tick aftT' evts = take1 $ sigToEvt $ evtLoop Nothing asigs evts- where + where asigs :: [SE Sig] asigs = fmap (return . sig) $ (replicate (length evts - 1) 0) ++ [1] @@ -246,7 +246,7 @@ when1 (sig isAwaiting ==* 1 &&* sig countDown ==* 0) $ do bam unit writeRef isAwaitingRef 0- where + where mkEvt ref e = do notFiredRef <- newRef (1 :: D) notFired <- readRef notFiredRef
src/Csound/Air/Wav.hs view
@@ -67,39 +67,39 @@ -- Signal manipulation -- | Takes only given amount (in seconds) from the signal (the rest is silence).-takeSnd :: Sigs a => D -> a -> a+takeSnd :: Sigs a => Sig -> a -> a takeSnd dt asig = sched (const $ return asig) $ withDur dt $ loadbang -- | Delays signals by the given amount (in seconds).-delaySnd :: Sigs a => D -> a -> a+delaySnd :: Sigs a => Sig -> a -> a delaySnd dt = segmentSnd dt infiniteDur -- | 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 ::Sigs a => Sig -> Sig -> a -> a segmentSnd dt dur asig = sched (const $ return asig) $ fmap (del dt) $ withDur dur $ loadbang -- | Repeats the signal with the given period.-repeatSnd :: Sigs a => D -> a -> a+repeatSnd :: Sigs a => Sig -> a -> a repeatSnd dt asig = sched (const $ return asig) $ segments dt -- | Plays the first signal for some time (in seconds) and then switches to the next one. -- -- > afterSnd dur sig1 sig2-afterSnd :: (Num b, Sigs b) => D -> b -> b -> b+afterSnd :: (Num b, Sigs b) => Sig -> b -> b -> b afterSnd dt a b = takeSnd dt a + delaySnd dt b -- | Creates a sequence of signals. Each segment lasts for -- fixed amount of time given in the first argument.-lineSnd :: (Num a, Sigs a) => D -> [a] -> a+lineSnd :: (Num a, Sigs a) => Sig -> [a] -> a lineSnd dt xs = foldr1 go xs where go a b = afterSnd dt a b -- | Creates a sequence of signals and loops over the sequence. -- Each segment lasts for fixed amount of time given in the first argument.-loopLineSnd :: (Num a, Sigs a) => D -> [a] -> a-loopLineSnd dt xs = repeatSnd (dt * (int $ length xs)) $ lineSnd dt xs+loopLineSnd :: (Num a, Sigs a) => Sig -> [a] -> a+loopLineSnd dt xs = repeatSnd (dt * (sig $ int $ length xs)) $ lineSnd dt xs -------------------------------------------------------------------------- -- sound files playback@@ -118,8 +118,8 @@ | otherwise = filelen $ text fileName -- | Produces repeating segments with the given time in seconds.-segments :: D -> Evt (Sco Unit)-segments dt = withDur dt $ metroE (sig $ recip dt)+segments :: Sig -> Evt (Sco Unit)+segments dt = withDur dt $ metroE (recip dt) -- Stereo @@ -131,13 +131,13 @@ -- | 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 :: Sig -> 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+loopSnd fileName = loopSndBy (sig $ 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.@@ -150,7 +150,7 @@ -- | Reads a segment from wav file. readSegWav :: D -> D -> Sig -> String -> (Sig, Sig)-readSegWav start end speed fileName = takeSnd (end - start) $ (diskin2 (text fileName) `withSig` speed) `withDs` [start, 1]+readSegWav start end speed fileName = takeSnd (sig $ end - start) $ (diskin2 (text fileName) `withSig` 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.@@ -170,12 +170,12 @@ | otherwise = diskin2 (text fileName) -- | The mono variant of the function @loopSndBy@.-loopSndBy1 :: D -> String -> Sig+loopSndBy1 :: Sig -> 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+loopSnd1 fileName = loopSndBy1 (sig $ lengthSnd fileName) fileName -- | The mono variant of the function @readWav@. readWav1 :: Sig -> String -> Sig@@ -187,7 +187,7 @@ -- | Reads a segment from wav file. readSegWav1 :: D -> D -> Sig -> String -> Sig-readSegWav1 start end speed fileName = takeSnd (end - start) $ diskin2 (text fileName) `withSig` speed `withDs` [start, 1]+readSegWav1 start end speed fileName = takeSnd (sig $ end - start) $ diskin2 (text fileName) `withSig` 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.
src/Csound/Air/Wave.hs view
@@ -31,7 +31,7 @@ urawTri, urawSaw, urawSqr, urawPw, urawTri', urawSaw', urawSqr', urawPw', urndRawTri, urndRawSaw, urndRawSqr, urndRawPw, -- * Noise- rndh, urndh, rndi, urndi, white, pink,+ rndh, urndh, rndi, urndi, white, pink, brown, -- * Frequency modulation fosc,@@ -253,6 +253,10 @@ -- | Pink noise. pink :: SE Sig pink = pinkish 1++-- | Brownian noise+brown :: SE Sig+brown = fmap (dcblock . integ . (* 0.1)) white -------------------------------------------------------------------------- -- lfo
src/Csound/Base.hs view
@@ -2,11 +2,11 @@ -- -- This module re-exports everything. ----- WARNING (for Csound users): the maximum amplitude is 1.0. There is no way to alter it. +-- WARNING (for Csound users): the maximum amplitude is 1.0. There is no way to alter it. -- Don't define your amplitudes with 9000 or 11000. But the good news are: all signals -- are clipped by 1 so that you can not damage your ears and your speakers by a little typo. module Csound.Base(- module Csound.Types, + module Csound.Types, module Csound.Control, module Csound.IO, module Csound.Air,@@ -28,7 +28,7 @@ module Csound.Typed.Opcode ) where -import Csound.Air +import Csound.Air import Csound.Tab import Csound.Tuning import Csound.Types@@ -44,10 +44,10 @@ import Data.Default import Data.Monoid import Control.Applicative hiding ((<*))- + import Csound.Typed.Opcode hiding ( button, display, space, lfo, initc7, ctrl7,- oscInit, oscListen, oscSend, + oscInit, oscListen, oscSend, lpshold, loopseg, loopxseg, partikkel, syncgrain, granule, sndwarp, sndwarpst, fof2, line, delay,
src/Csound/Control/Evt.hs view
@@ -107,7 +107,7 @@ impulseE = sigToEvt . impulse -- | Makes an event stream from list of events.-eventList :: [(D, D, a)] -> Evt (Sco a)+eventList :: [(Sig, Sig, a)] -> Evt (Sco a) eventList es = fmap (const $ har $ fmap singleEvent es) loadbang where singleEvent (start, duration, content) = del start $ str duration $ temp content
src/Csound/Control/Gui.hs view
@@ -123,14 +123,14 @@ -- | Hides the SE inside Source. joinSource :: Source (SE a) -> Source a-joinSource a = Source $ do- (g, mv) <- unSource a+joinSource a = do+ (g, mv) <- a v <- mv return (g, v) fromSource :: Source a -> SE a fromSource a = do- (gui, asig) <- unSource a+ (gui, asig) <- a panel gui return asig @@ -175,7 +175,7 @@ applyProportionsToList props f as = f $ zipWith sca (props ++ repeat 1) as genLifts :: ([Gui] -> Gui) -> ([a] -> b) -> [Source a] -> Source b-genLifts gf f as = Source $ fmap phi $ mapM unSource as+genLifts gf f as = fmap phi $ sequence as where phi xs = (gf gs, f vs) where (gs, vs) = unzip xs@@ -187,8 +187,8 @@ lift2 :: (Gui -> Gui -> Gui) -> (a -> b -> c) -> Source a -> Source b -> Source c lift2 gf f ma mb = source $ do- (ga, a) <- unSource ma- (gb, b) <- unSource mb+ (ga, a) <- ma+ (gb, b) <- mb return $ (gf ga gb, f a b) lift2' a b gf = lift2 (tfm2 a b gf)@@ -214,9 +214,9 @@ lift3 :: (Gui -> Gui -> Gui -> Gui) -> (a -> b -> c -> d) -> Source a -> Source b -> Source c -> Source d lift3 gf f ma mb mc = source $ do- (ga, a) <- unSource $ ma- (gb, b) <- unSource $ mb- (gc, c) <- unSource $ mc+ (ga, a) <- ma+ (gb, b) <- mb+ (gc, c) <- mc return $ (gf ga gb gc, f a b c) lift3' sa sb sc gf = lift3 (tfm3 sa sb sc gf)@@ -240,10 +240,10 @@ lift4 :: (Gui -> Gui -> Gui -> Gui -> Gui) -> (a -> b -> c -> d -> e) -> Source a -> Source b -> Source c -> Source d -> Source e lift4 gf f ma mb mc md = source $ do- (ga, a) <- unSource $ ma- (gb, b) <- unSource $ mb- (gc, c) <- unSource $ mc- (gd, d) <- unSource $ md+ (ga, a) <- ma+ (gb, b) <- mb+ (gc, c) <- mc+ (gd, d) <- md return $ (gf ga gb gc gd, f a b c d) lift4' sa sb sc sd gf = lift4 (tfm3 sa sb sc sd gf)@@ -268,11 +268,11 @@ lift5 :: (Gui -> Gui -> Gui -> Gui -> Gui -> Gui) -> (a1 -> a2 -> a3 -> a4 -> a5 -> b) -> Source a1 -> Source a2 -> Source a3 -> Source a4 -> Source a5 -> Source b lift5 gf f ma1 ma2 ma3 ma4 ma5 = source $ do- (ga1, a1) <- unSource $ ma1- (ga2, a2) <- unSource $ ma2- (ga3, a3) <- unSource $ ma3- (ga4, a4) <- unSource $ ma4- (ga5, a5) <- unSource $ ma5+ (ga1, a1) <- ma1+ (ga2, a2) <- ma2+ (ga3, a3) <- ma3+ (ga4, a4) <- ma4+ (ga5, a5) <- ma5 return $ (gf ga1 ga2 ga3 ga4 ga5, f a1 a2 a3 a4 a5) lift5' sa sb sc sd se gf = lift5 (tfm3 sa sb sc sd se gf)@@ -333,8 +333,8 @@ genBind :: (Gui -> Gui -> Gui) -> Source a -> (a -> Source b) -> Source b genBind gui ma mf = source $ do- (ga, a) <- unSource ma- (gb, b) <- unSource $ mf a+ (ga, a) <- ma+ (gb, b) <- mf a return (gui ga gb, b) -- | Creates a list of sources with mapping a function and stacks them horizontally.@@ -360,5 +360,5 @@ genMapM :: ([Gui] -> Gui) -> (a -> Source b) -> [a] -> Source [b] genMapM gui f xs = source $ do- (gs, vs) <- fmap unzip $ mapM (unSource . f) xs+ (gs, vs) <- fmap unzip $ mapM f xs return (gui gs, vs)
src/Csound/Control/Gui/Widget.hs view
@@ -79,8 +79,8 @@ -- | A radio button. It takes a list of values with labels. radioButton :: Arg a => String -> [(String, a)] -> Int -> Source (Evt a) radioButton title as initVal = source $ do- (g, ind) <- unSource $ butBank1 "" 1 (length as) (0, initVal)- gnames <- mapM (unDisplay . box) names+ (g, ind) <- butBank1 "" 1 (length as) (0, initVal)+ gnames <- mapM box names let val = listAt vals ind gui <- setTitle title $ padding 0 $ hor [sca 0.15 g, ver gnames] return (gui, val)@@ -89,7 +89,7 @@ -- | A matrix of values. matrixButton :: Arg a => String -> Int -> Int -> [a] -> (Int, Int) -> Source (Evt a) matrixButton name xn yn vals initVal = source $ do- (gui, ind) <- unSource $ butBank1 name xn yn initVal+ (gui, ind) <- butBank1 name xn yn initVal let val = listAt allVals ind return (gui, val) where allVals = readMatrix xn yn vals@@ -97,7 +97,7 @@ -- | 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 name as initVal = source $ do- (gui, ind) <- unSource $ radioButton name (zip names (fmap int [0 ..])) initVal+ (gui, ind) <- radioButton name (zip names (fmap int [0 ..])) initVal contInd <- stepper (sig $ int initVal) $ fmap sig ind let instr x = guardedTuple ( zipWith (\n f -> (contInd ==* (sig $ int n), f x)) [0 ..] funs@@ -108,7 +108,7 @@ -- | Matrix of functional values. funnyMatrix :: Tuple b => String -> Int -> Int -> [(a -> b)] -> (Int, Int) -> Source (a -> b) funnyMatrix name xn yn funs initVal@(x0, y0) = source $ do- (gui, ind) <- unSource $ butBank1 name xn yn initVal+ (gui, ind) <- butBank1 name xn yn initVal contInd <- stepper flattenInitVal $ fmap sig ind let instr x = guardedTuple ( zipWith (\n f -> (contInd ==* (sig $ int n), f x)) [0 ..] allFuns@@ -187,7 +187,7 @@ genNumbers :: ([Gui] -> Gui) -> [Double] -> Source Sig genNumbers gx as@(d:ds) = source $ do ref <- newGlobalCtrlRef (sig $ double d)- (gs, evts) <- fmap unzip $ mapM (unSource . button . show) as+ (gs, evts) <- fmap unzip $ mapM (button . show) as zipWithM_ (\x e -> runEvt e $ \_ -> writeRef ref (sig $ double x)) as evts res <- readRef ref return (gx gs, res)@@ -241,7 +241,7 @@ let f x y = (vals !! y) !! x return $ (gui, f) where- mkRow xs = fmap reGroupRow $ mapM (unSource . uncurry mk) xs+ mkRow xs = fmap reGroupRow $ mapM (uncurry mk) xs inits = split height width $ zip (names ++ repeat "") (as ++ repeat initVal) @@ -277,7 +277,7 @@ radioGroupSig :: ([Gui] -> Gui) -> [String] -> Int -> Source Sig radioGroupSig gcat names initVal = source $ do- (guis, writes, reads) <- fmap unzip3 $ mapM (\(i, tag) -> unSinkSource $ flip setToggleSig (i == initVal) tag) $ zip [0 ..] names+ (guis, writes, reads) <- fmap unzip3 $ mapM (\(i, tag) -> flip setToggleSig (i == initVal) tag) $ zip [0 ..] names curRef <- newGlobalCtrlRef (sig $ int initVal) current <- readRef curRef zipWithM_ (\w i -> w $ ifB (current ==* i) 1 0) writes ids@@ -399,7 +399,7 @@ -- The first argument is for external control. toggle' :: Evt D -> String -> Bool -> Source (Evt D) toggle' ctrl name initVal = source $ do- (gui, output, input) <- unSinkSource $ setToggle name initVal+ (gui, output, input) <- setToggle name initVal output ctrl return $ (gui, mappend ctrl input) @@ -452,7 +452,7 @@ radioGroupSig' :: ([Gui] -> Gui) -> Sig -> [String] -> Int -> Source Sig radioGroupSig' gcat ctrl names initVal = source $ do- (guis, writes, reads) <- fmap unzip3 $ mapM (\(i, tag) -> unSinkSource $ flip setToggleSig (i == initVal) tag) $ zip [0 ..] names+ (guis, writes, reads) <- fmap unzip3 $ mapM (\(i, tag) -> flip setToggleSig (i == initVal) tag) $ zip [0 ..] names curRef <- newGlobalCtrlRef (sig $ int initVal) when1 (changed [ctrl] ==* 1) $ writeRef curRef ctrl@@ -474,7 +474,7 @@ ctrlSig :: D -> Sig -> SinkSource Sig -> Source Sig ctrlSig initVal ctrl v = source $ do- (gui, output, input) <- unSinkSource v+ (gui, output, input) <- v ref <- newGlobalCtrlRef (sig initVal) when1 (changed [ctrl] ==* 1) $ writeRef ref ctrl when1 (changed [input] ==* 1) $ writeRef ref input
src/Csound/Control/Instr.hs view
@@ -1,5 +1,5 @@ {-# Language TypeFamilies, FlexibleContexts, FlexibleInstances, ScopedTypeVariables #-}--- | We can convert notes to sound signals with instruments. +-- | We can convert notes to sound signals with instruments. -- An instrument is a function: -- -- > (Arg a, Sigs b) => a -> SE b@@ -17,72 +17,72 @@ -- * By using midi-instruments (see @Csound.Control.Midi@). -- -- Sometimes we don't want to produce any sound. Our instrument is just--- a procedure that makes something useful without being noisy about it. +-- a procedure that makes something useful without being noisy about it. -- It's type is: -- -- > (Arg a) => a -> SE ()--- +-- -- To invoke the procedures there are functions with trailing underscore. -- For example we have the function @trig@ to convert event stream to sound: ----- > trig :: (Arg a, Sigs b) => (a -> SE b) -> Evts (D, D, a) -> b +-- > trig :: (Arg a, Sigs b) => (a -> SE b) -> Evts (D, D, a) -> b -- -- and we have a @trig@ with underscore to convert the event stream to -- the sequence of the procedure invkations: ----- > trig_ :: (Arg a) => (a -> SE ()) -> Evts (D, D, a) -> SE () +-- > trig_ :: (Arg a) => (a -> SE ()) -> Evts (D, D, a) -> SE () -- -- To invoke instruments from another instrumetnts we use artificial closures -- made with functions with trailing xxxBy. For example: -- -- > trigBy :: (Arg a, Arg c, Sigs b) => (a -> SE b) -> (c -> Evts (D, D, a)) -> (c -> b)--- +-- -- Notice that the event stream depends on the argument of the type c. Here goes -- all the parameters that we want to pass from the outer instrument. Unfortunately -- we can not just create the closure, because our values are not the real values. -- It's a text of the programm (a tiny snippet of it) to be executed. For a time being--- I don't know how to make it better. So we need to pass the values explicitly. +-- I don't know how to make it better. So we need to pass the values explicitly. -- -- For example, if we want to make an arpeggiator: -- -- > pureTone :: D -> SE Sig -- > pureTone cps = return $ mul env $ osc $ sig cps -- > where env = linseg [0, 0.01, 1, 0.25, 0]--- > +-- > -- > majArpeggio :: D -> SE Sig -- > majArpeggio = return . schedBy pureTone evts -- > where evts cps = withDur 0.5 $ fmap (* cps) $ cycleE [1, 5/3, 3/2, 2] $ metroE 5--- > +-- > -- > main = dac $ mul 0.5 $ midi $ onMsg majArpeggio -- -- We should use 'Csound.Base.schedBy' to pass the frequency as a parameter to the event stream. module Csound.Control.Instr( -- * Mix- -- | We can invoke instrument with specified notes. - -- Eqch note happens at some time and lasts for some time. It contains - -- the argument for the instrument. + -- | We can invoke instrument with specified notes.+ -- Eqch note happens at some time and lasts for some time. It contains+ -- the argument for the instrument. -- -- We can invoke the instrument on the sequence of notes (@sco@), process -- the sequence of notes with an effect (@eff@) and convert everything in- -- the plain sound signals (to send it to speakers or write to file or + -- the plain sound signals (to send it to speakers or write to file or -- use it in some another instrument). -- -- The sequence of notes is represented with type class @CsdSco@. Wich- -- has a very simple methods. So you can use your own favorite library - -- to describe the list of notes. If your type supports the scaling in + -- has a very simple methods. So you can use your own favorite library+ -- to describe the list of notes. If your type supports the scaling in -- the time domain (stretching the timeline) you can do it in the Mix-version -- (after the invokation of the instrument). All notes are rescaled all the- -- way down the Score-structure. + -- way down the Score-structure. Sco, Mix, sco, mix, eff, monoSco,- mixLoop, sco_, mix_, mixLoop_, mixBy, + mixLoop, sco_, mix_, mixLoop_, mixBy, infiniteDur, module Temporal.Media,- - -- * Evt + -- * Evt+ sched, retrig, schedHarp, schedUntil, schedToggle,- sched_, schedUntil_, + sched_, schedUntil_, schedBy, schedHarpBy, withDur, monoSched, @@ -90,7 +90,7 @@ -- | We can create named instruments. then we can trigger the named instruments with Csound API. -- Csound can be used not as a text to audio converter but also as a shared C-library. There are -- many bindings to many languages. For example we can use Python or Android SDK to create UI- -- and under the hood we can use the audio engine created with Haskell. The concept of named instruments + -- and under the hood we can use the audio engine created with Haskell. The concept of named instruments -- is the bridge for other lnguages to use our haskell-generated code. trigByName, trigByName_, trigByNameMidi, trigByNameMidi_,@@ -122,25 +122,25 @@ -- | Mixes the scores and plays them in the loop. mixLoop :: (Sigs a) => Sco (Mix a) -> a-mixLoop a = sched instr $ withDur dt $ repeatE unit $ metroE $ sig $ 1 / dt- where - dt = dur a +mixLoop a = sched instr $ withDur dt $ repeatE unit $ metroE $ 1 / dt+ where+ dt = dur a instr _ = return $ mix a -- | Mixes the procedures and plays them in the loop. mixLoop_ :: Sco (Mix Unit) -> SE ()-mixLoop_ a = sched_ instr $ withDur dt $ repeatE unit $ metroE $ sig $ 1 / dt- where +mixLoop_ a = sched_ instr $ withDur dt $ repeatE unit $ metroE $ 1 / dt+ where dt = dur a instr _ = mix_ a --- | Invokes an instrument with first event stream and +-- | Invokes an instrument with first event stream and -- holds the note until the second event stream is active. schedUntil :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> Evt c -> b schedUntil instr onEvt offEvt = sched instr' $ withDur infiniteDur onEvt- where - instr' x = do + where+ instr' x = do res <- instr x runEvt offEvt $ const $ turnoff return res@@ -148,21 +148,21 @@ -- | Invokes an instrument with toggle event stream (1 stands for on and 0 stands for off). schedToggle :: (Sigs b) => SE b -> Evt D -> b schedToggle res evt = schedUntil instr on off- where + where instr = const res (on, off) = splitToggle evt --- | Invokes an instrument with first event stream and +-- | Invokes an instrument with first event stream and -- holds the note until the second event stream is active. schedUntil_ :: (Arg a) => (a -> SE ()) -> Evt a -> Evt c -> SE () schedUntil_ instr onEvt offEvt = sched_ instr' $ withDur infiniteDur onEvt- where - instr' x = do + where+ instr' x = do res <- instr x runEvt offEvt $ const $ turnoff return res --- | Transforms an instrument from always on to conditional one. +-- | Transforms an instrument from always on to conditional one. -- The routput instrument plays only when condition is true otherwise -- it produces silence. playWhen :: forall a b. Sigs a => BoolSig -> (b -> SE a) -> (b -> SE a)@@ -176,8 +176,8 @@ ------------------------------------------------------------------------- -- singular --- | Sets the same duration for all events. It's useful with the functions @sched@, @schedBy@, @sched_@. -withDur :: D -> Evt a -> Evt (Sco a)+-- | Sets the same duration for all events. It's useful with the functions @sched@, @schedBy@, @sched_@.+withDur :: Sig -> Evt a -> Evt (Sco a) withDur dt = fmap (str dt . temp) retrig :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> b@@ -196,13 +196,13 @@ -- name of the instrument (should be defined with @trigByName@ or smth like that). -- -- kmode -- sum of the following values:--- +-- -- 0, 1, or 2: turn off all instances (0), oldest only (1), or newest only (2) -- -- 4: only turn off notes with exactly matching (fractional) instrument number, rather than ignoring fractional part -- -- 8: only turn off notes with indefinite duration (p3 < 0 or MIDI)--- +-- -- krelease -- if non-zero, the turned off instances are allowed to release, otherwise are deactivated immediately (possibly resulting in clicks) turnoffByName :: String -> Sig -> Sig -> SE () turnoffByName name kmode krelease = strTurnoff2 (text name) kmode krelease
src/Csound/Control/Osc.hs view
@@ -1,8 +1,8 @@ -- | Open Sound Control. module Csound.Control.Osc(- OscHost, OscPort, OscAddress, OscType,+ OscHost, OscPort, OscAddress, OscType, OscRef, -- * Server- initOsc, listenOsc, ListenOsc, OscVal, + initOsc, listenOsc, ListenOsc, OscVal, listenOscVal, listenOscSig, listenOscSig2, -- * Client sendOsc
src/Csound/IO.hs view
@@ -1,4 +1,4 @@-{-# Language FlexibleInstances, UndecidableInstances #-}+{-# Language 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?@@ -76,7 +76,7 @@ import Csound.Typed import Csound.Control.Gui -import Csound.Options(setSilent, setDac, setCabbage)+import Csound.Options(setSilent, setDac, setAdc, setCabbage) render :: Sigs a => Options -> SE a -> IO String render = renderOutBy@@ -90,12 +90,20 @@ instance {-# OVERLAPPING #-} RenderCsd (SE ()) where renderCsdBy = render_ +#if __GLASGOW_HASKELL__ >= 710 instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd a where renderCsdBy opt a = render opt (return a) instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (SE a) where renderCsdBy opt a = render opt a +instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Source a) where+ renderCsdBy opt a = renderCsdBy opt (fromSource a)++instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Source (SE a)) where+ renderCsdBy opt a = renderCsdBy opt (fromSourceSE a)+#endif+ instance {-# OVERLAPPABLE #-} (Sigs a, Sigs b) => RenderCsd (a -> b) where renderCsdBy opt f = renderEffBy opt (return . f) @@ -111,15 +119,9 @@ instance {-# OVERLAPPING #-} (Sigs a) => RenderCsd (a -> Source (SE Sig2)) where renderCsdBy opt f = renderEffBy opt (fromSourceSE . f) -instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Source a) where- renderCsdBy opt a = renderCsdBy opt (fromSource a)--instance {-# OVERLAPPABLE #-} Sigs a => RenderCsd (Source (SE a)) where- renderCsdBy opt a = renderCsdBy opt (fromSourceSE a)- instance {-# OVERLAPPING #-} RenderCsd (Source ()) where renderCsdBy opt src = renderCsdBy opt $ do- (ui, _) <- unSource src+ (ui, _) <- src panel ui instance {-# OVERLAPPING #-} RenderCsd (Source (SE ())) where@@ -173,7 +175,7 @@ where phi file = do runWithUserInterrupt $ player ++ " " ++ file --- | Renders csound code to file @tmp.csd@ with flags set to @-odac@ and @-Ma@+-- | Renders csound code to file @tmp.csd@ with flags set to @-odac@, @-iadc@ and @-Ma@ -- (sound output goes to soundcard in real time). dac :: (RenderCsd a) => a -> IO () dac = dacBy def@@ -183,7 +185,7 @@ dacBy opt' a = do writeCsdBy opt "tmp.csd" a runWithUserInterrupt $ "csound " ++ "tmp.csd"- where opt = opt' <> setDac+ where opt = opt' <> setDac <> setAdc -- | Output to dac with virtual midi keyboard. vdac :: (RenderCsd a) => a -> IO ()@@ -275,3 +277,64 @@ -- | Alias to process inputs of audio-card with 8 inputs. onCard8 :: (Sig8 -> a) -> (Sig8 -> a) onCard8= id+++#if __GLASGOW_HASKELL__ < 710++-- Sig++instance RenderCsd Sig where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig2++instance RenderCsd Sig2 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig2) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig2) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig2)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig3++instance RenderCsd Sig3 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig3) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig3) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig3)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig4++instance RenderCsd Sig4 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig4) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig4) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig4)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig5++instance RenderCsd Sig5 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig5) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig5) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig5)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig6++instance RenderCsd Sig6 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig6) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig6) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig6)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig7++instance RenderCsd Sig7 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig7) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig7) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig7)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++-- Sig8++instance RenderCsd Sig8 where { renderCsdBy opt a = render opt (return a) }+instance RenderCsd (SE Sig8) where { renderCsdBy opt a = render opt a }+instance RenderCsd (Source Sig8) where { renderCsdBy opt a = renderCsdBy opt (fromSource a) }+instance RenderCsd (Source (SE Sig8)) where { renderCsdBy opt a = renderCsdBy opt (fromSourceSE a) }++#endif
src/Csound/Options.hs view
@@ -3,16 +3,16 @@ -- * Shortcuts setDur,- setRates, setBufs, setGain, + setRates, setBufs, setGain, setJack, setAlsa, setCoreAudio, setMme,- setOutput, setInput, + setOutput, setInput, setDac, setAdc, setDacBy, setAdcBy, setThru, setSilent, setMidiDevice, setMa, setMessageLevel, noTrace,- setCabbage, + setCabbage, -- * Flags- -- | Csound's command line flags. See original documentation for + -- | Csound's command line flags. See original documentation for -- detailed overview: <http://www.csounds.com/manual/html/CommandFlagsCategory.html> Flags(..), @@ -23,7 +23,7 @@ -- * Realtime Audio Input/Output Rtaudio(..), PulseAudio(..),- + -- * MIDI File Input/Ouput MidiIO(..), @@ -34,7 +34,7 @@ Displays(..), DisplayMode(..), -- * Performance Configuration and Control- Config(..) + Config(..) ) where import Data.Monoid@@ -45,7 +45,7 @@ -- -- > setRates sampleRate blockSize setRates :: Int -> Int -> Options-setRates sampleRate blockSize = def +setRates sampleRate blockSize = def { csdSampleRate = Just sampleRate , csdBlockSize = Just blockSize } @@ -55,10 +55,12 @@ setBufs :: Int -> Int -> Options setBufs hw io = def { csdFlags = def { config = def { hwBuf = Just hw, ioBuf = Just io } } } +-- | Sets the default gain for the output signal (should be in range 0 to 1). setGain :: Double -> Options setGain d = def { csdGain = Just d' } where d' = max 0 $ min 1 $ d +-- | Runs as JACK unit with given name (first argument). setJack :: String -> Options setJack name = def { csdFlags = def { rtaudio = Just $ Jack name "input" "output" } } @@ -69,39 +71,49 @@ setJacko :: Jacko -> Options setJacko jackoSpec = def { csdJacko = Just jackoSpec } +-- | Sets real-time driver to Core Audio (use on OSX). setCoreAudio :: Options setCoreAudio = def { csdFlags = def { rtaudio = Just $ CoreAudio } } +-- | Sets real-time driver to Alsa (use on Linux). setAlsa :: Options setAlsa = def { csdFlags = def { rtaudio = Just $ Alsa } } +-- | Sets real-time driver to Mme (use on Windows). setMme :: Options setMme = def { csdFlags = def { rtaudio = Just $ Mme } } +-- | Sends output to speakers. setDac :: Options setDac = setDacBy "" +-- | Reads input from audio-card inputs. setAdc :: Options setAdc = setAdcBy "" +-- | Set's the input name of the device or file. setInput :: String -> 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 a = def { csdFlags = def { audioFileOutput = def { output = Just a } } } +-- | Provides name identifier for dac. setDacBy :: String -> Options setDacBy port = setOutput name- where name + where name | null port = "dac" | otherwise = "dac:" ++ port- ++-- | Provides name identifier for adc. setAdcBy :: String -> Options setAdcBy port = setInput name- where name + where name | null port = "adc" | otherwise = "adc:" ++ port +-- | Sets both dac and adc. setThru :: Options setThru = mappend setDac setAdc @@ -109,7 +121,15 @@ setSilent :: Options setSilent = (def { csdFlags = def { audioFileOutput = def { nosound = True } } }) --- | Sets midi device+-- | Sets midi device. It's an string identifier of the device.+--+-- Read MIDI events from device DEVICE. If using ALSA MIDI (-+rtmidi=alsa),+-- devices are selected by name and not number. So, you need to use an option+-- like -M hw:CARD,DEVICE where CARD and DEVICE are the card and device numbers (e.g. -M hw:1,0).+-- In the case of PortMidi and MME, DEVICE should be a number, and if it is out of range,+-- 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 a = def { csdFlags = def { midiRT = def { midiDevice = Just a } } } @@ -117,14 +137,20 @@ setMa :: Options setMa = setMidiDevice "a" +-- | Sets message level. For input integer value consult+-- the Csound docs+--+-- <http://csound.com/docs/manual/CommandFlagsCategory.html> setMessageLevel :: Int -> Options setMessageLevel n = def { csdFlags = def { displays = def { messageLevel = Just n }}} +-- | Sets the tracing or debug info of csound console to minimum. noTrace :: Options noTrace = setMessageLevel 0 --------------------------------------------- +-- | Provides options for Cabbage VST-engine. setCabbage :: Options setCabbage = setRates 48000 64 <> setNoRtMidi <> setMidiDevice "0"- where setNoRtMidi = def { csdFlags = def { rtmidi = Just NoRtmidi, audioFileOutput = def { nosound = True } }} + where setNoRtMidi = def { csdFlags = def { rtmidi = Just NoRtmidi, audioFileOutput = def { nosound = True } }}
src/Csound/Types.hs view
@@ -32,6 +32,9 @@ -- ** Constants idur, getSampleRate, getControlRate, getBlockSize, + -- ** BPM+ getBpm, setBpm, syn, takt,+ -- ** Converters ar, kr, ir, sig, @@ -140,5 +143,14 @@ (less, more) = splitAt (length conds `div` 2) conds rootCond = fst $ last less -+-- | It's used to synchronize changes with BPM.+-- Useful with LFO's or delay times.+syn :: Sig -> Sig+syn x = (bpm / 60) * x+ where bpm = getBpm +-- | Calculates seconds in ratio to global BPM.+-- It measures time according to changes in the BPM.+-- It's reciprocal to @syn@.+takt :: Sig -> Sig+takt = recip . syn