-- |
-- Module      :  DobutokO.Sound.Effects.Bend
-- Copyright   :  (c) OleksandrZhabenko 2020
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- Helps to create experimental music. 
-- Can be used for applying the \"bend\" SoX effect. 
-- 

{-# OPTIONS_GHC -threaded #-}
{-# LANGUAGE FlexibleInstances #-}

module DobutokO.Sound.Effects.Bend where

import Numeric (showFFloat)
import DobutokO.Sound.Effects.Timespec

data BendTrio a b = Bend3 a b a deriving BendTrio a b -> BendTrio a b -> Bool
(BendTrio a b -> BendTrio a b -> Bool)
-> (BendTrio a b -> BendTrio a b -> Bool) -> Eq (BendTrio a b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b. (Eq a, Eq b) => BendTrio a b -> BendTrio a b -> Bool
/= :: BendTrio a b -> BendTrio a b -> Bool
$c/= :: forall a b. (Eq a, Eq b) => BendTrio a b -> BendTrio a b -> Bool
== :: BendTrio a b -> BendTrio a b -> Bool
$c== :: forall a b. (Eq a, Eq b) => BendTrio a b -> BendTrio a b -> Bool
Eq

instance Show (BendTrio FirstTSpec Float) where
  show :: BendTrio FirstTSpec Float -> String
show (Bend3 FirstTSpec
x Float
y FirstTSpec
z) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [FirstTSpec -> String
forall a. Show a => a -> String
show FirstTSpec
x, String
",", Maybe Int -> Float -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showFFloat Maybe Int
forall a. Maybe a
Nothing Float
y String
",", FirstTSpec -> String
forall a. Show a => a -> String
show FirstTSpec
z]

type BendTr3 = BendTrio FirstTSpec Float

bendTrio1 :: BendTrio a b -> a
bendTrio1 :: BendTrio a b -> a
bendTrio1 (Bend3 a
x b
_ a
_) = a
x

bendTrio2 :: BendTrio a b -> b
bendTrio2 :: BendTrio a b -> b
bendTrio2 (Bend3 a
_ b
y a
_) = b
y

bendTrio3 :: BendTrio a b -> a
bendTrio3 :: BendTrio a b -> a
bendTrio3 (Bend3 a
_ b
_ a
z) = a
z

bendTrioSet1 :: a -> BendTrio a b -> BendTrio a b
bendTrioSet1 :: a -> BendTrio a b -> BendTrio a b
bendTrioSet1 a
x (Bend3 a
_ b
y a
z) = a -> b -> a -> BendTrio a b
forall a b. a -> b -> a -> BendTrio a b
Bend3 a
x b
y a
z

bendTrioSet2 :: b -> BendTrio a b -> BendTrio a b
bendTrioSet2 :: b -> BendTrio a b -> BendTrio a b
bendTrioSet2 b
y (Bend3 a
x b
_ a
z) = a -> b -> a -> BendTrio a b
forall a b. a -> b -> a -> BendTrio a b
Bend3 a
x b
y a
z

bendTrioSet3 :: a -> BendTrio a b -> BendTrio a b
bendTrioSet3 :: a -> BendTrio a b -> BendTrio a b
bendTrioSet3 a
z (Bend3 a
x b
y a
_) = a -> b -> a -> BendTrio a b
forall a b. a -> b -> a -> BendTrio a b
Bend3 a
x b
y a
z

data FrameRate a = FR a deriving FrameRate a -> FrameRate a -> Bool
(FrameRate a -> FrameRate a -> Bool)
-> (FrameRate a -> FrameRate a -> Bool) -> Eq (FrameRate a)
forall a. Eq a => FrameRate a -> FrameRate a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FrameRate a -> FrameRate a -> Bool
$c/= :: forall a. Eq a => FrameRate a -> FrameRate a -> Bool
== :: FrameRate a -> FrameRate a -> Bool
$c== :: forall a. Eq a => FrameRate a -> FrameRate a -> Bool
Eq

instance Show (FrameRate Float) where
  show :: FrameRate Float -> String
show (FR Float
x) 
    | Float -> Float -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Float
x Float
10.0 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
/= Ordering
LT Bool -> Bool -> Bool
&& Float -> Float -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Float
x Float
80.0 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
/= Ordering
GT = String
"-f " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe Int -> Float -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showFFloat Maybe Int
forall a. Maybe a
Nothing Float
x String
" "
    | Bool
otherwise = String
""

type FrRate = FrameRate Float    

frameRate1 :: FrameRate a -> a
frameRate1 :: FrameRate a -> a
frameRate1 (FR a
x) = a
x

frameRateSet1 :: a -> FrameRate a
frameRateSet1 :: a -> FrameRate a
frameRateSet1 = a -> FrameRate a
forall a. a -> FrameRate a
FR

data OverSample a = OS a deriving OverSample a -> OverSample a -> Bool
(OverSample a -> OverSample a -> Bool)
-> (OverSample a -> OverSample a -> Bool) -> Eq (OverSample a)
forall a. Eq a => OverSample a -> OverSample a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OverSample a -> OverSample a -> Bool
$c/= :: forall a. Eq a => OverSample a -> OverSample a -> Bool
== :: OverSample a -> OverSample a -> Bool
$c== :: forall a. Eq a => OverSample a -> OverSample a -> Bool
Eq

instance Show (OverSample Float) where
  show :: OverSample Float -> String
show (OS Float
x) 
    | Float -> Float -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Float
x Float
4.0 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
/= Ordering
LT Bool -> Bool -> Bool
&& Float -> Float -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Float
x Float
32.0 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
/= Ordering
GT = String
"-o " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe Int -> Float -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showFFloat Maybe Int
forall a. Maybe a
Nothing Float
x String
" "
    | Bool
otherwise = String
""

type OvSample = OverSample Float

overSample1 :: OverSample a -> a
overSample1 :: OverSample a -> a
overSample1 (OS a
x) = a
x

overSampleSet1 :: a -> OverSample a
overSampleSet1 :: a -> OverSample a
overSampleSet1 = a -> OverSample a
forall a. a -> OverSample a
OS

data Bend a b c = Bnd c | Bnd1 a c | Bnd2 b c | Bnd12 a b c deriving Bend a b c -> Bend a b c -> Bool
(Bend a b c -> Bend a b c -> Bool)
-> (Bend a b c -> Bend a b c -> Bool) -> Eq (Bend a b c)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b c.
(Eq c, Eq a, Eq b) =>
Bend a b c -> Bend a b c -> Bool
/= :: Bend a b c -> Bend a b c -> Bool
$c/= :: forall a b c.
(Eq c, Eq a, Eq b) =>
Bend a b c -> Bend a b c -> Bool
== :: Bend a b c -> Bend a b c -> Bool
$c== :: forall a b c.
(Eq c, Eq a, Eq b) =>
Bend a b c -> Bend a b c -> Bool
Eq

instance Show (Bend FrRate OvSample BendTr3) where
  show :: Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
-> String
show (Bnd BendTrio FirstTSpec Float
z) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"bend ",BendTrio FirstTSpec Float -> String
forall a. Show a => a -> String
show BendTrio FirstTSpec Float
z]
  show (Bnd1 FrameRate Float
x BendTrio FirstTSpec Float
z) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"bend ",FrameRate Float -> String
forall a. Show a => a -> String
show FrameRate Float
x,BendTrio FirstTSpec Float -> String
forall a. Show a => a -> String
show BendTrio FirstTSpec Float
z]
  show (Bnd2 OverSample Float
y BendTrio FirstTSpec Float
z) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"bend ",OverSample Float -> String
forall a. Show a => a -> String
show OverSample Float
y,BendTrio FirstTSpec Float -> String
forall a. Show a => a -> String
show BendTrio FirstTSpec Float
z]
  show (Bnd12 FrameRate Float
x OverSample Float
y BendTrio FirstTSpec Float
z) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"bend ", FrameRate Float -> String
forall a. Show a => a -> String
show FrameRate Float
x, OverSample Float -> String
forall a. Show a => a -> String
show OverSample Float
y, BendTrio FirstTSpec Float -> String
forall a. Show a => a -> String
show BendTrio FirstTSpec Float
z]

type BendE = Bend FrRate OvSample BendTr3

bend1 :: Bend a b c -> Maybe a
bend1 :: Bend a b c -> Maybe a
bend1 (Bnd1 a
x c
_) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
bend1 (Bnd12 a
x b
_ c
_) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
bend1 Bend a b c
_ = Maybe a
forall a. Maybe a
Nothing

bend2 :: Bend a b c -> Maybe b
bend2 :: Bend a b c -> Maybe b
bend2 (Bnd2 b
y c
_) = b -> Maybe b
forall a. a -> Maybe a
Just b
y
bend2 (Bnd12 a
_ b
y c
_) = b -> Maybe b
forall a. a -> Maybe a
Just b
y
bend2 Bend a b c
_ = Maybe b
forall a. Maybe a
Nothing

bendE1 :: BendE -> FrRate
bendE1 :: Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
-> FrameRate Float
bendE1 (Bnd1 FrameRate Float
x BendTrio FirstTSpec Float
_) = FrameRate Float
x
bendE1 (Bnd12 FrameRate Float
x OverSample Float
_ BendTrio FirstTSpec Float
_) = FrameRate Float
x
bendE1 Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
_ = Float -> FrameRate Float
forall a. a -> FrameRate a
FR Float
25.0

bendE2 :: BendE -> OvSample
bendE2 :: Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
-> OverSample Float
bendE2 (Bnd2 OverSample Float
y BendTrio FirstTSpec Float
_) = OverSample Float
y
bendE2 (Bnd12 FrameRate Float
_ OverSample Float
y BendTrio FirstTSpec Float
_) = OverSample Float
y
bendE2 Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
_ = Float -> OverSample Float
forall a. a -> OverSample a
OS Float
16.0

bend3 :: Bend a b c -> c
bend3 :: Bend a b c -> c
bend3 (Bnd c
z) = c
z
bend3 (Bnd1 a
_ c
z) = c
z
bend3 (Bnd2 b
_ c
z) = c
z
bend3 (Bnd12 a
_ b
_ c
z) = c
z

bendSet1 :: a -> Bend a b c -> Bend a b c
bendSet1 :: a -> Bend a b c -> Bend a b c
bendSet1 a
_ (Bnd c
z) = c -> Bend a b c
forall a b c. c -> Bend a b c
Bnd c
z
bendSet1 a
x (Bnd1 a
_ c
z) = a -> c -> Bend a b c
forall a b c. a -> c -> Bend a b c
Bnd1 a
x c
z
bendSet1 a
x (Bnd2 b
y c
z) = a -> b -> c -> Bend a b c
forall a b c. a -> b -> c -> Bend a b c
Bnd12 a
x b
y c
z
bendSet1 a
x (Bnd12 a
_ b
y c
z) = a -> b -> c -> Bend a b c
forall a b c. a -> b -> c -> Bend a b c
Bnd12 a
x b
y c
z

bendSet2 :: b -> Bend a b c -> Bend a b c
bendSet2 :: b -> Bend a b c -> Bend a b c
bendSet2 b
y (Bnd c
z) = b -> c -> Bend a b c
forall a b c. b -> c -> Bend a b c
Bnd2 b
y c
z
bendSet2 b
y (Bnd1 a
x c
z) = a -> b -> c -> Bend a b c
forall a b c. a -> b -> c -> Bend a b c
Bnd12 a
x b
y c
z
bendSet2 b
y (Bnd2 b
_ c
z) = b -> c -> Bend a b c
forall a b c. b -> c -> Bend a b c
Bnd2 b
y c
z
bendSet2 b
y (Bnd12 a
x b
_ c
z) = a -> b -> c -> Bend a b c
forall a b c. a -> b -> c -> Bend a b c
Bnd12 a
x b
y c
z

bendSet3 :: c -> Bend a b c -> Bend a b c
bendSet3 :: c -> Bend a b c -> Bend a b c
bendSet3 c
z (Bnd c
_) = c -> Bend a b c
forall a b c. c -> Bend a b c
Bnd c
z
bendSet3 c
z (Bnd1 a
x c
_) = a -> c -> Bend a b c
forall a b c. a -> c -> Bend a b c
Bnd1 a
x c
z
bendSet3 c
z (Bnd2 b
y c
_) = b -> c -> Bend a b c
forall a b c. b -> c -> Bend a b c
Bnd2 b
y c
z
bendSet3 c
z (Bnd12 a
x b
y c
_) = a -> b -> c -> Bend a b c
forall a b c. a -> b -> c -> Bend a b c
Bnd12 a
x b
y c
z

showBndQ :: BendE -> [String]
showBndQ :: Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
-> [String]
showBndQ = String -> [String]
words (String -> [String])
-> (Bend
      (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
    -> String)
-> Bend
     (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bend
  (FrameRate Float) (OverSample Float) (BendTrio FirstTSpec Float)
-> String
forall a. Show a => a -> String
show