Evolving Atmospheric Drone with Harmonized Melodies in Sonic Pi

Hello everyone,

I’m excited to share a piece I created in Sonic Pi. It features a main melody, a soft accompanying voice, a third harmonic voice, and a continuous evolving bass drone.

Feel free to try out the code, share your feedback, or suggest improvements. I hope it inspires some of you!

Here is the complete code:

use_bpm 60
use_synth :piano

melody = [:c4, :e4, :g4, :b4, :a4, :g4, :e4, :c4]
durations = [1, 1, 1, 1, 1, 1, 1, 2]

soft_melody = [:e3, :g3, :b3, :c4, :d4, :b3, :g3, :e3]
soft_durations = [1, 1, 1, 1, 1, 1, 1, 2]

third_voice = [:g2, :a2, :b2, :c3, :d3, :b2, :a2, :g2]
third_durations = durations

notes_played_main = 0
notes_played_bg = 0
notes_played_third = 0

amp_min_main = 0.2
amp_max_main = 1.0
amp_min_bg = 0.1
amp_max_bg = 0.3
amp_third = 0.15

live_loop :soft_melody do
with_fx :reverb, mix: 0.5, room: 1 do
melody.zip(durations).each do |note, dur|
amp_range = (amp_max_main - amp_min_main) / 2.0
amp_offset = amp_min_main + amp_range
amp = amp_offset + amp_range * Math.sin(notes_played_main * Math::PI / 8)
play note, amp: amp
sleep dur
notes_played_main += 1
end
end
end

live_loop :background_melody do
with_fx :reverb, mix: 0.7, room: 1 do
soft_melody.zip(soft_durations).each do |note, dur|
amp_range = (amp_max_bg - amp_min_bg) / 2.0
amp_offset = amp_min_bg + amp_range
amp = amp_offset + amp_range * Math.sin(notes_played_bg * Math::PI / 12)
play note, amp: amp
sleep dur
notes_played_bg += 1
end
end
end

live_loop :third_voice do
sleep durations.sum / 2
with_fx :reverb, mix: 0.4, room: 0.7 do
third_voice.zip(third_durations).each do |note, dur|
play note, amp: amp_third, sustain: dur * 0.9, release: dur * 0.1
sleep dur
notes_played_third += 1
end
end
end

live_loop :drone_continu do
use_synth :hollow
base_note = 36
dur = 0.1
tick_count = tick

scale_notes = scale(base_note, :minor_pentatonic, num_octaves: 1)

note = scale_notes[tick_count % scale_notes.length]

amp_mod = 0.9 + 0.1 * Math.sin(tick_count * Math::PI / 150 + Math::PI / 3)

play note, sustain: dur, release: 0, amp: amp_mod
sleep dur
end

happy listening and happy live coding to all

4 Likes

Kinda haunting. I like it.

Thank you so much! I’m really glad you like it , that’s exactly the vibe I was going for

I enjoyed it too. I love the legato melody contrasting with the rapidly bubbling bass.

fyi, code is easier to read and play with if you block it off with three backquotes.

Like so:

use_bpm 60
use_synth :piano

melody = [:c4, :e4, :g4, :b4, :a4, :g4, :e4, :c4]
durations = [1, 1, 1, 1, 1, 1, 1, 2]

soft_melody = [:e3, :g3, :b3, :c4, :d4, :b3, :g3, :e3]
soft_durations = [1, 1, 1, 1, 1, 1, 1, 2]

third_voice = [:g2, :a2, :b2, :c3, :d3, :b2, :a2, :g2]
third_durations = durations

notes_played_main = 0
notes_played_bg = 0
notes_played_third = 0

amp_min_main = 0.2
amp_max_main = 1.0
amp_min_bg = 0.1
amp_max_bg = 0.3
amp_third = 0.15

live_loop :soft_melody do
with_fx :reverb, mix: 0.5, room: 1 do
melody.zip(durations).each do |note, dur|
amp_range = (amp_max_main - amp_min_main) / 2.0
amp_offset = amp_min_main + amp_range
amp = amp_offset + amp_range * Math.sin(notes_played_main * Math::PI / 8)
play note, amp: amp
sleep dur
notes_played_main += 1
end
end
end

live_loop :background_melody do
with_fx :reverb, mix: 0.7, room: 1 do
soft_melody.zip(soft_durations).each do |note, dur|
amp_range = (amp_max_bg - amp_min_bg) / 2.0
amp_offset = amp_min_bg + amp_range
amp = amp_offset + amp_range * Math.sin(notes_played_bg * Math::PI / 12)
play note, amp: amp
sleep dur
notes_played_bg += 1
end
end
end

live_loop :third_voice do
sleep durations.sum / 2
with_fx :reverb, mix: 0.4, room: 0.7 do
third_voice.zip(third_durations).each do |note, dur|
play note, amp: amp_third, sustain: dur * 0.9, release: dur * 0.1
sleep dur
notes_played_third += 1
end
end
end

live_loop :drone_continu do
use_synth :hollow
base_note = 36
dur = 0.1
tick_count = tick

scale_notes = scale(base_note, :minor_pentatonic, num_octaves: 1)

note = scale_notes[tick_count % scale_notes.length]

amp_mod = 0.9 + 0.1 * Math.sin(tick_count * Math::PI / 150 + Math::PI / 3)

play note, sustain: dur, release: 0, amp: amp_mod
sleep dur
end