csound-expression 0.1.0 → 0.2.0
raw patch · 7 files changed
+216/−27 lines, 7 filesdep ~temporal-mediaPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: temporal-media
API changes (from Hackage documentation)
+ CsoundExpr.Base.Arithmetic: (^+) :: X a => Irate -> a -> a
+ CsoundExpr.Base.Score: dmap :: (Dur -> a -> b) -> Score a -> Score b
+ CsoundExpr.Base.Score: dmapRel :: (Dur -> a -> b) -> Score a -> Score b
+ CsoundExpr.Base.Score: dropS :: Dur -> Score a -> Score a
+ CsoundExpr.Base.Score: linseg :: (Num t, Ord t, Fractional t) => [t] -> t -> t
+ CsoundExpr.Base.Score: pedal :: Dur -> Score a -> Score a
+ CsoundExpr.Base.Score: pedalBy :: (Time -> Dur -> a -> (b, Dur)) -> Score a -> Score b
+ CsoundExpr.Base.Score: reprise :: Arrangeable a => a -> a -> a -> a
+ CsoundExpr.Base.Score: reverseS :: Score a -> Score a
+ CsoundExpr.Base.Score: rondo :: Arrangeable a => a -> a -> a -> a
+ CsoundExpr.Base.Score: sustain :: Dur -> Score a -> Score a
+ CsoundExpr.Base.Score: sustainBy :: (Time -> Dur -> a -> (b, Dur)) -> Score a -> Score b
+ CsoundExpr.Base.Score: takeS :: Dur -> Score a -> Score a
+ CsoundExpr.Base.Score: tdmap :: (Time -> Dur -> a -> b) -> Score a -> Score b
+ CsoundExpr.Base.Score: tdmapRel :: (Time -> Dur -> a -> b) -> Score a -> Score b
+ CsoundExpr.Base.Score: tmapRel :: (Time -> a -> b) -> Score a -> Score b
+ CsoundExpr.Base.Score: trill :: Arrangeable a => Int -> a -> a -> a
+ CsoundExpr.Base.Score: tstretch :: TemporalStretchable Dur a => (Time -> Dur) -> a -> a
+ CsoundExpr.Base.Score: tstretchRel :: TemporalStretchable Dur a => (Time -> Dur) -> a -> a
- CsoundExpr.Base.Score: tmap :: (Dur -> a -> b) -> Score a -> Score b
+ CsoundExpr.Base.Score: tmap :: (Time -> a -> b) -> Score a -> Score b
Files
- Changelog +26/−3
- csound-expression.cabal +5/−3
- src/CsoundExpr/Base/Arithmetic.hs +9/−4
- src/CsoundExpr/Base/Header.hs +1/−1
- src/CsoundExpr/Base/Score.hs +128/−7
- src/CsoundExpr/Tutorial/Composition.hs +44/−6
- src/CsoundExpr/Tutorial/Orchestra.hs +3/−3
Changelog view
@@ -1,11 +1,34 @@+-> 0.2.0 fixes few docs bugs,++ new functions in CsoundExpr.Base.Score :++ extends TemporalFunctor with new methods+ tmap, dmap, tdmap for mapping dependent on time/duration,+ enveloping on Score level (diminuendo or crescendo)+ + WARNING : API changes : tmap is now dmap and tmap stands for time + dependent mapping (not duration as it was before),++ new class Sustainable, adds ability for legato and pedal (sustain,+ sustainBy functions)++ new class TemporalStretch, adds ability to stretch score depndent+ on note's start time (ritardando or accelerando)++ adds list-like operations on Scores : reverseS, takeS, dropS++ new function in CsoundExpr.Base.Arithmetic + ^+ - shift with Irate+ + -> 0.1.0 new type BoolRate, functional if/then/else is possible new operators : <^>, <%> scaling becomes ^* (due to <* is defined as lower then for signals) --> 0.0.3 fix a bug with p-fields assignment+-> 0.0.3 fixes a bug with p-fields assignment --> 0.0.2 fix a bug in dependencies+-> 0.0.2 fixes a bug in dependencies --> 0.0.1 add Tutorial+-> 0.0.1 adds Tutorial 0.0
csound-expression.cabal view
@@ -1,12 +1,14 @@ Name: csound-expression-Version: 0.1.0+Version: 0.2.0 Cabal-Version: >= 1.2 License: BSD3 License-File: LICENSE Author: Anton Kholomiov Maintainer: <anton.kholomiov@gmail.com> Synopsis: Csound combinator library-Description: Csound code generator. See "CsoundExpr.Tutorial" for guides and examples.+Description: Csound code generator. See "CsoundExpr.Tutorial" for guides and examples. ++ WARNING : API changes (see TemporalFunctor method tmap, and ./Changelog) Category: Sound, Music Stability: Experimental Tested-With: GHC==6.12.1@@ -18,7 +20,7 @@ Library Build-Depends: base >= 4, base < 5, containers, mtl == 2.0.1.0, pretty, - filepath, directory, haskell98, Boolean, temporal-media == 0.0+ filepath, directory, haskell98, Boolean, temporal-media == 0.1.0 Hs-Source-Dirs: src/ Exposed-Modules: CsoundExpr
src/CsoundExpr/Base/Arithmetic.hs view
@@ -6,7 +6,7 @@ -- | Arithmetic operators module CsoundExpr.Base.Arithmetic - (Opr2, (<+>), neg, (<->), (<*>), (</>), (<^>), (<%>), (^*))+ (Opr2, (<+>), neg, (<->), (<*>), (</>), (<^>), (<%>), (^*), (^+)) where import Prelude hiding (div)@@ -24,7 +24,7 @@ import CsoundExpr.Base.Boolean infixr 9 ^* -infixr 8 <^>+infixr 8 ^+, <^> infixr 7 <*>, </> infixr 6 <+>, <->, <%> @@ -62,17 +62,19 @@ ---------------------------------------------------------- -- Type inference -(<+>), (<->), (<*>), (</>), (<^>), (<%>) :: (X a, X b, X (Opr2 a b)) => a -> b -> Opr2 a b+(<+>), (<->), (<*>), (</>) :: (X a, X b, X (Opr2 a b)) => a -> b -> Opr2 a b (<+>) = subst $ opr2 "+" (+) (<->) = subst $ opr2 "-" (-) (<*>) = subst $ opr2 "*" (*) (</>) = subst $ opr2 "/" (/) --- | "power of" operator+-- | \"power of\" operator+(<^>) :: (X a, X b, X (Opr2 a b)) => a -> b -> Opr2 a b (<^>) = subst $ opr2 "^" (**) -- | modulus operator+(<%>) :: (X a, X b, X (Opr2 a b)) => a -> b -> Opr2 a b (<%>) = subst $ opr2 "%" modDouble -- | negation@@ -83,6 +85,9 @@ (^*) :: X a => Irate -> a -> a (^*) = subst $ opr2 "*" (*) +-- | shifting+(^+) :: X a => Irate -> a -> a+(^+) = subst $ opr2 "+" (+) modDouble :: Double -> Double -> Double modDouble a b = signum a * until ( < b') (+ (-b')) a'
src/CsoundExpr/Base/Header.hs view
@@ -156,6 +156,6 @@ gSr <=> 44100, gKr <=> 4410, gKsmps <=> 10,- gNchnls <=> 1]+ gNchnls <=> 2]
src/CsoundExpr/Base/Score.hs view
@@ -1,15 +1,36 @@ {-# LANGUAGE FlexibleContexts #-} module CsoundExpr.Base.Score (- Arrangeable(..),- Time, Dur, Score, toList,- dur, rest, stretch, note, delay,- line, chord, loop, cut, tmap)+ -- * Types+ Time, Dur, Score, + -- * Constructors+ rest, note, toList,+ -- * Duration querry+ dur, + -- * Arrangers+ Arrangeable(..),+ line, chord, loop, trill, rondo, reprise, + -- * Transformers+ -- ** In time domain+ delay, + stretch, tstretch, + cut, takeS, dropS, reverseS,+ pedal, pedalBy,+ sustain, sustainBy,+ -- ** Mappings+ tmap, dmap, tdmap, + -- * Misc+ tmapRel, dmapRel, tdmapRel, tstretchRel,+ linseg+) where import CsoundExpr.Translator.Types(Time, Dur) import qualified Temporal.Media as M-import Temporal.Media(Arrangeable(..))+import Temporal.Media(Arrangeable(..), linseg) +import Control.Arrow(second)++ -- | representing score type Score a = M.MediaUnit Dur () a @@ -26,6 +47,41 @@ stretch :: M.Stretchable Dur a => Dur -> a -> a stretch = M.stretch +-- | stretch in time domain depndent on note's time+tstretch :: M.TemporalStretchable Dur a => (Time -> Dur) -> a -> a+tstretch = M.tstretch++-- | relative 'tstretch' +--+-- time normalized by durtion of value+tstretchRel :: M.TemporalStretchable Dur a => (Time -> Dur) -> a -> a+tstretchRel = M.tstretchRel++-- | adds given amount of duration to all notes+sustain :: Dur -> Score a -> Score a+sustain = M.sustain++-- | general sustain+sustainBy :: (Time -> Dur -> a -> (b, Dur)) -> Score a -> Score b+sustainBy = M.sustainBy++-- | adds sustain, but total duration of score elements remains unchaged+--+-- notes are sustained within total duration interval.+-- adds given amount of time to all notes.+pedal :: Dur -> Score a -> Score a +pedal dt' = pedalBy (\t dt a -> (a, dt + dt'))++-- | general \"pedal\"+--+-- total duration of score element remains unchanged. notes are sustained within total duration interval+pedalBy :: (Time -> Dur -> a -> (b, Dur)) -> Score a -> Score b+pedalBy f x = M.sustainBy f' x+ where d = dur x+ f' t dt a = second (min (d - t)) $ f t dt a + + + -- | constructor of score note :: Dur -> a -> Score a note = M.temp@@ -44,14 +100,79 @@ loop :: Arrangeable a => Int -> a -> a loop = M.loop +-- | loop for two groups of notes+trill :: Arrangeable a => Int -> a -> a -> a+trill n a b = loop n $ line [a, b]++-- | rondo form+--+-- >rondo a b c = line [a, b, a, c, a]+rondo :: Arrangeable a => a -> a -> a -> a+rondo a b c = line [a, b, a, c, a]++-- | reprise form+--+-- >reprise a b1 b2 = line [a, b1, a, b2]+reprise :: Arrangeable a => a -> a -> a -> a+reprise a b c = line [a, b, a, c]+ -- | extracting score parts in some time interval. -- it reverses output if @t1 < t0@. cut :: Dur -> Dur -> Score a -> Score a cut = M.cut --- | temporal functor-tmap :: (Dur -> a -> b) -> Score a -> Score b+-- | take sub-score from begining+takeS :: Dur -> Score a -> Score a+takeS = M.take++-- | drop sub-score+dropS :: Dur -> Score a -> Score a+dropS = M.drop++-- | reverse score+reverseS :: Score a -> Score a+reverseS = M.reverse++-- | temporal functor 'tmap' method for scores+--+-- map with time+tmap :: (Time -> a -> b) -> Score a -> Score b tmap = M.tmap++-- | temporal functor 'dmap' method for scores+--+-- map with duration+dmap :: (Dur -> a -> b) -> Score a -> Score b+dmap = M.dmap++-- | temporal functor 'tdmap' method for scores+--+-- map with time and duration+tdmap :: (Time -> Dur -> a -> b) -> Score a -> Score b+tdmap = M.tdmap+++-- | relative 'tmap' +--+-- map with time normalized by total duration value+tmapRel :: (Time -> a -> b) -> Score a -> Score b+tmapRel = M.tmapRel++-- | relative 'dmap' +--+-- map with duration normalized by total duration value+dmapRel :: (Dur -> a -> b) -> Score a -> Score b+dmapRel = M.dmapRel++-- | relative 'tdmap'+--+-- map with time and duration normalized by total duration value+tdmapRel :: (Time -> Dur -> a -> b) -> Score a -> Score b+tdmapRel = M.tdmapRel++++ -- | transform 'Score' to 'EventList' toList :: Score a -> M.EventList Dur a
src/CsoundExpr/Tutorial/Composition.hs view
@@ -109,13 +109,40 @@ -- ** TemporalFunctor {-|- There is class called 'TemporalFunctor' with method 'tmap'. - First argument of tmap's function means function from duration - of value @t@ and value itself @a@ to new value @b@.+ There is class called 'TemporalFunctor' with methods for time/duration dependent mapping.+ There are methods + + + 'tmap' - for time dependent mapping, + + 'dmap' - for duration dependent mapping and + 'tdmap' - for time/duration dependent mapping. + + >class Dur t => TemporalFunctor f where- > tmap :: (t -> a -> b) -> f a -> f b+ > tmap :: (t -> a -> b) -> f a -> f b+ > dmap :: (t -> a -> b) -> f a -> f b+ > tdmap :: (t -> t -> a -> b) -> f a -> f b + Note in 'Score' can be thought of as an event that happens in some time @t@ + and lasts for some time @d@. Thus note carries three parametters value @a@, start time @t@ + and duration time @d@. 'TemporalFunctor' provides different mappings over time parameters.++ First argument of 'tmap' function means function from start time of+ note and note's value @a@ to new value @b@+++ example : fadeOut++ >instr :: Irate -> SignalOut+ >instr vol = out $ oscilA [] vol (num 440) $ gen10 4096 [1]+ >+ >sco = fmap instr $ tmap (\t v -> double (5 - t) * v) $ loop 5 $ note 1 1000 ++ First argument of dmap's function means function from duration + of value @t@ and value itself @a@ to new value @b@.+ It allows to construct instruments that can rely on note duration. >instr :: Dur -> Irate -> SignalOut@@ -127,11 +154,22 @@ >v1 = 1.5 * v0 >v0 = 5000 >- >sco = tmap instr $ line [note 0.5 v1, note 0.5 v0, rest 1, note 2 v1]+ >sco = dmap instr $ line [note 0.5 v1, note 0.5 v0, rest 1, note 2 v1] Note : - >stretch t (tmap instr sco) =/= tmap instr (stretch t sco)+ >stretch t (dmap instr sco) =/= dmap instr (stretch t sco)++ 'tdmap' combines 'tmap' and 'dmap' behavior. It's first argument is a function from+ time, duration and value to value.++ There are helping functions 'tmapRel', 'dmapRel' and 'tdmapRel'. They express + time/duration dependent mapping with normalization in time domain. All time values are notmalized by + total duration of value.++ @sco@ of fadeOut example can be rewritten as++ >sco = fmap instr $ tmapRel (\t v -> double (1 - t) * v ) $ loop 5 $ note 1 5000 -}
src/CsoundExpr/Tutorial/Orchestra.hs view
@@ -303,9 +303,9 @@ delay 12 $ loop 4 scoBass, scoDrums] -scoAahs1 = loop 2 $ tmap aahs $ soloNotes [d 1, cs 1, e 0, fs 0]-scoAahs2 = loop 2 $ tmap aahs $ soloNotes [d 1, cs 1, a 0, d 0]-scoAahs3 = loop 2 $ tmap aahs $ soloNotes [a 0, cs 1, g 0, fs 0]+scoAahs1 = loop 2 $ dmap aahs $ soloNotes [d 1, cs 1, e 0, fs 0]+scoAahs2 = loop 2 $ dmap aahs $ soloNotes [d 1, cs 1, a 0, d 0]+scoAahs3 = loop 2 $ dmap aahs $ soloNotes [a 0, cs 1, g 0, fs 0] solo = delay 20 $ chord [ scoAahs1,