Monday, February 23, 2015

Elementary Music and Sonic Pi Drum Loops

We are going to investigate drum beats and learn a little programming. If you don't have Sonic Pi installed, you'll need to have that done.

Paste the following code into one of the Sonic Pi workspaces, and click Run.


# Drum loop one, half notes
beat_length = 0.25

4.times do
sample :drum_heavy_kick
sleep beat_length
sample :drum_snare_hard
sleep beat_length
end

This is a basic drum loop. Let’s look at the parts of the code line by line.
  1. The # symbol means that anything on the rest of the line is a comment. It’s for humans to read, the computer ignores it.
  2. We’ve made a variable named beat_length that means a value of 0.25. We’ll use this a few times later.
  3. This line is blank so we know that there is something different coming next.
  4. Here we are creating a loop that will do something four times.
  5. This plays a sample (recording) of a kick drum.
  6. The command sleep means to rest for a certain amount of time (in seconds). It will rest for the time stored in the variable beat_length.
  7. Play a different sample, this time a snare drum.
  8. This tells the computer that it is the end of the loop that started on line 4.


Now lets try adding a few things to the code to make it look like this:


# Drum loop two, quarter notes
beat_length = 0.5

4.times do
sample :drum_heavy_kick
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length
end


When you click Run you’ll hear high hat cymbal playing at the same time as the kick and snare drums.


Bars of music often have four beats in them, so let’s change it to this and it will play four bars with four beats in each:


# Drum loop three, quarter notes
beat_length = 0.5

4.times do
sample :drum_heavy_kick
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length
sample :drum_heavy_kick
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length
end


Now try changing the value in the beat_length variable to 0.25 or 0.7, and try replacing some of those samples with different drum samples:
sample :drum_heavy_kick
sample :drum_tom_mid_soft
sample :drum_tom_mid_hard
sample :drum_tom_lo_soft
sample :drum_tom_lo_hard
sample :drum_tom_hi_soft
sample :drum_tom_hi_hard
sample :drum_splash_soft
sample :drum_splash_hard
sample :drum_snare_soft
sample :drum_snare_hard
sample :drum_cymbal_soft
sample :drum_cymbal_hard
sample :drum_cymbal_open
sample :drum_cymbal_closed
sample :drum_cymbal_pedal
sample :drum_bass_soft
sample :drum_bass_hard


Cool, eh.


Next we’ll try some different rhythms by playing some samples halfway between beats. If each beat before was a quarter note, these would be eighth notes (because half of a quarter is an eighth). Listen to the kick drum:


# Drum loop four, quarter and eighth notes
beat_length = 0.5

4.times do
sample :drum_heavy_kick
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length/2
sample :drum_heavy_kick
sleep beat_length/2
sample :drum_heavy_kick
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length
end

That seems to be getting a little long, though, let’s try the same thing with a loop:


# Drum loop five, another loop
beat_length = 0.5

4.times do
sample :drum_heavy_kick
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
2.times do
  sleep beat_length/2
  sample :drum_heavy_kick
end
sample :drum_cymbal_closed
sleep beat_length
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length
end


Not much shorter, but hopefully you get the idea. We two spaces at the beginnings of lines 11 and 12 to show that they belong to a different loop. The computer ignores the spaces, but it makes it easier for other people to read your code. If you want to learn more about code style in this language, check out the Ruby Style Guide.


Getting back to loops, though, try this:


# Drum loop six, another loop
beat_length = 0.5

4.times do
3.times do
  sample :drum_heavy_kick
  sample :drum_cymbal_closed
  sleep beat_length
end
sample :drum_snare_hard
sample :drum_cymbal_open
sleep beat_length
end


You can see that on the first three beats we played the same samples, then different samples on the fourth beat.


Now let’s try some functions.


# Drum loop seven, with functions
beat_length = 0.5

def kickAndClosed
  sample :drum_heavy_kick
  sample :drum_cymbal_closed
end

def kickAndOpen
  sample :drum_heavy_kick
  sample :drum_cymbal_open
end

4.times do
3.times do
  kickAndClosed
  sleep beat_length
end
kickAndOpen
sleep beat_length
end


First we define two functions (using the term def) and then we can call them by their names to get them to do their thing. A function is just a set of instructions that you can reuse later. You might also hear them called methods, procedures, subroutines, or callable units.


Let’s try something with parameters.


# Drum loop eight, with parameters
def play_a_beat(chosen_sample, beat_length)
  sample chosen_sample
  sleep beat_length
end

4.times do
  play_a_beat(:drum_cymbal_closed,0.25)
end


The variables chose_sample and beat_length are passed to the function when it is called.


Now see if you can figure out what this next section of code will do, and then run it to check if you’re right.


# Drum loop nine, nested functions
def cymbalClosed(beat_length)
  sample :drum_cymbal_closed
  sleep beat_length
end

def loop_this(n)
  n.times do
  cymbalClosed 0.25
  end
end

loop_this 16


One more thing, if you want your beat to go on forever, or until you stop it, try this.


# Drum loop ten, in_thread
beat_length = 0.25

in_thread do
  loop do
  sample :drum_heavy_kick
  sample :drum_cymbal_closed
  sleep beat_length
  sample :drum_snare_hard
  sample :drum_cymbal_closed
  sleep beat_length
  end
end


So now you know the basics of creating beats in Sonic Pi. Show your friends.


If you’d like to play with electronic drum machines and make different rhythms, check out free drum machines such as:
DMach (Android)
Hydrogen (Windows, Mac, or Linux)
GarageBand (iOS or Mac)
HammerHead (Windows)

Wednesday, February 18, 2015

what I'm up to these days

A while back I had been blogging daily about what I do, but had found that I seemed to then gravitate towards tasks that I could accomplish easily and then write about at the end of the day.

Instead, I'm going to occasionally write about some things I'm working on. This will include work-related things as well as tasks and projects related to the Masters in Education that I'm hoping to have completed by April 2016.

One of the bigger work-related projects I'm working on these days is open data. We are working on getting some of our data on Strathcona County's Open Data Portal, as well as taking data that we already release and posting it in a more accessible format. We are also interested in getting teachers and students utilizing open data. As I write this, International Open Data Day is coming up soon.

On a somewhat-related note, we're also looking at Open Badges to highlight professional learning among staff in EIPS.

In terms of ongoing work in EIPS, I wrote up a list the other day of things we are often talking to staff about these days.
And a few things on my to do list at work:
  • publish to do list
  • plan Scratch Day
  • Moodle migration
  • automate creation of Google Apps users from PowerSchool
  • build a Minecraft server image with a web-based (or VNC) control panel
  • help plan summer school technology camps
  • explore web-based project management ideas
And a little Python script I wrote today to translate addresses into latitude and longitude coordinates:

Hopefully next time I'll write about some course-related things that are in progress.

Saturday, February 14, 2015

Datalogging to the Web with Python, Requests, and Phant

wikimedia.org
I've been looking at various ways of logging data to a web-accessible location, both for students and for my own learning. I think I've come across the simplest and most elegant way of doing this, using data.sparkfun.com (a free data logging service based on their phant engine).

Basically there are three parts to this, setting up the phant storage location, getting the data, and pushing it to the web. Aside from the hardware setup, this all should take about five minutes.

To set up the data storage location, visit data.sparkfun.com/streams/make and enter the appropriate information. Title and Description are required, and the Fields are the things you will be recording (e.g. humidity and temperature). You can change these later. For more information, check the documentation.

After you click Save, it is very important to make a note of the provided values since this is the only time you will get to see them. Copy them to a document and also use the "Send yourself a copy of your keys" option at the bottom of the page.

So now you have a free, Internet-accessible place to log your data. Of course if you'd like, you can even set up your own phant server.

Step two is developing a way to collect data. This could be something like a barometric pressure sensor connected to an ESP8266 module, a button connected to the GPIO pins of a Raspberry Pi, or data that are already available on the Internet. For this post, we'll use weather data from openweathermap.org.

Step three is to push the data. I like Python and I've recently discovered the excellent Requests HTTP library. If you're using a Chromebook or you don't want to bother setting up Python 2.7 and installing that library, you can use c9.io.

Assuming that you have Python 2.7 set up and the Requests library installed, here's some code that will log the current atmospheric pressure.


And there you have it, a few minutes to set up and a few lines of Python to start logging data to the web. Next I'd like to see this all done with a sensor or two connected directly to an ESP8266 module.