Dear list users, I'm glad to announce the new version of my csound library [1].
There is a cool feature in this release that makes the library truly unique. It features a novel approach to scheduling of the audio signals. There is a new type called a signal segment data Seg a = ... The signal segment can contain a signal or a tuple of signals. We can limit the segment duration, play the sequence of segments and loop over segments. That's not new operation and user that keeps his eye on functional approach to the musical composition can recognize these functions. What makes them special is that duration of the segment can depend on event stream. So the segment can lasts as long as we press the key `q` on the keyboard. It can start when we hit the button or update the value of the slider. Any time duration can be bound to an event stream. Let's create a button: ghci > :m +Csound.Base > let btn = button "start" Now we can create a signal segment that is delayed with an event stream > let segFun evt = runSeg $ sdel evt $ slim evt $ toSeg $ osc 440 toSeg and runSeg wraps and unwraps the signal to segments. sdel delays a segment with event and slim limits it with event Let's apply the the function to button: > dac $ lift1 segFun btn We can see a button. If we press it the signal starts playing, if we press it again the signal stops and the program exits. What if we want to repeat the process? We can apply a loop to it: > let segFun evt = runSeg $ sloop $ sdel evt $ slim evt $ toSeg $ osc 440 > dac $ lift1 segFun btn What if we want to play several notes in sequence. Then we need to sequence segments with function sflow: > let segFun evt = runSeg $ sloop $ sdel evt $ sflow $ fmap (slim evt . toSeg . osc) [220, 330, 440] What if we want to stop the process? We can add another button: > let btnStop = button "stop" and limit the whole expression with clicks from the button: > let segFun evt stop = runSeg $ sloop $ slim stop $ sloop $ sdel evt $ sflow $ fmap (slim evt . toSeg . osc) [220, 330, 440] > dac $ hlift2 segFun btn btnStop The complete description can be found in the module Csound.Air.Seg and in the tutorial [2] There are handy functions that are based on this approach. We can trigger signals with keyboard or midi device or some event stream. New functions reside in the module Csound.Air.Sampler Let's review some of them with keyboard. Let's create a couple of signals: > let snd1 a b = mul 1.5 $ mlp (400 + 500 * uosc 0.25) 0.1 $ mul (sqrSeq [1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5] b) $ saw a It's a nice pulsating dance drone. Let's trigger it with keyboard! > dac $ charTrig "q" "a" (snd1 110 8) Try to press 'q' and `a` keys to get the beat going. Let's create another signal. It's intended to be high pitched pulses. > let snd2 a b = mul 0.75 $ mul (usqr (b / 4) * sqrSeq [1, 0.5] b) $ osc a Let's try it out. Try to press `w`, `e`, 'r'' keys. > dac $ mul 0.5 $ sum [charPush 'w' $ snd2 440 4, charPush 'e' $ snd2 330 4, charPush 'r' $ snd2 660 8] Note that only one keyboard event can be recognized. So if you press or depress several keys only one is going to take effect. It's a limitation of current implementation. It's not so with midi events. Let's join the results: > let pulses = mul 0.5 $ sum [charPush 'w' $ snd2 440 4, charPush 'e' $ snd2 330 4, charPush 'r' $ snd2 660 8] > let beat = mul 0.5 $ sum [charTrig "q" "a" (snd1 110 8), charTrig "t" "g" $ snd1 220 4] Let's create some drum sounds: > let snd3 = osc (110 * linseg [1, 0.2, 0]) > let snd4 = mul 3 $ hp 300 10 $ osc (110 * linseg [1, 0.2, 0]) > let drums = sum [charTrig "z" "" snd3, charTrig "x" "" snd4] Let's the rave along. > dac $ sum [pulses, mul 0.5 beat, mul 1.2 drums] [1] https://hackage.haskell.org/package/csound-expression [2] https://github.com/anton-k/csound-expression/blob/master/tutorial/chapters/SignalSegmentsTutorial.md Cheers, Anton -- Read the whole topic here: Haskell Art: http://lurk.org/r/topic/6S9g3rq2taXDGVyEjoakLK To leave Haskell Art, email haskell-...@group.lurk.org with the following email subject: unsubscribe