-- | Tuning tables module Music.Theory.Tuning.Table where import qualified Music.Theory.Diagram.Grid as G import Music.Theory.List import Music.Theory.Pitch import Music.Theory.Pitch.Spelling import Music.Theory.Tuning import qualified Text.HTML.Light as H {- html-minimalist -} import Text.Printf -- * Equal temperament -- | 'octpc_to_pitch' and 'octpc_to_cps'. octpc_to_pitch_cps :: (Floating n) => OctPC -> (Pitch,n) octpc_to_pitch_cps x = (octpc_to_pitch pc_spell_ks x,octpc_to_cps x) -- | 12-tone equal temperament table equating 'Pitch' and frequency -- over range of human hearing, where @A4@ = @440@hz. -- -- > length tbl_12et == 132 -- > min_max (map (round . snd) tbl_12et) == (16,31609) tbl_12et :: [(Pitch,Double)] tbl_12et = let z = [(o,pc) | o <- [0..10], pc <- [0..11]] in map octpc_to_pitch_cps z -- | 24-tone equal temperament variant of 'tbl_12et'. -- -- > length tbl_24et == 264 -- > min_max (map (round . snd) tbl_24et) == (16,32535) tbl_24et :: [(Pitch, Double)] tbl_24et = let f x = let p = fmidi_to_pitch pc_spell_ks x p' = pitch_rewrite_threequarter_alteration p in (p',fmidi_to_cps x) in map f [12,12.5 .. 143.5] -- | Given an @ET@ table (or like) find bounds of frequency. -- -- > let r = Just (at_pair octpc_to_pitch_cps ((3,11),(4,0))) -- > in bounds_et_table tbl_12et 256 == r bounds_et_table :: Ord s => [(t,s)] -> s -> Maybe ((t,s),(t,s)) bounds_et_table tbl = let f (_,p) = compare p in find_bounds f (adj2 1 tbl) -- | 'bounds_et_table' of 'tbl_12et'. -- -- > map bounds_12et_tone (hsn 17 55) bounds_12et_tone :: Double -> Maybe ((Pitch,Double),(Pitch,Double)) bounds_12et_tone = bounds_et_table tbl_12et -- | Tuple indicating nearest 'Pitch' to /frequency/ with @ET@ -- frequency, and deviation in hertz and 'Cents'. type HS_R = (Double,Pitch,Double,Double,Cents) -- | Form 'HS_R' for /frequency/ by consulting table. -- -- > let {f = 256 -- > ;f' = octpc_to_cps (4,0) -- > ;r = (f,Pitch C Natural 4,f',f-f',to_cents (f/f'))} -- > in nearest_et_table_tone tbl_12et 256 == r nearest_et_table_tone :: [(Pitch,Double)] -> Double -> HS_R nearest_et_table_tone tbl f = case bounds_et_table tbl f of Nothing -> undefined Just ((lp,lf),(rp,rf)) -> let ld = f - lf rd = f - rf in if abs ld < abs rd then (f,lp,lf,ld,to_cents (f/lf)) else (f,rp,rf,rd,to_cents (f/rf)) nearest_12et_tone :: Double -> HS_R nearest_12et_tone = nearest_et_table_tone tbl_12et nearest_24et_tone :: Double -> HS_R nearest_24et_tone = nearest_et_table_tone tbl_24et -- * Cell -- | /n/-decimal places. -- -- > ndp 3 (1/3) == "0.333" ndp :: Int -> Double -> String ndp = printf "%.*f" -- | 'G.Table_Cell' from set of 'HS_R'. hs_r_cell :: Int -> (Int -> String) -> [HS_R] -> (Int,Int) -> G.Table_Cell hs_r_cell n nm_f t (i,j) = let dp = ndp n (f,p,pf,fd,c) = t !! i e = case j of 0 -> nm_f i 1 -> dp f 2 -> pitch_pp p 3 -> dp pf 4 -> dp fd 5 -> dp c _ -> undefined in ([],[H.cdata e])