Euterpea Reading Notes I
I’m starting to read The Haskell School of Music, (HSM) by Paul Hudak and Donya Quick. These notes show how to set up Euterpea, the Haskell package used in HSM. We also give a few examples of how to construct and play music using Euterpea. The examples, taken from Euterpea2-Examples/NoteLevel/ BlueLambda.lhs, are by Donya Quick. Quick’s website points to many good references on Euterpea and algorithmic music and also features some of her compositions.
Another reference for setting things up is Taro Kuriyama’s GitHub repo
It would be very good if someone could verify the procedure on a “clean” machine to ensure that it is correct, complete, and reproducible. While the instructions below are by no means the only way to install and configure Euterpea, they do work.
There are a number of steps and challenges:
- Installing GHC
- Installing Euterpea
- Installing a synthesizer
- Configuring the synthesizer
- Testing
1. Installing GHC
I used the installer at haskell.org. It gives you ghc, cabal, and stack.
This part went well.
2. Installing Euterpea
This is tricky. The best resource is the download and installation page of euterpea.com. It is important to use the right version of GHC in installing Euterpea. If you do not, installation will fail. It is recommended to use cabal for installation, but I prefer stack. It is possible it do this with the correct instructions. Here is what to do.
Set up a new project: stack new euterpea
If you do cd euterpea
, you get this:
$ tree
.
├── ChangeLog.md
├── LICENSE
├── README.md
├── Setup.hs
├── app
│ └── Main.hs
├── eutx.cabal
├── package.yaml
├── src
│ └── Lib.hs
├── stack.yaml
└── test
└── Spec.hs
Getting the correct version of GCH
Look at stack.yaml
and find the line which looks something
like resolver: lts-16.13
. The lts
stands for long-time support. This line determines the version of
GHC. The version numbers for lts
and ghc
are not the same.
According to the download and installation page,
you must use a GHC version in the range 8.2 through 8.6.5. Change
lts-*.*
to lts-12.26
. This will ensure that GHC 8.4.4 is used.
If you now run stack ghci
, GHCi will come up, reporting version 8.4.4.
Setting the dependencies (stack.yaml)
Still in stack.yaml
, define the extra dependencies:
extra-deps:
- Euterpea-2.0.6
- PortMidi-0.1.6.1
- arrows-0.4.4.2
- Stream-0.4.7.2
- lazysmallcheck-0.6
Setting the dependencies (package.yaml)
Modify package.yaml
so that the dependencies
section looks like this:
dependencies:
- base >= 4.7 && < 5
- Euterpea
Run stack ghci
again, and try this:
*Main Lib> import Euterpea
*Main Lib Euterpea> note (1/4) (A, 4)
Prim (Note (1 % 4) (A,4))
If you get as far as seeing Prim (Note (1 % 4) (A,4))
, you know that Euterpea is
properly installed.
3. Installing a synthesizer
Running the Euterpea code playDev 0 $ c 4 qn
sends a MIDI command to
the configured synthesizer on channel 0, producing a quarter-note C in octave 4.
The synthesizer receives MIDI commands and turns it into sound. Our tasks are to
install a synthesizer and configure the communication between it and Euterpea.
The synthesizer
Donya Quick’s MIDI page, last modified Sep 13, 2019, has lots of good information. There are a number of options, among which are
- SimpleSynth
- fluidsynth (use
brew install fluidsynth
) - Sforzando
I am now using (2) fluidsynth. See Taro Kuriyama’s GitHub repo for more information on this program.
4. Configuring the synthesizer
Follow the directions on Donya Quick’s page. section 2. Below is an extract of her directions.
Find Audio MIDI Studio in
/Applications
and double-click on it.If you are lucky, you will get 2-3 windows that open up and one of them will be called “MIDI Studio.” If you don’t see that window, go up to the top left of the screen and go to Audio MIDI Setup > Preferences and make sure the box called “MIDI Window” is ticked.
Once you have MIDI Studio open, double-click on “IAC Driver.”
There should be a list called “Ports.” If this is empty, you don’t have any ports set up. To add a new port, click the “+” button. This port will now always be there (potentially unless you upgrade your OS version – then you might need to go through these steps again).
You can manage the ports you have as you need new ones or if you want to remove some later. Typically it’s good to have at least 2 ports at any given time. You can give your ports meaningful names if you want by double-clicking the name of the port.
NOTE: The above may not be necessary. Some synthesizers open virtual ports by themselves. I have not been able to test this, so please let me know if the above is always necessary.
5. Testing
Once you have your synthesizer(s) installed, you should test to see if Euterpea can see them. Note that you must start your synthesizer before you start Euterpea.
Here is what I got:
*Main Lib Euterpea> devices
Input devices:
InputDeviceID 0 IAC Driver Bus 1
Output devices:
OutputDeviceID 1 IAC Driver Bus 1
OutputDeviceID 2 FluidSynth virtual port (48276)
OutputDeviceID 3 sforzando
In this case, Euterpea sees three devices. I used the third to play a note:
*Main Lib Euterpea> playDev 2 $ c 4 qn
If you hear a quarter-note C, you know that Euterpea works for you. Time to celebrate!
Now for some music
There is a page of resources and things to try when starting out, e.g:
playDev 2 $ line [c 4 qn, c 4 qn, g 4 qn, g 4 qn, a 4 qn, a 4 qn, g 4 hn]
If you have configured things the right way (I haven’t), you can
use play
instead of playDev 2
.
Test again
Let’s make sure that we can get back into Euterpea after we have quit:
-- PROCEDURE
--
-- $ cd MY_EUTERPEA_WORKING_DIRECTORY
-- $ stack ghci
-- > import Euterpea
-- > devices -- check to see which device to use
--
-- Input devices:
-- InputDeviceID 0 IAC Driver Bus 1
--
-- Output devices:
-- OutputDeviceID 1 IAC Driver Bus 1
-- OutputDeviceID 2 FluidSynth virtual port (48276)
--
-- Ah, yes, I'll use device 2
--
-- > playDev 2 line [c 4 qn, c 4 qn, g 4 qn, g 4 qn, a 4 qn, a 4 qn, g 4 hn]
Something more elaborate
The examples below are taken from Euterpea2-Examples/NoteLevel/BlueLambda.lhs by Donya Quick.
> x1 = c 4 en :+: g 4 en :+: c 5 en :+: g 5 en
> x2 = x1 :+: transpose 3 x1
> x3 = x2 :+: x2 :+: invert x2 :+: retro x2
> x4 = forever x3 :=: forever (tempo (2/3) x3)
> playDev 2 x4
As explained the first chapter of Hudak and Quick’s book,
The Haskell School of Music, playing foo :+: bar
is
to play foo
, then bar
, while foo :=: bar
is to
play foo
and bar
simultaneously.
The version below introduces a half-note offset:
> x4' = forever x3 :=: (rest hn :+: forever (tempo (2/3) x3))
> playDev 2 x4'