{-# LANGUAGE OverloadedStrings #-}
module Harmonic.Framework.Builder
(
gen
, gen'
, gen''
, genGrid
, gen4
, gen4'
, gen4''
, quad
, genFrom
, genFrom'
, genFrom''
, genP
, genP'
, genP''
, genI, genII, genIII, genIV, genV, genVI, genVII, genVIII, genIX, genX, genXI
, genI', genII', genIII', genIV', genV', genVI', genVII', genVIII', genIX', genX', genXI'
, genI'', genII'', genIII'', genIV'', genV'', genVI'', genVII'', genVIII'', genIX'', genX'', genXI''
, cue
, len
, seek
, entropy
, tonal
, relStrata
, absStrata
, sameBoost
, flipBoost
, triBoost
, attempt
, viability
, GenConfig(..)
, GenMode(..)
, Verbosity(..)
, defaultGenConfig
, execGenConfig
, execGenConfigPC
, generate
, generateWith
, genWith
, generate'
, genWith'
, generate''
, genWith''
, genPrint
, genPrint'
, genPrint''
, genSilent
, genSilent'
, genStandard
, genStandard'
, genVerbose
, genVerbose'
, printDiagnostics
, StepDiagnostic(..)
, GenerationDiagnostics(..)
, TransformTrace(..)
, AdvanceTrace(..)
, HarmonicContext(..)
, harmonicContext
, hContext
, Drift(..)
, hcOvertones
, hcKey
, hcRoots
, dissonant
, consonant
, invSkip
, hcPedal
, hcTristrata
, GeneratorConfig(..)
, defaultConfig
, matchesContext
, parseComposersWithOrder
, makePortmanteau
, extractByPosition
, takeFromBeginning
, takeFromEnd
, takeFromMiddle
, printHeader
) where
import qualified Database.Bolt as Bolt
import qualified Data.Text as T
import Data.Text (Text)
import Control.Monad (forM_, when)
import Data.Char (toLower)
import Data.List (intercalate)
import System.Random.MWC (GenIO, createSystemRandom, uniformRM)
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 qualified Harmonic.Rules.Types.ProgressionContext as PC
import qualified Harmonic.Rules.Types.Scale as Sc
import Harmonic.Rules.Import.Graph (connectNeo4j)
import qualified Harmonic.Evaluation.Database.Query as Q
import qualified Harmonic.Evaluation.Scoring.Progression as PS
import Control.Monad.IO.Class (liftIO)
import Harmonic.Rules.Constraints.Filter (parseTuningNamed, isWildcard)
import Harmonic.Rules.Constraints.Overtone (formatOvertoneAnnotation, formatOvertoneAnnotationPipe, possibleTriads)
import Data.Foldable (toList)
import Data.List (intercalate, sort, nub)
import Data.Maybe (fromMaybe)
import qualified Data.IntSet as IntSet
import qualified Data.Sequence as Seq
import Harmonic.Framework.Builder.Types
import Harmonic.Framework.Builder.Portmanteau
import Harmonic.Framework.Builder.Diagnostics
import Harmonic.Framework.Builder.Core
import qualified Harmonic.Framework.Builder.Strata as Strata
composerModeStr :: String -> String
composerModeStr :: [Char] -> [Char]
composerModeStr [Char]
s
| (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
s [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"none" = [Char]
"Mode: offline (fallback only — no graph)"
| [Char]
s [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"*" = [Char]
"Mode: online (composers: all)"
| Bool
otherwise = [Char]
"Mode: online (composers: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
names [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
where
names :: [Char]
names = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
", " (((Text, Double) -> [Char]) -> [(Text, Double)] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> [Char]
T.unpack (Text -> [Char])
-> ((Text, Double) -> Text) -> (Text, Double) -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, Double) -> Text
forall a b. (a, b) -> a
fst) (Text -> [(Text, Double)]
parseComposersWithOrder ([Char] -> Text
T.pack [Char]
s)))
generate :: H.CadenceState
-> Int
-> Text
-> Double
-> HarmonicContext
-> IO Prog.Progression
generate :: CadenceState
-> Int -> Text -> Double -> HarmonicContext -> IO Progression
generate CadenceState
start Int
len Text
composerStr Double
entropy HarmonicContext
context =
GeneratorConfig
-> CadenceState
-> Int
-> Text
-> Double
-> HarmonicContext
-> IO Progression
generateWith GeneratorConfig
defaultConfig CadenceState
start Int
len Text
composerStr Double
entropy HarmonicContext
context
genPrint :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genPrint :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genPrint CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
_diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
[Char] -> IO ()
putStrLn [Char]
""
Text -> Double -> HarmonicContext -> IO ()
printHeader ([Char] -> Text
T.pack [Char]
composerStr) Double
entropy HarmonicContext
ctx
Progression -> IO ()
forall a. Show a => a -> IO ()
print Progression
prog
[Char] -> IO ()
putStrLn [Char]
""
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
genWith :: GeneratorConfig -> H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genWith :: GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO Progression
genWith GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = GeneratorConfig
-> CadenceState
-> Int
-> Text
-> Double
-> HarmonicContext
-> IO Progression
generateWith GeneratorConfig
config CadenceState
start Int
len ([Char] -> Text
T.pack [Char]
composerStr) Double
entropy HarmonicContext
ctx
generateWith :: GeneratorConfig
-> H.CadenceState
-> Int
-> Text
-> Double
-> HarmonicContext
-> IO Prog.Progression
generateWith :: GeneratorConfig
-> CadenceState
-> Int
-> Text
-> Double
-> HarmonicContext
-> IO Progression
generateWith GeneratorConfig
config CadenceState
start Int
len Text
composerStr Double
entropy HarmonicContext
context = do
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
context
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
[CadenceState]
chain <- if (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (Text -> [Char]
T.unpack Text
composerStr) [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"none"
then GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> CadenceState
-> Int
-> IO [CadenceState]
buildChainOffline GeneratorConfig
config Gen RealWorld
GenIO
rng Double
entropy HarmonicContext
context ParsedContext
pctx CadenceState
start (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
else do
let composerWeights :: ComposerWeights
composerWeights = Text -> ComposerWeights
Q.parseComposerWeights Text
composerStr
Pipe
pipe <- IO Pipe
connectNeo4j
[CadenceState]
result <- Pipe -> BoltActionT IO [CadenceState] -> IO [CadenceState]
forall (m :: * -> *) a.
(MonadIO m, HasCallStack) =>
Pipe -> BoltActionT m a -> m a
Bolt.run Pipe
pipe (BoltActionT IO [CadenceState] -> IO [CadenceState])
-> BoltActionT IO [CadenceState] -> IO [CadenceState]
forall a b. (a -> b) -> a -> b
$ GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO [CadenceState]
buildChain GeneratorConfig
config Gen RealWorld
GenIO
rng Double
entropy HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
Pipe -> IO ()
forall (m :: * -> *). (MonadIO m, HasCallStack) => Pipe -> m ()
Bolt.close Pipe
pipe
[CadenceState] -> IO [CadenceState]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [CadenceState]
result
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Progression -> IO Progression) -> Progression -> IO Progression
forall a b. (a -> b) -> a -> b
$ [CadenceState] -> Progression
chainToProgression [CadenceState]
chain
generate' :: H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO (Prog.Progression, GenerationDiagnostics)
generate' :: CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx =
GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
defaultConfig CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
genPrint' :: H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO Prog.Progression
genPrint' :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genPrint' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
[Char] -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps [Char]
composerStr HarmonicContext
ctx GenerationDiagnostics
diag
[Char] -> IO ()
putStrLn [Char]
""
Text -> Double -> HarmonicContext -> IO ()
printHeader ([Char] -> Text
T.pack [Char]
composerStr) Double
entropy HarmonicContext
ctx
Progression -> IO ()
forall a. Show a => a -> IO ()
print Progression
prog
[Char] -> IO ()
putStrLn [Char]
""
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
renderStandardSteps :: String -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps :: [Char] -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps [Char]
composerStr HarmonicContext
ctx GenerationDiagnostics
diag = do
let tuningNames :: [([Char], Int)]
tuningNames = Text -> [([Char], Int)]
parseTuningNamed (HarmonicContext -> Text
_hcOvertones HarmonicContext
ctx)
hasAnnotation :: Bool
hasAnnotation = Bool -> Bool
not ([([Char], Int)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [([Char], Int)]
tuningNames)
allStates :: [CadenceState]
allStates = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression (GenerationDiagnostics -> Progression
gdProgression GenerationDiagnostics
diag))
annotateState :: CadenceState -> [Char]
annotateState CadenceState
cs =
let rootPC :: Int
rootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
cs))
intervals :: [Int]
intervals = (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
cs))
absPitches :: [Int]
absPitches = (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
rootPC) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12) [Int]
intervals
spelling :: EnharmonicSpelling
spelling = CadenceState -> EnharmonicSpelling
H.stateSpelling CadenceState
cs
pcName :: Int -> [Char]
pcName Int
pc = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
spelling (Int -> PitchClass
P.mkPitchClass Int
pc))
in [([Char], Int)] -> [Int] -> (Int -> [Char]) -> [Char]
formatOvertoneAnnotationPipe [([Char], Int)]
tuningNames [Int]
absPitches Int -> [Char]
pcName
[Char] -> IO ()
putStrLn [Char]
""
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Generation: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartRoot GenerationDiagnostics
diag [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartCadence GenerationDiagnostics
diag
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (GenerationDiagnostics -> Int
gdActualLen GenerationDiagnostics
diag) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" chords (entropy " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show (GenerationDiagnostics -> Double
gdEntropy GenerationDiagnostics
diag) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
composerModeStr [Char]
composerStr
[Char] -> IO ()
putStrLn [Char]
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
let bar1Suffix :: [Char]
bar1Suffix = if Bool
hasAnnotation Bool -> Bool -> Bool
&& Bool -> Bool
not ([CadenceState] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CadenceState]
allStates)
then let ann :: [Char]
ann = CadenceState -> [Char]
annotateState ([CadenceState] -> CadenceState
forall a. HasCallStack => [a] -> a
head [CadenceState]
allStates)
in if [Char] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
ann then [Char]
"" else [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
ann
else [Char]
""
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" 1: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartRoot GenerationDiagnostics
diag [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartCadence GenerationDiagnostics
diag
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" [starting state]" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
bar1Suffix
[Char] -> IO ()
putStrLn [Char]
""
[StepDiagnostic] -> (StepDiagnostic -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (GenerationDiagnostics -> [StepDiagnostic]
gdSteps GenerationDiagnostics
diag) ((StepDiagnostic -> IO ()) -> IO ())
-> (StepDiagnostic -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \StepDiagnostic
step -> do
let barNum :: Int
barNum = StepDiagnostic -> Int
sdStepNumber StepDiagnostic
step Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
stateInfo :: [Char]
stateInfo = StepDiagnostic -> [Char]
sdPriorRoot StepDiagnostic
step [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StepDiagnostic -> [Char]
sdPosteriorRoot StepDiagnostic
step
poolInfo :: [Char]
poolInfo = [Char]
"[" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdGraphCount StepDiagnostic
step) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"G/"
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdFallbackCount StepDiagnostic
step) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"F]"
mvmt :: [Char]
mvmt = StepDiagnostic -> [Char]
sdSelectedDbMovement StepDiagnostic
step
chord :: [Char]
chord = case StepDiagnostic -> Maybe [Char]
sdRenderedChord StepDiagnostic
step of
Just [Char]
c -> [Char]
c
Maybe [Char]
Nothing -> StepDiagnostic -> [Char]
sdPosteriorRoot StepDiagnostic
step
src :: [Char]
src = [Char]
"[" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StepDiagnostic -> [Char]
sdSelectedFrom StepDiagnostic
step [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]"
selIdx :: [Char]
selIdx = [Char]
"γ=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdGammaIndex StepDiagnostic
step)
let overtoneSuffix :: [Char]
overtoneSuffix =
if Bool
hasAnnotation
then let stateIdx :: Int
stateIdx = Int
barNum Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
in if Int
stateIdx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
stateIdx Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
allStates
then let ann :: [Char]
ann = CadenceState -> [Char]
annotateState ([CadenceState]
allStates [CadenceState] -> Int -> CadenceState
forall a. HasCallStack => [a] -> Int -> a
!! Int
stateIdx)
in if [Char] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
ann then [Char]
"" else [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
ann
else [Char]
""
else [Char]
""
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
barNum [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
stateInfo [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
poolInfo
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
mvmt [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
chord [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
src [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
selIdx
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
overtoneSuffix
let posteriorRootPC :: Int
posteriorRootPC = StepDiagnostic -> Int
sdPosteriorRootPC StepDiagnostic
step
renderCandidateName :: [Char] -> [Char]
renderCandidateName [Char]
name =
case [Char] -> Int -> Maybe [Char]
parseCadenceFromString [Char]
name Int
posteriorRootPC of
Just [Char]
renderedName -> [Char]
renderedName
Maybe [Char]
Nothing -> [Char]
name
let topCands :: [([Char], Double)]
topCands = if StepDiagnostic -> [Char]
sdSelectedFrom StepDiagnostic
step [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"graph"
then Int -> [([Char], Double)] -> [([Char], Double)]
forall a. Int -> [a] -> [a]
take Int
6 (StepDiagnostic -> [([Char], Double)]
sdGraphTop6 StepDiagnostic
step)
else Int -> [([Char], Double)] -> [([Char], Double)]
forall a. Int -> [a] -> [a]
take Int
6 [([Char]
n, Double
s) | ([Char]
n, Double
s, Double
_, Double
_, Double
_) <- StepDiagnostic -> [([Char], Double, Double, Double, Double)]
sdFallbackTop6 StepDiagnostic
step]
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not ([([Char], Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [([Char], Double)]
topCands)) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
let candNames :: [[Char]]
candNames = [[Char] -> [Char]
renderCandidateName [Char]
name | ([Char]
name, Double
_) <- [([Char], Double)]
topCands]
candStr :: [Char]
candStr = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
" | " [[Char]]
candNames
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" Candidates: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
candStr
case StepDiagnostic -> Maybe FusionDiag
sdFusion StepDiagnostic
step of
Just FusionDiag
fd -> do
let spelling :: EnharmonicSpelling
spelling = case Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression (GenerationDiagnostics -> Progression
gdProgression GenerationDiagnostics
diag)) of
[CadenceState]
css | Int
barNum Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< [CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
css -> CadenceState -> EnharmonicSpelling
H.stateSpelling ([CadenceState]
css [CadenceState] -> Int -> CadenceState
forall a. HasCallStack => [a] -> Int -> a
!! (Int
barNum Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
[CadenceState]
_ -> EnharmonicSpelling
H.FlatSpelling
toneName :: [Char]
toneName = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
spelling (Int -> PitchClass
P.mkPitchClass (FusionDiag -> Int
fdAddedPC FusionDiag
fd)))
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" fused: +" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
toneName
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StepDiagnostic -> [Char]
sdPosteriorRoot StepDiagnostic
step [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ FusionDiag -> [Char]
fdFusedName FusionDiag
fd
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" [rank " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (FusionDiag -> Int
fdGammaIdx FusionDiag
fd Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (FusionDiag -> Int
fdPoolK FusionDiag
fd) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]"
Maybe FusionDiag
Nothing -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
[Char] -> IO ()
putStrLn [Char]
""
[Char] -> IO ()
putStrLn [Char]
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
genWith' :: GeneratorConfig -> H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO (Prog.Progression, GenerationDiagnostics)
genWith' :: GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
context = do
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
context
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
([CadenceState]
chain, [StepDiagnostic]
stepDiags) <- if (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
composerStr [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"none"
then GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> CadenceState
-> Int
-> IO ([CadenceState], [StepDiagnostic])
buildChainOfflineWithDiag GeneratorConfig
config Gen RealWorld
GenIO
rng Double
entropy HarmonicContext
context ParsedContext
pctx CadenceState
start (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
else do
let composerWeights :: ComposerWeights
composerWeights = Text -> ComposerWeights
Q.parseComposerWeights ([Char] -> Text
T.pack [Char]
composerStr)
Pipe
pipe <- IO Pipe
connectNeo4j
([CadenceState], [StepDiagnostic])
result <- Pipe
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall (m :: * -> *) a.
(MonadIO m, HasCallStack) =>
Pipe -> BoltActionT m a -> m a
Bolt.run Pipe
pipe (BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic]))
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a b. (a -> b) -> a -> b
$ GeneratorConfig
-> GenIO
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildChainWithDiag GeneratorConfig
config Gen RealWorld
GenIO
rng Double
entropy HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
Pipe -> IO ()
forall (m :: * -> *). (MonadIO m, HasCallStack) => Pipe -> m ()
Bolt.close Pipe
pipe
([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState], [StepDiagnostic])
result
let prog :: Progression
prog = [CadenceState] -> Progression
chainToProgression [CadenceState]
chain
diag :: GenerationDiagnostics
diag = GenerationDiagnostics
{ gdStartCadence :: [Char]
gdStartCadence = Cadence -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> Cadence
extractCadence CadenceState
start)
, gdStartRoot :: [Char]
gdStartRoot = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start)
, gdRequestedLen :: Int
gdRequestedLen = Int
len
, gdActualLen :: Int
gdActualLen = Progression -> Int
Prog.progLength Progression
prog
, gdEntropy :: Double
gdEntropy = Double
entropy
, gdSteps :: [StepDiagnostic]
gdSteps = [StepDiagnostic]
stepDiags
, gdProgression :: Progression
gdProgression = Progression
prog
}
(Progression, GenerationDiagnostics)
-> IO (Progression, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Progression
prog, GenerationDiagnostics
diag)
generate'' :: H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO (Prog.Progression, GenerationDiagnostics)
generate'' :: CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate'' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx =
GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith'' GeneratorConfig
defaultConfig CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
genPrint'' :: H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO Prog.Progression
genPrint'' :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genPrint'' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate'' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
[Char] -> GenerationDiagnostics -> IO ()
renderVerboseSteps [Char]
composerStr GenerationDiagnostics
diag
[Char] -> IO ()
putStrLn [Char]
""
Text -> Double -> HarmonicContext -> IO ()
printHeader ([Char] -> Text
T.pack [Char]
composerStr) Double
entropy HarmonicContext
ctx
Progression -> IO ()
forall a. Show a => a -> IO ()
print Progression
prog
[Char] -> IO ()
putStrLn [Char]
""
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
renderVerboseSteps :: String -> GenerationDiagnostics -> IO ()
renderVerboseSteps :: [Char] -> GenerationDiagnostics -> IO ()
renderVerboseSteps [Char]
composerStr GenerationDiagnostics
diag = do
[Char] -> IO ()
putStrLn [Char]
""
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Verbose Generation: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartRoot GenerationDiagnostics
diag [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartCadence GenerationDiagnostics
diag
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (GenerationDiagnostics -> Int
gdActualLen GenerationDiagnostics
diag) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" chords (entropy " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show (GenerationDiagnostics -> Double
gdEntropy GenerationDiagnostics
diag) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
composerModeStr [Char]
composerStr
[Char] -> IO ()
putStrLn [Char]
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"STEP 1: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartRoot GenerationDiagnostics
diag [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ GenerationDiagnostics -> [Char]
gdStartCadence GenerationDiagnostics
diag [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" [starting state]"
[Char] -> IO ()
putStrLn [Char]
""
[StepDiagnostic] -> (StepDiagnostic -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (GenerationDiagnostics -> [StepDiagnostic]
gdSteps GenerationDiagnostics
diag) ((StepDiagnostic -> IO ()) -> IO ())
-> (StepDiagnostic -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \StepDiagnostic
step -> do
let barNum :: Int
barNum = StepDiagnostic -> Int
sdStepNumber StepDiagnostic
step Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
mvmt :: [Char]
mvmt = StepDiagnostic -> [Char]
sdSelectedDbMovement StepDiagnostic
step
chord :: [Char]
chord = case StepDiagnostic -> Maybe [Char]
sdRenderedChord StepDiagnostic
step of
Just [Char]
c -> [Char]
c
Maybe [Char]
Nothing -> StepDiagnostic -> [Char]
sdPosteriorRoot StepDiagnostic
step
src :: [Char]
src = [Char]
"[" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StepDiagnostic -> [Char]
sdSelectedFrom StepDiagnostic
step [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"]"
selIdx :: [Char]
selIdx = [Char]
"(γ=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdGammaIndex StepDiagnostic
step) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdPoolSize StepDiagnostic
step) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"STEP " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
barNum [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StepDiagnostic -> [Char]
sdPriorRoot StepDiagnostic
step [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StepDiagnostic -> [Char]
sdPosteriorRoot StepDiagnostic
step [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
mvmt [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
chord [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
src [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
selIdx
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" Pool: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdGraphCount StepDiagnostic
step) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" graph, "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (StepDiagnostic -> Int
sdFallbackCount StepDiagnostic
step) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" fallback"
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (StepDiagnostic -> [Char]
sdSelectedFrom StepDiagnostic
step [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"graph" Bool -> Bool -> Bool
&& Bool -> Bool
not ([([Char], Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (StepDiagnostic -> [([Char], Double)]
sdGraphTop6 StepDiagnostic
step))) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
[Char] -> IO ()
putStrLn [Char]
" Top graph:"
[([Char], Double)] -> (([Char], Double) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Int -> [([Char], Double)] -> [([Char], Double)]
forall a. Int -> [a] -> [a]
take Int
6 (StepDiagnostic -> [([Char], Double)]
sdGraphTop6 StepDiagnostic
step)) ((([Char], Double) -> IO ()) -> IO ())
-> (([Char], Double) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \([Char]
name, Double
conf) -> do
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show Double
conf [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (StepDiagnostic -> [Char]
sdSelectedFrom StepDiagnostic
step [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"fallback" Bool -> Bool -> Bool
&& Bool -> Bool
not ([([Char], Double, Double, Double, Double)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (StepDiagnostic -> [([Char], Double, Double, Double, Double)]
sdFallbackTop6 StepDiagnostic
step))) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
[Char] -> IO ()
putStrLn [Char]
" Top fallback:"
[([Char], Double, Double, Double, Double)]
-> (([Char], Double, Double, Double, Double) -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Int
-> [([Char], Double, Double, Double, Double)]
-> [([Char], Double, Double, Double, Double)]
forall a. Int -> [a] -> [a]
take Int
6 (StepDiagnostic -> [([Char], Double, Double, Double, Double)]
sdFallbackTop6 StepDiagnostic
step)) ((([Char], Double, Double, Double, Double) -> IO ()) -> IO ())
-> (([Char], Double, Double, Double, Double) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \([Char]
name, Double
score, Double
chordD, Double
motionD, Double
gammaD) -> do
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show Double
score
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
", c=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show Double
chordD
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
", m=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show Double
motionD
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
", γ=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Double -> [Char]
forall a. Show a => a -> [Char]
show Double
gammaD [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
case StepDiagnostic -> Maybe AdvanceTrace
sdAdvanceTrace StepDiagnostic
step of
Just AdvanceTrace
at -> do
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" Advance: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ AdvanceTrace -> [Char]
atCurrentRoot AdvanceTrace
at [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (AdvanceTrace -> Int
atCurrentRootPC AdvanceTrace
at) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" + " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (AdvanceTrace -> Int
atMovementInterval AdvanceTrace
at) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" → "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ AdvanceTrace -> [Char]
atNewRoot AdvanceTrace
at [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (AdvanceTrace -> Int
atNewRootPC AdvanceTrace
at) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
Maybe AdvanceTrace
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
[Char] -> IO ()
putStrLn [Char]
""
[Char] -> IO ()
putStrLn [Char]
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
genWith'' :: GeneratorConfig -> H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO (Prog.Progression, GenerationDiagnostics)
genWith'' :: GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith'' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
context = do
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
context
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
([CadenceState]
chain, [StepDiagnostic]
stepDiags) <- if (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower [Char]
composerStr [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"none"
then GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> CadenceState
-> Int
-> IO ([CadenceState], [StepDiagnostic])
buildChainOfflineWithDiagV GeneratorConfig
config Gen RealWorld
GenIO
rng Int
2 Double
entropy HarmonicContext
context ParsedContext
pctx CadenceState
start (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
else do
let composerWeights :: ComposerWeights
composerWeights = Text -> ComposerWeights
Q.parseComposerWeights ([Char] -> Text
T.pack [Char]
composerStr)
Pipe
pipe <- IO Pipe
connectNeo4j
([CadenceState], [StepDiagnostic])
result <- Pipe
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall (m :: * -> *) a.
(MonadIO m, HasCallStack) =>
Pipe -> BoltActionT m a -> m a
Bolt.run Pipe
pipe (BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic]))
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a b. (a -> b) -> a -> b
$ GeneratorConfig
-> GenIO
-> Int
-> Double
-> HarmonicContext
-> ParsedContext
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildChainWithDiagV GeneratorConfig
config Gen RealWorld
GenIO
rng Int
2 Double
entropy HarmonicContext
context ParsedContext
pctx ComposerWeights
composerWeights CadenceState
start (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
Pipe -> IO ()
forall (m :: * -> *). (MonadIO m, HasCallStack) => Pipe -> m ()
Bolt.close Pipe
pipe
([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState], [StepDiagnostic])
result
let prog :: Progression
prog = [CadenceState] -> Progression
chainToProgression [CadenceState]
chain
diag :: GenerationDiagnostics
diag = GenerationDiagnostics
{ gdStartCadence :: [Char]
gdStartCadence = Cadence -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> Cadence
extractCadence CadenceState
start)
, gdStartRoot :: [Char]
gdStartRoot = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start)
, gdRequestedLen :: Int
gdRequestedLen = Int
len
, gdActualLen :: Int
gdActualLen = Progression -> Int
Prog.progLength Progression
prog
, gdEntropy :: Double
gdEntropy = Double
entropy
, gdSteps :: [StepDiagnostic]
gdSteps = [StepDiagnostic]
stepDiags
, gdProgression :: Progression
gdProgression = Progression
prog
}
(Progression, GenerationDiagnostics)
-> IO (Progression, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Progression
prog, GenerationDiagnostics
diag)
genSilent :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genSilent :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genSilent CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
_diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
genStandard :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genStandard :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genStandard CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
Int -> GenerationDiagnostics -> IO ()
printDiagnostics Int
1 GenerationDiagnostics
diag
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
genVerbose :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genVerbose :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genVerbose CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate'' CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
Int -> GenerationDiagnostics -> IO ()
printDiagnostics Int
2 GenerationDiagnostics
diag
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
genSilent' :: GeneratorConfig -> H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genSilent' :: GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO Progression
genSilent' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
_diag) <- GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
genStandard' :: GeneratorConfig -> H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genStandard' :: GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO Progression
genStandard' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
diag) <- GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
Int -> GenerationDiagnostics -> IO ()
printDiagnostics Int
1 GenerationDiagnostics
diag
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
genVerbose' :: GeneratorConfig -> H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genVerbose' :: GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO Progression
genVerbose' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx = do
(Progression
prog, GenerationDiagnostics
diag) <- GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith'' GeneratorConfig
config CadenceState
start Int
len [Char]
composerStr Double
entropy HarmonicContext
ctx
Int -> GenerationDiagnostics -> IO ()
printDiagnostics Int
2 GenerationDiagnostics
diag
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
execGenConfig :: GenConfig -> IO Prog.Progression
execGenConfig :: GenConfig -> IO Progression
execGenConfig GenConfig
gc = do
(Progression
prog, GenerationDiagnostics
diag) <- GenConfig -> IO (Progression, GenerationDiagnostics)
execGenConfigWithDiag GenConfig
gc
GenConfig -> (ProgressionContext, GenerationDiagnostics) -> IO ()
emitFinalised GenConfig
gc (Progression -> ProgressionContext
PC.fromProgression Progression
prog, GenerationDiagnostics
diag)
Progression -> IO Progression
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Progression
prog
execGenConfigWithDiag :: GenConfig -> IO (Prog.Progression, GenerationDiagnostics)
execGenConfigWithDiag :: GenConfig -> IO (Progression, GenerationDiagnostics)
execGenConfigWithDiag GenConfig
gc = do
CadenceState
start0 <- GenConfig -> IO CadenceState
_gcCue GenConfig
gc
CadenceState
start <- if GenConfig -> Bool
_gcQuad GenConfig
gc
Bool -> Bool -> Bool
&& [PitchClass] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
start0)) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3
then do
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
(CadenceState
fused, Maybe FusionDiag
_) <- GenIO
-> Double
-> ParsedContext
-> Maybe CadenceState
-> CadenceState
-> IO (CadenceState, Maybe FusionDiag)
fuseState Gen RealWorld
GenIO
rng (GenConfig -> Double
_gcEntropy GenConfig
gc) ParsedContext
pctx Maybe CadenceState
forall a. Maybe a
Nothing CadenceState
start0
CadenceState -> IO CadenceState
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CadenceState
fused
else CadenceState -> IO CadenceState
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CadenceState
start0
let cfg :: GeneratorConfig
cfg = GeneratorConfig
defaultConfig { gcQuad = _gcQuad gc }
case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
Fresh -> case GenConfig -> Verbosity
_gcVerbosity GenConfig
gc of
Verbosity
Silent -> GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
cfg CadenceState
start (GenConfig -> Int
_gcLen GenConfig
gc) (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
Verbosity
Standard -> GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
cfg CadenceState
start (GenConfig -> Int
_gcLen GenConfig
gc) (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
Verbosity
Verbose -> GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith'' GeneratorConfig
cfg CadenceState
start (GenConfig -> Int
_gcLen GenConfig
gc) (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
GenMode
GridMode -> do
let grid :: Progression
grid = [CadenceState] -> Progression
Prog.fromCadenceStates (Int -> CadenceState -> [CadenceState]
forall a. Int -> a -> [a]
replicate (GenConfig -> Int
_gcLen GenConfig
gc) CadenceState
start)
diag :: GenerationDiagnostics
diag = GenerationDiagnostics
{ gdStartCadence :: [Char]
gdStartCadence = Cadence -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> Cadence
H.stateCadence CadenceState
start)
, gdStartRoot :: [Char]
gdStartRoot = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start)
, gdRequestedLen :: Int
gdRequestedLen = GenConfig -> Int
_gcLen GenConfig
gc
, gdActualLen :: Int
gdActualLen = Progression -> Int
Prog.progLength Progression
grid
, gdEntropy :: Double
gdEntropy = GenConfig -> Double
_gcEntropy GenConfig
gc
, gdSteps :: [StepDiagnostic]
gdSteps = []
, gdProgression :: Progression
gdProgression = Progression
grid
}
(Progression, GenerationDiagnostics)
-> IO (Progression, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Progression
grid, GenerationDiagnostics
diag)
FromProg Progression
srcProg Int
s Int
e -> do
let srcSizes :: [Int]
srcSizes = [ [PitchClass] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
cs))
| CadenceState
cs <- Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
srcProg) ]
srcQuad :: Bool
srcQuad = Bool -> Bool
not ([Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
srcSizes) Bool -> Bool -> Bool
&& (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
== Int
4) [Int]
srcSizes
srcMixed :: Bool
srcMixed = [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Int] -> [Int]
forall a. Eq a => [a] -> [a]
nub [Int]
srcSizes) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (GenConfig -> Bool
_gcQuad GenConfig
gc Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
srcQuad) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"genFrom is family-aware: this source is not a uniform 4-note (gen4) progression — regenerate with plain genFrom (quad is inferred from the source)"
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
srcMixed (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> IO ()
putStrLn [Char]
"genFrom: hand-mixed source cardinalities — regenerating as plain triads (regen never amplifies mixing)"
(Progression
fullProg, GenerationDiagnostics
regenDiag) <- GeneratorConfig
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWith' GeneratorConfig
cfg CadenceState
start (GenConfig -> Int
_gcLen GenConfig
gc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
(GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
let newChords :: [CadenceState]
newChords = [CadenceState] -> [CadenceState]
forall a. HasCallStack => [a] -> [a]
tail ([CadenceState] -> [CadenceState])
-> [CadenceState] -> [CadenceState]
forall a b. (a -> b) -> a -> b
$ Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Seq CadenceState -> [CadenceState])
-> Seq CadenceState -> [CadenceState]
forall a b. (a -> b) -> a -> b
$ Progression -> Seq CadenceState
Prog.unProgression Progression
fullProg
result :: Progression
result = Progression -> Int -> Int -> [CadenceState] -> Progression
Prog.spliceProgression Progression
srcProg Int
s Int
e [CadenceState]
newChords
(Progression, GenerationDiagnostics)
-> IO (Progression, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Progression
result, GenerationDiagnostics
regenDiag)
StrataMode StrataLabel
_ -> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start (GenConfig -> Int
_gcLen GenConfig
gc) (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
FromProgPC {} -> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start (GenConfig -> Int
_gcLen GenConfig
gc) (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
defaultGenConfig :: GenConfig
defaultGenConfig :: GenConfig
defaultGenConfig = GenConfig
{ _gcCue :: IO CadenceState
_gcCue = IO CadenceState
defaultCue
, _gcLen :: Int
_gcLen = Int
4
, _gcSeek :: [Char]
_gcSeek = [Char]
"*"
, _gcEntropy :: Double
_gcEntropy = Double
0.2
, _gcTonal :: HarmonicContext
_gcTonal = HarmonicContext
hContext
, _gcVerbosity :: Verbosity
_gcVerbosity = Verbosity
Silent
, _gcMode :: GenMode
_gcMode = GenMode
Fresh
, _gcLenOverride :: Maybe Int
_gcLenOverride = Maybe Int
forall a. Maybe a
Nothing
, _gcRelStrata :: Maybe [Int]
_gcRelStrata = Maybe [Int]
forall a. Maybe a
Nothing
, _gcAbsStrata :: Maybe [StrataLabel]
_gcAbsStrata = Maybe [StrataLabel]
forall a. Maybe a
Nothing
, _gcBoostSame :: Double
_gcBoostSame = Double
0.90
, _gcBoostFlip :: Double
_gcBoostFlip = Double
0.80
, _gcBoostTri :: Double
_gcBoostTri = Double
0.70
, _gcQuad :: Bool
_gcQuad = Bool
False
, _gcMaxAttempts :: Int
_gcMaxAttempts = Int
1
, _gcViableTarget :: Int
_gcViableTarget = Int
1
, _gcViabilityFloor :: Double
_gcViabilityFloor = Double
0.6
}
where
defaultCue :: IO CadenceState
defaultCue = do
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
Int
rootIdx <- (Int, Int) -> Gen RealWorld -> IO Int
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *). StatefulGen g m => (Int, Int) -> g -> m Int
uniformRM (Int
0 :: Int, Int
11) Gen RealWorld
rng
let rootName :: NoteName
rootName = EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
H.FlatSpelling (Int -> PitchClass
P.mkPitchClass Int
rootIdx)
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
$ Int -> [Char] -> [Int] -> CadenceState
H.initCadenceState Int
0 (NoteName -> [Char]
forall a. Show a => a -> [Char]
show NoteName
rootName) [Int
0, Int
4, Int
7]
gen :: GenConfig
gen :: GenConfig
gen = GenConfig
defaultGenConfig
gen' :: GenConfig
gen' :: GenConfig
gen' = GenConfig
defaultGenConfig { _gcVerbosity = Standard }
gen'' :: GenConfig
gen'' :: GenConfig
gen'' = GenConfig
defaultGenConfig { _gcVerbosity = Verbose }
genGrid :: GenConfig
genGrid :: GenConfig
genGrid = GenConfig
defaultGenConfig { _gcMode = GridMode }
quad :: GenConfig -> GenConfig
quad :: GenConfig -> GenConfig
quad GenConfig
gc = GenConfig
gc { _gcQuad = True }
gen4 :: GenConfig
gen4 :: GenConfig
gen4 = GenConfig -> GenConfig
quad GenConfig
gen
gen4' :: GenConfig
gen4' :: GenConfig
gen4' = GenConfig -> GenConfig
quad GenConfig
gen'
gen4'' :: GenConfig
gen4'' :: GenConfig
gen4'' = GenConfig -> GenConfig
quad GenConfig
gen''
genFrom :: PC.ProgressionContext -> Int -> Int -> GenConfig
genFrom :: ProgressionContext -> Int -> Int -> GenConfig
genFrom ProgressionContext
pc Int
s Int
e = GenConfig
defaultGenConfig
{ _gcCue = inferCue
, _gcLen = rSize
, _gcQuad = sourceIsQuad
, _gcMode = case PC.pcProvenance pc of
Just Seq (Tristrata, StrataLabel)
_ -> ProgressionContext -> Int -> Int -> GenMode
FromProgPC ProgressionContext
pc Int
s Int
e
Maybe (Seq (Tristrata, StrataLabel))
Nothing -> Progression -> Int -> Int -> GenMode
FromProg (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc) Int
s Int
e
}
where
triad :: Progression
triad = ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc
n :: Int
n = Progression -> Int
Prog.progLength Progression
triad
rSize :: Int
rSize = if Int
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
e then Int
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
e
cuePos :: Int
cuePos = ((Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
n) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
inferCue :: IO CadenceState
inferCue = case Progression -> Int -> Maybe CadenceState
Prog.getCadenceState Progression
triad Int
cuePos of
Just CadenceState
cs -> CadenceState -> IO CadenceState
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CadenceState
cs
Maybe CadenceState
Nothing -> GenConfig -> IO CadenceState
_gcCue GenConfig
defaultGenConfig
barSizes :: [Int]
barSizes = [ [PitchClass] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
cs))
| CadenceState
cs <- Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
triad) ]
sourceIsQuad :: Bool
sourceIsQuad = Bool -> Bool
not ([Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
barSizes) Bool -> Bool -> Bool
&& (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
== Int
4) [Int]
barSizes
genFrom' :: PC.ProgressionContext -> Int -> Int -> GenConfig
genFrom' :: ProgressionContext -> Int -> Int -> GenConfig
genFrom' ProgressionContext
pc Int
s Int
e = (ProgressionContext -> Int -> Int -> GenConfig
genFrom ProgressionContext
pc Int
s Int
e) { _gcVerbosity = Standard }
genFrom'' :: PC.ProgressionContext -> Int -> Int -> GenConfig
genFrom'' :: ProgressionContext -> Int -> Int -> GenConfig
genFrom'' ProgressionContext
pc Int
s Int
e = (ProgressionContext -> Int -> Int -> GenConfig
genFrom ProgressionContext
pc Int
s Int
e) { _gcVerbosity = Verbose }
cue :: H.CadenceState -> GenConfig -> GenConfig
cue :: CadenceState -> GenConfig -> GenConfig
cue CadenceState
start GenConfig
gc = GenConfig
gc { _gcCue = pure start }
len :: Int -> GenConfig -> GenConfig
len :: Int -> GenConfig -> GenConfig
len Int
n GenConfig
gc = GenConfig
gc { _gcLen = n, _gcLenOverride = Nothing }
seek :: String -> GenConfig -> IO PC.ProgressionContext
seek :: [Char] -> GenConfig -> IO ProgressionContext
seek [Char]
s GenConfig
gc = GenConfig -> IO ProgressionContext
execGenConfigPC GenConfig
gc { _gcSeek = s }
execGenConfigPC :: GenConfig -> IO PC.ProgressionContext
execGenConfigPC :: GenConfig -> IO ProgressionContext
execGenConfigPC GenConfig
gc
| GenConfig -> Int
_gcMaxAttempts GenConfig
gc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 = GenConfig -> IO ProgressionContext
generateBest GenConfig
gc
| Bool
otherwise = GenConfig -> IO ProgressionContext
singlePassExecPC GenConfig
gc
emitFinalised :: GenConfig -> (PC.ProgressionContext, GenerationDiagnostics) -> IO ()
emitFinalised :: GenConfig -> (ProgressionContext, GenerationDiagnostics) -> IO ()
emitFinalised GenConfig
gc (ProgressionContext
pc, GenerationDiagnostics
diag) = do
case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
Fresh -> IO ()
emitCueNotice
GenMode
GridMode -> IO ()
emitCueNotice
GenMode
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
let isStrata :: Bool
isStrata = case GenConfig -> GenMode
_gcMode GenConfig
gc of
StrataMode StrataLabel
_ -> Bool
True
FromProgPC {} -> Bool
True
GenMode
_ -> Bool
False
case GenConfig -> Verbosity
_gcVerbosity GenConfig
gc of
Verbosity
Silent -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Verbosity
Standard -> if Bool
isStrata
then Int -> GenerationDiagnostics -> IO ()
printStrataDiagnostics Int
1 GenerationDiagnostics
diag
else [Char] -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc) GenerationDiagnostics
diag
Verbosity
Verbose -> if Bool
isStrata
then Int -> GenerationDiagnostics -> IO ()
printStrataDiagnostics Int
2 GenerationDiagnostics
diag
else [Char] -> GenerationDiagnostics -> IO ()
renderVerboseSteps (GenConfig -> [Char]
_gcSeek GenConfig
gc) GenerationDiagnostics
diag
[Char] -> IO ()
putStrLn [Char]
""
Text -> Double -> HarmonicContext -> IO ()
printHeader ([Char] -> Text
T.pack (GenConfig -> [Char]
_gcSeek GenConfig
gc)) (GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
Progression -> IO ()
forall a. Show a => a -> IO ()
print (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
[Char] -> IO ()
putStrLn [Char]
""
where
emitCueNotice :: IO ()
emitCueNotice =
case Seq CadenceState -> ViewL CadenceState
forall a. Seq a -> ViewL a
Seq.viewl (Progression -> Seq CadenceState
Prog.unProgression (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)) of
CadenceState
firstState Seq.:< Seq CadenceState
_ -> HarmonicContext -> CadenceState -> IO ()
printCueEscapeNotice (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc) CadenceState
firstState
ViewL CadenceState
Seq.EmptyL -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
singlePassExecPC :: GenConfig -> IO PC.ProgressionContext
singlePassExecPC :: GenConfig -> IO ProgressionContext
singlePassExecPC GenConfig
gc = do
(ProgressionContext
pc, GenerationDiagnostics
diag) <- GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc
GenConfig -> (ProgressionContext, GenerationDiagnostics) -> IO ()
emitFinalised GenConfig
gc (ProgressionContext
pc, GenerationDiagnostics
diag)
ProgressionContext -> IO ProgressionContext
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ProgressionContext
pc
singlePassExecPCWithDiag :: GenConfig -> IO (PC.ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag :: GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc = case GenConfig -> GenMode
_gcMode GenConfig
gc of
StrataMode StrataLabel
_ | GenConfig -> Bool
_gcQuad GenConfig
gc ->
[Char] -> IO (ProgressionContext, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"quad/gen4 applies to the gen family only — genP (strata) stays 3-5-7"
FromProgPC {} | GenConfig -> Bool
_gcQuad GenConfig
gc ->
[Char] -> IO (ProgressionContext, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"quad/gen4 applies to the gen family only — this source is strata-aware (genP provenance); regenerate it with plain genFrom (family is inferred from the source)"
StrataMode StrataLabel
sStart -> StrataLabel
-> GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
runStrataGen StrataLabel
sStart GenConfig
gc
FromProgPC ProgressionContext
srcPC Int
s Int
e -> ProgressionContext
-> Int
-> Int
-> GenConfig
-> IO (ProgressionContext, GenerationDiagnostics)
runStrataGenFrom ProgressionContext
srcPC Int
s Int
e GenConfig
gc
GenMode
_ -> do
(Progression
prog, GenerationDiagnostics
diag) <- GenConfig -> IO (Progression, GenerationDiagnostics)
execGenConfigWithDiag GenConfig
gc
(ProgressionContext, GenerationDiagnostics)
-> IO (ProgressionContext, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Progression -> ProgressionContext
PC.fromProgression Progression
prog, GenerationDiagnostics
diag)
generateBest :: GenConfig -> IO PC.ProgressionContext
generateBest :: GenConfig -> IO ProgressionContext
generateBest GenConfig
gc = do
[Char] -> IO ()
putStrLn [Char]
"composing .."
let online :: Bool
online = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (GenConfig -> [Char]
_gcSeek GenConfig
gc) [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
/= [Char]
"none"
(ProgressionContext
winnerPC, GenerationDiagnostics
winnerDiag, [AttemptDiagnostic]
diags) <-
if Bool
online then GenConfig
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runOnline GenConfig
gc else GenConfig
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runOffline GenConfig
gc
GenConfig -> (ProgressionContext, GenerationDiagnostics) -> IO ()
emitFinalised GenConfig
gc (ProgressionContext
winnerPC, GenerationDiagnostics
winnerDiag)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (GenConfig -> Verbosity
_gcVerbosity GenConfig
gc Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
== Verbosity
Verbose Bool -> Bool -> Bool
&& GenConfig -> Int
_gcMaxAttempts GenConfig
gc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Double -> [AttemptDiagnostic] -> IO ()
printAttemptScoreboard (GenConfig -> Double
_gcViabilityFloor GenConfig
gc) [AttemptDiagnostic]
diags
ProgressionContext -> IO ProgressionContext
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ProgressionContext
winnerPC
runOffline :: GenConfig
-> IO (PC.ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runOffline :: GenConfig
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runOffline GenConfig
gc = do
let maxN :: Int
maxN = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (GenConfig -> Int
_gcMaxAttempts GenConfig
gc)
target :: Int
target = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (GenConfig -> Int
_gcViableTarget GenConfig
gc)
floorT :: Double
floorT = GenConfig -> Double
_gcViabilityFloor GenConfig
gc
[ScoredAttempt]
scored <- GenConfig -> Int -> Int -> Double -> IO [ScoredAttempt]
offlineLoop GenConfig
gc Int
maxN Int
target Double
floorT
GenConfig
-> [ScoredAttempt]
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
finaliseScored GenConfig
gc [ScoredAttempt]
scored
runOnline :: GenConfig
-> IO (PC.ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runOnline :: GenConfig
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runOnline GenConfig
gc = do
let maxN :: Int
maxN = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (GenConfig -> Int
_gcMaxAttempts GenConfig
gc)
target :: Int
target = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (GenConfig -> Int
_gcViableTarget GenConfig
gc)
floorT :: Double
floorT = GenConfig -> Double
_gcViabilityFloor GenConfig
gc
seekTxt :: Text
seekTxt = [Char] -> Text
T.pack (GenConfig -> [Char]
_gcSeek GenConfig
gc)
Pipe
pipe <- IO Pipe
connectNeo4j
[ScoredAttempt]
scored <- Pipe -> BoltActionT IO [ScoredAttempt] -> IO [ScoredAttempt]
forall (m :: * -> *) a.
(MonadIO m, HasCallStack) =>
Pipe -> BoltActionT m a -> m a
Bolt.run Pipe
pipe (Text
-> GenConfig
-> Int
-> Int
-> Double
-> BoltActionT IO [ScoredAttempt]
onlineLoop Text
seekTxt GenConfig
gc Int
maxN Int
target Double
floorT)
Pipe -> IO ()
forall (m :: * -> *). (MonadIO m, HasCallStack) => Pipe -> m ()
Bolt.close Pipe
pipe
GenConfig
-> [ScoredAttempt]
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
finaliseScored GenConfig
gc [ScoredAttempt]
scored
type ScoredAttempt = (PC.ProgressionContext, PS.ProgressionScore, Double, Bool, GenerationDiagnostics)
offlineLoop
:: GenConfig
-> Int
-> Int
-> Double
-> IO [ScoredAttempt]
offlineLoop :: GenConfig -> Int -> Int -> Double -> IO [ScoredAttempt]
offlineLoop GenConfig
gc Int
maxN Int
target Double
floorT = Int -> [ScoredAttempt] -> Int -> IO [ScoredAttempt]
forall {t}.
(Eq t, Num t) =>
Int -> [ScoredAttempt] -> t -> IO [ScoredAttempt]
go Int
0 [] Int
maxN
where
go :: Int -> [ScoredAttempt] -> t -> IO [ScoredAttempt]
go Int
_ [ScoredAttempt]
acc t
0 = [ScoredAttempt] -> IO [ScoredAttempt]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ScoredAttempt] -> [ScoredAttempt]
forall a. [a] -> [a]
reverse [ScoredAttempt]
acc)
go Int
viableSoFar [ScoredAttempt]
acc t
remaining
| Int
viableSoFar Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
target = [ScoredAttempt] -> IO [ScoredAttempt]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ScoredAttempt] -> [ScoredAttempt]
forall a. [a] -> [a]
reverse [ScoredAttempt]
acc)
| Bool
otherwise = do
(ProgressionContext
pc, GenerationDiagnostics
diag) <- GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc
let ps :: ProgressionScore
ps = ProgressionContext -> ProgressionScore
PS.scoreProgression ProgressionContext
pc
tot :: Double
tot = ProgressionScoreWeights -> ProgressionScore -> Double
PS.totalScore ProgressionScoreWeights
PS.defaultWeightsOffline ProgressionScore
ps
isOk :: Bool
isOk = ProgressionScore -> Double
PS.psModeValidity ProgressionScore
ps Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1.0 Bool -> Bool -> Bool
&& Double
tot Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
floorT
acc' :: [ScoredAttempt]
acc' = (ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
isOk, GenerationDiagnostics
diag) ScoredAttempt -> [ScoredAttempt] -> [ScoredAttempt]
forall a. a -> [a] -> [a]
: [ScoredAttempt]
acc
viable' :: Int
viable' = if Bool
isOk then Int
viableSoFar Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
viableSoFar
Int -> [ScoredAttempt] -> t -> IO [ScoredAttempt]
go Int
viable' [ScoredAttempt]
acc' (t
remaining t -> t -> t
forall a. Num a => a -> a -> a
- t
1)
onlineLoop
:: T.Text
-> GenConfig
-> Int
-> Int
-> Double
-> Bolt.BoltActionT IO [ScoredAttempt]
onlineLoop :: Text
-> GenConfig
-> Int
-> Int
-> Double
-> BoltActionT IO [ScoredAttempt]
onlineLoop Text
seekTxt GenConfig
gc Int
maxN Int
target Double
floorT = Int -> [ScoredAttempt] -> Int -> BoltActionT IO [ScoredAttempt]
forall {t}.
(Eq t, Num t) =>
Int -> [ScoredAttempt] -> t -> BoltActionT IO [ScoredAttempt]
go Int
0 [] Int
maxN
where
go :: Int -> [ScoredAttempt] -> t -> BoltActionT IO [ScoredAttempt]
go Int
_ [ScoredAttempt]
acc t
0 = [ScoredAttempt] -> BoltActionT IO [ScoredAttempt]
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ScoredAttempt] -> [ScoredAttempt]
forall a. [a] -> [a]
reverse [ScoredAttempt]
acc)
go Int
viableSoFar [ScoredAttempt]
acc t
remaining
| Int
viableSoFar Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
target = [ScoredAttempt] -> BoltActionT IO [ScoredAttempt]
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ScoredAttempt] -> [ScoredAttempt]
forall a. [a] -> [a]
reverse [ScoredAttempt]
acc)
| Bool
otherwise = do
(ProgressionContext
pc, GenerationDiagnostics
diag) <- IO (ProgressionContext, GenerationDiagnostics)
-> BoltActionT IO (ProgressionContext, GenerationDiagnostics)
forall a. IO a -> BoltActionT IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc)
ProgressionScore
ps <- Text -> ProgressionContext -> BoltActionT IO ProgressionScore
PS.scoreProgressionOnline Text
seekTxt ProgressionContext
pc
let tot :: Double
tot = ProgressionScoreWeights -> ProgressionScore -> Double
PS.totalScore ProgressionScoreWeights
PS.defaultWeights ProgressionScore
ps
isOk :: Bool
isOk = ProgressionScore -> Double
PS.psModeValidity ProgressionScore
ps Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1.0 Bool -> Bool -> Bool
&& Double
tot Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
floorT
acc' :: [ScoredAttempt]
acc' = (ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
isOk, GenerationDiagnostics
diag) ScoredAttempt -> [ScoredAttempt] -> [ScoredAttempt]
forall a. a -> [a] -> [a]
: [ScoredAttempt]
acc
viable' :: Int
viable' = if Bool
isOk then Int
viableSoFar Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
viableSoFar
Int -> [ScoredAttempt] -> t -> BoltActionT IO [ScoredAttempt]
go Int
viable' [ScoredAttempt]
acc' (t
remaining t -> t -> t
forall a. Num a => a -> a -> a
- t
1)
finaliseScored
:: GenConfig
-> [ScoredAttempt]
-> IO (PC.ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
finaliseScored :: GenConfig
-> [ScoredAttempt]
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
finaliseScored GenConfig
gc [ScoredAttempt]
scored = case [ScoredAttempt]
scored of
[] -> do
(ProgressionContext
pc, GenerationDiagnostics
diag) <- GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ProgressionContext
pc, GenerationDiagnostics
diag, [])
[ScoredAttempt]
xs -> do
let indexed :: [(Int, ScoredAttempt)]
indexed = [Int] -> [ScoredAttempt] -> [(Int, ScoredAttempt)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1..] [ScoredAttempt]
xs
(Int
winnerIdx, (ProgressionContext
winnerPC, ProgressionScore
_, Double
_, Bool
_, GenerationDiagnostics
winnerDiag)) =
((Int, ScoredAttempt) -> Double)
-> [(Int, ScoredAttempt)] -> (Int, ScoredAttempt)
forall b a. Ord b => (a -> b) -> [a] -> a
maximumByKey (\(Int
_, (ProgressionContext
_, ProgressionScore
_, Double
tot, Bool
_, GenerationDiagnostics
_)) -> Double
tot) [(Int, ScoredAttempt)]
indexed
diags :: [AttemptDiagnostic]
diags = [ AttemptDiagnostic
{ adIndex :: Int
adIndex = Int
i
, adScore :: ProgressionScore
adScore = ProgressionScore
ps
, adTotal :: Double
adTotal = Double
tot
, adViable :: Bool
adViable = Bool
ok
, adPicked :: Bool
adPicked = Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
winnerIdx
, adChords :: [[Char]]
adChords = Progression -> [[Char]]
chordNamesOf (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
}
| (Int
i, (ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
ok, GenerationDiagnostics
_)) <- [(Int, ScoredAttempt)]
indexed
]
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ProgressionContext
winnerPC, GenerationDiagnostics
winnerDiag, [AttemptDiagnostic]
diags)
where
maximumByKey :: Ord b => (a -> b) -> [a] -> a
maximumByKey :: forall b a. Ord b => (a -> b) -> [a] -> a
maximumByKey a -> b
f = (a -> a -> a) -> [a] -> a
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 (\a
x a
y -> if a -> b
f a
x b -> b -> Bool
forall a. Ord a => a -> a -> Bool
>= a -> b
f a
y then a
x else a
y)
chordNamesOf :: Prog.Progression -> [String]
chordNamesOf :: Progression -> [[Char]]
chordNamesOf Progression
prog =
let cads :: [CadenceState]
cads = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
prog)
enharms :: [PitchClass -> NoteName]
enharms = (CadenceState -> PitchClass -> NoteName)
-> [CadenceState] -> [PitchClass -> NoteName]
forall a b. (a -> b) -> [a] -> [b]
map (EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc (EnharmonicSpelling -> PitchClass -> NoteName)
-> (CadenceState -> EnharmonicSpelling)
-> CadenceState
-> PitchClass
-> NoteName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CadenceState -> EnharmonicSpelling
H.stateSpelling) [CadenceState]
cads
in ((PitchClass -> NoteName) -> CadenceState -> [Char])
-> [PitchClass -> NoteName] -> [CadenceState] -> [[Char]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (PitchClass -> NoteName) -> CadenceState -> [Char]
Prog.showHarmony [PitchClass -> NoteName]
enharms [CadenceState]
cads
entropy :: Double -> GenConfig -> GenConfig
entropy :: Double -> GenConfig -> GenConfig
entropy Double
e GenConfig
gc = GenConfig
gc { _gcEntropy = e }
attempt :: Int -> Int -> GenConfig -> GenConfig
attempt :: Int -> Int -> GenConfig -> GenConfig
attempt Int
viableTarget Int
maxAttempts GenConfig
gc = GenConfig
gc
{ _gcViableTarget = max 1 viableTarget
, _gcMaxAttempts = max 1 maxAttempts
}
viability :: Double -> GenConfig -> GenConfig
viability :: Double -> GenConfig -> GenConfig
viability Double
t GenConfig
gc = GenConfig
gc { _gcViabilityFloor = max 0 t }
tonal :: HarmonicContext -> GenConfig -> GenConfig
tonal :: HarmonicContext -> GenConfig -> GenConfig
tonal HarmonicContext
ctx GenConfig
gc = GenConfig
gc { _gcTonal = ctx }
relStrata :: String -> GenConfig -> GenConfig
relStrata :: [Char] -> GenConfig -> GenConfig
relStrata [Char]
s GenConfig
gc =
let ns :: [Int]
ns = [Char] -> [Int]
Sc.parseRelStrata [Char]
s
in GenConfig
gc { _gcRelStrata = Just ns
, _gcLenOverride = if null ns then Nothing else Just (length ns)
}
absStrata :: String -> GenConfig -> GenConfig
absStrata :: [Char] -> GenConfig -> GenConfig
absStrata [Char]
s GenConfig
gc =
let ss :: [StrataLabel]
ss = [Char] -> [StrataLabel]
Sc.parseAbsStrata [Char]
s
in GenConfig
gc { _gcAbsStrata = Just ss
, _gcLenOverride = if null ss then Nothing else Just (length ss)
}
sameBoost :: Double -> GenConfig -> GenConfig
sameBoost :: Double -> GenConfig -> GenConfig
sameBoost Double
x GenConfig
gc = GenConfig
gc { _gcBoostSame = x }
flipBoost :: Double -> GenConfig -> GenConfig
flipBoost :: Double -> GenConfig -> GenConfig
flipBoost Double
x GenConfig
gc = GenConfig
gc { _gcBoostFlip = x }
triBoost :: Double -> GenConfig -> GenConfig
triBoost :: Double -> GenConfig -> GenConfig
triBoost Double
x GenConfig
gc = GenConfig
gc { _gcBoostTri = x }
genP :: Sc.StrataLabel -> GenConfig
genP :: StrataLabel -> GenConfig
genP StrataLabel
s = GenConfig
defaultGenConfig { _gcMode = StrataMode s }
genP' :: Sc.StrataLabel -> GenConfig
genP' :: StrataLabel -> GenConfig
genP' StrataLabel
s = (StrataLabel -> GenConfig
genP StrataLabel
s) { _gcVerbosity = Standard }
genP'' :: Sc.StrataLabel -> GenConfig
genP'' :: StrataLabel -> GenConfig
genP'' StrataLabel
s = (StrataLabel -> GenConfig
genP StrataLabel
s) { _gcVerbosity = Verbose }
genI, genII, genIII, genIV, genV, genVI, genVII, genVIII, genIX, genX, genXI :: GenConfig
genI :: GenConfig
genI = StrataLabel -> GenConfig
genP StrataLabel
Sc.I
genII :: GenConfig
genII = StrataLabel -> GenConfig
genP StrataLabel
Sc.II
genIII :: GenConfig
genIII = StrataLabel -> GenConfig
genP StrataLabel
Sc.III
genIV :: GenConfig
genIV = StrataLabel -> GenConfig
genP StrataLabel
Sc.IV
genV :: GenConfig
genV = StrataLabel -> GenConfig
genP StrataLabel
Sc.V
genVI :: GenConfig
genVI = StrataLabel -> GenConfig
genP StrataLabel
Sc.VI
genVII :: GenConfig
genVII = StrataLabel -> GenConfig
genP StrataLabel
Sc.VII
genVIII :: GenConfig
genVIII = StrataLabel -> GenConfig
genP StrataLabel
Sc.VIII
genIX :: GenConfig
genIX = StrataLabel -> GenConfig
genP StrataLabel
Sc.IX
genX :: GenConfig
genX = StrataLabel -> GenConfig
genP StrataLabel
Sc.X
genXI :: GenConfig
genXI = StrataLabel -> GenConfig
genP StrataLabel
Sc.XI
genI', genII', genIII', genIV', genV', genVI', genVII', genVIII', genIX', genX', genXI' :: GenConfig
genI' :: GenConfig
genI' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.I
genII' :: GenConfig
genII' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.II
genIII' :: GenConfig
genIII' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.III
genIV' :: GenConfig
genIV' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.IV
genV' :: GenConfig
genV' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.V
genVI' :: GenConfig
genVI' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.VI
genVII' :: GenConfig
genVII' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.VII
genVIII' :: GenConfig
genVIII' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.VIII
genIX' :: GenConfig
genIX' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.IX
genX' :: GenConfig
genX' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.X
genXI' :: GenConfig
genXI' = StrataLabel -> GenConfig
genP' StrataLabel
Sc.XI
genI'', genII'', genIII'', genIV'', genV'', genVI'', genVII'', genVIII'', genIX'', genX'', genXI'' :: GenConfig
genI'' :: GenConfig
genI'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.I
genII'' :: GenConfig
genII'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.II
genIII'' :: GenConfig
genIII'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.III
genIV'' :: GenConfig
genIV'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.IV
genV'' :: GenConfig
genV'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.V
genVI'' :: GenConfig
genVI'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.VI
genVII'' :: GenConfig
genVII'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.VII
genVIII'' :: GenConfig
genVIII'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.VIII
genIX'' :: GenConfig
genIX'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.IX
genX'' :: GenConfig
genX'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.X
genXI'' :: GenConfig
genXI'' = StrataLabel -> GenConfig
genP'' StrataLabel
Sc.XI
runStrataGen :: Sc.StrataLabel -> GenConfig -> IO (PC.ProgressionContext, GenerationDiagnostics)
runStrataGen :: StrataLabel
-> GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
runStrataGen StrataLabel
sStart GenConfig
gc = do
CadenceState
start <- GenConfig -> IO CadenceState
_gcCue GenConfig
gc
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
let basePctx :: ParsedContext
basePctx = HarmonicContext -> ParsedContext
parseContextOnce (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
allowed :: [Tristrata]
allowed = ParsedContext -> [Tristrata]
pcAllowedTristrata ParsedContext
basePctx
allowed' :: [Tristrata]
allowed' = if [Tristrata] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Tristrata]
allowed then [Tristrata]
Sc.validTristrata else [Tristrata]
allowed
n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe (GenConfig -> Int
_gcLen GenConfig
gc) (GenConfig -> Maybe Int
_gcLenOverride GenConfig
gc))
(StrataLabel
s0, Tristrata
t0) = [Tristrata] -> StrataLabel -> (StrataLabel, Tristrata)
Strata.initialPlacement [Tristrata]
allowed' StrataLabel
sStart
narrow :: Int -> [(Sc.StrataLabel, Sc.Tristrata)] -> [(Sc.StrataLabel, Sc.Tristrata)]
narrow :: Int -> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
narrow Int
i [(StrataLabel, Tristrata)]
pool =
let pool1 :: [(StrataLabel, Tristrata)]
pool1 = case GenConfig -> Maybe [Int]
_gcRelStrata GenConfig
gc of
Just [Int]
ps | Bool -> Bool
not ([Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
ps) ->
let p :: Int
p = [Int]
ps [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i 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]
ps)
in [(StrataLabel
s',Tristrata
t') | (StrataLabel
s',Tristrata
t') <- [(StrataLabel, Tristrata)]
pool, Tristrata -> Int -> StrataLabel
Sc.tristrataStrataAt Tristrata
t' Int
p StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
s']
Maybe [Int]
_ -> [(StrataLabel, Tristrata)]
pool
pool2 :: [(StrataLabel, Tristrata)]
pool2 = case GenConfig -> Maybe [StrataLabel]
_gcAbsStrata GenConfig
gc of
Just [StrataLabel]
ss | Bool -> Bool
not ([StrataLabel] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [StrataLabel]
ss) ->
let s :: StrataLabel
s = [StrataLabel]
ss [StrataLabel] -> Int -> StrataLabel
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` [StrataLabel] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [StrataLabel]
ss)
in [(StrataLabel
s',Tristrata
t') | (StrataLabel
s',Tristrata
t') <- [(StrataLabel, Tristrata)]
pool1, StrataLabel
s' StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
s]
Maybe [StrataLabel]
_ -> [(StrataLabel, Tristrata)]
pool1
in [(StrataLabel, Tristrata)]
pool2
[Int]
walkSeeds <- (Int -> IO Int) -> [Int] -> IO [Int]
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 (IO Int -> Int -> IO Int
forall a b. a -> b -> a
const ((Int, Int) -> Gen RealWorld -> IO Int
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *). StatefulGen g m => (Int, Int) -> g -> m Int
uniformRM (Int
forall a. Bounded a => a
minBound :: Int, Int
forall a. Bounded a => a
maxBound :: Int) Gen RealWorld
rng))
[Int
1 .. Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)]
let
walk :: Int -> [Int] -> (Sc.StrataLabel, Sc.Tristrata) -> [(Sc.StrataLabel, Sc.Tristrata)]
walk :: Int
-> [Int] -> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
walk Int
i [Int]
seeds (StrataLabel, Tristrata)
prev
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n = []
| Bool
otherwise =
let cands :: [(StrataLabel, Tristrata)]
cands = Int -> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
narrow Int
i ([Tristrata]
-> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
Strata.allowedNext [Tristrata]
allowed' (StrataLabel, Tristrata)
prev)
(Int
seed, [Int]
seedsRest) = case [Int]
seeds of
(Int
s : [Int]
rest) -> (Int
s, [Int]
rest)
[] -> (Int
0, [])
chosen :: (StrataLabel, Tristrata)
chosen = (StrataLabel, Tristrata)
-> Maybe (StrataLabel, Tristrata) -> (StrataLabel, Tristrata)
forall a. a -> Maybe a -> a
fromMaybe (StrataLabel, Tristrata)
prev (Int
-> (StrataLabel, Tristrata)
-> [(StrataLabel, Tristrata)]
-> Maybe (StrataLabel, Tristrata)
Strata.selectNextSeeded Int
seed (StrataLabel, Tristrata)
prev [(StrataLabel, Tristrata)]
cands)
in (StrataLabel, Tristrata)
chosen (StrataLabel, Tristrata)
-> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
forall a. a -> [a] -> [a]
: Int
-> [Int] -> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
walk (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Int]
seedsRest (StrataLabel, Tristrata)
chosen
barSeq :: [(Sc.StrataLabel, Sc.Tristrata)]
barSeq :: [(StrataLabel, Tristrata)]
barSeq = (StrataLabel
s0, Tristrata
t0) (StrataLabel, Tristrata)
-> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
forall a. a -> [a] -> [a]
: Int
-> [Int] -> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
walk Int
1 [Int]
walkSeeds (StrataLabel
s0, Tristrata
t0)
strataOvertonesString :: Sc.StrataLabel -> String
strataOvertonesString :: StrataLabel -> [Char]
strataOvertonesString StrataLabel
s =
[[Char]] -> [Char]
unwords [ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
P.sharp (Int -> PitchClass
P.mkPitchClass (PitchClass -> Int
P.unPitchClass PitchClass
pc))) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
| PitchClass
pc <- StrataLabel -> [PitchClass]
Sc.strataChroma StrataLabel
s ]
boostFor :: Int -> Double
boostFor :: Int -> Double
boostFor Int
0 = Double
1.0
boostFor Int
i =
let (StrataLabel
sCurr, Tristrata
tCurr) = [(StrataLabel, Tristrata)]
barSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! Int
i
(StrataLabel
sPrev, Tristrata
tPrev) = [(StrataLabel, Tristrata)]
barSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
sGrand :: Maybe StrataLabel
sGrand = if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 then StrataLabel -> Maybe StrataLabel
forall a. a -> Maybe a
Just ((StrataLabel, Tristrata) -> StrataLabel
forall a b. (a, b) -> a
fst ([(StrataLabel, Tristrata)]
barSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2))) else Maybe StrataLabel
forall a. Maybe a
Nothing
mSame :: Double
mSame = if StrataLabel
sCurr StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
sPrev then GenConfig -> Double
_gcBoostSame GenConfig
gc else Double
1.0
mFlip :: Double
mFlip = case Maybe StrataLabel
sGrand of
Just StrataLabel
sg | StrataLabel
sCurr StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
sg Bool -> Bool -> Bool
&& StrataLabel
sCurr StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
/= StrataLabel
sPrev -> GenConfig -> Double
_gcBoostFlip GenConfig
gc
Maybe StrataLabel
_ -> Double
1.0
mTri :: Double
mTri = if Tristrata
tCurr Tristrata -> Tristrata -> Bool
forall a. Eq a => a -> a -> Bool
== Tristrata
tPrev then GenConfig -> Double
_gcBoostTri GenConfig
gc else Double
1.0
Tristrata
_ = Tristrata
tPrev
in Double
mSame Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
mFlip Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
mTri
pctxAt :: Int -> ParsedContext
pctxAt :: Int -> ParsedContext
pctxAt Int
barIdx1 =
let i :: Int
i = Int
barIdx1
(StrataLabel
s, Tristrata
_) = [(StrataLabel, Tristrata)]
barSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! Int
i
ctx' :: HarmonicContext
ctx' = [Char] -> HarmonicContext -> HarmonicContext
hcOvertones (StrataLabel -> [Char]
strataOvertonesString StrataLabel
s) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
ctx'
boost :: Double
boost = Int -> Double
boostFor Int
i
in ParsedContext
pctx { pcSoftBoost = boost
, pcStrictContainment = True
}
startAbsPCs :: [Int]
startAbsPCs =
let rpc :: Int
rpc = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start))
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
start))
in [ (Int
iv Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rpc) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12 | Int
iv <- [Int]
ivs ]
s0PCs :: [Int]
s0PCs = (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (StrataLabel -> [PitchClass]
Sc.strataChroma StrataLabel
s0)
cueValid :: Bool
cueValid = (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]
s0PCs) [Int]
startAbsPCs
if Bool -> Bool
not Bool
cueValid
then do
CadenceState -> StrataLabel -> IO ()
printInvalidCueError CadenceState
start StrataLabel
s0
let emptyPC :: ProgressionContext
emptyPC = PC.ProgressionContext
{ triadLayer :: Progression
PC.triadLayer = Progression
forall a. Monoid a => a
mempty
, strataLayer :: Progression
PC.strataLayer = Progression
forall a. Monoid a => a
mempty
, modeLayer :: Progression
PC.modeLayer = Progression
forall a. Monoid a => a
mempty
, pcProvenance :: Maybe (Seq (Tristrata, StrataLabel))
PC.pcProvenance = Seq (Tristrata, StrataLabel)
-> Maybe (Seq (Tristrata, StrataLabel))
forall a. a -> Maybe a
Just Seq (Tristrata, StrataLabel)
forall a. Seq a
Seq.empty
}
emptyDiag :: GenerationDiagnostics
emptyDiag = GenerationDiagnostics
{ gdStartCadence :: [Char]
gdStartCadence = Cadence -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> Cadence
H.stateCadence CadenceState
start)
, gdStartRoot :: [Char]
gdStartRoot = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start)
, gdRequestedLen :: Int
gdRequestedLen = Int
n
, gdActualLen :: Int
gdActualLen = Int
0
, gdEntropy :: Double
gdEntropy = GenConfig -> Double
_gcEntropy GenConfig
gc
, gdSteps :: [StepDiagnostic]
gdSteps = []
, gdProgression :: Progression
gdProgression = Progression
forall a. Monoid a => a
mempty
}
(ProgressionContext, GenerationDiagnostics)
-> IO (ProgressionContext, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ProgressionContext
emptyPC, GenerationDiagnostics
emptyDiag)
else StrataLabel
-> GenConfig
-> CadenceState
-> GenIO
-> StrataLabel
-> Tristrata
-> [(StrataLabel, Tristrata)]
-> (Int -> ParsedContext)
-> (Int -> Double)
-> Int
-> IO (ProgressionContext, GenerationDiagnostics)
runStrataGenBody StrataLabel
sStart GenConfig
gc CadenceState
start Gen RealWorld
GenIO
rng StrataLabel
s0 Tristrata
t0 [(StrataLabel, Tristrata)]
barSeq Int -> ParsedContext
pctxAt Int -> Double
boostFor Int
n
runStrataGenBody
:: Sc.StrataLabel
-> GenConfig
-> H.CadenceState
-> GenIO
-> Sc.StrataLabel
-> Sc.Tristrata
-> [(Sc.StrataLabel, Sc.Tristrata)]
-> (Int -> ParsedContext)
-> (Int -> Double)
-> Int
-> IO (PC.ProgressionContext, GenerationDiagnostics)
runStrataGenBody :: StrataLabel
-> GenConfig
-> CadenceState
-> GenIO
-> StrataLabel
-> Tristrata
-> [(StrataLabel, Tristrata)]
-> (Int -> ParsedContext)
-> (Int -> Double)
-> Int
-> IO (ProgressionContext, GenerationDiagnostics)
runStrataGenBody StrataLabel
_sStart GenConfig
gc CadenceState
start GenIO
rng StrataLabel
_s0 Tristrata
_t0 [(StrataLabel, Tristrata)]
barSeq Int -> ParsedContext
pctxAt Int -> Double
boostFor Int
n = do
let pctxAtStep :: Int -> ParsedContext
pctxAtStep :: Int -> ParsedContext
pctxAtStep = Int -> ParsedContext
pctxAt
verbArg :: Maybe Int
verbArg = case GenConfig -> Verbosity
_gcVerbosity GenConfig
gc of
Verbosity
Silent -> Maybe Int
forall a. Maybe a
Nothing
Verbosity
Standard -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1
Verbosity
Verbose -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
2
([CadenceState]
chain, [StepDiagnostic]
rawDiags) <-
if (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (GenConfig -> [Char]
_gcSeek GenConfig
gc) [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"none"
then GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> (Int -> ParsedContext)
-> CadenceState
-> Int
-> IO ([CadenceState], [StepDiagnostic])
buildStrataChainOffline GeneratorConfig
defaultConfig GenIO
rng Maybe Int
verbArg
(GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc) Int -> ParsedContext
pctxAtStep CadenceState
start (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
else do
let composerWeights :: ComposerWeights
composerWeights = Text -> ComposerWeights
Q.parseComposerWeights ([Char] -> Text
T.pack (GenConfig -> [Char]
_gcSeek GenConfig
gc))
Pipe
pipe <- IO Pipe
connectNeo4j
([CadenceState], [StepDiagnostic])
result <- Pipe
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall (m :: * -> *) a.
(MonadIO m, HasCallStack) =>
Pipe -> BoltActionT m a -> m a
Bolt.run Pipe
pipe (BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic]))
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a b. (a -> b) -> a -> b
$ GeneratorConfig
-> GenIO
-> Maybe Int
-> Double
-> HarmonicContext
-> (Int -> ParsedContext)
-> ComposerWeights
-> CadenceState
-> Int
-> BoltActionT IO ([CadenceState], [StepDiagnostic])
buildStrataChain GeneratorConfig
defaultConfig GenIO
rng Maybe Int
verbArg
(GenConfig -> Double
_gcEntropy GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc) Int -> ParsedContext
pctxAtStep ComposerWeights
composerWeights CadenceState
start (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
Pipe -> IO ()
forall (m :: * -> *). (MonadIO m, HasCallStack) => Pipe -> m ()
Bolt.close Pipe
pipe
([CadenceState], [StepDiagnostic])
-> IO ([CadenceState], [StepDiagnostic])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([CadenceState], [StepDiagnostic])
result
let
harmonicRootOf :: H.CadenceState -> Int
harmonicRootOf :: CadenceState -> Int
harmonicRootOf CadenceState
cs =
PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (Chord -> NoteName
H.chordNoteName (CadenceState -> Chord
H.fromCadenceState CadenceState
cs)))
harmonicRootNote :: H.CadenceState -> P.NoteName
harmonicRootNote :: CadenceState -> NoteName
harmonicRootNote CadenceState
cs = Chord -> NoteName
H.chordNoteName (CadenceState -> Chord
H.fromCadenceState CadenceState
cs)
chromaIntervals :: Int -> [P.PitchClass] -> [Int]
chromaIntervals :: Int -> [PitchClass] -> [Int]
chromaIntervals Int
rootPC [PitchClass]
chroma =
[Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int]
forall a. Eq a => [a] -> [a]
nub [ (PitchClass -> Int
P.unPitchClass PitchClass
p 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 | PitchClass
p <- [PitchClass]
chroma ]
modeResults :: [Sc.ModeResult]
modeResults :: [ModeResult]
modeResults =
[ [(StrataLabel, Tristrata)] -> Int -> Int -> ModeResult
Strata.modeForTriad [(StrataLabel, Tristrata)]
barSeq Int
i (CadenceState -> Int
harmonicRootOf CadenceState
cs)
| (Int
i, CadenceState
cs) <- [Int] -> [CadenceState] -> [(Int, CadenceState)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [CadenceState]
chain
]
modeChromaList :: [[P.PitchClass]]
modeChromaList :: [[PitchClass]]
modeChromaList =
[ case ModeResult
mr of
Sc.ModeOk Mode
m -> Mode -> [PitchClass]
Sc.modeChroma Mode
m
Sc.ModeInvalid [PitchClass]
pcs -> [PitchClass]
pcs
| ModeResult
mr <- [ModeResult]
modeResults
]
mkChromaCS :: P.NoteName -> [Int] -> H.CadenceState
mkChromaCS :: NoteName -> [Int] -> CadenceState
mkChromaCS NoteName
root [Int]
intervals = NoteName -> Movement -> [Int] -> CadenceState
H.mkCadenceStatePCs NoteName
root Movement
H.Unison [Int]
intervals
mkAuxLayers :: H.CadenceState
-> Sc.StrataLabel
-> [P.PitchClass]
-> (H.CadenceState, H.CadenceState)
mkAuxLayers :: CadenceState
-> StrataLabel -> [PitchClass] -> (CadenceState, CadenceState)
mkAuxLayers CadenceState
triadCS StrataLabel
sCurr [PitchClass]
modeChromaPCs =
let rootPC :: Int
rootPC = CadenceState -> Int
harmonicRootOf CadenceState
triadCS
rootNote :: NoteName
rootNote = CadenceState -> NoteName
harmonicRootNote CadenceState
triadCS
strataInts :: [Int]
strataInts = Int -> [PitchClass] -> [Int]
chromaIntervals Int
rootPC (StrataLabel -> [PitchClass]
Sc.strataChroma StrataLabel
sCurr)
modeInts :: [Int]
modeInts = Int -> [PitchClass] -> [Int]
chromaIntervals Int
rootPC [PitchClass]
modeChromaPCs
strataCS :: CadenceState
strataCS = NoteName -> [Int] -> CadenceState
mkChromaCS NoteName
rootNote [Int]
strataInts
modeCS :: CadenceState
modeCS = NoteName -> [Int] -> CadenceState
mkChromaCS NoteName
rootNote [Int]
modeInts
in (CadenceState
strataCS, CadenceState
modeCS)
stratas :: [CadenceState]
stratas = [CadenceState
s | (CadenceState
s, CadenceState
_) <- [(CadenceState, CadenceState)]
pairs]
modes :: [CadenceState]
modes = [CadenceState
m | (CadenceState
_, CadenceState
m) <- [(CadenceState, CadenceState)]
pairs]
pairs :: [(CadenceState, CadenceState)]
pairs = (CadenceState
-> StrataLabel -> [PitchClass] -> (CadenceState, CadenceState))
-> [CadenceState]
-> [StrataLabel]
-> [[PitchClass]]
-> [(CadenceState, CadenceState)]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 CadenceState
-> StrataLabel -> [PitchClass] -> (CadenceState, CadenceState)
mkAuxLayers [CadenceState]
chain (((StrataLabel, Tristrata) -> StrataLabel)
-> [(StrataLabel, Tristrata)] -> [StrataLabel]
forall a b. (a -> b) -> [a] -> [b]
map (StrataLabel, Tristrata) -> StrataLabel
forall a b. (a, b) -> a
fst [(StrataLabel, Tristrata)]
barSeq) [[PitchClass]]
modeChromaList
provSeq :: Seq (Tristrata, StrataLabel)
provSeq = [(Tristrata, StrataLabel)] -> Seq (Tristrata, StrataLabel)
forall a. [a] -> Seq a
Seq.fromList [(Tristrata
t, StrataLabel
s) | (StrataLabel
s, Tristrata
t) <- Int -> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
forall a. Int -> [a] -> [a]
take ([CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
chain) [(StrataLabel, Tristrata)]
barSeq]
resultPC :: ProgressionContext
resultPC = PC.ProgressionContext
{ triadLayer :: Progression
PC.triadLayer = [CadenceState] -> Progression
Prog.fromCadenceStates [CadenceState]
chain
, strataLayer :: Progression
PC.strataLayer = [CadenceState] -> Progression
Prog.fromCadenceStates [CadenceState]
stratas
, modeLayer :: Progression
PC.modeLayer = [CadenceState] -> Progression
Prog.fromCadenceStates [CadenceState]
modes
, pcProvenance :: Maybe (Seq (Tristrata, StrataLabel))
PC.pcProvenance = Seq (Tristrata, StrataLabel)
-> Maybe (Seq (Tristrata, StrataLabel))
forall a. a -> Maybe a
Just Seq (Tristrata, StrataLabel)
provSeq
}
let starterDiag :: StepDiagnostic
starterDiag = CadenceState -> StepDiagnostic
mkStarterDiag CadenceState
start
allBaseDiags :: [StepDiagnostic]
allBaseDiags = StepDiagnostic
starterDiag StepDiagnostic -> [StepDiagnostic] -> [StepDiagnostic]
forall a. a -> [a] -> [a]
: [StepDiagnostic]
rawDiags
let tristrataIdxOf :: Tristrata -> Maybe Int
tristrataIdxOf Tristrata
t =
let tpairs :: [(Tristrata, Int)]
tpairs = [Tristrata] -> [Int] -> [(Tristrata, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Tristrata]
Sc.validTristrata [Int
1 :: Int ..]
in Tristrata -> [(Tristrata, Int)] -> Maybe Int
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Tristrata
t [(Tristrata, Int)]
tpairs
barSpellingOf :: [P.PitchClass] -> Int -> H.EnharmonicSpelling
barSpellingOf :: [PitchClass] -> Int -> EnharmonicSpelling
barSpellingOf [PitchClass]
chroma Int
rootPC =
let pcs :: [Int]
pcs = Int
rootPC Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int
p | Int
p <- (PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass [PitchClass]
chroma, Int
p Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
rootPC]
in [Int] -> EnharmonicSpelling
H.inferSpelling [Int]
pcs
slashChordWith :: H.EnharmonicSpelling -> H.CadenceState -> String
slashChordWith :: EnharmonicSpelling -> CadenceState -> [Char]
slashChordWith EnharmonicSpelling
spelling CadenceState
cs =
(PitchClass -> NoteName) -> CadenceState -> [Char]
Prog.showHarmony (EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
spelling) CadenceState
cs
attachedDiags :: [StepDiagnostic]
attachedDiags =
[ let rootPC :: Int
rootPC = CadenceState -> Int
harmonicRootOf CadenceState
cs
spelling :: EnharmonicSpelling
spelling = [PitchClass] -> Int -> EnharmonicSpelling
barSpellingOf [PitchClass]
chroma Int
rootPC
(Maybe Mode
mMode, Maybe (PitchClass, ScaleFamily)
mParentKey) = case ModeResult
mr of
Sc.ModeOk Mode
mode -> (Mode -> Maybe Mode
forall a. a -> Maybe a
Just Mode
mode, (PitchClass, ScaleFamily) -> Maybe (PitchClass, ScaleFamily)
forall a. a -> Maybe a
Just (Mode -> (PitchClass, ScaleFamily)
Sc.parentKey Mode
mode))
Sc.ModeInvalid [PitchClass]
_ -> (Maybe Mode
forall a. Maybe a
Nothing, Maybe (PitchClass, ScaleFamily)
forall a. Maybe a
Nothing)
in StepDiagnostic
d { sdStepNumber = i + 1
, sdRenderedChord = Just (slashChordWith spelling cs)
, sdStrataLabel = Just s
, sdTristrata = Just t
, sdTristrataIdx = tristrataIdxOf t
, sdMode = mMode
, sdStrataChroma = Just (Sc.strataChroma s)
, sdModeChroma = Just chroma
, sdSoftBoost = Just (boostFor i)
, sdHarmonicRootPC = Just rootPC
, sdParentKey = mParentKey
, sdModeResult = Just mr
, sdBarSpelling = Just spelling
}
| (Int
i, StepDiagnostic
d, (StrataLabel
s, Tristrata
t), [PitchClass]
chroma, CadenceState
cs, ModeResult
mr) <- [Int]
-> [StepDiagnostic]
-> [(StrataLabel, Tristrata)]
-> [[PitchClass]]
-> [CadenceState]
-> [ModeResult]
-> [(Int, StepDiagnostic, (StrataLabel, Tristrata), [PitchClass],
CadenceState, ModeResult)]
forall {a} {b} {c} {d} {e} {f}.
[a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [(a, b, c, d, e, f)]
zip6 [Int
0..] [StepDiagnostic]
allBaseDiags [(StrataLabel, Tristrata)]
barSeq [[PitchClass]]
modeChromaList [CadenceState]
chain [ModeResult]
modeResults
]
attachedGen :: GenerationDiagnostics
attachedGen = GenerationDiagnostics
{ gdStartCadence :: [Char]
gdStartCadence = Cadence -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> Cadence
H.stateCadence CadenceState
start)
, gdStartRoot :: [Char]
gdStartRoot = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start)
, gdRequestedLen :: Int
gdRequestedLen = Int
n
, gdActualLen :: Int
gdActualLen = [CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
chain
, gdEntropy :: Double
gdEntropy = GenConfig -> Double
_gcEntropy GenConfig
gc
, gdSteps :: [StepDiagnostic]
gdSteps = [StepDiagnostic]
attachedDiags
, gdProgression :: Progression
gdProgression = ProgressionContext -> Progression
PC.triadLayer ProgressionContext
resultPC
}
let Maybe Int
_ = Maybe Int
verbArg
(ProgressionContext, GenerationDiagnostics)
-> IO (ProgressionContext, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ProgressionContext
resultPC, GenerationDiagnostics
attachedGen)
where
zip4 :: [a] -> [b] -> [c] -> [d] -> [(a, b, c, d)]
zip4 [a]
as [b]
bs [c]
cs [d]
ds = [ (a
a, b
b, c
c, d
d) | ((a
a, b
b), (c
c, d
d)) <- [(a, b)] -> [(c, d)] -> [((a, b), (c, d))]
forall a b. [a] -> [b] -> [(a, b)]
zip ([a] -> [b] -> [(a, b)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
as [b]
bs) ([c] -> [d] -> [(c, d)]
forall a b. [a] -> [b] -> [(a, b)]
zip [c]
cs [d]
ds) ]
zip6 :: [a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [(a, b, c, d, e, f)]
zip6 [a]
as [b]
bs [c]
cs [d]
ds [e]
es [f]
fs =
[ (a
a, b
b, c
c, d
d, e
e, f
f)
| ((a
a, b
b, c
c), (d
d, e
e, f
f)) <- [(a, b, c)] -> [(d, e, f)] -> [((a, b, c), (d, e, f))]
forall a b. [a] -> [b] -> [(a, b)]
zip ([a] -> [b] -> [c] -> [(a, b, c)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [a]
as [b]
bs [c]
cs) ([d] -> [e] -> [f] -> [(d, e, f)]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [d]
ds [e]
es [f]
fs)
]
mkStarterDiag :: H.CadenceState -> StepDiagnostic
mkStarterDiag :: CadenceState -> StepDiagnostic
mkStarterDiag CadenceState
cs =
let rootPC :: Int
rootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
cs))
in StepDiagnostic
{ sdStepNumber :: Int
sdStepNumber = Int
1
, sdPriorCadence :: [Char]
sdPriorCadence = [Char]
""
, sdPriorRoot :: [Char]
sdPriorRoot = [Char]
""
, sdPriorRootPC :: Int
sdPriorRootPC = Int
rootPC
, sdSelectedDbIntervals :: [Char]
sdSelectedDbIntervals = [Char]
""
, sdSelectedDbMovement :: [Char]
sdSelectedDbMovement = [Char]
""
, sdSelectedDbFunctionality :: [Char]
sdSelectedDbFunctionality = [Char]
""
, sdGraphCount :: Int
sdGraphCount = Int
0
, sdGraphTop6 :: [([Char], Double)]
sdGraphTop6 = []
, sdFallbackCount :: Int
sdFallbackCount = Int
0
, sdFallbackTop6 :: [([Char], Double, Double, Double, Double)]
sdFallbackTop6 = []
, sdPoolSize :: Int
sdPoolSize = Int
0
, sdEntropyUsed :: Double
sdEntropyUsed = Double
0
, sdGammaIndex :: Int
sdGammaIndex = -Int
1
, sdSelectedFrom :: [Char]
sdSelectedFrom = [Char]
"starter"
, sdPosteriorRoot :: [Char]
sdPosteriorRoot = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
cs)
, sdPosteriorRootPC :: Int
sdPosteriorRootPC = Int
rootPC
, sdRenderedChord :: Maybe [Char]
sdRenderedChord = Maybe [Char]
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
}
runStrataGenFrom :: PC.ProgressionContext
-> Int
-> Int
-> GenConfig
-> IO (PC.ProgressionContext, GenerationDiagnostics)
runStrataGenFrom :: ProgressionContext
-> Int
-> Int
-> GenConfig
-> IO (ProgressionContext, GenerationDiagnostics)
runStrataGenFrom ProgressionContext
srcPC Int
s Int
e GenConfig
gc = do
let srcProvSeq :: Seq (Tristrata, StrataLabel)
srcProvSeq = case ProgressionContext -> Maybe (Seq (Tristrata, StrataLabel))
PC.pcProvenance ProgressionContext
srcPC of
Just Seq (Tristrata, StrataLabel)
sq -> Seq (Tristrata, StrataLabel)
sq
Maybe (Seq (Tristrata, StrataLabel))
Nothing -> [Char] -> Seq (Tristrata, StrataLabel)
forall a. HasCallStack => [Char] -> a
error [Char]
"runStrataGenFrom: source ProgressionContext lacks pcProvenance — call genFrom on a 'genI'/'genP'-derived context"
srcProvList :: [(Tristrata, StrataLabel)]
srcProvList = Seq (Tristrata, StrataLabel) -> [(Tristrata, StrataLabel)]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq (Tristrata, StrataLabel)
srcProvSeq
srcN :: Int
srcN = Seq (Tristrata, StrataLabel) -> Int
forall a. Seq a -> Int
Seq.length Seq (Tristrata, StrataLabel)
srcProvSeq
seedPos :: Int
seedPos = ((Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
srcN) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
targetPos :: Int
targetPos = (Int
e Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
srcN) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
(Tristrata
t_seed, StrataLabel
s_seed) = [(Tristrata, StrataLabel)]
srcProvList [(Tristrata, StrataLabel)] -> Int -> (Tristrata, StrataLabel)
forall a. HasCallStack => [a] -> Int -> a
!! (Int
seedPos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
(Tristrata
t_target, StrataLabel
s_target) = [(Tristrata, StrataLabel)]
srcProvList [(Tristrata, StrataLabel)] -> Int -> (Tristrata, StrataLabel)
forall a. HasCallStack => [a] -> Int -> a
!! (Int
targetPos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
rSize :: Int
rSize = if Int
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
e then Int
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
srcN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
e
triadStates :: [CadenceState]
triadStates = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
srcPC))
cueCS :: CadenceState
cueCS = [CadenceState]
triadStates [CadenceState] -> Int -> CadenceState
forall a. HasCallStack => [a] -> Int -> a
!! (Int
seedPos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
Gen RealWorld
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
let basePctx :: ParsedContext
basePctx = HarmonicContext -> ParsedContext
parseContextOnce (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
allowed :: [Tristrata]
allowed = ParsedContext -> [Tristrata]
pcAllowedTristrata ParsedContext
basePctx
allowed' :: [Tristrata]
allowed' = if [Tristrata] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Tristrata]
allowed then [Tristrata]
Sc.validTristrata else [Tristrata]
allowed
narrow :: Int -> [(Sc.StrataLabel, Sc.Tristrata)] -> [(Sc.StrataLabel, Sc.Tristrata)]
narrow :: Int -> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
narrow Int
i [(StrataLabel, Tristrata)]
pool =
let pool1 :: [(StrataLabel, Tristrata)]
pool1 = case GenConfig -> Maybe [Int]
_gcRelStrata GenConfig
gc of
Just [Int]
ps | Bool -> Bool
not ([Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
ps) ->
let p :: Int
p = [Int]
ps [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i 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]
ps)
in [(StrataLabel
s',Tristrata
t') | (StrataLabel
s',Tristrata
t') <- [(StrataLabel, Tristrata)]
pool, Tristrata -> Int -> StrataLabel
Sc.tristrataStrataAt Tristrata
t' Int
p StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
s']
Maybe [Int]
_ -> [(StrataLabel, Tristrata)]
pool
pool2 :: [(StrataLabel, Tristrata)]
pool2 = case GenConfig -> Maybe [StrataLabel]
_gcAbsStrata GenConfig
gc of
Just [StrataLabel]
ss | Bool -> Bool
not ([StrataLabel] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [StrataLabel]
ss) ->
let lbl :: StrataLabel
lbl = [StrataLabel]
ss [StrataLabel] -> Int -> StrataLabel
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` [StrataLabel] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [StrataLabel]
ss)
in [(StrataLabel
s',Tristrata
t') | (StrataLabel
s',Tristrata
t') <- [(StrataLabel, Tristrata)]
pool1, StrataLabel
s' StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
lbl]
Maybe [StrataLabel]
_ -> [(StrataLabel, Tristrata)]
pool1
in [(StrataLabel, Tristrata)]
pool2
[Int]
walkSeeds <- (Int -> IO Int) -> [Int] -> IO [Int]
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 (IO Int -> Int -> IO Int
forall a b. a -> b -> a
const ((Int, Int) -> Gen RealWorld -> IO Int
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *). StatefulGen g m => (Int, Int) -> g -> m Int
uniformRM (Int
forall a. Bounded a => a
minBound :: Int, Int
forall a. Bounded a => a
maxBound :: Int) Gen RealWorld
rng))
[Int
1 .. Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
rSize]
let
walkRange :: Int -> [Int] -> (Sc.StrataLabel, Sc.Tristrata) -> [(Sc.StrataLabel, Sc.Tristrata)]
walkRange :: Int
-> [Int] -> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
walkRange Int
i [Int]
seeds (StrataLabel, Tristrata)
prev
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
rSize = []
| Bool
otherwise =
let rawCands :: [(StrataLabel, Tristrata)]
rawCands = Int -> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
narrow Int
i ([Tristrata]
-> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
Strata.allowedNext [Tristrata]
allowed' (StrataLabel, Tristrata)
prev)
isFinal :: Bool
isFinal = Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
rSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
filtered :: [(StrataLabel, Tristrata)]
filtered =
if Bool
isFinal
then ((StrataLabel, Tristrata) -> Bool)
-> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(StrataLabel, Tristrata)
p -> (StrataLabel
s_target, Tristrata
t_target)
(StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Tristrata]
-> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
Strata.allowedNext [Tristrata]
allowed' (StrataLabel, Tristrata)
p)
[(StrataLabel, Tristrata)]
rawCands
else [(StrataLabel, Tristrata)]
rawCands
cands :: [(StrataLabel, Tristrata)]
cands = if Bool
isFinal Bool -> Bool -> Bool
&& [(StrataLabel, Tristrata)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(StrataLabel, Tristrata)]
filtered then [(StrataLabel, Tristrata)]
rawCands else [(StrataLabel, Tristrata)]
filtered
(Int
seed, [Int]
seedsRest) = case [Int]
seeds of
(Int
sd : [Int]
rest) -> (Int
sd, [Int]
rest)
[] -> (Int
0, [])
chosen :: (StrataLabel, Tristrata)
chosen = (StrataLabel, Tristrata)
-> Maybe (StrataLabel, Tristrata) -> (StrataLabel, Tristrata)
forall a. a -> Maybe a -> a
fromMaybe (StrataLabel, Tristrata)
prev (Int
-> (StrataLabel, Tristrata)
-> [(StrataLabel, Tristrata)]
-> Maybe (StrataLabel, Tristrata)
Strata.selectNextSeeded Int
seed (StrataLabel, Tristrata)
prev [(StrataLabel, Tristrata)]
cands)
in (StrataLabel, Tristrata)
chosen (StrataLabel, Tristrata)
-> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
forall a. a -> [a] -> [a]
: Int
-> [Int] -> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
walkRange (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Int]
seedsRest (StrataLabel, Tristrata)
chosen
regenBarSeq :: [(Sc.StrataLabel, Sc.Tristrata)]
regenBarSeq :: [(StrataLabel, Tristrata)]
regenBarSeq = (StrataLabel
s_seed, Tristrata
t_seed) (StrataLabel, Tristrata)
-> [(StrataLabel, Tristrata)] -> [(StrataLabel, Tristrata)]
forall a. a -> [a] -> [a]
: Int
-> [Int] -> (StrataLabel, Tristrata) -> [(StrataLabel, Tristrata)]
walkRange Int
0 [Int]
walkSeeds (StrataLabel
s_seed, Tristrata
t_seed)
regenN :: Int
regenN = [(StrataLabel, Tristrata)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(StrataLabel, Tristrata)]
regenBarSeq
strataOvertonesString :: Sc.StrataLabel -> String
strataOvertonesString :: StrataLabel -> [Char]
strataOvertonesString StrataLabel
sl =
[[Char]] -> [Char]
unwords [ NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
P.sharp (Int -> PitchClass
P.mkPitchClass (PitchClass -> Int
P.unPitchClass PitchClass
pc))) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
| PitchClass
pc <- StrataLabel -> [PitchClass]
Sc.strataChroma StrataLabel
sl ]
boostFor :: Int -> Double
boostFor :: Int -> Double
boostFor Int
0 = Double
1.0
boostFor Int
i =
let (StrataLabel
sCurr, Tristrata
tCurr) = [(StrataLabel, Tristrata)]
regenBarSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! Int
i
(StrataLabel
sPrev, Tristrata
tPrev) = [(StrataLabel, Tristrata)]
regenBarSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
sGrand :: Maybe StrataLabel
sGrand = if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 then StrataLabel -> Maybe StrataLabel
forall a. a -> Maybe a
Just ((StrataLabel, Tristrata) -> StrataLabel
forall a b. (a, b) -> a
fst ([(StrataLabel, Tristrata)]
regenBarSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2))) else Maybe StrataLabel
forall a. Maybe a
Nothing
mSame :: Double
mSame = if StrataLabel
sCurr StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
sPrev then GenConfig -> Double
_gcBoostSame GenConfig
gc else Double
1.0
mFlip :: Double
mFlip = case Maybe StrataLabel
sGrand of
Just StrataLabel
sg | StrataLabel
sCurr StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
== StrataLabel
sg Bool -> Bool -> Bool
&& StrataLabel
sCurr StrataLabel -> StrataLabel -> Bool
forall a. Eq a => a -> a -> Bool
/= StrataLabel
sPrev -> GenConfig -> Double
_gcBoostFlip GenConfig
gc
Maybe StrataLabel
_ -> Double
1.0
mTri :: Double
mTri = if Tristrata
tCurr Tristrata -> Tristrata -> Bool
forall a. Eq a => a -> a -> Bool
== Tristrata
tPrev then GenConfig -> Double
_gcBoostTri GenConfig
gc else Double
1.0
Tristrata
_ = Tristrata
tPrev
in Double
mSame Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
mFlip Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
mTri
pctxAt :: Int -> ParsedContext
pctxAt :: Int -> ParsedContext
pctxAt Int
barIdx1 =
let i :: Int
i = Int
barIdx1
(StrataLabel
sl, Tristrata
_) = [(StrataLabel, Tristrata)]
regenBarSeq [(StrataLabel, Tristrata)] -> Int -> (StrataLabel, Tristrata)
forall a. HasCallStack => [a] -> Int -> a
!! Int
i
ctx' :: HarmonicContext
ctx' = [Char] -> HarmonicContext -> HarmonicContext
hcOvertones (StrataLabel -> [Char]
strataOvertonesString StrataLabel
sl) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
ctx'
boost :: Double
boost = Int -> Double
boostFor Int
i
in ParsedContext
pctx { pcSoftBoost = boost, pcStrictContainment = True }
(ProgressionContext
regenPC, GenerationDiagnostics
regenDiag) <- StrataLabel
-> GenConfig
-> CadenceState
-> GenIO
-> StrataLabel
-> Tristrata
-> [(StrataLabel, Tristrata)]
-> (Int -> ParsedContext)
-> (Int -> Double)
-> Int
-> IO (ProgressionContext, GenerationDiagnostics)
runStrataGenBody StrataLabel
s_seed GenConfig
gc CadenceState
cueCS Gen RealWorld
GenIO
rng StrataLabel
s_seed Tristrata
t_seed
[(StrataLabel, Tristrata)]
regenBarSeq Int -> ParsedContext
pctxAt Int -> Double
boostFor Int
regenN
let
dropCue :: Prog.Progression -> Prog.Progression
dropCue :: Progression -> Progression
dropCue (Prog.Progression Seq CadenceState
sq) = Seq CadenceState -> Progression
Prog.Progression (Int -> Seq CadenceState -> Seq CadenceState
forall a. Int -> Seq a -> Seq a
Seq.drop Int
1 Seq CadenceState
sq)
insertPC :: ProgressionContext
insertPC = PC.ProgressionContext
{ triadLayer :: Progression
PC.triadLayer = Progression -> Progression
dropCue (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
regenPC)
, strataLayer :: Progression
PC.strataLayer = Progression -> Progression
dropCue (ProgressionContext -> Progression
PC.strataLayer ProgressionContext
regenPC)
, modeLayer :: Progression
PC.modeLayer = Progression -> Progression
dropCue (ProgressionContext -> Progression
PC.modeLayer ProgressionContext
regenPC)
, pcProvenance :: Maybe (Seq (Tristrata, StrataLabel))
PC.pcProvenance = case ProgressionContext -> Maybe (Seq (Tristrata, StrataLabel))
PC.pcProvenance ProgressionContext
regenPC of
Just Seq (Tristrata, StrataLabel)
sq -> Seq (Tristrata, StrataLabel)
-> Maybe (Seq (Tristrata, StrataLabel))
forall a. a -> Maybe a
Just (Int -> Seq (Tristrata, StrataLabel) -> Seq (Tristrata, StrataLabel)
forall a. Int -> Seq a -> Seq a
Seq.drop Int
1 Seq (Tristrata, StrataLabel)
sq)
Maybe (Seq (Tristrata, StrataLabel))
Nothing -> Maybe (Seq (Tristrata, StrataLabel))
forall a. Maybe a
Nothing
}
splicedPC :: ProgressionContext
splicedPC = ProgressionContext
-> Int -> Int -> ProgressionContext -> ProgressionContext
PC.pcSplice ProgressionContext
srcPC Int
s Int
e ProgressionContext
insertPC
(ProgressionContext, GenerationDiagnostics)
-> IO (ProgressionContext, GenerationDiagnostics)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ProgressionContext
splicedPC, GenerationDiagnostics
regenDiag)
printCueEscapeNotice :: HarmonicContext -> H.CadenceState -> IO ()
printCueEscapeNotice :: HarmonicContext -> CadenceState -> IO ()
printCueEscapeNotice HarmonicContext
ctx CadenceState
start = do
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
ctx
rootPC :: Int
rootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start))
intervals :: [Int]
intervals = (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
start))
absPCs :: [Int]
absPCs = [ (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]
intervals ]
toneOff :: [Int]
toneOff = if ParsedContext -> Bool
pcIsKeyWild ParsedContext
pctx Bool -> Bool -> Bool
&& ParsedContext -> Bool
pcIsOvertonesWild ParsedContext
pctx
then []
else [ Int
p | Int
p <- [Int] -> [Int]
forall a. Eq a => [a] -> [a]
nub [Int]
absPCs
, Bool -> Bool
not (Int -> IntSet -> Bool
IntSet.member Int
p (ParsedContext -> IntSet
pcEffectiveOvertones ParsedContext
pctx)) ]
rootOff :: Bool
rootOff = Bool -> Bool
not (ParsedContext -> Bool
pcIsRootsWild ParsedContext
pctx)
Bool -> Bool -> Bool
&& Bool -> Bool
not (Int -> IntSet -> Bool
IntSet.member Int
rootPC (ParsedContext -> IntSet
pcAllowedBassNotes ParsedContext
pctx))
spelling :: EnharmonicSpelling
spelling = [Int] -> EnharmonicSpelling
H.inferSpelling [Int]
absPCs
enharm :: PitchClass -> NoteName
enharm = EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
spelling
spellPC :: Int -> [Char]
spellPC Int
p = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
enharm (Int -> PitchClass
P.mkPitchClass Int
p))
parts :: [[Char]]
parts = [ [Char]
"contains " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords ((Int -> [Char]) -> [Int] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Int -> [Char]
spellPC [Int]
toneOff)
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" outside the key/overtone set" | Bool -> Bool
not ([Int] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
toneOff) ]
[[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [ [Char]
"root " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
spellPC Int
rootPC [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" outside the allowed roots"
| Bool
rootOff ]
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not ([[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
parts)) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"⚠ cue escapes R: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"; " [[Char]]
parts
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ HarmonicContext -> [Char]
forall a. Show a => a -> [Char]
show HarmonicContext
ctx [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"
printInvalidCueError :: H.CadenceState -> Sc.StrataLabel -> IO ()
printInvalidCueError :: CadenceState -> StrataLabel -> IO ()
printInvalidCueError CadenceState
start StrataLabel
s = do
let rootPC :: Int
rootPC = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
start))
intervals :: [Int]
intervals = (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
start))
absPCs :: [Int]
absPCs = [ (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]
intervals ]
spelling :: EnharmonicSpelling
spelling = [Int] -> EnharmonicSpelling
H.inferSpelling [Int]
absPCs
enharm :: PitchClass -> NoteName
enharm = EnharmonicSpelling -> PitchClass -> NoteName
H.enharmonicFunc EnharmonicSpelling
spelling
chordName :: [Char]
chordName = (PitchClass -> NoteName) -> CadenceState -> [Char]
Prog.showHarmony PitchClass -> NoteName
enharm CadenceState
start
strataPCs :: [Int]
strataPCs = [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort ((PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (StrataLabel -> [PitchClass]
Sc.strataChroma StrataLabel
s))
offenders :: [Int]
offenders = [ Int
p | Int
p <- [Int]
absPCs, Int
p Int -> [Int] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Int]
strataPCs ]
spellPC :: Int -> [Char]
spellPC Int
p = NoteName -> [Char]
forall a. Show a => a -> [Char]
show (PitchClass -> NoteName
enharm (Int -> PitchClass
P.mkPitchClass Int
p))
strataNames :: [Char]
strataNames = [[Char]] -> [Char]
unwords ((Int -> [Char]) -> [Int] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Int -> [Char]
spellPC [Int]
strataPCs)
offenderStr :: [Char]
offenderStr = [[Char]] -> [Char]
unwords ((Int -> [Char]) -> [Int] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Int -> [Char]
spellPC [Int]
offenders)
[Char] -> IO ()
putStrLn [Char]
""
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"⚠ invalid starting state: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
chordName
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (escapes strata " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StrataLabel -> [Char]
forall a. Show a => a -> [Char]
show StrataLabel
s
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" — contains " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
offenderStr [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" outside {" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
strataNames [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"})"
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
" viable triads in strata " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ StrataLabel -> [Char]
forall a. Show a => a -> [Char]
show StrataLabel
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" {" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
strataNames [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"}:"
([Char] -> IO ()) -> [[Char]] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ([Char] -> IO ()
putStrLn ([Char] -> IO ()) -> ([Char] -> [Char]) -> [Char] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++)) (StrataLabel -> (PitchClass -> NoteName) -> [[Char]]
viableTriadLines StrataLabel
s PitchClass -> NoteName
enharm)
[Char] -> IO ()
putStrLn [Char]
""
viableTriadLines :: Sc.StrataLabel -> (P.PitchClass -> P.NoteName) -> [String]
viableTriadLines :: StrataLabel -> (PitchClass -> NoteName) -> [[Char]]
viableTriadLines StrataLabel
s PitchClass -> NoteName
enharm =
let strataPCs :: [Int]
strataPCs = [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort ((PitchClass -> Int) -> [PitchClass] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map PitchClass -> Int
P.unPitchClass (StrataLabel -> [PitchClass]
Sc.strataChroma StrataLabel
s))
triadsFor :: Int -> [[Char]]
triadsFor Int
r =
let ts :: [[Int]]
ts = (Int, [Int]) -> [[Int]]
possibleTriads (Int
r, [Int]
strataPCs)
names :: [[Char]]
names = [[Char]] -> [[Char]]
forall a. Eq a => [a] -> [a]
nub [ (PitchClass -> NoteName) -> Chord -> [Char]
Prog.showTriad PitchClass -> NoteName
enharm ((PitchClass -> NoteName) -> [Int] -> Chord
H.toTriad PitchClass -> NoteName
enharm [Int]
pcs) | [Int]
pcs <- [[Int]]
ts ]
in [[Char]]
names
allNames :: [[Char]]
allNames = (Int -> [[Char]]) -> [Int] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Int -> [[Char]]
triadsFor [Int]
strataPCs
colWidth :: Int
colWidth = if [[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
allNames then Int
0 else [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (([Char] -> Int) -> [[Char]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Char]]
allNames) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2
rootField :: Int -> [Char]
rootField = Int -> [Char] -> [Char]
padR Int
4 ([Char] -> [Char]) -> (Int -> [Char]) -> Int -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NoteName -> [Char]
forall a. Show a => a -> [Char]
show (NoteName -> [Char]) -> (Int -> NoteName) -> Int -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PitchClass -> NoteName
enharm (PitchClass -> NoteName) -> (Int -> PitchClass) -> Int -> NoteName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> PitchClass
P.mkPitchClass
in [ Int -> [Char]
rootField Int
r [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ ([Char] -> [Char]) -> [[Char]] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Int -> [Char] -> [Char]
padR Int
colWidth) (Int -> [[Char]]
triadsFor Int
r)
| Int
r <- [Int]
strataPCs
]
where
padR :: Int -> [Char] -> [Char]
padR Int
n [Char]
str = [Char]
str [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (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]
str)) Char
' '