100% found this document useful (1 vote)
113 views11 pages

A Functional Model of Jazz Improvisation: Donya Quick Kelland Thomas

Jazz Method

Uploaded by

Paulo Teles
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
113 views11 pages

A Functional Model of Jazz Improvisation: Donya Quick Kelland Thomas

Jazz Method

Uploaded by

Paulo Teles
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

A Functional Model of Jazz Improvisation

Donya Quick Kelland Thomas


Stevens Institute of Technology Stevens Institute of Technology
United States United States
donyaquick@gmail.com kthomas3@stevens.edu

Abstract explored bossa nova and styles with a walking bassline in


We present a model of jazz improvisation where short-term our two implementations.
decision making by each performer is modeled as a func- The Haskell implementation, which is detailed here, per-
tion from contexts to music. Contexts can be shared, such mits the computer to improvise with itself and produce poten-
as an agreed-upon chord progression, or they can also be tially infinitely long pieces of music. It serves as a formalism
private—a current state for each musician. We formalize this of the problem, and we are actively augmenting it to support
model in Haskell to generate potentially infinitely long jazz new styles of music.
improvisations, and we have also used the same model in Our Python implementation was directed towards human-
Python to support real-time human-computer interaction computer interaction and treats the human as simply another
through jazz. function, just as the other computer musicians are modeled.
While the Python implementation is in a less well-structured
CCS Concepts • Software and its engineering → Func- state than our Haskell implementation, and therefore cov-
tional languages; Domain specific languages; • Human- ered in less detail, we are currently using the Python version
centered computing → HCI theory, concepts and models; as a way to test human reactions to different generative
• Hardware → Sound-based input / output; • Computing algorithms—an important metric for evaluating algorithmi-
methodologies → Multi-agent systems. cally generated music.
Keywords generative music, jazz, improvisation, functional
programming 2 Related Work
Improvisation in a jazz ensemble setting is conditioned on
ACM Reference Format:
certain contexts. In orthodox modern jazz1 , harmonic and
Donya Quick and Kelland Thomas. 2019. A Functional Model of Jazz
Improvisation. In Proceedings of the 7th ACM SIGPLAN International rhythmic constraints are decided upon and shared by all
Workshop on Functional Art, Music, Modeling, and Design (FARM performers in advance[10]. These constraints constitute a
’19), August 23, 2019, Berlin, Germany. ACM, New York, NY, USA, shared context for that performance. Aspects of the musical
11 pages. https://doi.org/10.1145/3331543.3342577 performance that are shared by all musicians include the har-
monic progression, meter, and tempo. In addition to shared
1 Introduction contexts, we can also assume that each musician has some
internal model that helps to govern what he/she plays next.
Modeling jazz improvisation in a sufficiently general, yet
There are several studies of the cognitive processes em-
computable way is an open problem. In this paper, we present
ployed in musical improvisation[10, 24]. This work high-
a functionally-inspired view of how traditional jazz improvi-
lights one of the key difficulties in improvisational music:
sation and the flow of information between musicians can
unlike other forms of composition, where the work can be
be modeled. Musicians are modeled as a combination of two
revisited and altered in multiple passes, an improvising jazz
things: (1) a function from contexts to music and (2) a private
musician must make decisions quickly from a finite amount
context or state. We have implemented our high-level model
of working memory and cannot go back in time to make
in two languages: Haskell and Python. We have primarily
corrections. This is much like what is called a transducer in
Permission to make digital or hard copies of all or part of this work for automata theory: a recursive function that produces output
personal or classroom use is granted without fee provided that copies while reading input.
are not made or distributed for profit or commercial advantage and that An improvising musician’s internal generative model
copies bear this notice and the full citation on the first page. Copyrights
for components of this work owned by others than the author(s) must
should produce musical statements that meet the constraints
be honored. Abstracting with credit is permitted. To copy otherwise, or provided by the shared musical context. Debate in the lit-
republish, to post on servers or to redistribute to lists, requires prior specific erature exists about how this is most effectively modeled.
permission and/or a fee. Request permissions from permissions@acm.org. This internal generative model may be influenced by bio-
FARM ’19, August 23, 2019, Berlin, Germany logical priors, learned sets of rules, or a combination of the
© 2019 Copyright held by the owner/author(s). Publication rights licensed
to ACM. 1 Excludingpractices and traditions often termed “free jazz”, where no
ACM ISBN 978-1-4503-6811-7/19/08. . . $15.00 or very few constraints are decided on or shared prior to beginning a
https://doi.org/10.1145/3331543.3342577 performance.

11
FARM ’19, August 23, 2019, Berlin, Germany Donya Quick and Kelland Thomas

Bass State 2
fBass
Bass State 1
Initial
Bass State fBass …


(No music)
Music Music …
fChords fChords …
Initial Chords State 1 Chords State 2
Chords State

Initial
Solo State fSolo fSolo …
Solo State 1 Solo State 2

Lead Sheet Segment 1 Lead Sheet Segment 2 …

Figure 1. Illustration of our model for improvisation over lead sheet segments. Gray lines indicate passing of state information,
black lines indicate observation of produced music, and dashed lines are observation of the lead sheet segment. We assume that
all parts “hear” the music produced by all other parts, while each part’s generative function only receives state information
relevant to itself.

two [10]. The use of repeated melodic patterns in improvised models assume may not be well-suited to how musicians
output is well documented[2], and one hypothesis posits create improvisational music.
that performers employ patterns as pre-learned structures Neural nets are also increasingly popular in generative
[17]. An alternative hypothesis involves the use of rules, like music[1, 6, 15], and have the benefit of being a rapid genera-
algorithms, to generate novel musical statements without tive model once trained. However, neural nuets often suffer
resorting to pre-learned patterns sitting in memory [10]. Nor- from similar problems to Markov chains for achieving long-
gaard suggests that these are both happening in advanced term coherency, although some attempts to model long-term
improvisers [13], but subsequent computational experiments structure do exist, including for jazz [5]. Once trained, the
suggest that the former hypothesis is more likely [14]. Re- adaptability of neural nets to other situations is also prob-
gardless of the source of the patterns, this work collectively lematic - there is typically no way to simply insert a new rule
suggests that improvisational behavior can be modeled as or definition without providing additional training data. Our
the episodic production of collections of notes. We take a framework aims to address some of these long-term issues
similar view of music generation in the models presented in while also avoiding over-fitting the model to a particular
this paper. style.
In contrast to the idea of generating collections of notes in A number of grammatical approaches have been employed
a single step, many statistical models for music have focused in music analysis and generation [7, 12, 20–22]. Grammars
on note-to-note transitions. Markov chains have historically can solve some of the long-term structural problems exhib-
been a popular model for music analysis and generation [4, ited by Markov chains and neural nets, making them ap-
16, 18, 26]. The states involved in these models are typically pealing for modeling offline music composition. However,
single notes or chords rather than sequential collections of they are not always suitable for real-time usage. While a
notes. While a useful analytical tool and often successful for fast generative algorithm may exist for a given category
short-term generation, long-term structure is more difficult of grammars, a similarly rapid parser may not. For proba-
to model, and Markov-based generative models typically bilistic grammars, which are a popular generative strategy,
only make judgments based on history rather than planning learning production probabilities is often a computationally
towards a specific goal. The notion of long-term structure non-trivial task. These issues are potentially problematic if
is somewhat different in an improvisational setting than the same model is to be used both in analytical and genera-
for offline composition, but it still manifests in tasks such as tive capacities to, for example, analyze a solo and respond to
following the constraints of a lead sheet, remembering motifs it appropriately.
used by other musicians, and deciding when and how to There has also been substantial work in the area of gener-
insert them at a later time. While long-term structural issues ative algorithms for jazz, with a focus on creating tools for
can be mitigated with longer history lengths in models such musicians [9, 11]. While useful for generating novel musical
as variable-length Markov chains [23], the cognitive models content (an idea generator for composers) and as practice
described previously suggest that the notion of states these tools in a variety of styles (for the isolated musician who

12
A Functional Model of Jazz Improvisation FARM ’19, August 23, 2019, Berlin, Germany

type PCNum = Int planning. For example, knowing that a key change is coming
type Scale = [PCNum] soon, a bass player may need to plan a series of notes that
data ChordCtxt = is largely within the current scale, avoids large jumps, and
ChordCtxt{sym::String, scale::Scale} lands on the root of the new key on the beat at which the
change occurs. Similarly, when planning which pitches to
cM7 = ChordCtxt "CM7" [0,2,4,5,7,9,11] play for the next chord, a pianist or guitarist will need to
dm7 = ChordCtxt "Dm7" [2,4,5,7,9,10,0] consider only options that are reachable for his/her particular
g7 = ChordCtxt "G7" [7,9,11,0,2,4,5] physical limitations (like hand size). Soloists may also need
to plan ahead to decide when to include a particular motif
Figure 2. Types for our implementation of chord contexts in an upcoming section.
and examples of definitions for three chords. The first chord, Finally, each musician also hears everyone’s music, or the
CM7, corresponds to a C-major scale. Dm7 represents a chord history of what has been performed. This common set of
from the D minor scale, and G7 is a dominant 7th chord observations is exclusively in the past (by the time musician
corresponding to the G Mixolydian mode (a major scale with A hears musician B start playing a note, that event has al-
a lowered seventh). ready happened). While a more continuous model is perhaps
most cognitively accurate, it also presents problems from
the standpoint of creating real-time applications, where too-
needs a band), these systems do not support dynamically frequent calls to generative and analytical algorithms can
changing contexts in a way that would allow the computer create an excessive computational burden that negatively
musicians to adapt on-the-fly to each other and human par- impacts performance. Therefore, we take a simplified model
ticipants over the span of an individual piece. While there has where the history is aggregated over the relatively short
been some work in the area of trading solos between a hu- segments that comprise our lead sheets.
man and computer[3], it is not concerned with generatively Figure 1 only features one of each kind of part (bass,
modeling other parts of the music like bass and harmony. chords, solo). This is the strategy used in our Haskell im-
Our model aims to address shifting contexts for all of the plementation, which is described in Section 4. However,
parts, such that generative algorithms for bass, harmony, the same model is extensible to other scenarios and also
and solos, can all interact under the same framework. While to human-computer interaction. In a scenario such as trad-
not directly addressed in this paper, drum parts can also be ing fours, a task where two musicians alternate short solos,
supported. we could have fsolo1 and fsolo2 that become active over al-
ternating collections of lead sheet segments. Our Python
3 Model implementation (see Section 6), supports substitution of hu-
We propose a model of improvisational jazz interactions man input for one of these functions, retaining the same
where each musician’s decision-making process is modeled general flow of information.
as a function from musical context to performed music over Our model is only intended to capture improvisational
short segments of music (typically 1 measure or less). We music, not static compositions such as fugues and sonatas—
define several kinds of musical context: the lead sheet, a per- styles that have constraints well beyond that of improvisa-
former’s internal state, and observed music. Figure 1 shows tional music. Trying to apply a model intended for improvisa-
the flow of information in our model. tion to a non-improvisational style is likely to result in only
The lead sheet defines a shared set of harmonic assump- a surface-level similarity to the intended target, with deeper
tions across musicians. It is a shared context amongst all features of the intended style being lost. While our model
participants. This need not be limited to formally notated can be generalized to other kinds of improvisational music
lead sheets - it can simply be a repeating chord progression and is not strictly limited to jazz, it is best suited to music
that all parties have agreed upon before playing, such as that is strongly based around real-time decision-making.
ii-V-I in G-major. The lead sheet informs both what the cur-
rent harmonic context is, as well as what changes in that
context are coming in the future. A lead sheet is divided
into segments, such one segment per measure. Segments 4 Haskell Implementation
may also start/end at other important musical features, such We provide an implementation of our high-level model in
as key/chord changes or boundaries of fixed compositional Haskell. We first define a system of data and function types to
elements. formalize improvisational behavior. Assuming the existence
Each performer also has an internal state representing of appropriate function definitions for the short-term behav-
decisions made that are not known to the other performers. ior of individual parts, we then supply a generative algorithm
This state, essentially a private context for decision-making, that can “run” the system. Examples of part functions are
will include a mixture of short term memory and future included in Section 5.

13
FARM ’19, August 23, 2019, Berlin, Germany Donya Quick and Kelland Thomas

data Segment a = Segment{ one beat of a segment in 4/4 has the value 1, while the equiv-
chordCtxt :: ChordCtxt, alent Euterpean duration value is 1/4.
segOnset :: Onset,
segDur :: Beat, 4.1 Lead Sheets
... } A lead sheet can be viewed as a partial specification of a
performance, and some sections of the music will be more
seg1 = Segment cM7 (1,0) 4 ... concretely defined than others. The common feature across
seg2 = Segment dmM7 (2,0) 4 ... all parts is the notion of a chord context. Chord contexts in
seg3 = Segment g7 (3,0) 4 ... sheet music are typically indicated using chord symbols such
seg4 = Segment cM7 (4,0) 4 ... as Cmin7 or Cm7 (both read as: "C minor seventh chord").
leadSheet = [seg1, seg2, seg3, seg4] Each one of these symbols implies a particular scale.
In our implementation, a scale is a list of pitch classes,
Figure 3. The Segment type and an example definition of a beginning with the root. We represent pitch classes as the
4-segment lead sheet. It represents a I-ii-V-I progression in integers 0-11 for C through B. For example, the C-major scale
C-major. Some fields of the Segment definition are omitted would be represented ast [0,2,4,5,7,9,11]. Enharmonically
since htey are not used by the examples in this paper. equivalent pitch classes share the same pitch class number,
or PCNum. A chord context, then, is a chord symbol (String)
and the scale it implies. Figure 2 shows these type definitions
Our Haskell implementation makes use of some music
and examples of definitions for specific chords.
representation features from the Euterpea library[8], which
Each chord context lasts for some duration of time. Chord
provides representations for musical structures along with
contexts often span whole measures, but not always. Some-
export and playback options using MIDI. We make use of the
times, they may start in the middle of a measure or even
following types and data structures from Euterpea, which
last for only a single beat. We will refer to spans of a lead
define a tree structure for music:
sheet falling under a single chord context as segments. Each
type AbsPitch = Int segment has an onset at a particular measure and beat, and
type Dur = Rational has a duration in beats. A lead sheet, then, is simply a list
data Primitive a = of segments. Segments may also contain other information,
Note Dur a | Rest Dur such as the current time signature and whether there are
data Music a = Prim (Primitive a) fixed musical elements to be played verbatim. However, these
| Music a :+: Music a extra kinds of information are not featured in the examples
| Music a :=: Music a in following sections and, therefore, have been omitted from
| ... the definitions given in this paper. Figure 3 shows an example
Euterpea’s (:+:) constructor, sequential composition, means definition of a lead sheet.
to play two musical subtrees sequentially. Similarly, the (:=:) It is worth noting that lead sheets in our system do not
constructor for parallel composition means to play two mu- have to be finite—nor must they be repeating. In fact, the
sical subtrees in parallel, such that they have the same start generative algorithms we have tested with our system to date
time (end times may be different). Leaf nodes in trees are all work on randomized lead sheets. While this is perhaps not
either notes (Note) or rests (Rest). The type variable, a, in the entirely applicable to most human-made music, it illustrates
Music data structure is used for storing pitch information, the adaptability of our approaches.
and sometimes other values like volume. In this paper, we
will only use a pitch number (an integer) representation for 4.2 Parts
pitch and will ignore other possible parameters. Therefore, Each instrumentalist can be considered a part in our model.
a Note leaf node will contain a duration and a pitch number. As previously described, the behavior of a part is modeled
The AbsPitch type means “absolute pitch” and refers to pitch as a function from a collection of contexts to musical output.
numbers. We use the MIDI standard of pitch numbers from Several contexts are shared: the current lead sheet segment,
0 to 127. which lead sheet segment is coming next, and what everyone
In Euterpea, which has no explicit representation for time in the group has played up to the current point in time.
signatures, durations are represented in terms of measures Figure 4 shows the type signature expected for a part func-
of 4/4, such that one measure in that time signature has the tion, or PartFun. Since we want to allow the possibility of
value 1. In contrast, the generative framework presented in stochastic decision making, we also thread a random gen-
this paper represents lead sheet segment duration in terms of erator of type StdGen through our generative functions2 . A
beats, and it also allows specification of a time signature for
each segment. The code in the following sections involves 2 While this passing of random generators can be “hidden” in monadic
conversions between these two methods of measuring time: contexts to simplify some of the type signatures, we have chosen to make

14
A Functional Model of Jazz Improvisation FARM ’19, August 23, 2019, Berlin, Germany

type History a = [(PartType, Music a)] runBand :: JazzBand a s -> History a ->
type PartFun a s = LeadSheet a -> StdGen -> Music a
s -> -- part state runBand [] h segs g = rest 0
Segment a -> -- current segment runBand jb h [] g = rest 0
Maybe (Segment a) -> -- next segment runBand jb h (seg1:segs) g =
History a -> StdGen -> (StdGen, s, Music a) let seg2 = if null segs then Nothing
else Just (head segs)
data JazzPart a s = JazzPart { result =
partType :: PartType, runSegment jb h seg1 seg2 g
instr :: InstrumentName, (gs, states, ms) = unzip3 result
partFun :: PartFun a s, jb' = zipWith (\st jp -> jp{state=st})
state :: s} states jb
h' = zip (map partType jb) ms
type JazzBand a s = [JazzPart a s] in foldr1 (:=:) ms :+:
runBand jb' h' segs (last gs)
Figure 4. The type of a part function and jazz band in our
framework. Figure 6. Function for “running” a band over an entire lead
sheet.
runSegment :: JazzBand a s -> History a ->
Segment a -> Maybe (Segment a) -> simple, while others require more complex states. Multiple
StdGen -> [(StdGen, s, Music a)] data types have been used in experimentation, but the same
runSegment [] h seg1 seg2 g = [] generative framework can be applied regardless of the type
runSegment (jp:jps) h seg1 seg2 g = of state used. Typically, a state should be a data type that
let (g', st, m) = has constructors to store information relevant to the various
partFun jp (state jp) seg1 seg2 h g parts. Some example state definitions are given in Section 5.
m' = instrument (instr jp) m In our implementation, each part is associated with its
in (g', st, m') : own state information. However, for cohesiveness within
runSegment jps h seg1 seg2 g' the generative system, the data type used for state infor-
mation must be the same for all parts. This means that a
Figure 5. Function for generating a band’s music over a given part will not necessarily utilize all possible construc-
single lead sheet segment. The instrument function, which tors for the state type it uses. For example, a walking bass
is imported from Euterpea, sets the MIDI instrument of a may require a state with a constructor that stores the target
Music value (which is piano if unspecified). pitch for the start of the next lead sheet segment. However,
a pianist playing chords might have no use for that kind
of information. Determining which constructors make up
PartFun, therefore, takes the current state for the part, the
a sufficiently generalized yet also sufficiently detailed state
current lead sheet segment, the next lead sheet segment (if
is an area of ongoing work. It is also an issue that does not
one exists), the musical history, and a generator. The func-
not strongly affect implementation in other languages. For
tion will return a new generator, an updated part state, and
example, an implementation in Python can simply treat the
the music to be played during the current segment. State
state as a list of heterogeneously-typed objects.
information is simply represented as an open-ended type
variable, s (discussed more in section 4.3). Section 5 contains 4.4 Generative Function
example function implementations for different jazz features
The generative function iterates over segments of a lead
using the PartFun function type.
sheet. For each segment, we need to run the generative func-
4.3 States tion for each performer. The function performing this task
is called runSegment, shown in Figure 5. We then define
States are left as unconstrained type variables in this system.
a function called runBand, shown in Figure 6, which calls
This is because the kind of information that needs to be
runSegment over each segment of the lead sheet. Note that
stored in the state for different parts is an area of ongoing
this implementation is tail-recursive, so it can be used on
research. For some styles, state information can be relatively
infinitely long lead sheets and produce infinitely long music.
the use of random generators explicit and avoid encapsulating the entire
implementation within other monads. This is purely a design choice, and
we may yet monad-ify the implementation in the future once our collection
of generative functions for parts is in a more advanced state.

15
FARM ’19, August 23, 2019, Berlin, Germany Donya Quick and Kelland Thomas

To use this function, we must first define a jazz band with bassFun :: PartFun AbsPitch s
some parts. Each part has its own initial state. bassFun s seg1 seg2 hist g =
myBand = [ let p1 = 36 + (head $ scale $ chordCtxt seg1)
JazzPart Bass AcousticBass bassFun state0, p2 = p1 + 7
...] mPat = note dqn p1 :+: note en p2 :+:
note dqn p2 :+: note en p1
We can then “run” the band on the lead sheet defined in m = trimTo seg1 (forever mPat)
Figure 3 with a random number seed of our choosing. Below, in (g, s, note (segDur seg1 / 4) p1)
a seed value of 5 is used.
m :: Music AbsPitch trimTo :: Segment a -> Music a -> Music a
m = runBand myJB [] leadSheet (mkStdGen 5) trimTo seg m =
cut (segDur seg) $
5 Examples remove (snd $ segOnset seg) m
Here we present several examples of part implementations
for our framework and general descriptions of algorithms we Figure 7. A state-less bossa nova bass implementation,
have implemented using the described models. For the sake where forever, cut, and remove are functions from Euterpea
of concision, only the simpler cases are shown with their that respectively repeat a music value forever, preserve only
corresponding Haskell implementations. More advanced al- a specified amount from the beginning, and delete a specified
gorithms, such as those used in our interactive Python imple- amount from the beginning.
mentation are described in more general terms. Our complete
Haskell code and more information on our Python frame-
work is available online3 . duration as the current segment contains, it produces the
Not all of the features supported by the high-level gen- classic bossa nova pattern over the current scale’s root and
erative framework are utilized in our examples of part im- fifth. The state in this case is not used, and therefore can
plementations. The high-level formalization developed in simply be a type variable. This makes the function applicable
Section 3 and its corresponding Haskell implementation in to any state type.
Section 4 were designed to be very general. Their usage with Output from this stateless bass function in combination
new styles and more complex generative algorithms that with a similarly stateless strategy for chords is shown in
more completely utilize its features is an area of ongoing Figure 8. However, both the state-less bass and state-less
work. We also show examples of musical output from two chords will sound rather repetitive compared to algorithms
algorithms that were constructed according to the model in that maintain a state and take history into account in order
Figure 1, but which used different data structures to those to make more complex decisions. Nevertheless, it serves as
presented in Section 4. Rewriting of those algorithms to use a kind of base case to illustrate use of the larger generative
Section 4’s data types is an ongoing effort. framework.
For examples including code, we will make use of some
Euterpea types and functions: 5.2 A Walking Bass: Looking Forward
note :: Dur -> a -> Music a A walking bass line provides an example of the need to plan
note d = Prim (Note d p) ahead for the next lead sheet segment. It is common for
rest :: Dur -> Music a the bass’s pitch on the first beat of a key change to be the
rest d = Prim (Rest d) root of the new scale. In order to effectively “walk” to this
new location, we must decide where it is before plotting
The note and rest functions are shorthands to create Notes.
intermediate points.
We also use several duration shorthands, qn, en, and dqn,
To implement this within our Haskell framework, we use a
which indicate the values quarter note, eighth note, and
state that is either null or stores the upcoming root pitch that
dotted quarter note respectively. Recall that we will be only
we must reach by the start of the next segment. Figures 9 and
using pitch numbers, or AbsPitch values, for the “a” type vari-
10 show the important aspects of this implementation. The
able in the definitions above, and therefore will be working
approach involves finding the pitch spaces corresponding
exclusively with music values of type Music AbsPitch.
to each segment’s scale, which is to say the set of pitches
5.1 A Simple Bossa Nova Bass in each segment that conform to its harmonic context. The
pitch space of the next segment (seg2) is used to choose the
Figure 7 is a deterministic bossa nova bass function that is
next root pitch, nextR. Then, the state’s root pitch is used as
one of the simplest use cases for this framework. For as much
a starting point from which to plot a path towards nextR by
3 More information, source code, and example recordings are available at: walking through the pitch space corresponding to the current
www.donyaquick.com/generative-jazz segment (seg1). Filling each beat in the current segment left

16
A Functional Model of Jazz Improvisation FARM ’19, August 23, 2019, Berlin, Germany

Dmin7 G7 Cmaj7
44                                

     
 44  
            
   
   
4
4       

  

         
     
Figure 8. Output from a bossa nova algorithm where the harmony and bass generators do not utilize a state. The solo algorithm
utilizes a state for the purpose of keeping track of its last pitch, thereby ensuring smoothness between segments of the lead
sheet.

to right, the algorithm will choose an intermediate pitch implemented involve direct reuse of portions of the user’s
between the previous pitch and nextR if there is room to do pitch sequences. We are currently developing approaches
so, otherwise it will choose a pitch that is near nextR (either that identify more musically meaningful motifs and that
above or below by some amount). Finally, nextR is passed to utilize more abstract notions of motifs, such as identify-
the next iteration to become the starting pitch of the next ing patterns of pitch intervals that can be reused in trans-
segment. posed settings along the lines of the models proposed by
Figure 11 shows an example of the music produced from Norgaard [14].
this method. More complex versions of this approach can
also introduce chromaticism and ornaments into the path- 5.4 Generating Chords
finding process. Figure 12 shows an example of output from
Harmony generation at the level of an expert musician is
a more complex walking bass algorithm that uses the same
a non-trivial problem while maintaining novelty/variation
general strategy.
over time and adhering to real-time constraints. As a result,
5.3 Generating Solos: Looking Backwards the harmony implementations we have explored to date in
both our Haskell and Python implementations are not terri-
Soloing algorithms demonstrate the need for looking at the
bly complex—we sacrifice some novelty and musical finesse
performance’s history, or at least a recent subset of it, particu-
for simplicity and speed. We have primarily used two simple
larly in scenarios where there is more than one soloist. When
algorithms: generating chords within a small range that are
two human soloists alternate improvised melodies, they typ-
playable with one hand on a piano where each chord is never
ically incorporate material from previous iterations in their
very far away from the others, and generating chords within
response in addition to adding new material. Musically, this
a larger range by random pitch selection (not necessarily be-
is a way of saying “I heard you, and here are my ideas.” We
ing playable with one hand, but typically playable with two
have explored soloing algorithms in our interactive Python
hands when the pitch range is constrained to two octaves or
implementation with the following behavior:
less). While these produce interesting results, we recognize
For each lead sheet segment:
that they do not capture certain critical elements of decision
1. If it is not the soloist’s turn, remain silent. If it has making in jazz, such as planning the voice-leading between
just become the soloist turn, scan the history for input chords and considering how different voicings of the same
from other soloists and extract motifs from it. chord may affect its perception within the larger harmonic
2. Generate a response as a sequence of chunks, where a context. We are actively investigating algorithms to handle
chunk is a short collection of notes. With some proba- these additional features.
bility, use a chunk of notes from the observed collec- Kulitta [19], a library for automated music composition
tion of motifs, otherwise generate a novel chunk. in Haskell, presents an implementation of chord spaces[25]
Currently, we use a random walk within the current scale that can be adapted to jazz. These spaces are time-consuming
to generate novel sections. Examples of this is shown in to generate but significantly faster to traverse, meaning that
Figures 8 and 13. Figure 14 shows a very simplistic exam- they can be used in real-time as long as they are generated
ple of chunk-based responses where the responses contain and loaded into memory before real-time constraints are
no novel material. Most of the soloing algorithms we have imposed. We have also found that generating partial chord

17
FARM ’19, August 23, 2019, Berlin, Germany Donya Quick and Kelland Thomas

data WalkingState = walk :: Int -> [AbsPitch] -> AbsPitch ->


NextRoot AbsPitch | NullState AbsPitch -> StdGen -> (StdGen, [AbsPitch])
bassRange = [36..50] :: [AbsPitch] walk 0 pSpace p1 p2 g = (g, [])
toSpace :: [AbsPitch] -> [AbsPitch] walk i pSpace p1 p2 g =
toSpace scale allPs = let (g2, pMid) = makeStep pSpace p1 p2 g
filter (\p -> elem (mod p 12) scale) allPs (g3, ps) = walk (i-1) pSpace pMid p2 g2
in (g3, p1 : ps)
wBassFun :: PartFun AbsPitch WalkingState
wBassFun NullState seg1 seg2 hist g = ... makeStep :: [AbsPitch] -> AbsPitch ->
wBassFun (NextRoot r) seg1 Nothing hist g = ... AbsPitch -> StdGen -> (StdGen, AbsPitch)
wBassFun (NextRoot r) seg1 (Just seg2) hist g = makeStep pitchSpace p1 p2 g =
let scale1 = scale $ chordCtxt seg1 let pH = max p1 p2
scale2 = scale $ chordCtxt seg2 pL = min p1 p2
pSpace1 = toSpace scale1 bassRange midPs = filter (\p -> p<pH && p>pL)
pSpace2 =toSpace scale2 bassRange pitchSpace
roots2 = nearPs = filter (\p -> p<pL+7 && p>pL-7
filter (\p -> mod p 12 == scale2 !! 0) && p/=pL && p/=pH) pitchSpace
pSpace2 ps = if null midPs then nearPs else midPs
(g1, nextR) = choose g roots2 in choose g ps
beats = round (4*segDur seg1)
(g2, pitches) = Figure 10. One possible implementation of the walk function
walk beats pSpace1 r nextR g1 called by the code in Figure 9. The goal of makeStep is to find
bassLine = line $ map (note qn) pitches an intermediate pitch meeting certain criteria: if the endpoint
in (g2, NextRoot nextR, pitches, p1 and p2, are far enough apart, then a member of
cut (segDur seg1/4) bassLine) where the pitch space that is between them is selected. Otherwise, a
nearby, but different pitch is selected. In this case, we define
Figure 9. Haskell implementation of a simple walking bass “nearby” as being within 7 half steps or semitones (an interval
algorithm, where choose is a utility function that stochas- of a perfect fifth).
tically selects an item from a list and the walk function is
shown in Figure 10. The first two lines of the wBassFun
function are omitted since their behavior is comparatively
uninteresting. In the first case, because there is no state in- for use with pattern-based generation algorithms (the sub-
formation, the function will simply create a state for itself jects of specific motif detection and pattern-based generative
and then recurse. In the second case, because the second algorithms are both beyond the scope of this paper). We have
segment is Nothing, the end of the piece has been reached used our Python implementation in live performances and
and only a single note is played. are currently using as as a way to evaluate the human per-
ception of different generative algorithms for solos.
Time constraints on generation are non-trivial when per-
forming music in a real-time interactive scenario with a hu-
spaces on the fly to find nearby chords is a viable strategy.
man participant, particularly at faster tempos. Under these
This is applicable to instruments like piano where there is a
conditions, it is not necessarily feasible to transition imme-
limit to how rapidly a pianist can move his/her hand across
diately from observing all of the humans input over one
the keyboard, typically opting for chords that are close to
segment to generating a coherent response immediately in
what was played previously.
the next segment. If decision-making is left too late, we risk
an audible pause in the music while the computer stops to
6 Interactive Python Implementation “think” before it can begin playing again.
In addition to implementing our model of jazz improvisa- Parallelism and asynchrony are sometimes required to
tion in Haskell, we have also implemented the same ideas allow the computer enough time to make decisions without
in Python. Our Python implementation supports real-time creating audible pauses or time leaks. In our real-time Python
interaction with a human musician, where the machine will implementation, we allow the computer to start running its
respond to the human with a mixture of borrowed and novel functions for each part over the next lead sheet segment a
material. To date we have primarily explored basic recombi- small amount of time before the current segment has actually
natory strategies for echoing a user’s solos, but more sophis- finished, ensuring that the results will be ready in time. The
ticated methods of pattern-extraction are under development general flow of information remains the same as in Figure 1,

18
A Functional Model of Jazz Improvisation FARM ’19, August 23, 2019, Berlin, Germany

Dmin7 G7 Cmaj7
 44 







 44           
    

Figure 11. Output from a simple walking bass algorithm with chords added.

Dmin7 G7 Cmaj7
4   
 4  
  
    
 44               

Figure 12. Output from a more complex walking bass algorithm that features chromatic steps and ornaments.

but there is a small overlap on the order of 10-250 millisec- One of the interesting areas of future application for our
onds between the music playing and when the functions are Python implementation is that it allows the evaluation of
executed. This means that the end of the current segment’s different generative models through participant studies. In
music is still playing while the computer quickly creates one experimental design that we have explored already with
music for the next segment, thereby ensuring a seamless a pilot study, participants interact with a 3-part generative
result. This overlap of the generative phase with the end of system under several different soloing algorithm settings.
the current segment’s music typically only results in only After each improvisation session with the system, partici-
one beat’s worth of the user’s input not being considered pants rate the soloing algorithm’s performance according
during generation. Of course, the exact degree of overlap to a variety of criteria (creativity, coherency, appropriate-
needed (and therefore the amount of user input that becomes ness of responses, and so on). We plan to run full studies
inaccessible during generation) will depend on the tempo soon with this system as a way to quantitatively measure
and complexity of the generative algorithms used for each the performance of different soloing algorithms.
part. One shortcoming of this system is that it handles lead
The modularity of our model allows different generative sheet segments in a very discrete way that is uniform across
functions to be swapped in and out easily. This property of all of the parts. Planning may occur at different levels of
the design has allowed us to use our Python implementation granularity for different instruments or parts, so some in-
as a tool for measuring the performance of different gen- struments may be better modeled with smaller or larger
erative algorithms at the task of interactive improvisation. segments than others. Additionally, the modeling of “listen-
These participant studies are an area of ongoing work. ing” to the shared musical output could be more continuous
rather than at junctions of lead sheet segments. Using a
threaded approach similar to that of our interactive Python
7 Conclusion implementation, we feel this would be possible while still
We have presented a high-level generative model for tradi- using a more discrete approach to generating output.
tional jazz improvisation along with some examples of its For our Haskell implementation, a monadic implementa-
application. The music generated by our implementations tion that encapsulates behaviors like the passing of random
to date has been promising, and we plan to continue de- generators might present a cleaner and interface. This would
velopment of both our Haskell and Python versions of the allow us to wrap many common operations involved in gen-
system. We hope that our implementations can ultimately erating music, such as the selection of one pitch from a pitch
be used as adaptive, interactive tools for musicians looking space, finding collections of pitches that instantiate an ab-
for automated accompaniment and for composers looking stract chord, determine membership of pitches to a key/mode,
for sources of inspiration. We are also currently exploring a and so on. However, we also feel this type of design choice
broader application of our models to styles other than jazz.

19
FARM ’19, August 23, 2019, Berlin, Germany Donya Quick and Kelland Thomas

Dmaj7 Bb maj7 Db maj7


4                                 
4             
   
4      
 4                         
                    

          
4              
4
  
 44                             
                    

Figure 13. Excerpt from a 4-part system that also includes a generative function for drums. The lead sheet was also algorith-
mically generated and is technically infinite; only the first three measures are shown here.

Solo A  44        
       
 
Solo B
44    
              
5

Solo A        
          
Solo B
 
                
Figure 14. Example of simple solo trading generated by our model. In this very simplified case, soloist A simply chooses one
of three possible phrases to play, and soloist B recombines what it “hears” by re-arranging chunks of 4 notes to fill its segment.

is best left until we have a more complete picture of the References


possible behaviors that would need encapsulating, including [1] Google AI. 2019. Magenta. https://magenta.tensorflow.org/
what kinds of features constitute a sufficiently generalized [2] Paul F. Berliner. 1994. Thinking in jazz : the infinite art of improvisation.
state data structure. University of Chicago Press.
[3] John A. Biles. 1994. GenJam: A Genetic Algorithm for Generating Jazz
Our models are also applicable to styles beyond jazz. Other
Solos. In Proceedings of the International Computer Music Conference.
improvisational music that has a turn-based or segmented 131–137.
structure can also be implemented, although the complexity [4] Parag Chordia, Avinash Sastry, and Sertan Senturk. 2011. Predictive
of the style would potentially be limited by the algorithms’ Tabla Modeling using Variable-length Markov and Hidden Markov
ability to keep up with real-time demands. We have done Models. Journal of New Music Research 40, 2 (2011), 105–118.
[5] Douglas Eck and Jürgen Schmidhuber. 2002. Learning the long-term
some preliminary exploration of using the same techniques structure of the blues. In In Proceedings of the International Conference
to generate ambient background music (roughly in the style on Artificial Neural Networks. 284–289.
of some old game soundtracks) and call-and-response sys- [6] Judy A. Franklin. 2004. Recurrent Neural Networks and Pitch Repre-
tems similar to Gregorian chant. We are also exploring the sentations for Music Tasks. In Forida AI Research Symposium.
use of real-time key detection as a way to govern the changes [7] Jon Gillick, Kevin Tang, and Robert M. Keller. 2009. Learning Jazz
Grammars. In Proceedings of the Sound and Music Computing Confer-
in harmonic context rather than an existing lead sheet. ence. 125–130.
[8] Paul Hudak et al. 2019. Euterpea. http://hackage.haskell.org/package/
Euterpea
[9] PG Music Inc. 2019. Band in a Box. https://www.pgmusic.com/
[10] P.N. Johnson-Laird. 2002. How Jazz Musicians Improvise. Music
Acknowledgments Perception 19, 3 (2002), 415–442.
[11] Robert M. Keller. 2018. Impro-Vizor. https://www.cs.hmc.edu/~keller/
This work was funded in part by DARPA Grant W911NF-16- jazz/improvisor/
1-0567, which is part of the Communicating with Computers [12] Fred Lerdahl and Ray S. Jackendoff. 1996. A Generative Theory of Tonal
program. Music. The MIT Press.

20
A Functional Model of Jazz Improvisation FARM ’19, August 23, 2019, Berlin, Germany

[13] Martin Norgaard. 2011. Descriptions of Improvisational Thinking by [20] Donya Quick. 2016. Learning Production Probabilities for Musical
Artist-Level Jazz Musicians. Journal of research in Music Education 59, Grammars. Journal of New Music Research 45 (2016), 295–313. Issue 4.
2 (2011), 109–127. [21] Martin Rohrmeier. 2011. Towards a Generative Syntax of Tonal Har-
[14] Martin Norgaard. 2013. Testing cognitive Theories by Creating a mony. Journal of Mathematics and Music 5, 1 (2011), 35–53.
Pattern-Based Probabilistic Algorithm for Melody and Rhythm in Jazz [22] Gerard Roma and Perfecto Herrera. 2010. Graph grammar representa-
Improvisation. Psychology: Music, Mind, and Brain 23, 4 (2013), 243. tion for collaborative sample-based music creation. In 5th Audio Mostly
[15] Tomasz Oliwa and Markus Wagner. 2008. Composing Music with Neu- Conference. ACM, Article 17, 8 pages.
ral Networks and Probabilistic Finite-State Machines. In Proceedings [23] Dana Ron, Yoram Singer, and Saftali Tishby. 1996. The Power of Am-
of the Conference on Appications of Evolutionary Computing. 503–508. nesia: learning Probabilistic Automata with Variable Memory Length.
[16] François Pachet. 2002. The Continuator: Musical Interaction With Machine Learning 25 (1996), 117–149.
Style. In Proceedings of the International Computer Music Conference. [24] John Sloboda. 1988. Generative Processes in Music: The Psychology of
2011–218. Performance, Improvisation, and Composition. University of Oxford
[17] Jeff Pressing. 2001. Improvisation: Methods and Models. Oxford Schol- Press.
arship Online. [25] Dimitri Tymoczko. 2006. The Geometry of Musical Chords. Science
[18] Donya Quick. 1997. Improvising Jazz with Markov Chains. Magazine 313, 5783 (2006), 72–74.
[19] Donya Quick. 2015. Composing with Kulitta. In Proceedings of Inter- [26] Christopher W. White. 2013. Some Statistical Properties of Tonality,
national Computer Music Conference. 306–309. 1650-1900.

21

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy