My year teaching Sonic Pi - Week 15

After the last project of making functions and incorporating data structures, I wanted to take a step back and give the students something easy to play around with. I also felt we had reached a point where their sonic palate has been somewhat limited for a while at this point. I don’t necessarily think that is a bad think. I believe that creativity can be encouraged and developed over time through putting boundaries and limitations on what can be done. It gets students thinking of what could be done when those limitations are lifted as well as having to make creative maneuvers in the present.

Up until now, we have been working exclusively with synth sounds. At this point I wanted to introduce them to using samples. I introduced the concept by first explaining that what we have been using is synthesized sound which is the computer creating sounds that we then manipulate with pitch, duration, volume, timbre etc. In 6th grade, I teach students about how sound is created by a vibration and that certain things about the vibration affect how we perceive the sound (size of the vibration affects volume, speed of the vibration affects pitch). So in Sonic Pi, a synth sound is basically the computer simulating a vibration that produces sound and we can determining parameters like what pitch it will play or how long it will play for.

A sample, on the other hand, is a pre-recorded sound that we can play in Sonic Pi. It is basically a sound file like a song in an mp3. However, we cannot manipulate these sounds the same way we can with synth sounds. I had thought to play a song in an mp3 in Sonic Pi to prove that point, but since they were just being introduced to this concept and the syntax for it, I didn’t want to add confusion by loading a sound file through the file path since it would look very different from using the samples preloaded into Sonic Pi.

I showed them the sample command and the menu of sounds they have to choose from. I made sure to scroll all the way through it so they knew there was a wide range of samples available. I went with :ambi_drone first and played it. This is all there is to it. I picked a few more sounds just to give a taste of what was now available to them. I then went back to :ambi_drone. I added another sample before that which was :ambi_soft_buzz and ran the code. I did this to make it clear that both samples will play at the same time, the same as when we have multiple plays together.

To play them one at a time, I still use sleep. I added sleep 1 and played the code. The students heard :ambi_soft_buzz and then :ambi_drone. I then switched the order of the samples so :ambi_drone played first then sleep 1 then :ambi_soft_buzz. I said to listen for what happens. I played the code. I ran it twice in case they missed it the first time. I drew attention to the fact that while the first sample was playing, :ambi_soft_buzz played before the :ambi_drone sample had finished. Because these are recorded sounds, they each have a different length depending on how long the sound lasts. Not all samples will be the same length. This is not like synth sounds where we can change the duration using commands like release and attack.

To get the length of a sample, we can use the command sample_duration. I wrote puts sample_duration :ambi_drone. I reminded them that puts can be used to send information about our code to the console. I also commented out the other code and reminded them that commenting out code allows us to skip it without having to erase it. Both puts and commenting are things that I have brought up in the past, but haven’t really devoted a specific lesson to. I just try to reinforce the concepts when there is an appropriate time to use them. When I ran the code, a number was printed to the console. I brought it to their attention that the number represented the length of the sample. Now I could put this number as my sleep value but there is an easier way to do this by using the sample_duration command as the value for sleep. By doing this, Sonic Pi knows to sleep for the value that came up in the console. I included this code and ran it which resulted in the first sample playing and then when it was finished, the second sample played. I made it a point to say that we use this command if we want one sample to play only after the other sample is finished. If you want to have one sample play while another one is still playing, then you could use a different sleep value. I did this just to make the point that this wasn’t about a right or wrong way to write the code, but it all depends on what you are trying to achieve with your code.

One additional thing I showed them how to do was storing the sample duration value in a variable. At the top of the code I put t = sample_duration :ambi_drone, then put t as the value for sleep and played it again. This produced the same results as before.

From here, I showed them ways that we can manipulate the samples. I started with pitch. We can change the pitch of a sample by including the command pitch: with a number value. The value of 1 would increase the pitch by one midi note, like going from play 60 to play 61. For the example, I used sample :ambi_drone because this sample does have a discernible pitch to it. I chose to change the pitch by 4 because I felt changing it by 1 might be difficult to hear the difference. I also started by playing the sample without any manipulation, followed by a sleep for the sample duration, then the pitch change so the difference would be clear. I then changed the pitch to 9 and ran it again. I pointed out that the quality of the sample changes when we manipulate the pitch. This is because the sound itself is not what is being changed, but rather the sound file which involves a more difficult process to make it sound different pitchwise. As a result of this, we cannot have a value more than 24 or else we receive an error message. I ran an example to get this error message.

In one class a student asked what would happen if I did an negative number, to which I replied “Let’s find out” and made the point that this type of experimentation is always encourage. If you are wondering what would happen if you did something, the only way to find out is to try it. The worst that can happen is the code doesn’t run. I entered the code with a negative value and we listened. They could hear that it sounded lower. In another class, the question didn’t come up so I asked what they thought might happen if we used a negative number. Some said it would be lower. A few thought we would get an error message. Again, I responded “Let’s find out”.

Next, we looked at rate. I believe in one class, a student had asked if there was a way to speed up or slow down the sample which was great to see they are already anticipating possibilities of what they could do. I explained that rate is different from pitch in that we are changing the speed of the sample which will affect its length. This time I used a different sample, :guit_em9. This sample is longer and the changes caused by using rate are more noticeable. It is also a pretty cool sounding sample. When I played it the first time without any changes, the kids all seemed to like it. I used puts to print the sample_duration to the console which is roughly 9.9. Using the rate command at 2, I printed the duration to the console again which gave half the value to show that the amount of time the sample plays for is affected with this command. I then ran the code, again first with the unaltered sample and then with the sample with rate: 2.

When the code ran, they heard the first sample but then the second sample came in before the first one finished. I had planned for this to happen and asked the students why they thought it did this. A few of the students were able to point out that the variable I was using for the sleep value was the duration of the :ambi_drone sample, not :guit_em9 which was longer. I was glad to see them pick up on this as it is a common mistake to make when using variables to store these types of values. I changed the sample_duration variable to be for this :guit_em9 sample and ran the code again. This time they could hear the second sampel at rate 2 after the first sample was finished.

I pointed out that the pitch as well as the speed had changed. The students had learned last year that the speed of a vibration affects the pitch. The faster something vibrates, the higher pitch it has. This seemed like the best context to explain what was happening to the samples since it was referring to something they had learned already. By speeding them up, the recording of the vibrations are going faster which is causing the pitch to increase as well.

The default for a sample rate is 1, which means that it will play at regular speed when you put 1, so putting rate: 1 is unnecessary. I make it point to say this because I have noticed some occasion where the students enter a command with the default settings, like use_synth :beep or use_bpm 60. While it makes no real difference if they do this, part of our focus has been to make our code more concise, so it helps to avoid these redundancies when possible. Since rate: 1 is regular speed, I showed them how decimal points will have the sample play slower. I did this by putting the sample rate at 0.5. Next I asked what would happen if I put in a negative number. I got answers ranging from playing really slow to an error message to playing backwards. We ran the code with a rate of -1 and heard the sample play backwards.

The final command I showed the students was how to play sections of samples by using start and finish. I first showed them the finish command. I explained that finish takes a value between 0 and 1, so that means they will be using decimals. I said they could think of it like a percentage, which I am fairly certain they have covered in math class on how to convert decimals to percentage and vice versa. I gave the example of the :guit_em9 sample with a finish value of 0.5. I told them this would play the sample from the beginning and play 50 percent of the sample meaning it will stop halfway through. I ran that code and they could hear the sample cutoff. However, with that specific sample there is a good amount of ambient sound, so I also ran the code with finish: 0.3 to make the cutoff more pronounced, framing it as only 30% of the sample will play. I also ran the code as the first of the two samples I had been playing to illustrate that just because I added a finish command to the sample, the sample duration will stay the same unless I add that command to my variable for the sleep value.

I then showed them start which will start the sample after the beginning at a certain specified point. I tried to provide some context as to why they might do this. I said I really like the ambient sound at the end of the :guit_em9 sample and might want to use that and skip over the actual guitar part. I use start: 0.4, saying that this will start 40% into the sample. I ran the code and let them hear the noise that comes after the guitar. FInally I said that start and finish can be used together to play one section of a sample. I used start: 0.25 and finish: 0.75 as an example. I said there may be times you just want to zero in on a small part of a large sample and this would be the best way to do it.

All of these examples were provided on this handout:

Since we had been using arrays and rings in the past few weeks, I wanted to find a way to show them that those data structures could still be used with the examples we had gone over in class.
I wrote the following code to illustrate where we could put an array to make our code more interesting.

16.times do
  sample :elec_beep, rate: [1, 1.5, 2, 2.5, 3, 4].choose
  sleep 0.5

This gives some more melodic qualities to our sample. I also pointed out in this case that I didn’t need to use sample_duration because it is a short sample. I advised them to be aware of the lengths of the samples they are using to know when using sample_duration is appropriate.

The last thing I showed them to incorporate data structures was that you can put samples into an array. I wrote the code below as an example.

16.times do
  sample [:elec_beep, :ambi_choir, :bd_haus, :misc_crow].choose
  sleep 1

I pointed out that to do an array of samples you need to have an idea of which ones you want to use since the drop down menu will not come up inside of the array. The ones I included were ones I remembered off the top of my head but I encouraged students to go through and write down ones they liked if they wanted to try this approach. I also warned them again to be aware of the different sample lengths when deciding on a sleep value.

At this point, I turned them loose to explore. One of the main things I wanted them to do was to take time to explore the different samples that are available. I think it is important to have a good knowledge of the sonic palate you have available to you when working with any type of digital music environment. Providing time to explore these sounds pays off later on when they find sounds they really like and are able to incorporate them into their compositions. As I walked around, it didn’t seem like a lot of them were doing too much with the commands to manipulate the samples, but that wasn’t much of a concern to me. I feel the students will take what works for them. I’ve noticed they seem to gravitate to the bigger concepts, but do not do much with ways to add nuance and detail. For example, I haven’t seen students using amp, attack or release much in their code since it was presented to them back in the first few weeks. This might be something worth revisiting or perhaps showing them how it could be included in a ring or an array in tandem with other concepts we have explored more recently. Sometimes we forget things we have learned earlier on in our journey because we don’t fully understand their capabilities in regards to the bigger picture. But revisiting them after we have acquired a deeper understand may give those concepts new life. I will definitely consider this as something to do moving forward.