Euterpea Reading Notes II
This guide is a little log that I wrote am writing
while reading the book The Haskell School of Music,
by Paul Hudak and Donya Quick.
Solutions to some of the exercises. (But try them yourself first!)
Chapter 2
2.1 Preliminaries
I’ve found that good practice when starting a session with Euterpea is to check which device Euterpea will be talking to:
> devices
Input devices:
InputDeviceID 0 IAC Driver Bus 1
Output devices:
OutputDeviceID 1 IAC Driver Bus 1
OutputDeviceID 2 sforzando
Channel 1, doesn’t work for me, so I use channel 2, like this:
> playDev 2 $ c 4 qn
This will play a quarter note C in octave 4.
For convenience, I define p = playDev 2
so that it
is enough to say
> p $ c 4 qn
2.2 Note
My reading of the text is that note (1/2) (C,4) should produce a Music Pitch value and therefore be playable. Alas, this is not the case:
> :t note (1/2) (C,4)
note (1/2) (C,4) :: Num b => Music (PitchClass, b)
By comparison, we have this, which does produce a playable value:
> :t note (1/2) (mp C 4)
note (1/2) (mp C 4) :: Music Pitch
Go figure! So we introduce the function mp (make pitch):
mp :: PitchClass -> Int -> Pitch
mp pitchClass octave =
(pitchClass, octave)
Let’s check it out:
> import Experiments
> p $ note (1/2) (mp C 4)
-- A half note C in octave 4 is played
Note, however, that one has convenient functions for constructing notes:
c :: Octave -> Dur -> Music Pitch
cf :: Octave -> Dur -> Music Pitch
cs :: Octave -> Dur -> Music Pitch
2.3 Making Music: Notes in Sequence
Let’s put some notes together to make a simple melody. First, some useful (to me abbreviations):
do1 = c 4 qn -- can't use "do". It is reserved word.
> re = d 4 qn
> mi = e 4 qn
The operator :+:
is used to glue notes together in
sequence:
> mel = do1 :+: re :+: mi :+: do1
> p mel
Recognize it?
Note: it is important to always know the types of the things you are working with. It is easy to recall these. For example:
> :t (:+:)
(:+:) :: Music a -> Music a -> Music a
Addendum
We complete the scale for later use.
> fa = f 4 qn
> sol = g 4 qn
> la = a 4
> la = a 4 qn
> si = b 4 qn
2.4 Making Music: Notes in Parallel
Next, let’s harmonize our melody. To do this,
we use the operator :=:
to play notes in parallel.
Thus, we can construct a C major triad like this
> triad = do1 :=: mi :=: sol
Let’s harmonize our melody in parallel thirds:
> mel2 = mi :+: fa :+: sol :+: mi
> hmel = mel :=: mel2
We could have done this in another way, first constructing
do1 :=: mi
, then re :=: fa
, etc., and then putting them
in sequence.
You could also construct the second line like this:
mel2' = transpose 4 mel
Here transpose 4
is a function that raises the pitch of
each note in the melody by four semitones (half-steps),
that is, by a major third:
> :t transpose
transpose :: AbsPitch -> Music a -> Music a
Now we can do this:
> p $ mel :=: mel2
Does the new harmonization sound like the old one? What is the theoretical reason for your answer?
2.5 Some Other Music Functions
Euterpea has functions for modifying melodies. Suppose, for example, that we want to speed a melody up or slow it down. We can use this:
> :t tempo
tempo :: Dur -> Music a -> Music a
With tempo
it is easy play our test melody
faster or slower:
> p $ tempo (2) mel -- play it faster
> p $ tempo (1/2) mel -- play it slower
We can also change the instrument which plays the melody:
> p $ instrument Trombone mel