Hi there,
I’m new here and would like to share a piano framework with you, I created.
It uses the VSCO Upright Piano samples for playing and frees you from reading the sfz-file for using the right samples and pitching to get the right notes.
You can use the my_piano_raw* functions to play the piano and have full control on the effect hull curve or you can use the my_piano_play* functions to play a partiture directly.
I integrated a small example song part, too, for easy introduction and commented all functions and parameters to understand what they do.
To start with it you just have to edit the my_piano_dir variable to set the path to your VSCO Upright Piano samples.
I would really like to know what you think about it and especially if you have any better ideas for the tuning variables my_piano_nonleg_length, my_piano_staccato_length, my_piano_legato_length.
So, here is the framework:
# Framework for the VSCO piano
#
# Author: minced mind
# License: CC0 (see https://creativecommons.org/share-your-work/public-domain/cc0/)
# Version: 0.1
# Global variables
# Defines the directory of the piano samples from VSCO
my_piano_dir = "~/music-making/samples/VSCO-2-CE-SFZ/Keys/Upright Piano/"
# Length of a full note in seconds, often (current_bpm / 15)
my_piano_full_note_length = (current_bpm / 15)
# Relative length of a non-legato note length
my_piano_nonleg_length = 0.8
# Relative length of a staccato note length
my_piano_staccato_length = 0.5
# Relative length of a legato note length
my_piano_legato_length = 1.1
# The function my_piano_sample is used from the other framework functions to select the right sample
# Parameters:
# my_note = note value which should be played
# my_dyn = the dynamic (loudness) which should be played (1, 2, 3)
define :my_piano_sample do |my_note, my_dyn|
my_piano_list_dyn1 = ["Player_dyn1_rr1_000", "Player_dyn1_rr1_002", "Player_dyn1_rr1_004",
"Player_dyn1_rr1_006", "Player_dyn1_rr1_008", "Player_dyn1_rr1_010",
"Player_dyn1_rr1_012", "Player_dyn1_rr1_014", "Player_dyn1_rr1_016",
"Player_dyn1_rr1_018", "Player_dyn1_rr1_020", "Player_dyn1_rr1_022",
"Player_dyn1_rr1_024", "Player_dyn1_rr1_026", "Player_dyn1_rr1_028",
"Player_dyn1_rr1_030", "Player_dyn1_rr1_032", "Player_dyn1_rr1_034",
"Player_dyn1_rr1_036", "Player_dyn1_rr1_038", "Player_dyn1_rr1_040",
"Player_dyn1_rr1_042", "Player_dyn1_rr1_044"]
my_piano_list_dyn2 = ["Player_dyn2_rr1_000", "Player_dyn2_rr1_002", "Player_dyn2_rr1_004",
"Player_dyn2_rr1_006", "Player_dyn2_rr1_008", "Player_dyn2_rr1_010",
"Player_dyn2_rr1_012", "Player_dyn2_rr1_014", "Player_dyn2_rr1_016",
"Player_dyn2_rr1_018", "Player_dyn2_rr1_020", "Player_dyn2_rr1_022",
"Player_dyn2_rr1_024", "Player_dyn2_rr1_026", "Player_dyn2_rr1_028",
"Player_dyn2_rr1_030", "Player_dyn2_rr1_032", "Player_dyn2_rr1_034",
"Player_dyn2_rr1_036", "Player_dyn2_rr1_038", "Player_dyn2_rr1_040",
"Player_dyn2_rr1_042", "Player_dyn2_rr1_044"]
my_piano_list_dyn3 = ["Player_dyn3_rr1_000", "Player_dyn3_rr1_002", "Player_dyn3_rr1_004",
"Player_dyn3_rr1_006", "Player_dyn3_rr1_008", "Player_dyn3_rr1_010",
"Player_dyn3_rr1_012", "Player_dyn3_rr1_014", "Player_dyn3_rr1_016",
"Player_dyn3_rr1_018", "Player_dyn3_rr1_020", "Player_dyn3_rr1_022",
"Player_dyn3_rr1_024", "Player_dyn3_rr1_026", "Player_dyn3_rr1_028",
"Player_dyn3_rr1_030", "Player_dyn3_rr1_032", "Player_dyn3_rr1_034",
"Player_dyn3_rr1_036", "Player_dyn3_rr1_038", "Player_dyn3_rr1_040",
"Player_dyn3_rr1_042", "Player_dyn3_rr1_044"]
my_midi_num = note(my_note)
if my_midi_num < 21
assert false, "Note too low for my_piano_sample"
end
if my_midi_num > 108
assert false, "Note too high for my_piano_sample"
end
if my_dyn < 1
assert false, "Dynamic too low for my_piano_sample"
end
if my_dyn > 3
assert false, "Dynamic too high for my_piano_sample"
end
case my_dyn
when 1
my_piano_list = my_piano_list_dyn1
when 2
my_piano_list = my_piano_list_dyn2
when 3
my_piano_list = my_piano_list_dyn3
end
case my_midi_num
when 21
sample my_piano_dir, my_piano_list[0]
when 22
sample my_piano_dir, my_piano_list[0], rpitch: 1
when 23..106
my_listnum = (my_midi_num - 19) / 4
my_pitch = ((my_midi_num - 23) % 4) - 2
if my_pitch == 0
sample my_piano_dir, my_piano_list[my_listnum]
else
sample my_piano_dir, my_piano_list[my_listnum], rpitch: my_pitch
end
when 107
sample my_piano_dir, my_piano_list[22], rpitch: -1
when 108
sample my_piano_dir, my_piano_list[22]
end
end
# Play a note with a given dynamic. With this you can control the whole effect hull curve.
# Parameters:
# my_note = note value to play
# my_dyn = dynamic to play (1 = quiet, 2 = louder, 3 = loud)
#
# Please note, the sfz-file recommends a release of 0.6
#
# Examplecall:
# Play note C at the 4th octave with 1 second sustain and loud dynamic
# with_sample_defaults amp: 1.0, sustain: 1.0, release: 0.6 do
# my_piano_raw :C4, 3
# end
define :my_piano_raw do |my_note, my_dyn|
my_piano_sample my_note, my_dyn
end
# Play a chord with a given dynamic. With this you can control the whole effect hull curve.
# Parameters:
# my_chord = chord to play
# my_dyn = dynamic to play (1 = quiet, 2 = louder, 3 = loud)
#
# Please note, the sfz-file recommends a release of 0.6
#
# Examplecall:
# Play a C-major chord of the 4th octave with 1 second sustain and loud dynamic
# with_sample_defaults amp: 1.0, sustain: 1.0, release: 0.6 do
# my_piano_raw_chord chord(:C4, :major), 3
# end
define :my_piano_raw_chord do |my_chord, my_dyn|
my_chord.each do |i|
my_piano_sample i, my_dyn
end
end
# Play a note with a given note length value
# Parameters:
# my_note = note value to play
# my_note_length = note length to play
# my_artic = articulation to use ("non" = non-legato, "stac" = staccato, "leg" = legato)
# my_dyn = dynamic to play ("ppp", "pp", "p", "mp", "mf", "f", "ff", "fff")
#
# Examplecall:
# Play a full note C at the 4th octave in non-legato with mezzo forte loudness
# my_piano :C4, 1.0, "non", "mf"
define :my_piano_play do |my_note, my_note_length, my_artic, my_dyn|
my_sleep_length = my_note_length * my_piano_full_note_length * (current_bpm / 60)
my_sample_dyn = 0
case my_artic
when "non"
my_play_length = my_note_length * my_piano_full_note_length * my_piano_nonleg_length
my_release_length = 0.6
when "stac"
my_play_length = my_note_length * my_piano_full_note_length * my_piano_staccato_length
my_release_length = 0.6 * my_piano_staccato_length
when "leg"
my_play_length = my_note_length * my_piano_full_note_length * my_piano_legato_length
my_release_length = 0.6 * my_piano_legato_length
end
case my_dyn
when "ppp"
my_sample_dyn = 1
when "pp"
my_sample_dyn = 1
when "p"
my_sample_dyn = 1
when "mp"
my_sample_dyn = 1
when "mf"
my_sample_dyn = 2
when "f"
my_sample_dyn = 2
when "ff"
my_sample_dyn = 2
when "fff"
my_sample_dyn = 3
end
if my_sample_dyn == 0
assert false, "Dynamic unknown for my_piano_play"
end
if my_note == "pause"
sleep my_sleep_length
else
with_merged_sample_defaults sustain: my_play_length, release: my_release_length do
my_piano_sample my_note, my_sample_dyn
sleep my_sleep_length
end
end
end
# Play a chord with a given note length value
# Parameters:
# my_chord = chord to play
# my_note_length = note length to play
# my_artic = articulation to use ("non" = non-legato, "stac" = staccato, "leg" = legato)
# my_dyn = dynamic to play ("ppp", "pp", "p", "mp", "mf", "f", "ff", "fff")
#
# Examplecall:
# Play a full note length C-major chord of the 4th octave in non-legato with mezzo forte loudness
# my_piano_chord chord(:C4, :major), 1.0, "non", "mf"
define :my_piano_play_chord do |my_chord, my_note_length, my_artic, my_dyn|
my_sleep_length = my_note_length * my_piano_full_note_length * (current_bpm / 60)
my_sample_dyn = 0
case my_artic
when "non"
my_play_length = my_note_length * my_piano_full_note_length * my_piano_nonleg_length
my_release_length = 0.6
when "stac"
my_play_length = my_note_length * my_piano_full_note_length * my_piano_staccato_length
my_release_length = 0.6 * my_piano_staccato_length
when "leg"
my_play_length = my_note_length * my_piano_full_note_length * my_piano_legato_length
my_release_length = 0.6 * my_piano_legato_length
end
case my_dyn
when "ppp"
my_sample_dyn = 1
when "pp"
my_sample_dyn = 1
when "p"
my_sample_dyn = 1
when "mp"
my_sample_dyn = 1
when "mf"
my_sample_dyn = 2
when "f"
my_sample_dyn = 2
when "ff"
my_sample_dyn = 2
when "fff"
my_sample_dyn = 3
end
if my_sample_dyn == 0
assert false, "Dynamic unknown for my_piano_play_chord"
end
with_merged_sample_defaults sustain: my_play_length, release: my_release_length do
my_chord.each do |i|
my_piano_sample i, my_sample_dyn
end
sleep my_sleep_length
end
end
# Hints for note and chord notation:
# Notenames 4th octave: :C4, :Cs4, :D4, :Ds4, :E4, :F4, :Fs4, :G4, :Gs4, :A4, :Bb4, :B4
# Chordnames can be printed out with the following command:
#puts chord_names
#
# You can also use [:C4, :E4, :G4] as chord notation (here it is C-major chord of 4th octave)
#
# Examplesong
#
# "Für Elise" from Ludwig van Beethoven, first 9 tacts
my_artic = "leg"
my_dyn = "pp"
# Right hand
in_thread do
my_piano_play :E5, 1.0/16, my_artic, my_dyn
my_piano_play :Ds5, 1.0/16, my_artic, my_dyn
my_piano_play :E5, 1.0/16, my_artic, my_dyn
my_piano_play :Ds5, 1.0/16, my_artic, my_dyn
my_piano_play :E5, 1.0/16, my_artic, my_dyn
my_piano_play :B4, 1.0/16, my_artic, my_dyn
my_piano_play :D5, 1.0/16, my_artic, my_dyn
my_piano_play :C5, 1.0/16, my_artic, my_dyn
my_piano_play :A4, 1.0/8, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play :C4, 1.0/16, my_artic, my_dyn
my_piano_play :E4, 1.0/16, my_artic, my_dyn
my_piano_play :A4, 1.0/16, my_artic, my_dyn
my_piano_play :B4, 1.0/8, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play :E4, 1.0/16, my_artic, my_dyn
my_piano_play :Gs4, 1.0/16, my_artic, my_dyn
my_piano_play :B4, 1.0/16, my_artic, my_dyn
my_piano_play :C5, 1.0/8, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play :E4, 1.0/16, my_artic, my_dyn
my_piano_play :E5, 1.0/16, my_artic, my_dyn
my_piano_play :Ds5, 1.0/16, my_artic, my_dyn
my_piano_play :E5, 1.0/16, my_artic, my_dyn
my_piano_play :Ds5, 1.0/16, my_artic, my_dyn
my_piano_play :E5, 1.0/16, my_artic, my_dyn
my_piano_play :B4, 1.0/16, my_artic, my_dyn
my_piano_play :D5, 1.0/16, my_artic, my_dyn
my_piano_play :C5, 1.0/16, my_artic, my_dyn
my_piano_play :A4, 1.0/8, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play :C4, 1.0/16, my_artic, my_dyn
my_piano_play :E4, 1.0/16, my_artic, my_dyn
my_piano_play :A4, 1.0/16, my_artic, my_dyn
my_piano_play :B4, 1.0/8, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play :D4, 1.0/16, my_artic, my_dyn
my_piano_play :C5, 1.0/16, my_artic, my_dyn
my_piano_play :B4, 1.0/16, my_artic, my_dyn
my_piano_play :A4, 1.0/8, my_artic, my_dyn
my_piano_play "pause", 1.0/8, my_artic, my_dyn
end
# Left hand
in_thread do
my_piano_play "pause", 1.0/8, my_artic, my_dyn
my_piano_play "pause", 3.0/8, my_artic, my_dyn
my_piano_play :A2, 1.0/16, my_artic, my_dyn
my_piano_play :E3, 1.0/16, my_artic, my_dyn
my_piano_play :A3, 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/8, my_artic, my_dyn
my_piano_play :E2, 1.0/16, my_artic, my_dyn
my_piano_play :E3, 1.0/16, my_artic, my_dyn
my_piano_play :Gs3, 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/8, my_artic, my_dyn
my_piano_play :A2, 1.0/16, my_artic, my_dyn
my_piano_play :E3, 1.0/16, my_artic, my_dyn
my_piano_play :A3, 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/8, my_artic, my_dyn
my_piano_play "pause", 3.0/8, my_artic, my_dyn
my_piano_play :A2, 1.0/16, my_artic, my_dyn
my_piano_play :E3, 1.0/16, my_artic, my_dyn
my_piano_play :A3, 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/8, my_artic, my_dyn
my_piano_play :E2, 1.0/16, my_artic, my_dyn
my_piano_play :E3, 1.0/16, my_artic, my_dyn
my_piano_play :Gs3, 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/8, my_artic, my_dyn
my_piano_play :A2, 1.0/16, my_artic, my_dyn
my_piano_play :E3, 1.0/16, my_artic, my_dyn
my_piano_play :A3, 1.0/16, my_artic, my_dyn
my_piano_play "pause", 1.0/16, my_artic, my_dyn
end