module Sound.Tidal.Chords where

{-
    Chords.hs - For .. chords
    Copyright (C) 2020, Alex McLean and contributors

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

import Data.Maybe

import Sound.Tidal.Pattern

-- major chords
major :: Num a => [a]
major :: [a]
major = [a
0,a
4,a
7]
aug :: Num a => [a]
aug :: [a]
aug = [a
0,a
4,a
8]
six :: Num a => [a]
six :: [a]
six = [a
0,a
4,a
7,a
9]
sixNine :: Num a => [a]
sixNine :: [a]
sixNine = [a
0,a
4,a
7,a
9,a
14]
major7 :: Num a => [a]
major7 :: [a]
major7 = [a
0,a
4,a
7,a
11]
major9 :: Num a => [a]
major9 :: [a]
major9 = [a
0,a
4,a
7,a
11,a
14]
add9 :: Num a => [a]
add9 :: [a]
add9 = [a
0,a
4,a
7,a
14]
major11 :: Num a => [a]
major11 :: [a]
major11 = [a
0,a
4,a
7,a
11,a
14,a
17]
add11 :: Num a => [a]
add11 :: [a]
add11 = [a
0,a
4,a
7,a
17]
major13 :: Num a => [a]
major13 :: [a]
major13 = [a
0,a
4,a
7,a
11,a
14,a
21]
add13 :: Num a => [a]
add13 :: [a]
add13 = [a
0,a
4,a
7,a
21]
-- dominant chords
dom7 :: Num a => [a]
dom7 :: [a]
dom7 = [a
0,a
4,a
7,a
10]
dom9 :: Num a => [a]
dom9 :: [a]
dom9 = [a
0,a
4,a
7,a
14]
dom11 :: Num a => [a]
dom11 :: [a]
dom11 = [a
0,a
4,a
7,a
17]
dom13 :: Num a => [a]
dom13 :: [a]
dom13 = [a
0,a
4,a
7,a
21]
sevenFlat5 :: Num a => [a]
sevenFlat5 :: [a]
sevenFlat5 = [a
0,a
4,a
6,a
10]
sevenSharp5 :: Num a => [a]
sevenSharp5 :: [a]
sevenSharp5 = [a
0,a
4,a
8,a
10]
sevenFlat9 :: Num a => [a]
sevenFlat9 :: [a]
sevenFlat9 = [a
0,a
4,a
7,a
10,a
13]
nine :: Num a => [a]
nine :: [a]
nine = [a
0,a
4,a
7,a
10,a
14]
eleven :: Num a => [a]
eleven :: [a]
eleven = [a
0,a
4,a
7,a
10,a
14,a
17]
thirteen :: Num a => [a]
thirteen :: [a]
thirteen = [a
0,a
4,a
7,a
10,a
14,a
17,a
21]
-- minor chords
minor :: Num a => [a]
minor :: [a]
minor = [a
0,a
3,a
7]
diminished :: Num a => [a]
diminished :: [a]
diminished = [a
0,a
3,a
6]
minorSharp5 :: Num a => [a]
minorSharp5 :: [a]
minorSharp5 = [a
0,a
3,a
8]
minor6 :: Num a => [a]
minor6 :: [a]
minor6 = [a
0,a
3,a
7,a
9]
minorSixNine :: Num a => [a]
minorSixNine :: [a]
minorSixNine = [a
0,a
3,a
9,a
7,a
14]
minor7flat5 :: Num a => [a]
minor7flat5 :: [a]
minor7flat5 = [a
0,a
3,a
6,a
10]
minor7 :: Num a => [a]
minor7 :: [a]
minor7 = [a
0,a
3,a
7,a
10]
minor7sharp5 :: Num a => [a]
minor7sharp5 :: [a]
minor7sharp5 = [a
0,a
3,a
8,a
10]
minor7flat9 :: Num a => [a]
minor7flat9 :: [a]
minor7flat9 = [a
0,a
3,a
7,a
10,a
13]
minor7sharp9 :: Num a => [a]
minor7sharp9 :: [a]
minor7sharp9 = [a
0,a
3,a
7,a
10,a
14]
diminished7 :: Num a => [a]
diminished7 :: [a]
diminished7 = [a
0,a
3,a
6,a
9]
minor9 :: Num a => [a]
minor9 :: [a]
minor9 = [a
0,a
3,a
7,a
10,a
14]
minor11 :: Num a => [a]
minor11 :: [a]
minor11 = [a
0,a
3,a
7,a
10,a
14,a
17]
minor13 :: Num a => [a]
minor13 :: [a]
minor13 = [a
0,a
3,a
7,a
10,a
14,a
17,a
21]
-- other chords
one :: Num a => [a]
one :: [a]
one = [a
0]
five :: Num a => [a]
five :: [a]
five = [a
0,a
7]
sus2 :: Num a => [a]
sus2 :: [a]
sus2 = [a
0,a
2,a
7]
sus4 :: Num a => [a]
sus4 :: [a]
sus4 = [a
0,a
5,a
7]
sevenSus2 :: Num a => [a]
sevenSus2 :: [a]
sevenSus2 = [a
0,a
2,a
7,a
10]
sevenSus4 :: Num a => [a]
sevenSus4 :: [a]
sevenSus4 = [a
0,a
5,a
7,a
10]
nineSus4 :: Num a => [a]
nineSus4 :: [a]
nineSus4 = [a
0,a
5,a
7,a
10,a
14]
-- questionable chords
sevenFlat10 :: Num a => [a]
sevenFlat10 :: [a]
sevenFlat10 = [a
0,a
4,a
7,a
10,a
15]
nineSharp5 :: Num a => [a]
nineSharp5 :: [a]
nineSharp5 = [a
0,a
1,a
13]
m9sharp5 :: Num a => [a]
m9sharp5 :: [a]
m9sharp5 = [a
0,a
1,a
14]
sevenSharp5flat9 :: Num a => [a]
sevenSharp5flat9 :: [a]
sevenSharp5flat9 = [a
0,a
4,a
8,a
10,a
13]
m7sharp5flat9 :: Num a => [a]
m7sharp5flat9 :: [a]
m7sharp5flat9 = [a
0,a
3,a
8,a
10,a
13]
elevenSharp :: Num a => [a]
elevenSharp :: [a]
elevenSharp = [a
0,a
4,a
7,a
10,a
14,a
18]
m11sharp :: Num a => [a]
m11sharp :: [a]
m11sharp = [a
0,a
3,a
7,a
10,a
14,a
18]

-- | @chordate cs m n@ selects the @n@th "chord" (a chord is a list of Ints)
-- from a list of chords @cs@ and transposes it by @m@
-- chordate :: Num b => [[b]] -> b -> Int -> [b]
-- chordate cs m n = map (+m) $ cs!!n

-- | @enchord chords pn pc@ turns every note in the note pattern @pn@ into
-- a chord, selecting from the chord lists @chords@ using the index pattern
-- @pc@.  For example, @Chords.enchord [Chords.major Chords.minor] "c g" "0 1"@
-- will create a pattern of a C-major chord followed by a G-minor chord.
-- enchord :: Num a => [[a]] -> Pattern a -> Pattern Int -> Pattern a
-- enchord chords pn pc = flatpat $ (chordate chords) <$> pn <*> pc

chordTable :: Num a => [(String, [a])]
chordTable :: [(String, [a])]
chordTable = [(String
"major", [a]
forall a. Num a => [a]
major),
              (String
"maj", [a]
forall a. Num a => [a]
major),
              (String
"aug", [a]
forall a. Num a => [a]
aug),
              (String
"plus", [a]
forall a. Num a => [a]
aug),
              (String
"sharp5", [a]
forall a. Num a => [a]
aug),
              (String
"six", [a]
forall a. Num a => [a]
six),
              (String
"6", [a]
forall a. Num a => [a]
six),
              (String
"sixNine", [a]
forall a. Num a => [a]
sixNine),
              (String
"six9", [a]
forall a. Num a => [a]
sixNine),
              (String
"sixby9", [a]
forall a. Num a => [a]
sixNine),
              (String
"6by9", [a]
forall a. Num a => [a]
sixNine),
              (String
"major7", [a]
forall a. Num a => [a]
major7),
              (String
"maj7", [a]
forall a. Num a => [a]
major7),
              (String
"major9", [a]
forall a. Num a => [a]
major9),
              (String
"maj9", [a]
forall a. Num a => [a]
major9),
              (String
"add9", [a]
forall a. Num a => [a]
add9),
              (String
"major11", [a]
forall a. Num a => [a]
major11),
              (String
"maj11", [a]
forall a. Num a => [a]
major11),
              (String
"add11", [a]
forall a. Num a => [a]
add11),
              (String
"major13", [a]
forall a. Num a => [a]
major13),
              (String
"maj13", [a]
forall a. Num a => [a]
major13),
              (String
"add13", [a]
forall a. Num a => [a]
add13),
              (String
"dom7", [a]
forall a. Num a => [a]
dom7),
              (String
"dom9", [a]
forall a. Num a => [a]
dom9),
              (String
"dom11", [a]
forall a. Num a => [a]
dom11),
              (String
"dom13", [a]
forall a. Num a => [a]
dom13),
              (String
"sevenFlat5", [a]
forall a. Num a => [a]
sevenFlat5),
              (String
"7f5", [a]
forall a. Num a => [a]
sevenFlat5),
              (String
"sevenSharp5", [a]
forall a. Num a => [a]
sevenSharp5),
              (String
"7s5", [a]
forall a. Num a => [a]
sevenSharp5),
              (String
"sevenFlat9", [a]
forall a. Num a => [a]
sevenFlat9),
              (String
"7f9", [a]
forall a. Num a => [a]
sevenFlat9),
              (String
"nine", [a]
forall a. Num a => [a]
nine),
              (String
"eleven", [a]
forall a. Num a => [a]
eleven),
              (String
"11", [a]
forall a. Num a => [a]
eleven),
              (String
"thirteen", [a]
forall a. Num a => [a]
thirteen),
              (String
"13", [a]
forall a. Num a => [a]
thirteen),
              (String
"minor", [a]
forall a. Num a => [a]
minor),
              (String
"min", [a]
forall a. Num a => [a]
minor),
              (String
"diminished", [a]
forall a. Num a => [a]
diminished),
              (String
"dim", [a]
forall a. Num a => [a]
diminished),
              (String
"minorSharp5", [a]
forall a. Num a => [a]
minorSharp5),
              (String
"msharp5", [a]
forall a. Num a => [a]
minorSharp5),
              (String
"mS5", [a]
forall a. Num a => [a]
minorSharp5),
              (String
"minor6", [a]
forall a. Num a => [a]
minor6),
              (String
"min6", [a]
forall a. Num a => [a]
minor6),
              (String
"m6", [a]
forall a. Num a => [a]
minor6),
              (String
"minorSixNine", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"minor69", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"min69", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"minSixNine", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"m69", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"mSixNine", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"m6by9", [a]
forall a. Num a => [a]
minorSixNine),
              (String
"minor7flat5", [a]
forall a. Num a => [a]
minor7flat5),
              (String
"min7flat5", [a]
forall a. Num a => [a]
minor7flat5),
              (String
"m7flat5", [a]
forall a. Num a => [a]
minor7flat5),
              (String
"m7f5", [a]
forall a. Num a => [a]
minor7flat5),
              (String
"minor7", [a]
forall a. Num a => [a]
minor7),
              (String
"min7", [a]
forall a. Num a => [a]
minor7),
              (String
"m7", [a]
forall a. Num a => [a]
minor7),
              (String
"minor7sharp5", [a]
forall a. Num a => [a]
minor7sharp5),
              (String
"min7sharp5", [a]
forall a. Num a => [a]
minor7sharp5),
              (String
"m7sharp5", [a]
forall a. Num a => [a]
minor7sharp5),
              (String
"m7s5", [a]
forall a. Num a => [a]
minor7sharp5),
              (String
"minor7flat9", [a]
forall a. Num a => [a]
minor7flat9),
              (String
"min7flat9", [a]
forall a. Num a => [a]
minor7flat9),
              (String
"m7flat9", [a]
forall a. Num a => [a]
minor7flat9),
              (String
"m7f9", [a]
forall a. Num a => [a]
minor7flat9),
              (String
"minor7sharp9", [a]
forall a. Num a => [a]
minor7sharp9),
              (String
"min7sharp9", [a]
forall a. Num a => [a]
minor7sharp9),
              (String
"m7sharp9", [a]
forall a. Num a => [a]
minor7sharp9),
              (String
"m7s9", [a]
forall a. Num a => [a]
minor7sharp9),
              (String
"diminished7", [a]
forall a. Num a => [a]
diminished7),
              (String
"dim7", [a]
forall a. Num a => [a]
diminished7),
              (String
"minor9", [a]
forall a. Num a => [a]
minor9),
              (String
"min9", [a]
forall a. Num a => [a]
minor9),
              (String
"m9", [a]
forall a. Num a => [a]
minor9),
              (String
"minor11", [a]
forall a. Num a => [a]
minor11),
              (String
"min11", [a]
forall a. Num a => [a]
minor11),
              (String
"m11", [a]
forall a. Num a => [a]
minor11),
              (String
"minor13", [a]
forall a. Num a => [a]
minor13),
              (String
"min13", [a]
forall a. Num a => [a]
minor13),
              (String
"m13", [a]
forall a. Num a => [a]
minor13),
              (String
"one", [a]
forall a. Num a => [a]
one),
              (String
"1", [a]
forall a. Num a => [a]
one),
              (String
"five", [a]
forall a. Num a => [a]
five),
              (String
"5", [a]
forall a. Num a => [a]
five),
              (String
"sus2", [a]
forall a. Num a => [a]
sus2),
              (String
"sus4", [a]
forall a. Num a => [a]
sus4),
              (String
"sevenSus2", [a]
forall a. Num a => [a]
sevenSus2),
              (String
"7sus2", [a]
forall a. Num a => [a]
sevenSus2),
              (String
"sevenSus4", [a]
forall a. Num a => [a]
sevenSus4),
              (String
"7sus4", [a]
forall a. Num a => [a]
sevenSus4),
              (String
"nineSus4", [a]
forall a. Num a => [a]
nineSus4),
              (String
"ninesus4", [a]
forall a. Num a => [a]
nineSus4),
              (String
"9sus4", [a]
forall a. Num a => [a]
nineSus4),
              (String
"sevenFlat10", [a]
forall a. Num a => [a]
sevenFlat10),
              (String
"7f10", [a]
forall a. Num a => [a]
sevenFlat10),
              (String
"nineSharp5", [a]
forall a. Num a => [a]
nineSharp5),
              (String
"9s5", [a]
forall a. Num a => [a]
nineSharp5),
              (String
"m9sharp5", [a]
forall a. Num a => [a]
m9sharp5),
              (String
"m9s5", [a]
forall a. Num a => [a]
m9sharp5),
              (String
"sevenSharp5flat9", [a]
forall a. Num a => [a]
sevenSharp5flat9),
              (String
"7s5f9", [a]
forall a. Num a => [a]
sevenSharp5flat9),
              (String
"m7sharp5flat9", [a]
forall a. Num a => [a]
m7sharp5flat9),
              (String
"elevenSharp", [a]
forall a. Num a => [a]
elevenSharp),
              (String
"11s", [a]
forall a. Num a => [a]
elevenSharp),
              (String
"m11sharp", [a]
forall a. Num a => [a]
m11sharp),
              (String
"m11s", [a]
forall a. Num a => [a]
m11sharp)
             ]

chordL :: Num a => Pattern String -> Pattern [a]
chordL :: Pattern String -> Pattern [a]
chordL Pattern String
p = (\String
name -> [a] -> Maybe [a] -> [a]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [a] -> [a]) -> Maybe [a] -> [a]
forall a b. (a -> b) -> a -> b
$ String -> [(String, [a])] -> Maybe [a]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
name [(String, [a])]
forall a. Num a => [(String, [a])]
chordTable) (String -> [a]) -> Pattern String -> Pattern [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pattern String
p

chordList :: String
chordList :: String
chordList = [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ ((String, [Int]) -> String) -> [(String, [Int])] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, [Int]) -> String
forall a b. (a, b) -> a
fst ([(String, [Int])]
forall a. Num a => [(String, [a])]
chordTable :: [(String, [Int])])