------------------------------------------------------------------------------------ -- | -- Copyright : (c) Hans Hoglund 2012 -- -- License : BSD-style -- -- Maintainer : hans@hanshoglund.se -- Stability : experimental -- Portability : non-portable (TF,GNTD) -- -- Provides a representation of pitch as defined in Common Music Theory (CMT). -- ------------------------------------------------------------------------------------- module Music.Pitch.Common ( -- -- * Enharmonic representation -- -- ** Octaves -- Octaves, -- -- HasOctaves(..), -- -- -- ** Steps -- -- Steps, -- -- HasSteps(..), -- -- -- ** Semitones -- Semitones, -- HasSemitones(..), -- semitone, -- tone, -- ditone, -- tritone, -- isSemitone, -- isTone, -- isTritone, -- -- -- ** Enharmonic equivalence -- (=:=), -- (/:=), -- -- -- * Pitches -- -- ** Name type -- Name(..), -- -- -- ** Accidental type -- Accidental, -- doubleFlat, -- flat, -- natural, -- sharp, -- doubleSharp, -- -- -- *** Inspecting accidentals -- isNatural, -- isSharpened, -- isFlattened, -- isStandard, -- -- -- ** Pitch type -- Pitch, -- pitch, -- name, -- accidental, -- asPitch, -- -- -- module Music.Pitch.Common.Name, -- -- module Music.Pitch.Common.Accidental, -- -- module Music.Pitch.Common.Pitch, -- -- -- * Intervals -- -- ** Number type -- Number, -- HasNumber(..), -- unison, -- prime, -- second, -- third, -- fourth, -- fifth, -- sixth, -- seventh, -- octave, -- ninth, -- tenth, -- twelfth, -- duodecim, -- thirteenth, -- fourteenth, -- fifteenth, -- -- -- ** Quality type -- Quality(..), -- HasQuality(..), -- invertQuality, -- isPerfect, -- isMajor, -- isMinor, -- isAugmented, -- isDiminished, -- -- -- ** Interval type -- Interval, -- -- -- *** Creating intervals -- interval, -- perfect, -- major, -- minor, -- augmented, -- diminished, -- doublyAugmented, -- doublyDiminished, -- asInterval, -- -- -- *** Inspecting intervals -- isNegative, -- isPositive, -- isNonNegative, -- isPerfectUnison, -- isStep, -- isLeap, -- -- -- *** Simple and compound intervals -- isSimple, -- isCompound, -- separate, -- octaves, -- simple, -- -- -- *** Inversion -- invert, -- * Enharmonic representation module Music.Pitch.Common.Semitones, -- * Non-enharmonic representation module Music.Pitch.Common.Interval, module Music.Pitch.Common.Pitch, -- * Utility module Music.Pitch.Common.Spell, module Music.Pitch.Common.Harmony, ) where import Data.Maybe import Data.Either import Data.Semigroup import Data.VectorSpace import Data.AffineSpace import Control.Monad import Control.Applicative import qualified Data.List as List import Music.Pitch.Absolute import Music.Pitch.Literal import Music.Pitch.Common.Pitch import Music.Pitch.Common.Interval import Music.Pitch.Common.Semitones import Music.Pitch.Common.Spell import Music.Pitch.Common.Harmony {- Semitones is the smallest musical unit (Semitones in Western music) The `semitones` function retrieves the number of Semitones in a pitch, for example semitones :: Interval -> Semitones semitones major third = 4 Note that semitones is surjetive. We can define a non-deterministic function `spellings` spellings :: Semitones -> [Interval] spellings 4 = [majorThird, diminishedFourth] Law map semitones (spellings a) = replicate n a for all n > 0 Lemma map semitones (spellings a) isHemitonic [1,2,2] = True isHemitonic [2,2,2] = False isCohemitonic [1,1,2] = True isCohemitonic [1,2,1] = False isTritonic ... A Scale is a [Semitones], for example [2,2,1,2,2,2,1] From this we can derive [2,4,5,7,9,11,12] A Scale is a function (Number -> Interval) A Scale is a function (Number -> Semitones) -- TODO simplify etc isMelodicDissonance :: Interval -> Bool "Post-tonal" Messiaen mode1 = [2,2,2,2,2] mode2 = [1,2, 1,2, 1,2, 1,2] mode3 = [2,1,1, 2,1,1, 2,1,1] mode4 = [1,1,3,1, 1,1,3,1] mode5 = [1,4,1, 1,4,1] mode6 = [2,2,1,1, 2,2,1,1] mode7 = [1,1,1,2,1, 1,1,1,2,1] - Old stuff> -- Semitone is an enumerated associated type type family Semitone a :: * type family Alteration a :: * -- A scale is a function :: Semitone a -> a newtype Scale a = Scale { getScale :: [Semitone a] } -- Eq, Show semitone :: Scale a -> Semitone a -> a semitone = undefined semitone (Scale xs) p = xs !! (fromIntegral p `mod` length xs) fromSemitone :: (Num a, Ord a, Integral b, Num c) => Scale a -> b -> c fromSemitone (Scale xs) p = fromIntegral $ fromMaybe (length xs - 1) $ List.findIndex (>= fromIntegral p) xs scaleFromSemitones :: Num a => [a] -> Scale a scaleFromSemitones = Scale . accum where accum = snd . List.mapAccumL add 0 add a x = (a + x, a + x) -- numberOfSemitones :: Scale a -> Int numberOfSemitones = length . getScale major :: Num a => Scale a major = scaleFromSemitones [0,2,2,1,2,2,2,1] naturalMinor :: Num a => Scale a naturalMinor = scaleFromSemitones [0,2,1,2,2,1,2,2] harmonicMinor :: Num a => Scale a harmonicMinor = scaleFromSemitones [0,2,1,2,2,1,3,1] -} -- or' :: (t -> Bool) -> (t -> Bool) -> t -> Bool -- or' p q x = p x || q x -- replicate' n = replicate (fromIntegral n)