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.