My year teaching Sonic Pi - Week 6

#1

After having two weeks to finish the first project using basic commands, I wanted to allow some exploration time for this class using some new functions. First off, I showed them amp:. In one of the classes, a student had asked how to make a note louder. I also saw another group use this code in an effort to make a louder note:

10.times do
play 90
end

I demonstrated using the amp: command and emphasized that there needed to be a comma in between play and amp. I then ran the code without a comma to show the error message that would pop up. I started with play 60, amp: 1 just to revisit the idea of default settings since we had discussed that with use_synth and use_bpm last class. I said even if I didn’t write this, it would sound the same. But then I changed to amp: 2 and amp: 4 so they could hear the change. Of course, some yelled out to “Try amp: 50”. I advised against doing that but said they were free to experiment when they had their headphones on later. I also made the point that amp will only affect the note it is next to, it will not carry over to another line of code. I demonstrated by putting a play with no amp:, sleep 1 and then another play with amp: 4 to clearly show the difference.

I also wanted to share some envelope parameters since up to this point every note they play only lasts for 1 beat. I decided ahead of time that I would not frame it as “envelope parameters” but rather “duration”. The concept of envelopes in sound synthesis just seemed like it would require a lot of additional explaining of concepts that were secondary to what I wanted them to get out of it. All I really wanted was for them to be able to have notes last longer and the concept of duration would make that much simpler and to the point.

I was kind of surprised the question never came up, that being “How do I make a note last longer?”. I mentioned that when I started demonstrating. As I’ve said before, I want to model thought process when forming questions just to reinforce that idea of wanting to do something and being able to articulate what it is. I mentioned that up until now every note lasts only 1 beat. I reminded them that the amount for sleep was how long of a space there is between notes, but does not affect the length of the note itself. To change the length of the note, we need release: . I demonstrated with play 60, release: 2, again pointing out that they needed a comma between those two commands. I also mentioned if they were to include amp:, they would need an additional comma. I then changed release to 4 which made the effect more clear.

From here, I said “let’s see what happens if I want to use release and then play another note” After play 60, release: 4, I put sleep 1 and play 67. I asked the class what they thought would happen. The few who were brave enough to guess assumed the first note would last for 4 beats, then sleep for 1 and then play the next note. I said “let’s listen and see” Upon running the code, they heard that the first note played, but then the next note also played before the first note finished. I ran it twice more just in case some missed it the first time. This was an opportunity to revisit iteration and the fact that the code is run through very quickly so the program is only going to sleep for 1 before it plays the next note even though the first note lasts 4 beats. I made it clear that in some cases this might be exactly what you are trying to do which is fine. You can have notes overlapping if that is the effect you are going for. However, what if we wanted to have the first note play for 4 beats, then have the next note play without any overlap? Several students were able to infer that now the sleep would need to last the same amount as the release. This brought up an important idea that the timing of sleep begins at the start of a note being played, not at the end. This concept will be important later down the line we we look at making drumbeats. I changed the sleep to 4 and ran the code again. Sure enough, we got the results we were looking for.

Next, I showed them attack:. I framed it as a “fade in”. Where release is the length of the note after it is played, attack is the lead in time to the note. The example I did were play 60, attack: 4. I realize that attack with envelopes isn’t generally used with whole numbers as much, but more so decimals less than one, 0.1, 0.07 etc. However, I felt they would have more fun using it in this way. I also pointed out that depending on the synth you use, you can get some cool effects. I added use_synth :tb303 and ran the code. It had a great drawn out “wah” type of effect which really emphasized the fade in.

At this point, I still had the sleep 4 and play 67 after the code. So I took the opportunity to show that I could use both attack and release on the same note. I added release: 4, again emphasizing the comma. I asked what they thought would happen. This time, some kids seemed more confident to say that the second note was going to happen after 4 beats. I ran the code to prove they were right. I then asked “So what do I need to do to make the first note finish before the second note begins and we arrived at the answer of needing to add together the duration of attack and release and use the answer in our sleep command. In this case, we needed to sleep for 8. I made the change and ran the code. There was a great moment of anticipation as the note played waiting to be vindicated by our conclusion….at least for me.
This is the reference sheet I provided to them for these 3 commands - link

The other concept I wanted them to play around with was using conditional statements. I decided to go this route because for the last project, one pair of students had asked how they could play some code, go back and repeat it but then skip a section of that code and go on to a different section. They had this idea because they wanted to have some different synth changes throughout the code and within the repetition block they were using, they couldn’t figure out how to do it. When they presented it to me, I knew that it would involve some sort of conditional statement, but within the confines of the class, I didn’t have time to think it through enough and whatever I tried didn’t work. So I told them this was a great question, but I needed to play around with it outside of class.

Within the Sonic Pi help reference and tutorials, the introduction to conditional statements involves using one_in() as a boolean to generate a random number that will decide whether or not the code will run. I do see the benefits with this in a musical setting, especially for simulating improvisation or adding variation to a drumbeat, but in this case, I wanted to try and do what I would consider a more “traditional” type of conditional statement that is used in programming, at least from my point of view. This is somewhat against my philosophy of focusing on musical elements over Computer Science. But I know that when I first learned about how conditional statement works, it really opened my eyes to how computer programs run and it changed how I looked at the so many different things going on around me. There were so many aspects of all types of programs and websites that I use where I could see these types of if/else statements at work. I decided I wanted to expose the students to this as well, even without getting too deep into the formal CS definition, in hopes that it might change their way of thinking about the world around them.

When I say more “traditional”, I am referring to an if statement with a boolean variable that would decide whether or not to execute a block of code. I wanted to incorporate using variable values for the boolean since we had briefly discussed variables last class and I feel like those type of booleans come up a lot in general with programming. I also wanted to have the first examples be a conditional block where they could see first see the conditional block execute when the boolean is true and then see it not execute when the boolean was false. I felt that this would be more clear than using the one_in() boolean from the help reference which already has an else statement built into it and regardless of the boolean value, something was going to happen. Since we are dealing with sound, my concern for that type of example was that students might not pick up on what was happening since they would hear something happen for either result of the conditional. As I’ve stated before, just because something in a listening example seems obvious to me, doesn’t mean it is going to get through to the students in the way I’ve intended it.

I presented the concept of conditionals as a requirement needing to be met in order for something else to happen. This is presented as something being true or false. If the condition is true, do this. If it isn’t true, don’t do this. I wrote out a short example of plays and sleeps and ran the code for them to hear. Next I said I was going to write some more code but I was going to start with a conditional statement. To do this, I start with the command if, as in if whatever I put here is true, do whatever comes next. If it isn’t true, don’t do whatever comes next. What I am going to put in that space after if is a variable. I reminded them about what we covered in regards to variables last class, that we can pick a letter or word and assign it a number value and whenever that variable appears in our code, the program will interpret it as the value assigned to it.

At the top of my code, I wrote ‘n = 1’. So now Sonic Pi knows that anytime it sees the letter ‘n’ , that means ‘1’. I then went to the ‘if’ statement and said “Now I am going to use that variable as my condition. If n is equal to 1, play the following code.” One important thing I mentioned (which I had totally forgotten when that first group asked me about how to skip parts in their code and I couldn’t do it on the spot) was that in a conditional statement, we need to include TWO equal signs ==. One equal sign assigns value to a variable, but two equal signs checks for equality. In other words, one equal sign says “This is what this letter/word is equal to now” while two equal signs is asking “is this letter/word equal to this?” I put in n == 1 after if and reiterated that when we get to this part of the code, it will ask “is n equal to 1”. If it is true, it will run whatever comes next.

I also explained that a conditional statement is a block of code, which means I need to include an end. So for best practice, I wrote the end and then started to add some code inside of the block to play. I also decided to change the synth sound in my conditional block of code to emphasize the change. I then went over it one more time. For this type of example, I really wanted to drive the point home and I figured it can’t hurt to talk through my code repeatedly to get them thinking about what is happening before they actually hear it. I ran the code and everything played as it should.

n = 1

  play 60
  sleep 1
  play 67
  sleep 1
  play 64
  sleep 1
  if n == 1
    use_synth :chiplead
    play 72
    sleep 0.5
    play 74
    sleep 0.5
    play 76
    sleep 1
  end

Next, I went back up to the variable I declared at the top and said “Now let’s see what happens if I change the value of this variable to n = 2.” I then talked through the code “It will play this first part, then get to the if statement and ask “does n equal 1”? I looked at the class “does n equal 1”? Some stared somewhat blankly, there were one or two meak “yes’s and a few more ‘no’s. I pointed to the top of the code. “n now equals 2, so when we get to the conditional statement and it asks is n equal to 1, the answers is ‘no’ so it will not run this code.” I ran the code and enjoyed the moment when they would have heard the conditional code but didn’t. There were a few “woahs” and looks of astonishment which I found very exciting. However, I kept it moving because I wanted to give them time to explore this.

I then proposed “what if I wanted to play this code twice and have the conditional code play the first time but not the second? What do I need to do?” I first got some responses that I would need to use a 2.times block which was true. I wrote 2.times do and ran the code. Error message. “What happened? Why did I get this message?” Quite a few jumped up to say I forgot the end in my code block. “Great debugging!” I then ran the code and only the first part played then no conditional code then the first part again. “What happened”? This time, no responses. I talked through the code again. When I got to “Does n equal 1”? I pointed up to the top where I declared the variable. No, it does not. So I changed it back to n = 1. Will that fix it? Some said yes. Lets run it and listen. This time the conditional block played but it also played a second time. I also pointed out that the second time the synth was different in the beginning. Why is that? “Because you changed the synth and it carried around the second time”. That’s right! So to keep it consistent, I added use_synth :beep to keep the starting plays and sleeps the same both times around.

In order to make the conditional block not play a second time, the condition has to be false. So I am going to change the value of the variable at the end of my conditional block of code. At the bottom I put n = 2. I then spoke through the code starting from the top “n equals 1” “First time” pointing at the 2.times block “Do this” pointing to the first lines of plays and sleeps “If statement. Does n equal 1” I looked at the class for an answer “yes” “play this code” pointing to the conditional block “n now equals 2” pointing to the changing of the variable value then pointed back to the 2.times block “Second time” pointing at the 2.times block “Do this” pointing to the first lines of plays and sleeps “If statement. Does n equal 1” I looked at the class for an answer “No. Now it equals two” “Therefore, the condition is false and this code will not play” Let’s listen. I played the code and it all ran as expected which was met with some light applause. I was getting hype at this point.

n = 1

2.times do
use_synth :beep
  play 60
  sleep 1
  play 67
  sleep 1
  play 64
  sleep 1
  if n == 1
    use_synth :chiplead
    play 72
    sleep 0.5
    play 74
    sleep 0.5
    play 76
    sleep 1
    n = 2
  end
end

One more thing before I turn them loose. Let’s say I want it to happen twice but the second time, I want some different code to play instead of what is in the first conditional block. Now I need to add the word else. As in “If this is true, do this. If it isn’t true do something else.” I typed in the word else after the first conditional code and added some new code. I again changed the synth sound to emphasize the changes when they happened. I spoke through the code again exactly as I said it before. It was sounding like a broken record, but I wanted to keep reinforcing this idea of predicting what your code was going to do before you actually ran it. I felt that I couldn’t do that enough and everytime it would feel a bit more familiar. The only change now was when we got to the second time evaluating the conditional statement “Does n equal 1” “no” so now we do not run this block of code but instead we do the else statement. I ran the code and listened to the change. Success!

n = 1

2.times do
  use_synth :beep
  play 60
  sleep 1
  play 67
  sleep 1
  play 64
  sleep 1
  if n == 1
    use_synth :chiplead
    play 72
    sleep 0.5
    play 74
    sleep 0.5
    play 76
    sleep 1
    n = 2
  else
    use_synth :mod_fm
    play 67
    sleep 0.5
    play 65
    sleep 0.5
    play 64
    sleep 1
  end
end

At this point, I had spoken enough and gave them the rest of the period to explore these new concepts. As I circulated the room, some were playing around with release and attack, some with conditionals, some were playing around with live loops, and others were getting into coming up with crazy variable names to put in their sleep and play commands. I was fine with all of it. I addressed problems as they came to me but tried to get them to look through their own code first and try to debug it. A few students would hand me their headphones and asked me to listen to what they. It all sounded great to me.

Thoughts…….

1.) I noticed a larger number of the students were getting more comfortable to answering questions. The concepts we had covered this time allowed for more opportunities for me to pose questions where they could apply what they now knew to what was happening. Now before I do something or if there is an error in my code, I can say “what is going to happen?” or “why didn’t this work?” To me, this was a sign that the concept of coding in general was becoming more familiar to them and they were feeling more comfortable thinking through what is going on because it doesn’t feel as foreign. I am hoping to continue this as we go deeper and deeper.

2.) With one class I decided to show them that when using variables as booleans, you can actually assign the value of true or false, as in n = true. Then in your conditional statement you can just put the variable like’ if n’ and it will be read as if true. Then you can change it to false later so the conditional block won’t run. After doing this and looking at some students who were trying it, they didn’t quite seem to get the concept as they were using the variables in the wrong places and not putting it in the conditional correctly. Sometimes I want to give a more in depth look at a concept, but for a 40 minute period, I think it is too much. I need to give them less and let them spend more time working with it and get acquainted with how to use that basic idea without adding more on top of it since more often than not, it just confuses them. However, this is a mistake I am destined to repeat because what I think is just the right amount of information is often too much for the students. But like I said in the beginning, we are going to make mistakes and that is ok. We will learn from them.

As I was teaching the conditional, something clicked in my musical brain as to how I could tie this into a legitimate musical concept. Next week: Form with conditional statements.

2 Likes
#2

Hello,
I like the way you present conditionals it’s very thorough, starts simple and builds up. I introduced it after mentioning randomness and then used rand with less than operator for the if condition making it less clear than equal operator and introduces 2 concepts too quickly. I will definitely come back to conditionals the way you did, thanks for sharing.
Laurent

1 Like
#3

Thanks for the feedback. Glad it is helpful.

I know Sonic PI introduces conditionals using the one_in coin flip concept, but I agree with you that trying to introduce randomness in addition to conditionals is a lot for students to get all at once.

I am just now introducing randomness along with arrays and scales as a way to create melodies. I feel like its easier to see/hear the results of the randomness in a more concrete way. I’ll be writing about that for the next week.