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

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

module DobutokO.Sound.Effects.Pad where

import DobutokO.Sound.Effects.Timespec
import DobutokO.Sound.One

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

instance Show (PadSpec TSpecification) where
  show :: PadSpec TSpecification -> String
show (PS TSpecification
x TSpecification
y) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [TSpecification -> String
forall a. Show a => a -> String
show TSpecification
x,String
"@",TSpecification -> String
forall a. Show a => a -> String
show TSpecification
y,String
" "]

type PadS = PadSpec TSpecification

padSpec1 :: PadSpec a -> a
padSpec1 :: PadSpec a -> a
padSpec1 (PS a
x a
_)   = a
x

padSpec2 :: PadSpec a -> a
padSpec2 :: PadSpec a -> a
padSpec2 (PS a
_ a
y)   = a
y

padSpecSet1 :: a -> PadSpec a -> PadSpec a
padSpecSet1 :: a -> PadSpec a -> PadSpec a
padSpecSet1 a
x (PS a
_ a
y) = a -> a -> PadSpec a
forall a. a -> a -> PadSpec a
PS a
x a
y

padSpecSet2 :: a -> PadSpec a -> PadSpec a
padSpecSet2 :: a -> PadSpec a -> PadSpec a
padSpecSet2 a
y (PS a
x a
_) = a -> a -> PadSpec a
forall a. a -> a -> PadSpec a
PS a
x a
y

showPSQ :: PadS -> [String]
showPSQ :: PadSpec TSpecification -> [String]
showPSQ = String -> [String]
words (String -> [String])
-> (PadSpec TSpecification -> String)
-> PadSpec TSpecification
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PadSpec TSpecification -> String
forall a. Show a => a -> String
show 

data Pad a b = PD1 [b] | PD2 a [b] | PD3 a a [b] deriving Pad a b -> Pad a b -> Bool
(Pad a b -> Pad a b -> Bool)
-> (Pad a b -> Pad a b -> Bool) -> Eq (Pad a b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b. (Eq b, Eq a) => Pad a b -> Pad a b -> Bool
/= :: Pad a b -> Pad a b -> Bool
$c/= :: forall a b. (Eq b, Eq a) => Pad a b -> Pad a b -> Bool
== :: Pad a b -> Pad a b -> Bool
$c== :: forall a b. (Eq b, Eq a) => Pad a b -> Pad a b -> Bool
Eq

instance Show (Pad TSpecification PadS) where
  show :: Pad TSpecification (PadSpec TSpecification) -> String
show (PD1 [PadSpec TSpecification]
ys) 
    | [PadSpec TSpecification] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [PadSpec TSpecification]
ys = String
""
    | Bool
otherwise = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"pad ", [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String)
-> ([PadSpec TSpecification] -> [String])
-> [PadSpec TSpecification]
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PadSpec TSpecification -> String)
-> [PadSpec TSpecification] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map PadSpec TSpecification -> String
forall a. Show a => a -> String
show ([PadSpec TSpecification] -> String)
-> [PadSpec TSpecification] -> String
forall a b. (a -> b) -> a -> b
$ [PadSpec TSpecification]
ys]
  show (PD2 TSpecification
x [PadSpec TSpecification]
ys) 
    | [PadSpec TSpecification] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [PadSpec TSpecification]
ys = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"pad ", TSpecification -> String
forall a. Show a => a -> String
show TSpecification
x]
    | Bool
otherwise = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"pad ", TSpecification -> String
forall a. Show a => a -> String
show TSpecification
x, String
" ", [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String)
-> ([PadSpec TSpecification] -> [String])
-> [PadSpec TSpecification]
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PadSpec TSpecification -> String)
-> [PadSpec TSpecification] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map PadSpec TSpecification -> String
forall a. Show a => a -> String
show ([PadSpec TSpecification] -> String)
-> [PadSpec TSpecification] -> String
forall a b. (a -> b) -> a -> b
$ [PadSpec TSpecification]
ys]
  show (PD3 TSpecification
x TSpecification
z [PadSpec TSpecification]
ys) 
    | [PadSpec TSpecification] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [PadSpec TSpecification]
ys = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"pad ", TSpecification -> String
forall a. Show a => a -> String
show TSpecification
x, String
" ", TSpecification -> String
forall a. Show a => a -> String
show TSpecification
z, String
" "]
    | Bool
otherwise = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"pad ", TSpecification -> String
forall a. Show a => a -> String
show TSpecification
x, String
" ", [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String)
-> ([PadSpec TSpecification] -> [String])
-> [PadSpec TSpecification]
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PadSpec TSpecification -> String)
-> [PadSpec TSpecification] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map PadSpec TSpecification -> String
forall a. Show a => a -> String
show ([PadSpec TSpecification] -> String)
-> [PadSpec TSpecification] -> String
forall a b. (a -> b) -> a -> b
$ [PadSpec TSpecification]
ys, TSpecification -> String
forall a. Show a => a -> String
show TSpecification
z, String
" "]

type Pad4 = Pad TSpecification PadS

padC :: Pad a b -> String
padC :: Pad a b -> String
padC (PD1 [b]
_)   = String
"PD1"
padC (PD2 a
_ [b]
_)   = String
"PD2"
padC (PD3 a
_ a
_ [b]
_)    = String
"PD3"

pad1 :: Pad a b -> [a]
pad1 :: Pad a b -> [a]
pad1 (PD1 [b]
_) = []
pad1 (PD2 a
x [b]
_) = [a
x]
pad1 (PD3 a
x a
y [b]
_) = [a
x,a
y]

pad2 :: Pad a b -> [b]
pad2 :: Pad a b -> [b]
pad2 (PD1 [b]
ys) = [b]
ys
pad2 (PD2 a
_ [b]
ys) = [b]
ys
pad2 (PD3 a
_ a
_ [b]
ys) = [b]
ys

padSet1 :: One2 a -> Pad a b -> Pad a b
padSet1 :: One2 a -> Pad a b -> Pad a b
padSet1 (O21 a
x) (PD1 [b]
zs) = a -> [b] -> Pad a b
forall a b. a -> [b] -> Pad a b
PD2 a
x [b]
zs
padSet1 (O22 a
x a
y) (PD1 [b]
zs) = a -> a -> [b] -> Pad a b
forall a b. a -> a -> [b] -> Pad a b
PD3 a
x a
y [b]
zs
padSet1 (O21 a
x) (PD2 a
_ [b]
zs) = a -> [b] -> Pad a b
forall a b. a -> [b] -> Pad a b
PD2 a
x [b]
zs
padSet1 (O22 a
x a
y) (PD2 a
_ [b]
zs) = a -> a -> [b] -> Pad a b
forall a b. a -> a -> [b] -> Pad a b
PD3 a
x a
y [b]
zs
padSet1 (O21 a
x) (PD3 a
_ a
_ [b]
zs) = a -> [b] -> Pad a b
forall a b. a -> [b] -> Pad a b
PD2 a
x [b]
zs
padSet1 (O22 a
x a
y) (PD3 a
_ a
_ [b]
zs) = a -> a -> [b] -> Pad a b
forall a b. a -> a -> [b] -> Pad a b
PD3 a
x a
y [b]
zs

padSet2 :: [b] -> Pad a b -> Pad a b
padSet2 :: [b] -> Pad a b -> Pad a b
padSet2 [b]
zs (PD1 [b]
_) = [b] -> Pad a b
forall a b. [b] -> Pad a b
PD1 [b]
zs
padSet2 [b]
zs (PD2 a
x [b]
_) = a -> [b] -> Pad a b
forall a b. a -> [b] -> Pad a b
PD2 a
x [b]
zs
padSet2 [b]
zs (PD3 a
x a
y [b]
_) = a -> a -> [b] -> Pad a b
forall a b. a -> a -> [b] -> Pad a b
PD3 a
x a
y [b]
zs

showPaQ :: Pad4 -> [String]
showPaQ :: Pad TSpecification (PadSpec TSpecification) -> [String]
showPaQ = String -> [String]
words (String -> [String])
-> (Pad TSpecification (PadSpec TSpecification) -> String)
-> Pad TSpecification (PadSpec TSpecification)
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pad TSpecification (PadSpec TSpecification) -> String
forall a. Show a => a -> String
show