{-# language GADTs #-} -- | An example implementation of a `Generate.Chaos` that generates music with -- chaotic octave and pitch selection. module Generate.Applications.ChaosPitches ( genChaosMusic , chaos1 , bSolo , chaos1Selector) where import Music import Utils.Vec import Generate.Generate import Control.Monad.State hiding (state) import Generate.Chaos -- | Generates `Music` with chaos function f x = 1 - 1.9521 * x^2 in range [-1,1] -- with initial x = 1.2. genChaosMusic :: IO (Music Pitch) genChaosMusic = do let mapping = defaultMapping {pcSel=chaos1Selector, octSel=chaos1Selector } runChaosGenerator chaos1 mapping bSolo -- | ChaosState with chaos function f x = 1 - 1.9521 * x^2 in range [-1,1] -- with initial x = 1.2. chaos1 :: ChaosState D1 chaos1 = do let startX = 1.2 buildChaos (startX :. Nil) (f :. Nil) where f :: (Vec D1 Double -> Double) f (x:.Nil) = max (-1) (min 1 (1 - 1.9521 * x**2)) -- | `MusicGenerator` that uses `chaos1` to generate some blues music. bSolo :: MusicGenerator (ChaosState D1) Melody bSolo = do addConstraint pitchClass (`elem` (E +| blues :: [PitchClass])) run1 <- local $ do octave >! (`elem` [4,5]) duration >! (`elem` [1%32, 1%16]) line <$> 12 .#. genNote run2 <- local $ do octave >! (`elem` [2,3,4]) duration >! (`elem` [1%8, 1%16]) pitchClass >! (`elem` [E, Fs, Gs, B, Cs]) line <$> 6 .#. genNote return $ run1 :=: run2 -- | The selector that maps the chaos function from `chaos1` to an element in a. chaos1Selector :: Selector (ChaosState n) a chaos1Selector s as = do ([d], s') <- runStateT genNextIteration s let dNormalised = (d+1) / 2 let maxI = fromIntegral (length as - 1) let index = round (dNormalised * maxI) let a = as !! index return (snd a, s')