This week the students were continuing their work on their projects using functions to create an ABACA form piece which used arrays, scales and rings. Since this was going to be a graded assignment, I did not present anything to the class during this time, but rather circulated throughout the room and addressed problems or sometimes just made observations. For this post, I’ll just be writing about observations I made and issues that came up consistently both while students were working in class and going through their code after it was submitted. I will also include some examples from class to make these issues more tangible.
When walking around, I will take notice of a student’s code if I see something that seems off and take time to talk them through what is happening. For example, I was coming across students who were using scales without any .tick or .choose which makes all the notes in the scale play together at the same time. I generally avoid saying anything is “wrong” with the code, but instead I just ask if they are “aware” that this is what the code is going to do. Sometimes they say yes and keep it, sometimes they did not realize that was the case and will make a change. But I don’t want to give the impression that what they are doing is “wrong” if it is what they meant to do. Below is an example of student code which uses that example purposely.
a= 0.3 b= 0.4 c= 0.5 d= 1 ainsley= 70 define :ree do play scale( :g1, :minor) wait b play ainsley wait b play scale( 90, :major) wait a wait a play ainsley wait b play scale( :c4, :minor) end define :oof do play scale( 50, :major) wait b play ainsley wait c 6.times do play (ring 54, 60, 78, 80, 62, 54).tick wait c end play scale( :c4, :minor) end define :no do 4.times do play scale( 69, :major) wait a end wait a play scale( 70, :major).tick wait b play scale( 76, :major) wait c play scale( 70, :major) wait c play scale( 80, :major) wait c play scale( 76, :major) wait c play scale( 72, :major) wait c play scale( 68, :major) wait c play scale( 64, :major) wait d 4.times do play scale( 69, :major) wait a end wait d play scale( :e4, :minor) wait b 6.times do play (ring 68,70,72,74,80,76) end wait c play scale( 70, :major) wait c play scale( :e8, :minor) wait b end ree oof ree no ree
A common issue I came across while walking around was mixing up syntax when using scales, rings and arrays. I had quite a few students ask me why their code wasn’t working and often it was having regular parentheses around a group of values. I would remind them that if they wanted a ring, they would need to write the word “ring’ inside the parentheses. If they wanted an array, they needed to change to square brackets. Other times, it would simply be that students were putting a space between the word “scale” and the parentheses that followed it.
I feel like these syntax errors are just part of the learning process. I’m sure that the sequence of presenting them got confusing since we looked at arrays one class and then scales and rings in the next. Using them all together when still unfamiliar with the concept will naturally lead to mistakes. I have been providing handouts for all of these concepts and try to bring them to students attention when they have these types of errors. I want them to become more confident to debug their own code, however I also understand we are working under time constraints and I don’t want them spending a large chunk of time combing through their code to find out they just forgot a comma somewhere or something like that. I feel like those kind of mistakes can lead to frustration that might turn the students off to coding. If this were an actual CS class, I would probably have a different opinion about that, but my main goal is to have them making music and those minute syntax errors can be discouraging to their overall productivity. So I have been helping to fix those types of errors and hope that seeing that it was a small detail will make them more aware of looking for that type of bug in the future.
Something else I have been trying to get students to do is think about what their code is supposed to sound like before they run it. This is difficult to do as I think most students are using more of a trial and error method of typing in some seemingly random code and listening to what it sounds like, then from there trying to shape it into something that sounds good to them. I am fine with this. I am not really expecting most of them to have the musical knowledge to envision something in their head and then translate it into code. I honestly do not feel a lot of them could even really form a musical idea in their head to build off of. That takes a lot of musical experience to think like that and then being able to pull that idea from their head and try and shape it into an audible example. I’ve been making music over 30 years and I still have trouble doing that sometimes.
The reason I bring this up is because one of the biggest issues I noticed in the code that was submitted was with using .tick and .look with data structures. I had given a brief demonstration of how .tick and .look work but I feel like until you see how your code is affected by it, it is kind of an abstract concept. Several students were using .tick within the same function which resulted in certain values getting skipped over. However, given that they are just typing code and seeing what happens, I don’t think they realize that certain values are being skipped. They just listen and accept whatever is happening without necessarily understanding the nuances behind the commands they are using. I have tried to point out the console on a few different occasions to show how we can find out what is actually happening in our code, but I don’t think it is a tool they really understand how to use yet. I feel like the best I can do at this point is to continue to reinforce the correct way to do write the these commands and point out times where I see it used incorrectly. Below is an example of student code which used multiple ticks.
#ThisExists use_bpm 100 define :weiwhrl do 3.times do 4.times do use_synth :tb303 play [:c8, 69, 70, 60, 69.99999999999].tick sleep [0.5, 0.3, 0.1, 0, 1, 1.3].choose use_synth :mod_saw play (knit, 60, 3, 80, 2, 40, 4).tick end 3.times do play (ring, 70, 45, 80).tick use_synth :prophet play (ring, 80, 70, 60, 50, 40).tick end end end
Something else I noticed was the way tick was behaving when being used across multiple functions. The code below is from a student who was having problems with arrays and .tick because when she got to the second function nothing was playing as a result of tick having gone through the positions in the array. I hadn’t realized that ticking through one array would be carried across to another function that also was ticking through an array. Throughout this process, I have come across certain problems that I never would have encountered on my own and it has caused me to go deeper into those problems and commands in order to figure them out. This .tick issue was one of them and truthfully I am still not fully clear on exactly how it works, but I now know more than I did. Anyone reading who wants to weigh in with more explanation about tick is more than welcome.
define :mini do use_synth :chiplead 8.times do play [85, 80, 90, 95, 85, 80, 90, 95].tick sleep 1 end end define :strangepuppy do tick_reset use_synth :chiplead 8.times do play [90, 84, 90, 84, 82, 97, 80, 98].tick sleep 1 end end define :a do tick_reset use_synth :beep use_random_seed 99 16.times do play scale(60, :spanish).choose sleep 1 end end define :happy do tick_reset use_synth :beep use_random_seed 90 8.times do play [ 70, 75, 70, 95, 85, 79, 90, 90].tick sleep 1 end end mini sleep 0.5 puts 60 strangepuppy sleep 0.5 puts 60 a sleep 1 puts 60 happy
We were able to fix this issue by using tick_reset in each function, but it was not a concept I did not shared with the class. There times when certain things come up in a specific student’s code where I will use it as an example to share with the class because it is a concept I think everyone will benefit from seeing. However, in this case, this was an issue that was more specific to this one example and I didn’t think it was going to be applicable to everyone. I also have be weary of presenting too much information as I have been seeing that it creates confusion when students try to implement it in places that it isn’t really necessary.
Other issues I saw with moving through individual values of data structure was some students using .choose with rings, which although I know there is nothing that will go wrong with that, I tried to let students know that rings are better for ticking through because they let you repeat patterns by going back to the beginning unlike arrays. Arrays and scales seem better for using .choose. This was an another example of me pointing out the issue as something to “be aware of” as opposed to saying it was done incorrectly.
One final thing I saw was a lack of understanding in the connection between using repetition blocks and data structures in terms of the relationship between the number of times in the repetition block and the number of values in the array or ring. Sometimes it would be an array with less values than the number of times it repeated causing the array to play rests after a certain number of times.
8.times do play [60, 70, 80, 90].tick sleep 0.5 end
Other times it would be a ring that would have several values in it but only would repeat for 3.times which would then not play all the other parts in the ring.
3.times do play (ring, 67, 48, 77, 89, 102, 103, 116).tick sleep (ring, 0.75, 0.25, 0.05).look end
This is an example of feedback I provided to the students who made this example
You do a good job using a mix of scales and rings. Be aware that when using a ring in a repetition block (3.times do/end) You should repeat at least as many times as you have notes in the ring. For example, you had (ring, 67, 48, 77, 89, 102, 103, 116) but inside a 3.times do block. This means only the first 3 notes of your ring (67, 48, 77) are going to play.
While I try to be specific with the feedback I give, I am not sure how much it registers with the students after the fact. Usually at least one week, if not more, has passed from submitting the project to when they get the feedback, so even a specific example like this might not make sense since they probably don’t even remember what their code looked liked.
Also in the interest of time, I try to keep things moving on to the next concept since we only meet once a week and I don’t want them to feel like we are spending weeks and weeks on the same topic because they will get bored and disengaged. This is something I have been struggling with throughout the year and not just within using Sonic Pi. I always try to provide actionable feedback for students to improve upon their work. This is something that my administration has put time and effort into having all teachers do. They are very big on “next steps” in terms of how you are providing feedback to students. The issue for me is that most of my next steps are specific to the project we just completed and not always relevant to where we are going. In Sonic Pi, I do feel that any feedback can be relevant since we are not just going to abandon functions or arrays moving forward. It is all about adding to the students’ toolbox of concepts and commands they can use in their code. But I don’t know if the specific feedback they receive resonates enough with them to remember to apply it later on.
One thought I have had is to have students go back and make changes to their code based on the feedback they have received, listen to the difference after making the changes, and make some sort of reflection on how the changes affected their code. This would provide them with some accountability on using their feedback. This is something else my administration has been pushing: making sure students are using the feedback so that you are not just wasting your time writing it all out and then it goes completely unused by students because there is no system put in place to have them apply it. Since I have more recently been having them submit code at the end of each class, I have also considered having them quickly go back to that code at the beginning of the following class and read the feedback and make the changes. Since I am using Google docs, it is very easy to make comments that reference specific parts of the code, then have the students fix the code and close out the comments. Google docs is very good for checking edits that have been made to the document and alerting me to when the comments I have made have been closed out.
My main concern is that this type of exercise will cut into moving forward with new concepts as students can be somewhat slow to do this type of work in class. Some because they don’t understand what the feedback is asking them to do and need more guided instruction, some because they are just lazy and will stretch a seemingly simple correction to take way longer than it needs to. I also know that implementing this type of routine midyear can be difficult and take a while to solidify. I might experiment with it for one or two assignments to see how it works out. From there, depending on how successful it is, both in terms of time and efficiency as well as how much of an impact it has on their actual code in the future, I may implement it as part of the class when I start over again next year. Keep in mind, this is my first year teaching Sonic Pi, so I am doing everything for the first time. It has been a great learning experience and as I am constantly looking back and reflecting on the process, I can refine the overall curriculum to make it more successful for teaching it the next year.
With that said, please consider becoming a Patreon support of @samaaron to ensure that Sonic Pi will be around for me and countless others to teach to students in the future.