Parser for the Scala scale file format. See http://www.huygens-fokker.org/scala/scl_format.html for details. This module succesfully parses all 4115 scales in v.77 of the scale library.
- type Pitch i = Either Cents (Ratio i)
- type Scale i = (String, i, [Pitch i])
- scale_description :: Scale i -> String
- scale_degree :: Scale i -> i
- scale_pitches :: Scale i -> [Pitch i]
- scale_octave :: Scale i -> Maybe (Pitch i)
- perfect_octave :: Integral i => Scale i -> Bool
- scale_pitch_representations :: Integral t => Scale i -> (t, t)
- pitch_cents :: Pitch Integer -> Cents
- type Epsilon = Double
- pitch_ratio :: Epsilon -> Pitch Integer -> Rational
- scale_uniform :: Epsilon -> Scale Integer -> Scale Integer
- scale_cents :: Scale Integer -> [Cents]
- scale_ratios :: Epsilon -> Scale Integer -> [Rational]
- comment_p :: String -> Bool
- filter_cr :: String -> String
- p_or :: [a -> Bool] -> a -> Bool
- remove_eol_comments :: String -> String
- filter_comments :: [String] -> [String]
- delete_trailing_point :: String -> String
- pitch :: (Read i, Integral i) => String -> Pitch i
- pitch_ln :: (Read i, Integral i) => String -> Pitch i
- parse :: (Read i, Integral i) => String -> Scale i
- load :: (Read i, Integral i) => FilePath -> IO (Scale i)
- dir_subset :: [String] -> FilePath -> IO [FilePath]
- load_dir :: (Read i, Integral i) => FilePath -> IO [Scale i]
A scale has a description, a degree, and a list of
Pitch element of the scale (ie. the ocatve).
Make scale pitches uniform, conforming to the most promininent pitch type.
Remove comments and null lines.
filter_comments ["!a","b","","c"] == ["b","c"]
Pitches are either cents (with decimal point) or ratios (with
map pitch ["700.0","3/2","2"] == [Left 700,Right (3/2),Right 2]
s <- load "/home/rohan/opt/scala/scl/xenakis_chrom.scl" scale_pitch_representations s == (6,1) scale_ratios 1e-3 s == [1,21/20,29/23,179/134,280/187,11/7,100/53,2]
Subset of files in dir with an extension in ext.
.scl files at dir.
db <- load_dir "/home/rohan/opt/scala/scl" length db == 4115 length (filter ((== 0) . scale_degree) db) == 1 length (filter (== Just (Right 2)) (map scale_octave db)) == 3562
let r = [0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24 ,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44 ,45,46,47,48,49,50,51,53,54,55,56,57,58,59,60,61,62,63,64 ,65,66,67,68,69,70,71,72,74,75,77,78,79,80,81,84,87,88 ,90,91,92,95,96,99,100,101,105,110,112,117,118,130,140,171 ,180,271,311,342,366,441,612] in nub (sort (map scale_degree db)) == r
let r = ["Xenakis's Byzantine Liturgical mode, 5 + 19 + 6 parts" ,"Xenakis's Byzantine Liturgical mode, 12 + 11 + 7 parts" ,"Xenakis's Byzantine Liturgical mode, 7 + 16 + 7 parts"] in filter (isInfixOf "Xenakis") (map scale_description db) == r
length (filter (not . perfect_octave) db) == 544
mapM_ (putStrLn.scale_description) (filter (not . perfect_octave) db)