module Music.Theory.Duration.Rq where
import Data.Function
import Data.List
import Data.Maybe
import Data.Ratio
import qualified Music.Theory.List as T
import Music.Theory.Duration
type Rq = Rational
rq_tuplet_duration_table :: [(Rq, Duration)]
rq_tuplet_duration_table :: [(Rq, Duration)]
rq_tuplet_duration_table =
[(Rq
1forall a. Fractional a => a -> a -> a
/Rq
3,Integer -> Dots -> Rq -> Duration
Duration Integer
8 Dots
0 (Rq
2forall a. Fractional a => a -> a -> a
/Rq
3))
,(Rq
2forall a. Fractional a => a -> a -> a
/Rq
3,Integer -> Dots -> Rq -> Duration
Duration Integer
4 Dots
0 (Rq
2forall a. Fractional a => a -> a -> a
/Rq
3))
,(Rq
1forall a. Fractional a => a -> a -> a
/Rq
5,Integer -> Dots -> Rq -> Duration
Duration Integer
16 Dots
0 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
5))
,(Rq
2forall a. Fractional a => a -> a -> a
/Rq
5,Integer -> Dots -> Rq -> Duration
Duration Integer
8 Dots
0 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
5))
,(Rq
3forall a. Fractional a => a -> a -> a
/Rq
5,Integer -> Dots -> Rq -> Duration
Duration Integer
8 Dots
1 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
5))
,(Rq
4forall a. Fractional a => a -> a -> a
/Rq
5,Integer -> Dots -> Rq -> Duration
Duration Integer
4 Dots
0 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
5))
,(Rq
1forall a. Fractional a => a -> a -> a
/Rq
6,Integer -> Dots -> Rq -> Duration
Duration Integer
16 Dots
0 (Rq
2forall a. Fractional a => a -> a -> a
/Rq
3))
,(Rq
1forall a. Fractional a => a -> a -> a
/Rq
7,Integer -> Dots -> Rq -> Duration
Duration Integer
16 Dots
0 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
7))
,(Rq
2forall a. Fractional a => a -> a -> a
/Rq
7,Integer -> Dots -> Rq -> Duration
Duration Integer
8 Dots
0 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
7))
,(Rq
3forall a. Fractional a => a -> a -> a
/Rq
7,Integer -> Dots -> Rq -> Duration
Duration Integer
8 Dots
1 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
7))
,(Rq
4forall a. Fractional a => a -> a -> a
/Rq
7,Integer -> Dots -> Rq -> Duration
Duration Integer
4 Dots
0 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
7))
,(Rq
6forall a. Fractional a => a -> a -> a
/Rq
7,Integer -> Dots -> Rq -> Duration
Duration Integer
4 Dots
1 (Rq
4forall a. Fractional a => a -> a -> a
/Rq
7))
]
rq_tuplet_to_duration :: Rq -> Maybe Duration
rq_tuplet_to_duration :: Rq -> Maybe Duration
rq_tuplet_to_duration Rq
x = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Rq
x [(Rq, Duration)]
rq_tuplet_duration_table
rq_plain_duration_tbl :: Dots -> [(Rq,Duration)]
rq_plain_duration_tbl :: Dots -> [(Rq, Duration)]
rq_plain_duration_tbl Dots
k = forall a b. (a -> b) -> [a] -> [b]
map (\Duration
d -> (Duration -> Rq
duration_to_rq Duration
d,Duration
d)) (Dots -> [Duration]
duration_set Dots
k)
rq_plain_to_duration :: Dots -> Rq -> Maybe Duration
rq_plain_to_duration :: Dots -> Rq -> Maybe Duration
rq_plain_to_duration Dots
k Rq
x = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Rq
x (Dots -> [(Rq, Duration)]
rq_plain_duration_tbl Dots
k)
rq_plain_to_duration_err :: Dots -> Rq -> Duration
rq_plain_to_duration_err :: Dots -> Rq -> Duration
rq_plain_to_duration_err Dots
k Rq
x = forall k v. Eq k => k -> [(k, v)] -> v
T.lookup_err Rq
x (Dots -> [(Rq, Duration)]
rq_plain_duration_tbl Dots
k)
rq_to_duration :: Dots -> Rq -> Maybe Duration
rq_to_duration :: Dots -> Rq -> Maybe Duration
rq_to_duration Dots
k Rq
x = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Rq
x ([(Rq, Duration)]
rq_tuplet_duration_table forall a. [a] -> [a] -> [a]
++ Dots -> [(Rq, Duration)]
rq_plain_duration_tbl Dots
k)
rq_to_duration_err :: Show a => a -> Dots -> Rq -> Duration
rq_to_duration_err :: forall a. Show a => a -> Dots -> Rq -> Duration
rq_to_duration_err a
msg Dots
k Rq
n =
let err :: a
err = forall a. HasCallStack => [Char] -> a
error ([Char]
"rq_to_duration:" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (a
msg,Rq
n))
in forall a. a -> Maybe a -> a
fromMaybe forall {a}. a
err (Dots -> Rq -> Maybe Duration
rq_to_duration Dots
k Rq
n)
rq_is_cmn :: Dots -> Rq -> Bool
rq_is_cmn :: Dots -> Rq -> Bool
rq_is_cmn Dots
k = forall a. Maybe a -> Bool
isJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. Dots -> Rq -> Maybe Duration
rq_plain_to_duration Dots
k
whole_note_division_to_rq :: Division -> Rq
whole_note_division_to_rq :: Integer -> Rq
whole_note_division_to_rq Integer
x =
let f :: Integer -> Rq
f = (forall a. Num a => a -> a -> a
* Rq
4) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Fractional a => a -> a
recip forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Integral a => a -> a -> Ratio a
% Integer
1)
in case Integer
x of
Integer
0 -> Rq
8
-1 -> Rq
16
Integer
_ -> Integer -> Rq
f Integer
x
rq_apply_dots :: Rq -> Dots -> Rq
rq_apply_dots :: Rq -> Dots -> Rq
rq_apply_dots Rq
n Dots
d =
let m :: [Rq]
m = forall a. (a -> a) -> a -> [a]
iterate (forall a. Fractional a => a -> a -> a
/ Rq
2) Rq
n
in forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (forall i a. Integral i => i -> [a] -> [a]
genericTake (Dots
d forall a. Num a => a -> a -> a
+ Dots
1) [Rq]
m)
duration_to_rq :: Duration -> Rq
duration_to_rq :: Duration -> Rq
duration_to_rq (Duration Integer
n Dots
d Rq
m) =
let x :: Rq
x = Integer -> Rq
whole_note_division_to_rq Integer
n
in Rq -> Dots -> Rq
rq_apply_dots Rq
x Dots
d forall a. Num a => a -> a -> a
* Rq
m
duration_compare_rq :: Duration -> Duration -> Ordering
duration_compare_rq :: Duration -> Duration -> Ordering
duration_compare_rq = forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Duration -> Rq
duration_to_rq
rq_mod :: Rq -> Rq -> Rq
rq_mod :: Rq -> Rq -> Rq
rq_mod Rq
i Rq
j
| Rq
i forall a. Eq a => a -> a -> Bool
== Rq
j = Rq
0
| Rq
i forall a. Ord a => a -> a -> Bool
< Rq
0 = Rq -> Rq -> Rq
rq_mod (Rq
i forall a. Num a => a -> a -> a
+ Rq
j) Rq
j
| Rq
i forall a. Ord a => a -> a -> Bool
> Rq
j = Rq -> Rq -> Rq
rq_mod (Rq
i forall a. Num a => a -> a -> a
- Rq
j) Rq
j
| Bool
otherwise = Rq
i
rq_divisible_by :: Rq -> Rq -> Bool
rq_divisible_by :: Rq -> Rq -> Bool
rq_divisible_by Rq
i Rq
j = forall a. Ratio a -> a
denominator (Rq
i forall a. Fractional a => a -> a -> a
/ Rq
j) forall a. Eq a => a -> a -> Bool
== Integer
1
rq_is_integral :: Rq -> Bool
rq_is_integral :: Rq -> Bool
rq_is_integral = (forall a. Eq a => a -> a -> Bool
== Integer
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ratio a -> a
denominator
rq_integral :: Rq -> Maybe Integer
rq_integral :: Rq -> Maybe Integer
rq_integral Rq
n = if Rq -> Bool
rq_is_integral Rq
n then forall a. a -> Maybe a
Just (forall a. Ratio a -> a
numerator Rq
n) else forall a. Maybe a
Nothing
rq_derive_tuplet_plain :: [Rq] -> Maybe (Integer,Integer)
rq_derive_tuplet_plain :: [Rq] -> Maybe (Integer, Integer)
rq_derive_tuplet_plain [Rq]
x =
let i :: Integer
i = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall a. Integral a => a -> a -> a
lcm Integer
1 (forall a b. (a -> b) -> [a] -> [b]
map forall a. Ratio a -> a
denominator [Rq]
x)
j :: Integer
j = let z :: [Integer]
z = forall a. (a -> a) -> a -> [a]
iterate (forall a. Num a => a -> a -> a
* Integer
2) Integer
2
in forall a. HasCallStack => Maybe a -> a
fromJust (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (forall a. Ord a => a -> a -> Bool
>= Integer
i) [Integer]
z) forall a. Integral a => a -> a -> a
`div` Integer
2
in if Integer
i forall a. Integral a => a -> a -> a
`rem` Integer
j forall a. Eq a => a -> a -> Bool
== Integer
0 then forall a. Maybe a
Nothing else forall a. a -> Maybe a
Just (Integer
i,Integer
j)
rq_derive_tuplet :: [Rq] -> Maybe (Integer,Integer)
rq_derive_tuplet :: [Rq] -> Maybe (Integer, Integer)
rq_derive_tuplet =
let f :: (b, b) -> (b, b)
f (b
i,b
j) = let k :: Ratio b
k = b
i forall a. Integral a => a -> a -> Ratio a
% b
j
in (forall a. Ratio a -> a
numerator Ratio b
k,forall a. Ratio a -> a
denominator Ratio b
k)
in forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall {b}. Integral b => (b, b) -> (b, b)
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Rq] -> Maybe (Integer, Integer)
rq_derive_tuplet_plain
rq_un_tuplet :: (Integer,Integer) -> Rq -> Rq
rq_un_tuplet :: (Integer, Integer) -> Rq -> Rq
rq_un_tuplet (Integer
i,Integer
j) Rq
x = Rq
x forall a. Num a => a -> a -> a
* (Integer
i forall a. Integral a => a -> a -> Ratio a
% Integer
j)
rq_to_cmn :: Rq -> Maybe (Rq,Rq)
rq_to_cmn :: Rq -> Maybe (Rq, Rq)
rq_to_cmn Rq
x =
let (Integer
i,Integer
j) = (forall a. Ratio a -> a
numerator Rq
x,forall a. Ratio a -> a
denominator Rq
x)
k :: Maybe (Integer, Integer)
k = case Integer
i of
Integer
5 -> forall a. a -> Maybe a
Just (Integer
4,Integer
1)
Integer
7 -> forall a. a -> Maybe a
Just (Integer
4,Integer
3)
Integer
9 -> forall a. a -> Maybe a
Just (Integer
8,Integer
1)
Integer
_ -> forall a. Maybe a
Nothing
f :: (Integer, Integer) -> (Rq, Rq)
f (Integer
n,Integer
m) = (Integer
nforall a. Integral a => a -> a -> Ratio a
%Integer
j,Integer
mforall a. Integral a => a -> a -> Ratio a
%Integer
j)
in forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Integer, Integer) -> (Rq, Rq)
f Maybe (Integer, Integer)
k
rq_can_notate :: Dots -> [Rq] -> Bool
rq_can_notate :: Dots -> [Rq] -> Bool
rq_can_notate Dots
k [Rq]
x =
let x' :: [Rq]
x' = case [Rq] -> Maybe (Integer, Integer)
rq_derive_tuplet [Rq]
x of
Maybe (Integer, Integer)
Nothing -> [Rq]
x
Just (Integer, Integer)
t -> forall a b. (a -> b) -> [a] -> [b]
map ((Integer, Integer) -> Rq -> Rq
rq_un_tuplet (Integer, Integer)
t) [Rq]
x
in forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Dots -> Rq -> Bool
rq_is_cmn Dots
k) [Rq]
x'
rq_to_seconds_qpm :: Fractional a => a -> a -> a
rq_to_seconds_qpm :: forall a. Fractional a => a -> a -> a
rq_to_seconds_qpm a
qpm a
rq = a
rq forall a. Num a => a -> a -> a
* (a
60 forall a. Fractional a => a -> a -> a
/ a
qpm)
rq_to_qpm :: Fractional a => a -> a -> a
rq_to_qpm :: forall a. Fractional a => a -> a -> a
rq_to_qpm a
rq a
x = (a
rq forall a. Fractional a => a -> a -> a
/ a
x) forall a. Num a => a -> a -> a
* a
60