-- | Time Signatures. module Music.Theory.Time_Signature where import Data.Ratio import Music.Theory.Duration import Music.Theory.Duration.Name import Music.Theory.Duration.RQ -- | A Time Signature is a /(numerator,denominator)/ pair. type Time_Signature = (Integer,Integer) -- | Tied, non-multiplied durations to fill a whole measure. -- -- > ts_whole_note (3,8) == [dotted_quarter_note] -- > ts_whole_note (2,2) == [whole_note] ts_whole_note :: Time_Signature -> [Duration] ts_whole_note t = case t of (1,8) -> [eighth_note] (2,16) -> [eighth_note] (3,16) -> [dotted_eighth_note] (1,4) -> [quarter_note] (2,8) -> [quarter_note] (4,16) -> [quarter_note] (5,16) -> [quarter_note,sixteenth_note] (3,8) -> [dotted_quarter_note] (6,16) -> [dotted_quarter_note] (7,16) -> [quarter_note,dotted_eighth_note] (1,2) -> [half_note] (2,4) -> [half_note] (4,8) -> [half_note] (5,8) -> [half_note,eighth_note] (3,4) -> [dotted_half_note] (6,8) -> [dotted_half_note] (1,1) -> [whole_note] (2,2) -> [whole_note] (4,4) -> [whole_note] (5,4) -> [whole_note,quarter_note] (3,2) -> [dotted_whole_note] (6,4) -> [dotted_whole_note] (7,4) -> [whole_note,dotted_half_note] (2,1) -> [breve] (4,2) -> [breve] (3,1) -> [dotted_breve] (6,2) -> [dotted_breve] _ -> error ("ts_whole_note: " ++ show t) -- | Duration of measure in 'RQ'. -- -- > map ts_whole_note_rq [(3,8),(2,2)] == [3/2,4] ts_whole_note_rq :: Time_Signature -> RQ ts_whole_note_rq = sum . map duration_to_rq . ts_whole_note -- | Duration, in 'RQ', of a measure of indicated 'Time_Signature'. -- -- > map ts_rq [(3,4),(5,8)] == [3,5/2] ts_rq :: Time_Signature -> RQ ts_rq (n,d) = (4 * n) % d -- | Uniform division of time signature. -- -- > ts_divisions (3,4) == [1,1,1] -- > ts_divisions (3,8) == [1/2,1/2,1/2] -- > ts_divisions (2,2) == [2,2] -- > ts_divisions (1,1) == [4] ts_divisions :: Time_Signature -> [RQ] ts_divisions (i,j) = let k = fromIntegral i in replicate k (recip (j % 4)) -- | Convert a duration to a pulse count in relation to the indicated -- time signature. -- -- > ts_duration_pulses (3,8) quarter_note == 2 ts_duration_pulses :: Time_Signature -> Duration -> Rational ts_duration_pulses (_, b) (Duration dv dt ml) = let n = b % dv in rq_apply_dots n dt * ml -- | Rewrite time signature to indicated denominator. -- -- > ts_rewrite 8 (3,4) == (6,8) ts_rewrite :: Integer -> Time_Signature -> Time_Signature ts_rewrite d' = let dv i j = let (x,y) = i `divMod` j in if y == 0 then x else error "ts_rewrite" go (n,d) = case compare d d' of EQ -> (n,d) GT -> go (n `dv` 2, d `dv` 2) LT -> go (n * 2, d * 2) in go -- | Sum time signatures. -- -- > ts_sum [(3,16),(1,2)] == (11,16) ts_sum :: [Time_Signature] -> Time_Signature ts_sum t = let i = maximum (map snd t) t' = map (ts_rewrite i) t j = sum (map fst t') in (j,i)