Now that you know about loops we can start putting songs together! Imagine having a bassline and a drumbeat playing at the same time. You could weave them together but that quickly becomes confusing. This is where threads come in handy. You can think of threads like branches on a tree. The buffer is the main branch and the main thread. Then, each thread branches off of that. This allows each thread to run simultaneously to each other. If we didn’t use threads, our code would enter a loop and then never exit. Look at the code below for a simple example of threads.
in_thread do loop do sample :drum_heavy_kick sleep 1 end end in_thread do loop do use_synth :fm play 40, release: 0.2 sleep 0.5 end end
As you can hear in the above example, both loops are playing at the same time. This is because the in_thread keyword creates a new thread every time it is called and they are both set to start at the same time. Without the in_thread keyword, the second loop would never be reached! It is best practice to use in_thread for every thread you want to create even though you don’t have to for the last loop in your sequence.
It is important to note that threads isolate settings. This is known as scope and it simply means that settings are only applied to the thread they are set in. Take a look at this example to see how this works:
play 50 sleep 1 in_thread do use_synth :tb303 play 50 end sleep 1 play 50
As you can hear in this example, the use_synth keyword changes the note that is inside of that thread! This can be combined to create different melodies in one song. You can have a bassline that uses one synth and another melody that uses a completely different synth.
There is another concept in scope called inheritance and it means that a thread will inherit any settings from it’s parent thread unless otherwise set. Basically, the main thread can pass settings to a child thread but a child thread cannot pass settings to its parent. Take a look at the example below:
use_synth :tb303 play 50 sleep 1 in_thread do play 55 end
As you can see, the use_synth setting is passed down from the main thread into the child thread. Keep this in mind when writing your music.
The last thing to know about threads is that you can name them. This may not seem important now but it will definitely come in handy later. I like to give my threads descriptive names so that I can remember exactly what each thread does. Below is an example of how to name threads:
in_thread(name: :bass) do loop do use_synth :prophet play :E2 sleep 0.5 play :D2 sleep 0.5 end end in_thread(name: :drums) do loop do sample :elec_snare sleep 1 end end
🌟 The name of the thread has to be enclosed with parentheses and must have a colon at the beginning of the name.
This will allow you to easily keep track of your threads and even see when they are playing if you look in the log pane! The final thing to note about naming threads is that each thread has to have a unique name. If any of the threads have the same name then every thread after the first one will not be created.