Safe Haskell | Safe-Inferred |
---|

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]

# Documentation

type Scale i = (String, i, [Pitch i])Source

A scale has a description, a degree, and a list of `Pitch`

es.

scale_description :: Scale i -> StringSource

Text description of scale.

scale_degree :: Scale i -> iSource

The degree of the scale (number of `Pitch`

es).

scale_octave :: Scale i -> Maybe (Pitch i)Source

The last `Pitch`

element of the scale (ie. the *ocatve*).

perfect_octave :: Integral i => Scale i -> BoolSource

Is `scale_octave`

perfect, ie. `Ratio`

of `2`

or `Cents`

of
`1200`

.

scale_pitch_representations :: Integral t => Scale i -> (t, t)Source

pitch_cents :: Pitch Integer -> CentsSource

Pitch as `Cents`

, conversion by `to_cents_r`

if necessary.

pitch_ratio :: Epsilon -> Pitch Integer -> RationalSource

Pitch as `Rational`

, conversion by `reconstructed_ratio`

if
necessary, hence *epsilon*.

scale_uniform :: Epsilon -> Scale Integer -> Scale IntegerSource

Make scale pitches uniform, conforming to the most promininent pitch type.

scale_cents :: Scale Integer -> [Cents]Source

Scale as list of `Cents`

(ie. `pitch_cents`

) with `0`

prefix.

scale_ratios :: Epsilon -> Scale Integer -> [Rational]Source

Scale as list of `Rational`

(ie. `pitch_ratio`

) with `1`

prefix.

remove_eol_comments :: String -> StringSource

Remove to end of line `!`

comments.

filter_comments :: [String] -> [String]Source

Remove comments and null lines.

filter_comments ["!a","b","","c"] == ["b","c"]

delete_trailing_point :: String -> StringSource

Delete trailing `.`

, `read`

fails for `700.`

.

pitch :: (Read i, Integral i) => String -> Pitch iSource

Pitches are either cents (with decimal point) or ratios (with `/`

).

map pitch ["700.0","3/2","2"] == [Left 700,Right (3/2),Right 2]

load :: (Read i, Integral i) => FilePath -> IO (Scale i)Source

Load `.scl`

file.

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]

dir_subset :: [String] -> FilePath -> IO [FilePath]Source

Subset of files in *dir* with an extension in *ext*.

load_dir :: (Read i, Integral i) => FilePath -> IO [Scale i]Source

Load all `.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)