Chapter 14

Making Music with Sonic Pi

In This Chapter

arrow Playing notes and melodies using Sonic Pi

arrow Creating random computer-generated music

arrow Adding samples to your compositions

arrow Synchronizing your tunes with drumbeats and samples

For much of the music we hear today, computers are at least as important in the studio as microphones are, and they have been for many years. Using Sonic Pi, you can start composing your own computer music by programming your Raspberry Pi. It enables you to put together simple programs that play synthesizer melodies and sampled sounds, generating your own distinctive instrumental music.

Sonic Pi is based on the Ruby programming language, so it works differently than the Python code you’ve become familiar with in the last couple of chapters. It uses some of the same ideas you saw there and in Scratch, however, including loops and lists (here in the form of arrays). We don’t have space in this book to teach you the Ruby programming language, but we can give you some examples that you can experiment with and modify to make your own musical programs. If you’ve completed the chapters on Python, the syntax might look strange, but what it’s doing should feel intuitive.

Sonic Pi runs from the desktop environment (see Chapter 4) and is pre-installed in Raspbian.

You run Sonic Pi by clicking the Programs Menu button in the bottom-left of the screen, clicking Programming, and then clicking the entry for Sonic Pi. There is also a large icon on the desktop you can double-click.

Understanding the Sonic Pi Screen Layout

Figure 14-1 shows the screen layout for Sonic Pi. You might see some differences between your screen layout and ours, but the fundamentals should be the same. Click to enlarge the window if necessary (see Resizing and closing your program windows in Chapter 4). On the left is the Programming panel, where you type in your code. On the right is the Output panel, where Sonic Pi tells you what it’s doing as it plays your music. At the bottom is the Help panel, which is opened and closed by clicking the Help button in the top right.

9781118904916-fg1401.tif

Figure 14-1: The Sonic Pi screen layout.

Sonic Pi uses eight different workspaces, which you access by clicking the tabs at the bottom of the Programming panel. You can think of each workspace as being like having a different file open for editing, but you can play music from different workspaces at the same time. This can be particularly useful for live performance: You might set up a loop in one workspace and then experiment with code to add notes on top in another workspace. When you exit Sonic Pi, the content of your workspaces is saved for you, and it’s loaded when you come back again.

At the top of the screen are buttons to run your program (play your music) and stop it. They use symbols similar to any audio player: a triangle to play and a square to stop. There are also buttons to adjust the text size, fix the alignment in your code, show the info screen, and show the help panel at the bottom of the screen.

There is also a Preferences button to the right of the Help button. It doesn’t fit on our screen, so we have to press the double-arrow symbol beside the Help button to find it. The Preferences panel provides a volume control and enables you to force the audio output to go through headphones or through the HDMI cable.

Playing Your First Notes

Click in the Programming panel and type the following:

  play 60

Nothing happens because you’ve entered your program but haven’t run it yet. Click the Run button and you will hear a middle C note sound. At the same time, you’ll see the Output panel update.

tip.eps The note numbers used are standard MIDI note numbers, widely used in electronic instruments. You’ve already seen them in Scratch. Higher-sounding notes use higher numbers, and lower-sounding notes use lower numbers.

Try adding some more notes to your program:

  play 60
play 64
play 67

When you click the Run button, you still hear just one sound, but three different notes are playing at the same time. It’s actually a C chord you hear, which uses the notes C (60), E (64), and G (67). If you want to play the notes separately, you can add a pause between them using the sleep command:

  play 60
sleep 0.5
play 64
sleep 0.5
play 67
sleep 0.5
play 72

We added an extra higher C note on the end of that sequence to make it sound like a fanfare. You can experiment with writing your own tunes. Just put together a sequence of notes.

Table 14-1 shows the standard MIDI notes, which run from 0 to 127. In practice, they sound extremely tinkly at the high end and descend into indistinct soft thuds at the low end. For best results, we recommend you keep your numbers between 48 and 96, but feel free to experiment to find out what sounds good to you.

1401

As you can see, the numbers in the table go from top to bottom, and from left to right. Notes get higher as you go down the table and as you move from left to right across the columns. The next highest note after B (at the bottom of the table) is the C at the top of the next column to the right. It’s like a piano, where the same key layout (running from C to G, then A to B, and then starting from C again) repeats all the way along it.

tip.eps If you don’t know much about music, stick to the notes that don’t have a # on them and avoid too many huge leaps. Try moving a few notes up or down a column and dip into a neighboring column when you’re near the top or bottom of your column. By following those simple guidelines, you should end up with a jolly little ditty.

Writing Shorter Programs

There is a more efficient way you can play a sequence of notes and specify the time, in seconds, between each one: Use the play_pattern_timed command. Click a tab to go to a new workspace and try this:

  play_pattern_timed [60, 64, 67, 72], [0.5, 0.5, 1]

Pay careful attention to the brackets and commas here. This command takes two different sets of information, and each set is between square brackets. The first set is the notes you want to play, and they are the same notes as we used in our fanfare earlier. The second set of information is separated from the first set by a comma, and it is the length of the pause between the notes. There are four notes but just three gaps between them, so the second set of brackets has fewer items in it. The numbers we’ve used here put a half a second pause between the first and second notes, and the second and third notes, but double that to build up the suspense (such as it is) before the final note sounds.

Composing Random Tunes Using Shuffle

The bracketed sections are Ruby arrays, similar to lists in Python. You can add different methods to the arrays to change the order of the items in them. For example, try this, using the reverse method:

  play_pattern_timed [60, 64, 67, 72], [0.5, 0.5, 1]
play_pattern_timed [60, 64, 67, 72].reverse, [0.5, 0.5, 1]

You’ll hear the notes of the fanfare played forward and then backward, but with the same timing each time. You can use the shuffle method to hear a random tune. Try this:

  play_pattern_timed [60, 62, 64, 65, 67, 69, 72].shuffle, arr.eps [0.5, 0.5, 1, 0.5, 0.5, 1]

We’ve used a simple rhythm there, two short notes and then a long note. You might have noticed that we added a pause after the final note too. It’s a cheery melody, but it’s a bit short, so get Sonic Pi to repeat it. Here’s how:

  4.times do
  play_pattern_timed [60, 62, 64, 65, 67, 69, 72].shuffle, arr.eps [0.5, 0.5, 1, 0.5, 0.5, 1, 2]
end
play 60

We’ve wrapped our tune playing code in a loop that repeats it four times. The start of the loop is 4.times do and the end of the repeating section is marked, appropriately enough, with the word end. We indent our musical code by two spaces to show it’s the part that is to be repeated. If you want to repeat more or less than four times, change the number 4 at the start.

We made two other changes here too: First, we added a timing value for the last note in the sequence. It’s the 2 that has sneaked inside the last square bracket. We’ve also added a final note, C. Whatever randomness happens in the rest of the tune, this sequence of notes always sounds good when it ends on a C because all the notes in the sequence are from the C major scale.

Using Array Names in Your Programs

The arrays of notes and values can make your program look cluttered, but you can tidy it up by giving the arrays names. That makes it easier to reuse them too. You can streamline your previous program like this:

  note_pitches = [60, 62, 64, 65, 67, 69, 72]
note_timings = [0.5, 0.5, 1, 0.5, 0.5, 1, 2]
4.times do
  play_pattern_timed note_pitches.shuffle, note_timings
end
play 60

Using Threads to Play Accompaniments

Threads are different bits of program that run at the same time. We can write two different pieces of code to play music, and have them play together, if they are in different threads. We can use different synthesizer sounds too, to create a richer accompaniment. Try it out with this program:

  note_pitches = [60, 62, 64, 65, 67, 69, 72]
note_timings = [0.5, 0.5, 1, 0.5, 0.5, 1, 2]

in_thread do
  use_synth :zawa
  4.times do
    play_pattern_timed note_pitches.shuffle, note_timings
  end
  play 60
end

in_thread do
  use_synth :saw
  2.times do
    play_pattern_timed note_pitches.reverse, note_timings
    play_pattern_timed note_pitches, note_timings
  end
  play 48
end

That program uses two threads. The first thread is the same as your previous program, and plays the notes in a random sequence four times. The second thread takes those same notes, but plays them first in reverse order (going from high to low), and then in their real order (from low to high), and then repeats that. The final note in that thread is a lower C.

We’ve used two different synth sounds here, so it’s easier to hear the different parts of the music: zawa and saw. To get a full list of the synths available, click the Help button at the upper right of the screen and then click the Synths tab in the bottom left. If it’s not shown, use the arrows next to the help tabs to show it first.

Playing Random Notes

You can play random notes, like this:

  lowest_note = 60
note_range = 24
play lowest_note + Random.rand(note_range)

In that program, lowest_note and note_range are variables. You can change the numbers after them to change the random note chosen. For example, if you want to pick one of three notes starting with F, change the lowest_note to 65 and the note_range to 3. Each time you run the program, you get a different note. This uses the Ruby language to produce a random number.

Sonic Pi also offers a way to get random numbers in a repeatable fashion. That is, you let the computer pick the notes to play, but each time you run the program, it generates the same random numbers, so the music sounds the same. This example invents a melody for you, but always plays the same tune:

  lowest_note = 60
highest_note = 84
6.times do
  play rrandi_i(lowest_note, highest_note)
  sleep 0.5
end

The problem with generating totally random numbers is that not all notes sound good together. In this chapter, we’ve been using the notes from the white keys on the piano (the scale of C major) and none of the sharp notes. When you start throwing in sharp notes randomly, it can start to sound too chaotic. An alternative way to pick a random note is to create an array of the notes you like (the scale of C major we’ve been using so far) and then use the Ruby sample array method to pick a random note from it. Here’s an example:

  note_pitches = [60, 62, 64, 65, 67, 69, 72]
loop do
  play note_pitches.sample
  sleep 0.2
end

That program uses a loop that repeats forever, so it’ll keep improvising until you click the Stop button. Each time you run that program, you get a different sequence of notes.

Sonic Pi has an approach you can use to randomly pick numbers from the array in a repeatable fashion too, similar to the way rrand_i() works for picking random numbers. To use it, replace the play line in the code above with:

  play choose(note_pitches)

remember.eps The Output panel shows you the note numbers that are played, so you can use this to see which notes are being chosen and check to make sure that your program is behaving as you expect.

warning.eps Later in this chapter, we talk about snippets of music called samples. Don’t get confused by the sample array method we’re using here in Ruby, which picks a random item from your array.

Turning Names into Music

Ever heard a song on the radio and thought it was written just for you? Well, it wasn’t, but thanks to Sonic Pi, you can have a piece of music personalized for you, or at least lay claim to your very own jingle.

This short program takes a name and turns it into music. In the software, letters are represented by numbers, called ASCII numbers. You can get the ASCII number for each letter in a word, and then play it as if it were a MIDI number, effectively turning letters into notes and words into tunes.

The program actually plays two notes: One is the note from your name, and the other is the same note plus 12, which is an octave higher. This shows how you can use mathematics to generate a richer sound:

  name = "Karen"
name.each_byte do |note|
  play note
  play note + 12
  sleep 0.25
end

Using Note Names

MIDI notes are great because you can use sums to generate music with them, but if you’re more musically inclined, you might prefer to use the proper note names. Sonic Pi enables you to do that by using the name of the note (a letter from A to G), plus the number of the octave it’s in. You can see those numbers labeling the columns in Table 14-1.

For example, to play a middle C, you can use

  play :c4

To play the B one note before it, which is in the next lowest octave, you would use

  play :b3

The Output panel shows that Sonic Pi plays notes 60 and 59 respectively. You can check the note names and numbers in Table 14-1 to confirm that this is what you expected.

You can also use names to play chords. You tell Sonic Pi the lowest note in the chord and can optionally add if you want the chord to be a minor chord. Try this:

  play chord(:a3)
sleep 0.25
play chord (:a3, :minor)

In each case, it plays three notes at the same time. If you look at the note numbers in the Output panel, you can see that the middle note was one pitch lower in the second chord because it’s a minor chord. Again, you can use Table 14-1 to check the note numbers Sonic Pi displays against the musical note names.

Using Samples

The programs you’ve made so far are an interesting way to explore computer music, especially when the computer starts surprising you with its random compositions.

It doesn’t sound like proper recorded music, though. Sonic Pi also has the capability to use samples, which are short snippets of music that you can manipulate, such as by changing their speed or adding effects to them. Sonic Pi includes more than 70 samples, and you can see a list of them by clicking the Help button and then using the tabs in the bottom left to see the samples. Use the arrow to scroll the tabs if the one you need isn’t showing.

Here’s one of our favorites:

  sample :loop_industrial

You can speed it up or slow it down by changing its rate. Here’s how you make it play at half its normal speed:

  sample :loop_industrial, rate: 0.5

warning.eps Take care with where you put spaces around colons. The program won’t work if you put a space between the colon and the sample name.

We can repeat that sample to make a continuous rhythm. Like we did when we were playing notes, we use the sleep command to put a pause between each repetition. Samples can be different lengths, however, so Sonic Pi provides a feature in the language to find out how long a particular sample is, called sample_duration. You can use it like this:

  loop do
  sample :loop_industrial
  sleep sample_duration :loop_industrial
end

If you change the rate of your sample, remember that your sleep duration needs to change too. If you play your sample at half speed (0.5), it’s going to take twice as long as usual to finish playing. That means you need to sleep for twice as long as the sample duration. To perform calculations like this, use a variable to store how long Sonic Pi should sleep for between each sample playback.

  drum_rate = sample_duration :loop_industrial
drum_rate = drum_rate * 2
loop do
  sample :loop_industrial, rate:0.5
  sleep drum_rate
end

In that program, we set the variable drum_rate to be equal to the length of the sample, and then double it because we’re playing the sample at half speed.

Adding Special Effects

You can play a sample and add effects to it, including distortion, echo, and reverb. There is a full list of effects (also known as Fx) in the Help pane. This is how you add distortion to one of the guitar samples:

  with_fx :distortion do
  sample:guit_e_fifths
end

Synchronizing with Your Drumbeat

You now know how to play a repeating rhythm, and you can use threads to play other samples and synth melodies on top of it. One of the tricky things is to synchronize all the threads so they play to the same rhythm. Sonic Pi provides two commands you can use for this, cue and sync. They work a bit like broadcasts in Scratch (see Chapter 10).

The cue command sends a message to all the threads, and the sync command pauses a thread until it receives a particular message. We can use these commands to synchronize threads with a drumbeat. Here’s an example:

  in_thread do
  drum_rate = sample_duration :loop_industrial
  drum_rate = drum_rate * 2
  loop_number = 0
  loop do
    loop_number = loop_number + 1
    puts "Loop number " + loop_number.to_s #Displays arr.eps loop number
    cue :cymbals_begin if loop_number == 3
    cue :loop_start
    sample :loop_industrial, rate: 0.5
    sleep drum_rate
  end
end

in_thread do
  sync :cymbals_begin
  4.times do
    sync :loop_start
    sample :elec_cymbal
  end
end

In that program, the first thread plays the loop_industrial sample forever. Just before each playback, it sends the message loop_start to all the other threads. Threads can choose to wait until they get that message, and you can use a different message name if you prefer.

It also uses the variable loop_number to keep track of how many times it has repeated its loop. If this is the third repetition, it sends the message cymbals_begin, which is used to cue in the cymbals.

The second thread waits to receive the cymbals_begin message before it does anything else. That means it doesn’t play anything until loop_industrial has played two times. Then it plays the elec_cymbal sample four times, synchronized with the start of the loop_industrial sample. The effect is of the drums starting first, and then a cymbal comes in on the first beat in the bar.

You can use this technique to synchronize different samples and synth patterns and build up a piece of music. The following program uses a sample for the drums, two guitar samples, and a synth melody, all in separate threads. They’re synchronized with the drumbeat using the cue and sync commands.

  # Showroom Dummies (minimal)
# Music example from Raspberry Pi For Dummies, 2nd Edition

in_thread do
  drum_rate = sample_duration :loop_industrial
  drum_rate = drum_rate * 2
  loop_number = 0
  loop do
    loop_number = loop_number + 1
    puts "Loop number " + loop_number.to_s #Displays arr.eps loop number
    cue :guit_e_begin if loop_number == 5
    cue :melody_begin if loop_number == 9
    cue :slide_begin if loop_number == 19
    cue :loop_start
    sample :loop_industrial, rate: 0.5
    sleep drum_rate
  end
end

in_thread do
  sync :guit_e_begin
  loop do
    with_fx :distortion do
      sample :guit_e_fifths
    end
    2.times do
      sync :loop_start #Gap before repeating this part
    end
  end
end

in_thread do
  sync :melody_begin
  loop do
    note_pitches = [67, 62, 64, 64, 67, 62, 64, 67, 62]
    note_pitches.each do |note|
      use_synth :saw
      with_fx :wobble do
        play note
        play note-12
      end
      sync :loop_start
    end
    7.times do
      sync :loop_start #Gap before repeating this part
    end
  end
end

in_thread do
  sync :slide_begin
  loop do
    with_fx :echo do
      sample :guit_e_slide
    end
    4.times do
      sync :loop_start #Gap before repeating this part
    end
  end
end

Anything after a # symbol on the same line is a comment, to help you see what the different bits of program do. The guitar samples don’t start immediately: The guit_e_fifths sample waits until the drum loop has played four times before coming in at the start of the fifth drum loop, and the guit_e_slide sample waits until after the synth melody has played before coming in. The effect is of the music gradually building up, but each part of the music starts in sync with the drumbeat because they’re all taking their timings from its cue command. For an extended version of this music, visit Sean’s website at www.sean.co.uk.

This program also introduces a new technique you can use for playing music in Sonic Pi. The notes for the synth to play are stored in an array called note_pitches, and a loop plays each note in turn. The following line sets up a loop that goes through the array and takes each item in it in turn and puts it into the variable note:

  note_pitches.each do |note|

If you have a particular melody you want to play and you want to synchronize with a rhythm or do other fancy things with the notes, this code enables you to do that.

We hope that this chapter has inspired you to experiment with making music on the Raspberry Pi. You’ve learned how to play melodies using different synths. You’ve also discovered several different ways to create improvised music, using random note numbers, random notes picked from an array, or by converting words into music. We’ve shown you how to bring it all together, too, combining effects and synth melodies and synchronizing them to a drumbeat. Using the code in this chapter, and the rich range of samples and tools that Sonic Pi provides, you can compose your own music. Whether you like dance, prog, pop, or rock, Sonic Pi deserves to be in your band.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.81.232