-- | -- Module : DobutokO.Sound.Effects.Dither -- Copyright : (c) OleksandrZhabenko 2020 -- License : MIT -- Stability : Experimental -- Maintainer : olexandr543@yahoo.com -- -- Helps to create experimental music. -- Can be used for applying the SoX \"dither\" effect. -- {-# OPTIONS_GHC -threaded #-} {-# LANGUAGE CPP, FlexibleInstances #-} module DobutokO.Sound.Effects.Dither where #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__>=710 /* code that applies only to GHC 7.10.* and higher versions */ import GHC.Base (mconcat) #endif #endif import Numeric (showFFloat) import DobutokO.Sound.ToRange #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__==708 /* code that applies only to GHC 7.8.* */ mconcat = concat #endif #endif data NoiseType = Lipshitz | FWeighted | ModifiedEWeighted | ImprovedEWeighted | Gesemann | Shibata | LowShibata | HighShibata deriving Eq instance Show NoiseType where show Lipshitz = "lipshitz " show FWeighted = "f-weighted " show ModifiedEWeighted = "modified-e-weighted " show ImprovedEWeighted = "improved-e-weighted " show Gesemann = "gesemann " show Shibata = "shibata " show LowShibata = "low-shibata " show HighShibata = "high-shibata " data Filter a = N | Ss | S | F a deriving Eq instance Show (Filter NoiseType) where show N = "" show S = "-S " show (F x) = mconcat ["-f ", show x] show _ = "-s " type FilterN = Filter NoiseType filterC :: Filter a -> String filterC N = "N" filterC S = "S" filterC Ss = "Ss" filterC _ = "F" filter1 :: Filter a -> Maybe a filter1 (F x) = Just x filter1 _ = Nothing filterN1 :: FilterN -> Maybe NoiseType filterN1 (F x) = Just x filterN1 Ss = Just Shibata filterN1 _ = Nothing filterSet1 :: a -> Filter a filterSet1 = F data AutoD = A | N0 deriving Eq instance Show AutoD where show A = "-a " show _ = "" autoDC :: AutoD -> String autoDC A = "A" autoDC _ ="N0" data PrecisionD a = P a | N2 deriving Eq instance Show (PrecisionD Float) where show N2 = "" show (P x) = mconcat ["-p ", showFFloat Nothing (if compare (toRange 24.0 . abs $ x) 1.0 == LT then 1.0 else (toRange 24.0 . abs $ x)) " "] type Precision = PrecisionD Float precisionDC :: PrecisionD a -> String precisionDC (P _) = "P" precisionDC _ = "N2" precisionD1 :: PrecisionD a -> Maybe a precisionD1 (P x) = Just x precisionD1 _ = Nothing precisionSet1 :: Float -> Precision precisionSet1 x = if compare (toRange 24.0 . abs $ x) 1.0 == LT then P 1.0 else P (toRange 24.0 . abs $ x) data Dither a b c = DT0 | DT100 a | DT010 b | DT001 c | DT011 b c | DT110 a b | DT101 a c | DT a b c deriving Eq instance Show (Dither FilterN AutoD Precision) where show DT0 = "dither " show (DT100 x) = mconcat ["dither ", show x] show (DT010 y) = mconcat ["dither ", show y] show (DT001 z) = mconcat ["dither ", show z] show (DT011 y z) = mconcat ["dither ", show y, show z] show (DT110 x y) = mconcat ["dither ", show x, show y] show (DT101 x z) = mconcat ["dither ", show x, show z] show (DT x y z) = mconcat ["dither ", show x, show y, show z] type Dith = Dither FilterN AutoD Precision ditherC :: Dither a b c -> String ditherC DT0 = "DT0" ditherC (DT100 _) = "DT100" ditherC (DT010 _) = "DT010" ditherC (DT001 _) = "DT001" ditherC (DT011 _ _) = "DT011" ditherC (DT110 _ _) = "DT110" ditherC (DT101 _ _) = "DT101" ditherC _ = "DT" dither1 :: Dither a b c -> Maybe a dither1 (DT100 x) = Just x dither1 (DT101 x _) = Just x dither1 (DT110 x _) = Just x dither1 (DT x _ _) = Just x dither1 _ = Nothing dither2 :: Dither a b c -> Maybe b dither2 (DT010 y) = Just y dither2 (DT011 y _) = Just y dither2 (DT110 _ y) = Just y dither2 (DT _ y _) = Just y dither2 _ = Nothing dither3 :: Dither a b c -> Maybe c dither3 (DT001 z) = Just z dither3 (DT101 _ z) = Just z dither3 (DT011 _ z) = Just z dither3 (DT _ _ z) = Just z dither3 _ = Nothing ditherSet1 :: a -> Dither a b c -> Dither a b c ditherSet1 x (DT010 y) = DT110 x y ditherSet1 x (DT001 z) = DT101 x z ditherSet1 x (DT011 y z) = DT x y z ditherSet1 x (DT110 _ y) = DT110 x y ditherSet1 x (DT101 _ z) = DT101 x z ditherSet1 x (DT _ y z) = DT x y z ditherSet1 x _ = DT100 x ditherSet2 :: b -> Dither a b c -> Dither a b c ditherSet2 y (DT100 x) = DT110 x y ditherSet2 y (DT001 z) = DT011 y z ditherSet2 y (DT011 _ z) = DT011 y z ditherSet2 y (DT110 x _) = DT110 x y ditherSet2 y (DT101 x z) = DT x y z ditherSet2 y (DT x _ z) = DT x y z ditherSet2 y _ = DT010 y ditherSet3 :: c -> Dither a b c -> Dither a b c ditherSet3 z (DT100 x) = DT101 x z ditherSet3 z (DT010 y) = DT011 y z ditherSet3 z (DT011 y _) = DT011 y z ditherSet3 z (DT101 x _) = DT101 x z ditherSet3 z (DT110 x y) = DT x y z ditherSet3 z (DT x y _) = DT x y z ditherSet3 z _ = DT001 z showDQ :: Dith -> [String] showDQ = words . show