My year teaching Sonic PI - Week 19

After a few classes working on using in_thread for concurrency and how to make rhythms align correctly, I felt that I needed to assign a graded project to see how well the students were getting this concept. So far, the projects we have been doing usually have a form component to them but for this one, I wanted to get away from that. However, I wanted them to do more than just have a bunch of in_thread blocks. There needed to be some aspect of a piece with more than one part. So I decided to have students make sections of in_thread blocks but without worrying about any form or order to the sections as we had done with the Rondo.

When hashing out the requirements and rubric for this project, I knew that having the rhythms of each block align with each other was definitely the main thing I wanted to focus on. But I wanted to include some other requirements to push the students to write more code. So I decided to set a strand in the rubric for the amount of blocks in each section (At least 3 or more) and one for the number of sections (2 or more). Since we had spent time looking at using both samples and synth sounds, I also added a strand which was for using multiple types of sounds in each section. In addition to the rubric, I made a checklist so that the expectations for the project would also be clear. In hindsight, there are definitely some things I would change about the rubric. But I’ll address that at a later time.

Rubric & Checklist: https://docs.google.com/document/d/19naYbFw2i-_KXowEp0DlKp-0_7kCEDfrrWJhNXxFZ_8/edit?usp=sharing

When I presented the project to the students, I decided to hand out the rubric and checklist first so that they could easily see each category and connect it to the example of code I would provide. There are varying points of view about distributing assignment sheets when presenting the assignment. I have heard people say that having the paper can be more of a distraction and the students will not be as likely to listen to you as you roll out the project. I have leaned more towards this philosophy for most of the projects, but since there were 4 categories on this rubric and I was worried some of the language might be unclear, I made sure they had it in hand as I explained what to do.

As I explained what the project would be, I made sure to reference each part of the rubric as it came up. One of the main things I was concerned about while explaining this was the language used to refer to the different requirements of the project. I started with the number of blocks in a section. I wrote out an in_thread block and some code inside it. I stressed that this is one block of code in my section. One of the main focuses of this project is having multiple blocks of code playing together. This will demonstrate that you are able to use the in_thread block correctly. Because of this, you should have at least two in_thread blocks to have multiple parts playing at once. To get a 4 on the rubric, you need at least four different blocks of code playing at the same time.

The other main part of this project is having all the rhythms of each block align with each other so that every block starts and finishes at the same time. The key to doing this correctly is to be aware of the number of beats in your section. Each block you have in the section should last for this amount of beats. I recommended that students try to decide what they want that number to be prior to writing any code as this would make the math easier to work out. However, I didn’t say they needed to do it this way. I know it can be hard for the students to envision what they want to do before they do it. Often they just experiment until they find something they like. But my plan was to model the method of deciding before starting. I said I was going to have 8 beats for each block in this section. The next thing I should decide is how many times I want the sound to play per beat. In this case, I had a bass drum sound and I want it to play twice every beat, so I would indicate that in the sleep value as t/2 having declared t at the beginning as my sleep value which equals 1. To figure out how many times I need to have this sound play, I multiply the number I divided the sleep value by (2) by the total number of beats in the section (8) which would give me 16.times. The first block looked like this:

t = 1

in_thread do
  16.times do
    sample :bd_haus
    sleep t/2.0
  end
end

To drive the point home about the math, I did a few more example where I changed the sleep values and asked the students to figure out how many times I should repeat. I did t/4.0 (repeat 32 times) t/5 (repeat 40 times) etc. I knew that this would probably be the area where a lot of students would have difficulty since it was somewhat of an abstract concept.

From here, my next example was more simple. I showed that the easiest way to establish the number of beats in the section was to have a block with a sleep value of 1 (or in our case, t). This way the number of times that sound is repeated will be the number of beats in the section. While I didn’t want to overwhelm them with a lot of extra stuff, I did include a example of using an array of rate values to change the pitch of the sample I was using to make it more interesting:

in_thread do
  8.times do
    sample :ambi_piano, rate: [1, 1.25, 1.5, 1.75, 2].choose
    sleep t
  end
end

I made reference to the strand on the rubric about aligning rhythms. I played what I had so far and pointed out how they both end at the same time. I made it clear that this is what we were looking for. If you play your code and one block goes on after the other block has stopped, there is something off with the math and you should look into why that is happening. In order to achieve a 4 on the rubric, at least one of the blocks needed to include multiple sleep values. We had gone over this in the previous class, but I did a quick review for students who wanted to attempt it. In order to do this, we need to make a ring of different sleep values. Since these values are fractions, the total sum of these fractions must equal 1. I suggested keeping these values relatively simple to make the math easier. I did the following ring: t/4, t/2, t/8, t/8. I did a quick add up of the fractions to show they equaled 1 or in this case 8/8. Since they equal 1, I can count the number of values in the ring and that will be the number of sounds played per beat. In this example I had 4 values in the ring. I then multiply that number by the total number of beats in the section (8) to get the number for my repetition block. I played it with the other two blocks I had so far to confirm that all the blocks still lasted for the same amount of time. The block looked like this:

in_thread do
  use_synth :beep
  32.times do
    play scale(:e3, :chinese, num_octaves: 3).choose, amp: 0.3
    sleep (ring, t/4.0, t/2.0, t/8.0, t/8.0).tick
  end
end

The final strand of the rubric was to encourage students to use both samples and synth sounds. We had covered both, so I wanted them to try to incorporate both into this project. I think if left to their own devices a lot of them would simply choose samples. But we had spent a lot of time playing with rings and scales and I wanted them to continue using that. I explained that in order to get a 4 for this part of the rubric, each section needed multiple samples and synths. At this point in my example, I had two samples and one synth, so i added an additional synth. I kept the math simple on this one as well. I also used the octs command as a review of when we had discussed last week as a method to provide some simple harmonic support to a melody. That block of code was as follows:

8.times do
  use_synth :subpulse
  play (octs, :e1, 2).tick
  sleep t
end

The entire first section looked liked this:

t = 1

in_thread do
  16.times do
    sample :bd_haus
    sleep t/2.0
  end
end

in_thread do
  8.times do
    sample :ambi_piano, rate: [1, 1.25, 1.5, 1.75, 2].choose
    sleep t
  end
end

in_thread do
  use_synth :beep
  32.times do
    play scale(:e3, :chinese, num_octaves: 3).choose, amp: 0.3
    sleep (ring, t/4.0, t/2.0, t/8.0, t/8.0).tick
  end
end

8.times do
  use_synth :subpulse
  play (octs, :e1, 2).tick
  sleep t
end

# end of first thread section

I used this opportunity to point out that I did not include an in_thread block around this piece of code because it was going to be the last block in this section. Anything I write after this will play separately after all the preceding blocks of code. From here I can add a new section of code to play after it. I referred to the part of the rubric which addressed sections. I stated that what I have so far is one section. To try and make that more clear, I made a comment under the last block which said = #end of first thread section. I quickly reminded students what a comment was and how it could be used in this case. I had another section of code prepared in another buffer that I went to. I copied and pasted it and put it after the comment I had just made. I explained that this would be another section. I took a quick moment to explain how it would fit into the rubric. I said this section lasts for 9 beats and pointed out the different blocks and the math that went with it. I had 4 in_thread blocks in this section with two synth sounds and two samples.

in_thread do
  9.times do
    sample (ring, :elec_bong, :elec_flip, :elec_ping).tick
    sleep t
  end
end


in_thread do
  18.times do
    sample :drum_cymbal_closed, amp: 0.5
    sleep t/2.0
  end
end

in_thread do
  use_synth :hollow
  54.times do
    play [50, 53, 56, 59, 62, 65].choose
    sleep t/6.0
  end
end

27.times do
  use_synth :dtri
  play (ring, 38, 41, 38).tick, release: 0.3, amp: 3
  sleep (ring, t/2.0, t/4.0, t/4.0).look
end

I played the code and pointed out when the first section stopped and the second began. I also had made an effort to make each section have a distinct sound to be clear when it changed. I made it clear that at this point I only had two sections. If I want to get 4 on that part of the rubric, I would need to make a third section.

At this point, I was done explaining the project and wanted to get them started. There were a few questions, some of which were very insightful. One student wanted to confirm whether or not the last block of code in my first section would thread with the other blocks since there was no in_thread block around it. Another student asked if they could use functions for each section. I thought this was a great question and was glad to see they were making connections of how to use previous concepts in a new project. I said of course they could, but it was not necessary. I had considered making this part of the project since we were going to be working with sections again. But I felt like that would just add an additional layer of difficulty to the project and since it wasn’t really the main focus of the project, I decided to leave it out entirely to avoid giving them too much on their plate.

As the students worked, I noticed a few issues that I hadn’t really anticipated. The first was that they were making their variable for the sleep value something other than 1. Now ultimately, this wouldn’t make any difference but I wanted them to keep it relatively simple for this project. I also encouraged them to keep the math simple. Don’t do something like 17.times and sleep for t/3.6. I made sure to stress that there isn’t anything wrong with doing that, but for this project which was going to be graded, it was just going to make things more complicated for them in the long run. I definitely feel torn having to stifle some of their creative instincts for the purpose of fulfilling the project requirements, but since we are operating under the reality of a classroom setting, it is just the way it is. I told them outside of this project, anything would be ok, but to just try and keep it simpler for this one time.

The other thing I saw which I hadn’t thought about was students using multiple sleep commands within one in_thread block. I hadn’t given any examples like that and in my mind, each block was meant to be one sound and one sleep command. But I saw a few students write a play or sample then sleep then another play or sample and another sleep. This would also make the math more difficult to figure out and it seemed that students who took this approach most likely did not fully understand the concept of getting each block to line up. I sat down with those students and explain what was happening in their code. In some cases, we could still figure out the math but in others, it was too complicated to make sense of for the purpose of this project. I brought it to the class’ attention that this was going on and encouraged them to stick to one sound and one sleep command per block to make their lives a little easier. I again stressed that I was making this suggestion strictly for this project and that without any requirements to fulfill this approach would be fine.

I intended to have the students work for the rest of this class and another class. We only get to work in Sonic Pi once a week and the following week there was something else going on so we would be able to revisit these projects until two weeks from this class. I was concerned that they would not remember much of what we had covered up for this project but I hoped having the reference sheet, rubric and checklist would at least give them a blueprint for what to do.