My year teaching Sonic Pi - Week 18

This week I wanted to continue working with the concept of concurrency and aligning rhythms with each block of code, but instead of working with samples, we were going to use synths to incorporate some more melodic elements. The main concept I wanted to stress during this lesson was that we are working with a definitive amount of time. There is a beginning and an end to this section of music we are going to make. Since all the blocks are playing together at the same time, we want each in_thread block we make to last for the same amount of time. I realized this could be a somewhat abstract concept when working with just sound, so I wanted to incorporate a simple visual accompaniment to try and reinforce this concept. I had done something similar in the last lesson making drum beats and I felt like that really helped. So I make a simple rectangle on the board and told the students, this is going to represent the section of music I want to make. It is going to last for a certain amount of time.

I am going to measure the amount of time in beats. This section is going to last for a certain amount of beats. Ultimately you can choose how long it is. It could be 4 beats or 8, 9, 12, 16 , 25 etc. But the point is that every different sound you have playing along needs to last for that amount of beats. For this example, I am going to have my section last for 8 beats. I am going to start simple by just using a bass drum to mark those 8 beats. I wrote a simple block of code to show 8 beats of a bass drum and made a variable for my sleep value as we had done in the last lesson:

t = 1

8.times do
sample :bd_haus
sleep t
end 

I then played it for them and counted each bass drum to drive home the point that there was 8 beats. I then went back to the drawing of the rectangle and drew a line to mark a section that represented the bass drum sound. I then divided that section into 8 equal parts and said each part represents one bass drum sound, so in total there are 8 bass drums. I played the code again while displaying the visual example and each bass drum hit, I pointed to the next part of the section.


Next I want to add another sound. I am going to add a bassline. So I first drew another section alongside the bass drum to indicate this was a separate track but they are running next to each other to show that they will be playing at the same time. I said I was going to start simple by having the same number of bass notes as bass drum notes which was 8, so I divided the new section into 8 parts. I then added some code to go with this. I kept the bass drum at the bottom and added the new code above starting with an in_thread block. One reason I did this was that I felt it might be confusing starting with an in_thread block with only one sound playing. I’ve been trying to avoid including code that isn’t relevant because the kids will sometimes copy everything I do and that leads to problems down the line. I have seen them include code they don’t need but because they saw me do it at some point, they put it in without fully understanding why. I added this block of code:

in_thread do
  8.times do
    use_synth :chipbass
    play :e2
    sleep t
  end
end


I played that with the code I already had so they could hear both parts play together and more importantly finish at the same time. I played it again while pointing to the visual diagram to reinforce that. I took this opportunity to include a new function, octs. I really like this command as a way to make simple bass lines that just add some basic harmonic support to a melody. Octs takes two arguments: the starting note and how many octaves you want. It will just play your starting note and then go up one octave at a time for however many octaves you have specified. I started simple by just going back and forth between two octaves:

in_thread do
  8.times do
    use_synth :chipbass
    play (octs, :e2, 2).tick
    sleep t
  end
end

After playing that, I changed the number of octaves to 3. When I played it I pointed out that we after the second time through we only hear the first two octaves and not the third. I asked why this happened and a few students were able to remember that we only had 8 beats in our section. I then changed it to 4 octaves to hear an even subdivision. I also showed them that we can use .choose instead of .tick to make it more randomized.

I changed it back to just 2 octaves. I told the class I now wanted there to be 2 bass notes for each bass drum hit. I went back to the drawing and drew a line through each of the 8 parts representing the bass notes thereby cutting them all in half. They could now still see the 8 parts representing the bass drum, but now next to each bass drum part were two bass note parts.

So now I need to change my code. First off, how many bass notes are there. The class answered “16”. This means the bass is going to happen 16 times, so I need to change the number in my repetition block. Is that all I need to do? I got a few blank stares, so I played the new code. They could easily hear that the bass went on for much longer then the bass drum and I reminded them that our objective is to have all our parts end at the same time. The concept from last class started to come back to some students and they pointed out that I had to change my sleep value to t/2.0. This is the resulting code:

t = 1

in_thread do
  16.times do
    use_synth :chipbass
    play (octs, :e2, 2).tick
    sleep t/2.0
  end
end

8.times do
  sample :bd_haus
  sleep t
end

When I played this, is was clear that they could hear what was happening in each part. I also used the visual diagram to drive that point home. This led me to review that basic math that we had gone over last time to figure out the way to find how many repetitions you need based on your sleep value and the number of beats in your section. While I did not present this formula to the class because I don’t want to confuse them with more math then they absolutely need, this is what I have come up with to explain this concept:

Number of .times (T) = beats in the section(B) * number of notes played in one beat(N)

In this case, I wanted 2 notes per beat played for 8 beats which is how I got 16.times.

Instead of doing some more examples of this concept in the same block of code, I wanted to move on to another block of code which would represent a melody. This would be more suitable for other types of rhythms. So I first went back to the diagram and added a third section to indicate that we would be adding another sound to play along with the bass drum and bass line. And added 8 parts as a reminder that there are 8 total beats in the section. As I typed out the code, when I got to repetition block, I did not include how many times I was going to repeat yet. I said we would figure that out in a minute.

I chose to use a scale to make a random melody. I explained that since I had chosen the note ‘E’ for my bass line, I was going to use “E’ as the starting note for my scale to make the fit together well. I also introduced them to the num_octaves: argument for scales which we hadn’t learned yet. I explained that this would allow us to have more notes to choose from in our scale. It basically means we are going to have the same group of notes some played low and some played high. If we start on :e3, it will play the scale starting on this note but also will include the notes starting on :e4. I advised that they should keep the number for this arguments in the single digits since having too many octaves will lead to notes that are too high to hear, especially if your starting note is already high (:e6).

When I got to the sleep command, I told the class that I wanted to have 4 notes play each beat and reminded them that we had 8 beats total in our section. So using our formula to find the number of times we need to repeat, we would multiply 4 (number of notes played in one beat) by 8 (beats in the section) and that would give us 32 times. So I added that number to the repetition block which gave us this:

in_thread do
  32.times do
    use_synth :saw
    play scale(:e3, :minor_pentatonic, num_octaves: 2).choose
    sleep t/4.0
  end
end

I ran it with the other blocks to point out that all the sounds are playing a different amount of notes but they all end at the same time. When I went back to the diagram, I was going to have trouble dividing one block into 4 parts without looking cramped and I wanted to do another example, so I just wrote in the number 4. In retrospect, I liked the way this looked and think it made more sense from the math point of view by providing an actual number.

To reinforce the concept, I asked the class to pick a different number to use for our sleep command. I said to keep it between 3 and 9 just to keep things easier to multiply. Someone said ‘5’. So I said “this means we have 5 notes per beat and I have 8 beats in my section. How many times do I need to put in the repetition block? Remember we multiply number of beats (pointing to sleep command) and number of blocks total (8).” A few students yelled out “40”. I made the sleep value t/5.0 and the repetition block as 40.times and ran the code. I was kind of glad a student chose an uneven number because it made the code sound a little off in comparison to even beats but it still ended at the same time. I asked for another number and someone said “7”. So we did the same process: 7 notes per beats times 8 beats total equals………56. I changed the sleep value to t/7.0 and the repetition block to 56 and ran the code again. I could tell some of the kids were intrigued by the seemingly chaotic sound of 7 against 2 (from the bass line) which was encouraging to see.

Throughout all of this, I made sure to stress that the important number to be aware of is the number of beats in the section. We can change the sleep value or repetition block but what needs to be consistent is that number of beats. You can make a decision before you start coding anything as to how many beats you want to have in your section or your can play around with something that sounds good and then figure it out after by dividing the number in the repetition block by the number in the sleep value. But once you have this number, you need to make sure all the different in_thread blocks have this amount of beats.

The last thing I wanted to show the students was how they could do different sleep values to create more complex rhythms. I pointed out that all the rhythms we have done have been using the same amount of time so there is no change or variation from the length of one note to the next. There is a way we can do this but it involves a little more math. What we have to do is to make a ring with different sleep values in it. Keep in mind that when we write the sleep values as for example t/4.0, we are performing the mathematical operation of division, as we are dividing the value of t by 4.0. Since we are having t equal to 1, t/4.0 can also represent the fraction one fourth which in this case means one fourth of a beat. To have multiple different rhythms, we need to make sure the different fractions add up to 1. So we can use, for example, t/4.0, t/8.0 and t/2.0 all in the same block but we just need to make sure that they all add up to 1.

To show that this could work with any amount, I gave the students options to choose instead of me just giving a example. I gave them the following fractions to choose from:1/2, 1/4, 1/8 and 1/16. We were going to choose a combination of all these different fractions but needed to keep track of what the total amount was. I realized this involved some pretty straight ahead math of adding fractions together which is something as 7th graders they have to learn the previous year. However, since this isn’t music class, it was clear that most of their brains weren’t really in that frame of mind. Luckily I had a few who are pretty sharp at math that were able to lead the way.

First, we had to remember what the lowest common denominator was, in this case, 16. So I asked a student to choose one of the values. She chose 1/4. I then asked how many 16th that would be. 4/16. So I wrote first 1/4 and below it I wrote 4/16. The next student chose 1/8. This gave use 2/16. I continued to write in the pattern of the fraction above and the value in 16 below. I reminded them that now we have 6/16. The next student chose 1/2. This is 8/16. Now we have 14/16, so we can’t choose another 1/2 or 1/4 because it will add up to more than 1. I decided to finish it by choosing two 1/16 which gave use a total of 16/16 or 1. Our pattern of sleep values was now 1/4, 1/8, 1/2, 1/16, 1/16. I put that into a ring after the sleep command in the code.

I left the .times blank at first before explaining how we find it. What this code is saying is that since all our sleep values add up to one, the amount of sleep values we have is the number of notes that will play per one beat. So we just count the number of values we have in our ring. In this example, we have 5 values in our ring. We then multiply that by the total number of beats in our section which is 8. So 5 times 8 equals 40. 40 is the number we put in the repetition block. The final code looked like this:

t = 1

in_thread do
  16.times do
    use_synth :chipbass
    play (octs, :e2, 2).tick
    sleep t/2.0
  end
end

in_thread do
 40.times do
    use_synth :saw
    play scale(:e3, :minor_pentatonic, num_octaves: 2).choose
    sleep (ring, t/4.0, t/8.0, t/2.0, t/16.0, t/16.0).tick
  end
end

8.times do
  sample :bd_haus
  sleep t
end

After showing them this, I knew I had tried to push maybe a little further than I should have, so I turned them loose to experiment. I provided a reference sheet that also explained what we had gone over. I realized that this might have been a little confusing to the students and as I try writing about it, it seems even more confusing. I think in the future I may try to have some type of sheet that has a few examples on it to check if the students can look at some code and determine how many beats are in a section or how many times they should repeat something, just to get a sense of whether or not they actually understand what I am trying to teach them. I have spoken against giving them worksheets or paper work in other posts because my main objective is just to have them creating music. But as I get into more complex concepts, I want to see that they are at least trying to do it. I feel like if they don’t understand something, a lot of the times they just will not even bother attempting it. If I have them do a few examples, they can get more comfortable with it and then feel more confident putting it in their own code. Another thought would be to give them some incomplete code to write down and have them figure out how to finish it and then listen to determine whether or not it works. I think I like this more because they are still working within the coding environment, but they are not just trying out the concept by building something out of nothing.

4 Likes