summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2018-05-15 21:21:48 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2018-05-15 21:21:48 +0200
commit879e0c7218298349b9c92e9d3362830c371ec78e (patch)
tree5f50ccbea875c2ef77c830da43fbe29964e5630a
parente8bd291609192725ea0b40190fd3bd84f0d96920 (diff)
downloadtrivmix-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.yaml49
-rw-r--r--src/Data/Scientific/Lift.hs9
-rw-r--r--src/Trivmix/Types.hs60
-rw-r--r--trivmix.cabal115
-rw-r--r--trivmix.cabal.gup4
-rw-r--r--trivmix.nix8
-rw-r--r--trivmix/Trivmix.hs27
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 @@
1name: trivmix
2version: 4.0.0
3license: PublicDomain
4license-file: LICENSE
5author: Gregor Kleen <aethoago@141.li>
6category: Sound
7build-type: Simple
8git: https://git.yggdrasil.li/gkleen/pub/trivmix
9
10library:
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
21executables:
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
4module Data.Scientific.Lift where
5
6import Data.Scientific (Scientific)
7import Language.Haskell.TH.Lift (deriveLift)
8
9deriveLift ''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
3module Trivmix.Types 3module 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
28import Refined 28import Refined
29 29
30type Level' = Refined NonNegative Float 30import Data.Scientific
31import Data.Scientific.Lift
32
33
34type Level' = Refined NonNegative Scientific
31data Level = Lin { toLin :: Level' } | DB { toLin :: Level' } 35data Level = Lin { toLin :: Level' } | DB { toLin :: Level' }
32 36
33instance Num Level where 37instance 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
41asFloat :: (Float -> Float -> Float) -> Level -> Level -> Either String Level 45asScientific :: (Scientific -> Scientific -> Scientific) -> Level -> Level -> Either String Level
42asFloat ((`on` toFloat) -> f) x y = toLvl <$> refine (f x y) 46asScientific ((`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
49toFloat :: Level -> Float 53toScientific :: Level -> Scientific
50toFloat = unrefine . toLin 54toScientific = unrefine . toLin
51 55
52withPrec :: (Num a, RealFrac a, HasResolution b) => a -> Fixed b 56withPrec :: (Num a, RealFrac a, HasResolution b) => a -> Fixed b
53withPrec x = withResolution $ \p' -> MkFixed $ toInteger $ round $ x * (fromInteger p') 57withPrec x = withResolution $ \p' -> MkFixed $ toInteger $ round $ x * (fromInteger p')
@@ -58,11 +62,11 @@ withType f = f undefined
58withResolution :: (HasResolution a) => (Integer -> f a) -> f a 62withResolution :: (HasResolution a) => (Integer -> f a) -> f a
59withResolution f = withType (f . resolution) 63withResolution f = withType (f . resolution)
60 64
61linToDb :: Level' -> Float 65linToDb :: Level' -> Scientific
62linToDb (unrefine -> x) = 20 * (logBase 10 x) 66linToDb (unrefine -> x) = realToFrac (20 * (logBase 10 $ toRealFloat x) :: Double)
63 67
64dBToLin :: Float -> Level' 68dBToLin :: Scientific -> Level'
65dBToLin x = either error id . refine $ 10 ** (0.05 * x) 69dBToLin x = either error id . refine . realToFrac $ (10 ** (0.05 * toRealFloat x) :: Double)
66 70
67instance Show Level where 71instance 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
96newtype Balance = Balance { unBalance :: Refined ZeroToOne Float } 100newtype Balance = Balance { unBalance :: Refined ZeroToOne Scientific }
97 deriving (Ord, Eq) 101 deriving (Ord, Eq)
98 102
99bAsFloat :: (Float -> Float -> Float) -> Balance -> Balance -> Either String Balance 103bAsScientific :: (Scientific -> Scientific -> Scientific) -> Balance -> Balance -> Either String Balance
100bAsFloat f (unrefine . unBalance -> x) (unrefine . unBalance -> y) = fmap Balance . refine $ f x y 104bAsScientific f (unrefine . unBalance -> x) (unrefine . unBalance -> y) = fmap Balance . refine $ f x y
101 105
102bToFloat :: Balance -> Float 106bToScientific :: Balance -> Scientific
103bToFloat = unrefine . unBalance 107bToScientific = unrefine . unBalance
104 108
105instance Num Balance where 109instance 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
113instance Show Balance where 117instance Show Balance where
114 show = show . bToFloat 118 show = show . bToScientific
115 119
116instance Read Balance where 120instance 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 1name: trivmix
2-- documentation, see http://haskell.org/cabal/users-guide/ 2version: 4.0.0
3category: Sound
4author: Gregor Kleen <aethoago@141.li>
5license: PublicDomain
6license-file: LICENSE
7build-type: Simple
8cabal-version: >= 1.10
3 9
4name: trivmix 10source-repository head
5version: 3.3.2 11 type: git
6-- synopsis: 12 location: https://git.yggdrasil.li/gkleen/pub/trivmix
7-- description:
8license: PublicDomain
9license-file: LICENSE
10author: Gregor Kleen
11maintainer: aethoago@141.li
12-- copyright:
13category: Sound
14build-type: Simple
15-- extra-source-files:
16cabal-version: >=1.10
17 13
18library 14library
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:
27executable 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
50executable adjmix 31executable 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
45executable 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
3gup -u ${2:h}/package.yaml
4hpack ${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}:
6mkDerivation { 6mkDerivation {
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
44import Text.Heredoc (str) 44import Text.Heredoc (str)
45 45
46import Refined (refine) 46import Refined
47 47
48import Data.Scientific
48import Trivmix.Types 49import Trivmix.Types
49 50
50data Options = Options 51data 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
194mix :: MVar Level -> CFloat -> IO CFloat 201mix :: MVar CFloat -> CFloat -> IO CFloat
195mix level input = do 202mix level input = (input *) <$> readMVar level
196 level' <- readMVar level
197 return $ (CFloat $ toFloat level') * input
198 203
199handleFiles :: (Read l, Show l, Eq l) => INotify -> MVar l -> [FilePath] -> IO () 204handleFiles :: (Read l, Show l, Eq l) => INotify -> MVar l -> [FilePath] -> IO ()
200handleFiles inotify level files = do 205handleFiles inotify level files = do