Algorithmic Music in Haskell

15 downloads 0 Views 685KB Size Report
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