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

-- * Chord definitions

-- ** Major chords

major :: (Num a) => [a]
major :: forall a. Num a => [a]
major = [a
0, a
4, a
7]

aug :: (Num a) => [a]
aug :: forall a. Num a => [a]
aug = [a
0, a
4, a
8]

six :: (Num a) => [a]
six :: forall a. Num a => [a]
six = [a
0, a
4, a
7, a
9]

sixNine :: (Num a) => [a]
sixNine :: forall a. Num a => [a]
sixNine = [a
0, a
4, a
7, a
9, a
14]

major7 :: (Num a) => [a]
major7 :: forall a. Num a => [a]
major7 = [a
0, a
4, a
7, a
11]

major9 :: (Num a) => [a]
major9 :: forall a. Num a => [a]
major9 = [a
0, a
4, a
7, a
11, a
14]

add9 :: (Num a) => [a]
add9 :: forall a. Num a => [a]
add9 = [a
0, a
4, a
7, a
14]

major11 :: (Num a) => [a]
major11 :: forall a. Num a => [a]
major11 = [a
0, a
4, a
7, a
11, a
14, a
17]

add11 :: (Num a) => [a]
add11 :: forall a. Num a => [a]
add11 = [a
0, a
4, a
7, a
17]

major13 :: (Num a) => [a]
major13 :: forall a. Num a => [a]
major13 = [a
0, a
4, a
7, a
11, a
14, a
21]

add13 :: (Num a) => [a]
add13 :: forall a. Num a => [a]
add13 = [a
0, a
4, a
7, a
21]

-- ** Dominant chords

dom7 :: (Num a) => [a]
dom7 :: forall a. Num a => [a]
dom7 = [a
0, a
4, a
7, a
10]

dom9 :: (Num a) => [a]
dom9 :: forall a. Num a => [a]
dom9 = [a
0, a
4, a
7, a
14]

dom11 :: (Num a) => [a]
dom11 :: forall a. Num a => [a]
dom11 = [a
0, a
4, a
7, a
17]

dom13 :: (Num a) => [a]
dom13 :: forall a. Num a => [a]
dom13 = [a
0, a
4, a
7, a
21]

sevenFlat5 :: (Num a) => [a]
sevenFlat5 :: forall a. Num a => [a]
sevenFlat5 = [a
0, a
4, a
6, a
10]

sevenSharp5 :: (Num a) => [a]
sevenSharp5 :: forall a. Num a => [a]
sevenSharp5 = [a
0, a
4, a
8, a
10]

sevenFlat9 :: (Num a) => [a]
sevenFlat9 :: forall a. Num a => [a]
sevenFlat9 = [a
0, a
4, a
7, a
10, a
13]

nine :: (Num a) => [a]
nine :: forall a. Num a => [a]
nine = [a
0, a
4, a
7, a
10, a
14]

eleven :: (Num a) => [a]
eleven :: forall a. Num a => [a]
eleven = [a
0, a
4, a
7, a
10, a
14, a
17]

thirteen :: (Num a) => [a]
thirteen :: forall a. Num a => [a]
thirteen = [a
0, a
4, a
7, a
10, a
14, a
17, a
21]

-- ** Minor chords

minor :: (Num a) => [a]
minor :: forall a. Num a => [a]
minor = [a
0, a
3, a
7]

diminished :: (Num a) => [a]
diminished :: forall a. Num a => [a]
diminished = [a
0, a
3, a
6]

minorSharp5 :: (Num a) => [a]
minorSharp5 :: forall a. Num a => [a]
minorSharp5 = [a
0, a
3, a
8]

minor6 :: (Num a) => [a]
minor6 :: forall a. Num a => [a]
minor6 = [a
0, a
3, a
7, a
9]

minorSixNine :: (Num a) => [a]
minorSixNine :: forall a. Num a => [a]
minorSixNine = [a
0, a
3, a
9, a
7, a
14]

minor7flat5 :: (Num a) => [a]
minor7flat5 :: forall a. Num a => [a]
minor7flat5 = [a
0, a
3, a
6, a
10]

minor7 :: (Num a) => [a]
minor7 :: forall a. Num a => [a]
minor7 = [a
0, a
3, a
7, a
10]

minor7sharp5 :: (Num a) => [a]
minor7sharp5 :: forall a. Num a => [a]
minor7sharp5 = [a
0, a
3, a
8, a
10]

minor7flat9 :: (Num a) => [a]
minor7flat9 :: forall a. Num a => [a]
minor7flat9 = [a
0, a
3, a
7, a
10, a
13]

minor7sharp9 :: (Num a) => [a]
minor7sharp9 :: forall a. Num a => [a]
minor7sharp9 = [a
0, a
3, a
7, a
10, a
15]

diminished7 :: (Num a) => [a]
diminished7 :: forall a. Num a => [a]
diminished7 = [a
0, a
3, a
6, a
9]

minor9 :: (Num a) => [a]
minor9 :: forall a. Num a => [a]
minor9 = [a
0, a
3, a
7, a
10, a
14]

minor11 :: (Num a) => [a]
minor11 :: forall a. Num a => [a]
minor11 = [a
0, a
3, a
7, a
10, a
14, a
17]

minor13 :: (Num a) => [a]
minor13 :: forall a. Num a => [a]
minor13 = [a
0, a
3, a
7, a
10, a
14, a
17, a
21]

minorMajor7 :: (Num a) => [a]
minorMajor7 :: forall a. Num a => [a]
minorMajor7 = [a
0, a
3, a
7, a
11]

-- ** Other chords

one :: (Num a) => [a]
one :: forall a. Num a => [a]
one = [a
0]

five :: (Num a) => [a]
five :: forall a. Num a => [a]
five = [a
0, a
7]

sus2 :: (Num a) => [a]
sus2 :: forall a. Num a => [a]
sus2 = [a
0, a
2, a
7]

sus4 :: (Num a) => [a]
sus4 :: forall a. Num a => [a]
sus4 = [a
0, a
5, a
7]

sevenSus2 :: (Num a) => [a]
sevenSus2 :: forall a. Num a => [a]
sevenSus2 = [a
0, a
2, a
7, a
10]

sevenSus4 :: (Num a) => [a]
sevenSus4 :: forall a. Num a => [a]
sevenSus4 = [a
0, a
5, a
7, a
10]

nineSus4 :: (Num a) => [a]
nineSus4 :: forall a. Num a => [a]
nineSus4 = [a
0, a
5, a
7, a
10, a
14]

-- ** Questionable chords

sevenFlat10 :: (Num a) => [a]
sevenFlat10 :: forall a. Num a => [a]
sevenFlat10 = [a
0, a
4, a
7, a
10, a
15]

nineSharp5 :: (Num a) => [a]
nineSharp5 :: forall a. Num a => [a]
nineSharp5 = [a
0, a
1, a
13]

minor9sharp5 :: (Num a) => [a]
minor9sharp5 :: forall a. Num a => [a]
minor9sharp5 = [a
0, a
1, a
14]

sevenSharp5flat9 :: (Num a) => [a]
sevenSharp5flat9 :: forall a. Num a => [a]
sevenSharp5flat9 = [a
0, a
4, a
8, a
10, a
13]

minor7sharp5flat9 :: (Num a) => [a]
minor7sharp5flat9 :: forall a. Num a => [a]
minor7sharp5flat9 = [a
0, a
3, a
8, a
10, a
13]

elevenSharp :: (Num a) => [a]
elevenSharp :: forall a. Num a => [a]
elevenSharp = [a
0, a
4, a
7, a
10, a
14, a
18]

minor11sharp :: (Num a) => [a]
minor11sharp :: forall a. Num a => [a]
minor11sharp = [a
0, a
3, a
7, a
10, a
14, a
18]

-- * Chord functions

-- | @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

-- |
--  The @chordTable@ function outputs a list of all available chords and their
--  corresponding notes. For example, its first entry is @("major",[0,4,7])@ which
--  means that a major triad is formed by the root (0), the major third (4 semitones
--  above the root), and the perfect fifth (7 semitones above the root).
--
--  As the list is big, you can use the function 'chordL'.
--
--  If you know the notes from a chord, but can’t find the name of it, you can use this Haskell code to do a reverse look up into the table:
--
--  > filter (\(_,x)->x==[0,4,7,10]) chordTable
--
--  This will output @[("dom7",[0,4,7,10])]@
--
--  (You’ll need to run @import Sound.Tidal.Chords@ before using this function.)
chordTable :: (Num a) => [(String, [a])]
chordTable :: forall a. Num a => [(String, [a])]
chordTable =
  [ (String
"major", [a]
forall a. Num a => [a]
major),
    (String
"maj", [a]
forall a. Num a => [a]
major),
    (String
"M", [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
"M7", [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
"M9", [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
"M11", [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
"M13", [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
"m", [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
"minor7f5", [a]
forall a. Num a => [a]
minor7flat5),
    (String
"min7flat5", [a]
forall a. Num a => [a]
minor7flat5),
    (String
"min7f5", [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
"minor7s5", [a]
forall a. Num a => [a]
minor7sharp5),
    (String
"min7sharp5", [a]
forall a. Num a => [a]
minor7sharp5),
    (String
"min7s5", [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
"minor7f9", [a]
forall a. Num a => [a]
minor7flat9),
    (String
"min7flat9", [a]
forall a. Num a => [a]
minor7flat9),
    (String
"min7f9", [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
"minor7s9", [a]
forall a. Num a => [a]
minor7sharp9),
    (String
"min7sharp9", [a]
forall a. Num a => [a]
minor7sharp9),
    (String
"min7s9", [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
"minorMajor7", [a]
forall a. Num a => [a]
minorMajor7),
    (String
"minMaj7", [a]
forall a. Num a => [a]
minorMajor7),
    (String
"mmaj7", [a]
forall a. Num a => [a]
minorMajor7),
    (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
"9sharp5", [a]
forall a. Num a => [a]
nineSharp5),
    (String
"9s5", [a]
forall a. Num a => [a]
nineSharp5),
    (String
"minor9sharp5", [a]
forall a. Num a => [a]
minor9sharp5),
    (String
"minor9s5", [a]
forall a. Num a => [a]
minor9sharp5),
    (String
"min9sharp5", [a]
forall a. Num a => [a]
minor9sharp5),
    (String
"min9s5", [a]
forall a. Num a => [a]
minor9sharp5),
    (String
"m9sharp5", [a]
forall a. Num a => [a]
minor9sharp5),
    (String
"m9s5", [a]
forall a. Num a => [a]
minor9sharp5),
    (String
"sevenSharp5flat9", [a]
forall a. Num a => [a]
sevenSharp5flat9),
    (String
"7s5f9", [a]
forall a. Num a => [a]
sevenSharp5flat9),
    (String
"minor7sharp5flat9", [a]
forall a. Num a => [a]
minor7sharp5flat9),
    (String
"m7sharp5flat9", [a]
forall a. Num a => [a]
minor7sharp5flat9),
    (String
"elevenSharp", [a]
forall a. Num a => [a]
elevenSharp),
    (String
"11s", [a]
forall a. Num a => [a]
elevenSharp),
    (String
"minor11sharp", [a]
forall a. Num a => [a]
minor11sharp),
    (String
"m11sharp", [a]
forall a. Num a => [a]
minor11sharp),
    (String
"m11s", [a]
forall a. Num a => [a]
minor11sharp)
  ]

-- | Look up a specific chord: @chordL "minor7"@ returns @(0>1)|[0,3,7,10]@.
chordL :: (Num a) => Pattern String -> Pattern [a]
chordL :: forall a. Num a => 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

-- |
-- Outputs all the available chords:
--
-- @
-- major maj M aug plus sharp5 six 6 sixNine six9 sixby9 6by9 major7 maj7
-- major9 maj9 add9 major11 maj11 add11 major13 maj13 add13 dom7 dom9 dom11
-- dom13 sevenFlat5 7f5 sevenSharp5 7s5 sevenFlat9 7f9 nine eleven 11 thirteen 13
-- minor min m diminished dim minorSharp5 msharp5 mS5 minor6 min6 m6 minorSixNine
-- minor69 min69 minSixNine m69 mSixNine m6by9 minor7flat5 minor7f5 min7flat5
-- min7f5 m7flat5 m7f5 minor7 min7 m7 minor7sharp5 minor7s5 min7sharp5 min7s5
-- m7sharp5 m7s5 minor7flat9 minor7f9 min7flat9 min7f9 m7flat9 m7f9 minor7sharp9
-- minor7s9 min7sharp9 min7s9 m7sharp9 m7s9 diminished7 dim7 minor9 min9 m9
-- minor11 min11 m11 minor13 min13 m13 minorMajor7 minMaj7 mmaj7 one 1 five 5
-- sus2 sus4 sevenSus2 7sus2 sevenSus4 7sus4 nineSus4 ninesus4 9sus4 sevenFlat10
-- 7f10 nineSharp5 9sharp5 9s5 minor9sharp5 minor9s5 min9sharp5 min9s5 m9sharp5
-- m9s5 sevenSharp5flat9 7s5f9 minor7sharp5flat9 m7sharp5flat9 elevenSharp 11s
-- minor11sharp m11sharp m11s
-- @
--
-- (You’ll need to run @import Sound.Tidal.Chords@ before using this function.)
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])])

data Modifier = Range Int | Drop Int | Invert | Open deriving (Modifier -> Modifier -> Bool
(Modifier -> Modifier -> Bool)
-> (Modifier -> Modifier -> Bool) -> Eq Modifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Modifier -> Modifier -> Bool
== :: Modifier -> Modifier -> Bool
$c/= :: Modifier -> Modifier -> Bool
/= :: Modifier -> Modifier -> Bool
Eq)

instance Show Modifier where
  show :: Modifier -> String
show (Range Int
i) = String
"Range " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
  show (Drop Int
i) = String
"Drop " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
  show Modifier
Invert = String
"Invert"
  show Modifier
Open = String
"Open"

applyModifier :: (Enum a, Num a) => Modifier -> [a] -> [a]
applyModifier :: forall a. (Enum a, Num a) => Modifier -> [a] -> [a]
applyModifier (Range Int
i) [a]
ds = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
i ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ (a -> [a]) -> [a] -> [a]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\a
x -> (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a
forall a. Num a => a -> a -> a
+ a
x) [a]
ds) [a
0, a
12 ..]
applyModifier Modifier
Invert [] = []
applyModifier Modifier
Invert (a
d : [a]
ds) = [a]
ds [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a
d a -> a -> a
forall a. Num a => a -> a -> a
+ a
12]
applyModifier Modifier
Open [a]
ds = case [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ds Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2 of
  Bool
True -> [([a]
ds [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
0 a -> a -> a
forall a. Num a => a -> a -> a
- a
12), ([a]
ds [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
2 a -> a -> a
forall a. Num a => a -> a -> a
- a
12), ([a]
ds [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
1)] [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a] -> [a]
forall a. [a] -> [a]
reverse (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ds Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
ds))
  Bool
False -> [a]
ds
applyModifier (Drop Int
i) [a]
ds = case [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ds Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
i of
  Bool
True -> [a]
ds
  Bool
False -> ([a]
ds [a] -> Int -> a
forall a. HasCallStack => [a] -> Int -> a
!! Int
s a -> a -> a
forall a. Num a => a -> a -> a
- a
12) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: ([a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
1 [a]
ys)
  where
    ([a]
xs, [a]
ys) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
s [a]
ds
    s :: Int
s = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ds Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i

applyModifierPat :: (Num a, Enum a) => Pattern [a] -> Pattern [Modifier] -> Pattern [a]
applyModifierPat :: forall a.
(Num a, Enum a) =>
Pattern [a] -> Pattern [Modifier] -> Pattern [a]
applyModifierPat Pattern [a]
pat Pattern [Modifier]
modsP = do
  [a]
ch <- Pattern [a]
pat
  [Modifier]
ms <- Pattern [Modifier]
modsP
  [a] -> Pattern [a]
forall a. a -> Pattern a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> Pattern [a]) -> [a] -> Pattern [a]
forall a b. (a -> b) -> a -> b
$ ([a] -> Modifier -> [a]) -> [a] -> [Modifier] -> [a]
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl ((Modifier -> [a] -> [a]) -> [a] -> Modifier -> [a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip Modifier -> [a] -> [a]
forall a. (Enum a, Num a) => Modifier -> [a] -> [a]
applyModifier) [a]
ch [Modifier]
ms

applyModifierPatSeq :: (Num a, Enum a) => (a -> b) -> Pattern [a] -> [Pattern [Modifier]] -> Pattern [b]
applyModifierPatSeq :: forall a b.
(Num a, Enum a) =>
(a -> b) -> Pattern [a] -> [Pattern [Modifier]] -> Pattern [b]
applyModifierPatSeq a -> b
f Pattern [a]
pat [] = ([a] -> [b]) -> Pattern [a] -> Pattern [b]
forall a b. (a -> b) -> Pattern a -> Pattern b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> [a] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map a -> b
f) Pattern [a]
pat
applyModifierPatSeq a -> b
f Pattern [a]
pat (Pattern [Modifier]
mP : [Pattern [Modifier]]
msP) = (a -> b) -> Pattern [a] -> [Pattern [Modifier]] -> Pattern [b]
forall a b.
(Num a, Enum a) =>
(a -> b) -> Pattern [a] -> [Pattern [Modifier]] -> Pattern [b]
applyModifierPatSeq a -> b
f (Pattern [a] -> Pattern [Modifier] -> Pattern [a]
forall a.
(Num a, Enum a) =>
Pattern [a] -> Pattern [Modifier] -> Pattern [a]
applyModifierPat Pattern [a]
pat Pattern [Modifier]
mP) [Pattern [Modifier]]
msP

chordToPatSeq :: (Num a, Enum a) => (a -> b) -> Pattern a -> Pattern String -> [Pattern [Modifier]] -> Pattern b
chordToPatSeq :: forall a b.
(Num a, Enum a) =>
(a -> b)
-> Pattern a -> Pattern String -> [Pattern [Modifier]] -> Pattern b
chordToPatSeq a -> b
f Pattern a
noteP Pattern String
nameP [Pattern [Modifier]]
modsP = Pattern [b] -> Pattern b
forall a. Pattern [a] -> Pattern a
uncollect (Pattern [b] -> Pattern b) -> Pattern [b] -> Pattern b
forall a b. (a -> b) -> a -> b
$ do
  a
n <- Pattern a
noteP
  String
name <- Pattern String
nameP
  let ch :: [a]
ch = (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a
forall a. Num a => a -> a -> a
+ a
n) ([a] -> Maybe [a] -> [a]
forall a. a -> Maybe a -> a
fromMaybe [a
0] (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)
  (a -> b) -> Pattern [a] -> [Pattern [Modifier]] -> Pattern [b]
forall a b.
(Num a, Enum a) =>
(a -> b) -> Pattern [a] -> [Pattern [Modifier]] -> Pattern [b]
applyModifierPatSeq a -> b
f ([a] -> Pattern [a]
forall a. a -> Pattern a
forall (m :: * -> *) a. Monad m => a -> m a
return [a]
ch) [Pattern [Modifier]]
modsP

-- | Turns a given pattern of some 'Num' type, a pattern of chord names, and a
-- list of patterns of modifiers into a chord pattern
chord :: (Num a, Enum a) => Pattern a -> Pattern String -> [Pattern [Modifier]] -> Pattern a
chord :: forall a.
(Num a, Enum a) =>
Pattern a -> Pattern String -> [Pattern [Modifier]] -> Pattern a
chord = (a -> a)
-> Pattern a -> Pattern String -> [Pattern [Modifier]] -> Pattern a
forall a b.
(Num a, Enum a) =>
(a -> b)
-> Pattern a -> Pattern String -> [Pattern [Modifier]] -> Pattern b
chordToPatSeq a -> a
forall a. a -> a
id