module Music.Theory.Tuning.Type where
import Data.List
import Data.Maybe
import qualified Music.Theory.Either as T
import qualified Music.Theory.Math.Prime as T
import qualified Music.Theory.Tuning as T
data Tuning = Tuning {Tuning -> Either [Rational] [Approximate_Ratio]
tn_ratios_or_cents :: Either [Rational] [T.Cents]
,Tuning -> Maybe (Either Rational Approximate_Ratio)
tn_octave :: Maybe (Either Rational T.Cents)}
deriving (Tuning -> Tuning -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tuning -> Tuning -> Bool
$c/= :: Tuning -> Tuning -> Bool
== :: Tuning -> Tuning -> Bool
$c== :: Tuning -> Tuning -> Bool
Eq,Int -> Tuning -> ShowS
[Tuning] -> ShowS
Tuning -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tuning] -> ShowS
$cshowList :: [Tuning] -> ShowS
show :: Tuning -> String
$cshow :: Tuning -> String
showsPrec :: Int -> Tuning -> ShowS
$cshowsPrec :: Int -> Tuning -> ShowS
Show)
tn_epsilon :: Double
tn_epsilon :: Approximate_Ratio
tn_epsilon = Approximate_Ratio
0.001
tn_as_ratio :: Double -> Either Rational T.Cents -> Rational
tn_as_ratio :: Approximate_Ratio -> Either Rational Approximate_Ratio -> Rational
tn_as_ratio Approximate_Ratio
epsilon = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. a -> a
id (Approximate_Ratio -> Approximate_Ratio -> Rational
T.reconstructed_ratio Approximate_Ratio
epsilon)
tn_as_cents :: Either Rational T.Cents -> T.Cents
tn_as_cents :: Either Rational Approximate_Ratio -> Approximate_Ratio
tn_as_cents = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall i. Integral i => Ratio i -> Approximate_Ratio
T.ratio_to_cents forall a. a -> a
id
tn_octave_def :: Tuning -> Either Rational T.Cents
tn_octave_def :: Tuning -> Either Rational Approximate_Ratio
tn_octave_def = forall a. a -> Maybe a -> a
fromMaybe (forall a b. a -> Either a b
Left Rational
2) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Maybe (Either Rational Approximate_Ratio)
tn_octave
tn_octave_cents :: Tuning -> T.Cents
tn_octave_cents :: Tuning -> Approximate_Ratio
tn_octave_cents = Either Rational Approximate_Ratio -> Approximate_Ratio
tn_as_cents forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Either Rational Approximate_Ratio
tn_octave_def
tn_octave_ratio :: Double -> Tuning -> Rational
tn_octave_ratio :: Approximate_Ratio -> Tuning -> Rational
tn_octave_ratio Approximate_Ratio
epsilon = Approximate_Ratio -> Either Rational Approximate_Ratio -> Rational
tn_as_ratio Approximate_Ratio
epsilon forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Either Rational Approximate_Ratio
tn_octave_def
tn_divisions :: Tuning -> Int
tn_divisions :: Tuning -> Int
tn_divisions = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (t :: * -> *) a. Foldable t => t a -> Int
length forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Either [Rational] [Approximate_Ratio]
tn_ratios_or_cents
tn_ratios :: Tuning -> Maybe [Rational]
tn_ratios :: Tuning -> Maybe [Rational]
tn_ratios = forall a b. Either a b -> Maybe a
T.from_left forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Either [Rational] [Approximate_Ratio]
tn_ratios_or_cents
tn_limit :: Tuning -> Maybe Integer
tn_limit :: Tuning -> Maybe Integer
tn_limit = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall i. Integral i => Ratio i -> i
T.rational_prime_limit) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Maybe [Rational]
tn_ratios
tn_ratios_err :: Tuning -> [Rational]
tn_ratios_err :: Tuning -> [Rational]
tn_ratios_err = forall a. a -> Maybe a -> a
fromMaybe (forall a. HasCallStack => String -> a
error String
"ratios") forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Maybe [Rational]
tn_ratios
tn_cents :: Tuning -> [T.Cents]
tn_cents :: Tuning -> [Approximate_Ratio]
tn_cents = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. (a -> b) -> [a] -> [b]
map forall i. Integral i => Ratio i -> Approximate_Ratio
T.ratio_to_cents) forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> Either [Rational] [Approximate_Ratio]
tn_ratios_or_cents
tn_cents_i :: Integral i => Tuning -> [i]
tn_cents_i :: forall i. Integral i => Tuning -> [i]
tn_cents_i = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (RealFrac a, Integral b) => a -> b
round forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> [Approximate_Ratio]
tn_cents
tn_cents_octave :: Tuning -> [T.Cents]
tn_cents_octave :: Tuning -> [Approximate_Ratio]
tn_cents_octave Tuning
t = Tuning -> [Approximate_Ratio]
tn_cents Tuning
t forall a. [a] -> [a] -> [a]
++ [Tuning -> Approximate_Ratio
tn_octave_cents Tuning
t]
tn_fmidi :: Tuning -> [Double]
tn_fmidi :: Tuning -> [Approximate_Ratio]
tn_fmidi = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Num a => a -> a -> a
* Approximate_Ratio
0.01) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tuning -> [Approximate_Ratio]
tn_cents
tn_approximate_ratios :: Tuning -> [T.Approximate_Ratio]
tn_approximate_ratios :: Tuning -> [Approximate_Ratio]
tn_approximate_ratios =
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. (a -> b) -> [a] -> [b]
map Rational -> Approximate_Ratio
T.approximate_ratio) (forall a b. (a -> b) -> [a] -> [b]
map forall a. Floating a => a -> a
T.cents_to_fratio) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Tuning -> Either [Rational] [Approximate_Ratio]
tn_ratios_or_cents
tn_approximate_ratios_cyclic :: Tuning -> [T.Approximate_Ratio]
tn_approximate_ratios_cyclic :: Tuning -> [Approximate_Ratio]
tn_approximate_ratios_cyclic Tuning
t =
let r :: [Approximate_Ratio]
r = Tuning -> [Approximate_Ratio]
tn_approximate_ratios Tuning
t
m :: Approximate_Ratio
m = forall a. Floating a => a -> a
T.cents_to_fratio (Tuning -> Approximate_Ratio
tn_octave_cents Tuning
t)
g :: [Approximate_Ratio]
g = forall a. (a -> a) -> a -> [a]
iterate (forall a. Num a => a -> a -> a
* Approximate_Ratio
m) Approximate_Ratio
1
f :: Approximate_Ratio -> [Approximate_Ratio]
f Approximate_Ratio
n = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Num a => a -> a -> a
* Approximate_Ratio
n) [Approximate_Ratio]
r
in forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Approximate_Ratio -> [Approximate_Ratio]
f [Approximate_Ratio]
g
tn_ratios_lookup :: Tuning -> Int -> Maybe Rational
tn_ratios_lookup :: Tuning -> Int -> Maybe Rational
tn_ratios_lookup Tuning
t Int
n =
let (Int
o,Int
pc) = Int
n forall a. Integral a => a -> a -> (a, a)
`divMod` Tuning -> Int
tn_divisions Tuning
t
o_ratio :: Rational
o_ratio = forall a. Integral a => Ratio a -> Int -> Ratio a
T.oct_diff_to_ratio (Approximate_Ratio -> Tuning -> Rational
tn_octave_ratio Approximate_Ratio
tn_epsilon Tuning
t) Int
o
in forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\[Rational]
r -> Rational
o_ratio forall a. Num a => a -> a -> a
* ([Rational]
r forall a. [a] -> Int -> a
!! Int
pc)) (Tuning -> Maybe [Rational]
tn_ratios Tuning
t)
tn_approximate_ratios_lookup :: Tuning -> Int -> T.Approximate_Ratio
tn_approximate_ratios_lookup :: Tuning -> Int -> Approximate_Ratio
tn_approximate_ratios_lookup Tuning
t Int
n =
let (Int
o,Int
pc) = Int
n forall a. Integral a => a -> a -> (a, a)
`divMod` Tuning -> Int
tn_divisions Tuning
t
o_ratio :: Approximate_Ratio
o_ratio = forall a. Fractional a => Rational -> a
fromRational (forall a. Integral a => Ratio a -> Int -> Ratio a
T.oct_diff_to_ratio (Approximate_Ratio -> Tuning -> Rational
tn_octave_ratio Approximate_Ratio
tn_epsilon Tuning
t) Int
o)
in Approximate_Ratio
o_ratio forall a. Num a => a -> a -> a
* (Tuning -> [Approximate_Ratio]
tn_approximate_ratios Tuning
t forall a. [a] -> Int -> a
!! Int
pc)
tn_reconstructed_ratios :: Double -> Tuning -> Maybe [Rational]
tn_reconstructed_ratios :: Approximate_Ratio -> Tuning -> Maybe [Rational]
tn_reconstructed_ratios Approximate_Ratio
epsilon =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map (Approximate_Ratio -> Approximate_Ratio -> Rational
T.reconstructed_ratio Approximate_Ratio
epsilon)) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall x t. Either x t -> Maybe t
T.from_right forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Tuning -> Either [Rational] [Approximate_Ratio]
tn_ratios_or_cents
tn_equal_temperament :: Integral n => n -> Tuning
tn_equal_temperament :: forall n. Integral n => n -> Tuning
tn_equal_temperament n
n =
let c :: [Approximate_Ratio]
c = forall i a. Integral i => i -> [a] -> [a]
genericTake n
n [Approximate_Ratio
0,Approximate_Ratio
1200 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n ..]
in Either [Rational] [Approximate_Ratio]
-> Maybe (Either Rational Approximate_Ratio) -> Tuning
Tuning (forall a b. b -> Either a b
Right [Approximate_Ratio]
c) forall a. Maybe a
Nothing
tn_equal_temperament_12 :: Tuning
tn_equal_temperament_12 :: Tuning
tn_equal_temperament_12 = forall n. Integral n => n -> Tuning
tn_equal_temperament (Int
12::Int)
tn_equal_temperament_19 :: Tuning
tn_equal_temperament_19 :: Tuning
tn_equal_temperament_19 = forall n. Integral n => n -> Tuning
tn_equal_temperament (Int
19::Int)
tn_equal_temperament_31 :: Tuning
tn_equal_temperament_31 :: Tuning
tn_equal_temperament_31 = forall n. Integral n => n -> Tuning
tn_equal_temperament (Int
31::Int)
tn_equal_temperament_53 :: Tuning
tn_equal_temperament_53 :: Tuning
tn_equal_temperament_53 = forall n. Integral n => n -> Tuning
tn_equal_temperament (Int
53::Int)
tn_equal_temperament_72 :: Tuning
tn_equal_temperament_72 :: Tuning
tn_equal_temperament_72 = forall n. Integral n => n -> Tuning
tn_equal_temperament (Int
72::Int)
tn_equal_temperament_96 :: Tuning
tn_equal_temperament_96 :: Tuning
tn_equal_temperament_96 = forall n. Integral n => n -> Tuning
tn_equal_temperament (Int
96::Int)