module Harmonic.Framework.Builder
(
gen
, gen'
, gen''
, genGrid
, genGrid'
, genGrid''
, genFrom
, genFrom'
, genFrom''
, genE
, genE'
, genE''
, genJ, genJ', genJ''
, steer
, 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
, generate'
, generate''
, genPrint
, genPrint'
, genPrint''
, genSilent
, genStandard
, genVerbose
, printDiagnostics
, StepDiagnostic(..)
, GenerationDiagnostics(..)
, TransformTrace(..)
, AdvanceTrace(..)
, HarmonicContext(..)
, harmonicContext
, hContext
, Drift(..)
, hcOvertones
, hcKey
, hcRoots
, dissonant
, consonant
, invSkip
, hcPedal
, hcTristrata
, parseComposersWithOrder
, makePortmanteau
, extractByPosition
, takeFromBeginning
, takeFromEnd
, takeFromMiddle
, printHeader
) where
import Harmonic.Database (DbActionT, runDb)
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 (createSystemRandom)
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 Harmonic.Rules.Import.Graph (connectNeo4j)
import qualified Harmonic.Evaluation.Scoring.Progression as PS
import Harmonic.Evaluation.Analysis.KeyArea (chordscale)
import Control.Monad.IO.Class (liftIO)
import Harmonic.Rules.Constraints.Filter (parseTuningNamed)
import Harmonic.Rules.Constraints.Overtone (formatOvertoneAnnotationPipe)
import Data.Foldable (toList)
import Data.List (nub)
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 Harmonic.Framework.Builder.Modifiers
import Harmonic.Framework.Builder.StrataGen (runStrataGen, runStrataGenFrom, strataStartCue)
import Harmonic.Framework.Builder.JazzGen (runJazzGen, runJazzGenFrom, jazzGuardSeek, jazzStartCue)
import Harmonic.Framework.Builder.PolyGen (runPolyGen, runPolyGenFrom)
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
nBars Text
composerStr Double
ent HarmonicContext
context =
CadenceState
-> Int -> Text -> Double -> HarmonicContext -> IO Progression
generateWith CadenceState
start Int
nBars Text
composerStr Double
ent HarmonicContext
context
genPrint :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genPrint :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genPrint CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx = do
(prog, _diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
putStrLn ""
printHeader (T.pack composerStr) ent ctx
print prog
putStrLn ""
pure prog
generateWith :: H.CadenceState
-> Int
-> Text
-> Double
-> HarmonicContext
-> IO Prog.Progression
generateWith :: CadenceState
-> Int -> Text -> Double -> HarmonicContext -> IO Progression
generateWith CadenceState
start Int
nBars Text
composerStr Double
ent HarmonicContext
context = do
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
context
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
source <- sourceFor composerStr
(chain, _) <- buildChainWith source rng Nothing ent context (const pctx) start (nBars - 1)
pure $ chainToProgression 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
nBars [Char]
composerStr Double
ent HarmonicContext
ctx =
Maybe Int
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWithV (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1) CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
genPrint' :: H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO Prog.Progression
genPrint' :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genPrint' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx = do
(prog, diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
renderStandardSteps show composerStr ctx diag
putStrLn ""
printHeader (T.pack composerStr) ent ctx
print prog
putStrLn ""
pure prog
renderStandardSteps :: (Int -> String) -> String -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps :: (Int -> [Char])
-> [Char] -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps Int -> [Char]
barLabel [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 (ent " [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 = case [CadenceState]
allStates of
(CadenceState
a0 : [CadenceState]
_) | Bool
hasAnnotation ->
let ann :: [Char]
ann = CadenceState -> [Char]
annotateState CadenceState
a0
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
[CadenceState]
_ -> [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]
barLabel Int
1 [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": " [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]
barLabel 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
[Char] -> IO ()
putStrLn [Char]
""
[Char] -> IO ()
putStrLn [Char]
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
genWithV :: Maybe Int -> H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO (Prog.Progression, GenerationDiagnostics)
genWithV :: Maybe Int
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWithV Maybe Int
mLevel CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
context = do
let pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce HarmonicContext
context
rng <- IO (Gen RealWorld)
IO GenIO
createSystemRandom
source <- sourceFor (T.pack composerStr)
(chain, stepDiags) <- buildChainWith source rng mLevel ent context (const pctx) start (nBars - 1)
let prog = [CadenceState] -> Progression
chainToProgression [CadenceState]
chain
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
nBars
, gdActualLen :: Int
gdActualLen = Progression -> Int
Prog.progLength Progression
prog
, gdEntropy :: Double
gdEntropy = Double
ent
, gdSteps :: [StepDiagnostic]
gdSteps = [StepDiagnostic]
stepDiags
, gdProgression :: Progression
gdProgression = Progression
prog
, gdJazzTrace :: [[Char]]
gdJazzTrace = []
}
pure (prog, 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
nBars [Char]
composerStr Double
ent HarmonicContext
ctx =
Maybe Int
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWithV (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
2) CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
genPrint'' :: H.CadenceState -> Int -> String -> Double -> HarmonicContext
-> IO Prog.Progression
genPrint'' :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genPrint'' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx = do
(prog, diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate'' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
renderVerboseSteps show composerStr diag
putStrLn ""
printHeader (T.pack composerStr) ent ctx
print prog
putStrLn ""
pure prog
renderVerboseSteps :: (Int -> String) -> String -> GenerationDiagnostics -> IO ()
renderVerboseSteps :: (Int -> [Char]) -> [Char] -> GenerationDiagnostics -> IO ()
renderVerboseSteps Int -> [Char]
barLabel [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 (ent " [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 " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
barLabel Int
1 [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": " [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]
barLabel 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]
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
genSilent :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genSilent :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genSilent CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx = do
(prog, _diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
pure prog
genStandard :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genStandard :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genStandard CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx = do
(prog, diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
printDiagnostics 1 diag
pure prog
genVerbose :: H.CadenceState -> Int -> String -> Double -> HarmonicContext -> IO Prog.Progression
genVerbose :: CadenceState
-> Int -> [Char] -> Double -> HarmonicContext -> IO Progression
genVerbose CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx = do
(prog, diag) <- CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
generate'' CadenceState
start Int
nBars [Char]
composerStr Double
ent HarmonicContext
ctx
printDiagnostics 2 diag
pure prog
diagLevelOf :: Verbosity -> Maybe Int
diagLevelOf :: Verbosity -> Maybe Int
diagLevelOf Verbosity
Silent = Maybe Int
forall a. Maybe a
Nothing
diagLevelOf Verbosity
Standard = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1
diagLevelOf Verbosity
Verbose = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
2
execGenConfig :: GenConfig -> IO Prog.Progression
execGenConfig :: GenConfig -> IO Progression
execGenConfig GenConfig
gc = ProgressionContext -> Progression
PC.triadLayer (ProgressionContext -> Progression)
-> IO ProgressionContext -> IO Progression
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenConfig -> IO ProgressionContext
execGenConfigPC GenConfig
gc
execGenConfigWithDiag :: GenConfig -> IO (Prog.Progression, GenerationDiagnostics)
execGenConfigWithDiag :: GenConfig -> IO (Progression, GenerationDiagnostics)
execGenConfigWithDiag GenConfig
gc = do
start <- case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
Fresh | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc) -> GenConfig -> IO CadenceState
tonalStartCue GenConfig
gc
GenMode
GridMode | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc) -> GenConfig -> IO CadenceState
tonalStartCue GenConfig
gc
GenMode
_ -> GenConfig -> IO CadenceState
_gcCue GenConfig
gc
case _gcMode gc of
GenMode
JazzMode -> [Char] -> IO (Progression, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"unreachable: JazzMode dispatches to runJazzGen before this case"
FromProgJ {} -> [Char] -> IO (Progression, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"unreachable: FromProgJ dispatches to runJazzGenFrom before this case"
GenMode
PolyMode -> [Char] -> IO (Progression, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"unreachable: PolyMode dispatches to runPolyGen before this case"
FromProgPoly {} -> [Char] -> IO (Progression, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"unreachable: FromProgPoly dispatches to runPolyGenFrom before this case"
GenMode
Fresh ->
Maybe Int
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWithV (Verbosity -> Maybe Int
diagLevelOf (GenConfig -> Verbosity
_gcVerbosity GenConfig
gc)) 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
, gdJazzTrace :: [[Char]]
gdJazzTrace = []
}
(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) ]
srcExtended :: Bool
srcExtended = 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. Ord 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 (Bool
srcExtended 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
$
[Char] -> IO ()
putStrLn [Char]
"genFrom: extended source — regenerated bars come back as plain triads (the walk seeds from each bar's most-consonant embedded triad)"
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
srcMixed 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
$
[Char] -> IO ()
putStrLn [Char]
"genFrom: hand-mixed source cardinalities — regenerating as plain triads (regen never amplifies mixing)"
(fullProg, regenDiag) <- Maybe Int
-> CadenceState
-> Int
-> [Char]
-> Double
-> HarmonicContext
-> IO (Progression, GenerationDiagnostics)
genWithV (Verbosity -> Maybe Int
diagLevelOf (GenConfig -> Verbosity
_gcVerbosity GenConfig
gc)) 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 = Int -> [CadenceState] -> [CadenceState]
forall a. Int -> [a] -> [a]
drop Int
1 ([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 -> Int -> Int -> [CadenceState] -> Progression
Prog.spliceProgression Progression
srcProg Int
s Int
e [CadenceState]
newChords
pure (result, regenDiag)
StrataMode StrataLabel
_ -> [Char] -> IO (Progression, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"unreachable: StrataMode dispatches to runStrataGen before this case"
FromProgPC {} -> [Char] -> IO (Progression, GenerationDiagnostics)
forall a. HasCallStack => [Char] -> a
error [Char]
"unreachable: FromProgPC dispatches to runStrataGenFrom before this case"
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
PolyMode -> IO ()
emitCueNotice
GenMode
JazzMode -> IO ()
emitCueNotice
StrataMode StrataLabel
_ -> IO ()
emitCueNotice
GenMode
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
([Char] -> IO ()) -> [[Char]] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ [Char] -> IO ()
putStrLn (ParsedContext -> [[Char]]
pcWarnings (HarmonicContext -> ParsedContext
parseContextOnce (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)))
let isStrata :: Bool
isStrata = case GenConfig -> GenMode
_gcMode GenConfig
gc of
StrataMode StrataLabel
_ -> Bool
True
FromProgPC {} -> Bool
True
GenMode
_ -> Bool
False
isJazz :: Bool
isJazz = case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
JazzMode -> Bool
True
FromProgJ {} -> Bool
True
GenMode
_ -> Bool
False
isPoly :: Bool
isPoly = case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
PolyMode -> Bool
True
FromProgPoly {} -> Bool
True
GenMode
_ -> Bool
False
let nBars :: Int
nBars = Progression -> Int
Prog.progLength (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
regenLabel :: Int -> Int -> [Char]
regenLabel Int
s Int
k = Int -> [Char]
forall a. Show a => a -> [Char]
show (((Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 Int
nBars) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
barLabel :: Int -> [Char]
barLabel = case GenConfig -> GenMode
_gcMode GenConfig
gc of
FromProg Progression
_ Int
s Int
_ -> Int -> Int -> [Char]
regenLabel Int
s
FromProgPC ProgressionContext
_ Int
s Int
_ -> Int -> Int -> [Char]
regenLabel Int
s
FromProgJ ProgressionContext
_ Int
s Int
_ -> Int -> Int -> [Char]
regenLabel Int
s
FromProgPoly ProgressionContext
_ Int
s Int
_ -> Int -> Int -> [Char]
regenLabel Int
s
GenMode
_ -> Int -> [Char]
forall a. Show a => a -> [Char]
show
regenNote :: IO ()
regenNote = case GenConfig -> GenMode
_gcMode GenConfig
gc of
FromProg Progression
_ Int
s Int
_ | GenConfig -> Verbosity
_gcVerbosity GenConfig
gc Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
/= Verbosity
Silent ->
[Char] -> IO ()
putStrLn (Int -> [Char]
regenNoteStr Int
s)
FromProgPC ProgressionContext
_ Int
s Int
_ | GenConfig -> Verbosity
_gcVerbosity GenConfig
gc Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
/= Verbosity
Silent ->
[Char] -> IO ()
putStrLn (Int -> [Char]
regenNoteStr Int
s)
FromProgJ ProgressionContext
_ Int
s Int
_ | GenConfig -> Verbosity
_gcVerbosity GenConfig
gc Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
/= Verbosity
Silent ->
[Char] -> IO ()
putStrLn (Int -> [Char]
regenNoteStr Int
s)
FromProgPoly ProgressionContext
_ Int
s Int
_ | GenConfig -> Verbosity
_gcVerbosity GenConfig
gc Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
/= Verbosity
Silent ->
[Char] -> IO ()
putStrLn (Int -> [Char]
regenNoteStr Int
s)
GenMode
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
regenNoteStr :: Int -> [Char]
regenNoteStr Int
s =
let rN :: Int
rN = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (GenerationDiagnostics -> Int
gdActualLen GenerationDiagnostics
diag Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
eEff :: Int
eEff = ((Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rN) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 Int
nBars) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
in [Char]
"regenerated bars " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
s [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 Int
eEff [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" of "
[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
nBars [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" (trace numbers are source bars; first row is the seed)"
IO ()
regenNote
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
_ | Bool
isJazz -> ([Char] -> IO ()) -> [[Char]] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ [Char] -> IO ()
putStrLn (GenerationDiagnostics -> [[Char]]
gdJazzTrace GenerationDiagnostics
diag)
Verbosity
Standard
| Bool
isStrata -> (Int -> [Char]) -> Int -> GenerationDiagnostics -> IO ()
printStrataDiagnostics Int -> [Char]
barLabel Int
1 GenerationDiagnostics
diag
| Bool
isPoly -> (Int -> [Char]) -> Int -> GenerationDiagnostics -> IO ()
printPolyDiagnostics Int -> [Char]
barLabel Int
1 GenerationDiagnostics
diag
| Bool
otherwise -> (Int -> [Char])
-> [Char] -> HarmonicContext -> GenerationDiagnostics -> IO ()
renderStandardSteps Int -> [Char]
barLabel (GenConfig -> [Char]
_gcSeek GenConfig
gc) (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc) GenerationDiagnostics
diag
Verbosity
Verbose
| Bool
isStrata -> (Int -> [Char]) -> Int -> GenerationDiagnostics -> IO ()
printStrataDiagnostics Int -> [Char]
barLabel Int
2 GenerationDiagnostics
diag
| Bool
isPoly -> (Int -> [Char]) -> Int -> GenerationDiagnostics -> IO ()
printPolyDiagnostics Int -> [Char]
barLabel Int
2 GenerationDiagnostics
diag
| Bool
otherwise -> (Int -> [Char]) -> [Char] -> GenerationDiagnostics -> IO ()
renderVerboseSteps Int -> [Char]
barLabel (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)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isPoly (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
[Char] -> IO ()
putStrLn [Char]
" combined (TSM):"
Progression -> IO ()
forall a. Show a => a -> IO ()
print (Layer -> ProgressionContext -> Progression
PC.layer Layer
PC.TSM 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
(pc, diag) <- GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc
emitFinalised gc (pc, diag)
pure pc
singlePassExecPCWithDiag :: GenConfig -> IO (PC.ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag :: GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc = case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
JazzMode -> GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
runJazzGen GenConfig
gc
FromProgJ ProgressionContext
srcPC Int
s Int
e -> ProgressionContext
-> Int
-> Int
-> GenConfig
-> IO (ProgressionContext, GenerationDiagnostics)
runJazzGenFrom ProgressionContext
srcPC Int
s Int
e GenConfig
gc
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
PolyMode -> GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
runPolyGen GenConfig
gc
FromProgPoly ProgressionContext
srcPC Int
s Int
e -> ProgressionContext
-> Int
-> Int
-> GenConfig
-> IO (ProgressionContext, GenerationDiagnostics)
runPolyGenFrom ProgressionContext
srcPC Int
s Int
e GenConfig
gc
GenMode
_ -> do
(prog, diag) <- GenConfig -> IO (Progression, GenerationDiagnostics)
execGenConfigWithDiag GenConfig
gc
pure (chordscale (PC.fromProgression prog), diag)
generateBest :: GenConfig -> IO PC.ProgressionContext
generateBest :: GenConfig -> IO ProgressionContext
generateBest GenConfig
gc0 = do
[Char] -> IO ()
putStrLn [Char]
"composing .."
start0 <- case GenConfig -> GenMode
_gcMode GenConfig
gc0 of
StrataMode StrataLabel
sLbl | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc0) -> StrataLabel -> GenConfig -> IO CadenceState
strataStartCue StrataLabel
sLbl GenConfig
gc0
GenMode
JazzMode | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc0) -> GenConfig -> IO CadenceState
jazzStartCue GenConfig
gc0
GenMode
Fresh | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc0) -> GenConfig -> IO CadenceState
tonalStartCue GenConfig
gc0
GenMode
GridMode | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc0) -> GenConfig -> IO CadenceState
tonalStartCue GenConfig
gc0
GenMode
PolyMode | Bool -> Bool
not (GenConfig -> Bool
_gcCueExplicit GenConfig
gc0) -> GenConfig -> IO CadenceState
tonalStartCue GenConfig
gc0
GenMode
_ -> GenConfig -> IO CadenceState
_gcCue GenConfig
gc0
let gc = GenConfig
gc0 { _gcCue = pure start0, _gcCueExplicit = True }
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"
isJazzGc = case GenConfig -> GenMode
_gcMode GenConfig
gc of
GenMode
JazzMode -> Bool
True
FromProgJ {} -> Bool
True
GenMode
_ -> Bool
False
(winnerPC, winnerDiag, diags) <-
if isJazzGc then runJazzBest gc
else if online then runOnline gc else runOffline gc
when (PC.pcLength winnerPC == 0) $
putStrLn "⚠ attempt: every attempt produced an empty progression — run the same chain without attempt for the full diagnosis (e.g. an invalid genP cue)"
emitFinalised gc (winnerPC, winnerDiag)
when (_gcVerbosity gc == Verbose && _gcMaxAttempts gc > 1) $
printAttemptScoreboard (_gcViabilityFloor gc) diags
pure 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
scored <- GenConfig -> Int -> Int -> Double -> IO [ScoredAttempt]
offlineLoop GenConfig
gc Int
maxN Int
target Double
floorT
finaliseScored gc 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 <- IO DbConn
connectNeo4j
cache <- PS.newTransitionCache
scored <- runDb pipe (onlineLoop cache seekTxt gc maxN target floorT)
finaliseScored gc scored
runJazzBest :: GenConfig
-> IO (PC.ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runJazzBest :: GenConfig
-> IO
(ProgressionContext, GenerationDiagnostics, [AttemptDiagnostic])
runJazzBest GenConfig
gc = do
GenConfig -> IO ()
jazzGuardSeek GenConfig
gc
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 <- IO DbConn
connectNeo4j
cache <- PS.newTransitionCache
scored <- runDb pipe (jazzLoop cache seekTxt gc maxN target floorT)
finaliseScored gc scored
jazzLoop
:: PS.TransitionCache -> T.Text -> GenConfig -> Int -> Int -> Double
-> DbActionT [ScoredAttempt]
jazzLoop :: TransitionCache
-> Text
-> GenConfig
-> Int
-> Int
-> Double
-> DbActionT [ScoredAttempt]
jazzLoop TransitionCache
cache Text
seekTxt GenConfig
gc Int
maxN Int
target Double
floorT = do
jazzBlend <- Text -> DbActionT ComposerWeights
PS.resolveJazzBlend Text
seekTxt
let go Int
_ [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
acc t
0 = [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
-> ReaderT
DbConn
IO
[(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
forall a. a -> ReaderT DbConn IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
-> [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
forall a. [a] -> [a]
reverse [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
acc)
go Int
viableSoFar [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
acc t
remaining
| Int
viableSoFar Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
target = [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
-> ReaderT
DbConn
IO
[(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
forall a. a -> ReaderT DbConn IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
-> [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
forall a. [a] -> [a]
reverse [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
acc)
| Bool
otherwise = do
(pc, diag) <- IO (ProgressionContext, GenerationDiagnostics)
-> ReaderT DbConn IO (ProgressionContext, GenerationDiagnostics)
forall a. IO a -> ReaderT DbConn IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc)
ps <- PS.scoreProgressionJazz cache jazzBlend pc
let tot = ProgressionScoreWeights -> ProgressionScore -> Double
PS.totalScore ProgressionScoreWeights
PS.defaultWeights ProgressionScore
ps
isOk = ProgressionContext -> ProgressionScore -> Bool
viableAttempt ProgressionContext
pc ProgressionScore
ps Bool -> Bool -> Bool
&& Double
tot Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
floorT
acc' = (ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
isOk, GenerationDiagnostics
diag, Maybe a
forall a. Maybe a
Nothing) (ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)
-> [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
-> [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
forall a. a -> [a] -> [a]
: [(ProgressionContext, ProgressionScore, Double, Bool,
GenerationDiagnostics, Maybe a)]
acc
viable' = if Bool
isOk then Int
viableSoFar Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
viableSoFar
go viable' acc' (remaining - 1)
go (0 :: Int) [] maxN
viableAttempt :: PC.ProgressionContext -> PS.ProgressionScore -> Bool
viableAttempt :: ProgressionContext -> ProgressionScore -> Bool
viableAttempt ProgressionContext
pc ProgressionScore
ps =
ProgressionScore -> Double
PS.psModeValidity ProgressionScore
ps Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1.0 Bool -> Bool -> Bool
&& Progression -> Int
Prog.progLength (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
type ScoredAttempt =
( PC.ProgressionContext, PS.ProgressionScore, Double, Bool
, GenerationDiagnostics, Maybe PS.PolyScore )
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
(pc, diag) <- GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc
let ps = ProgressionContext -> ProgressionScore
PS.scoreProgression ProgressionContext
pc
poly = if ProgressionContext -> Family
PC.pcFamily ProgressionContext
pc Family -> Family -> Bool
forall a. Eq a => a -> a -> Bool
== Family
PC.FPoly
then PolyScore -> Maybe PolyScore
forall a. a -> Maybe a
Just (ProgressionScoreWeights -> ProgressionContext -> PolyScore
PS.scorePoly ProgressionScoreWeights
PS.defaultWeightsOffline ProgressionContext
pc)
else Maybe PolyScore
forall a. Maybe a
Nothing
tot = Double -> (PolyScore -> Double) -> Maybe PolyScore -> Double
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ProgressionScoreWeights -> ProgressionScore -> Double
PS.totalScore ProgressionScoreWeights
PS.defaultWeightsOffline ProgressionScore
ps) PolyScore -> Double
PS.pyTotal Maybe PolyScore
poly
isOk = ProgressionContext -> ProgressionScore -> Bool
viableAttempt ProgressionContext
pc ProgressionScore
ps Bool -> Bool -> Bool
&& Double
tot Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
floorT
acc' = (ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
isOk, GenerationDiagnostics
diag, Maybe PolyScore
poly) ScoredAttempt -> [ScoredAttempt] -> [ScoredAttempt]
forall a. a -> [a] -> [a]
: [ScoredAttempt]
acc
viable' = if Bool
isOk then Int
viableSoFar Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
viableSoFar
go viable' acc' (remaining - 1)
onlineLoop
:: PS.TransitionCache
-> T.Text
-> GenConfig
-> Int
-> Int
-> Double
-> DbActionT [ScoredAttempt]
onlineLoop :: TransitionCache
-> Text
-> GenConfig
-> Int
-> Int
-> Double
-> DbActionT [ScoredAttempt]
onlineLoop TransitionCache
cache Text
seekTxt GenConfig
gc Int
maxN Int
target Double
floorT = Int -> [ScoredAttempt] -> Int -> DbActionT [ScoredAttempt]
forall {t}.
(Eq t, Num t) =>
Int -> [ScoredAttempt] -> t -> DbActionT [ScoredAttempt]
go Int
0 [] Int
maxN
where
go :: Int -> [ScoredAttempt] -> t -> DbActionT [ScoredAttempt]
go Int
_ [ScoredAttempt]
acc t
0 = [ScoredAttempt] -> DbActionT [ScoredAttempt]
forall a. a -> ReaderT DbConn 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] -> DbActionT [ScoredAttempt]
forall a. a -> ReaderT DbConn IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([ScoredAttempt] -> [ScoredAttempt]
forall a. [a] -> [a]
reverse [ScoredAttempt]
acc)
| Bool
otherwise = do
(pc, diag) <- IO (ProgressionContext, GenerationDiagnostics)
-> ReaderT DbConn IO (ProgressionContext, GenerationDiagnostics)
forall a. IO a -> ReaderT DbConn IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc)
ps <- PS.scoreProgressionOnline cache seekTxt pc
poly <- if PC.pcFamily pc == PC.FPoly
then Just <$> PS.scorePolyOnline cache seekTxt PS.defaultWeights pc
else pure Nothing
let tot = Double -> (PolyScore -> Double) -> Maybe PolyScore -> Double
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (ProgressionScoreWeights -> ProgressionScore -> Double
PS.totalScore ProgressionScoreWeights
PS.defaultWeights ProgressionScore
ps) PolyScore -> Double
PS.pyTotal Maybe PolyScore
poly
isOk = ProgressionContext -> ProgressionScore -> Bool
viableAttempt ProgressionContext
pc ProgressionScore
ps Bool -> Bool -> Bool
&& Double
tot Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
floorT
acc' = (ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
isOk, GenerationDiagnostics
diag, Maybe PolyScore
poly) ScoredAttempt -> [ScoredAttempt] -> [ScoredAttempt]
forall a. a -> [a] -> [a]
: [ScoredAttempt]
acc
viable' = if Bool
isOk then Int
viableSoFar Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 else Int
viableSoFar
go viable' acc' (remaining - 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
(pc, diag) <- GenConfig -> IO (ProgressionContext, GenerationDiagnostics)
singlePassExecPCWithDiag GenConfig
gc
pure (pc, 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
pctx :: ParsedContext
pctx = HarmonicContext -> ParsedContext
parseContextOnce (GenConfig -> HarmonicContext
_gcTonal GenConfig
gc)
dvOf :: (ProgressionContext, b, c, d, e, f) -> Int
dvOf (ProgressionContext
pc, b
_, c
_, d
_, e
_, f
_) = ParsedContext -> Progression -> Int
directionViolations ParsedContext
pctx (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
(Int
winnerIdx, (ProgressionContext
winnerPC, ProgressionScore
_, Double
_, Bool
_, GenerationDiagnostics
winnerDiag, Maybe PolyScore
_)) =
((Int, ScoredAttempt) -> (Int, Double))
-> [(Int, ScoredAttempt)] -> (Int, ScoredAttempt)
forall b a. Ord b => (a -> b) -> [a] -> a
maximumByKey (\(Int
_, a :: ScoredAttempt
a@(ProgressionContext
_, ProgressionScore
_, Double
tot, Bool
_, GenerationDiagnostics
_, Maybe PolyScore
_)) -> (Int -> Int
forall a. Num a => a -> a
negate (ScoredAttempt -> Int
forall {b} {c} {d} {e} {f}.
(ProgressionContext, b, c, d, e, f) -> Int
dvOf ScoredAttempt
a), 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
, adDirViolations :: Int
adDirViolations = ScoredAttempt -> Int
forall {b} {c} {d} {e} {f}.
(ProgressionContext, b, c, d, e, f) -> Int
dvOf ScoredAttempt
a
, adChords :: [[Char]]
adChords = Progression -> [[Char]]
chordNamesOf (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
, adPoly :: Maybe PolyScore
adPoly = Maybe PolyScore
poly
}
| (Int
i, a :: ScoredAttempt
a@(ProgressionContext
pc, ProgressionScore
ps, Double
tot, Bool
ok, GenerationDiagnostics
_, Maybe PolyScore
poly)) <- [(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
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]
")"