packages feed

hsc3-data (empty) → 0.15

raw patch · 8 files changed

+924/−0 lines, 8 filesdep +Globdep +SVGPathdep +basesetup-changed

Dependencies added: Glob, SVGPath, base, bifunctors, hcg-minus, hmt, hsc3-lang, hsc3-plot, hsc3-sf-hsndfile, safe, split, xml

Files

+ README view
@@ -0,0 +1,12 @@+hsc3-data - data functions for SC3 related work+-----------------------------------------------++[hs]: http://haskell.org/+[sc3]: http://audiosynth.com/+[hsc3]: http://rd.slavepianos.org/?t=hsc3+[hsc3-data]: http://rd.slavepianos.org/?t=hsc3-data++© [rohan drape][rd], 2013-2014, [gpl]++[rd]: http://rd.slavepianos.org/+[gpl]: http://gnu.org/copyleft/
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ Sound/SC3/Data/Math/Bourke.hs view
@@ -0,0 +1,86 @@+-- | <http://paulbourke.net/>+module Sound.SC3.Data.Math.Bourke where++-- | 2-element /h/ transform.+h_transform_2 :: Num t => t -> ((t,t) -> (t,t)) -> (t,t) -> (t,t)+h_transform_2 h f (x,y) =+    let (x',y') = f (x,y)+    in (x + h * x',y + h * y')++-- | 3-element /h/ transform.+h_transform_3 :: Num t => t -> ((t,t,t) -> (t,t,t)) -> (t,t,t) -> (t,t,t)+h_transform_3 h f (x,y,z) =+    let (x',y',z') = f (x,y,z)+    in (x + h * x',y + h * y',z + h * z')++-- | <http://paulbourke.net/fractals/lorenz/>+lorenz :: Num t => t -> t -> t -> (t,t,t) -> (t,t,t)+lorenz a b c (x,y,z) =+    (a * (y - x)+    ,x * (b - z) - y+    ,x * y - c * z)++{- | <http://paulbourke.net/fractals/lorenz/>++> import Sound.SC3.Plot {- hsc3-plot -}++> let l = iterate (lorenz_h 0.01 10 28 (8/3)) (0.1,0.0,0.0)+> in plot_p3_ln [take 5000 l]++> let {l = iterate (lorenz_h 0.01 10 28 (8/3)) (0.1,0.0,0.0)+>     ;f (x,_,z) = (x,z)}+> in plot_p2_ln [take 15000 (map f l)]++-}+lorenz_h :: Num t => t -> t -> t -> t -> (t,t,t) -> (t,t,t)+lorenz_h h a b c = h_transform_3 h (lorenz a b c)++-- | <http://paulbourke.net/fractals/rossler/>+rossler :: Num t => t -> t -> t -> (t, t, t) -> (t, t, t)+rossler a b c (x,y,z) =+    (negate y - z+    ,x + a * y+    ,b + z * (x - c))++{- | <http://paulbourke.net/fractals/rossler/>++> plot_p3_ln [take 5000 (iterate (rossler_h 0.02 0.2 0.2 5.7) (0.1,0,0))]++-}+rossler_h :: Num t => t -> t -> t -> t -> (t,t,t) -> (t,t,t)+rossler_h h a b c = h_transform_3 h (rossler a b c)++{- | <http://paulbourke.net/fractals/peterdejong/>++> let pdj a b c d =+>   let vw x = plot_p2_pt [take 15000 x]+>   in vw (iterate (peter_de_jong a b c d) (-0.72,-0.64))++> pdj 1.4 (-2.3) 2.4 (-2.1)+> pdj 2.01 (-2.53) 1.61 (-0.33)+> pdj (-2.7) (-0.09) (-0.86) (-2.2)+> pdj (-2.24) 0.43 (-0.65) (-2.43)+> pdj (-2.0) (-2.0) (-1.2) 2.0++-}+peter_de_jong :: Floating t => t -> t -> t -> t -> (t, t) -> (t, t)+peter_de_jong a b c d (x,y) =+    (sin (a * y) - cos (b * x)+    ,sin (c * x) - cos (d * y))++{- | <http://paulbourke.net/fractals/clifford/>++> let clf a b c d =+>   let vw x = plot_p2_pt [take 12500 x]+>   in vw (iterate (clifford a b c d) (-0.72,-0.64))++> clf (-1.4) (1.6) (1.0) (0.7)+> clf (1.1) (-1.0) (1.0) (1.5) {- not as pb indicates -}+> clf (1.6) (-0.6) (-1.2) (1.6)+> clf (1.7) (1.7) (0.6) (1.2)++-}+clifford :: Floating t => t -> t -> t -> t -> (t, t) -> (t, t)+clifford a b c d (x,y) =+    (sin (a * y) + c * cos (a * x)+    ,sin (b * x) + d * cos (b * y))
+ Sound/SC3/Data/Math/Loudness.hs view
@@ -0,0 +1,121 @@+-- | Perceptual loudness functions.+module Sound.SC3.Data.Math.Loudness where++-- * A Weighting++{- | A-weighting curve multiplier function, ie. for linear magnitude+-- value.  See <http://en.wikipedia.org/wiki/A-weighting>++> import Sound.SC3.Plot++> let {f w = map w [20::Double,50 .. 20000]+>     ;r = [a_weighting_R,b_weighting_R,c_weighting_R,d_weighting_R]}+> in plotTable (map f r)++> let {f w = zip (map log [1..]) (map w [25,50 .. 20000])+>     ;r = [a_weighting_R,b_weighting_R,c_weighting_R,d_weighting_R]}+> in plot_p2_ln (map f r)++-}+a_weighting_R :: Floating a => a -> a+a_weighting_R f =+    let sq x = x * x+        dot = foldl1 (*)+        n = dot [sq 12200+                ,f ** 4]+        d = dot [sq f + sq 20.6+                ,sqrt ((sq f + sq 107.7) * (sq f + sq 737.9))+                ,sq f + sq 12200]+    in n / d++-- | A-weighting curve Db offset (additive) function, ie. for+-- un-weighted Db readings.+--+-- > plotTable1 (map a_weighting [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map a_weighting [25,50 .. 20000])]+a_weighting :: Floating a => a -> a+a_weighting f = 2 + 20 * logBase 10 (a_weighting_R f)++-- * B Weighting++-- | B-weighting curve multiplier function, ie. for linear magnitude+-- value.  See <http://en.wikipedia.org/wiki/A-weighting>+--+-- > import Sound.SC3.Plot+-- > plotTable1 (map b_weighting_R [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map b_weighting_R [25,50 .. 20000])]+b_weighting_R :: Floating a => a -> a+b_weighting_R f =+    let sq x = x * x+        dot = foldl1 (*)+        n = dot [sq 12200+                ,f ** 3]+        d = dot [sq f + sq 20.6+                ,sqrt (sq f + sq 158.5)+                ,sq f + sq 12200]+    in n / d++-- | B-weighting curve Db offset (additive) function, ie. for+-- un-weighted Db readings.+--+-- > plotTable1 (map b_weighting [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map b_weighting [25,50 .. 20000])]+b_weighting :: Floating a => a -> a+b_weighting f = 0.17 + 20 * logBase 10 (b_weighting_R f)++-- * C Weighting++-- | C-weighting curve multiplier function, ie. for linear magnitude+-- value.  See <http://en.wikipedia.org/wiki/A-weighting>+--+-- > import Sound.SC3.Plot+-- > plotTable1 (map c_weighting_R [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map c_weighting_R [25,50 .. 20000])]+c_weighting_R :: Floating a => a -> a+c_weighting_R f =+    let sq x = x * x+        dot = foldl1 (*)+        n = dot [sq 12200+                ,f ** 2]+        d = dot [sq f + sq 20.6+                ,sq f + sq 12200]+    in n / d++-- | C-weighting curve Db offset (additive) function, ie. for+-- un-weighted Db readings.+--+-- > plotTable1 (map c_weighting [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map c_weighting [25,50 .. 20000])]+c_weighting :: Floating a => a -> a+c_weighting f = 0.06 + 20 * logBase 10 (c_weighting_R f)++-- * D Weighting++-- | /h/ function for D weighting.+d_h_function :: Fractional a => a -> a+d_h_function f =+    let sq x = x * x+        n = sq (1037918.48 - sq f) + (1080768.16 * sq f)+        d = sq (9837328 - sq f) + (11723776 * sq f)+    in n / d++-- | D-weighting curve multiplier function, ie. for linear magnitude+-- value.  See <http://en.wikipedia.org/wiki/A-weighting>+--+-- > import Sound.SC3.Plot+-- > plotTable1 (map d_weighting_R [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map d_weighting_R [25,50 .. 20000])]+d_weighting_R :: Floating a => a -> a+d_weighting_R f =+    let sq x = x * x+        a = f / (6.8966888496476 * (10 ** (-5)))+        b = sqrt (d_h_function f / ((sq f + 79919.29) * (sq f + 1345600)))+    in a * b++-- | D-weighting curve Db offset (additive) function, ie. for+-- un-weighted Db readings.+--+-- > plotTable1 (map d_weighting [20,50 .. 20000])+-- > plot_p2_ln [zip (map log [1..]) (map d_weighting [25,50 .. 20000])]+d_weighting :: Floating a => a -> a+d_weighting f = 20 * logBase 10 (d_weighting_R f)
+ Sound/SC3/Data/Math/Sprott_1993a.hs view
@@ -0,0 +1,304 @@+-- | <http://sprott.physics.wisc.edu/sa.htm>+module Sound.SC3.Data.Math.Sprott_1993a where++import Data.Maybe {- base -}++import Sound.SC3.Plot {- hsc3-plot -}++-- * Coding Table++-- | Table 2-1. ASCII character set and associated coefficient values (p.28)+sprott_tbl_2_1 :: [(Char,Int,Double)]+sprott_tbl_2_1 =+    let i = [32 .. 127]+        n = map (/ 10) [-45,-44 .. 50]+        c = map toEnum i+    in zip3 c i n++-- | Lookup coeffient at 'sprott_tbl_2_1'.+--+-- > sprott_coef 'M' == Just 0+sprott_coef :: Char -> Maybe Double+sprott_coef c =+    let (ch,_,cf) = unzip3 sprott_tbl_2_1+    in lookup c (zip ch cf)++-- | 'fromJust' of 'sprott_coef'.+sprott_coef_err :: Char -> Double+sprott_coef_err = fromJust . sprott_coef++-- * General forms++-- | Pair each elements with the element /n/ places further along.+--+-- > with_delayed 3 [1..9] == [(1,4),(2,5),(3,6),(4,7),(5,8),(6,9)]+with_delayed :: Int -> [t] -> [(t,t)]+with_delayed n l =+    case l of+      [] -> []+      e0:l' -> case drop n l of+                 [] -> []+                 e1:_ -> (e0,e1) : with_delayed n l'++{- hsc3-plot...++-- | /n/ '*' /n/.+square :: Num a => a -> a+square x = x * x++-}++-- | General one-dimensional quadratic iterated map (Equation 2A, p.25)+quadratic_1 :: Num a => a -> a -> a -> a -> a+quadratic_1 a1 a2 a3 x = a1 + a2 * x + a3 * square x++-- | List (/l/) variant of 'quadratic_1'.+quadratic_1l :: Num a => [a] -> a -> a+quadratic_1l l =+    case l of+      [a1,a2,a3] -> quadratic_1 a1 a2 a3+      _ -> error "quadratic_1l"++-- | General one-dimensional quintic iterated map (Equation 2E, p.41)+quintic_1 :: Num a => a -> a -> a -> a -> a -> a -> a -> a+quintic_1 a1 a2 a3 a4 a5 a6 x =+    let f :: Num a => Integer -> a -> a+        f k n = if k == 1 then n else n * f (k - 1) n+    in a1 + a2 * x + a3 * f 2 x + a4 * f 3 x + a5 * f 4 x + a6 * f 5 x++-- | List (/l/) variant of 'quintic_1'.+quintic_1l :: Num a => [a] -> a -> a+quintic_1l l =+    case l of+      [a1,a2,a3,a4,a5,a6] -> quintic_1 a1 a2 a3 a4 a5 a6+      _ -> error "quintic_1l"++-- | Generalised one-dimensional iterated map.+general_1l :: Num a => [a] -> Maybe (a -> a)+general_1l l =+     case length l of+       3 -> Just (quadratic_1l l)+       4 -> Just (quintic_1l (l ++ [0,0]))+       5 -> Just (quintic_1l (l ++ [0]))+       6 -> Just (quintic_1l l)+       _ -> Nothing++-- | General two-dimensional iterated quadratic map (Equation 3B, p.53)+quadratic_2 :: Num t => t->t->t->t->t->t->t->t->t->t->t->t->(t,t)->(t,t)+quadratic_2 a1 a2 a3 a4 a5 a6 a7 a8 a9 aA aB aC (x,y) =+    let sq n = n * n+        x' = a1 + a2 * x + a3 * sq x + a4 * x * y + a5 * y + a6 * sq y+        y' = a7 + a8 * x + a9 * sq x + aA * x * y + aB * y + aC * sq y+    in (x',y')++-- | List (/l/) variant of 'quadratic_2'.+quadratic_2l :: Num t => [t] -> (t,t) -> (t,t)+quadratic_2l l =+    case l of+      [a1,a2,a3,a4,a5,a6,a7,a8,a9,aA,aB,aC] ->+        quadratic_2 a1 a2 a3 a4 a5 a6 a7 a8 a9 aA aB aC+      _ -> error "quadratic_2l"++-- | General two-dimensional iterated cubic map (Equation 3F, p.80)+cubic_2 :: Num t => t->t->t->t->t->t->t->t->t->t->t->t->t->t->t->t->t->t->t->t->(t,t)->(t,t)+cubic_2 a1 a2 a3 a4 a5 a6 a7 a8 a9 aA aB aC aD aE aF aG aH aI aJ aK (x,y) =+    let sq n = n * n+        cb n = n * n * n+        x' = a1 + a2 * x + a3 * sq x + a4 * cb x + a5 * sq x * y ++             a6 * x * y + a7 * x * sq y + a8 * y + a9 * sq y + aA * cb y+        y' = aB + aC * x + aD * sq x + aE * cb x + aF * sq x * y ++             aG * x * y + aH * x * sq y + aI * y + aJ * sq y + aK * cb y+    in (x',y')++-- | List (/l/) variant of 'cubic_2'.+cubic_2l :: Num t => [t] -> (t,t) -> (t,t)+cubic_2l l =+    case l of+      [a1,a2,a3,a4,a5,a6,a7,a8,a9,aA,aB,aC,aD,aE,aF,aG,aH,aI,aJ,aK] ->+        cubic_2 a1 a2 a3 a4 a5 a6 a7 a8 a9 aA aB aC aD aE aF aG aH aI aJ aK+      _ -> error "cubic_2l"+++-- | Generalised two-dimensional iterated map.+general_2l :: Num t => [t] -> Maybe ((t,t) -> (t,t))+general_2l l =+    case length l of+      12 -> Just (quadratic_2l l)+      20 -> Just (cubic_2l l)+      _ -> Nothing++-- | General three-dimensional iterated quadratic map (Equation 4A, p.147)+quadratic_3 :: Num t => t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> t -> (t, t, t) -> (t, t, t)+quadratic_3 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10+            a11 a12 a13 a14 a15 a16 a17 a18 a19 a20+            a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 (x,y,z) =+    let sq n = n * n+        x' = a1 + a2 * x + a3 * sq x + a4 * x * y + a5 * x * z ++             a6 * y + a7 * sq y + a8 * y * z + a9 * z + a10 * sq z+        y' = a11 + a12 * x + a13 * sq x + a14 * x * y + a15 * x * z ++             a16 * y + a17 * sq y + a18 * y * z + a19 * z + a20 * sq z+        z' = a21 + a22 * x + a23 * sq x + a24 * x * y + a25 * x * z ++             a26 * y + a27 * sq y + a28 * y * z + a29 * z + a30 * sq z+    in (x',y',z')++-- | List (/l/) variant of 'quadratic_3'.+quadratic_3l :: Num t => [t] -> (t, t, t) -> (t, t, t)+quadratic_3l l =+    case l of+      [a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,+       a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,+       a21,a22,a23,a24,a25,a26,a27,a28,a29,a30] ->+        quadratic_3 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10+                a11 a12 a13 a14 a15 a16 a17 a18 a19 a20+                a21 a22 a23 a24 a25 a26 a27 a28 a29 a30+      _ -> error "quadratic_3l"++-- | Generalised three-dimensional iterated map.+general_3l :: Num t => [t] -> Maybe ((t,t,t) -> (t,t,t))+general_3l l =+    case length l of+      30 -> Just (quadratic_3l l)+      _ -> Nothing++-- * Projections++-- | Projection onto sphere (Equation 3G, p.107)+sphere_proj :: (Floating t,Ord t) => [(t,t)] -> [(t,t)]+sphere_proj l =+    let (xs,ys) = unzip l+        (x0,x1) = minmax xs+        (y0,y1) = minmax ys+        xa = (x0 + x1) / 2+        ya = (y0 + y1) / 2+        tt = pi / (x1 - x0)+        pt = pi / (y1 - y0)+        prj (x,y) = let th = tt * (x1 - x)+                        ph = pt * (y1 - y)+                    in (xa + 0.36 * (x1 - x0) * cos th * sin ph+                       ,ya + 0.5 * (y1 - y0) * cos ph)+    in map prj l++-- * Code Plotting++-- | Plot one-dimensional code, /m/ is delay, /n/ is iteration degree, /i/ is initial value.+plot_code_1 :: Int -> Int -> Double -> (Code,Annotation) -> IO ()+plot_code_1 m n i (c,_) =+    case c of+      c0:c' -> if c0 `elem` "ABCD"+               then case general_1l (map sprott_coef_err c') of+                      Just f -> plot_p2_pt [with_delayed m (take n (iterate f i))]+                      Nothing -> error "plot_code_1: ill-formed coef"+               else error "plot_code_1: not type {A,B,C,D}"+      _ -> error "plot_code_1: ill-formed code"++-- | Plot two-dimensional code, /n/ is iteration degree, /i/ is initial value.+plot_code_2 :: Bool -> Int -> (Double,Double) -> (Code,Annotation) -> IO ()+plot_code_2 sph n i (c,_) =+    case c of+      c0:c' -> if c0 `elem` "EF"+               then case general_2l (map sprott_coef_err c') of+                      Just f -> let prj = if sph then sphere_proj else id+                                in plot_p2_pt [prj (take n (iterate f i))]+                      Nothing -> error "plot_code_2: ill-formed coef"+               else error "plot_code_2: not type {E,F}"+      _ -> error "plot_code_2: ill-formed code"++-- | Plot three-dimensional code, /n/ is iteration degree, /i/ is initial value.+plot_code_3 :: Int -> (Double,Double,Double) -> (Code,Annotation) -> IO ()+plot_code_3 n i (c,_) =+    case c of+      c0:c' -> if c0 `elem` "I"+               then case general_3l (map sprott_coef_err c') of+                      Just f -> plot_p3_pt [take n (iterate f i)]+                      Nothing -> error "plot_code_3: ill-formed coef"+               else error "plot_code_3: not type {I}"+      _ -> error "plot_code_3: ill-formed code"++-- * Co-efficient codes.++-- | A code is a string.  The set of book codes are at:+-- <http://sprott.physics.wisc.edu/fractals/bookdisk/BOOKFIGS.DIC> and+-- there is a further set of codes at:+-- <http://sprott.physics.wisc.edu/fractals/bookdisk/SELECTED.DIC>+type Code = String+type Annotation = String++-- | One-dimensional codes.+--+-- > plot_code_1 5 12500 0.1 (codes_1 !! 7)+codes_1 :: [(Code,Annotation)]+codes_1 =+    [("AMu%","Fig 1-4")+    ,("AXBH","Fig 2-1")+    ,("ABDU","Fig 2-2")+    ,("ACAV","Fig 2-3")+    ,("AXDA","Fig 2-4")+    ,("BZEZK","Fig 2-5")+    ,("CBLCTX","Fig 2-6")+    ,("CUTXJE","Fig 2-7")+    ,("DBOGIZI","Fig 2-8")+    ,("DFBIEVV","Fig 2-9")+    ,("DOOYRIL","Fig 2-10")]++-- | Two-dimensional codes.+--+-- > plot_code_2 False 25000 (0.1,0) (codes_2 !! 25)+codes_2 :: [(Code,Annotation)]+codes_2 =+    [("EWM?MPMMWMMMM","Fig 3-1") -- 0+    ,("EAGHNFODVNJCP","Fig 3-2")+    ,("EBCQAFMFVPXKQ","Fig 3-3")+    ,("EDSYUECINGQNV","Fig 3-4")+    ,("EELXAPXMPQOBT","Fig 3-5")+    ,("EEYYMKTUMXUVC","Fig 3-6")+    ,("EJTTSMBOGLLQF","Fig 3-7")+    ,("ENNMJRCTVVTYG","Fig 3-8")+    ,("EOUGFJKDHSAJU","Fig 3-9")+    ,("EQKOCSIDVTPGY","Fig 3-10")+    ,("EQLOIARXYGHAJ","Fig 3-11") -- 10+    ,("ETJUBWEDNRORR","Fig 3-12")+    ,("ETSILUNDQSIFA","Fig 3-13")+    ,("EUEBJLCDISIIQ","Fig 3-14")+    ,("EVDUOTLRBKTJD","Fig 3-15")+    ,("EWLKWPSMOGIGS","Fig 3-16")+    ,("EZPMSGCNFRENG","Fig 3-17")+    ,("FIRPGVTFIDGCSXMFPKIDJ","Fig 3-18")+    ,("FISMHQCHPDFKFBKEALIFD","Fig 3-19")+    ,("FJYCBMNFNYOEPYUGHHESU","Fig 3-20")+    ,("FNUYLCURDUHQUQMRZQWQB","Fig 3-24") -- 20+    ,("ECSRKVVQLGFFS","Fig 3-42")+    ,("ECVQKGHQTPHTE","Fig 3-43")+    ,("EKPNERVOTBYCM","Fig 3-44")+    ,("EUWACXDQIGKHF","Fig 3-45")+    ,("ECMMMEWHXRMMM","Fig 3-58")+    ,("EMVWMGCMaMaRM","Fig 8-6 (Tinkerbell)")+    ,("EAEUBNVIAHERQ","SELECTED.DIC #1 (p. 583)")+    ,("EAHSVIGTJKOTB","SELECTED.DIC #1")+    ]++-- | Three-dimensional codes.+--+-- > plot_code_3 15000 (0.1,0,0) (codes_3 !! 1)+codes_3 :: [(Code,Annotation)]+codes_3 =+    [("IJKRADSXGDBHIJTQJJDICEJKYSTXFNU","Fig 4-1")+    ,("ILURCEGOHOIQFJKBSNYGSNRUKKIKIHW","Fig 4-2")+    ,("INRRXLCEYLFHYAPFSTPHHJMYRYJFBNM","Fig 4-4")+    ,("IWDWOGDGWGORJOBTUHFQBPRNTCBYQHP","Fig 4-8")]++-- > let cf = map sprott_coef_err "FUXRRRUIRDYKDUBPHHHOMOBRIRBINCS"+-- > plot_p2_pt [take 25000 (iterate (quartic_2l cf) (0.1,0))]++-- * Specialised forms++-- | Sprott p.9 (Equation 1C)+--+-- > plot_p2_pt [with_delayed 1 (take 5000 (iterate (logistic 4) 0.05))]+logistic :: Num a => a -> a -> a+logistic r x = r * x * (1 - x)++-- | Figure 3-1. The Hénon map (p.52)+--+-- > plot_p2_pt [take 5000 (iterate (henon (-1.4) 0.3) (0.1,0))]+henon :: Num t => t -> t -> (t, t) -> (t, t)+henon a b (x,y) = (1 + a * square x + b * y, x)
+ Sound/SC3/Data/SVG.hs view
@@ -0,0 +1,51 @@+-- | Load linearised path data from SVG files.+module Sound.SC3.Data.SVG where++import Data.Maybe {- base -}+import System.IO.Unsafe {- base -}+import qualified Text.XML.Light as X {- xml -}++import Graphics.SVG.ReadPath as P {- SVGPath -}++import Data.CG.Minus {- hcg-minus -}+import Sound.SC3.Plot {- hsc3-plot -}++-- | Make 'X.QName' with @svg@ 'X.qURI'.+svg_name :: String -> X.QName+svg_name nm =+    X.blank_name+         {X.qName = nm+         ,X.qURI = Just "http://www.w3.org/2000/svg"}++pathFromString' :: String -> Either String [PathCommand]+pathFromString' = Right . unsafePerformIO . P.pathFromString++parse_path :: String -> [P.PathCommand]+parse_path str =+    case pathFromString' str of+      Left err -> error err+      Right cmd -> cmd++svg_read_path_d :: String -> [[P.PathCommand]]+svg_read_path_d s =+    let p = case X.parseXMLDoc s of+              Nothing -> error "svg_read_path_d: no parse"+              Just e -> X.findElements (svg_name "path") e+        d = mapMaybe (X.findAttr (X.unqual "d")) p+    in map parse_path d++subpaths_to_ls :: (Double,Double) -> [P.PathCommand] -> [Ls Double]+subpaths_to_ls (dx,dy) r =+    case P.commandsToPoints r (dx,dy) (0,0) of+      [] -> error "subpaths_to_ls: no sub-paths"+      p -> map (map pt') p++svg_load_ls :: (Double, Double) -> FilePath -> IO [Ls Double]+svg_load_ls rs fn = do+  s <- readFile fn+  let d = svg_read_path_d s+      p = concatMap (subpaths_to_ls rs) d+  return p++plot_ls :: PNum t => [Ls t] -> IO ()+plot_ls = plotCoord . map (map pt_xy)
+ Sound/SC3/Data/Trace.hs view
@@ -0,0 +1,307 @@+module Sound.SC3.Data.Trace where++import Control.Monad {- base -}+import Data.Bifunctor {- bifunctor -}+import Data.List {- base -}+import Data.List.Split {- split -}+import Data.Maybe {- base -}+import Safe {- safe -}+import System.FilePath.Glob {- glob -}++import Data.CG.Minus {- hcg-minus -}+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Tuple as T {- hmt -}+import qualified Sound.File.HSndFile as F {- hsc3-sf-hsndfile -}+import Sound.SC3.Lang.Core {- hsc3-lang -}+import Sound.SC3.Plot {- hsc3-plot -}++{- | Traces are sequences @Ord t => [(t,a)]@ where t is ascending.++Ordinarily t is a time-point, and traces are temporal.++However /t/ may be, for instance, distance traversed so that line+segments (sequences of cartesian points) can be transformed into+Traces by associating each point with the distance along the line.++If there is an interpolation function (linear or otherwise) for the type /a/ we can lookup a value for any index /t/ in the window of the trace.++Traces can be both more accurate and more compact than sampled data streams.++Break-point envelopes are Traces where /a/ is a scalar+@(interpolation-type,value)@.++Traces are /normal/ if t0 is >= 0 and tn is <= 1.++Traces are /strictly normal/ if t0 == 0 and tn == 1.++-}+type Trace t a = [(t,a)]++-- | Start time of trace, or zero for null trace.+trace_start_time :: Num t => Trace t a -> t+trace_start_time = maybe 0 fst . headMay++-- | End time of trace, or zero for null trace.+trace_end_time :: Num t => Trace t a -> t+trace_end_time = maybe 0 fst . lastMay++-- | A trace window is a pait (t0,t1) indicating the begin and end+-- time points.+type Window t = (t,t)++-- | Start and end times of trace, or (0,0) for null trace.+trace_window :: Num t => Trace t a -> Window t+trace_window t = (trace_start_time t,trace_end_time t)++-- | Interpolation function type.+type Lerp_F t a b = (t -> a -> a -> b)++-- | Synonym for real valued time point.+type Time = R++-- * IO++-- | Load real valued trace stored as a sound file.+--+-- The temporal data is in the first channel, subsequent channels are+-- associated data points.  If set /nc/ is set it requires the file+-- have precisely the indicated number of _data_ channels, ie. /nc/+-- does not include the _temporal_ channel.+trace_load_sf :: Maybe Int -> FilePath -> IO (Trace Time [R])+trace_load_sf nc fn = do+  (h,t:d) <- F.read fn+  let nc' = F.channelCount h+  when (maybe False (/= (nc' - 1)) nc) (error "trace_load_sf: incorrect nc")+  return (zip t (transpose d))++-- | Variant for loading two-channel trace file.+trace_load_sf2 :: FilePath -> IO (Trace Time (R,R))+trace_load_sf2 =+    let f = map (bimap id T.t2)+    in fmap f . trace_load_sf (Just 2)++-- | Variant for set of traces given by 'glob' pattern'.+trace_load_sf_dir :: Maybe Int -> String -> IO [Trace Time [R]]+trace_load_sf_dir n p = do+  nm <- glob p+  mapM (trace_load_sf n) nm++trace_load_sf2_dir :: String -> IO [Trace Time (R,R)]+trace_load_sf2_dir p = do+  nm <- glob p+  mapM trace_load_sf2 nm++-- * Functor++-- | Map over trace times.+trace_map_t :: (t -> t') -> Trace t a -> Trace t' a+trace_map_t f = map (\(t,a) -> (f t,a))++-- | Map over trace values.+trace_map :: (a -> b) -> Trace t a -> Trace t b+trace_map f = map (\(t,a) -> (t,f a))++-- * Lookup++-- | Trace nodes that bracket time /t/, and trace starting from left neighbour.+--+-- > map (trace_locate (zip [0..9] ['a'..])) [-1,3.5,10]+trace_locate :: (Ord t,Fractional t) => Trace t a -> t -> Either String (((t,a),(t,a)),Trace t a)+trace_locate tr tm =+    case tr of+      p0:p1:r -> let (t0,_) = p0+                     (t1,_) = p1+                 in if tm < t0+                    then Left "trace_locate: time point before trace window"+                    else if tm <= t1+                         then Right ((p0,p1),tr)+                         else trace_locate (p1:r) tm+      _ -> Left "trace_locate: time point after trace window"++-- | 'fst' of 'trace_locate'+--+-- > trace_neighbours (zip [0..9] ['a'..]) 3.5 == Just ((3.0,'d'),(4.0,'e'))+trace_neighbours :: (Ord t,Fractional t) => Trace t a -> t -> Maybe ((t,a),(t,a))+trace_neighbours = either (const Nothing) (Just . fst) .: trace_locate++-- | 'fromJust' of 'trace_neighbours'.+trace_neighbours_err :: (Fractional t,Ord t) => Trace t a -> t -> ((t,a),(t,a))+trace_neighbours_err = fromJust .: trace_neighbours++-- | Interpolate between to trace points using given interpolation function.+trace_lerp :: Fractional t => Lerp_F t a b -> t -> (t,a) -> (t,a) -> (t,b)+trace_lerp lerp_f n (t0,d0) (t1,d1) =+    let i = (n - t0) / (t1 - t0)+    in (n,lerp_f i d0 d1)++-- | Linear interpolating lookup, ie. 'trace_lerp' of 'trace_neighbours'.+--+-- > t <- trace_load_sf2_dir "/home/rohan/sw/hsc3-data/help/au/*.txy.au"+-- > map (\z -> trace_lookup lerpn2 z 0.5) t+trace_lookup :: (Ord t,Fractional t) => Lerp_F t a b -> Trace t a -> t -> Maybe (t,b)+trace_lookup lerp_f t n =+    let f (p0,p1) = trace_lerp lerp_f n p0 p1+    in fmap f (trace_neighbours t n)++-- | 'trace_lookup' with default value.+trace_lookup_def :: (Ord t,Fractional t) => b -> Lerp_F t a b -> Trace t a -> t -> (t,b)+trace_lookup_def def lerp_f t n = maybe (n,def) id (trace_lookup lerp_f t n)++-- | 'fromJust' of 'trace_lookup'.+trace_lookup_err :: (Ord t,Fractional t) => Lerp_F t a b -> Trace t a -> t -> (t,b)+trace_lookup_err = fromJust .:: trace_lookup++trace_lookup_seq_asc :: (Ord t,Fractional t) => Lerp_F t a b -> Trace t a -> [t] -> Trace t b+trace_lookup_seq_asc lerp_f =+    let loop tr n = case n of+                      n0:n' -> case trace_locate tr n0 of+                                 Right ((p0,p1),tr') -> trace_lerp lerp_f n0 p0 p1 : loop tr' n'+                                 Left err -> error err+                      _ -> []+    in loop++-- * Operate++-- | Normalise so that 'trace_window' is (0,1).+--+-- > let r = [(0,'a'),(0.2,'b'),(1,'c')]+-- > in trace_normalise_t [(0,'a'),(1,'b'),(5,'c')] == r+trace_normalise_t :: Fractional t => Trace t a -> Trace t a+trace_normalise_t trace =+    let (t0,t1) = trace_window trace+        d = t1 - t0+        f t = ((t - t0) / d)+    in trace_map_t f trace++-- | Transform trace to an /n/-point linear form (time-points are+-- equi-distant) over indicated 'Window' (which must be ascending, ie+-- /t0/ < /t1/).+trace_linearise :: (Ord t,Fractional t) => Int -> Lerp_F t a b -> Trace t a -> Window t -> Trace t b+trace_linearise n lerp_f t (t0,t1) = trace_lookup_seq_asc lerp_f t (iota t0 t1 n)++-- | Variant where the range is derived implicity from input trace+-- ('trace_window').+--+-- > t <- trace_load_sf2_dir "/home/rohan/sw/hsc3-data/help/au/*.txy.au"+-- > plotCoord (map (trace_linearise_w 1024 lerpn . trace_map fst) t)+-- > plotCoord (map (trace_map fst) t)+-- > trace2_plot_tbl t+trace_linearise_w :: (Ord t,Fractional t) => Int -> Lerp_F t a b -> Trace t a -> Trace t b+trace_linearise_w n lerp_f t = trace_linearise n lerp_f t (trace_window t)++-- | Values only of 'trace_linearise_w'.+--+-- > plotTable (map (trace_table 1024 lerpn . trace_map fst) t)+trace_table :: (Ord t,Fractional t) => Int -> Lerp_F t a b -> Trace t a -> [b]+trace_table = map snd .:: trace_linearise_w++-- | Variant of 'trace_linearize' assuming /t/ is normalised.+--+-- > trace_rescale lerpd [(0,[1]),(2,[2])] 3 == [(0,[1]),(0.5,[1.25]),(1,[1.5])]+trace_rescale :: (Eq t,Ord t,Fractional t) => Lerp_F t a b -> Trace t a -> Int -> Trace t b+trace_rescale lerp_f t = map (trace_lookup_err lerp_f t) . iota 0 1++-- | Interpolate maintaining temporal shape, divide each step in half.+--+-- > let r = [(0,[0]),(0.5,[0.5]),(1,[1]),(2.5,[2.5]),(4,[4])]+-- > in trace_expand lerpd [(0,[0]),(1,[1]),(4,[4])] == r+--+-- > trace2_plot_3d (map (trace_expand lerpn2) t)+trace_expand :: (Fractional t) => Lerp_F t a a -> Trace t a -> Trace t a+trace_expand lerp_f t =+    let f p0 p1 = trace_lerp lerp_f (h p0 p1) p0 p1+        h (t0,_) (t1,_) = ((t1 - t0) / 2.0) + t0+        t' = zipWith f t (tail t)+    in interleave2 (t,t')++-- | Recursive expansion+--+-- > length (trace_expand_n lerpd [(0,[0]),(1,[1]),(4,[4])] 3) == 17+trace_expand_n :: (Fractional t,Integral n) => Lerp_F t a a -> Trace t a -> n -> Trace t a+trace_expand_n f t n =+    if n == 1+    then trace_expand f t+    else trace_expand_n f (trace_expand f t) (n - 1)++-- * Interpolation++-- | Linear interpolation.+--+-- > zipWith (lerpn 0.25) [4,5] [6,9] == [4.5,6.0]+lerpn :: Num a => a -> a -> a -> a+lerpn i a b = a + ((b - a) * i)++-- | Variant at uniform 2-tuple.+--+-- > lerpn2 0.25 (4,5) (6,9) == (4.5,6.0)+lerpn2 :: Num n => n -> (n,n) -> (n,n) -> (n,n)+lerpn2 i = T.t2_zipWith (lerpn i)++-- | Pointwise linear interpolation at lists.+--+-- > lerp_pw lerpn 0.25 [4,5] [6,9] == [4.5,6]+lerp_pw :: Lerp_F t a b -> t -> [a] -> [a] -> [b]+lerp_pw lerp_f i = zipWith (lerp_f i)++-- | 'lerp_pw' of 'lerpn'.+--+-- > lerpd 0.25 [4,5] [6,9] == [4.5,6]+lerpd :: Num c => c -> [c] -> [c] -> [c]+lerpd = lerp_pw lerpn++-- * Geometry++-- | Transform 'Ls' to 'Trace', /t/ is distance along line.+ls_with_distance :: (Eq t,Floating t) => Ls t -> Trace t (Pt t)+ls_with_distance p =+    let d = T.dx_d 0 (zipWith pt_distance p (tail p))+    in zip d p++-- * List++-- | Generic iota function (name courtesy scheme language) with+-- explicit increment.  The last value is the given end-point+-- regardless of accumulated errors.+--+-- > iota' 0 1 0.25 5 == [0,0.25,0.5,0.75,1]+iota' :: (Eq n,Num n,Eq m,Num m) => n -> n -> n -> m -> [n]+iota' a b i n =+    case n of+      0 -> []+      1 -> [b]+      _ -> a : iota' (a + i) b i (n - 1)++-- | Fractional iota function with implicit increment.+--+-- > iota 0 1 5 == [0,0.25,0.5,0.75,1]+iota :: (Integral m,Eq n,Fractional n) => n -> n -> m -> [n]+iota a b n = iota' a b ((b - a) / fromIntegral (n - 1)) n++-- | Alternate elements of two lists.+--+-- > interleave2 ("one","two") == "otnweo"+-- > interleave2 ("long","short") == "lsohnogrt"+interleave2 :: ([t],[t]) -> [t]+interleave2 = concat . transpose . T.t2_list++-- | Inverse of 'interleave2'.+--+-- > interleave2 ("abcd","ABCD") == "aAbBcCdD"+-- > deinterleave2 "aAbBcCdD" == ("abcd","ABCD")+deinterleave2 :: [a] -> ([a],[a])+deinterleave2 = T.t2 . transpose . chunksOf 2++-- * Plotting++-- | Three-dimensional plot of two-dimensional traces (/time/ on @x@ axis), ie. 'plotPath'.+trace2_plot_3d :: [Trace R (R,R)] -> IO ()+trace2_plot_3d = plotPath . map (map (\(t,(p,q)) -> (t,p,q)))++-- | Two-dimensional plot of two-dimensional traces (/time/ not drawn), ie. 'plotCoord'.+trace2_plot_2d :: [Trace R (R,R)] -> IO ()+trace2_plot_2d = plotCoord . map (map snd)++trace2_plot_tbl :: [Trace R (R,R)] -> IO ()+trace2_plot_tbl =+    let f t = [trace_map fst t,trace_map snd t]+    in plotCoord . concatMap f
+ hsc3-data.cabal view
@@ -0,0 +1,40 @@+Name:              hsc3-data+Version:           0.15+Synopsis:          haskell supercollider data+Description:       Data related functions useful when working with SC3.+License:           GPL+Category:          Sound+Copyright:         (c) Rohan Drape, 2013-2014+Author:            Rohan Drape+Maintainer:        rd@slavepianos.org+Stability:         Experimental+Homepage:          http://rd.slavepianos.org/t/hsc3-data+Tested-With:       GHC == 7.8.2+Build-Type:        Simple+Cabal-Version:     >= 1.8++Data-files:        README++Library+  Build-Depends:   base == 4.*,+                   bifunctors,+                   Glob,+                   hcg-minus == 0.15.*,+                   hmt == 0.15.*,+                   hsc3-lang == 0.15.*,+                   hsc3-plot == 0.15.*,+                   hsc3-sf-hsndfile == 0.15.*,+                   safe,+                   split,+                   SVGPath >= 1.1.1,+                   xml+  GHC-Options:     -Wall -fwarn-tabs+  Exposed-modules: Sound.SC3.Data.Math.Bourke+                   Sound.SC3.Data.Math.Loudness+                   Sound.SC3.Data.Math.Sprott_1993a+                   Sound.SC3.Data.SVG+                   Sound.SC3.Data.Trace++Source-Repository  head+  Type:            darcs+  Location:        http://rd.slavepianos.org/sw/hsc3-data