Safe Haskell | None |
---|---|
Language | Haskell98 |
- newtype P_Event = P_Event {}
- pplay :: Transport m => P Event -> m ()
- paudition :: P Event -> IO ()
- type P_Bind = (Key, P Field)
- padd :: P_Bind -> P Event -> P Event
- pbind :: [P_Bind] -> P Event
- (<|) :: F_Value v => Key -> P v -> P_Bind
- pkey :: Key -> P Event -> P Field
- pmono :: [P_Bind] -> P Event
- pmul :: P_Bind -> P Event -> P Event
- ppar :: [P Event] -> P Event
- pstretch :: P Field -> P Event -> P Event
- ptpar :: [(Time, P Event)] -> P Event
- pinstr' :: Instr -> P Field
- pinstr :: String -> P Field
- psynth :: Synthdef -> P Field
- pmce2 :: P Field -> P Field -> P Field
- pmce3 :: P Field -> P Field -> P Field -> P Field
- p_un_mce :: P Event -> P Event
- pedit :: Key -> (Field -> Field) -> P Event -> P Event
- p_time :: P Event -> P Time
- pkey_m :: Key -> P Event -> P (Maybe Field)
- pmerge :: P Event -> P Event -> P Event
- pmul' :: P_Bind -> P Event -> P Event
- ptmerge :: (Time, P Event) -> (Time, P Event) -> P Event
- punion :: P Event -> P Event -> P Event
- p_with :: P_Bind -> P Event -> P Event
- pNRT :: P Event -> NRT
SC3 Event Patterns
NewType for event patterns.
padd :: P_Bind -> P Event -> P Event Source
Padd. Add a value to an existing key, or set the key if it doesn't exist.
> p = Padd(\freq,801,Pbind(\freq,Pseq([100],1))); > p.asStream.all(()) == [('freq':901)]
let p = padd (K_freq,801) (pbind [(K_freq,return 100)]) in p == pbind [(K_freq,return 901)]
> Padd(\freq,Pseq([401,801],2),Pbind(\freq,100)).play
paudition (padd (K_freq,pseq [401,801] 2) (pbind [(K_freq,100)]))
let {d = pseq [pshuf 'α' [-7,-3,0,2,4,7] 2 ,pseq [0,1,2,3,4,5,6,7] 1] 1 ;p = pbind [(K_dur,0.15),(K_degree,d)] ;t n = padd (K_mtranspose,n) p} in paudition (pseq [p,t 1,t 2] inf)
pbind :: [P_Bind] -> P Event Source
Pbind. SC3 pattern to assign keys to a set of Field
patterns
making an Event
pattern.
Each input pattern is assigned to key in the resulting event pattern.
There are a set of reserved keys that have particular roles in the pattern library.
> p = Pbind(\x,Pseq([1,2,3],1),\y,Pseed(Pn(100,1),Prand([4,5,6],inf))); > p.asStream.all(()) == [('y':4,'x':1),('y':6,'x':2),('y':4,'x':3)]
let p = pbind [(K_param "x",prand 'α' [100,300,200] inf) ,(K_param "y",pseq [1,2,3] 1)] in pkey (K_param "x") p == toP [200,200,300]
K_param
can be elided if OverloadedStrings are in place.
:set -XOverloadedStrings
ptake 2 (pbind [("x",pwhitei 'α' 0 9 inf) ,("y",pseq [1,2,3] inf)])
Event
s implement variations on the SC3
Dur
and
Pitch
models.
> Pbind(\freq,Prand([300,500,231.2,399.2],inf), > \dur,0.1).play;
paudition (pbind [(K_freq,prand 'α' [300,500,231.2,399.2] inf) ,(K_dur,0.1)])
> Pbind(\freq, Prand([300,500,231.2,399.2],inf), > \dur,Prand([0.1,0.3],inf)).play;
paudition (pbind [(K_freq,prand 'α' [300,500,231.2,399.2] inf) ,(K_dur,prand 'β' [0.1,0.3] inf)])
> Pbind(\freq,Prand([1,1.2,2,2.5,3,4],inf) * 200, > \dur,0.1).play;
paudition (pbind [(K_freq,prand 'α' [1,1.2,2,2.5,3,4] inf * 200) ,(K_dur,0.1)])
paudition (pbind [(K_freq,pseq [440,550,660,770] 2) ,(K_dur,pseq [0.1,0.15,0.1] inf) ,(K_amp,pseq [0.1,0.05] inf) ,(K_param "pan",pseq [-1,0,1] inf)])
A finite binding stops the Event
pattern.
> Pbind(\freq,Prand([300,500,231.2,399.2],inf), > \dur,Pseq([0.1,0.2],3)).play;
paudition (pbind [(K_freq,prand 'α' [300,500,231.2,399.2] inf) ,(K_dur,pseq [0.1,0.2] 3)])
> Pbind(\freq,Prand([300,500,231.2,399.2],inf), > \dur,Prand([0.1,0.3],inf)).play
All infinite inputs:
paudition (pbind [(K_freq,prand 'α' [300,500,231.2,399.2] inf) ,(K_dur,prand 'β' [0.1,0.3] inf)])
Implicit field patterns is this context are infinite.
paudition (pbind [(K_freq,prand 'α' [1,1.2,2,2.5,3,4] inf * 200) ,(K_dur,0.1)])
let test = let {freq = control KR "freq" 440 ;amp = control KR "amp" 0.1 ;nharms = control KR "nharms" 10 ;pan = control KR "pan" 0 ;gate = control KR "gate" 1 ;s = blip AR freq nharms * amp ;e = linen gate 0.01 0.6 0.4 RemoveSynth ;o = offsetOut 0 (pan2 s pan e)} in synthdef "test" o
paudition (pbind [(K_instr,psynth test) ,(K_freq,prand 'α' [1,1.2,2,2.5,3,4] inf * 200) ,(K_dur,0.1)])
paudition (pbind [(K_instr,psynth test) ,(K_param "nharms",pseq [4,10,40] inf) ,(K_dur,pseq [1,1,2,1] inf / 10) ,(K_freq,pn (pseries 1 1 16 * 50) 4) ,(K_sustain,pseq [1/10,0.5,1,2] inf)])
let acid = let {freq = control KR "freq" 1000 ;gate = control KR "gate" 1 ;pan = control KR "pan" 0 ;cut = control KR "cut" 4000 ;res = control KR "res" 0.8 ;amp = control KR "amp" 1 ;s = rlpf (pulse AR freq 0.05) cut res ;d = envLinen 0.01 1 0.3 1 ;e = envGen KR gate amp 0 1 RemoveSynth d ;o = out 0 (pan2 s pan e)} in synthdef "acid" o
> Pbind(\instrument,\acid, > \dur,Pseq([0.25,0.5,0.25],4), > \root,-24, > \degree,Pseq([0,3,5,7,9,11,5,1],inf), > \pan,Pfunc({1.0.rand2}), > \cut,Pxrand([1000,500,2000,300],inf), > \rez,Pfunc({0.7.rand +0.3}), > \amp,0.2).play
paudition (pbind [(K_instr,psynth acid) ,(K_dur,pseq [0.25,0.5,0.25] 4) ,(K_root,-24) ,(K_degree,pseq [0,3,5,7,9,11,5,1] inf) ,(K_param "pan",pwhite 'α' (-1.0) 1.0 inf) ,(K_param "cut",pxrand 'β' [1000,500,2000,300] inf) ,(K_param "res",pwhite 'γ' 0.3 1.0 inf) ,(K_amp,0.2)])
> Pseq([Pbind(\instrument,\acid, > \dur,Pseq([0.25,0.5,0.25],4), > \root,-24, > \degree,Pseq([0,3,5,7,9,11,5,1],inf), > \pan,Pfunc({1.0.rand2}), > \cut,Pxrand([1000,500,2000,300],inf), > \rez,Pfunc({0.7.rand + 0.3}), > \amp,0.2), > Pbind(\instrument,\acid, > \dur,Pseq([0.25],6), > \root,-24, > \degree,Pseq([18,17,11,9],inf), > \pan,Pfunc({1.0.rand2}), > \cut,1500, > \rez,Pfunc({0.7.rand + 0.3}), > \amp,0.16)],inf).play
paudition (pseq [pbind [(K_instr,psynth acid) ,(K_dur,pseq [0.25,0.5,0.25] 4) ,(K_root,-24) ,(K_degree,pseq [0,3,5,7,9,11,5,1] inf) ,(K_param "pan",pwhite 'α' (-1.0) 1.0 inf) ,(K_param "cut",pxrand 'β' [1000,500,2000,300] inf) ,(K_param "res",pwhite 'γ' 0.3 1.0 inf) ,(K_amp,0.2)] ,pbind [(K_instr,psynth acid) ,(K_dur,pn 0.25 6) ,(K_root,-24) ,(K_degree,pser [18,17,11,9] inf) ,(K_param "pan",pwhite 'δ' (-1.0) 1.0 inf) ,(K_param "cut",1500) ,(K_param "res",pwhite 'ε' 0.3 1.0 inf) ,(K_amp,0.16)]] inf)
> Pbind(\instrument, \acid, > \dur, Pseq([0.25,0.5,0.25], inf), > \root, [-24,-17], > \degree, Pseq([0,3,5,7,9,11,5,1], inf), > \pan, Pfunc({1.0.rand2}), > \cut, Pxrand([1000,500,2000,300], inf), > \rez, Pfunc({0.7.rand +0.3}), > \amp, 0.2).play;
paudition (pbind [(K_instr,psynth acid) ,(K_dur,pseq [0.25,0.5,0.25] inf) ,(K_root,pmce2 (-24) (-17)) ,(K_degree,pseq [0,3,5,7,9,11,5,1] inf) ,(K_param "pan",pwhite 'α' (-1.0) 1.0 inf) ,(K_param "cut",pxrand 'β' [1000,500,2000,300] inf) ,(K_param "res",pwhite 'γ' 0.3 1.0 inf) ,(K_amp,0.2)])
A persistent synthesis node with freq and amp controls.
import Sound.SC3.ID
let {freq = control KR "freq" 440 ;amp = control KR "amp" 0.6 ;n = pinkNoise 'α' AR * amp} in audition (out 0 (pan2 (moogFF n freq 2 0) 0 1))
A pattern to set freq and amp controls at the most recently instantiated synthesis node.
:set -XOverloadedStrings
paudition (pbind [(K_type,prepeat "n_set") ,(K_id,(-1)) ,(K_freq,pwhite 'α' 100 1000 inf) ,(K_dur,0.2) ,(K_amp,toP [1,0.99 .. 0.1])])
let berlinb = let {k = control KR ;o = k "out" 0 ;f = k "freq" 80 ;a = k "amp" 0.01 ;p = k "pan" 0 ;g = k "gate" 1 ;env = decay2 g 0.05 8 * 0.0003 ;syn = rlpf (lfPulse AR f 0 (sinOsc KR 0.12 (mce2 0 (pi/2)) * 0.48 + 0.5)) (f * (sinOsc KR 0.21 0 * 18 + 20)) 0.07 ;syn_env = syn * env ;kil = detectSilence (mceChannel 0 syn_env) 0.1 0.2 RemoveSynth} in mrg2 (out o (a * mix (panAz 4 syn_env (mce2 p (p + 1)) 1 2 0.5))) kil
paudition (ppar [pbind [(K_degree,pseq [0,1,2,4,6,3,4,8] inf) ,(K_dur,0.5) ,(K_octave,3) ,(K_instr,psynth (synthdef "berlinb" berlinb))] ,pbind [(K_degree,pseq [0,1,2,4,6,3,4,8] inf) ,(K_dur,0.5) ,(K_octave,pmce2 2 1) ,(K_param "pan",pwhite 'a' (-1) 1 inf) ,(K_instr,psynth (synthdef "berlinb" berlinb))]])
pkey :: Key -> P Event -> P Field Source
Pkey. SC3 pattern to read Key
at Event
pattern. Note
-- however that in haskell is usually more appropriate to name the
-- pattern using let.
pkey K_freq (pbind [(K_freq,return 440)]) == toP [440] pkey K_amp (pbind [(K_amp,toP [0,1])]) == toP [0,1]
> Pbind(\degree,Pseq([Pseries(-7,1,14),Pseries(7,-1,14)],inf), > \dur,0.25, > \legato,Pkey(\degree).linexp(-7,7,2.0,0.05)).play
let {d = pseq [pseries (-7) 1 14,pseries 7 (-1) 14] inf ;l = fmap (Sound.SC3.Lang.Math.linexp (-7) 7 2 0.05) d} in paudition (pbind [(K_degree,d) ,(K_dur,0.25) ,(K_legato,l)])
pmono :: [P_Bind] -> P Event Source
Pmono. SC3 pattern that is a variant of pbind
for controlling
-- monophonic (persistent) synthesiser nodes.
let p = [(K_instr,pinstr' (Instr_Ref "default" False)) ,(K_id,100) ,(K_degree,pxrand 'α' [0,2,4,5,7,9,11] inf) ,(K_amp,pwrand 'β' [0.05,0.2] [0.7,0.3] inf) ,(K_dur,0.25)] in paudition (pmono p)
pmul :: P_Bind -> P Event -> P Event Source
Pmul. SC3 pattern to multiply an existing key by a value, or set the key if it doesn't exist.
let p = pbind [(K_dur,0.15),(K_freq,prand 'α' [440,550,660] 6)] in paudition (pseq [p,pmul (K_freq,2) p,pmul (K_freq,0.5) p] 2)
ppar :: [P Event] -> P Event Source
Ppar. Variant of ptpar
with zero start times.
The result of pmerge
can be merged again, ppar
merges a list of
patterns.
let {a = pbind [(K_param "a",pseq [1,2,3] inf)] ;b = pbind [(K_param "b",pseq [4,5,6] inf)] ;r = toP [e_from_list [(K_param "a",1),(K_fwd',0)] ,e_from_list [(K_param "b",4),(K_fwd',1)]]} in ptake 2 (ppar [a,b]) == r
let {p = pbind [(K_dur,0.2),(K_midinote,pseq [62,65,69,72] inf)] ;q = pbind [(K_dur,0.4),(K_midinote,pseq [50,45] inf)] ;r = pbind [(K_dur,0.6),(K_midinote,pseq [76,79,81] inf)]} in paudition (ppar [p,q,r])
Multiple nested ppar
patterns.
let {a u = pbind [(K_dur,0.2),(K_param "pan",0.5),(K_midinote,pseq u 1)] ;b l = pbind [(K_dur,0.4),(K_param "pan",-0.5),(K_midinote,pseq l 1)] ;f u l = ppar [a u,b l] ;h = pbind [(K_dur,prand 'α' [0.2,0.4,0.6] inf) ,(K_midinote,prand 'β' [72,74,76,77,79,81] inf) ,(K_db,-26) ,(K_legato,1.1)] ;m = pseq [pbind [(K_dur,3.2),(K_freq,return nan)] ,prand 'γ' [f [60,64,67,64] [48,43] ,f [62,65,69,65] [50,45] ,f [64,67,71,67] [52,47]] 12] inf} in paudition (ppar [h,m])
ptpar :: [(Time, P Event)] -> P Event Source
Ptpar. Merge a set of Event
patterns each with indicated
-- start Time
.
ptpar
is a variant of ppar
which allows non-equal start times.
let {f d p n = pbind [(K_dur,d),(K_param "pan",p),(K_midinote,n)] ;a = f 0.2 (-1) (pseries 60 1 15) ;b = f 0.15 0 (pseries 58 2 15) ;c = f 0.1 1 (pseries 46 3 15)} in paudition (ptpar [(0,a),(1,b),(2,c)])
let {d = pseq [pgeom 0.05 1.1 24,pgeom 0.5 0.909 24] 2 ;f n a p = pbind [(K_dur,d) ,(K_db,a) ,(K_param "pan",p) ,(K_midinote,pseq [n,n-4] inf)]} in audition (ptpar [(0,f 53 (-20) (-0.9)) ,(2,f 60 (-23) (-0.3)) ,(4,f 67 (-26) 0.3) ,(6,f 74 (-29) 0.9)])
Instrument Event Patterns
pinstr' :: Instr -> P Field Source
Pattern from Instr
. An Instr
is either a Synthdef
or a
name. In the Synthdef
case the instrument is asynchronously
sent to the server before processing the event, which has timing
implications. The pattern constructed here uses the Synthdef
for
the first element, and the subsequently the name.
paudition (pbind [(K_instr,pinstr' defaultInstr) ,(K_degree,toP [0,2,4,7]) ,(K_dur,0.25)])
pinstr :: String -> P Field Source
Instr
pattern from instrument name. See also psynth
(where
the sine instrument below is defined).
let {si = return (F_Instr (Instr_Ref "sine" True)) ;di = return (F_Instr (Instr_Ref "default" True)) ;i = pseq [si,si,di] inf ;p = pbind [(K_instr,i),(K_degree,pseq [0,2,4,7] inf),(K_dur,0.25)]} in paudition p
psynth :: Synthdef -> P Field Source
Synthdef
s can be used directly as an instrument using psynth
.
The default synthdef is at def
.
let sineSynth = let {f = control KR "freq" 440 ;g = control KR "gate" 1 ;a = control KR "amp" 0.1 ;d = envASR 0.01 1 1 (EnvNum (-4)) ;e = envGen KR g a 0 1 RemoveSynth d ;o = out 0 (sinOsc AR f 0 * e)} in synthdef "sine" o
paudition (pbind [(K_instr,psynth sineSynth) ,(K_degree,toP [0,2,4,7]) ,(K_dur,0.25)])
MCE Patterns
pmce2 :: P Field -> P Field -> P Field Source
Two-channel MCE for field patterns.
pmce2 (toP [1,2]) (toP [3,4]) == toP [f_array [1,3],f_array [2,4]]
let p = pmce2 (pseq [1,2] inf) (pseq [3,4] inf) in ptake 2 p == toP [f_array [1,3],f_array [2,4]]
p_un_mce :: P Event -> P Event Source
Remove one layer of MCE expansion at an event pattern. The pattern will be expanded only to the width of the initial input. Holes are filled with rests.
let {a = pseq [65,69,74] inf ;b = pseq [60,64,67,72,76] inf ;c = pseq [pmce3 72 76 79,pmce2 a b] 1} in paudition (p_un_mce (pbind [(K_midinote,c) ,(K_param "pan",pmce2 (-1) 1) ,(K_dur,1 `pcons` prepeat 0.15)]))
p_un_mce
translates via ppar
. This allows dur
related fields to
be MCE values. The underlying event processor also implements one
layer of MCE expansion.
paudition (p_un_mce (pbind [(K_dur,pmce2 0.25 0.2525) ,(K_legato,pmce2 0.25 2.5) ,(K_freq,pmce2 (pseq [300,400,500] inf) (pseq [302,402,502,202] inf)) ,(K_param "pan",pmce2 (-0.5) 0.5)]))
Non-SC3 Event Patterns
p_time :: P Event -> P Time Source
Pattern of start times of events at event pattern.
p_time (pbind [(K_dur,toP [1,2,3,2,1])]) == toP [0,1,3,6,8,9] p_time (pbind [(K_dur,pseries 0.5 0.5 5)]) == toP [0,0.5,1.5,3,5,7.5]
NRT
Transform an event pattern into a non-real time SC3 score.
let n = pNRT (pbind [(K_freq,prand 'α' [300,500,231.2,399.2] inf) ,(K_dur,pseq [0.1,0.2] 3)])
audition n
mapM_ (putStrLn . bundlePP) (nrt_bundles n)
Infinite NRT
scores are productive for audition
ing.
let n' = pNRT (pbind [(K_dur,0.25),(K_freq,pseq [300,600,900] inf)]) audition n' mapM_ (putStrLn . bundlePP) (take 9 (nrt_bundles n'))