As a continuation of the lesson on arrays from last time, this week I focused on similar concepts: rings and scales. I had introduced arrays as a way to make our code more concise as well as introduce the concept of randomness to create melodies. Using rings and scales felt like a good extension of this. As I said last time, I had initially wanted to have students make scales using midi notes and put them in an array, then afterwards show them the scale function. But as I have been teaching, I’ve found that I have more success keeping the concepts and explanations concise to allow time for students to experiment with those concepts during the same class period. Since Sonic Pi has so many scales already built in, it felt unnecessary to go through that extra step, even though it would reinforce something we had done last year when learning about scales.
I started by quickly reviewing the concept of arrays. One of the things we had covered with arrays was when using a repetition block to play through each note in the array in order, the number of times we repeat through the block should not exceed the number of notes in the array. If it did, once each note had been played, Sonic Pi would continue through the array with rests for the remaining repetitions. To have a repeated sequence in an array, we can use a ring. I framed a ring as being like an array but once it gets to the end, it will return back to the beginning. This allows us to have more repetitions then we have notes in the ring. It also allows us to play repeated patterns of notes.
I provided an example as seen below.
16.times do play (ring, 60, 64, 67, 72).tick sleep 0.5 end
I stressed the syntax of including the word ring and using regular parentheses instead of square brackets. I play it and pointed to the notes as they went around and reinforced to the students that it was the same 4 note pattern playing 4 times in a row. I then changed the 16.times to 14.times just to show that things don’t have to match up evenly, but when running this type of code the ring will continue to play but may stop in the middle, leaving out a few notes, depending on how many times you are repeating.
I then showed the students that rings and arrays can also be used for sleep values to provided more interesting rhythms. I changed the 14.times back to 16, then added a ring to my sleep command so the code looked like this:
16.times do play (ring, 60, 64, 67, 72).tick sleep (ring, 0.5, 0.25, 1, 0.25).tick end
I ran the code and something didn’t sound right to me. I could tell the students didn’t really pick up on it, but I made it clear to them that something wasn’t right in my code and in all honesty, I wasn’t sure what it was at that moment. I played it again and pointed out to them that there were only two notes playing (60 & 67) and it would sleep for the same amount of time each note (0.25). I was able to pick up on this by hearing it but I know the students probably didn’t so I drew their attention to the console. We could clearly see that there were only two notes and one sleep value. I took this opportunity to show how the console can be used to retrieve information about our code to figure out what was going on. I explained that this was an example of when there was a bug, but it wasn’t a bug in the program itself because everything was running fine. There was something I had done which was not giving me the results I was looking for.
Sam Aaron has spoken about this idea before and it really resonated with me when I heard it. He said sometimes there is a bug in the program but sometimes there is a bug in your understanding of the concept or material (I’m paraphrasing here). I really like the idea of a bug in your understanding. I have come to like the idea of calling mistakes “bugs” in computer programming in general because bug seems to carry with it a sense that it is only temporary, that it is just an obstacle that needs to be cleared to eventually achieve your goal. Calling something a “Mistake” can sometimes seem more permanent, something which cannot be undone or fixed. I know this is not always the case, but pyschologically, especially for students, I think this makes a big difference. In this sense, a bug in your understanding is not the same as “I don’t get it” or “I don’t understand”, it is more that “There is something I need to fix before I can move forward on this concept which I know I will eventually understand”.
Since I was mid presentation and was trying to keep things moving to maximize time for the students to explore, I told them I needed to take a look at it later and would get back to them as to why that happened.
From there, I moved onto scales. Since we had spent time learning about them last year, I wanted to at least pay lip service to those concepts just so they could see that what they had learned at a previous time could be applicable to what they are learning now. I feel like making those connections is very important in education because so often students are learning things and then forgetting them shortly after, never to be thought about again. With music, so much of what we learn is applicable over and over again in different contexts. I had a guitar teacher tell me early on that it takes about 6 months after learning something before it really starts to make sense. I had to learn about modes three different times from three different people before I really felt confident in my understanding of the material. So I always try to do callbacks to things we have learned in the past when it can be applied to something we are currently learning.
I reminded them about when we learned major scales and would have to count a certain sequence of numbers to find all the notes in that scale. We would have a starting note, the root note and from there we would have to count a certain number to the next note then another number and so on. I asked if anyone remembered what that sequence was. I got mostly blank stares but a few had a look like they remembered learning this but just couldn’t recall what those numbers were. When I prodded the class to see if they at least remembered doing this, most of them affirmed that it sounded familiar.
I reminded them the sequence = 2 - 2 - 1 - 2 - 2 - 2 - 1. 2 meaning whole steps and 1 meaning half steps. This got a lot of “oohhh yeah” from the class. I figured once they heard it, it would sound familiar. So I showed them that this worked especially well when our notes are numbers. I made an array and started with 60. I then added 2 and put 62, then added 2 to that and put 64, then added 1 to that and got 65 and so on until I had the whole scale in an array [60, 62, 64, 65, 67, 69, 71, 72]. I then put it in an 8.times block and ticked through it. Once played we established this was a major scale. From there I reminded them to how we can use notes in a major scale to make melodies by putting them in different orders (We used an app in Chrome Music Lab called Melody Maker the previous year which I highly recommend checking out). We could do the same thing with this array by doing .choose and playing around with the random seeds we learned about last week.
However, Sonic Pi has a great feature built in which will play scales for us without having to know the notes for the scale. I showed them how to make a scale. I typed play scale(:c4, and then showed them the menu which pops up. I went through all the options we had, I pointed out major and minor which they were familiar with and then pointed out some interesting sounding ones, skipping through a lot just to make the point that there was a lot to choose from.
I then had the following code
8.times do play scale(:c4, :major).tick sleep 0.5 do
I let it run and they heard the same scale I had just played with the array of midi notes. I explained that scales were like rings in that I could have more repeats than notes in the scale and it would just go back to the beginning when it got to the end of the scale. I demonstrated by changing 8.times to 16.times and ran the code again. I also pointed out that this scale had 8 notes but not all scales have that many notes.
I then changed the .tick to a .choose and ran the code. From there I added a use_random_seed to the code to change the pattern. I changed the random seed a few times until I found one I liked. From there I added another block of code. This time I picked a different scale, I believe it was :egyptian and added a ring of sleep values. I included a different random seed as well as changing the synth sound to really highlight when the first block was finished and the next block with a new scale began.
That was all I had to share for that lesson which had only taken about 15 minutes from when we started setting up which left almost a half hour to play around. This seems like the optimal balance of instruction and exploration for these classes. I told students to play around using rings and scales as well as incorporating arrays. As I had done the previous time, I told students at the end of class to log onto google classroom and copy their code into the google doc for their assignment. I really liked having students be accountable to share what they were doing just to make sure they were trying out the concepts I was showing them. It was also very helpful last time for me to go through everyone’s code and see how well they were able to understand what I had shown them. I told them I wasn’t looking for a masterpiece or 100 lines of code. Just an example of what they were doing to see how they were using the rings and scales. I am going to continue to do this for the duration of the year and occasionally have longer assignments that are an accumulation of some of the concepts we have learned, similar to the form project I assigned a few weeks back.
While the students were working, I took the time to go back to the bug I had in my code when trying to use a ring in my sleep command as well as my notes. I realized the issue was that I had two ticks in the same block of code so what was happening was that the first tick would play the 1st note in the ring (60), but the next tick would be the 2nd value in the sleep ring (.25), then the 3rd tick was back to the play ring and the 3rd note(67) and the 4th tick was the 4th value in the sleep ring (0.25). I had played around with this feature previously on my on time and knew that I needed to change the .tick in the sleep ring to .look. When I ran it, I got the results I wanted. I brought attention back to me for a moment to point out what had happened and told them that if they want 2 ticks in a block, the second tick needs to be changed to .look to make them run in the correct order. I didn’t take much time explaining it because I didn’t want to disrupt their flow. I figured I could come back to it next time at the beginning of class.
As I circulated and checked what students were doing, the errors I encountered were mostly syntax related ie using the wrong type of brackets, putting a space where it didn’t belong, missing a comma etc. Some students would have a scale but no .tick or .choose, so I would ask them to explain what they were hearing and lead them to realize they were getting a bunch of notes instead of just one and from there tried to get them to figure out what to do. More and more I am trying to get students to debug their own problems. However, since I know it is still all relatively new and they don’t get much time to work with it, I don’t let them dangle for too long.
I have also started trying to get students to explain what they want to happen before offering a solution. I want them to be aware of the fact that they should have an idea of what they are trying to do and then trying to verbalize what that is. I had a great encounter with two students who were making an array but trying to get the same notes to play a few times in a row before moving onto the next note. This brought up the example of a knit which I am a big fan of. I showed them how to do it and decided this was a great opportunity to share this with the class. I wanted to first highlight that these students had an idea of what they wanted to do and then asked for help when they couldn’t make it happen.
I took the time to do a quick demo, I first showed the code of what they wanted to do as an array which looked like this.
16.times do play [60, 60, 60, 60, 63, 63, 63, 63, 66, 66, 66, 66, 69, 69, 69, 69].tick sleep 0.5 end
I then explained the concept of a knit. A knit is like a ring but can be used to repeat certain values without writing each value individually. For each value you want, you provide two arguments, the first is the value, the second is the number of times you want it to happen.
I went back to the code and commented out the array. Commenting is not something we have talked about, so I also used this opportunity to show a quick practical application for commenting. By putting a hashtag in front of a line of code, it will be ignored by Sonic PI when you run the code. Underneath the line I commented out I wrote the knit version of the code, so the code now looked like this:
16.times do #play [60, 60, 60, 60, 63, 63, 63, 63, 66, 66, 66, 66, 69, 69, 69, 69].tick play (knit, 60, 4, 63, 4, 66, 4, 69, 4).tick sleep 0.5 end
I ran the knit code first. Then I commented out the knit and ran the original array so students could hear that they were the same. I encouraged students to try that out as well. I hadn’t intended on teaching knits at this point and I didn’t wind up showing it to other classes, but since it had come up organically in this case, I took the chance to share it since it was very relevant to the concept we were working on and it was the result of students thinking critically about their code which is a practice I wanted to highlight and share. I enjoy when these teachable moments come up because it feels more like a collaborative process then me just providing steps for them to follow.
Next week, we will cover making functions to continue the idea of making more concise and efficient code.