hsc3-lang-0.15: Haskell SuperCollider Language

Safe HaskellNone
LanguageHaskell98

Sound.SC3.Lang.Pattern.P.Event

Contents

Description

sclang event pattern functions.

SC3 event patterns: padd (Padd), pbind (Pbind), pkey (Pkey), pmono (Pmono), pmul (Pmul), ppar (Ppar), pstretch (Pstretch), ptpar (Ptpar). pedit, pinstr, pmce2, psynth, punion.

Synopsis

SC3 Event Patterns

newtype P_Event Source

NewType for event patterns.

Constructors

P_Event 

Fields

p_Event :: P Event
 

Instances

Audible P_Event

P_Event is audible, P Event could be as well but it'd be an orphan instance.

pplay :: Transport m => P Event -> m () Source

type P_Bind = (Key, P Field) Source

Synonym for (Key,'P Field').

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)])

Events 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))]])

(<|) :: F_Value v => Key -> P v -> P_Bind infixl 3 Source

Operator to lift F_Value pattern to P_Bind tuple.

let {r = True `pcons` preplicate 3 False :: P Bool}
in pbind [K_rest <| r] == pbind [(K_rest,pseq [1,0,0,0] 1)]

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])

pstretch :: P Field -> P Event -> P Event Source

Pstretch. SC3 pattern to do time stretching. It is equal to pmul at K_stretch.

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)]}
in paudition (pseq [p,pstretch 0.5 p,pstretch 2 p] inf)

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

Synthdefs 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]]

pmce3 :: P Field -> P Field -> P Field -> P Field Source

Three-channel MCE for field patterns.

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

pedit :: Key -> (Field -> Field) -> P Event -> P Event Source

Edit a at Key in each element of an Event pattern.

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]

pkey_m :: Key -> P Event -> P (Maybe Field) Source

Pattern to extract as at Key from an Event pattern.

pkey_m K_freq (pbind [(K_freq,return 440)]) == toP [Just 440]

pmerge :: P Event -> P Event -> P Event Source

Variant of ptmerge with zero start times.

pmerge merges two event streams, adding fwd' entries as required.

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)]}
in paudition (pmerge p q)

pmul' :: P_Bind -> P Event -> P Event Source

Variant that does not insert key.

ptmerge :: (Time, P Event) -> (Time, P Event) -> P Event Source

Merge two Event patterns with indicated start Times.

punion :: P Event -> P Event -> P Event Source

Left-biased union of event patterns.

p_with :: P_Bind -> P Event -> P Event Source

punion of pbind of return, ie. p_with (K_Instr,psynth s).

NRT

pNRT :: P Event -> NRT Source

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 auditioning.

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'))