-- | -- Module : DobutokO.Sound.Effects.Remix -- Copyright : (c) OleksandrZhabenko 2020 -- License : MIT -- Stability : Experimental -- Maintainer : olexandr543@yahoo.com -- -- Helps to create experimental music. -- Can be used for applying the SoX \"remix\" effect. -- {-# OPTIONS_GHC -threaded #-} {-# LANGUAGE CPP, FlexibleInstances #-} module DobutokO.Sound.Effects.Remix 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 Data.List (intersperse) #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__==708 /* code that applies only to GHC 7.8.* */ mconcat = concat #endif #endif data Vol3 a = P | I | V | P2 a | I2 a | V2 a deriving Eq instance (Show a, RealFloat a) => Show (Vol3 a) where show P = "p0" show I = "i0" show V = "v1" show (P2 a) = 'p':showFFloat Nothing a "" show (I2 a) = 'i':showFFloat Nothing a "" show (V2 a) = 'v':showFFloat Nothing a "" vol31 :: Vol3 Float -> Float vol31 P = 0.0 vol31 I = 0.0 vol31 V = 1.0 vol31 (P2 x) = x vol31 (I2 x) = x vol31 (V2 x) = x vol3Set1 :: Float -> Vol3 Float -> Vol3 Float vol3Set1 x P | x == 0.0 = P | otherwise = P2 x vol3Set1 x I | x == 0.0 = I | otherwise = I2 x vol3Set1 x V | x == 1.0 = V | otherwise = V2 x vol3Set1 x (P2 _) = P2 x vol3Set1 x (I2 _) = I2 x vol3Set1 x (V2 _) = V2 x type Vol3F = Vol3 Float data IChannel a b = ICh a (Vol3 b) deriving Eq ichannel1 :: IChannel a b -> a ichannel1 (ICh x _) = x ichannel2 :: Vol3F -> IChannel a Float -> Vol3F ichannel2 P (ICh _ y) = y ichannel2 I (ICh _ y) = y ichannel2 V (ICh _ y) = y ichannel2 (P2 _) (ICh _ y) = P2 (vol31 y) ichannel2 (I2 _) (ICh _ y) = I2 (vol31 y) ichannel2 (V2 _) (ICh _ y) = V2 (vol31 y) ichannel2C :: IChannel a b -> String ichannel2C (ICh _ P) = "P" ichannel2C (ICh _ I) = "I" ichannel2C (ICh _ V) = "V" ichannel2C (ICh _ (P2 _)) = "P2" ichannel2C (ICh _ (I2 _)) = "I2" ichannel2C (ICh _ (V2 _)) = "V2" ichannel21 :: IChannel a Float -> Float ichannel21 (ICh _ y) = vol31 y ichannelSet1 :: a -> IChannel a b -> IChannel a b ichannelSet1 x (ICh _ y) = ICh x y ichannelSet2 :: Vol3 b -> IChannel a b -> IChannel a b ichannelSet2 y (ICh x _) = ICh x y type IChanF = IChannel Int Float instance (Show a, Integral a, Show b, RealFloat b) => Show (IChannel a b) where show (ICh x y) = mconcat [show x, show y] data OChannel a = OCh [a] deriving Eq instance (Show a) => Show (OChannel a) where show (OCh []) = [] show (OCh [x]) = show x show (OCh ys) = mconcat . intersperse "," . map show $ ys ochannel1 :: OChannel a -> [a] ochannel1 (OCh xs) = xs ochannelSet1 :: [a] -> OChannel a -> OChannel a ochannelSet1 xs _ = OCh xs type OChanF = OChannel IChanF data MixSpec = A | M | D deriving Eq instance Show MixSpec where show A = "-a " show M = "-m " show D = [] data Remix a b = Rmx | Rmix a [b] deriving Eq instance Show (Remix MixSpec OChanF) where show (Rmix x ys) = mconcat ["remix ",show x, mconcat . intersperse " " . map show $ ys] show Rmx = "remix -" remixC :: Remix a b -> String remixC Rmx = "Rmx" remixC (Rmix _ _) = "Rmix" remix1 :: Remix a b -> Maybe a remix1 Rmx = Nothing remix1 (Rmix x _) = Just x remix2 :: Remix a b -> [b] remix2 Rmx = [] remix2 (Rmix _ xs) = xs type ReMix = Remix MixSpec OChanF remixSet1 :: MixSpec -> ReMix -> ReMix remixSet1 _ Rmx = Rmx remixSet1 y (Rmix _ xs) = Rmix y xs remixSet2 :: [OChanF] -> ReMix -> ReMix remixSet2 ys Rmx = Rmix D ys remixSet2 ys (Rmix x _) = Rmix x ys showRmQ :: ReMix -> [String] showRmQ = words . show