conductive-song 0.1 → 0.2
raw patch · 4 files changed
+21/−212 lines, 4 filesdep +conductive-basedep −MissingHdep −arraydep ~basedep ~randomPVP ok
version bump matches the API change (PVP)
Dependencies added: conductive-base
Dependencies removed: MissingH, array
Dependency ranges changed: base, random
API changes (from Hackage documentation)
- Sound.Conductive.MiscListUtils: absolutesToDeltas :: Num a => [a] -> [a]
- Sound.Conductive.MiscListUtils: coin :: IO Bool
- Sound.Conductive.MiscListUtils: deltasToAbsolutes :: Num a => a -> [a] -> [a]
- Sound.Conductive.MiscListUtils: joinVals :: Num a => Int -> Int -> [a] -> [a]
- Sound.Conductive.MiscListUtils: lace :: [[a]] -> Int -> [a]
- Sound.Conductive.MiscListUtils: normalize :: Fractional a => a -> [a] -> [a]
- Sound.Conductive.MiscListUtils: npletAt :: Fractional a => Int -> Int -> [a] -> [a]
- Sound.Conductive.MiscListUtils: odds :: Int -> Int -> IO Bool
- Sound.Conductive.MiscListUtils: phrases :: (Num a, Enum a) => a -> [b] -> IO [[b]]
- Sound.Conductive.MiscListUtils: pick :: [a] -> IO a
- Sound.Conductive.MiscListUtils: pick' :: (Num p, Random p) => t -> [t] -> p -> IO t
- Sound.Conductive.MiscListUtils: pickN :: (Num a, Enum a) => a -> [b] -> IO [b]
- Sound.Conductive.MiscListUtils: rList :: Int -> IO [Int]
- Sound.Conductive.MiscListUtils: randomList :: Int -> StdGen -> [Int]
- Sound.Conductive.MiscListUtils: replaceAt :: Int -> [a] -> [a] -> [a]
- Sound.Conductive.MiscListUtils: replicator :: [(Int, b)] -> [b]
- Sound.Conductive.MiscListUtils: rotate :: [a] -> Int -> [a]
- Sound.Conductive.MiscListUtils: scaleList :: (Fractional a, Ord a) => a -> [a] -> [a]
- Sound.Conductive.MiscListUtils: shuffle :: [a] -> IO [a]
- Sound.Conductive.MiscListUtils: shuffle' :: [a] -> StdGen -> ([a], StdGen)
- Sound.Conductive.MiscListUtils: slice :: [a] -> [Int] -> [a]
- Sound.Conductive.MiscListUtils: stutter :: Int -> Int -> Int -> [a] -> [a]
- Sound.Conductive.MiscListUtils: takeToValue :: (Num a, Ord a) => a -> [a] -> [a]
- Sound.Conductive.MiscListUtils: takeToValue' :: (Ord a, Num a) => [a] -> a -> a -> [a] -> [a]
+ Sound.Conductive.Pitch: a4 :: Int
+ Sound.Conductive.Pitch: a440 :: Int
+ Sound.Conductive.Pitch: a440MIDI :: Int
+ Sound.Conductive.Pitch: a4MIDI :: Int
+ Sound.Conductive.Pitch: cent :: Double
+ Sound.Conductive.Scale: chromatic :: Int -> Integer -> [Integer]
+ Sound.Conductive.Scale: chromaticRel :: [Integer]
+ Sound.Conductive.Scale: rawToScaleDegrees :: (Num a, Ord a) => [a] -> [a] -> [a]
Files
- Sound/Conductive/MiscListUtils.hs +0/−206
- Sound/Conductive/Pitch.hs +0/−1
- Sound/Conductive/Scale.hs +16/−0
- conductive-song.cabal +5/−5
− Sound/Conductive/MiscListUtils.hs
@@ -1,206 +0,0 @@----------------------------------------------------------------------------------- MiscListUtils.hs--- created: Sun Mar 14 17:00:11 JST 2010------------------------------------------------------------------------------------ A set of functions for operating on lists of floats--- The purpose is to create interesting lists for use in music.--module Sound.Conductive.MiscListUtils where--import System.Random-import Data.List-import Data.List.Utils-import Data.Array.ST-import Control.Monad-import Control.Monad.ST-import Data.STRef---- based on deltasToTimes and timesToDeltas from SimpleSequencerMarkov.hs-deltasToAbsolutes :: (Num a) => a -> [a] -> [a]-deltasToAbsolutes start input = scanl (+) start input--absolutesToDeltas :: (Num a) => [a] -> [a]-absolutesToDeltas [] = []-absolutesToDeltas (x:[]) = []-absolutesToDeltas (x:xs) = ((head xs) - x):absolutesToDeltas xs---- http://old.nabble.com/Request-for-code-review:-slice-1.0.0,-TestSupport-td20658828.html--slice :: [a] -> [Int] -> [a]-xs `slice` indices = map (xs !!) indices--replaceAt :: Int -> [a] -> [a] -> [a]-replaceAt i ys xs = - let xz = splitAt i xs- in (fst xz) ++ ys ++ (tail $ snd xz)---- use this for double-time, creating triplets, fivelets even...--npletAt :: (Fractional a) => Int -> Int -> [a] -> [a]-npletAt n i xs =- let x = xs!!i- plet = replicate n $ x/(fromIntegral n)- in replaceAt i plet xs---- joins n number of values in list of xs beginning from sp--joinVals :: (Num a) => Int -> Int -> [a] -> [a]-joinVals sp n xs = let- splitXs = splitAt sp xs- newFront = fst splitXs- oldRest = snd splitXs- newRest = [sum $ take n $ oldRest] ++ (snd $ splitAt n oldRest)- in newFront ++ newRest--stutter :: Int -> Int -> Int -> [a] -> [a]-stutter sp l n xs = let- splitList = splitAt sp xs- initial = fst splitList- toBeStuttered = take l $ snd splitList- remainder = snd $ splitAt l $ snd splitList- stuttered = concat $ replicate n toBeStuttered- in initial ++ stuttered ++ remainder---- randomStutter--- randomStutter (x:xs) n chance = do--- let a = x---- | Randomly shuffle a list without the IO Monad--- /O(N)/--- ??? -- where did I get this function from? I didn't write it...--shuffle' :: [a] -> StdGen -> ([a],StdGen)-shuffle' xs gen = runST (do- g <- newSTRef gen- let randomRST lohi = do- (a,s') <- liftM (randomR lohi) (readSTRef g)- writeSTRef g s'- return a- ar <- newArray n xs- xs' <- forM [1..n] $ \i -> do- j <- randomRST (i,n)- vi <- readArray ar i- vj <- readArray ar j- writeArray ar j vi- return vj- gen' <- readSTRef g- return (xs',gen'))- where- n = length xs- newArray :: Int -> [a] -> ST s (STArray s Int a)- newArray n xs = newListArray (1,n) xs--shuffle :: [a] -> IO [a]-shuffle xs = getStdRandom (shuffle' xs) --rotate :: [a] -> Int -> [a]-rotate xs n = drop nn xs ++ take nn xs- where - nn = n `mod` length xs--lace :: [[a]] -> Int -> [a]-lace xss n = let- listNLengths = zip (map length xss) (xss)- selector t x = (snd x)!!(mod t $ fst x)- aRun t = map (selector t) listNLengths- o = ceiling $ (fromIntegral n)/(fromIntegral $ length xss)- in take n $ concat $ map aRun [0..o]--randomList :: Int -> StdGen -> [Int]-randomList n = take n . unfoldr (Just . random)--normalize :: (Fractional a) => a -> [a] -> [a]-normalize max x = map (flip (*) (1.0 / max)) x--scaleList :: (Fractional a, Ord a) => a -> [a] -> [a]-scaleList targetMax xs =- let scalar = targetMax/(maximum xs)- in map (*scalar) xs--rList :: Int -> IO [Int]-rList x = do- seed <- newStdGen- let rs = randomList x seed- return $ map abs rs---- http://osfameron.vox.com/library/post/random-pain-in-haskell.html--- pick a = do r <- randomRIO (1, length a)--- return $ a !! (r - 1)--pick :: [a] -> IO a-pick [] = undefined-pick [x] = do return x-pick (x:xs) = pick' x xs (2 :: Int)--pick' :: (Num p, Random p) => t -> [t] -> p -> IO t-pick' curr [] _ = do return curr-pick' curr (next:rest) prob- = do r <- getStdRandom (randomR (1,prob))- let curr' = if r == 1 then next else curr- pick' curr' rest (prob+1)--pickN :: (Num a, Enum a) => a -> [b] -> IO [b]-pickN n xs = mapM (\_ -> pick xs) [1..n]--coin :: IO Bool-coin = pick [True,False]---- odds against --odds :: Int -> Int -> IO Bool-odds n d = pick $ (replicate n False) ++ (replicate d True)---- from tuples where fst says how many and snd says what, create the lists--replicator :: [(Int, b)] -> [b]-replicator xs = concat $ map (\x -> replicate (fst x) $ snd x ) xs-------------------------------------------------------------------------------------- takeToValue--- give the maximum sum of a list--- if the sum is greater than the given value, the list is cropped--- the final sum is lowered so that the list sum equals the given value--- if the list is short of the given value, another item is added so that the list sum equals the given value------ This can be used to make a list of values sum to a specific number of beats.-------------------------------------------------------------------------------------takeToValue' :: (Ord a, Num a) => [a] -> a -> a -> [a] -> [a]-takeToValue' xs val curVal ys- | xs == [] = if (val <= curVal)- then ys- else ys ++ [val-curVal]- | otherwise =- let c = head xs- d = curVal + c- adjustValue input comparison- | input >= comparison = (False,input - comparison)- | input < comparison = (True,0)- test = adjustValue d val- in if (fst test)- then takeToValue' (tail xs) val d $ ys ++ [c]- else takeToValue' ([]) val d $ ys ++ [c - (snd test)]--takeToValue :: (Num a, Ord a) => a -> [a] -> [a]-takeToValue val xs = takeToValue' xs val 0 []------------------------------------------------------------------------------------ from here, test data--rhythmValues = [0.25,0.5..4]-rhythmValues2 = replicator $ zip [64,60..0] rhythmValues--phraseLengths = do pl <- pickN 100 [1..8]- return $ sort pl--phrases :: (Num a, Enum a) => a -> [b] -> IO [[b]]-phrases n vs = do - pl' <- phraseLengths- pl <- pickN n pl'- mapM (\x -> pickN x vs) pl
Sound/Conductive/Pitch.hs view
@@ -8,7 +8,6 @@ module Sound.Conductive.Pitch where import Data.List-import Data.List.Utils import Data.Maybe a440 = 9 :: Int
Sound/Conductive/Scale.hs view
@@ -9,8 +9,11 @@ import Data.List import Sound.Conductive.MiscListUtils+import Sound.Conductive.MusicalTime import Sound.Conductive.Pitch +chromaticRel = [1,1,1,1,1,1,1,1,1,1]+ -- church modes ionianRel :: [Integer]@@ -38,6 +41,10 @@ absoluteScaleMaker scale n startingNote = take n $ deltasToAbsolutes startingNote $ cycle scale +-- give the number of pitches and the root pitch to generate the scale++chromatic = absoluteScaleMaker chromaticRel+ ionian :: Int -> Integer -> [Integer] ionian = absoluteScaleMaker ionianRel @@ -93,6 +100,7 @@ todiRel :: [Integer] todiRel = [ 1, 2, 3, 1, 1, 3, 1 ] +--- bilawal :: Int -> Integer -> [Integer] bilawal = ionian@@ -148,6 +156,14 @@ fitToScale :: (Num b, Ord b) => [b] -> [b] -> [b] fitToScale scale input = reverse $ foldl (\x y -> mold scale x y) [] input++-- I'm imagining "raw" to mean values between 0 and 1, but I haven't thought about suitability for other ranges...++rawToScaleDegrees scale rs = fitToScale scale $ map convRaw rs where+ scaleMin = head scale+ scaleMax = last scale+ scaleRange = scaleMax - scaleMin+ convRaw x = (x * scaleRange) + scaleMin transpose :: (Num a) => a -> [a] -> [a] transpose n xs = map (\x -> x + n) xs
conductive-song.cabal view
@@ -7,13 +7,13 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version: 0.1+Version: 0.2 -- A short (one-line) description of the package. Synopsis: a library of functions which are useful for composing music -- A longer description of the package.-Description: This library contains functions which are useful for composing music. One module deals with lists, intially intended to be useful for algorithmically generating rhythm patterns. The other two modules, Scale and Pitch, deal with exactly those two concepts.+Description: This library contains functions which are useful for composing music, including scales and pitch. -- URL for the project homepage or repository. Homepage: http://www.renickbell.net/doku.php?id=conductive-song@@ -45,15 +45,15 @@ -- Extra-source-files: -- Constraint on the version of Cabal needed to build this package.-Cabal-version: >=1.4+Cabal-version: >=1.6 Library -- Modules exported by the library.- Exposed-modules: Sound.Conductive.Pitch, Sound.Conductive.Scale, Sound.Conductive.MiscListUtils+ Exposed-modules: Sound.Conductive.Pitch, Sound.Conductive.Scale -- Packages needed in order to build this package.- Build-depends: array >= 0.3 && < 0.4, base < 5, MissingH >= 1.1 && < 1.2, random >= 1.0 && < 1.1+ Build-depends: base == 4.*, conductive-base >= 0.3, random -- Modules not exported by this package. -- Other-modules: