Skip to content

Instantly share code, notes, and snippets.

@ejfox
Created December 25, 2023 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ejfox/075557d7bb167f6ccd70a653024a151e to your computer and use it in GitHub Desktop.
Save ejfox/075557d7bb167f6ccd70a653024a151e to your computer and use it in GitHub Desktop.
Sonic Pi + Midi Christmas Medley
# Defining all melodies with their durations in a dictionary-like structure
melodies = {
silent_night: {
notes: [:G, :A, :G, :E, :G, :A, :G, :E, :C, :G, :C, :G, :A, :A, :G],
durations: [0.5, 0.5, 1, 1, 0.5, 0.5, 1, 1, 0.5, 0.5, 1, 1, 0.5, 0.5, 1]
},
jingle_bells: {
notes: [:E, :E, :E, :E, :E, :E, :E, :G, :C, :D, :E, :F, :F, :F, :F, :F, :E, :E, :E, :E, :E, :D, :D, :E, :D, :G],
durations: [0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0.5, 1, 1, 0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.5, 0.5, 0.5, 1]
},
deck_the_halls: {
notes: [:E, :G, :F, :E, :D, :C, :D, :E, :D, :G, :G, :A, :G, :F, :E, :D],
durations: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
},
o_christmas_tree: {
notes: [:C, :C, :D, :C, :F, :E, :C, :C, :D, :C, :G, :F],
durations: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
},
we_wish_you_a_merry_christmas: {
notes: [:G, :E, :D, :C, :D, :G, :G, :E, :D, :C, :E, :C],
durations: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
},
the_first_noel: {
notes: [:G, :A, :B, :G, :G, :A, :B, :G, :E, :E, :F, :G],
durations: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
},
giant_steps_segment: {
notes: [:B, :D, :F, :B, :G, :B, :D, :F, :E, :G, :B, :D],
durations: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
}
}
# Function to play a specific melody with MIDI, swapping notes from another melody
define :play_melody_with_variation_midi do |channel, primary_melody_name|
primary_melody = melodies[primary_melody_name][:notes]
primary_durations = melodies[primary_melody_name][:durations]
total_duration = primary_durations.sum * [1, 0.5, 1.5].choose # Slowing down the melody
primary_melody.each_with_index do |note, i|
if one_in(6 )
alternate_melody_name = melodies.keys.reject { |m| m == primary_melody_name }.choose
note = melodies[alternate_melody_name][:notes].choose
end
midi note, channel: channel, sustain: primary_durations[i]
sleep total_duration / primary_melody.length
end
end
# Function to play a more harmonious jazzy chord based on the currently active melody
define :play_jazzy_chord_midi do |channel, current_melody|
if one_in(4) # Adjust the frequency of jazzy chords here
melody_notes = melodies[current_melody][:notes]
root_note = melody_notes.choose # Choosing a root note from the melody
# Selecting chord types that are more likely to harmonize
chord_types = [:major7, :minor7, :maj9]
chord_type = chord_types.choose
chord_notes = chord(root_note, chord_type)
chord_notes.each do |note|
midi note, channel: channel, sustain: [2,4,6].choose
end
sleep [2,4,8].choose # Pause between chords
end
end
# Mixing of evolving melodies and occasional jazzy chords over different MIDI channels
in_thread do
loop do
primary_melody = melodies.keys.choose
play_melody_with_variation_midi 1, primary_melody
play_jazzy_chord_midi 3, primary_melody
sleep [1, 2, 4].choose # Adjusting space between melody plays
end
end
in_thread do
loop do
primary_melody = melodies.keys.choose
play_melody_with_variation_midi 2, primary_melody
play_jazzy_chord_midi 3, primary_melody
sleep [2, 4, 8].choose # Adjusting space between melody plays
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment