summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2015-06-21 19:40:40 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2015-06-21 19:40:40 +0200
commit4658cc95745dbdffd7bc1be2e61fa463b28b4a16 (patch)
tree0656da1577123f9f4eb05b72d66ad6c4682c5661
parent5aeef88338cd761066ba196472e22f2c55fc846a (diff)
downloadtrivmix-4658cc95745dbdffd7bc1be2e61fa463b28b4a16.tar
trivmix-4658cc95745dbdffd7bc1be2e61fa463b28b4a16.tar.gz
trivmix-4658cc95745dbdffd7bc1be2e61fa463b28b4a16.tar.bz2
trivmix-4658cc95745dbdffd7bc1be2e61fa463b28b4a16.tar.xz
trivmix-4658cc95745dbdffd7bc1be2e61fa463b28b4a16.zip
Added adjmix
-rw-r--r--adjmix/Adjmix.hs71
-rw-r--r--src/Trivmix/Types.hs90
-rw-r--r--trivmix.cabal23
-rw-r--r--trivmix.nix12
-rw-r--r--trivmix/Trivmix.hs (renamed from src/Trivmix.hs)46
5 files changed, 189 insertions, 53 deletions
diff --git a/adjmix/Adjmix.hs b/adjmix/Adjmix.hs
new file mode 100644
index 0000000..49b820f
--- /dev/null
+++ b/adjmix/Adjmix.hs
@@ -0,0 +1,71 @@
1{-# LANGUAGE RecordWildCards #-}
2
3import Options.Applicative
4
5import System.FilePath
6
7import Data.Char
8
9import Trivmix.Types
10
11data Options = Options
12 { baseDirectory :: FilePath
13 , targetDirectory :: FilePath
14 , levelFile :: FilePath
15 , adjustment :: Adjustment Level
16 }
17optionParser :: Parser Options
18optionParser = Options
19 <$> strOption ( long "base"
20 <> metavar "DIRECTORY"
21 <> value "/dev/shm/mix"
22 )
23 <*> strOption ( long "target"
24 <> short 't'
25 <> metavar "DIRECTORY"
26 <> help "Directory relative to ‘--base’ containing the level file"
27 )
28 <*> strOption ( long "level"
29 <> metavar "FILENAME"
30 <> value "level"
31 <> help "Filename of the level file"
32 )
33 <*> ( ( Set <$> option auto ( long "set"
34 <> short 'o'
35 <> metavar "LEVEL"
36 )
37 )
38 <|> ( Add <$> option auto ( long "add"
39 <> short 'a'
40 <> metavar "LEVEL"
41 )
42 )
43 <|> ( Sub <$> option auto ( long "sub"
44 <> short 's'
45 <> metavar "LEVEL"
46 )
47 )
48 )
49
50main :: IO ()
51main = execParser opts >>= adjmix
52 where
53 opts = info (helper <*> optionParser)
54 ( fullDesc
55 <> progDesc "Adjust the level file of a trivmix"
56 <> header "Adjmix — A trivial interface to a trivial mixer"
57 )
58
59adjmix :: Options -> IO ()
60adjmix Options{..} = do
61 oldLevel <- readFile levelFile >>= readIO . stripSpace
62 let
63 newLevel = oldLevel `doAdjustment` adjustment
64 writeFile levelFile (show newLevel ++ "\n")
65 where
66 levelFile = baseDirectory </> targetDirectory </> levelFile
67 stripSpace = reverse . stripSpace' . reverse . stripSpace'
68 stripSpace' [] = []
69 stripSpace' l@(x:xs) = if isSpace x
70 then stripSpace' xs
71 else l
diff --git a/src/Trivmix/Types.hs b/src/Trivmix/Types.hs
new file mode 100644
index 0000000..66accdf
--- /dev/null
+++ b/src/Trivmix/Types.hs
@@ -0,0 +1,90 @@
1{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
2
3module Trivmix.Types
4 ( Level
5 , toFloat
6 , Adjustment(..)
7 , doAdjustment
8 , module Data.Default
9 ) where
10
11import Data.Fixed
12import Data.CaseInsensitive ( CI )
13import qualified Data.CaseInsensitive as CI
14
15import Data.Default
16
17import Data.Function (on)
18
19data Level = Lin Float | DB Float
20
21instance Num Level where
22 (+) = asFloat (+)
23 (-) = asFloat (-)
24 (*) = asFloat (*)
25 abs = Lin . abs . toFloat
26 signum = Lin . signum . toFloat
27 fromInteger = Lin . fromInteger
28
29asFloat :: (Float -> Float -> Float) -> Level -> Level -> Level
30asFloat f (Lin x) (Lin y) = Lin $ f x y
31asFloat f x y = DB $ (f `on` toFloat) x y
32
33toFloat :: Level -> Float
34toFloat (Lin x) = x
35toFloat (DB x) = x
36
37withPrec :: (Num a, RealFrac a, HasResolution b) => a -> Fixed b
38withPrec x = withResolution $ \p' -> MkFixed $ toInteger $ round $ x * (fromInteger p')
39
40withType :: (p a -> f a) -> f a
41withType f = f undefined
42
43withResolution :: (HasResolution a) => (Integer -> f a) -> f a
44withResolution f = withType (f . resolution)
45
46instance Show Level where
47 show (Lin x) = show x
48 show (DB x) = (show $ (withPrec x' :: Milli)) ++ "dB"
49 where
50 x' = 20 * (logBase 10 x)
51
52instance Read Level where
53 readsPrec i = map toL . readsPrec i
54 where
55 toL :: (Float, String) -> (Level, String)
56 toL (f, str)
57 | ((==) `on` CI.mk) prec unit = (DB $ 10 ** (0.05 * f), rest)
58 | otherwise = (Lin f, str)
59 where
60 prec = take lU str
61 rest = drop lU str
62 unit = "dB"
63 lU = length unit
64
65instance Eq Level where
66 (Lin a) == (Lin b) = a == b
67 (Lin a) == (DB b) = a == b
68 (DB a) == (Lin b) = a == b
69 (DB a) == (DB b) = a == b
70
71instance Default Level where
72 def = Lin 0
73
74data Adjustment a = Set a
75 | Add a
76 | Sub a
77 deriving (Show, Eq)
78
79class Adjustable a where
80 add :: a -> a -> a
81 sub :: a -> a -> a
82
83instance Num a => Adjustable a where
84 add = (+)
85 sub = (-)
86
87doAdjustment :: Adjustable a => a -> Adjustment a -> a
88doAdjustment _ (Set y) = y
89doAdjustment x (Add y) = add x y
90doAdjustment x (Sub y) = sub x y
diff --git a/trivmix.cabal b/trivmix.cabal
index 40aa9a8..0e02a7d 100644
--- a/trivmix.cabal
+++ b/trivmix.cabal
@@ -2,7 +2,7 @@
2-- documentation, see http://haskell.org/cabal/users-guide/ 2-- documentation, see http://haskell.org/cabal/users-guide/
3 3
4name: trivmix 4name: trivmix
5version: 2.4.6 5version: 2.5.0
6-- synopsis: 6-- synopsis:
7-- description: 7-- description:
8license: PublicDomain 8license: PublicDomain
@@ -15,6 +15,14 @@ build-type: Simple
15-- extra-source-files: 15-- extra-source-files:
16cabal-version: >=1.10 16cabal-version: >=1.10
17 17
18library
19 hs-source-dirs: src
20 default-language: Haskell2010
21 exposed-modules: Trivmix.Types
22 build-depends: base >=4.7 && <4.8
23 , data-default >=0.5 && <1
24 , case-insensitive >=1.2 && <2
25
18executable trivmix 26executable trivmix
19 main-is: Trivmix.hs 27 main-is: Trivmix.hs
20 -- other-modules: 28 -- other-modules:
@@ -29,12 +37,21 @@ executable trivmix
29 , transformers >=0.3 && <1 37 , transformers >=0.3 && <1
30 , explicit-exception >=0.1 && <1 38 , explicit-exception >=0.1 && <1
31 , process >=1.2 && <2 39 , process >=1.2 && <2
32 , case-insensitive >=1.2 && <2
33 , filelock >=0.1 && <1 40 , filelock >=0.1 && <1
34 hs-source-dirs: src 41 , trivmix
42 hs-source-dirs: trivmix
35 default-language: Haskell2010 43 default-language: Haskell2010
36 ghc-options: -threaded 44 ghc-options: -threaded
37 45
46executable adjmix
47 main-is: Adjmix.hs
48 build-depends: base >=4.7 && <4.8
49 , optparse-applicative >=0.11 && <1
50 , filepath >=1.3 && <2
51 , trivmix
52 hs-source-dirs: adjmix
53 default-language: Haskell2010
54
38-- Local Variables: 55-- Local Variables:
39-- firestarter: "nix-shell -p haskellPackages.cabal2nix --command 'cabal2nix ./.' | tee trivmix.nix" 56-- firestarter: "nix-shell -p haskellPackages.cabal2nix --command 'cabal2nix ./.' | tee trivmix.nix"
40-- End: 57-- End:
diff --git a/trivmix.nix b/trivmix.nix
index fae88fc..6edcff0 100644
--- a/trivmix.nix
+++ b/trivmix.nix
@@ -1,18 +1,18 @@
1# This file was auto-generated by cabal2nix. Please do NOT edit manually! 1# This file was auto-generated by cabal2nix. Please do NOT edit manually!
2 2
3{ cabal, caseInsensitive, explicitException, filelock, filepath 3{ cabal, caseInsensitive, dataDefault, explicitException, filelock
4, hinotify, jack, optparseApplicative, transformers 4, filepath, hinotify, jack, optparseApplicative, transformers
5}: 5}:
6 6
7cabal.mkDerivation (self: { 7cabal.mkDerivation (self: {
8 pname = "trivmix"; 8 pname = "trivmix";
9 version = "2.4.6"; 9 version = "2.5.0";
10 src = ./.; 10 src = ./.;
11 isLibrary = false; 11 isLibrary = true;
12 isExecutable = true; 12 isExecutable = true;
13 buildDepends = [ 13 buildDepends = [
14 caseInsensitive explicitException filelock filepath hinotify jack 14 caseInsensitive dataDefault explicitException filelock filepath
15 optparseApplicative transformers 15 hinotify jack optparseApplicative transformers
16 ]; 16 ];
17 meta = { 17 meta = {
18 license = self.stdenv.lib.licenses.publicDomain; 18 license = self.stdenv.lib.licenses.publicDomain;
diff --git a/src/Trivmix.hs b/trivmix/Trivmix.hs
index 37ecec6..9f0cf22 100644
--- a/src/Trivmix.hs
+++ b/trivmix/Trivmix.hs
@@ -34,11 +34,8 @@ import Data.Char
34import Data.Function 34import Data.Function
35 35
36import Control.Monad 36import Control.Monad
37
38import Data.Fixed
39 37
40import Data.CaseInsensitive ( CI ) 38import Trivmix.Types
41import qualified Data.CaseInsensitive as CI
42 39
43data Options = Options 40data Options = Options
44 { input :: String 41 { input :: String
@@ -48,42 +45,6 @@ data Options = Options
48 , levelFiles :: [FilePath] 45 , levelFiles :: [FilePath]
49 } 46 }
50 47
51data Level = Lin Float | DB Float
52
53withPrec :: (Num a, RealFrac a, HasResolution b) => a -> Fixed b
54withPrec x = withResolution $ \p' -> MkFixed $ toInteger $ round $ x * (fromInteger p')
55
56withType :: (p a -> f a) -> f a
57withType f = f undefined
58
59withResolution :: (HasResolution a) => (Integer -> f a) -> f a
60withResolution f = withType (f . resolution)
61
62instance Show Level where
63 show (Lin x) = show x
64 show (DB x) = (show $ (withPrec x' :: Milli)) ++ "dB"
65 where
66 x' = 20 * (logBase 10 x)
67
68instance Read Level where
69 readsPrec i = map toL . readsPrec i
70 where
71 toL :: (Float, String) -> (Level, String)
72 toL (f, str)
73 | ((==) `on` CI.mk) prec unit = (DB $ 10 ** (0.05 * f), rest)
74 | otherwise = (Lin f, str)
75 where
76 prec = take lU str
77 rest = drop lU str
78 unit = "dB"
79 lU = length unit
80
81instance Eq Level where
82 (Lin a) == (Lin b) = a == b
83 (Lin a) == (DB b) = a == b
84 (DB a) == (Lin b) = a == b
85 (DB a) == (DB b) = a == b
86
87optionParser :: Parser Options 48optionParser :: Parser Options
88optionParser = Options <$> 49optionParser = Options <$>
89 (fromMaybe "in" <$> optional (strOption ( long "input" 50 (fromMaybe "in" <$> optional (strOption ( long "input"
@@ -120,7 +81,7 @@ watchedAttrs = [ Modify
120 ] 81 ]
121 82
122initialLevel :: Level 83initialLevel :: Level
123initialLevel = Lin 0 84initialLevel = def
124 85
125defFileMode :: FileMode 86defFileMode :: FileMode
126defFileMode = foldl unionFileModes nullFileMode [ ownerReadMode 87defFileMode = foldl unionFileModes nullFileMode [ ownerReadMode
@@ -168,9 +129,6 @@ mix :: MVar Level -> CFloat -> IO CFloat
168mix level input = do 129mix level input = do
169 level' <- readMVar level 130 level' <- readMVar level
170 return $ (CFloat $ toFloat level') * input 131 return $ (CFloat $ toFloat level') * input
171 where
172 toFloat (Lin x) = x
173 toFloat (DB x) = x
174 132
175handleFiles :: INotify -> MVar Level -> [FilePath] -> IO () 133handleFiles :: INotify -> MVar Level -> [FilePath] -> IO ()
176handleFiles inotify level files = do 134handleFiles inotify level files = do