-- | The Interval module implements diatonic intervals. module Music.Diatonic.Interval ( Interval( Unison,Min2nd,Maj2nd,Min3rd,Maj3rd,Perf4th, Perf5th,Min6th,Maj6th,Min7th,Maj7th ), augment, diminish, steps, semitones ) where import Music.Diatonic.Quality -- | Use these constructors to create 'Interval's. To alter them, use the 'diminish' or 'augment' functions. data Interval = Unison | Min2nd | Maj2nd | Min3rd | Maj3rd | Perf4th | Perf5th | Min6th | Maj6th | Min7th | Maj7th | Aug Interval | Dim Interval deriving (Eq) instance Show Interval where show Unison = "P1" ; show Min2nd = "m2" ; show Maj2nd = "M2" ; show Min3rd = "m3" show Maj3rd = "M3" ; show Perf4th = "P4" ; show Perf5th = "P5" ; show Min6th = "m6" show Maj6th = "M6" ; show Min7th = "m7" ; show Maj7th = "M7" show (Aug i@(Aug _)) = "A" ++ show i show (Aug i) = "A" ++ (tail . show $ i) show (Dim i@(Dim _)) = "d" ++ show i show (Dim i) = "d" ++ (tail . show $ i) instance Qual Interval where quality i | i `elem` [Maj2nd, Maj3rd, Maj6th, Maj7th] = Major quality i | i `elem` [Min2nd, Min3rd, Min6th, Min7th] = Minor quality i | i `elem` [Perf4th, Perf5th] = Perfect quality (Aug i) = Augmented quality (Dim i) = Diminished -- | Augments an 'Interval' by a semitone. The interval type remains the same. augment :: Interval -> Interval augment (Dim i) = i augment Min2nd = Maj2nd ; augment Min3rd = Maj3rd augment Min6th = Maj6th ; augment Min7th = Maj7th augment i = Aug i -- | Diminishes an 'Interval' by a semitone. The interval type remains the same. diminish :: Interval -> Interval diminish (Aug i) = i diminish Maj2nd = Min2nd ; diminish Maj3rd = Min3rd diminish Maj6th = Min6th ; diminish Maj7th = Min7th diminish i = Dim i -- | Returns the number of scale steps in an 'Interval'. steps :: Interval -> Int steps Unison = 0 ; steps Min2nd = 1 ; steps Maj2nd = 1 ; steps Min3rd = 2 steps Maj3rd = 2 ; steps Perf4th = 3 ; steps Perf5th = 4 ; steps Min6th = 5 steps Maj6th = 5 ; steps Min7th = 6 ; steps Maj7th = 6 steps (Aug i) = steps i steps (Dim i) = steps i -- | Returns the number of semitones in an 'Interval'. semitones :: Interval -> Int semitones Unison = 0 ; semitones Min2nd = 1 ; semitones Maj2nd = 2 ; semitones Min3rd = 3 semitones Maj3rd = 4 ; semitones Perf4th = 5 ; semitones Perf5th = 7 ; semitones Min6th = 8 semitones Maj6th = 9 ; semitones Min7th = 10 ; semitones Maj7th = 11 semitones (Aug i) = semitones i + 1 semitones (Dim i) = semitones i - 1