-- Copyright 2019 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

-- | Utilities for Balinese instruments.
module Synth.Sampler.Patch.Lib.Bali where
import qualified Data.Char as Char
import qualified Text.Read as Read

import qualified Util.Num as Num
import qualified Perform.Pitch as Pitch
import qualified Synth.Sampler.Patch.Lib.Util as Util

import           Global


data Pitch = Pitch !Pitch.Octave !PitchClass
    deriving (Pitch -> Pitch -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Pitch -> Pitch -> Bool
$c/= :: Pitch -> Pitch -> Bool
== :: Pitch -> Pitch -> Bool
$c== :: Pitch -> Pitch -> Bool
Eq, Eq Pitch
Pitch -> Pitch -> Bool
Pitch -> Pitch -> Ordering
Pitch -> Pitch -> Pitch
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Pitch -> Pitch -> Pitch
$cmin :: Pitch -> Pitch -> Pitch
max :: Pitch -> Pitch -> Pitch
$cmax :: Pitch -> Pitch -> Pitch
>= :: Pitch -> Pitch -> Bool
$c>= :: Pitch -> Pitch -> Bool
> :: Pitch -> Pitch -> Bool
$c> :: Pitch -> Pitch -> Bool
<= :: Pitch -> Pitch -> Bool
$c<= :: Pitch -> Pitch -> Bool
< :: Pitch -> Pitch -> Bool
$c< :: Pitch -> Pitch -> Bool
compare :: Pitch -> Pitch -> Ordering
$ccompare :: Pitch -> Pitch -> Ordering
Ord, Int -> Pitch -> ShowS
[Pitch] -> ShowS
Pitch -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Pitch] -> ShowS
$cshowList :: [Pitch] -> ShowS
show :: Pitch -> [Char]
$cshow :: Pitch -> [Char]
showsPrec :: Int -> Pitch -> ShowS
$cshowsPrec :: Int -> Pitch -> ShowS
Show)

instance Pretty Pitch where
    pretty :: Pitch -> Text
pretty (Pitch Int
oct PitchClass
pc) = forall a. Show a => a -> Text
showt Int
oct forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
Util.showtLower PitchClass
pc

instance Enum Pitch where
    toEnum :: Int -> Pitch
toEnum Int
n = let (Int
oct, Int
pc) = Int
n forall a. Integral a => a -> a -> (a, a)
`divMod` Int
5 in Int -> PitchClass -> Pitch
Pitch Int
oct (forall a. Enum a => Int -> a
toEnum Int
pc)
    fromEnum :: Pitch -> Int
fromEnum (Pitch Int
oct PitchClass
pc) = Int
oct forall a. Num a => a -> a -> a
* Int
5 forall a. Num a => a -> a -> a
+ forall a. Enum a => a -> Int
fromEnum PitchClass
pc

data PitchClass = I | O | E | U | A
    deriving (PitchClass -> PitchClass -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PitchClass -> PitchClass -> Bool
$c/= :: PitchClass -> PitchClass -> Bool
== :: PitchClass -> PitchClass -> Bool
$c== :: PitchClass -> PitchClass -> Bool
Eq, Eq PitchClass
PitchClass -> PitchClass -> Bool
PitchClass -> PitchClass -> Ordering
PitchClass -> PitchClass -> PitchClass
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PitchClass -> PitchClass -> PitchClass
$cmin :: PitchClass -> PitchClass -> PitchClass
max :: PitchClass -> PitchClass -> PitchClass
$cmax :: PitchClass -> PitchClass -> PitchClass
>= :: PitchClass -> PitchClass -> Bool
$c>= :: PitchClass -> PitchClass -> Bool
> :: PitchClass -> PitchClass -> Bool
$c> :: PitchClass -> PitchClass -> Bool
<= :: PitchClass -> PitchClass -> Bool
$c<= :: PitchClass -> PitchClass -> Bool
< :: PitchClass -> PitchClass -> Bool
$c< :: PitchClass -> PitchClass -> Bool
compare :: PitchClass -> PitchClass -> Ordering
$ccompare :: PitchClass -> PitchClass -> Ordering
Ord, Int -> PitchClass -> ShowS
[PitchClass] -> ShowS
PitchClass -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [PitchClass] -> ShowS
$cshowList :: [PitchClass] -> ShowS
show :: PitchClass -> [Char]
$cshow :: PitchClass -> [Char]
showsPrec :: Int -> PitchClass -> ShowS
$cshowsPrec :: Int -> PitchClass -> ShowS
Show, Int -> PitchClass
PitchClass -> Int
PitchClass -> [PitchClass]
PitchClass -> PitchClass
PitchClass -> PitchClass -> [PitchClass]
PitchClass -> PitchClass -> PitchClass -> [PitchClass]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: PitchClass -> PitchClass -> PitchClass -> [PitchClass]
$cenumFromThenTo :: PitchClass -> PitchClass -> PitchClass -> [PitchClass]
enumFromTo :: PitchClass -> PitchClass -> [PitchClass]
$cenumFromTo :: PitchClass -> PitchClass -> [PitchClass]
enumFromThen :: PitchClass -> PitchClass -> [PitchClass]
$cenumFromThen :: PitchClass -> PitchClass -> [PitchClass]
enumFrom :: PitchClass -> [PitchClass]
$cenumFrom :: PitchClass -> [PitchClass]
fromEnum :: PitchClass -> Int
$cfromEnum :: PitchClass -> Int
toEnum :: Int -> PitchClass
$ctoEnum :: Int -> PitchClass
pred :: PitchClass -> PitchClass
$cpred :: PitchClass -> PitchClass
succ :: PitchClass -> PitchClass
$csucc :: PitchClass -> PitchClass
Enum, PitchClass
forall a. a -> a -> Bounded a
maxBound :: PitchClass
$cmaxBound :: PitchClass
minBound :: PitchClass
$cminBound :: PitchClass
Bounded, ReadPrec [PitchClass]
ReadPrec PitchClass
Int -> ReadS PitchClass
ReadS [PitchClass]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [PitchClass]
$creadListPrec :: ReadPrec [PitchClass]
readPrec :: ReadPrec PitchClass
$creadPrec :: ReadPrec PitchClass
readList :: ReadS [PitchClass]
$creadList :: ReadS [PitchClass]
readsPrec :: Int -> ReadS PitchClass
$creadsPrec :: Int -> ReadS PitchClass
Read)

parsePitch :: String -> Maybe Pitch
parsePitch :: [Char] -> Maybe Pitch
parsePitch [Char
oct, Char
pc] = Int -> PitchClass -> Pitch
Pitch forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> Maybe Int
Num.readDigit Char
oct
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Read a => [Char] -> Maybe a
Read.readMaybe (Char -> Char
Char.toUpper Char
pc forall a. a -> [a] -> [a]
: [Char]
"")
parsePitch [Char]
_ = forall a. Maybe a
Nothing