Introduction
Hello there! I’m very excited to join the community to contribute some ideas and various future lines to consider.
This is the first idea: Although, Neo-Riemannian Theory is mainly used to analyze music, I think that an improvisational approach would be quite interesting in the Sonic Pi environment. For this reason, I was configuring three common functions from Neo-Riemannian Theory (P = parallel, R= relative, L = leading tone) to apply during live improvisations.
On the other hand, I have been working with these functions while teaching introductory classes to SP with Mathematical Music Theory; in this sense, it is also a good concept to intersect computer science, music and mathematics.
I share with you the functions and I propose a simple example with a loop that takes base notes and chords and transforms them according to the function P, R or L; also showing the name of the chord in the log.
Code and example
define :p_neo_riemannian do |note, triad|
if triad == :major
x = (chord note, :major)[0]
y = (chord note, :major)[1]
y2 = (y - 1)
z = (chord note, :major)[2]
puts [note_info(x), "minor"]
play [x, y2, z].ring
elsif triad == :minor
x = (chord note, :minor)[0]
y = (chord note, :minor)[1]
y3 = (y + 1)
z = (chord note, :minor)[2]
puts [note_info(x), "major"]
play [x, y3, z].ring
else
puts "Wrong chord, enter a major or minor chord"
end
end
define :r_neo_riemannian do |note, triad|
if triad == :major
x = (chord note, :major)[0]
y = (chord note, :major)[1]
z = (chord note, :major)[2]
z2 = (z + 2)
puts [note_info(z2), "minor"]
play [x, y, z2].ring
elsif triad == :minor
x = (chord note, :minor)[0]
x2 = (x - 2)
y = (chord note, :minor)[1]
z = (chord note, :minor)[2]
puts [note_info(y), "major"]
play [x2, y, z].ring
else
puts "Wrong chord, enter a major or minor chord"
end
end
define :l_neo_riemannian do |note, triad|
if triad == :major
x = (chord note, :major)[0]
x2 = (x - 1)
y = (chord note, :major)[1]
z = (chord note, :major)[2]
puts [note_info(y), "minor"]
play [x2, y, z].ring
elsif triad == :minor
x = (chord note, :minor)[0]
y = (chord note, :minor)[1]
z = (chord note, :minor)[2]
z2 = (z + 1)
puts [note_info(z2), "major"]
play [x, y, z2].ring
else
puts "Wrong chord, enter a major or minor chord"
end
end
# Example
4.times do
n = 4
density n / (n/2) do
n.times do
r_neo_riemannian [:a, :f, :d, :e ].tick,
[:minor, :major, :minor, :minor].look
sleep 1
end
n.times do
l_neo_riemannian [:c, :b, :d, :g ].tick,
[:major, :minor, :major, :minor].look
sleep 1
end
n.times do
p_neo_riemannian [:e, :g, :a, :b ].tick,
[:major, :major, :minor, :minor].look
sleep 1
end
end
end
Future works
-
It would be great to create functions that allow you to easily compose, in this way, you could create music with PLP, LRP and other functions from the nuclear functions P, L and R.
-
Another interesting functionality would be to create an analysis in “improvisational” time of the functions that occur in any chord progression. Thus, you could observe which functions contain a harmonic progression.
-
Some more generative music: take pseudorandomly generated Neo-Riemannian functions to apply them to a set of chords.