Mode Space Implementation Donya Quick Last modified: 19-August-2014 Based on mode space implementation for doctoral thesis. Major changes since last version: - Changed occurrences of AbsPitch to PitchNum to avoid conflict with Euterpea's AbsPitch > module Kulitta.ChordSpaces.ModeSpace where > import Kulitta.ChordSpaces.OPTIC > import Kulitta.QuotientSpaces > import Data.List > import System.Random > type AbsMode = [PitchNum] > type JChord = (AbsChord, AbsMode) > modeEq :: EqRel JChord > modeEq a b = normO(snd a) == normO(snd b) The set of all modes rooted at 0 > allModes :: [AbsMode] > allModes = allRots [0,2,4,5,7,9,11] where > allRots x = take 7 $ iterate doRot x > doRot x = normO $ normT (tail x ++ [head x + 12]) > allKModes = map (normO . uncurry t) [(k,m) | k<-[0..11], m<-allModes] > allJChords :: [JChord] > allJChords = > let masks = makeRange (take 7 $ repeat (0,1)) > applyMask (f, m) = (map snd $ filter ((>0).fst) $ zip f m, m) > in map applyMask [(f,m) | f<-masks, m<-allKModes] > modeSpace :: QSpace JChord > modeSpace = allJChords // modeEq This version allows more efficient specification of modal space involving only chords fitting certain templates. > modeSpace' :: [[Int]] -> QSpace JChord > modeSpace' temps = filter (f temps) allJChords // modeEq where > f temps (c,m) = elem c $ map (toTemp m) temps > toTemp m t = map (m!!) t For example, to get only triads with the root, third, and fifth, one would use: modeSpace' [[0,2,4]].