{-# LANGUAGE OverloadedStrings #-}
module Harmonic.Framework.Builder.Core
(
buildChain
, buildChainWithDiag
, buildChainWithDiagV
, buildChainOffline
, buildChainOfflineWithDiag
, buildChainOfflineWithDiagV
, buildStrataChain
, buildStrataChainOffline
, stepChainCore
, fuseState
, stepChainOffline
, chainToProgression
, extractCadence
, matchesContext
, matchesContextWithTarget
, applyDriftFilter
) where
import qualified Database.Bolt as Bolt
import qualified Data.Text as T
import qualified Data.IntSet as IntSet
import Control.Monad (foldM)
import Control.Monad.IO.Class (liftIO)
import Data.List (sort, sortBy)
import Data.Function (on)
import Data.Ord (Down(..))
import System.Random.MWC (GenIO, createSystemRandom, uniform, uniformR)
import qualified System.Random.MWC.Distributions as Dist
import qualified Harmonic.Rules.Types.Harmony as H
import qualified Harmonic.Rules.Types.Pitch as P
import qualified Harmonic.Rules.Types.Progression as Prog
import Harmonic.Evaluation.Database.Query (ComposerWeights, fetchTransitions)
import qualified Harmonic.Evaluation.Database.Query as Q
import Harmonic.Traversal.Probabilistic (gammaIndexScaledWith)
import Harmonic.Rules.Constraints.Filter (parseOvertones', parseKey, isWildcard, resolveRoots,
nthAbove, nthBelow,
BassDirectionSpec(..), BDKind(..), BDSelector(..))
import Harmonic.Rules.Constraints.Overtone (overtoneSets)
import Harmonic.Evaluation.Scoring.Dissonance (dissonanceScore)
import qualified Harmonic.Evaluation.Scoring.Dissonance as D
import Harmonic.Framework.Builder.Types
import Harmonic.Framework.Builder.Diagnostics (computeChordTrace)
buildChain :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> H.CadenceState
-> Int
-> Bolt.BoltActionT IO [H.CadenceState]
buildChain :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO [CadenceState]
buildChain GeneratorConfig
config GenIO
gen Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start Int
totalSteps = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_current, [CadenceState]
revChain, Int
_counter), [StepDiagnostic]
_noDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainCore GeneratorConfig
config GenIO
gen Maybe Int
forall a. Maybe a
Nothing Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
totalSteps]
[CadenceState] -> BoltActionT IO [CadenceState]
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> BoltActionT IO [CadenceState])
-> [CadenceState] -> BoltActionT IO [CadenceState]
forall a b. (a -> b) -> a -> b
$ [CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain
resolveBassDirection
:: GenIO -> Int -> Maybe BassDirectionSpec -> IO (Maybe BassDirection)
resolveBassDirection :: GenIO -> Int -> Maybe BassDirectionSpec -> IO (Maybe BassDirection)
resolveBassDirection GenIO
_ Int
_ Maybe BassDirectionSpec
Nothing = Maybe BassDirection -> IO (Maybe BassDirection)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe BassDirection
forall a. Maybe a
Nothing
resolveBassDirection GenIO
gen Int
stepNum (Just BassDirectionSpec
spec) = do
Bool
active <- if BassDirectionSpec -> Bool
bdsOptional BassDirectionSpec
spec
then do
Double
r <- GenIO -> IO Double
forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
Gen (PrimState m) -> m a
forall (m :: * -> *). PrimMonad m => Gen (PrimState m) -> m Double
uniform GenIO
gen :: IO Double
Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double
r Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.5)
else Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
if Bool -> Bool
not Bool
active
then Maybe BassDirection -> IO (Maybe BassDirection)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe BassDirection
forall a. Maybe a
Nothing
else do
let cs :: [Int]
cs = BassDirectionSpec -> [Int]
bdsChoices BassDirectionSpec
spec
Int
n <- case BassDirectionSpec -> BDSelector
bdsSelector BassDirectionSpec
spec of
BDSelector
BDFixed -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Int] -> Int
forall a. HasCallStack => [a] -> a
head [Int]
cs)
BDSelector
BDRotate -> Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Int]
cs [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! ((Int
stepNum Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cs))
BDSelector
BDRandomPick -> do
Int
i <- (Int, Int) -> GenIO -> IO Int
forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
(a, a) -> Gen (PrimState m) -> m a
forall (m :: * -> *).
PrimMonad m =>
(Int, Int) -> Gen (PrimState m) -> m Int
uniformR (Int
0, [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) GenIO
gen
Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Int]
cs [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
i)
Maybe BassDirection -> IO (Maybe BassDirection)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe BassDirection -> IO (Maybe BassDirection))
-> Maybe BassDirection -> IO (Maybe BassDirection)
forall a b. (a -> b) -> a -> b
$ BassDirection -> Maybe BassDirection
forall a. a -> Maybe a
Just (BassDirection -> Maybe BassDirection)
-> BassDirection -> Maybe BassDirection
forall a b. (a -> b) -> a -> b
$ case BassDirectionSpec -> BDKind
bdsKind BassDirectionSpec
spec of
BDKind
RiseK -> Int -> BassDirection
Rise Int
n
BDKind
FallK -> Int -> BassDirection
Fall Int
n
stepChainBody :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((H.CadenceState, [H.CadenceState], Int), [StepDiagnostic])
-> Int
-> [(H.Cadence, ComposerWeights)]
-> IO ((H.CadenceState, [H.CadenceState], Int), [StepDiagnostic])
stepChainBody :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> [(Cadence, ComposerWeights)]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainBody GeneratorConfig
config GenIO
gen Maybe Int
mVerbosity Double
ent HarmonicContext
_context ParsedContext
pctx ComposerWeights
composerWeights ((CadenceState
current, [CadenceState]
revChain, Int
nonInvCount), [StepDiagnostic]
revDiags) Int
stepNum [(Cadence, ComposerWeights)]
transitions = do
let walkCur :: CadenceState
walkCur = CadenceState -> CadenceState
H.walkTriadState CadenceState
current
Maybe BassDirection
mDir <- GenIO -> Int -> Maybe BassDirectionSpec -> IO (Maybe BassDirection)
resolveBassDirection GenIO
gen Int
stepNum (ParsedContext -> Maybe BassDirectionSpec
pcBassDirectionSpec ParsedContext
pctx)
let prevBassPC :: Int
prevBassPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
current))
bassTarget :: Maybe Int
bassTarget = case Maybe BassDirection
mDir of
Maybe BassDirection
Nothing -> Maybe Int
forall a. Maybe a
Nothing
Just (Rise Int
n) -> Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> IntSet -> Int
nthAbove Int
n Int
prevBassPC (ParsedContext -> IntSet
pcAllowedBassNotes ParsedContext
pctx)
Just (Fall Int
n) -> Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> IntSet -> Int
nthBelow Int
n Int
prevBassPC (ParsedContext -> IntSet
pcAllowedBassNotes ParsedContext
pctx)
let filtered :: [(Cadence, ComposerWeights)]
filtered = Maybe Int
-> ParsedContext
-> CadenceState
-> [(Cadence, ComposerWeights)]
-> [(Cadence, ComposerWeights)]
applyRConstraintsWithTarget Maybe Int
bassTarget ParsedContext
pctx CadenceState
walkCur [(Cadence, ComposerWeights)]
transitions
let scored :: [(Cadence, Double)]
scored = ComposerWeights
-> [(Cadence, ComposerWeights)] -> [(Cadence, Double)]
scoreByConfidence ComposerWeights
composerWeights [(Cadence, ComposerWeights)]
filtered
boost :: Double
boost = ParsedContext -> Double
pcSoftBoost ParsedContext
pctx
graphCandidates :: [(Cadence, Double)]
graphCandidates
| Double
boost Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
1.0 = [(Cadence, Double)]
scored
| Bool
otherwise =
let boosted :: [(Cadence, Double)]
boosted = [(Cadence
c, Double
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
boost) | (Cadence
c, Double
s) <- [(Cadence, Double)]
scored]
in ((Cadence, Double) -> (Cadence, Double) -> Ordering)
-> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Down Double -> Down Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Down Double -> Down Double -> Ordering)
-> ((Cadence, Double) -> Down Double)
-> (Cadence, Double)
-> (Cadence, Double)
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (Double -> Down Double
forall a. a -> Down a
Down (Double -> Down Double)
-> ((Cadence, Double) -> Double)
-> (Cadence, Double)
-> Down Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, Double) -> Double
forall a b. (a, b) -> b
snd)) [(Cadence, Double)]
boosted
graphCount :: Int
graphCount = [(Cadence, Double)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Cadence, Double)]
graphCandidates
[(Cadence, Double, Double, Double, Double)]
fallbackAll <- GenIO
-> CadenceState
-> ParsedContext
-> IO [(Cadence, Double, Double, Double, Double)]
consonanceFallbackParsed GenIO
gen CadenceState
walkCur ParsedContext
pctx
let unfilteredFallback :: [(Cadence, Double)]
unfilteredFallback = [(Cadence
cad, Double
score) | (Cadence
cad, Double
score, Double
_, Double
_, Double
_) <- [(Cadence, Double, Double, Double, Double)]
fallbackAll]
filteredFallback :: [(Cadence, Double)]
filteredFallback = ((Cadence, Double) -> Bool)
-> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Cadence
cad, Double
_) -> Maybe Int -> ParsedContext -> CadenceState -> Cadence -> Bool
matchesContextWithTarget Maybe Int
bassTarget ParsedContext
pctx CadenceState
walkCur Cadence
cad) [(Cadence, Double)]
unfilteredFallback
fallbackCount :: Int
fallbackCount = [(Cadence, Double)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Cadence, Double)]
filteredFallback
pool :: [(Cadence, Double)]
pool = [(Cadence, Double)]
graphCandidates [(Cadence, Double)] -> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. [a] -> [a] -> [a]
++ [(Cadence, Double)]
filteredFallback
driftedPool :: [(Cadence, Double)]
driftedPool = Drift -> CadenceState -> [(Cadence, Double)] -> [(Cadence, Double)]
applyDriftFilter (ParsedContext -> Drift
pcDrift ParsedContext
pctx) CadenceState
walkCur [(Cadence, Double)]
pool
invSpacing :: Int
invSpacing = ParsedContext -> Int
pcInversionSpacing ParsedContext
pctx
inversionAllowed :: Bool
inversionAllowed = Int
nonInvCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
invSpacing
spacedPool :: [(Cadence, Double)]
spacedPool = if Bool
inversionAllowed
then [(Cadence, Double)]
driftedPool
else ((Cadence, Double) -> Bool)
-> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> ((Cadence, Double) -> Bool) -> (Cadence, Double) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cadence -> Bool
H.isInversion (Cadence -> Bool)
-> ((Cadence, Double) -> Cadence) -> (Cadence, Double) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, Double) -> Cadence
forall a b. (a, b) -> a
fst) [(Cadence, Double)]
driftedPool
prepedalPool :: [(Cadence, Double)]
prepedalPool = if [(Cadence, Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Cadence, Double)]
spacedPool then [(Cadence, Double)]
driftedPool else [(Cadence, Double)]
spacedPool
finalPool :: [(Cadence, Double)]
finalPool = ParsedContext
-> CadenceState -> [(Cadence, Double)] -> [(Cadence, Double)]
applyPedalFilter ParsedContext
pctx CadenceState
walkCur [(Cadence, Double)]
prepedalPool
if [(Cadence, Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Cadence, Double)]
finalPool
then do
let diags :: [StepDiagnostic]
diags = case Maybe Int
mVerbosity of
Maybe Int
Nothing -> [StepDiagnostic]
revDiags
Just Int
_ ->
let diag :: StepDiagnostic
diag = StepDiagnostic
{ sdStepNumber :: Int
sdStepNumber = Int
stepNum
, sdPriorCadence :: String
sdPriorCadence = Cadence -> String
forall a. Show a => a -> String
show (CadenceState -> Cadence
extractCadence CadenceState
current)
, sdPriorRoot :: String
sdPriorRoot = NoteName -> String
forall a. Show a => a -> String
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
current)
, sdPriorRootPC :: Int
sdPriorRootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
current))
, sdSelectedDbIntervals :: String
sdSelectedDbIntervals = String
"N/A"
, sdSelectedDbMovement :: String
sdSelectedDbMovement = String
"N/A"
, sdSelectedDbFunctionality :: String
sdSelectedDbFunctionality = String
"N/A"
, sdGraphCount :: Int
sdGraphCount = Int
0
, sdGraphTop6 :: [(String, Double)]
sdGraphTop6 = []
, sdFallbackCount :: Int
sdFallbackCount = Int
0
, sdFallbackTop6 :: [(String, Double, Double, Double, Double)]
sdFallbackTop6 = []
, sdPoolSize :: Int
sdPoolSize = Int
0
, sdEntropyUsed :: Double
sdEntropyUsed = Double
ent
, sdGammaIndex :: Int
sdGammaIndex = -Int
1
, sdSelectedFrom :: String
sdSelectedFrom = String
"none (absorbing)"
, sdPosteriorRoot :: String
sdPosteriorRoot = NoteName -> String
forall a. Show a => a -> String
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
current)
, sdPosteriorRootPC :: Int
sdPosteriorRootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
current))
, sdRenderedChord :: Maybe String
sdRenderedChord = Maybe String
forall a. Maybe a
Nothing
, sdTransformTrace :: Maybe TransformTrace
sdTransformTrace = Maybe TransformTrace
forall a. Maybe a
Nothing
, sdAdvanceTrace :: Maybe AdvanceTrace
sdAdvanceTrace = Maybe AdvanceTrace
forall a. Maybe a
Nothing
, sdTristrataIdx :: Maybe Int
sdTristrataIdx = Maybe Int
forall a. Maybe a
Nothing
, sdTristrata :: Maybe Tristrata
sdTristrata = Maybe Tristrata
forall a. Maybe a
Nothing
, sdStrataLabel :: Maybe StrataLabel
sdStrataLabel = Maybe StrataLabel
forall a. Maybe a
Nothing
, sdMode :: Maybe Mode
sdMode = Maybe Mode
forall a. Maybe a
Nothing
, sdStrataChroma :: Maybe [PitchClass]
sdStrataChroma = Maybe [PitchClass]
forall a. Maybe a
Nothing
, sdModeChroma :: Maybe [PitchClass]
sdModeChroma = Maybe [PitchClass]
forall a. Maybe a
Nothing
, sdSoftBoost :: Maybe Double
sdSoftBoost = Maybe Double
forall a. Maybe a
Nothing
, sdHarmonicRootPC :: Maybe Int
sdHarmonicRootPC = Maybe Int
forall a. Maybe a
Nothing
, sdParentKey :: Maybe (PitchClass, ScaleFamily)
sdParentKey = Maybe (PitchClass, ScaleFamily)
forall a. Maybe a
Nothing
, sdModeResult :: Maybe ModeResult
sdModeResult = Maybe ModeResult
forall a. Maybe a
Nothing
, sdBarSpelling :: Maybe EnharmonicSpelling
sdBarSpelling = Maybe EnharmonicSpelling
forall a. Maybe a
Nothing
, sdFusion :: Maybe FusionDiag
sdFusion = Maybe FusionDiag
forall a. Maybe a
Nothing
}
in StepDiagnostic
diag StepDiagnostic -> [StepDiagnostic] -> [StepDiagnostic]
forall a. a -> [a] -> [a]
: [StepDiagnostic]
revDiags
((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((CadenceState
current, CadenceState
current CadenceState -> [CadenceState] -> [CadenceState]
forall a. a -> [a] -> [a]
: [CadenceState]
revChain, Int
nonInvCount), [StepDiagnostic]
diags)
else do
Int
idx <- GenIO -> Double -> Int -> IO Int
gammaIndexScaledWith GenIO
gen Double
ent ([(Cadence, Double)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Cadence, Double)]
finalPool)
let nextCadence :: Cadence
nextCadence = (Cadence, Double) -> Cadence
forall a b. (a, b) -> a
fst ([(Cadence, Double)]
finalPool [(Cadence, Double)] -> Int -> (Cadence, Double)
forall a. HasCallStack => [a] -> Int -> a
!! Int
idx)
(CadenceState
newState, AdvanceTrace
advTrace) = Maybe EnharmonicSpelling
-> CadenceState -> Cadence -> (CadenceState, AdvanceTrace)
advanceStateTraced (ParsedContext -> Maybe EnharmonicSpelling
pcKeySpelling ParsedContext
pctx) CadenceState
walkCur Cadence
nextCadence
newCounter :: Int
newCounter = if Cadence -> Bool
H.isInversion Cadence
nextCadence then Int
0 else Int
nonInvCount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
(CadenceState
emitState, Maybe FusionDiag
mFusion) <-
if GeneratorConfig -> Bool
gcQuad GeneratorConfig
config
then GenIO
-> Double
-> ParsedContext
-> Maybe CadenceState
-> CadenceState
-> IO (CadenceState, Maybe FusionDiag)
fuseState GenIO
gen Double
ent ParsedContext
pctx (CadenceState -> Maybe CadenceState
forall a. a -> Maybe a
Just CadenceState
current) CadenceState
newState
else (CadenceState, Maybe FusionDiag)
-> IO (CadenceState, Maybe FusionDiag)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CadenceState
newState, Maybe FusionDiag
forall a. Maybe a
Nothing)
let diags :: [StepDiagnostic]
diags = case Maybe Int
mVerbosity of
Maybe Int
Nothing -> [StepDiagnostic]
revDiags
Just Int
verbosity ->
let finalShows :: [String]
finalShows = ((Cadence, Double) -> String) -> [(Cadence, Double)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Cadence -> String
forall a. Show a => a -> String
show (Cadence -> String)
-> ((Cadence, Double) -> Cadence) -> (Cadence, Double) -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, Double) -> Cadence
forall a b. (a, b) -> a
fst) [(Cadence, Double)]
finalPool
graphShows :: [String]
graphShows = ((Cadence, Double) -> String) -> [(Cadence, Double)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Cadence -> String
forall a. Show a => a -> String
show (Cadence -> String)
-> ((Cadence, Double) -> Cadence) -> (Cadence, Double) -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, Double) -> Cadence
forall a b. (a, b) -> a
fst) [(Cadence, Double)]
graphCandidates
selectedFrom :: String
selectedFrom = if Cadence -> String
forall a. Show a => a -> String
show Cadence
nextCadence String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
graphShows
then String
"graph" else String
"fallback"
graphTop6 :: [(String, Double)]
graphTop6 = Int -> [(String, Double)] -> [(String, Double)]
forall a. Int -> [a] -> [a]
take Int
6 [(String
s', Double
conf) | (Cadence
cad, Double
conf) <- [(Cadence, Double)]
graphCandidates
, let s' :: String
s' = Cadence -> String
forall a. Show a => a -> String
show Cadence
cad, String
s' String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
finalShows]
fallbackTop6' :: [(String, Double, Double, Double, Double)]
fallbackTop6' = Int
-> [(String, Double, Double, Double, Double)]
-> [(String, Double, Double, Double, Double)]
forall a. Int -> [a] -> [a]
take Int
6 [(String
s', Double
score, Double
cd, Double
md, Double
gd) | (Cadence
cad, Double
score, Double
cd, Double
md, Double
gd) <- [(Cadence, Double, Double, Double, Double)]
fallbackAll
, let s' :: String
s' = Cadence -> String
forall a. Show a => a -> String
show Cadence
cad, String
s' String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
finalShows]
(Maybe String
renderedChord, Maybe TransformTrace
transformTrace) = Int -> CadenceState -> (Maybe String, Maybe TransformTrace)
computeChordTrace Int
verbosity CadenceState
emitState
priorRoot :: NoteName
priorRoot = CadenceState -> NoteName
H.stateCadenceRoot CadenceState
current
priorRootPC :: Int
priorRootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass NoteName
priorRoot)
posteriorRoot :: NoteName
posteriorRoot = CadenceState -> NoteName
H.stateCadenceRoot CadenceState
emitState
posteriorRootPC :: Int
posteriorRootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass NoteName
posteriorRoot)
diag :: StepDiagnostic
diag = StepDiagnostic
{ sdStepNumber :: Int
sdStepNumber = Int
stepNum
, sdPriorCadence :: String
sdPriorCadence = Cadence -> String
forall a. Show a => a -> String
show (CadenceState -> Cadence
extractCadence CadenceState
current)
, sdPriorRoot :: String
sdPriorRoot = NoteName -> String
forall a. Show a => a -> String
show NoteName
priorRoot
, sdPriorRootPC :: Int
sdPriorRootPC = Int
priorRootPC
, sdSelectedDbIntervals :: String
sdSelectedDbIntervals = [PitchClass] -> String
forall a. Show a => a -> String
show (Cadence -> [PitchClass]
H.cadenceIntervals Cadence
nextCadence)
, sdSelectedDbMovement :: String
sdSelectedDbMovement = Movement -> String
forall a. Show a => a -> String
show (Cadence -> Movement
H.cadenceMovement Cadence
nextCadence)
, sdSelectedDbFunctionality :: String
sdSelectedDbFunctionality = Cadence -> String
H.cadenceFunctionality Cadence
nextCadence
, sdGraphCount :: Int
sdGraphCount = Int
graphCount
, sdGraphTop6 :: [(String, Double)]
sdGraphTop6 = [(String, Double)]
graphTop6
, sdFallbackCount :: Int
sdFallbackCount = Int
fallbackCount
, sdFallbackTop6 :: [(String, Double, Double, Double, Double)]
sdFallbackTop6 = [(String, Double, Double, Double, Double)]
fallbackTop6'
, sdPoolSize :: Int
sdPoolSize = [(Cadence, Double)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Cadence, Double)]
finalPool
, sdEntropyUsed :: Double
sdEntropyUsed = Double
ent
, sdGammaIndex :: Int
sdGammaIndex = Int
idx
, sdSelectedFrom :: String
sdSelectedFrom = String
selectedFrom
, sdPosteriorRoot :: String
sdPosteriorRoot = NoteName -> String
forall a. Show a => a -> String
show NoteName
posteriorRoot
, sdPosteriorRootPC :: Int
sdPosteriorRootPC = Int
posteriorRootPC
, sdRenderedChord :: Maybe String
sdRenderedChord = Maybe String
renderedChord
, sdTransformTrace :: Maybe TransformTrace
sdTransformTrace = Maybe TransformTrace
transformTrace
, sdAdvanceTrace :: Maybe AdvanceTrace
sdAdvanceTrace = if Int
verbosity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 then AdvanceTrace -> Maybe AdvanceTrace
forall a. a -> Maybe a
Just AdvanceTrace
advTrace else Maybe AdvanceTrace
forall a. Maybe a
Nothing
, sdTristrataIdx :: Maybe Int
sdTristrataIdx = Maybe Int
forall a. Maybe a
Nothing
, sdTristrata :: Maybe Tristrata
sdTristrata = Maybe Tristrata
forall a. Maybe a
Nothing
, sdStrataLabel :: Maybe StrataLabel
sdStrataLabel = Maybe StrataLabel
forall a. Maybe a
Nothing
, sdMode :: Maybe Mode
sdMode = Maybe Mode
forall a. Maybe a
Nothing
, sdStrataChroma :: Maybe [PitchClass]
sdStrataChroma = Maybe [PitchClass]
forall a. Maybe a
Nothing
, sdModeChroma :: Maybe [PitchClass]
sdModeChroma = Maybe [PitchClass]
forall a. Maybe a
Nothing
, sdSoftBoost :: Maybe Double
sdSoftBoost = Maybe Double
forall a. Maybe a
Nothing
, sdHarmonicRootPC :: Maybe Int
sdHarmonicRootPC = Maybe Int
forall a. Maybe a
Nothing
, sdParentKey :: Maybe (PitchClass, ScaleFamily)
sdParentKey = Maybe (PitchClass, ScaleFamily)
forall a. Maybe a
Nothing
, sdModeResult :: Maybe ModeResult
sdModeResult = Maybe ModeResult
forall a. Maybe a
Nothing
, sdBarSpelling :: Maybe EnharmonicSpelling
sdBarSpelling = Maybe EnharmonicSpelling
forall a. Maybe a
Nothing
, sdFusion :: Maybe FusionDiag
sdFusion = Maybe FusionDiag
mFusion
}
in StepDiagnostic
diag StepDiagnostic -> [StepDiagnostic] -> [StepDiagnostic]
forall a. a -> [a] -> [a]
: [StepDiagnostic]
revDiags
((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((CadenceState
emitState, CadenceState
emitState CadenceState -> [CadenceState] -> [CadenceState]
forall a. a -> [a] -> [a]
: [CadenceState]
revChain, Int
newCounter), [StepDiagnostic]
diags)
stepChainCore :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((H.CadenceState, [H.CadenceState], Int), [StepDiagnostic])
-> Int
-> Bolt.BoltActionT IO ((H.CadenceState, [H.CadenceState], Int), [StepDiagnostic])
stepChainCore :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainCore GeneratorConfig
config GenIO
gen Maybe Int
mVerbosity Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights acc :: ((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc@((CadenceState
current, [CadenceState]
_, Int
_), [StepDiagnostic]
_) Int
stepNum = do
let currentShow :: Text
currentShow = String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Cadence -> String
forall a. Show a => a -> String
show (CadenceState -> Cadence
extractCadence (CadenceState -> CadenceState
H.walkTriadState CadenceState
current))
[(Cadence, ComposerWeights)]
transitions <- Text -> BoltActionT IO [(Cadence, ComposerWeights)]
fetchTransitions Text
currentShow
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall a. IO a -> BoltActionT IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall a b. (a -> b) -> a -> b
$ GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> [(Cadence, ComposerWeights)]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainBody GeneratorConfig
config GenIO
gen Maybe Int
mVerbosity Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights ((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
stepNum [(Cadence, ComposerWeights)]
transitions
stepChainOffline :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ((H.CadenceState, [H.CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((H.CadenceState, [H.CadenceState], Int), [StepDiagnostic])
stepChainOffline :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainOffline GeneratorConfig
config GenIO
gen Maybe Int
mVerbosity Double
ent HarmonicContext
context ParsedContext
pctx ((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
stepNum =
GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> [(Cadence, ComposerWeights)]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainBody GeneratorConfig
config GenIO
gen Maybe Int
mVerbosity Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
forall a. Monoid a => a
mempty ((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
stepNum []
buildChainWithDiag :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> H.CadenceState
-> Int
-> Bolt.BoltActionT IO ([H.CadenceState], [StepDiagnostic])
buildChainWithDiag :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildChainWithDiag GeneratorConfig
config GenIO
gen Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start Int
totalSteps =
GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildChainWithDiagV GeneratorConfig
config GenIO
gen Int
1 Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start Int
totalSteps
buildChainWithDiagV :: GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> H.CadenceState
-> Int
-> Bolt.BoltActionT IO ([H.CadenceState], [StepDiagnostic])
buildChainWithDiagV :: GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildChainWithDiagV GeneratorConfig
config GenIO
gen Int
verbosity Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start Int
totalSteps = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_current, [CadenceState]
revChain, Int
_counter), [StepDiagnostic]
revDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainCore GeneratorConfig
config GenIO
gen (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
verbosity) Double
ent HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
totalSteps]
([CadenceState], [StepDiagnostic])
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain, [StepDiagnostic] -> [StepDiagnostic]
forall a. [a] -> [a]
reverse [StepDiagnostic]
revDiags)
buildChainOffline :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> H.CadenceState
-> Int
-> IO [H.CadenceState]
buildChainOffline :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> CadenceState
-> Int
-> IO [CadenceState]
buildChainOffline GeneratorConfig
config GenIO
gen Double
ent HarmonicContext
context ParsedContext
pctx CadenceState
start Int
totalSteps = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_current, [CadenceState]
revChain, Int
_counter), [StepDiagnostic]
_noDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainOffline GeneratorConfig
config GenIO
gen Maybe Int
forall a. Maybe a
Nothing Double
ent HarmonicContext
context ParsedContext
pctx)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
totalSteps]
[CadenceState] -> IO [CadenceState]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> IO [CadenceState])
-> [CadenceState] -> IO [CadenceState]
forall a b. (a -> b) -> a -> b
$ [CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain
buildChainOfflineWithDiag :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> H.CadenceState
-> Int
-> IO ([H.CadenceState], [StepDiagnostic])
buildChainOfflineWithDiag :: GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> CadenceState
-> Int
-> IO ([CadenceState], [StepDiagnostic])
buildChainOfflineWithDiag GeneratorConfig
config GenIO
gen Double
ent HarmonicContext
context ParsedContext
pctx CadenceState
start Int
totalSteps = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_current, [CadenceState]
revChain, Int
_counter), [StepDiagnostic]
revDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainOffline GeneratorConfig
config GenIO
gen (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1) Double
ent HarmonicContext
context ParsedContext
pctx)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
totalSteps]
([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain, [StepDiagnostic] -> [StepDiagnostic]
forall a. [a] -> [a]
reverse [StepDiagnostic]
revDiags)
buildChainOfflineWithDiagV :: GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> H.CadenceState
-> Int
-> IO ([H.CadenceState], [StepDiagnostic])
buildChainOfflineWithDiagV :: GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> CadenceState
-> Int
-> IO ([CadenceState], [StepDiagnostic])
buildChainOfflineWithDiagV GeneratorConfig
config GenIO
gen Int
verbosity Double
ent HarmonicContext
context ParsedContext
pctx CadenceState
start Int
totalSteps = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_current, [CadenceState]
revChain, Int
_counter), [StepDiagnostic]
revDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainOffline GeneratorConfig
config GenIO
gen (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
verbosity) Double
ent HarmonicContext
context ParsedContext
pctx)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
totalSteps]
([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain, [StepDiagnostic] -> [StepDiagnostic]
forall a. [a] -> [a]
reverse [StepDiagnostic]
revDiags)
buildStrataChain :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> (Int -> ParsedContext)
-> ComposerWeights
-> H.CadenceState
-> Int
-> Bolt.BoltActionT IO ([H.CadenceState], [StepDiagnostic])
buildStrataChain :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> (Int -> ParsedContext)
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildStrataChain GeneratorConfig
config GenIO
gen Maybe Int
mVerb Double
ent HarmonicContext
ctx Int -> ParsedContext
pctxAt ComposerWeights
weights CadenceState
start Int
n = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_, [CadenceState]
revChain, Int
_), [StepDiagnostic]
revDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (\((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
i -> GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> BoltActionT
IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainCore GeneratorConfig
config GenIO
gen Maybe Int
mVerb Double
ent HarmonicContext
ctx (Int -> ParsedContext
pctxAt Int
i) ComposerWeights
weights ((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
i)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
n]
([CadenceState], [StepDiagnostic])
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain, [StepDiagnostic] -> [StepDiagnostic]
forall a. [a] -> [a]
reverse [StepDiagnostic]
revDiags)
buildStrataChainOffline :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> (Int -> ParsedContext)
-> H.CadenceState
-> Int
-> IO ([H.CadenceState], [StepDiagnostic])
buildStrataChainOffline :: GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> (Int -> ParsedContext)
-> CadenceState
-> Int
-> IO ([CadenceState], [StepDiagnostic])
buildStrataChainOffline GeneratorConfig
config GenIO
gen Maybe Int
mVerb Double
ent HarmonicContext
ctx Int -> ParsedContext
pctxAt CadenceState
start Int
n = do
let initCounter :: Int
initCounter = if Cadence -> Bool
H.isInversion (CadenceState -> Cadence
H.stateCadence CadenceState
start) then Int
0 else Int
1
((CadenceState
_, [CadenceState]
revChain, Int
_), [StepDiagnostic]
revDiags) <-
(((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic]))
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> [Int]
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (\((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
i -> GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ((CadenceState, [CadenceState], Int), [StepDiagnostic])
-> Int
-> IO ((CadenceState, [CadenceState], Int), [StepDiagnostic])
stepChainOffline GeneratorConfig
config GenIO
gen Maybe Int
mVerb Double
ent HarmonicContext
ctx (Int -> ParsedContext
pctxAt Int
i) ((CadenceState, [CadenceState], Int), [StepDiagnostic])
acc Int
i)
((CadenceState
start, [CadenceState
start], Int
initCounter), [])
[Int
1..Int
n]
([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState] -> [CadenceState]
forall a. [a] -> [a]
reverse [CadenceState]
revChain, [StepDiagnostic] -> [StepDiagnostic]
forall a. [a] -> [a]
reverse [StepDiagnostic]
revDiags)
scoreByConfidence :: ComposerWeights -> [(H.Cadence, ComposerWeights)] -> [(H.Cadence, Double)]
scoreByConfidence :: ComposerWeights
-> [(Cadence, ComposerWeights)] -> [(Cadence, Double)]
scoreByConfidence ComposerWeights
blend [(Cadence, ComposerWeights)]
transitions = ComposerWeights
-> [(Cadence, ComposerWeights)] -> [(Cadence, Double)]
Q.applyComposerBlend ComposerWeights
blend [(Cadence, ComposerWeights)]
transitions
consonanceFallback :: H.CadenceState -> HarmonicContext -> IO [(H.Cadence, Double, Double, Double, Double)]
consonanceFallback :: CadenceState
-> HarmonicContext
-> IO [(Cadence, Double, Double, Double, Double)]
consonanceFallback CadenceState
currentState HarmonicContext
context = do
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
GenIO
-> CadenceState
-> HarmonicContext
-> IO [(Cadence, Double, Double, Double, Double)]
consonanceFallbackWith Gen RealWorld
GenIO
rng CadenceState
currentState HarmonicContext
context
consonanceFallbackWith :: GenIO -> H.CadenceState -> HarmonicContext -> IO [(H.Cadence, Double, Double, Double, Double)]
consonanceFallbackWith :: GenIO
-> CadenceState
-> HarmonicContext
-> IO [(Cadence, Double, Double, Double, Double)]
consonanceFallbackWith GenIO
gen CadenceState
currentState HarmonicContext
context =
let
currentRoot :: PitchClass
currentRoot = NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
currentState)
overtones :: [Int]
overtones = Int -> Text -> [Int]
parseOvertones' Int
3 (HarmonicContext -> Text
_hcOvertones HarmonicContext
context)
keyPcs :: [Int]
keyPcs = Text -> [Int]
parseKey (HarmonicContext -> Text
_hcKey HarmonicContext
context)
effectiveOvertones :: [Int]
effectiveOvertones = if Text -> Bool
isWildcard (HarmonicContext -> Text
_hcKey HarmonicContext
context)
then [Int]
overtones
else (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
keyPcs) [Int]
overtones
triads :: [[Int]]
triads = let allRoots :: [Int]
allRoots = [Int]
effectiveOvertones
in (Int -> [[Int]]) -> [Int] -> [[Int]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Int
r -> Int -> [Int] -> [Int] -> [[Int]]
forall a. (Eq a, Ord a) => Int -> [a] -> [a] -> [[a]]
overtoneSets Int
3 [Int
r] [Int]
effectiveOvertones) [Int]
allRoots
uniqueTriads :: [[Int]]
uniqueTriads = [[Int]]
triads
in do
[(Cadence, Double, Double, Double, Double)]
results <- ([Int] -> IO (Cadence, Double, Double, Double, Double))
-> [[Int]] -> IO [(Cadence, Double, Double, Double, Double)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\[Int]
t -> do
let cad :: Cadence
cad = PitchClass -> [Int] -> Cadence
triadToCadenceFrom PitchClass
currentRoot [Int]
t
(Double
score, Double
cd, Double
md, Double
gd) <- GenIO
-> PitchClass
-> Cadence
-> [Int]
-> IO (Double, Double, Double, Double)
computeFallbackScoreWith GenIO
gen PitchClass
currentRoot Cadence
cad [Int]
t
(Cadence, Double, Double, Double, Double)
-> IO (Cadence, Double, Double, Double, Double)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Cadence
cad, Double
score, Double
cd, Double
md, Double
gd)
) [[Int]]
uniqueTriads
[(Cadence, Double, Double, Double, Double)]
-> IO [(Cadence, Double, Double, Double, Double)]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(Cadence, Double, Double, Double, Double)]
-> IO [(Cadence, Double, Double, Double, Double)])
-> [(Cadence, Double, Double, Double, Double)]
-> IO [(Cadence, Double, Double, Double, Double)]
forall a b. (a -> b) -> a -> b
$ ((Cadence, Double, Double, Double, Double)
-> (Cadence, Double, Double, Double, Double) -> Ordering)
-> [(Cadence, Double, Double, Double, Double)]
-> [(Cadence, Double, Double, Double, Double)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Down Double -> Down Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Down Double -> Down Double -> Ordering)
-> ((Cadence, Double, Double, Double, Double) -> Down Double)
-> (Cadence, Double, Double, Double, Double)
-> (Cadence, Double, Double, Double, Double)
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (\(Cadence
_, Double
s, Double
_, Double
_, Double
_) -> Double -> Down Double
forall a. a -> Down a
Down Double
s)) [(Cadence, Double, Double, Double, Double)]
results
consonanceFallbackParsed :: GenIO -> H.CadenceState -> ParsedContext -> IO [(H.Cadence, Double, Double, Double, Double)]
consonanceFallbackParsed :: GenIO
-> CadenceState
-> ParsedContext
-> IO [(Cadence, Double, Double, Double, Double)]
consonanceFallbackParsed GenIO
gen CadenceState
currentState ParsedContext
pctx =
let currentRoot :: PitchClass
currentRoot = NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
currentState)
effectiveOvertones :: [Int]
effectiveOvertones = IntSet -> [Int]
IntSet.toList (ParsedContext -> IntSet
pcEffectiveOvertones ParsedContext
pctx)
triads :: [[Int]]
triads = (Int -> [[Int]]) -> [Int] -> [[Int]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Int
r -> Int -> [Int] -> [Int] -> [[Int]]
forall a. (Eq a, Ord a) => Int -> [a] -> [a] -> [[a]]
overtoneSets Int
3 [Int
r] [Int]
effectiveOvertones) [Int]
effectiveOvertones
boost :: Double
boost = ParsedContext -> Double
pcSoftBoost ParsedContext
pctx
in do
[(Cadence, Double, Double, Double, Double)]
results <- ([Int] -> IO (Cadence, Double, Double, Double, Double))
-> [[Int]] -> IO [(Cadence, Double, Double, Double, Double)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\[Int]
t -> do
let cad :: Cadence
cad = PitchClass -> [Int] -> Cadence
triadToCadenceFrom PitchClass
currentRoot [Int]
t
(Double
score, Double
cd, Double
md, Double
gd) <- GenIO
-> PitchClass
-> Cadence
-> [Int]
-> Double
-> IO (Double, Double, Double, Double)
computeFallbackScoreWithBoost GenIO
gen PitchClass
currentRoot Cadence
cad [Int]
t Double
boost
(Cadence, Double, Double, Double, Double)
-> IO (Cadence, Double, Double, Double, Double)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Cadence
cad, Double
score, Double
cd, Double
md, Double
gd)
) [[Int]]
triads
[(Cadence, Double, Double, Double, Double)]
-> IO [(Cadence, Double, Double, Double, Double)]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(Cadence, Double, Double, Double, Double)]
-> IO [(Cadence, Double, Double, Double, Double)])
-> [(Cadence, Double, Double, Double, Double)]
-> IO [(Cadence, Double, Double, Double, Double)]
forall a b. (a -> b) -> a -> b
$ ((Cadence, Double, Double, Double, Double)
-> (Cadence, Double, Double, Double, Double) -> Ordering)
-> [(Cadence, Double, Double, Double, Double)]
-> [(Cadence, Double, Double, Double, Double)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Down Double -> Down Double -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Down Double -> Down Double -> Ordering)
-> ((Cadence, Double, Double, Double, Double) -> Down Double)
-> (Cadence, Double, Double, Double, Double)
-> (Cadence, Double, Double, Double, Double)
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (\(Cadence
_, Double
s, Double
_, Double
_, Double
_) -> Double -> Down Double
forall a. a -> Down a
Down Double
s)) [(Cadence, Double, Double, Double, Double)]
results
triadToCadenceFrom :: P.PitchClass -> [Int] -> H.Cadence
triadToCadenceFrom :: PitchClass -> [Int] -> Cadence
triadToCadenceFrom PitchClass
currentRoot [Int]
pitches =
let triadRoot :: PitchClass
triadRoot = Int -> PitchClass
P.mkPitchClass ([Int] -> Int
forall a. HasCallStack => [a] -> a
head [Int]
pitches)
movement :: Movement
movement = PitchClass -> PitchClass -> Movement
H.toMovement PitchClass
currentRoot PitchClass
triadRoot
pcs :: [PitchClass]
pcs = [PitchClass] -> [PitchClass]
H.zeroFormPC ((Int -> PitchClass) -> [Int] -> [PitchClass]
forall a b. (a -> b) -> [a] -> [b]
map Int -> PitchClass
P.mkPitchClass [Int]
pitches)
functionality :: String
functionality = [PitchClass] -> String
H.toFunctionality [PitchClass]
pcs
in String -> Movement -> [PitchClass] -> Cadence
H.Cadence String
functionality Movement
movement [PitchClass]
pcs
computeFallbackScoreWithComponents :: P.PitchClass -> H.Cadence -> [Int] -> IO (Double, Double, Double, Double)
computeFallbackScoreWithComponents :: PitchClass
-> Cadence -> [Int] -> IO (Double, Double, Double, Double)
computeFallbackScoreWithComponents PitchClass
currentRoot Cadence
cad [Int]
triad = do
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
GenIO
-> PitchClass
-> Cadence
-> [Int]
-> IO (Double, Double, Double, Double)
computeFallbackScoreWith Gen RealWorld
GenIO
rng PitchClass
currentRoot Cadence
cad [Int]
triad
computeFallbackScoreWith :: GenIO -> P.PitchClass -> H.Cadence -> [Int] -> IO (Double, Double, Double, Double)
computeFallbackScoreWith :: GenIO
-> PitchClass
-> Cadence
-> [Int]
-> IO (Double, Double, Double, Double)
computeFallbackScoreWith GenIO
gen PitchClass
currentRoot Cadence
cad [Int]
triad =
GenIO
-> PitchClass
-> Cadence
-> [Int]
-> Double
-> IO (Double, Double, Double, Double)
computeFallbackScoreWithBoost GenIO
gen PitchClass
currentRoot Cadence
cad [Int]
triad Double
1.0
computeFallbackScoreWithBoost :: GenIO -> P.PitchClass -> H.Cadence -> [Int] -> Double -> IO (Double, Double, Double, Double)
computeFallbackScoreWithBoost :: GenIO
-> PitchClass
-> Cadence
-> [Int]
-> Double
-> IO (Double, Double, Double, Double)
computeFallbackScoreWithBoost GenIO
gen PitchClass
_currentRoot Cadence
cad [Int]
triad Double
boost = do
let chordDiss :: Double
chordDiss = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Int] -> Integer
dissonanceScore [Int]
triad) :: Double
interval :: Int
interval = Movement -> Int
extractMovementInterval (Cadence -> Movement
H.cadenceMovement Cadence
cad)
motionDiss :: Double
motionDiss = Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer
D.rootMotionScore Int
interval) :: Double
Double
gammaDraw <- Double -> Double -> Gen RealWorld -> IO Double
forall g (m :: * -> *).
StatefulGen g m =>
Double -> Double -> g -> m Double
Dist.gamma Double
1.01 Double
1.0 Gen RealWorld
GenIO
gen
let badness :: Double
badness = Double
chordDiss Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
motionDiss Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
gammaDraw Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.0) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
boost
finalScore :: Double
finalScore = Double
10000.0 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
badness
(Double, Double, Double, Double)
-> IO (Double, Double, Double, Double)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double
finalScore, Double
chordDiss, Double
motionDiss, Double
gammaDraw)
computeFallbackScore :: P.PitchClass -> H.Cadence -> [Int] -> IO Double
computeFallbackScore :: PitchClass -> Cadence -> [Int] -> IO Double
computeFallbackScore PitchClass
root Cadence
cad [Int]
triad = do
(Double
score, Double
_, Double
_, Double
_) <- PitchClass
-> Cadence -> [Int] -> IO (Double, Double, Double, Double)
computeFallbackScoreWithComponents PitchClass
root Cadence
cad [Int]
triad
Double -> IO Double
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Double
score
extractMovementInterval :: H.Movement -> Int
Movement
movement = case Movement
movement of
H.Asc PitchClass
pc -> Int -> Int
forall {a}. Integral a => a -> a
intervalClassFromPC (PitchClass -> Int
P.unPitchClass PitchClass
pc)
H.Desc PitchClass
pc -> Int -> Int
forall {a}. Integral a => a -> a
intervalClassFromPC (PitchClass -> Int
P.unPitchClass PitchClass
pc)
Movement
H.Unison -> Int
0
Movement
H.Tritone -> Int
6
where
intervalClassFromPC :: a -> a
intervalClassFromPC a
semitones =
let m :: a
m = a
semitones a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
12
in if a
m a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
6 then a
m else a
12 a -> a -> a
forall a. Num a => a -> a -> a
- a
m
applyDriftFilter :: Drift -> H.CadenceState -> [(H.Cadence, Double)] -> [(H.Cadence, Double)]
applyDriftFilter :: Drift -> CadenceState -> [(Cadence, Double)] -> [(Cadence, Double)]
applyDriftFilter Drift
Free CadenceState
_ [(Cadence, Double)]
pool = [(Cadence, Double)]
pool
applyDriftFilter Drift
direction CadenceState
currentState [(Cadence, Double)]
pool =
let currentDiss :: Integer
currentDiss = [Int] -> Integer
dissonanceScore
((PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
currentState)))
candidateDiss :: Cadence -> Integer
candidateDiss Cadence
cad = [Int] -> Integer
dissonanceScore ((PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (Cadence -> [PitchClass]
H.cadenceIntervals Cadence
cad))
predicate :: (Cadence, b) -> Bool
predicate = case Drift
direction of
Drift
Dissonant -> \(Cadence
cad, b
_) -> Cadence -> Integer
candidateDiss Cadence
cad Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
currentDiss
Drift
Consonant -> \(Cadence
cad, b
_) -> Cadence -> Integer
candidateDiss Cadence
cad Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
currentDiss
filtered :: [(Cadence, Double)]
filtered = ((Cadence, Double) -> Bool)
-> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Cadence, Double) -> Bool
forall {b}. (Cadence, b) -> Bool
predicate [(Cadence, Double)]
pool
in if [(Cadence, Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Cadence, Double)]
filtered then [(Cadence, Double)]
pool else [(Cadence, Double)]
filtered
fuseState :: GenIO
-> Double
-> ParsedContext
-> Maybe H.CadenceState
-> H.CadenceState
-> IO (H.CadenceState, Maybe FusionDiag)
fuseState :: GenIO
-> Double
-> ParsedContext
-> Maybe CadenceState
-> CadenceState
-> IO (CadenceState, Maybe FusionDiag)
fuseState GenIO
gen Double
ent ParsedContext
pctx Maybe CadenceState
mPrev CadenceState
triadState = do
let rootPC :: Int
rootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
triadState))
ivs :: [Int]
ivs = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
triadState))
absPCs :: IntSet
absPCs = [Int] -> IntSet
IntSet.fromList [ (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rootPC) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12 | Int
i <- [Int]
ivs ]
cands :: [Int]
cands = IntSet -> [Int]
IntSet.toList (ParsedContext -> IntSet
pcEffectiveOvertones ParsedContext
pctx IntSet -> IntSet -> IntSet
IntSet.\\ IntSet
absPCs)
if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
cands
then (CadenceState, Maybe FusionDiag)
-> IO (CadenceState, Maybe FusionDiag)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CadenceState
triadState, Maybe FusionDiag
forall a. Maybe a
Nothing)
else do
let fusedOf :: Int -> (Int, [Int], Integer)
fusedOf Int
x =
let interval :: Int
interval = (Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
rootPC) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12
zf :: [Int]
zf = [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort (Int
interval Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
ivs)
in (Int
x, [Int]
zf, [Int] -> Integer
dissonanceScore [Int]
zf)
scoredAll :: [(Int, [Int], Integer)]
scoredAll = (Int -> (Int, [Int], Integer)) -> [Int] -> [(Int, [Int], Integer)]
forall a b. (a -> b) -> [a] -> [b]
map Int -> (Int, [Int], Integer)
fusedOf [Int]
cands
prevDiss :: Maybe Integer
prevDiss = case Maybe CadenceState
mPrev of
Just CadenceState
prev | [PitchClass] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
prev)) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
3 ->
Integer -> Maybe Integer
forall a. a -> Maybe a
Just ([Int] -> Integer
dissonanceScore
((PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
prev))))
Maybe CadenceState
_ -> Maybe Integer
forall a. Maybe a
Nothing
drifted :: [(Int, [Int], Integer)]
drifted = case (ParsedContext -> Drift
pcDrift ParsedContext
pctx, Maybe Integer
prevDiss) of
(Drift
Consonant, Just Integer
d) -> ((Int, [Int], Integer) -> Bool)
-> [(Int, [Int], Integer)] -> [(Int, [Int], Integer)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Int
_, [Int]
_, Integer
ds) -> Integer
ds Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
d) [(Int, [Int], Integer)]
scoredAll
(Drift
Dissonant, Just Integer
d) -> ((Int, [Int], Integer) -> Bool)
-> [(Int, [Int], Integer)] -> [(Int, [Int], Integer)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Int
_, [Int]
_, Integer
ds) -> Integer
ds Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
d) [(Int, [Int], Integer)]
scoredAll
(Drift, Maybe Integer)
_ -> [(Int, [Int], Integer)]
scoredAll
pool :: [(Int, [Int], Integer)]
pool = if [(Int, [Int], Integer)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Int, [Int], Integer)]
drifted then [(Int, [Int], Integer)]
scoredAll else [(Int, [Int], Integer)]
drifted
ranked :: [(Int, [Int], Integer)]
ranked = ((Int, [Int], Integer) -> (Int, [Int], Integer) -> Ordering)
-> [(Int, [Int], Integer)] -> [(Int, [Int], Integer)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Integer -> Integer -> Ordering)
-> ((Int, [Int], Integer) -> Integer)
-> (Int, [Int], Integer)
-> (Int, [Int], Integer)
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (\(Int
_, [Int]
_, Integer
d) -> Integer
d)) [(Int, [Int], Integer)]
pool
Int
idx <- GenIO -> Double -> Int -> IO Int
gammaIndexScaledWith GenIO
gen Double
ent ([(Int, [Int], Integer)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, [Int], Integer)]
ranked)
let (Int
x, [Int]
zf, Integer
_) = [(Int, [Int], Integer)]
ranked [(Int, [Int], Integer)] -> Int -> (Int, [Int], Integer)
forall a. HasCallStack => [a] -> Int -> a
!! Int
idx
cad0 :: Cadence
cad0 = CadenceState -> Cadence
H.stateCadence CadenceState
triadState
fused0 :: CadenceState
fused0 = NoteName -> Movement -> [Int] -> CadenceState
H.mkCadenceStatePCs (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
triadState)
(Cadence -> Movement
H.cadenceMovement Cadence
cad0) [Int]
zf
fused :: CadenceState
fused = CadenceState
fused0 { H.stateSpelling = H.stateSpelling triadState }
name :: String
name = Cadence -> String
H.cadenceFunctionality (CadenceState -> Cadence
H.stateCadence CadenceState
fused)
(CadenceState, Maybe FusionDiag)
-> IO (CadenceState, Maybe FusionDiag)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CadenceState
fused, FusionDiag -> Maybe FusionDiag
forall a. a -> Maybe a
Just (Int -> String -> Int -> Int -> FusionDiag
FusionDiag Int
x String
name Int
idx ([(Int, [Int], Integer)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, [Int], Integer)]
ranked)))
applyPedalFilter :: ParsedContext -> H.CadenceState -> [(H.Cadence, Double)] -> [(H.Cadence, Double)]
applyPedalFilter :: ParsedContext
-> CadenceState -> [(Cadence, Double)] -> [(Cadence, Double)]
applyPedalFilter ParsedContext
pctx CadenceState
currentState [(Cadence, Double)]
pool
| IntSet -> Bool
IntSet.null IntSet
req Bool -> Bool -> Bool
&& IntSet -> Bool
IntSet.null IntSet
pref = [(Cadence, Double)]
pool
| Bool
otherwise =
let cadenceAbsPCs :: Cadence -> IntSet
cadenceAbsPCs Cadence
cadence =
let (Movement
movement, [PitchClass]
chord) = Cadence -> (Movement, [PitchClass])
H.deconstructCadence Cadence
cadence
prevRoot :: PitchClass
prevRoot = NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
currentState)
newRoot :: PitchClass
newRoot = case Movement
movement of
Movement
H.Unison -> PitchClass
prevRoot
Movement
H.Tritone -> Int -> PitchClass -> PitchClass
P.transpose Int
6 PitchClass
prevRoot
H.Asc PitchClass
pc -> Int -> PitchClass -> PitchClass
P.transpose (PitchClass -> Int
P.unPitchClass PitchClass
pc) PitchClass
prevRoot
H.Desc PitchClass
pc -> Int -> PitchClass -> PitchClass
P.transpose (Int -> Int
forall a. Num a => a -> a
negate (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ PitchClass -> Int
P.unPitchClass PitchClass
pc) PitchClass
prevRoot
Movement
H.Empty -> PitchClass
prevRoot
rootInt :: Int
rootInt = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (PitchClass -> Int
P.unPitchClass PitchClass
newRoot)
chordInts :: [Int]
chordInts = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> (PitchClass -> Int) -> PitchClass -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PitchClass -> Int
P.unPitchClass) [PitchClass]
chord
in [Int] -> IntSet
IntSet.fromList ([Int] -> IntSet) -> [Int] -> IntSet
forall a b. (a -> b) -> a -> b
$ (Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
i -> (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rootInt) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
chordInts
combined :: IntSet
combined = IntSet -> IntSet -> IntSet
IntSet.union IntSet
req IntSet
pref
reqFiltered :: [(Cadence, Double)]
reqFiltered = ((Cadence, Double) -> Bool)
-> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. (a -> Bool) -> [a] -> [a]
filter (IntSet -> IntSet -> Bool
IntSet.isSubsetOf IntSet
req (IntSet -> Bool)
-> ((Cadence, Double) -> IntSet) -> (Cadence, Double) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cadence -> IntSet
cadenceAbsPCs (Cadence -> IntSet)
-> ((Cadence, Double) -> Cadence) -> (Cadence, Double) -> IntSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, Double) -> Cadence
forall a b. (a, b) -> a
fst) [(Cadence, Double)]
pool
combFiltered :: [(Cadence, Double)]
combFiltered = ((Cadence, Double) -> Bool)
-> [(Cadence, Double)] -> [(Cadence, Double)]
forall a. (a -> Bool) -> [a] -> [a]
filter (IntSet -> IntSet -> Bool
IntSet.isSubsetOf IntSet
combined (IntSet -> Bool)
-> ((Cadence, Double) -> IntSet) -> (Cadence, Double) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cadence -> IntSet
cadenceAbsPCs (Cadence -> IntSet)
-> ((Cadence, Double) -> Cadence) -> (Cadence, Double) -> IntSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, Double) -> Cadence
forall a b. (a, b) -> a
fst) [(Cadence, Double)]
pool
result :: [(Cadence, Double)]
result
| IntSet -> Bool
IntSet.null IntSet
pref = [(Cadence, Double)]
reqFiltered
| [(Cadence, Double)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Cadence, Double)]
combFiltered Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
minPedalPool = [(Cadence, Double)]
combFiltered
| Bool -> Bool
not ([(Cadence, Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Cadence, Double)]
reqFiltered) = [(Cadence, Double)]
reqFiltered
| Bool
otherwise = [(Cadence, Double)]
pool
in [(Cadence, Double)]
result
where
req :: IntSet
req = ParsedContext -> IntSet
pcPedalRequired ParsedContext
pctx
pref :: IntSet
pref = ParsedContext -> IntSet
pcPedalPreferred ParsedContext
pctx
minPedalPool :: Int
minPedalPool :: Int
minPedalPool = Int
10
applyRConstraints :: HarmonicContext
-> H.CadenceState
-> [(H.Cadence, ComposerWeights)]
-> [(H.Cadence, ComposerWeights)]
applyRConstraints :: HarmonicContext
-> CadenceState
-> [(Cadence, ComposerWeights)]
-> [(Cadence, ComposerWeights)]
applyRConstraints HarmonicContext
context CadenceState
currentState = ((Cadence, ComposerWeights) -> Bool)
-> [(Cadence, ComposerWeights)] -> [(Cadence, ComposerWeights)]
forall a. (a -> Bool) -> [a] -> [a]
filter (HarmonicContext -> CadenceState -> Cadence -> Bool
matchesContext HarmonicContext
context CadenceState
currentState (Cadence -> Bool)
-> ((Cadence, ComposerWeights) -> Cadence)
-> (Cadence, ComposerWeights)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, ComposerWeights) -> Cadence
forall a b. (a, b) -> a
fst)
matchesContext :: HarmonicContext -> H.CadenceState -> H.Cadence -> Bool
matchesContext :: HarmonicContext -> CadenceState -> Cadence -> Bool
matchesContext HarmonicContext
context CadenceState
currentState Cadence
cadence =
let (Movement
movement, [PitchClass]
chord) = Cadence -> (Movement, [PitchClass])
H.deconstructCadence Cadence
cadence
rawOvertones :: [Int]
rawOvertones = Int -> Text -> [Int]
parseOvertones' Int
3 (HarmonicContext -> Text
_hcOvertones HarmonicContext
context)
keyPcs :: [Int]
keyPcs = Text -> [Int]
parseKey (HarmonicContext -> Text
_hcKey HarmonicContext
context)
effectiveOvertones :: [Int]
effectiveOvertones = if Text -> Bool
isWildcard (HarmonicContext -> Text
_hcKey HarmonicContext
context)
then [Int]
rawOvertones
else (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
keyPcs) [Int]
rawOvertones
allowedBassNotes :: [Int]
allowedBassNotes = Text -> Text -> Text -> [Int]
resolveRoots (HarmonicContext -> Text
_hcOvertones HarmonicContext
context) (HarmonicContext -> Text
_hcKey HarmonicContext
context) (HarmonicContext -> Text
_hcRoots HarmonicContext
context)
prevRoot :: PitchClass
prevRoot = NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
currentState)
currentRoot :: PitchClass
currentRoot = case Movement
movement of
Movement
H.Unison -> PitchClass
prevRoot
Movement
H.Tritone -> Int -> PitchClass -> PitchClass
P.transpose Int
6 PitchClass
prevRoot
H.Asc PitchClass
pc -> Int -> PitchClass -> PitchClass
P.transpose (PitchClass -> Int
P.unPitchClass PitchClass
pc) PitchClass
prevRoot
H.Desc PitchClass
pc -> Int -> PitchClass -> PitchClass
P.transpose (Int -> Int
forall a. Num a => a -> a
negate (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ PitchClass -> Int
P.unPitchClass PitchClass
pc) PitchClass
prevRoot
Movement
H.Empty -> PitchClass
prevRoot
chordInts :: [Int]
chordInts = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> (PitchClass -> Int) -> PitchClass -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PitchClass -> Int
P.unPitchClass) [PitchClass]
chord
currentRootInt :: Int
currentRootInt = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (PitchClass -> Int
P.unPitchClass PitchClass
currentRoot)
absolutePitches :: [Int]
absolutePitches = (Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
interval -> (Int
interval Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
currentRootInt) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
chordInts
bassInt :: Int
bassInt = if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
absolutePitches then Int
0 else [Int] -> Int
forall a. HasCallStack => [a] -> a
head [Int]
absolutePitches
overtonesMatch :: Bool
overtonesMatch = (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
effectiveOvertones) [Int]
absolutePitches
bassMatch :: Bool
bassMatch = Text -> Bool
isWildcard (HarmonicContext -> Text
_hcRoots HarmonicContext
context)
Bool -> Bool -> Bool
|| Int
bassInt Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int]
allowedBassNotes
in Bool
overtonesMatch Bool -> Bool -> Bool
&& Bool
bassMatch
applyRConstraintsParsed :: ParsedContext
-> H.CadenceState
-> [(H.Cadence, ComposerWeights)]
-> [(H.Cadence, ComposerWeights)]
applyRConstraintsParsed :: ParsedContext
-> CadenceState
-> [(Cadence, ComposerWeights)]
-> [(Cadence, ComposerWeights)]
applyRConstraintsParsed ParsedContext
pctx CadenceState
currentState = ((Cadence, ComposerWeights) -> Bool)
-> [(Cadence, ComposerWeights)] -> [(Cadence, ComposerWeights)]
forall a. (a -> Bool) -> [a] -> [a]
filter (ParsedContext -> CadenceState -> Cadence -> Bool
matchesContextParsed ParsedContext
pctx CadenceState
currentState (Cadence -> Bool)
-> ((Cadence, ComposerWeights) -> Cadence)
-> (Cadence, ComposerWeights)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, ComposerWeights) -> Cadence
forall a b. (a, b) -> a
fst)
applyRConstraintsWithTarget :: Maybe Int
-> ParsedContext
-> H.CadenceState
-> [(H.Cadence, ComposerWeights)]
-> [(H.Cadence, ComposerWeights)]
applyRConstraintsWithTarget :: Maybe Int
-> ParsedContext
-> CadenceState
-> [(Cadence, ComposerWeights)]
-> [(Cadence, ComposerWeights)]
applyRConstraintsWithTarget Maybe Int
bassTarget ParsedContext
pctx CadenceState
currentState =
((Cadence, ComposerWeights) -> Bool)
-> [(Cadence, ComposerWeights)] -> [(Cadence, ComposerWeights)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Maybe Int -> ParsedContext -> CadenceState -> Cadence -> Bool
matchesContextWithTarget Maybe Int
bassTarget ParsedContext
pctx CadenceState
currentState (Cadence -> Bool)
-> ((Cadence, ComposerWeights) -> Cadence)
-> (Cadence, ComposerWeights)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cadence, ComposerWeights) -> Cadence
forall a b. (a, b) -> a
fst)
matchesContextParsed :: ParsedContext -> H.CadenceState -> H.Cadence -> Bool
matchesContextParsed :: ParsedContext -> CadenceState -> Cadence -> Bool
matchesContextParsed = Maybe Int -> ParsedContext -> CadenceState -> Cadence -> Bool
matchesContextWithTarget Maybe Int
forall a. Maybe a
Nothing
matchesContextWithTarget :: Maybe Int -> ParsedContext -> H.CadenceState -> H.Cadence -> Bool
matchesContextWithTarget :: Maybe Int -> ParsedContext -> CadenceState -> Cadence -> Bool
matchesContextWithTarget Maybe Int
bassTarget ParsedContext
pctx CadenceState
currentState Cadence
cadence =
let (Movement
movement, [PitchClass]
chord) = Cadence -> (Movement, [PitchClass])
H.deconstructCadence Cadence
cadence
prevRoot :: PitchClass
prevRoot = NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
currentState)
currentRoot :: PitchClass
currentRoot = case Movement
movement of
Movement
H.Unison -> PitchClass
prevRoot
Movement
H.Tritone -> Int -> PitchClass -> PitchClass
P.transpose Int
6 PitchClass
prevRoot
H.Asc PitchClass
pc -> Int -> PitchClass -> PitchClass
P.transpose (PitchClass -> Int
P.unPitchClass PitchClass
pc) PitchClass
prevRoot
H.Desc PitchClass
pc -> Int -> PitchClass -> PitchClass
P.transpose (Int -> Int
forall a. Num a => a -> a
negate (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ PitchClass -> Int
P.unPitchClass PitchClass
pc) PitchClass
prevRoot
Movement
H.Empty -> PitchClass
prevRoot
chordInts :: [Int]
chordInts = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> (PitchClass -> Int) -> PitchClass -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PitchClass -> Int
P.unPitchClass) [PitchClass]
chord
currentRootInt :: Int
currentRootInt = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (PitchClass -> Int
P.unPitchClass PitchClass
currentRoot)
absolutePitches :: [Int]
absolutePitches = (Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
interval -> (Int
interval Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
currentRootInt) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
chordInts
bassInt :: Int
bassInt = if [Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
absolutePitches then Int
0 else [Int] -> Int
forall a. HasCallStack => [a] -> a
head [Int]
absolutePitches
pitchesToCheck :: [Int]
pitchesToCheck
| ParsedContext -> Bool
pcStrictContainment ParsedContext
pctx = [Int]
absolutePitches
| Bool
otherwise = case Maybe Int
bassTarget of
Just Int
target -> (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
target) [Int]
absolutePitches
Maybe Int
Nothing -> [Int]
absolutePitches
overtonesMatch :: Bool
overtonesMatch = (Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Int -> IntSet -> Bool
`IntSet.member` ParsedContext -> IntSet
pcEffectiveOvertones ParsedContext
pctx) [Int]
pitchesToCheck
bassMatch :: Bool
bassMatch = case Maybe Int
bassTarget of
Just Int
target -> Int
bassInt Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
target
Maybe Int
Nothing -> ParsedContext -> Bool
pcIsRootsWild ParsedContext
pctx
Bool -> Bool -> Bool
|| Int
bassInt Int -> IntSet -> Bool
`IntSet.member` ParsedContext -> IntSet
pcAllowedBassNotes ParsedContext
pctx
in Bool
overtonesMatch Bool -> Bool -> Bool
&& Bool
bassMatch
advanceState :: H.CadenceState -> H.Cadence -> H.CadenceState
advanceState :: CadenceState -> Cadence -> CadenceState
advanceState CadenceState
currentState Cadence
newCadence =
(CadenceState, AdvanceTrace) -> CadenceState
forall a b. (a, b) -> a
fst ((CadenceState, AdvanceTrace) -> CadenceState)
-> (CadenceState, AdvanceTrace) -> CadenceState
forall a b. (a -> b) -> a -> b
$ Maybe EnharmonicSpelling
-> CadenceState -> Cadence -> (CadenceState, AdvanceTrace)
advanceStateTraced Maybe EnharmonicSpelling
forall a. Maybe a
Nothing CadenceState
currentState Cadence
newCadence
advanceStateTraced :: Maybe H.EnharmonicSpelling -> H.CadenceState -> H.Cadence -> (H.CadenceState, AdvanceTrace)
advanceStateTraced :: Maybe EnharmonicSpelling
-> CadenceState -> Cadence -> (CadenceState, AdvanceTrace)
advanceStateTraced Maybe EnharmonicSpelling
keyBias CadenceState
currentState Cadence
newCadence =
let currentRoot :: NoteName
currentRoot = CadenceState -> NoteName
H.stateCadenceRoot CadenceState
currentState
currentRootPC :: PitchClass
currentRootPC = NoteName -> PitchClass
P.pitchClass NoteName
currentRoot
movement :: Movement
movement = Cadence -> Movement
H.cadenceMovement Cadence
newCadence
movementInterval :: PitchClass
movementInterval = Movement -> PitchClass
H.fromMovement Movement
movement
newRootPC :: PitchClass
newRootPC = PitchClass
currentRootPC PitchClass -> PitchClass -> PitchClass
forall a. Num a => a -> a -> a
+ PitchClass
movementInterval
tones :: [Int]
tones = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass ([PitchClass] -> [Int]) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> a -> b
$ Cadence -> [PitchClass]
H.cadenceIntervals Cadence
newCadence
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
P.unPitchClass PitchClass
newRootPC) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
tones
inferredSpelling :: EnharmonicSpelling
inferredSpelling = [Int] -> EnharmonicSpelling
H.inferSpelling [Int]
absolutePitches
newSpelling :: EnharmonicSpelling
newSpelling = case Maybe EnharmonicSpelling
keyBias of
Just EnharmonicSpelling
ks -> EnharmonicSpelling
ks
Maybe EnharmonicSpelling
Nothing
| PitchClass
newRootPC PitchClass -> PitchClass -> Bool
forall a. Eq a => a -> a -> Bool
== PitchClass
currentRootPC -> CadenceState -> EnharmonicSpelling
H.stateSpelling CadenceState
currentState
| [Int] -> Bool
H.isAmbiguousPattern [Int]
absolutePitches -> CadenceState -> EnharmonicSpelling
H.stateSpelling CadenceState
currentState
| Bool
otherwise -> EnharmonicSpelling
inferredSpelling
newRoot :: NoteName
newRoot = EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
newSpelling PitchClass
newRootPC
newState :: CadenceState
newState = Cadence -> NoteName -> EnharmonicSpelling -> CadenceState
H.CadenceState Cadence
newCadence NoteName
newRoot EnharmonicSpelling
newSpelling
enharmName :: String
enharmName = case EnharmonicSpelling
newSpelling of
EnharmonicSpelling
H.FlatSpelling -> String
"flat"
EnharmonicSpelling
H.SharpSpelling -> String
"sharp"
trace :: AdvanceTrace
trace = AdvanceTrace
{ atCurrentRoot :: String
atCurrentRoot = NoteName -> String
forall a. Show a => a -> String
show NoteName
currentRoot
, atCurrentRootPC :: Int
atCurrentRootPC = PitchClass -> Int
P.unPitchClass PitchClass
currentRootPC
, atMovement :: String
atMovement = Movement -> String
forall a. Show a => a -> String
show Movement
movement
, atMovementInterval :: Int
atMovementInterval = PitchClass -> Int
P.unPitchClass PitchClass
movementInterval
, atNewRootPC :: Int
atNewRootPC = PitchClass -> Int
P.unPitchClass PitchClass
newRootPC
, atEnharmFunc :: String
atEnharmFunc = String
enharmName
, atNewRoot :: String
atNewRoot = NoteName -> String
forall a. Show a => a -> String
show NoteName
newRoot
}
in (CadenceState
newState, AdvanceTrace
trace)
extractCadence :: H.CadenceState -> H.Cadence
= CadenceState -> Cadence
H.stateCadence
chainToProgression :: [H.CadenceState] -> Prog.Progression
chainToProgression :: [CadenceState] -> Progression
chainToProgression = [CadenceState] -> Progression
Prog.fromCadenceStates