hsc3-lang-0.11: Sound/SC3/Lang/Data/Vowel.hs
-- | Data set giving formant locations for 'Vowel's.
module Sound.SC3.Lang.Data.Vowel where
import Data.List
import Data.Maybe
-- * Lookup functions
-- | Extract 'Fn'th formant triple of an 'Fdata'.
--
-- > formant F1 (fdata Bass I) == (1750,-30,90)
formant :: Num n => Fn -> Fdata n -> (n,n,n)
formant n v = formants v !! fromEnum n
-- | Lookup formant 'Fdata' given 'Voice' and 'Vowel'.
--
-- > fdata Bass I == (Bass,I,[250,1750,2600,3050,3340]
-- > ,[0,-30,-16,-22,-28]
-- > ,[60,90,100,120,120])
fdata :: Num n => Voice -> Vowel -> Fdata n
fdata v i =
let f (p,q,_,_,_) = p == v && q == i
in fromMaybe (error "fdata") (find f fdata_table)
-- | Formant triples of an 'Fdata'.
--
-- > formants (fdata Bass I) == [(250,0,60)
-- > ,(1750,-30,90)
-- > ,(2600,-16,100)
-- > ,(3050,-22,120)
-- > ,(3340,-28,120)]
formants :: Num n => Fdata n -> [(n,n,n)]
formants (_,_,f,a,bw) = map triple' (transpose [f,a,bw])
-- * Data types
-- | Enumeration of voices.
data Voice = Soprano | Alto | CounterTenor | Tenor | Bass
deriving (Enum,Bounded,Eq,Read,Show)
-- | Enumeration of vowels.
data Vowel = A | E | I | O | U
deriving (Enum,Bounded,Eq,Read,Show)
-- | Vowel tuple of form ('Voice','Vowel',/freq/,/db/,/bw/).
type Fdata n = (Voice,Vowel,[n],[n],[n])
-- | Enumeration of formant indices.
data Fn = F0 | F1 | F2 | F3 | F4
deriving (Enum,Bounded,Eq,Read,Show)
-- * Table
-- | 'Fdata' table.
fdata_table :: Num n => [Fdata n]
fdata_table =
[(Soprano
,A
,[800,1150,2900,3900,4950]
,[0,-6,-32,-20,-50]
,[80,90,120,130,140])
,(Soprano
,E
,[350,2000,2800,3600,4950]
,[0,-20,-15,-40,-56]
,[60,100,120,150,200])
,(Soprano
,I
,[270,2140,2950,3900,4950]
,[0,-12,-26,-26,-44]
,[60,90,100,120,120])
,(Soprano
,O
,[450,800,2830,3800,4950]
,[0,-11,-22,-22,-50]
,[70,80,100,130,135])
,(Soprano
,U
,[325,700,2700,3800,4950]
,[0,-16,-35,-40,-60]
,[50,60,170,180,200])
,(Alto
,A
,[800,1150,2800,3500,4950]
,[0,-4 ,-20,-36,-60]
,[80,90,120,130,140])
,(Alto
,E
,[400,1600,2700,3300,4950]
,[0,-24,-30,-35,-60]
,[60,80,120,150,200])
,(Alto
,I
,[350,1700,2700,3700,4950]
,[0,-20,-30,-36,-60]
,[50,100,120,150,200])
,(Alto
,O
,[450,800,2830,3500,4950]
,[0,-9 ,-16,-28,-55]
,[70,80,100,130,135])
,(Alto
,U
,[325,700,2530,3500,4950]
,[0,-12,-30,-40,-64]
,[50,60,170,180,200])
,(CounterTenor
,A
,[660,1120,2750,3000,3350]
,[0,-6 ,-23,-24,-38]
,[80,90,120,130,140])
,(CounterTenor
,E
,[440,1800,2700,3000,3300]
,[0,-14,-18,-20,-20]
,[70,80,100,120,120])
,(CounterTenor
,I
,[270,1850,2900,3350,3590]
,[0,-24,-24,-36,-36]
,[40,90,100,120,120])
,(CounterTenor
,O
,[430,820,2700,3000,3300]
,[0,-10,-26,-22,-34]
,[40,80,100,120,120])
,(CounterTenor
,U
,[370,630,2750,3000,3400]
,[0,-20,-23,-30,-34]
,[40,60,100,120,120])
,(Tenor
,A
,[650,1080,2650,2900,3250]
,[0,-6 ,-7 ,-8,-22]
,[80,90,120,130,140])
,(Tenor
,E
,[400,1700,2600,3200,3580]
,[0,-14,-12,-14,-20]
,[70,80,100,120,120])
,(Tenor
,I
,[290,1870,2800,3250,3540]
,[0,-15,-18,-20,-30]
,[40,90,100,120,120])
,(Tenor
,O
,[400,800,2600,2800,3000]
,[0,-10,-12,-12,-26]
,[40,80,100,120,120])
,(Tenor
,U
,[350,600,2700,2900,3300]
,[0,-20,-17,-14,-26]
,[40,60,100,120,120])
,(Bass
,A
,[600,1040,2250,2450,2750]
,[0,-7 ,-9 ,-9,-20]
,[60,70,110,120,130])
,(Bass
,E
,[400,1620,2400,2800,3100]
,[0,-12 ,-9,-12,-18]
,[40,80,100,120,120])
,(Bass
,I
,[250,1750,2600,3050,3340]
,[0,-30,-16,-22,-28]
,[60,90,100,120,120])
,(Bass
,O
,[400,750,2400,2600,2900]
,[0,-11,-21,-20,-40]
,[40,80,100,120,120])
,(Bass
,U
,[350,600,2400,2675,2950]
,[0,-20,-32,-28,-36]
,[40,80,100,120,120])]
-- * Tuple/List functions
-- | Construct a triple from a three element list.
--
-- > triple [1..3] == Just (1,2,3)
triple :: [a] -> Maybe (a,a,a)
triple x =
case x of
[p,q,r] -> Just (p,q,r)
_ -> Nothing
-- | Partial variant of 'triple'.
--
-- > triple' [1..3] == (1,2,3)
triple' :: [a] -> (a,a,a)
triple' = fromJust . triple