module Harmonic.Rules.Types.Progression
(
Progression(..)
, singleton
, fromCadenceStates
, fromChordStates
, progLength
, progChords
, progCadences
, getCadenceState
, getChordState
, rotateProgression
, rotateSeq
, excerptProgression
, excerptSeq
, insertProgression
, fuseProgression
, interleaveSeq
, transposeProgression
, overlapProgression
, expandProgression
, spliceProgression
, fixMovementAt
, literalVoicing
, harmonyVoicing
, closeVoicing
, wideVoicing
, showTriad
, showHarmony
) where
import GHC.Generics (Generic)
import Data.List (sort)
import Data.Sequence (Seq, (><))
import qualified Data.Sequence as Seq
import Data.Foldable (toList)
import Data.List.Split (chunksOf)
import qualified Data.List as List
import qualified Data.Char as Char
import Harmonic.Rules.Types.Pitch (PitchClass(..), mkPitchClass, unPitchClass, NoteName(..), pitchClass)
import Harmonic.Rules.Types.Harmony (Chord(..), Cadence(..), ChordState(..), CadenceState(..), fromCadenceState, Movement(..), toMovement, zeroFormPC, enharmonicFunc, inferSpelling, toFunctionalityChord)
import qualified Harmonic.Rules.Import.Jazz as J
import qualified Data.Text as T
import qualified Harmonic.Rules.Types.Scale as Sc
newtype Progression = Progression { Progression -> Seq CadenceState
unProgression :: Seq CadenceState }
deriving (Progression -> Progression -> Bool
(Progression -> Progression -> Bool)
-> (Progression -> Progression -> Bool) -> Eq Progression
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Progression -> Progression -> Bool
== :: Progression -> Progression -> Bool
$c/= :: Progression -> Progression -> Bool
/= :: Progression -> Progression -> Bool
Eq, (forall x. Progression -> Rep Progression x)
-> (forall x. Rep Progression x -> Progression)
-> Generic Progression
forall x. Rep Progression x -> Progression
forall x. Progression -> Rep Progression x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Progression -> Rep Progression x
from :: forall x. Progression -> Rep Progression x
$cto :: forall x. Rep Progression x -> Progression
to :: forall x. Rep Progression x -> Progression
Generic)
instance Show Progression where
show :: Progression -> [Char]
show (Progression Seq CadenceState
sq)
| Seq CadenceState -> Bool
forall a. Seq a -> Bool
Seq.null Seq CadenceState
sq = [Char]
"[empty progression]"
| Bool
otherwise =
let cadenceStates :: [CadenceState]
cadenceStates = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq CadenceState
sq
enharms :: [PitchClass -> NoteName]
enharms = (CadenceState -> PitchClass -> NoteName)
-> [CadenceState] -> [PitchClass -> NoteName]
forall a b. (a -> b) -> [a] -> [b]
map (EnharmonicSpelling -> PitchClass -> NoteName
enharmonicFunc (EnharmonicSpelling -> PitchClass -> NoteName)
-> (CadenceState -> EnharmonicSpelling)
-> CadenceState
-> PitchClass
-> NoteName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CadenceState -> EnharmonicSpelling
stateSpelling) [CadenceState]
cadenceStates
showChords :: [[Char]]
showChords = ((PitchClass -> NoteName) -> CadenceState -> [Char])
-> [PitchClass -> NoteName] -> [CadenceState] -> [[Char]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (PitchClass -> NoteName) -> CadenceState -> [Char]
showHarmony [PitchClass -> NoteName]
enharms [CadenceState]
cadenceStates
paddedChords :: [[Char]]
paddedChords = ShowS -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (([Char] -> ShowS
forall a. [a] -> [a] -> [a]
++[Char]
"| ") ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
padTo Int
14) [[Char]]
showChords
barLabels :: [[Char]]
barLabels = [[Char]
"\n 1 || ", [Char]
"\n 5 | ", [Char]
"\n 9 | ", [Char]
"\n 13 | ",
[Char]
"\n 17 | ", [Char]
"\n 21 | ", [Char]
"\n 25 | ", [Char]
"\n 29 | ",
[Char]
"\n 33 | ", [Char]
"\n 37 | ", [Char]
"\n 41 | ", [Char]
"\n 45 | ",
[Char]
"\n 49 | ", [Char]
"\n 53 | ", [Char]
"\n 57 | ", [Char]
"\n 61 | "]
groupedChords :: [[[Char]]]
groupedChords = Int -> [[Char]] -> [[[Char]]]
forall e. Int -> [e] -> [[e]]
chunksOf Int
4 [[Char]]
paddedChords
formattedGroups :: [[Char]]
formattedGroups = ([[Char]] -> [Char]) -> [[[Char]]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (ShowS
forall a. HasCallStack => [a] -> [a]
init ShowS -> ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. HasCallStack => [a] -> [a]
init ShowS -> ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
forall a. HasCallStack => [a] -> [a]
init ShowS -> ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat) [[[Char]]]
groupedChords
result :: [Char]
result = [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ ([Char] -> ShowS) -> [[Char]] -> [[Char]] -> [[Char]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith [Char] -> ShowS
forall a. [a] -> [a] -> [a]
(++) [[Char]]
barLabels [[Char]]
formattedGroups
in [Char]
result [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"|\n"
where
padTo :: Int -> ShowS
padTo Int
n [Char]
s = [Char]
s [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- [Char] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
s) Char
' '
instance Semigroup Progression where
(<>) :: Progression -> Progression -> Progression
(Progression Seq CadenceState
a) <> :: Progression -> Progression -> Progression
<> (Progression Seq CadenceState
b) = Seq CadenceState -> Progression
Progression (Seq CadenceState
a Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
b)
instance Monoid Progression where
mempty :: Progression
mempty :: Progression
mempty = Seq CadenceState -> Progression
Progression Seq CadenceState
forall a. Seq a
Seq.empty
singleton :: CadenceState -> Progression
singleton :: CadenceState -> Progression
singleton CadenceState
cs = Seq CadenceState -> Progression
Progression (CadenceState -> Seq CadenceState
forall a. a -> Seq a
Seq.singleton CadenceState
cs)
fromCadenceStates :: [CadenceState] -> Progression
fromCadenceStates :: [CadenceState] -> Progression
fromCadenceStates = Seq CadenceState -> Progression
Progression (Seq CadenceState -> Progression)
-> ([CadenceState] -> Seq CadenceState)
-> [CadenceState]
-> Progression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CadenceState] -> Seq CadenceState
forall a. [a] -> Seq a
Seq.fromList
fromChordStates :: [ChordState] -> Progression
fromChordStates :: [ChordState] -> Progression
fromChordStates [] = Progression
forall a. Monoid a => a
mempty
fromChordStates [ChordState
_] = Progression
forall a. Monoid a => a
mempty
fromChordStates [ChordState]
states =
let pairs :: [(ChordState, ChordState)]
pairs = [ChordState] -> [ChordState] -> [(ChordState, ChordState)]
forall a b. [a] -> [b] -> [(a, b)]
zip [ChordState]
states (Int -> [ChordState] -> [ChordState]
forall a. Int -> [a] -> [a]
drop Int
1 [ChordState]
states)
cadenceStates :: [CadenceState]
cadenceStates = ((ChordState, ChordState) -> CadenceState)
-> [(ChordState, ChordState)] -> [CadenceState]
forall a b. (a -> b) -> [a] -> [b]
map (ChordState, ChordState) -> CadenceState
toCadenceStateFromPair [(ChordState, ChordState)]
pairs
in [CadenceState] -> Progression
fromCadenceStates [CadenceState]
cadenceStates
toCadenceStateFromPair :: (ChordState, ChordState) -> CadenceState
toCadenceStateFromPair :: (ChordState, ChordState) -> CadenceState
toCadenceStateFromPair (ChordState
from, ChordState
to) =
let toChord :: Chord
toChord = ChordState -> Chord
stateChord ChordState
to
fromRoot :: PitchClass
fromRoot = NoteName -> PitchClass
pitchClass (ChordState -> NoteName
stateRoot ChordState
from)
toRoot :: PitchClass
toRoot = NoteName -> PitchClass
pitchClass (ChordState -> NoteName
stateRoot ChordState
to)
mvmt :: Movement
mvmt = PitchClass -> PitchClass -> Movement
calculateMovement PitchClass
fromRoot PitchClass
toRoot
cad :: Cadence
cad = [Char] -> Movement -> [PitchClass] -> Cadence
Cadence (Chord -> [Char]
chordFunctionality Chord
toChord) Movement
mvmt ([PitchClass] -> [PitchClass]
zeroFormPC ([PitchClass] -> [PitchClass]) -> [PitchClass] -> [PitchClass]
forall a b. (a -> b) -> a -> b
$ (Int -> PitchClass) -> [Int] -> [PitchClass]
forall a b. (a -> b) -> [a] -> [b]
map Int -> PitchClass
mkPitchClass ([Int] -> [PitchClass]) -> [Int] -> [PitchClass]
forall a b. (a -> b) -> a -> b
$ Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take Int
3 ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Integer -> Int) -> [Integer] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Chord -> [Integer]
chordIntervals Chord
toChord))
tones :: [Int]
tones = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
unPitchClass ([PitchClass] -> [Int]) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> a -> b
$ Cadence -> [PitchClass]
cadenceIntervals Cadence
cad
absolutePitches :: [Int]
absolutePitches = (Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
t -> (Int
t Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PitchClass -> Int
unPitchClass PitchClass
toRoot) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
tones
spelling :: EnharmonicSpelling
spelling = [Int] -> EnharmonicSpelling
inferSpelling [Int]
absolutePitches
in Cadence -> NoteName -> EnharmonicSpelling -> CadenceState
CadenceState Cadence
cad (ChordState -> NoteName
stateRoot ChordState
to) EnharmonicSpelling
spelling
where
calculateMovement :: PitchClass -> PitchClass -> Movement
calculateMovement :: PitchClass -> PitchClass -> Movement
calculateMovement (P Int
pcF) (P Int
pcT) =
let diff :: Int
diff = (Int
pcT Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
pcF) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12
in if Int
diff Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
6
then if Int
diff Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Movement
Unison
else if Int
diff Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
6 then Movement
Tritone
else PitchClass -> Movement
Asc (Int -> PitchClass
P Int
diff)
else PitchClass -> Movement
Desc (Int -> PitchClass
P (Int
12 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
diff))
progLength :: Progression -> Int
progLength :: Progression -> Int
progLength = Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length (Seq CadenceState -> Int)
-> (Progression -> Seq CadenceState) -> Progression -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Progression -> Seq CadenceState
unProgression
progChords :: Progression -> [Chord]
progChords :: Progression -> [Chord]
progChords (Progression Seq CadenceState
sq) = (CadenceState -> Chord) -> [CadenceState] -> [Chord]
forall a b. (a -> b) -> [a] -> [b]
map CadenceState -> Chord
fromCadenceState (Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq CadenceState
sq)
progCadences :: Progression -> [Cadence]
progCadences :: Progression -> [Cadence]
progCadences (Progression Seq CadenceState
sq) = (CadenceState -> Cadence) -> [CadenceState] -> [Cadence]
forall a b. (a -> b) -> [a] -> [b]
map CadenceState -> Cadence
stateCadence (Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq CadenceState
sq)
getCadenceState :: Progression -> Int -> Maybe CadenceState
getCadenceState :: Progression -> Int -> Maybe CadenceState
getCadenceState (Progression Seq CadenceState
sq) Int
idx = Int -> Seq CadenceState -> Maybe CadenceState
forall a. Int -> Seq a -> Maybe a
Seq.lookup (Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Seq CadenceState
sq
getChordState :: Progression -> Int -> Maybe ChordState
getChordState :: Progression -> Int -> Maybe ChordState
getChordState Progression
prog Int
idx = do
cs <- Progression -> Int -> Maybe CadenceState
getCadenceState Progression
prog Int
idx
let chord = CadenceState -> Chord
fromCadenceState CadenceState
cs
return $ ChordState chord (stateCadenceRoot cs)
rotateProgression :: Int -> Progression -> Progression
rotateProgression :: Int -> Progression -> Progression
rotateProgression Int
n (Progression Seq CadenceState
sq) = Seq CadenceState -> Progression
Progression (Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
rotateSeq Int
n Seq CadenceState
sq)
rotateSeq :: Int -> Seq.Seq a -> Seq.Seq a
rotateSeq :: forall a. Int -> Seq a -> Seq a
rotateSeq Int
n Seq a
sq
| Seq a -> Bool
forall a. Seq a -> Bool
Seq.null Seq a
sq = Seq a
sq
| Bool
otherwise =
let len :: Int
len = Seq a -> Int
forall a. Seq a -> Int
Seq.length Seq a
sq
n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
len
(Seq a
front, Seq a
back) = Int -> Seq a -> (Seq a, Seq a)
forall a. Int -> Seq a -> (Seq a, Seq a)
Seq.splitAt Int
n' Seq a
sq
in Seq a
back Seq a -> Seq a -> Seq a
forall a. Seq a -> Seq a -> Seq a
>< Seq a
front
excerptProgression :: Int -> Int -> Progression -> Progression
excerptProgression :: Int -> Int -> Progression -> Progression
excerptProgression Int
start Int
end (Progression Seq CadenceState
sq) =
Seq CadenceState -> Progression
Progression (Int -> Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Int -> Seq a -> Seq a
excerptSeq Int
start Int
end Seq CadenceState
sq)
excerptSeq :: Int -> Int -> Seq.Seq a -> Seq.Seq a
excerptSeq :: forall a. Int -> Int -> Seq a -> Seq a
excerptSeq Int
start Int
end Seq a
sq =
let start' :: Int
start' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
start Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
len :: Int
len = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
end Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
start Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
in Int -> Seq a -> Seq a
forall a. Int -> Seq a -> Seq a
Seq.take Int
len (Int -> Seq a -> Seq a
forall a. Int -> Seq a -> Seq a
Seq.drop Int
start' Seq a
sq)
insertProgression :: Int -> Progression -> Progression -> Progression
insertProgression :: Int -> Progression -> Progression -> Progression
insertProgression Int
pos Progression
insert (Progression Seq CadenceState
target) =
let pos' :: Int
pos' = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
(Seq CadenceState
before, Seq CadenceState
after) = Int -> Seq CadenceState -> (Seq CadenceState, Seq CadenceState)
forall a. Int -> Seq a -> (Seq a, Seq a)
Seq.splitAt Int
pos' Seq CadenceState
target
in Seq CadenceState -> Progression
Progression (Seq CadenceState
before Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Progression -> Seq CadenceState
unProgression Progression
insert Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
after)
fuseProgression :: Progression -> Progression -> Progression
fuseProgression :: Progression -> Progression -> Progression
fuseProgression (Progression Seq CadenceState
a) (Progression Seq CadenceState
b) =
Seq CadenceState -> Progression
Progression (Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
interleaveSeq Seq CadenceState
a Seq CadenceState
b)
interleaveSeq :: Seq.Seq a -> Seq.Seq a -> Seq.Seq a
interleaveSeq :: forall a. Seq a -> Seq a -> Seq a
interleaveSeq Seq a
a Seq a
b = [a] -> Seq a
forall a. [a] -> Seq a
Seq.fromList ([a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
go (Seq a -> [a]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq a
a) (Seq a -> [a]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq a
b))
where
go :: [a] -> [a] -> [a]
go [] [a]
ys = [a]
ys
go [a]
xs [] = [a]
xs
go (a
x:[a]
xs) (a
y:[a]
ys) = a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a
y a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a] -> [a]
go [a]
xs [a]
ys
transposeProgression :: Int -> Progression -> Progression
transposeProgression :: Int -> Progression -> Progression
transposeProgression Int
n (Progression Seq CadenceState
sq) =
Seq CadenceState -> Progression
Progression (Seq CadenceState -> Progression)
-> Seq CadenceState -> Progression
forall a b. (a -> b) -> a -> b
$ (CadenceState -> CadenceState)
-> Seq CadenceState -> Seq CadenceState
forall a b. (a -> b) -> Seq a -> Seq b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> CadenceState -> CadenceState
transposeCadenceState Int
n) Seq CadenceState
sq
transposeCadenceState :: Int -> CadenceState -> CadenceState
transposeCadenceState :: Int -> CadenceState -> CadenceState
transposeCadenceState Int
n (CadenceState Cadence
cad NoteName
root EnharmonicSpelling
_oldSpelling) =
let pc :: PitchClass
pc = NoteName -> PitchClass
pitchClass NoteName
root
newRootPC :: PitchClass
newRootPC = PitchClass
pc PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
mkPitchClass Int
n
tones :: [Int]
tones = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
unPitchClass ([PitchClass] -> [Int]) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> a -> b
$ Cadence -> [PitchClass]
cadenceIntervals Cadence
cad
absolutePitches :: [Int]
absolutePitches = (Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
t -> (Int
t Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PitchClass -> Int
unPitchClass PitchClass
newRootPC) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
tones
newSpelling :: EnharmonicSpelling
newSpelling = [Int] -> EnharmonicSpelling
inferSpelling [Int]
absolutePitches
newRoot :: NoteName
newRoot = EnharmonicSpelling -> PitchClass -> NoteName
enharmonicFunc EnharmonicSpelling
newSpelling PitchClass
newRootPC
in Cadence -> NoteName -> EnharmonicSpelling -> CadenceState
CadenceState Cadence
cad NoteName
newRoot EnharmonicSpelling
newSpelling
overlapProgression :: Int -> Progression -> Progression -> Progression
overlapProgression :: Int -> Progression -> Progression -> Progression
overlapProgression Int
overlap (Progression Seq CadenceState
a) (Progression Seq CadenceState
b)
| Int
overlap Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
a = Seq CadenceState -> Progression
Progression Seq CadenceState
b
| Bool
otherwise =
let aLen :: Int
aLen = Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
a
aTruncated :: Seq CadenceState
aTruncated = Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.take (Int
aLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
overlap) Seq CadenceState
a
in Seq CadenceState -> Progression
Progression (Seq CadenceState
aTruncated Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
b)
expandProgression :: Int -> Progression -> Progression
expandProgression :: Int -> Progression -> Progression
expandProgression Int
n Progression
prog
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Progression
forall a. Monoid a => a
mempty
| Bool
otherwise = [Progression] -> Progression
forall a. Monoid a => [a] -> a
mconcat (Int -> Progression -> [Progression]
forall a. Int -> a -> [a]
replicate Int
n Progression
prog)
spliceProgression :: Progression -> Int -> Int -> [CadenceState] -> Progression
spliceProgression :: Progression -> Int -> Int -> [CadenceState] -> Progression
spliceProgression (Progression Seq CadenceState
sq) Int
start Int
end [CadenceState]
newChords =
let n :: Int
n = Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
sq
newSeq :: Seq CadenceState
newSeq = [CadenceState] -> Seq CadenceState
forall a. [a] -> Seq a
Seq.fromList [CadenceState]
newChords
in if Int
start Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
end then
let prefix :: Seq CadenceState
prefix = Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.take (Int
start Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Seq CadenceState
sq
suffix :: Seq CadenceState
suffix = Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.drop Int
end Seq CadenceState
sq
result :: Seq CadenceState
result = Seq CadenceState
prefix Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
newSeq Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
suffix
jIdx :: Int
jIdx = Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
prefix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
newSeq
in if Int
jIdx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
result Bool -> Bool -> Bool
&& Int
jIdx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (Seq CadenceState -> Bool
forall a. Seq a -> Bool
Seq.null Seq CadenceState
suffix)
then Int -> Progression -> Progression
fixMovementAt0 Int
jIdx (Seq CadenceState -> Progression
Progression Seq CadenceState
result)
else Seq CadenceState -> Progression
Progression Seq CadenceState
result
else
let kept :: Seq CadenceState
kept = Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.take (Int
start Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
end Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.drop Int
end Seq CadenceState
sq)
headCount :: Int
headCount = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
start Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
newAtEnd :: Seq CadenceState
newAtEnd = Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.take Int
headCount Seq CadenceState
newSeq
newAtStart :: Seq CadenceState
newAtStart = Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.drop Int
headCount Seq CadenceState
newSeq
result :: Seq CadenceState
result = Seq CadenceState
newAtStart Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
kept Seq CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Seq a -> Seq a -> Seq a
>< Seq CadenceState
newAtEnd
jIdx :: Int
jIdx = Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
newAtStart
in if Int
jIdx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
result Bool -> Bool -> Bool
&& Int
jIdx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Bool -> Bool
not (Seq CadenceState -> Bool
forall a. Seq a -> Bool
Seq.null Seq CadenceState
kept)
then Int -> Progression -> Progression
fixMovementAt0 Int
jIdx (Seq CadenceState -> Progression
Progression Seq CadenceState
result)
else Seq CadenceState -> Progression
Progression Seq CadenceState
result
fixMovementAt :: Int -> Progression -> Progression
fixMovementAt :: Int -> Progression -> Progression
fixMovementAt Int
pos = Int -> Progression -> Progression
fixMovementAt0 (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
fixMovementAt0 :: Int -> Progression -> Progression
fixMovementAt0 :: Int -> Progression -> Progression
fixMovementAt0 Int
idx (Progression Seq CadenceState
sq)
| Seq CadenceState -> Bool
forall a. Seq a -> Bool
Seq.null Seq CadenceState
sq Bool -> Bool -> Bool
|| Int
idx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Int
idx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Seq CadenceState -> Int
forall a. Seq a -> Int
Seq.length Seq CadenceState
sq = Seq CadenceState -> Progression
Progression Seq CadenceState
sq
| Bool
otherwise =
let prevCS :: CadenceState
prevCS = Seq CadenceState -> Int -> CadenceState
forall a. Seq a -> Int -> a
Seq.index Seq CadenceState
sq (Int
idx Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
currCS :: CadenceState
currCS = Seq CadenceState -> Int -> CadenceState
forall a. Seq a -> Int -> a
Seq.index Seq CadenceState
sq Int
idx
prevRootPC :: PitchClass
prevRootPC = NoteName -> PitchClass
pitchClass (CadenceState -> NoteName
stateCadenceRoot CadenceState
prevCS)
currRootPC :: PitchClass
currRootPC = NoteName -> PitchClass
pitchClass (CadenceState -> NoteName
stateCadenceRoot CadenceState
currCS)
newMovement :: Movement
newMovement = PitchClass -> PitchClass -> Movement
toMovement PitchClass
prevRootPC PitchClass
currRootPC
oldCadence :: Cadence
oldCadence = CadenceState -> Cadence
stateCadence CadenceState
currCS
newCadence :: Cadence
newCadence = Cadence
oldCadence { cadenceMovement = newMovement }
fixed :: CadenceState
fixed = CadenceState
currCS { stateCadence = newCadence }
in Seq CadenceState -> Progression
Progression (Int -> CadenceState -> Seq CadenceState -> Seq CadenceState
forall a. Int -> a -> Seq a -> Seq a
Seq.update Int
idx CadenceState
fixed Seq CadenceState
sq)
literalVoicing :: Progression -> [[Int]]
literalVoicing :: Progression -> [[Int]]
literalVoicing (Progression Seq CadenceState
sq) =
(CadenceState -> [Int]) -> [CadenceState] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map ((Integer -> Int) -> [Integer] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Integer] -> [Int])
-> (CadenceState -> [Integer]) -> CadenceState -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chord -> [Integer]
chordIntervals (Chord -> [Integer])
-> (CadenceState -> Chord) -> CadenceState -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CadenceState -> Chord
fromCadenceState) (Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq CadenceState
sq)
harmonyVoicing :: Progression -> [[Int]]
harmonyVoicing :: Progression -> [[Int]]
harmonyVoicing Progression
prog = ([Int] -> [Int]) -> [[Int]] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map ((Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12)) (Progression -> [[Int]]
literalVoicing Progression
prog)
closeVoicing :: Progression -> [[Int]]
closeVoicing :: Progression -> [[Int]]
closeVoicing Progression
prog = ([Int] -> [Int]) -> [[Int]] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map [Int] -> [Int]
forall {a}. Integral a => [a] -> [a]
toCloseVoicing (Progression -> [[Int]]
literalVoicing Progression
prog)
where
toCloseVoicing :: [a] -> [a]
toCloseVoicing [a]
xs =
let sorted :: [a]
sorted = [a] -> [a]
forall a. Ord a => [a] -> [a]
sort ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ (a -> a) -> [a] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
12) [a]
xs
in [a]
sorted
wideVoicing :: Progression -> [[Int]]
wideVoicing :: Progression -> [[Int]]
wideVoicing Progression
prog = ([Int] -> [Int]) -> [[Int]] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map [Int] -> [Int]
forall {a}. Num a => [a] -> [a]
toWideVoicing (Progression -> [[Int]]
literalVoicing Progression
prog)
where
toWideVoicing :: [a] -> [a]
toWideVoicing [] = []
toWideVoicing (a
bass:[a]
rest) =
let bassOctave :: a
bassOctave = a
bass
spread :: [a]
spread = (a -> a -> a) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> a
forall a. Num a => a -> a -> a
(+) [a]
rest [a
12, a
24, a
36, a
48]
in a
bassOctave a -> [a] -> [a]
forall a. a -> [a] -> [a]
: 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]
rest) [a]
spread
showTriad :: (PitchClass -> NoteName) -> Chord -> String
showTriad :: (PitchClass -> NoteName) -> Chord -> [Char]
showTriad PitchClass -> NoteName
f (Chord NoteName
noteName [Char]
functionality [Integer]
_)
| [Char]
"sus4" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality Bool -> Bool -> Bool
&& Bool -> Bool
not (([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality) [[Char]
"_1stInv", [Char]
"_2ndInv"]) =
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
functionality
| ([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality) [[Char]
"_1stInv", [Char]
"maj"] =
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
Char.isAlphaNum [Char]
functionality
[Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
noteName PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
P Int
4))
| ([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality) [[Char]
"_1stInv", [Char]
"min"] =
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
Char.isAlphaNum [Char]
functionality
[Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
noteName PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
P Int
3))
| ([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality) [[Char]
"_1stInv", [Char]
"dim"] =
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
Char.isAlphaNum [Char]
functionality [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++
[Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
noteName PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
P Int
3))
| [Char]
"_2ndInv" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality Bool -> Bool -> Bool
&& ([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality) [[Char]
"maj", [Char]
"min"] =
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++
(Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
Char.isAlphaNum [Char]
functionality [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
noteName PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
P Int
7))
| [Char]
"_2ndInv" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality Bool -> Bool -> Bool
&& [Char]
"dim" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`List.isInfixOf` [Char]
functionality =
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++
(Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
Char.isAlphaNum [Char]
functionality [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
noteName PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
P Int
6))
| Bool
otherwise = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (PitchClass -> NoteName) -> PitchClass -> NoteName
forall a b. (a -> b) -> a -> b
$ NoteName -> PitchClass
pitchClass NoteName
noteName) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
functionality
showHarmony :: (PitchClass -> NoteName) -> CadenceState -> String
showHarmony :: (PitchClass -> NoteName) -> CadenceState -> [Char]
showHarmony PitchClass -> NoteName
f cs :: CadenceState
cs@(CadenceState Cadence
cad NoteName
root EnharmonicSpelling
_)
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
3 = (PitchClass -> NoteName) -> Chord -> [Char]
showTriad PitchClass -> NoteName
f (CadenceState -> Chord
fromCadenceState CadenceState
cs)
| Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
7 =
case Int -> [PitchClass] -> Maybe Mode
Sc.classifyModeAt Int
rootInt [PitchClass]
absPCs of
Just (Sc.Mode ModeQuality
q (P Int
r)) ->
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (Int -> PitchClass
mkPitchClass Int
r)) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ ModeQuality -> [Char]
Sc.showModeQuality ModeQuality
q
Maybe Mode
Nothing -> [Char]
chordName
| Bool
otherwise = [Char]
chordName
where
ivs :: [PitchClass]
ivs = Cadence -> [PitchClass]
cadenceIntervals Cadence
cad
n :: Int
n = [PitchClass] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [PitchClass]
ivs
rootInt :: Int
rootInt = PitchClass -> Int
unPitchClass (NoteName -> PitchClass
pitchClass NoteName
root)
absPCs :: [PitchClass]
absPCs = (PitchClass -> PitchClass) -> [PitchClass] -> [PitchClass]
forall a b. (a -> b) -> [a] -> [b]
map (PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ NoteName -> PitchClass
pitchClass NoteName
root) [PitchClass]
ivs
storedF :: [Char]
storedF = Cadence -> [Char]
cadenceFunctionality Cadence
cad
fn :: [Char]
fn | [Char] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
storedF = [PitchClass] -> [Char]
toFunctionalityChord [PitchClass]
ivs
| Bool
otherwise = [Char]
storedF
chordName :: [Char]
chordName = case Text -> Maybe (Text, Int)
J.parseSlashName ([Char] -> Text
T.pack [Char]
fn) of
Just (Text
quality, Int
d) | Int
d Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 ->
NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
root PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ Int -> PitchClass
P Int
d)) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> [Char]
T.unpack Text
quality
[Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
root))
Maybe (Text, Int)
_ -> NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
f (NoteName -> PitchClass
pitchClass NoteName
root)) [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
fn