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
"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
"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
da -> 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