hmt-0.12: Music/Theory/Time_Signature.hs
-- | 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)