After playing around with conditional statements, I realized that using if and else if statements were a great way to incorporate form into a composition, specifically ABA or ABACA (Rondo) form. Form is a concept that is often taught in all levels of music class and a central concept when having students compose their own music. It felt like a great opportunity to provide a project which had a musical concept (form) as its objective but also incorporated an important CS concept (conditional statements) as part of the execution. The project that I presented to the students was “Create a composition that incorporates form using conditional statements”.
The first thing I needed to do for the roll out of this project was to make sure the students were clear on what “form” was. After introducing the task, I asked “what does form mean when referring to music”? Some answers were along the lines of “the way a song goes” which could work, but I always want a clearer, more precise definition. I define form as “the order of the parts of a song”. For students, I use pop music forms as an example which they are all familiar with. Pop songs tend to have parts like verse and chorus. The form of a pop song might be verse - chorus -verse - chorus -bridge -chorus. They all understand that example. Then I explain that some songs have different parts, but instead of a verse and chorus, the parts or sections of a song are referred to as “A” and “B” and sometimes, a “C” section.
To provide an example, I presented them with the lyrics to “Twinkle Twinkle, Little Star” which I framed as an ABA form. I realize that this may not be a true ABA form, but it worked for what I wanted to do for a few different reasons. 1.) It is a song they are all familiar with. 2.) It has a melody and lyrics which get repeated for the A section. 3.) It is short. 4.) It is a piece that I could easily code in Sonic Pi when demonstrating the concept of using conditional statements to add form. I showed them the visual of the lyrics so they could get a better sense of what I was talking about. In some classes we sang the song together which they got a kick out of.
I had prepared the code for the song ahead of time. I knew that explaining everything for this project might take a little while so I wanted to save time where I could. I also didn’t have students open the laptops when they got them at the beginning of class. I really wanted to make sure I had their attention (as best as I can hold it) without any additional distractions. I’ve been noticing if they have the computers open, even halfway, they aren’t always focused or sometimes I’ll show them one thing which is leading into another concept but they will go ahead and just start working with that one thing and ignore everything else I say.
I first played the code of what I called the A section. Then in another buffer, I had the B section. However, I only had it play once “Up above the world so high” I did this on purpose and asked what would I need to do to play it twice. Each class was able to say that I needed the 2.times block. I would follow the student’s directions exactly, so if they didn’t say to put end at the bottom of the code, I would leave it out, run the code and then have them debug it once we got the error message. They were all able to figure it out. I was determined to make them think more about the code as we were piecing it together, so I had lots of questions planned moving forward.
I then copied the B section code and added it to the buffer with the A section. I played it just to be sure it was all working. Then I said “I now have the A section and the B section. How do I make the A section play again to get an ABA form?” In each class, someone suggested copying and pasting the A section to the bottom. I agreed that this would give me the results I was looking for but it would not include a conditional statement like I was asking for in this project. I explained that we were looking to keep our code concise and avoid having to rewrite any code. First, I am going to put this code inside a 2.times block so that the A will play twice. “Is this going to give me the results I’m looking for”? A few said ‘yes’ but others said ‘no’. “Why not”? “Because it is going to play the B section again too” Correct! I was going to use this line of questioning a lot for this demo to get them to predict what the code was going to do.
This is why we need to include conditional statements. Before the B section, I put an if statement. I explained this is going to check to see if something is true or false. If it is true, it will execute the B section of my code. If it is false, it will not execute this code. I need to put something in this if statement. I am going to go to the top of my code and write a variable. n = 1. I did a quick recap of variables from last time, stating that now Sonic Pi will know anytime it sees the letter n, it knows that it has the value of 1. Now I am going to go to my if statement and add if n == 1. I reminded them that one equal sign assigns value to a variable, two equal signs checks for equality, in other words “does n equal 1”? If n does equal 1 it will play the code and in this case it does because I declared the variable n at the top. Will this give me the results I want?
Let’s walk through our code. n = 1, 1st time through, play the A section, we get to the if statement, does n = 1? Yes, play the B section. Go back to the top, 2nd time, play the A section, get to the if statement, does n = 1? Yes. This isn’t what I want to happen. What do I need to do? The general consensus was we need to make n not equal to 1 the second time, but many seemed unclear how to do that which was fine by me. At least they are thinking more about it. So I showed them that at the end of the B section, before it goes back to the top to play a second time, we are going to change the value of n to something besides 1, in this case n = 2. Is this going to give me the results I want? Let’s walk through the code. I went through the same order again, but the second time when we get to the if statement, we now know n does not equal 1 so the following code will not run. Then we listened to make sure. I think in one class, I forgot to put an end after the if statement, so we had to debug it together. I try to be honest when I make a mistake like that which wasn’t on purpose to normalize that process of messing up your syntax. It happens to all of us at one time or another.
n = 1 2.times do play 60 sleep 0.5 play 60 sleep 0.5 play 67 sleep 0.5 play 67 sleep 0.5 play 69 sleep 0.5 play 69 sleep 0.5 play 67 sleep 1 play 65 sleep 0.5 play 65 sleep 0.5 play 64 sleep 0.5 play 64 sleep 0.5 play 62 sleep 0.5 play 62 sleep 0.5 play 60 sleep 1 if n == 1 2.times do play 67 sleep 0.5 play 67 sleep 0.5 play 65 sleep 0.5 play 65 sleep 0.5 play 64 sleep 0.5 play 64 sleep 0.5 play 62 sleep 1 n = 2 end else end
Once we had successfully made an ABA form, I proposed that we add a C section. I switched to another buffer which had the Twinkle code along with a C section I made which is basically the B section played backwards. I wasn’t expecting anyone to remember the else statements we touched upon last class and I didn’t want it to drag out by trying to pull the answer out of them. I was trying to get through this whole demo quickly so they could have some time at the end to get started. My biggest fear was to give a whole long demo of the project only to have no time to work on it at the end of class which would mean they have a whole week to forget everything before working on the project next time.
I reminded them the else statement is there to give us an alternative to the if statement. If the condition is true, play the if statement, otherwise if it is false, do this instead, in this case the C section. I walked through the code in the same way and played it. This gave us an ABAC form. However, I wanted to do an ABACA form. What do I need to do for that? I pointed out that in this form, I want the A section to play a total of 3 times and I hinted to the 2.times block at the beginning of the code. The answer came that we need to make that a 3.times block. I also need to change my else statement to an else if statement which will require another condition to check if it is true or false. I am going to use the same variable and now check for the value I changed it to at the end of my B section, n =2.
Lets walk through the code. n = 1, 1st time through, play the A section, we get to the if statement, does n = 1? Yes, play the B section, at the bottom, n now equals 2. Go back to the top, 2nd time, play the A section, get to the if statement, does n = 1? No, else if does n = 2? Yes, play C section. Back to the top, 3rd time, play the A section, get to if statement, does n = 1? No. else if, does n = 2? There was a pause. Some said no, some said yes. I pointed to the n = 2 at the end of B section. Yes it still equals 2. Is this going to give me the results I want? No. What do I need to do? Again, the majority was that we need to change n to something at the end of the C section. I reminded them that the last time I don’t want the if or else if statement to be true, so n can’t equal 1 and it can’t equal 2. But it can equal anything else. I changed it to 7, just so they could see it didn’t have to follow any certain order, like n =1, n =2, n = 3. Lets walk through the code. You know how it goes so I’ll spare the re-iteration. But I really feel like the repetition of going through the code is important for the students to hear which is why I keep doing it. Moving forward, I may start asking students to walk us through the code instead of me.
n = 1 3.times do play 60 sleep 0.5 play 60 sleep 0.5 play 67 sleep 0.5 play 67 sleep 0.5 play 69 sleep 0.5 play 69 sleep 0.5 play 67 sleep 1 play 65 sleep 0.5 play 65 sleep 0.5 play 64 sleep 0.5 play 64 sleep 0.5 play 62 sleep 0.5 play 62 sleep 0.5 play 60 sleep 1 if n == 1 2.times do play 67 sleep 0.5 play 67 sleep 0.5 play 65 sleep 0.5 play 65 sleep 0.5 play 64 sleep 0.5 play 64 sleep 0.5 play 62 sleep 1 n = 2 end else if n == 2 2.times do play 62 sleep 0.5 play 62 sleep 0.5 play 64 sleep 0.5 play 64 sleep 0.5 play 65 sleep 0.5 play 65 sleep 0.5 play 67 sleep 1 n = 7 end end end end
After walking through the code, I played it and we successfully got our ABACA form. I would call out which section we were on each time just to make sure everyone was clear about it. If you’ve read my other posts, you know my thoughts on expectations with listening examples. When it was over, I restated that this was an ABACA form. In classical music, this order of parts is also referred to as a Rondo. I told them I was going to play an example of a very famous Rondo which I assumed many of them had heard.
As it played, I made sure to call out which part we were on just to be sure. Afterwards I asked for a show of hands of how many have heard that entire song before. More hands went up than I expected. I feel like everyone knows the A section but not the others… But now you know this is a Rondo. I then pointed out that the B and C section were quicker than the A section. I posed the question “if I wanted to do this in my code, how could I achieve that same effect”? Sure enough, students were able to say that using the use_bpm function would do this. I reminded them I would need to put it at the beginning of each section, but I didn’t actually write it in my code.
I then played another example of a Rondo. Fossils by Camille Saint-Saens from The Carnival of the Animals. When this was finished, I drew their attention to the fact that each section had a different instrumentation. The A section had very clear xylophones playing the melody, the B section had more piano and strings while the C section had a clarinet carrying the melody. How could I achieve the effect of different sounds in each of my section in my code? Again, the answer came to include use_synth for each part. I made it clear that this was also part of what I would be looking for in this project, to add contrast to each part by including the use_bpm and use_synth commands.
At this point there was about 15 minutes left in class, so I stopped talking and let them get started. I handed out a reference sheet for the conditional statements and an assignment sheet with the task, a rubric and a checklist. I told them we would have all of next class to work on this.
1.) I was very pleased about the responses I was getting as we kept walking through the code and asking if I was going to get the results I was looking for. It was feeling more and more like the students, at least some of them, were getting more comfortable with how code works and can start making predictions. There were also a few instances of some good debugging that came from my own mistakes, sometimes on purpose, sometimes not.
2.) I really loved being able to play musical examples, point to something we heard and ask how we could execute that in our code. This felt like the first time I had found the perfect balance that I am trying to achieve between teaching music through code. I had been on the fence about whether I should play these examples, mostly from a time point of view, but ultimately I am glad I did. It was really an amazing moment for me in my journey of teaching Sonic Pi.
3.) I felt like the roll out took a bit long and was disappointed that the students didn’t have a lot of time to work at the end. I had figured that giving it a lot of attention to make sure everyone understood was the right thing to do, but I also worried that when we come back in a week, a lot of what we discussed today would be forgotten and I would wind up having to explain the concepts again. Spoiler alert: This definitely happened. So much so that my next post is going to combined the next two weeks because I wound up giving them an extra class period to complete the projects. But it is all part of the learning process. It is funny looking back how I felt so good about this lesson and then the following week, I felt down because a lot of kids didn’t really seem to remember the concept of conditional statements or even that it was part of the project. But that is teaching in a microcosm. One day you’re up, the next you are down.