Octave. You clap your hands on the beat. Usually a beat is a quarter note (qn). Half a beat .... Python is the big hub language for AI and NLP right now. 18 of 22 ...
Note to online readers: this was an invited talk, not a regular paper. It has no published paper associated with it in the conference proceedings.
Algorithmic Music in Haskell* D O N YA Q U I C K HASKELL SYMPOSIUM, SEPTEMBER 2017 * And a little bit of non-Haskell 1 of 22
Libraries in This Talk Euterpea 2 (euterpea.com) ◦ A Haskell library for musical representation, algorithmic composition, and virtual instrument design. ◦ Hackage: cabal update (current version is 2.0.4) cabal install Euterpea ◦ Textbook coming soon: The Haskell School of Music
Kulitta (donyaquick.com/kulitta) ◦ A Haskell library for automated music composition.
MusECI (musica.ml4ai.org/museci)
The little bit of non-Haskell
◦ A DSL within MUSICA, a large system under development for musical interaction and natural language processing.
2 of 22
“Algorithmic” vs. “Automated” Often used interchangeably. However… The words mean different things when applied to music. Algorithmic = some kind of algorithm is involved in some way. Automated = an algorithm is trying to reproduce specific human behaviors (a form of AI) Algorithmic:
Automated: Algorithmic
(from real-time interactive systems)
Automated
(computer-made score, human performance)
3 of 22
Composition vs. Performance Instrument
Composer
Score
We’ll be looking at this area today.
Performer
Performance
Sound
4 of 22
Representing Music: Numbers
Pitch
Highness or lowness. Often represented as a number or a tuple.
Pitch Number
Also called absolute pitch in some libraries.
Pitch Class Octave Beat Measure 5 of 22
Each key on a piano has a pitch number. C, C#, D, etc. Absolute pitch modulo 12. Folding the pitch axis onto itself.
Pitch number = pitch class + 12 * (octave +1)
You clap your hands on the beat. Usually a beat is a quarter note (qn). Half a beat is an eighth note (en). A grouping of beats. Most Western music has 4 beats per measure.
Representing Music: Larger Data Structures
Lists
• Pros: simple! Easy to represent simple melody+chords. • Cons: must either (1) be event-style or (2) sacrifice musical complexity or (3) be needlessly complicated.
Trees
• Pros: there is a LOT of hierarchy in music that really fits this kind of model. This is Euterpea’s approach. • Cons: one musical idea can many different topologies (sometimes way too many).
Graphs
• Common in real-time applications. • Used to some degree by Kulitta to capture repetition.
6 of 22
Representing Music: Functions
Transpose
Shift up/down along pitch axis.
Retrograde Reverse in time.
Invert
Invert: flip upside-down on the pitch axis around a particular point.
Invert then retrograde
Retrograde …or… Inversion
retrograde.invert
7 of 22
Some other operations: insertion, deletion, selection of musically meaningful features (i.e. a melody vs. harmony), tagging with meta/performance information, etc.
The Euterpea Library Score/Note-Level
Sound Synthesis
• •
• •
Music as trees Algorithmic composition
Real Time MIDI Stream
MIDI Files
Virtual instrument design Offline sound synthesis
WAV Files
8 of 22
Musical Trees in Euterpea Pitch-related data goes here.
Notes and Rests are leaves. ◦ Musical Primitives ◦ Notes are polymorphic.
Intermediate nodes compose subtrees in 2 ways: ◦ In sequence (:+:) ◦ Play all of one, then the other.
data Primitive a = Note Dur a | Rest Dur data Music a = Primitive a | Music a :+: Music a | Music a :=: Music a | Modify Control (Music a)
◦ In parallel (:=:). ◦ Play both starting at the same time.
Notice that this field is completely polymorphic. This may seem strange but is actually very powerful. 9 of 22
Euterpea Shorthands c 4 qn
Prim(Note qn (C,4))
note qn (C,4) note qn 60
Prim(Note qn 60)
line [m1, m2, …]
m1 :+: m2 :+: …
Some other functions: transpose retro (retrograde) invert forever - repeat to infinity
10 of 22
Making Music with Euterpea 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) And with some more work… Custom performance algorithm ( \p -> [NT (T, p)] (T, 0.25) :-> \p -> [NT (D, h p), NT (T, h p)] (I, 0.187) :-> \p -> [v (h p), i (h p)] (II, 0.40) :-> \p -> if isMaj p then [ii p] else [iv p] Arbitrary Haskell expressions are technically possible, although plain vanilla Kulitta sticks to conditionals. 17 of 22
Spoken Language and Music Consider the following sentence: “Move the C in measure 1 up a whole step.” Problem: descriptors can occur at many levels of abstraction! Must pattern match with incomplete information in an NLPfriendly way. ◦ Aspects of a query language.
Solution: a new language to address this: MusECI ◦ Musical Elementary Composable Ideas ◦ Currently implemented in Python*, but strongly functional. ◦ A direct outgrowth of the models in Euterpea and Kulitta. * Python is the big hub language for AI and NLP right now. 18 of 22
MusECI: Composition by Conversation “Move the B in measure 2 up an octave.”
What comes out of the TRIPS parser:
transpose( 12 , select( N((B,_), (1,_)) , m)) N(…) = a note _ = “any” or “don’t care,” which is a lot like None in Python.
19 of 22
Being Functional is Important “Move all the notes below A up one.” ◦ transpose(2, select(N((x: x(C,4) && x