-
Notifications
You must be signed in to change notification settings - Fork 0
/
Note.hs
75 lines (60 loc) · 1.69 KB
/
Note.hs
1
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
module Note where
import Scale (Scale, Step (..))
data Note
= C
| CSharp
| D
| DSharp
| E
| F
| FSharp
| G
| GSharp
| A
| ASharp
| B
deriving (Show, Read, Enum, Eq)
type SemiTone = Int
type ScalePattern = [Note]
-- | Generate and print a scale pattern to the screen.
presentScalePattern :: Note -> Scale -> IO ()
presentScalePattern n s =
mapM_ (putStr . noteToStr) (genScalePattern n s) >> putStrLn ""
-- | Generate a concrete scale beginning at root note.
genScalePattern :: Note -> Scale -> ScalePattern
genScalePattern = scanl transpose
-- | Transpose a note by a given step.
transpose :: Note -> Step -> Note
transpose note step
= case step of
Half -> toNote . sameOctave . halfStep $ toTone note
Whole -> toNote . sameOctave . wholeStep $ toTone note
AugSec -> toNote . sameOctave . augSec $ toTone note
-- | Perform a half step.
halfStep :: SemiTone -> SemiTone
halfStep = (+ 1)
-- | Perform a whole step.
wholeStep :: SemiTone -> SemiTone
wholeStep = (+ 2)
-- | Perform both half and whole step to form an 'augmented second'.
augSec :: SemiTone -> SemiTone
augSec = (+ 3)
-- | Keep a tone in the same octave.
sameOctave :: SemiTone -> SemiTone
sameOctave = flip mod 12
-- | Used for transposition
toTone :: Note -> SemiTone
toTone = fromEnum
-- | Transform SemiTone back into classical notation as 'Note'
toNote :: SemiTone -> Note
toNote = toEnum
-- | Print a Note to the screen.
noteToStr :: Note -> String
noteToStr n =
case n of
CSharp -> "C# "
DSharp -> "D# "
FSharp -> "F# "
GSharp -> "G# "
ASharp -> "A# "
_ -> show n ++ " "