diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2018-05-15 21:21:48 +0200 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2018-05-15 21:21:48 +0200 |
commit | 879e0c7218298349b9c92e9d3362830c371ec78e (patch) | |
tree | 5f50ccbea875c2ef77c830da43fbe29964e5630a | |
parent | e8bd291609192725ea0b40190fd3bd84f0d96920 (diff) | |
download | trivmix-879e0c7218298349b9c92e9d3362830c371ec78e.tar trivmix-879e0c7218298349b9c92e9d3362830c371ec78e.tar.gz trivmix-879e0c7218298349b9c92e9d3362830c371ec78e.tar.bz2 trivmix-879e0c7218298349b9c92e9d3362830c371ec78e.tar.xz trivmix-879e0c7218298349b9c92e9d3362830c371ec78e.zip |
Switch to Scientific-math
-rw-r--r-- | package.yaml | 49 | ||||
-rw-r--r-- | src/Data/Scientific/Lift.hs | 9 | ||||
-rw-r--r-- | src/Trivmix/Types.hs | 60 | ||||
-rw-r--r-- | trivmix.cabal | 115 | ||||
-rw-r--r-- | trivmix.cabal.gup | 4 | ||||
-rw-r--r-- | trivmix.nix | 8 | ||||
-rw-r--r-- | trivmix/Trivmix.hs | 27 |
7 files changed, 176 insertions, 96 deletions
diff --git a/package.yaml b/package.yaml new file mode 100644 index 0000000..123fe83 --- /dev/null +++ b/package.yaml | |||
@@ -0,0 +1,49 @@ | |||
1 | name: trivmix | ||
2 | version: 4.0.0 | ||
3 | license: PublicDomain | ||
4 | license-file: LICENSE | ||
5 | author: Gregor Kleen <aethoago@141.li> | ||
6 | category: Sound | ||
7 | build-type: Simple | ||
8 | git: https://git.yggdrasil.li/gkleen/pub/trivmix | ||
9 | |||
10 | library: | ||
11 | source-dirs: src | ||
12 | exposed-modules: Trivmix.Types | ||
13 | dependencies: | ||
14 | - base >=4.8 && <5 | ||
15 | - data-default >=0.5 && <1 | ||
16 | - case-insensitive >=1.2 && <2 | ||
17 | - refined >=0.1.2.1 && <1 | ||
18 | - scientific >=0.3.6.2 && <1 | ||
19 | - th-lift >=0.7.10 && <1 | ||
20 | |||
21 | executables: | ||
22 | trivmix: | ||
23 | main: Trivmix.hs | ||
24 | source-dirs: trivmix | ||
25 | dependencies: | ||
26 | - base >=4.8 && <5 | ||
27 | - jack >=0.7 && <1 | ||
28 | - optparse-applicative >=0.11 && <1 | ||
29 | - directory >=1.2 && <2 | ||
30 | - filepath >=1.3 && <2 | ||
31 | - unix >=2.7 && <3 | ||
32 | - hinotify >=0.3 && <1 | ||
33 | - transformers >=0.3 && <1 | ||
34 | - explicit-exception >=0.1 && <1 | ||
35 | - process >=1.2 && <2 | ||
36 | - filelock >=0.1 && <1 | ||
37 | - systemd >=1.1.2 && <2 | ||
38 | - heredoc >=0.2.0.0 && <1 | ||
39 | - refined >=0.1.2.1 && <1 | ||
40 | - trivmix | ||
41 | adjmix: | ||
42 | main: Adjmix.hs | ||
43 | source-dirs: adjmix | ||
44 | dependencies: | ||
45 | - base >=4.8 && <5 | ||
46 | - optparse-applicative >=0.11 && <1 | ||
47 | - filepath >=1.3 && <2 | ||
48 | - filelock >=0.1 && <1 | ||
49 | - trivmix | ||
diff --git a/src/Data/Scientific/Lift.hs b/src/Data/Scientific/Lift.hs new file mode 100644 index 0000000..7d1a372 --- /dev/null +++ b/src/Data/Scientific/Lift.hs | |||
@@ -0,0 +1,9 @@ | |||
1 | {-# LANGUAGE TemplateHaskell #-} | ||
2 | {-# OPTIONS_GHC -fno-warn-orphans #-} | ||
3 | |||
4 | module Data.Scientific.Lift where | ||
5 | |||
6 | import Data.Scientific (Scientific) | ||
7 | import Language.Haskell.TH.Lift (deriveLift) | ||
8 | |||
9 | deriveLift ''Scientific | ||
diff --git a/src/Trivmix/Types.hs b/src/Trivmix/Types.hs index fe44a27..5e4660d 100644 --- a/src/Trivmix/Types.hs +++ b/src/Trivmix/Types.hs | |||
@@ -2,12 +2,12 @@ | |||
2 | 2 | ||
3 | module Trivmix.Types | 3 | module Trivmix.Types |
4 | ( Level' | 4 | ( Level' |
5 | , Level(Lin), toLin | 5 | , Level(Lin, toLin) |
6 | , toFloat | 6 | , toScientific |
7 | , asFloat | 7 | , asScientific |
8 | , Balance(..) | 8 | , Balance(..) |
9 | , bToFloat | 9 | , bToScientific |
10 | , bAsFloat | 10 | , bAsScientific |
11 | , Adjustment(..) | 11 | , Adjustment(..) |
12 | , doAdjustment | 12 | , doAdjustment |
13 | , module Data.Default | 13 | , module Data.Default |
@@ -27,27 +27,31 @@ import Data.Function (on) | |||
27 | 27 | ||
28 | import Refined | 28 | import Refined |
29 | 29 | ||
30 | type Level' = Refined NonNegative Float | 30 | import Data.Scientific |
31 | import Data.Scientific.Lift | ||
32 | |||
33 | |||
34 | type Level' = Refined NonNegative Scientific | ||
31 | data Level = Lin { toLin :: Level' } | DB { toLin :: Level' } | 35 | data Level = Lin { toLin :: Level' } | DB { toLin :: Level' } |
32 | 36 | ||
33 | instance Num Level where | 37 | instance Num Level where |
34 | (+) = fmap (either error id) . asFloat (+) | 38 | (+) = fmap (either error id) . asScientific (+) |
35 | (-) = fmap (either error id) . asFloat (-) | 39 | (-) = fmap (either error id) . asScientific (-) |
36 | (*) = fmap (either error id) . asFloat (*) | 40 | (*) = fmap (either error id) . asScientific (*) |
37 | abs = id | 41 | abs = id |
38 | signum = Lin . either error id . refine . signum . toFloat | 42 | signum = Lin . either error id . refine . signum . toScientific |
39 | fromInteger = Lin . either error id . refine . fromInteger | 43 | fromInteger = Lin . either error id . refine . fromInteger |
40 | 44 | ||
41 | asFloat :: (Float -> Float -> Float) -> Level -> Level -> Either String Level | 45 | asScientific :: (Scientific -> Scientific -> Scientific) -> Level -> Level -> Either String Level |
42 | asFloat ((`on` toFloat) -> f) x y = toLvl <$> refine (f x y) | 46 | asScientific ((`on` toScientific) -> f) x y = toLvl <$> refine (f x y) |
43 | where | 47 | where |
44 | toLvl | 48 | toLvl |
45 | | DB _ <- x = DB | 49 | | DB _ <- x = DB |
46 | | DB _ <- y = DB | 50 | | DB _ <- y = DB |
47 | | otherwise = Lin | 51 | | otherwise = Lin |
48 | 52 | ||
49 | toFloat :: Level -> Float | 53 | toScientific :: Level -> Scientific |
50 | toFloat = unrefine . toLin | 54 | toScientific = unrefine . toLin |
51 | 55 | ||
52 | withPrec :: (Num a, RealFrac a, HasResolution b) => a -> Fixed b | 56 | withPrec :: (Num a, RealFrac a, HasResolution b) => a -> Fixed b |
53 | withPrec x = withResolution $ \p' -> MkFixed $ toInteger $ round $ x * (fromInteger p') | 57 | withPrec x = withResolution $ \p' -> MkFixed $ toInteger $ round $ x * (fromInteger p') |
@@ -58,11 +62,11 @@ withType f = f undefined | |||
58 | withResolution :: (HasResolution a) => (Integer -> f a) -> f a | 62 | withResolution :: (HasResolution a) => (Integer -> f a) -> f a |
59 | withResolution f = withType (f . resolution) | 63 | withResolution f = withType (f . resolution) |
60 | 64 | ||
61 | linToDb :: Level' -> Float | 65 | linToDb :: Level' -> Scientific |
62 | linToDb (unrefine -> x) = 20 * (logBase 10 x) | 66 | linToDb (unrefine -> x) = realToFrac (20 * (logBase 10 $ toRealFloat x) :: Double) |
63 | 67 | ||
64 | dBToLin :: Float -> Level' | 68 | dBToLin :: Scientific -> Level' |
65 | dBToLin x = either error id . refine $ 10 ** (0.05 * x) | 69 | dBToLin x = either error id . refine . realToFrac $ (10 ** (0.05 * toRealFloat x) :: Double) |
66 | 70 | ||
67 | instance Show Level where | 71 | instance Show Level where |
68 | show (Lin (unrefine -> x)) = show x | 72 | show (Lin (unrefine -> x)) = show x |
@@ -93,25 +97,25 @@ instance Default Level where | |||
93 | 97 | ||
94 | 98 | ||
95 | 99 | ||
96 | newtype Balance = Balance { unBalance :: Refined ZeroToOne Float } | 100 | newtype Balance = Balance { unBalance :: Refined ZeroToOne Scientific } |
97 | deriving (Ord, Eq) | 101 | deriving (Ord, Eq) |
98 | 102 | ||
99 | bAsFloat :: (Float -> Float -> Float) -> Balance -> Balance -> Either String Balance | 103 | bAsScientific :: (Scientific -> Scientific -> Scientific) -> Balance -> Balance -> Either String Balance |
100 | bAsFloat f (unrefine . unBalance -> x) (unrefine . unBalance -> y) = fmap Balance . refine $ f x y | 104 | bAsScientific f (unrefine . unBalance -> x) (unrefine . unBalance -> y) = fmap Balance . refine $ f x y |
101 | 105 | ||
102 | bToFloat :: Balance -> Float | 106 | bToScientific :: Balance -> Scientific |
103 | bToFloat = unrefine . unBalance | 107 | bToScientific = unrefine . unBalance |
104 | 108 | ||
105 | instance Num Balance where | 109 | instance Num Balance where |
106 | (+) = fmap (either error id) . bAsFloat (+) | 110 | (+) = fmap (either error id) . bAsScientific (+) |
107 | (-) = fmap (either error id) . bAsFloat (-) | 111 | (-) = fmap (either error id) . bAsScientific (-) |
108 | (*) = fmap (either error id) . bAsFloat (*) | 112 | (*) = fmap (either error id) . bAsScientific (*) |
109 | abs = id | 113 | abs = id |
110 | signum = Balance . either error id . refine . signum . bToFloat | 114 | signum = Balance . either error id . refine . signum . bToScientific |
111 | fromInteger = Balance . either error id . refine . fromInteger | 115 | fromInteger = Balance . either error id . refine . fromInteger |
112 | 116 | ||
113 | instance Show Balance where | 117 | instance Show Balance where |
114 | show = show . bToFloat | 118 | show = show . bToScientific |
115 | 119 | ||
116 | instance Read Balance where | 120 | instance Read Balance where |
117 | readsPrec = readPrec_to_S $ do | 121 | readsPrec = readPrec_to_S $ do |
diff --git a/trivmix.cabal b/trivmix.cabal index 0cbccdb..962edd6 100644 --- a/trivmix.cabal +++ b/trivmix.cabal | |||
@@ -1,58 +1,67 @@ | |||
1 | -- Initial trivmix.cabal generated by cabal init. For further | 1 | name: trivmix |
2 | -- documentation, see http://haskell.org/cabal/users-guide/ | 2 | version: 4.0.0 |
3 | category: Sound | ||
4 | author: Gregor Kleen <aethoago@141.li> | ||
5 | license: PublicDomain | ||
6 | license-file: LICENSE | ||
7 | build-type: Simple | ||
8 | cabal-version: >= 1.10 | ||
3 | 9 | ||
4 | name: trivmix | 10 | source-repository head |
5 | version: 3.3.2 | 11 | type: git |
6 | -- synopsis: | 12 | location: https://git.yggdrasil.li/gkleen/pub/trivmix |
7 | -- description: | ||
8 | license: PublicDomain | ||
9 | license-file: LICENSE | ||
10 | author: Gregor Kleen | ||
11 | maintainer: aethoago@141.li | ||
12 | -- copyright: | ||
13 | category: Sound | ||
14 | build-type: Simple | ||
15 | -- extra-source-files: | ||
16 | cabal-version: >=1.10 | ||
17 | 13 | ||
18 | library | 14 | library |
19 | hs-source-dirs: src | 15 | exposed-modules: |
20 | default-language: Haskell2010 | 16 | Trivmix.Types |
21 | exposed-modules: Trivmix.Types | 17 | other-modules: |
22 | build-depends: base >=4.8 && <5 | 18 | Data.Scientific.Lift |
23 | , data-default >=0.5 && <1 | 19 | Paths_trivmix |
24 | , case-insensitive >=1.2 && <2 | 20 | hs-source-dirs: |
25 | , refined >=0.1.2.1 && <1 | 21 | src |
26 | 22 | build-depends: | |
27 | executable trivmix | 23 | base >=4.8 && <5 |
28 | main-is: Trivmix.hs | 24 | , case-insensitive >=1.2 && <2 |
29 | -- other-modules: | 25 | , data-default >=0.5 && <1 |
30 | -- other-extensions: | 26 | , refined >=0.1.2.1 && <1 |
31 | build-depends: base >=4.8 && <5 | 27 | , scientific >=0.3.6.2 && <1 |
32 | , jack >=0.7 && <1 | 28 | , th-lift >=0.7.10 && <1 |
33 | , optparse-applicative >=0.11 && <1 | 29 | default-language: Haskell2010 |
34 | , directory >=1.2 && <2 | ||
35 | , filepath >=1.3 && <2 | ||
36 | , unix >=2.7 && <3 | ||
37 | , hinotify >=0.3 && <1 | ||
38 | , transformers >=0.3 && <1 | ||
39 | , explicit-exception >=0.1 && <1 | ||
40 | , process >=1.2 && <2 | ||
41 | , filelock >=0.1 && <1 | ||
42 | , systemd >=1.1.2 && <2 | ||
43 | , heredoc >=0.2.0.0 && <1 | ||
44 | , refined >=0.1.2.1 && <1 | ||
45 | , trivmix | ||
46 | hs-source-dirs: trivmix | ||
47 | default-language: Haskell2010 | ||
48 | ghc-options: -threaded | ||
49 | 30 | ||
50 | executable adjmix | 31 | executable adjmix |
51 | main-is: Adjmix.hs | 32 | main-is: Adjmix.hs |
52 | build-depends: base >=4.8 && <5 | 33 | other-modules: |
53 | , optparse-applicative >=0.11 && <1 | 34 | Paths_trivmix |
54 | , filepath >=1.3 && <2 | 35 | hs-source-dirs: |
55 | , filelock >=0.1 && <1 | 36 | adjmix |
56 | , trivmix | 37 | build-depends: |
57 | hs-source-dirs: adjmix | 38 | base >=4.8 && <5 |
58 | default-language: Haskell2010 | 39 | , filelock >=0.1 && <1 |
40 | , filepath >=1.3 && <2 | ||
41 | , optparse-applicative >=0.11 && <1 | ||
42 | , trivmix | ||
43 | default-language: Haskell2010 | ||
44 | |||
45 | executable trivmix | ||
46 | main-is: Trivmix.hs | ||
47 | other-modules: | ||
48 | Paths_trivmix | ||
49 | hs-source-dirs: | ||
50 | trivmix | ||
51 | build-depends: | ||
52 | base >=4.8 && <5 | ||
53 | , directory >=1.2 && <2 | ||
54 | , explicit-exception >=0.1 && <1 | ||
55 | , filelock >=0.1 && <1 | ||
56 | , filepath >=1.3 && <2 | ||
57 | , heredoc >=0.2.0.0 && <1 | ||
58 | , hinotify >=0.3 && <1 | ||
59 | , jack >=0.7 && <1 | ||
60 | , optparse-applicative >=0.11 && <1 | ||
61 | , process >=1.2 && <2 | ||
62 | , refined >=0.1.2.1 && <1 | ||
63 | , systemd >=1.1.2 && <2 | ||
64 | , transformers >=0.3 && <1 | ||
65 | , trivmix | ||
66 | , unix >=2.7 && <3 | ||
67 | default-language: Haskell2010 | ||
diff --git a/trivmix.cabal.gup b/trivmix.cabal.gup new file mode 100644 index 0000000..51bcecc --- /dev/null +++ b/trivmix.cabal.gup | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/usr/bin/env zsh | ||
2 | |||
3 | gup -u ${2:h}/package.yaml | ||
4 | hpack ${2:h}/package.yaml - >! ${1} \ No newline at end of file | ||
diff --git a/trivmix.nix b/trivmix.nix index be84746..bcc7037 100644 --- a/trivmix.nix +++ b/trivmix.nix | |||
@@ -1,16 +1,16 @@ | |||
1 | { mkDerivation, base, case-insensitive, data-default, directory | 1 | { mkDerivation, base, case-insensitive, data-default, directory |
2 | , explicit-exception, filelock, filepath, heredoc, hinotify, jack | 2 | , explicit-exception, filelock, filepath, heredoc, hinotify, jack |
3 | , optparse-applicative, process, refined, stdenv, systemd | 3 | , optparse-applicative, process, refined, scientific, stdenv |
4 | , transformers, unix | 4 | , systemd, th-lift, transformers, unix |
5 | }: | 5 | }: |
6 | mkDerivation { | 6 | mkDerivation { |
7 | pname = "trivmix"; | 7 | pname = "trivmix"; |
8 | version = "3.3.2"; | 8 | version = "4.0.0"; |
9 | src = ./.; | 9 | src = ./.; |
10 | isLibrary = true; | 10 | isLibrary = true; |
11 | isExecutable = true; | 11 | isExecutable = true; |
12 | libraryHaskellDepends = [ | 12 | libraryHaskellDepends = [ |
13 | base case-insensitive data-default refined | 13 | base case-insensitive data-default refined scientific th-lift |
14 | ]; | 14 | ]; |
15 | executableHaskellDepends = [ | 15 | executableHaskellDepends = [ |
16 | base directory explicit-exception filelock filepath heredoc | 16 | base directory explicit-exception filelock filepath heredoc |
diff --git a/trivmix/Trivmix.hs b/trivmix/Trivmix.hs index b2d87ec..5cddf6f 100644 --- a/trivmix/Trivmix.hs +++ b/trivmix/Trivmix.hs | |||
@@ -43,8 +43,9 @@ import Control.Monad | |||
43 | 43 | ||
44 | import Text.Heredoc (str) | 44 | import Text.Heredoc (str) |
45 | 45 | ||
46 | import Refined (refine) | 46 | import Refined |
47 | 47 | ||
48 | import Data.Scientific | ||
48 | import Trivmix.Types | 49 | import Trivmix.Types |
49 | 50 | ||
50 | data Options = Options | 51 | data Options = Options |
@@ -53,7 +54,7 @@ data Options = Options | |||
53 | , client :: String | 54 | , client :: String |
54 | , initialLevel :: Level | 55 | , initialLevel :: Level |
55 | , initialBalance :: Balance | 56 | , initialBalance :: Balance |
56 | , fps, interval :: Float | 57 | , fps, interval, watchdogInterval :: Scientific |
57 | , run :: [FilePath] | 58 | , run :: [FilePath] |
58 | , balanceFiles :: [FilePath] | 59 | , balanceFiles :: [FilePath] |
59 | , levelFiles :: [FilePath] | 60 | , levelFiles :: [FilePath] |
@@ -101,6 +102,12 @@ optionParser = Options | |||
101 | <> value 0.2 | 102 | <> value 0.2 |
102 | <> showDefault | 103 | <> showDefault |
103 | ) | 104 | ) |
105 | <*> option auto ( long "watchdog" | ||
106 | <> metavar "NUMBER" | ||
107 | <> help "Signal watchdog every ’NUMBER’ seconds" | ||
108 | <> value 1 | ||
109 | <> showDefault | ||
110 | ) | ||
104 | <*> many ( strOption ( long "run" | 111 | <*> many ( strOption ( long "run" |
105 | <> metavar "FILE" | 112 | <> metavar "FILE" |
106 | <> help [str|Execute a file once setup of jacks is done (use this to autoconnect) | 113 | <> help [str|Execute a file once setup of jacks is done (use this to autoconnect) |
@@ -183,18 +190,16 @@ trivmix Options{..} = do | |||
183 | frames = interval * fps | 190 | frames = interval * fps |
184 | delay = round $ recip fps * 1e6 | 191 | delay = round $ recip fps * 1e6 |
185 | linInt x a b = a * (1 - x) + b * x | 192 | linInt x a b = a * (1 - x) + b * x |
186 | linInt' x a b = either error id $ asFloat (linInt x) a b | 193 | linInt' x a b = either error id $ asScientific (linInt x) a b |
187 | mulBalance (bToFloat -> b) x = either error id $ asFloat (*) (Lin . either error id $ refine b) x | 194 | mulBalance (bToScientific -> b) x = either error id $ asScientific (*) (Lin . either error id $ refine b) x |
188 | newLevel <- mulBalance <$> readMVar balance <*> readMVar level | 195 | newLevel <- mulBalance <$> readMVar balance <*> readMVar level |
189 | currentLevel <- readMVar level' | 196 | currentLevel <- (\(CFloat f) -> Lin . either error id . refine $ realToFrac f) <$> readMVar level' |
190 | mapM_ (\x -> swapMVar level' (linInt' x currentLevel newLevel) >> threadDelay delay) [0,recip frames..1] | 197 | mapM_ (\x -> (swapMVar level' $! toRealFloat . unrefine . toLin $ linInt' x currentLevel newLevel) >> threadDelay delay) (takeWhile (<= 1) $ iterate (+ recip frames) 0) |
191 | notifyReady | 198 | notifyReady |
192 | forever $ threadDelay 1000000 >> notifyWatchdog | 199 | forever $ threadDelay (round $ watchdogInterval * 1e6) >> notifyWatchdog |
193 | 200 | ||
194 | mix :: MVar Level -> CFloat -> IO CFloat | 201 | mix :: MVar CFloat -> CFloat -> IO CFloat |
195 | mix level input = do | 202 | mix level input = (input *) <$> readMVar level |
196 | level' <- readMVar level | ||
197 | return $ (CFloat $ toFloat level') * input | ||
198 | 203 | ||
199 | handleFiles :: (Read l, Show l, Eq l) => INotify -> MVar l -> [FilePath] -> IO () | 204 | handleFiles :: (Read l, Show l, Eq l) => INotify -> MVar l -> [FilePath] -> IO () |
200 | handleFiles inotify level files = do | 205 | handleFiles inotify level files = do |