Hey Ava,
Someone else may chip in as well, but here’s my thoughts:
Re live bpm variation, the following thread may be of interest:
I see what you mean with the bar numbers being printed out in the video as bar 1, 13, 2, 14, 3… etc.
Something to note about this is that you are mostly using un-named threads to do things simultaneously. This means every time ‘Run’ is pressed, a new thread is created and run with that code, even if an instance of that thread from the previous run is still executing. In the case of the logs, this causes multiple separate counters to count up at the same time.
The first change you could make to avoid this is to give un-named threads names, if you do not want them to potentially overlap between runs. (Then, whenever Run is pressed, a new thread is only created if the previous instance with the same name has finished executing. See the threads documentation for further details). Hope that makes sense!
I’ll paste some code below which should give an example of how you could address what you want, including bpm variation, correct thread/log behaviour, and bar counting. I’ve tried to only change the code enough to get it to do what you might want it to do.
Happy to clarify anything that might still be unclear about it if needed ![]()
# recode ver
# minecraft type of game music idk
# 4/4
# c major but an fs added idk what mode that is
# being able to divide music simply by function and how i want to is such an advantage when coding
# to do (no order):
# () bpm ramp over time
# (x) code a play_pattern_timed_amp function
# () send the midi output to labs
# (x) humanise amp and timing with rrand
# (x) set a humanisation parameter to be used
# () automatic calculation of how many bars the piece is
# () and of course write the whole thing
use_random_seed 896767 # for humanisation
h = 1.5 # how strong the humanisation in the sleeps is, 0<h
# Use link as the bpm source, as this allows it to be easily globally modified
use_bpm :link
set_link_bpm! 82
# humanised_play_pattern_timed_amp legit freestyle
define :hppta do |notes, times, amps, sleepdev, ampdev|
comment do # !!!!!!!!!! uncomment if "nil cannot be coerced into integer" type error
puts "Control: Notes amount: #{notes.length}"
puts "Control: Times amount: #{times.length}"
puts "Control: Amps amount: #{amps.length}"
end
notes.zip(times, amps).each do |note, time, amp|
play note, amp: rrand(amp-ampdev, amp+ampdev)
sleep rrand(time-sleepdev, time+sleepdev)
end
end
# piano
da = 1 # default amp
dsd = h*0.01 # default sleep deviation
dad = 0.15 # default amp deviation
s = h*0.01 # "simulatenous" notes sleep
# Extract the melody patterns out of the hppta method so they can be examined once in the beginning
# to calculate the total number of bars
patterns = [
[[:g2, :b3, :c3, :e3, :b4, :a4, :g4], [s, 0.5-s, 0.5, 0.5, 1.5, 0.5, 0.5], [da,da,da,da,da,da-0.2,da-0.3], dsd, dad],
[[:fs4, :g2, :b2, :d3, :fs3], [s, 0.5-s, 0.5, 0.5, 1.5], [da, da, da, da, da], dsd, dad],
[[:c4, :a3, :a2, :c3, :e3, :fs3], [1, s, 0.5-s, 0.5, 0.5, 1.5], [da, da, da, da, da, da], dsd, dad],
[[:a3, :b3, :g2, :a3, :b2, :d3, :a3], [0.5, 0.5, s, 0.5-s, 0.5, 0.5, 2.5], [da, da, da, da, da, da, da], dsd, dad],
[[:g2, :b3, :c3, :e3, :b4, :a4, :c5], [s, 0.5-s, 0.5, 0.5, 1.5, 0.5, 0.5], [da,da,da,da,da,da-0.2,da-0.3], dsd, dad],
[[:g3, :fs3, :b4, :b2, :d3, :fs4, :c4], [s, s, 0.5-s-s, 0.5, 0.5, 1.5, 1], [da, da, da, da, da, da], dsd, dad],
[[:a3, :a2, :c3, :e3, :fs3], [s, 0.5-s, 0.5, 0.5, 1.5], [da, da, da, da, da], dsd, dad],
[[:a3, :b3, :g2, :g3, :b2, :d3, :g3, :c4, :fs4, :b4, :d5], [0.5, 0.5, s, 0.5-s, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [da, da, da, da, da, da, da, da, da, da, da], dsd, dad]
]
# Apply the 'reduce' method,
# (which calculates a single value of some kind from a _collection_ of things),
# to each item in the patterns array,
# by keeping count of a total sum (starting at 0) of all the note lengths in the composition,
# and adding the sum of each pattern's times (reduce(:+)) to the total sum
# As mentioned below this assumes that the total sum of note durations in the composition is evenly divisible by 4
total_duration = patterns.reduce(0) {|sum, pattern| sum + pattern[1].reduce(:+) }
total_bars = total_duration / 4
# bar counter, works as long as this stays in 4/4
# named threads do not create new thread instances that overlap when running
in_thread(name: :counter) do
total_bars.times do |i|
puts "Bar #{i + 1}"
# change the global bpm via link at a certain point (in this case, when the 5th bar starts)
set_link_bpm! 120 if i == 4
sleep 4
end
end
use_synth :piano
use_synth_defaults amp: da
with_fx :lpf, cutoff: 70 do
with_fx :hpf, cutoff: 30 do
with_fx :reverb, mix: 0.6 do
in_thread(name: :piano) do
patterns.each do |(notes, times, amps, sleepdev, ampdev)|
hppta(notes, times, amps, sleepdev, ampdev)
end
end
end
end
end
#bass kinda strings something
use_synth :hollow
use_synth_defaults amp: 1.25, attack: 0.5, sustain: 3.5, release: 1
with_fx :lpf do
in_thread(name: :hollow) do
sleep 15.75
play_pattern_timed [[:c3, :g3], [:g2, :d3], [:a2, :e3], [:d2, :b2]], [4]
end
end
use_synth :dark_ambience
use_synth_defaults amp: 1.5, attack: 0.5, sustain: 3.5, release: 1
with_fx :hpf do
in_thread(name: :dark_ambience) do
sleep 15.75
play_pattern_timed [[:c3, :g3], [:g2, :d3], [:a2, :e3], [:d2, :b2]], [4]
end
end