module HarmTrace.Base.Chord.Datatypes (
Note (..)
, Accidental (..)
, Root
, DiatonicNatural (..)
, ScaleDegree
, DiatonicDegree (..)
, Key (..)
, Mode (..)
, Chord (..)
, chordRoot
, chordShorthand
, chordAdditions
, chordBass
, Shorthand (..)
, Addition (..)
, IntNat (..)
, Interval
, ChordLabel
, ChordDegree
, ClassType (..)
, Triad (..)
, shortChord
, discardBass
, isNoneChord
, isAddition
, catchNoChord
) where
import Data.Maybe ( fromJust )
import Data.List ( elemIndex, intercalate )
import Data.Binary ( Binary )
import GHC.Generics ( Generic )
data Key = Key { keyRoot :: Root, keyMode :: Mode } deriving (Eq, Ord, Generic)
data Mode = MajMode | MinMode deriving (Eq, Ord, Generic)
type ChordLabel = Chord Root
type ChordDegree = Chord ScaleDegree
data Chord a = Chord a Shorthand [Addition] Interval
| NoChord
| UndefChord
deriving (Eq, Ord, Generic, Functor)
chordRoot :: Show a => Chord a -> a
chordRoot = catchNoChord "Chord.Datatypes.chordRoot" (\(Chord r _ _ _) -> r)
chordShorthand :: Show a => Chord a -> Shorthand
chordShorthand = catchNoChord "Chord.Datatypes.chordRoot" (\(Chord _ s _ _) ->s)
chordAdditions :: Show a => Chord a -> [Addition]
chordAdditions = catchNoChord "Chord.Datatypes.chordRoot" (\(Chord _ _ a _) ->a)
chordBass :: Show a => Chord a -> Interval
chordBass = catchNoChord "Chord.Datatypes.chordRoot" (\(Chord _ _ _ b) -> b)
data ClassType = MajClass | MinClass | DomClass | DimClass | NoClass
deriving (Eq, Enum, Ord, Bounded, Generic)
data Shorthand =
Maj | Min | Dim | Aug
| Maj7 | Min7 | Sev | Dim7 | HDim7 | MinMaj7 | Aug7
| Maj6 | Min6
| Nin | Maj9 | Min9
| Sus4 | Sus2 | SevSus4
| Five
| None
| Eleven | Thirteen | Min11 | Maj13 | Min13
deriving (Eq, Ord, Enum, Bounded, Generic)
type ScaleDegree = Note DiatonicDegree
data DiatonicDegree = I | II | III | IV | V | VI | VII
| Imp
deriving (Show, Eq, Enum, Ord, Bounded, Generic)
type Root = Note DiatonicNatural
data DiatonicNatural = C | D | E | F | G | A | B
deriving (Show, Eq, Enum, Ord, Bounded, Generic)
data Addition = Add Interval
| NoAdd Interval deriving (Eq, Ord, Generic)
data IntNat = I1 | I2 | I3 | I4 | I5 | I6 | I7 | I8 | I9 | I10
| I11 | I12 | I13
deriving (Eq, Enum, Ord, Bounded, Generic)
type Interval = Note IntNat
data Note a = Note Accidental a deriving (Eq, Ord, Generic)
data Accidental = Nat
| Sh
| Fl
| SS
| FF
deriving (Eq, Ord, Generic)
data Triad = MajTriad | MinTriad | AugTriad | DimTriad | NoTriad
deriving (Ord, Eq, Generic)
instance Show Key where
show (Key r m) = show r ++ show m
instance Show Mode where
show MajMode = ""
show MinMode = "m"
instance Show ChordLabel where
show NoChord = "N"
show UndefChord = "X"
show (Chord r None [] b) = show r ++ ":1" ++ showIv b
show (Chord r sh add b) = show r ++ ':' : show sh ++ showAdd add ++ showIv b
showIv :: Interval -> String
showIv (Note Nat I1) = ""
showIv i = '/' : show i
showAdd :: [Addition] -> String
showAdd [] = ""
showAdd x = '(' : intercalate "," (map show x) ++ ")"
instance Show Shorthand where
show Maj = "maj"
show Min = "min"
show Dim = "dim"
show Aug = "aug"
show Maj7 = "maj7"
show Min7 = "min7"
show Sev = "7"
show Dim7 = "dim7"
show HDim7 = "hdim7"
show MinMaj7 = "minmaj7"
show Aug7 = "aug7"
show Maj6 = "maj6"
show Min6 = "min6"
show Maj9 = "maj9"
show Min9 = "min9"
show Min11 = "min11"
show Min13 = "min13"
show Maj13 = "maj13"
show Sus4 = "sus4"
show Sus2 = "sus2"
show SevSus4 = "7sus4"
show Five = "5"
show Nin = "9"
show Eleven = "11"
show Thirteen = "13"
show None = ""
instance Show ClassType where
show MajClass = ""
show MinClass = "m"
show DomClass = "7"
show DimClass = "0"
show NoClass = "N"
instance Show (Note IntNat) where
show (Note m i) = show m ++ show i
instance Show (Note DiatonicNatural) where
show (Note m r) = show r ++ show m
instance Show (Note DiatonicDegree) where
show (Note m r) = show m ++ show r
instance Show IntNat where
show a = show . ((!!) ([1..13]::[Integer]))
. fromJust $ elemIndex a [minBound..]
instance Show Accidental where
show Nat = ""
show Sh = "#"
show Fl = "b"
show SS = "##"
show FF = "bb"
instance Show Addition where
show (Add n) = show n
show (NoAdd n) = '*' : show n
instance Show Triad where
show MajTriad = "maj"
show MinTriad = "min"
show AugTriad = "aug"
show DimTriad = "dim"
show NoTriad = "NoTriad"
shortChord :: Root -> Shorthand -> ChordLabel
shortChord r sh = Chord r sh [] (Note Nat I1)
isNoneChord :: ChordLabel -> Bool
isNoneChord NoChord = True
isNoneChord _ = False
isAddition :: Addition -> Bool
isAddition (Add _) = True
isAddition (NoAdd _) = False
discardBass :: Chord a -> Chord a
discardBass NoChord = NoChord
discardBass UndefChord = UndefChord
discardBass (Chord r sh a _b) = Chord r sh a (Note Nat I1)
catchNoChord :: Show a => String -> (Chord a -> b) -> Chord a -> b
catchNoChord s f c = case c of
NoChord -> error ("HarmTrace.Base."++s++" applied to a NoChord")
UndefChord -> error ("HarmTrace.Base."++s++" applied to a UndefChord")
_ -> f c
instance Binary Key
instance Binary Mode
instance Binary a => Binary (Chord a)
instance Binary ClassType
instance Binary Shorthand
instance Binary DiatonicDegree
instance Binary DiatonicNatural
instance Binary Addition
instance Binary IntNat
instance Binary a => Binary (Note a)
instance Binary Accidental
instance Binary Triad