Transcripts
1. Course overview: Welcome to make music with code, the complete guide to
code them as Sonic Pi. This fun course is aimed at
musicians with little or no coding experience and
will teach you how to compose and perform music using
code is your instruments. My name is Steven Moffat and
I'll be your instructor. I've been writing
software and creating music for over 30 years. And during that
time I've learned, worked in and
taught over a dozen different programming
languages in this course, which contains over four
hours of video lessons, you'll learn how to use a hugely popular and free
Sonic Pi framework. You will cover everything
from the very basics of programming to use
in Sonic Pi for sound design and live
performance with in-depth and detailed
explanations and examples. At every stage, you'll
learn how to create music by coding musical patterns
with since and samples. Fundamental programming
concepts including program flow and Sonic Pi is
built-in data structures. How to create a drum sequencer
and looping melodies, chord progressions and
baselines from scratch. How to use filters and ADSR envelope for
code-based sound design. The use of randomization
algorithms to create generative music. How to add effects
such as distortion, delay and reverb to make your sounds that much
more interested. You'll learn how to control
midi and audio from your code and integrate them
into your performances. By the end of the course,
you'll be able to apply what you've
learned to create unique musical compositions
and perform live using code. And you'll see that anyone
can learn to program. I'd take each new concepts step-by-step and it really
is much easier than you think the course is aimed at musicians
wishing the gain some programming
knowledge using code as an instrument
for composition, inspiration, recording,
and live performance. You don't need any prior
coding experience or deep knowledge of mathematics
or computer science. Or you need is some basic
musical concepts such as note, scales, chords and rhythm. And a Windows mac or
Raspberry Pi computer. So join in and learn how to use code to create any
music you can imagine. And perhaps even some you can't.
2. Introduction: Hi there and welcome to this course where we're
going to look at using code to make music both for live performances and
for our compositions. So I've assumed absolutely no prior programming knowledge
at all for this course. This course is very much aimed at musicians who would like to use code to compose
and to perform music, or introduce each programming
concepts step-by-step. We'll take it nice and
slowly and there'll be plenty of opportunity
for practice. Now there are some
things you should have to get the most
out of the course. The first of those
is a computer. Now, any Windows, mac or Raspberry Pi computer
will be absolutely fine. The second thing is some
basic musical knowledge. Now we're not talking
advanced music theory here, but as long as you've
got knowledge of notes and scales and octaves, these kind of concepts, then you'll be absolutely fine. And lastly, I would definitely recommend that you
listened to the course on a good pair of headphones or
a good stereo speaker setup. This is to make sure that
you are able to hear the nuances of some of the changes to the
sounds that we create. So with that in
mind, grab yourself a coffee, and let's
dive right in.
3. Getting Sonic Pi: Now the software we're going
to use with this course is the fantastic Sonic Pi, which was created by
Sam Aaron is become hugely popular in
the algorithm scene. And it's a music
framework based on Ruby, which is a programming language. Don't worry about that too much, but it might be interesting
to you if you've got some pass codes and experience, Sonic Pi runs on Windows and Mac and as the
name suggests, actually is designed to run particularly well
on a Raspberry Pi. So let's head over to
the sonic Pi website and see how we go about downloading
and installing them. Here we are on the Sonic Pi
website and here you can see there's buttons here
to download for Windows, for Mac OS, and
for Raspberry Pi. But there's so much
more to this website. So I would definitely
encourage you to get involved
with the community. Look at the examples, read
through the tutorials. There's lots of
great info on here. Now, Sonic Pi is
available free of charge. It's hugely popular in education for teaching
kids to code. But it requires a
lot of maintenance. And Sam has been doing this
free of charge for years. So if you can afford it, I definitely recommend
you just do scroll a little way down the website
and either use patria and, or GitHub Sponsors to donate a little bit
of money to Sam, whatever you can afford
in order to keep this fantastic initiative going.
4. Getting to know the Sonic Pi user interface: Okay, so once you've
got Sonic Pi installed, go ahead and run it and you
should be presented with a screen that looks
something similar to this. Don't worry if it doesn't
look exactly like this. I'll be showing you
how to configure the screen in this session. So let's walk through each
part of the UI step-by-step. So the main part of
the screen is taken up by the code window. This is where we actually type the code and this is where
we can run it from two, using these buttons up here
that run on the Stop button. So once we've finished
with our code, once it's, once the code is complete,
we can hit the Run button. And here the results. If the code is running
for a long time, we want it to stop. We can press the stop button. If we want to record
the output of the code, either music that
regenerated with the code out to a WAV file. We can press Record button and then run the code and we'll, we'll get a audio file produced. We can save and load our code. Now by default, Sonic Pi is going to persist your
code between sessions. What I mean by that
is if you type some code into Sonic Pi
and then quit Sonic Pi, next time you come back in, that code that you
had there previously, will be there and available
for you on the screen. So it's got its own
built-in save mechanism. However, I wouldn't rely on that if you've got a
piece of code that is, you're particularly
proud of or is a piece of completed
composition, or it's something that
you want to share with your friends or share with
somebody in the community, then definitely use,
use the buttons there to save your code to make
a good backup copy of it. Again, once you've got
a code or a piece of code that you want to load back in a file that
you want to go back in, you can just do that through the load button.
Down at the bottom. We've got these
numbers 0 to nine. These are different. You can think of
these like tabs so that they're called
buffers within, within Sonic Pi, we can think
of these as separate tabs. Whenever we click
the Run button, we're going to run the
code within this buffer. So if I'm here at the moment, if I click run and I'm going to run the code within buffer one. If I click over here,
now in buffer six, I'm going to run the code
that's in buffer six only. Top right, then we've got
two controls to control the size of the font
in the code window. And I'll be using these later on to make the code nice and big so that you can follow
along nice and easily. Let's go, Let's have a look at the rest of these
over here then. So the first is the scope. So this, this this panel up here on the top
right is the scope. And this by default is
set as a spectrum graph. You'll see this as we start to generate some noise
in the next lesson. But this can be changed
through the preferences panel and I'll show you how
to do that in a second. This next section here is
probably the most useful, useful puddle other than the code window, and
that is the log. And this is going
to show you exactly what's going on as
your code is running. And you can output things to the log as well to
get information. So this window is
particularly important. The cues panel will
show you what's actually happening
within Sonic Pi. This panel you'll
find particularly important when it comes
to live performances. Then down the bottom here across the
bottom of the screen, we have the Help panel. The panel has had a huge
amount of effort put into it. There are, there is
a full tutorial, there's links to other articles. There are example programs to produce different
types of music. There's information
about the bill incense, about the built-in
effects and samples. And there's information
there about the language itself
for you to go and look up absolutely fantastic help
facilities within Sonic Pi. So please, please do
have a dig around in there to switch each of
these panels on and off. I can just go and hit
this toggle buttons here. So I can, if I hit
the Help button, the highlight is removed
along with the health panel. When I click it again and the
Help panel will reappear. And the same for these other
three buttons up here. The one we haven't looked at
is the preferences panel. In here. We can just see a whole
bunch of different kind of configuration items within Sonic Pi will quickly
flip through these. We won't go through
every one of these in detail and we will be using
them throughout the course. But I'll just take
you through some of the important things are the settings that you might
want to use it early on. The first of these in the Audio tab then
is the main volume. And this just simply controls the output volume of Sonic Pi. But there's nothing else
in here that you really need to worry about just yet. Inside IO, then you
can see here that I've got a midi
keyboard connected, and that's really the only interesting thing
in here for now. Now, if you don't
have a midi keyboard, do not worry at all. You don't need one for Sonic Pi. And in fact, we'll
only be using it in a very small part of the course. But it's, it's
interesting to be able to create a sense sound,
for example, in midi, in sight Pi, and then play that sense with
your midi keyboard or other midi input device. But we're doing that much later, but don't worry
about it for now. This one you might want to
play around with a bit. This is configuring
the preferences for the code editor,
for the code window. And you can see that I've got it set on a
light theme here. I think it's nice and easy and easier for you to
read on this course. But if you prefer it in dark
mode, you could use that. And then there are
other different window types as we
go through here. I'm going to flip back
to the light theme here. And in here where we can toggle panels on
and off and we can toggle all the information that we want to be shown
within these panels. So over here we can see that the we're showing the line numbers were showing code completion, tabs, titles, buttons, etc. I'll leave all those
switched on for now, but feel free to go and configure this to be exactly
how you prefer to work. Individuals, then we can look at the different
types of scopes. I mentioned there are different
types of scopes in here. So by default is set
to the spectrum graph, but we have mono stereo
charts as independent scopes. There are the graphs which illustrate phase relationships,
all sorts in there. I prefer to leave mine
on the spectrum graph. These are not toggle, so you can have more than
one graph shown at once. But throughout this
course we'll leave it on the spectrum graph, but others may be useful to you. So over on the right here we
have the transparency panel, and this is controlling
the transparency of the Sonic Pi
interface itself. Now, by default it in 99% of cases you'll
leave this set a 0. But as I mentioned earlier, Sonic Pi has become
really popular in things like the
algorithms seen and people are doing live
performances with Sonic Pi, but they'll be up on the
stage and they'll project the Sonic Pi user interface on the wall behind them
or a screen behind them. And actually part
of the experience, part of the performance
is watching the, the person code live and hearing the music
and dancing alone. So what you can do is you could, you can set the transparency of the window here and
you might have some, some visual effects
on video or something running in the background
with Sonic Pi over the top with the
transparency set down a little so that Sonic Pi is showing up over
the top of the video. I'm very cool. In here. We can come in and
check for updates. I leave mine as to check for
updates every two weeks. But if you want to, you can go and hit the check now button and it will go and check for you right now whether
you need an update. And finally in the
language type, then you can go and set the language for the UI
and for the tutorial. So as I said, there's a thriving and fantastically friendly
community around sonic Pi. People within the
community of have translated the tutorials
and translated the UI. So if English is not
your first language and you prefer to use
your native language, then you can go and
select that in. Here. I'll click on the Close button
to shut this window down. One last thing I want
to show you here is just this info pane. And this is going to
show you a bit of a splash screen where you can get all sorts of
information about Sonic Pi. And you can see here is
a link to the website. There's a link to Twitter to follow for updates
about Sonic Pi. I would definitely
encourage you to do that. You can see here your
current version is, or my current version is 4.3. Just check that you're
on version 4.3 or above. If not, head over to the preferences panel and click Update to get
the latest version. Okay, So that's giving
you an overview of the user interface. Now it's time to
make some noise.
5. Lets make some noise!: So head over to the
code window here, I'm going to make
the font a little bigger so that you can see it. We're going to start off with perhaps the most simple program that we can possibly imagine. So I'm just going
to type straightens this Coburn note and I'm going to type the command play in. The command play is one of
the commands that we can use to tell Sonic Pi to
make some noise for us. So let's head over here
and we can do play 60. So just type play 60 into your code window and then
click the Run button. And there we are. So Sonic Pi is omitted
some noise for us. So I click the Run button up here to do this,
I'll do it again. But to save you reaching for the keyboard
and mouse over time, you can also press Command R on a Mac or Control R
on a Windows PC, and that will achieve
the same thing. So let's break this
down a little bit. So the command play
is, as I said, one of the commands and probably
the most useful command, or most used command
initially to tell a sonic Pi to
omit some noise. But what's the 60 about? Well, it's 60 is actually
a midi note number. So the way that midi
works is that there are numbers from 0 to 127, so 128 different midi notes. And each of those corresponds to a note name and
normal note names. So we can see here that
midi note number 60 is a C for a C note on
the fourth octave. And we can look over
here and we can see that actually midi note names correspond to a
frequency as we know that the higher the frequency,
the higher the note. So a C4 is 261.63 hertz. And then there are
others on here. So we can move up and down. Each increment or decrement
by one is a semitone. So from 60 to 61 takes us
from a C to a C sharp. From 61 to 62 texts
was two a d 263 takes us through D-Sharp that
corresponds up and down there. Now I've included a
full midi note char inside the resources
for the course. But for now it's just
important to know that we can either use a midi note
number or a midi note name. And at the moment we're
using midi note number 60. So when we run our
code is actually playing a C in the
fourth octave. So this is great and this are our first bit of sound out of, out of Sonic Pi, but it's not going
to make number one. So let's add some more code. So to add another line of
code, just hit return. And here I go. Let me make that a little
bit bigger for you. There we go. So to
add some more notes, I can just add some
more play commands. So let's type in a play 64. Let's add a play 67. Let's hit Run or, or
Command R. We are, so there are three notes
playing all at the same time. So that is a, C and E and a G. If we look at the midi notes are a C
and E energy was 606467, and that gives us
a C major triad. Now, all these notes
are playing at once. So what we're effectively
producing here as a chord, if I want to play these
notes in an ascending order, then I need to tell Sonic Pi to leave a little bit of time. I'll leave a rest
between these notes. And I can do that using
our next command, which is the sleep command. Now, so in-between
each nodes I'm going to add a sleep one. This is telling Sonic Pi
to sleep for one beat. Okay, So all of the timings within Sonic Pi or within beats. By default, the
beats per minute or the BPM for a sonic
Pi program is 60. So 60 beats a minute. So 60 beats per minute. If we sleep for one beat, then we are going to
sleep for 1 second. So let's add another sleep here. Again for one more beat, for one more bit.
And let's play it. And there we are. There's our 33
notes major triad, but this time arpeggiated, playing one note after another rather than as a single cord. So I can put anything I want to in terms of the sleep pair. So I could change these
to sleep for two. And this is going to
sleep for two beats. Or I could sleep for fractions
of a second as well. So I can sleep for half, half a beat or half a half a second because we're at 60
beats per minute. And I'll show you how
to change the beats per minute a bit later. There we are.
6. Using MIDI note names: As well as using the
midi numbers here, we could also use
the midi note names. So we can have exactly
the same thing here, but we can use the note
names IEEE C4, E4, and G4. So let's, let's try that. So if I want to use a
note name that I need to use a prefix it with a colon. So I simply hit here
the colon C four. I can use a mix, so I don't have to
choose one or the other. I could use C4 here and 6467. That'll work perfectly well, exactly as it was before. I sometimes prefer to use the note names when I know
what they're going to be. But the note numbers can be
really useful when we're doing more kind of
algorithmic work later on. Now, don't worry about that
for now it's a big word, but nothing to worry about. But you'll see that
midi notes can be, the numbers can be useful later. Let's change this to a C4. Sorry, this should be an a4, G4. And again, this is gonna give us that the major or C major triad. But what if I want to
use sharps and flats? While it's pretty easy to do. So if I want to use a
flatness, flatten the, flatten the third here and
this triad and make it into a minor chord, minor arpeggio. I use that just using
the lowercase b. Let me also change
that E into an E-flat. I can also use a, an S to denote a sharp. So if I wanted to say
instead of E flat, I wanted to say
D-sharp, same notes, but I could do that here, so I could just go a D. And we use the lowercase S for sharp on octave number four, where we are to change octaves. And if I want to
go down an octave, I could, I could just change
the optimal number here. And this will play
an octave lower. Again. It really, as you can tell, it really, really doesn't
matter what order I plane. So if I wanted to do an
inversion, for example, maybe I play the G first. So let's move that up there. This time I'll need to
put asleep in here. 2.5th. We can move this one from the end. And there we are. So have a play around
in there and produce some little short pieces of music just using the
midi note names, remembering that we use a
lowercase b for a flat, a lowercase s for a sharp, or you can use the midi
note numbers there. Have a play around, create
yourself a little tune. I'd use the sleeps to provide the rest between
notes that you want.
7. Code comments: So let's change this back. We'll put the sleep back here and play that G3 at the end. Loops. Again. Let's run that. Okay, so those are our C minor
triad, C minor arpeggio. So we might want to just
remember what we've called that. So let's go up here and we
can use the hash command or the pound sign or the
hash sign depending on whether which side of the
Atlantic you're from. We can use the hash sign to
say that this is gonna be a comment in our code and add a comment is just a piece
of text just for us. So it's not executed
by Sonic Pi at all. And we can type anything
we wanted here. So we could say, this
is a C minor arpeggio. As I say, that
code's not going to be executed by Sonic Pi, but it's just notes that we can put in the
code for ourselves. We refer to as a code comment. Again, if I, if I run this, it's completely ignored
by the sonic pie, but allows us to
put comments in. One of the thing
that's commonly done by programmers is to use comments just to tell a sonic Pi to just ignore
a piece of code for now. So if I wanted to experiment
with this and say, okay, well what happens
if I remove this sleep? Well rather than delete it
and then if I don't like it, I had to type it back in later. I can just go and put a
pound sign or hash sign at the beginning and run it again. And this time it's going
to ignore that sleep. We can see that it plays
a D-sharp and the G. At the same time. Again, if I don't like that, I just go ahead and
remove that comment. I'm about to how we started. Now there is a shortcut
key in Sonic Pi, a bit like the command R or
control R to run the code, there was a shortcut key, if I want to comment something out. And this is a really
good one to remember for live performances is you want to switch bits of code on and off. And I can press the Command
and the forward slash key, and it will add this little
symbol in the front. Now, it looks a
little bit different, but it works exactly the same. Two hashes and a pipe side. This just put in a comment
a little bit of the code. So wherever I am on a, on a, on a line of code, I can just press Command or
Control and forward slash. It will comment out
that line of code. And then when I run it on back to the to the court because
the sleeps have been removed. If I want to remove that
code comment again, I could just go back
again anywhere on that line and press command
and forward slash again, or Control and forward slash, and it will remove
that code comment. And then we are back
to our arpeggio.
9. Play options: So as well as using code to define the pitch of the
note we want to play, we can also add a
number of options. And you'll see these
throughout Sonic Pi options which allow us to customize the sounds
that are being produced. So we're going to start
with two simple ones which we can add to
the play commands. So let's, let's
create this down. And let's just add a
nice simple Play, 60. Okay, so that's going to play at the default volume for Sonic Pi. But part of music is the
dynamics of the music and the dynamics of music involved the volume at which the
notes are being played. So if we want to change out, then we can add an option to it. So for Sonic Pi, this is called the
amplitude option. So let's just add this. So if I hit a comma
and once I hit a comma after the
sixties allows me to add a number of
different options. The amplitude option or the volume option is
simply called AMP. And you can see
that here in the, in the code completion window. So Sonic Pi is, again try to help us out. So what's used? The amplitudes. So we'll say AMP and
then we say colon. And now we're going
to set the amplitude. The amplitude and Sonic Pi
is defined by a number, so 0 is no volume at all. One is the normal
default output volume, but we can go up from there too. So for example, if I
set the opportunity to nought 0.5 and press play, that has just been output at
half of the normal volume. Now it's very difficult to
hear that difference here. So let's add a little bit more
code to demonstrate that. So let's start off
with a play at 60. This is going to be
the default amplitude. Will sleep for two beats. And then we will play
this one at half volume. And you should be able
to hear the difference. Okay, So you can hear that second note was
definitely quieter. Let's add another sleep. And again, we'll play at 60, but this time we will play it
at twice the normal volume. We can set that as an
opportunity to an area. So very simple to set. It's important to remember
that the options that we set here only relate to the
note that we're playing. So they only relate
to this note. So if I just go and do another, another line here, I'll just out-of-plane play 60
with no options at all. So we can hear that line seven played just with the
default amplitude of one, which is exactly the
equivalent of typing that. But the, the, the
settings that we make, the options that we put on here, the amplitude
option in this case only relates to this note
that's being played. It doesn't set the amplitude for all future
nodes, for example. As well as amplitude
we have pan. So this is the second simple option that we're
going to look at now. And pan is simply setting the where the sound is going to appear within
the stereo field. Are you from, from left to
right, often called balance. So let's do this again, but let's, Let's
just start here. So we can say again, a play 60 by default is going to send
it right down the middle. So you're going to have an
equal amount of this note in the left and right speaker or the left and right headphone. So if I do another
sleep for two, this time, I'm going
to use the pan option. So I press a comma and
I'll say Pan colon. Now, pan in. Sonic Pi is set by a
value between minus 11. So minus one will give us a
pan all the way to the left. A one book gave us a pan
all the way to the right. A 0 will palette straight
down the middle, but I even an equal volume in
the left and right speaker. And those values don't need
to be minus one or one. They can be any value
between minus 11. So if I want it halfway
into the left speaker, then I can set the, the pan as minus
0.5, for example. Just to demonstrate this, let's pan to the left and right. So we're going to
cancel the left first. We will go straight
down the center, but pan to the left,
will sleep again. And we will pan all
the way to the right. We are fairly simple
and you can actually, if you look at the scope and the top right-hand corner
here, you'll see that. You'll be able to see
that reflected in the scope even if you're
not wearing headphones. So all the stuff
above the line is the left speaker and the stuff below the line in the graph
is the right speaker. I can combine these. So I could, I could then
do another color and say, I want to set the
amplitude as well. Cool. By typing apologies. So I can set the amplitude
of this one to be half. Like I said, the amplitude of this one to be twice.
Let's try that. We can hear, or perhaps you heard a little bit
of distortion there. I certainly did. With this one. You just have to be
a bit careful with the amplitude because
as you go across, go up to higher
volumes, you're gonna get some distortion in and cropping don't generally
tend to go above 1.52. Only on rare occasions
when you really want it for as part
of the composition. Okay, so that's it
for four options. In the next video, we're
going to talk very quickly about beats per minute.
10. Setting the tempo: Okay, so here we
have a bit of code which you should fully
understand by now. Just read through it and just make sure that you
understand it. But very quickly we're going to play a note at midi note 60. We're going asleep for one beat. Then we're going to play
another note at 60. We're going asleep for one
beat and then we're going to play a final note,
note number 60. Now, as I mentioned
briefly earlier, the when, when I set any kind
of duration and he options relating to
time within Sonic Pi, it is measured in beats. Now to keep this
nice and simple. So asleep here, for example, is it's going to sleep for one beat in between these nodes. Now, to keep this
nice and simple and to make the
maths nice and easy. By default, anything
that we play in Sonic Pi is set to
60 beats per minute. And this is done just to make the maths nice and easy
so that I can look at that sleep one and I can
think about that as being either a second or
being one beat, because 60 beats per
minute is the same thing. However, not a lot of music has produced a
60 beats per minute. So we need a way of being out of control what the
beats per minute. And I'm gonna just
gonna show you how to just very briefly. So all I need to do is go to
the top of the program here. I'm just going to use
this simple command. So I'm going to say
use underscore BPM. Oh, put a hundred and ten, hundred, ten beats per minute. Now when I play it,
going much faster, he's going 110 beats per minute. If I just comment this
out using Command or Control and forward slash or by adding a pound sign or hash
sign at the beginning. And run this again. There we are back to
60 beats a minute. If I remove that comment. There we are. So that's how we
can set the beats per minute within,
within our programs.
11. Synths: Okay, So this is
great. We can actually produce a music
using code and we can rest between notes or we could play all the
notes together as a chord. You can set the amplitude,
we can set the pan. But the sounds that
is producing a not very interesting
to your audience as soon can we be getting
very bored or that beep sound coming out of Sonic Pi. Luckily, Sonic Pi has
got over $0.40 built-in. There's a list on
the screen now. We're going to look
at some of them now. And there's some really
great sense in here. So let's go back
over to Sonic Pi. And we can see here that we've
got just a C major triad. And to use one of the sensor is actually really, really simple. So what I'll do,
I'll go up here. It's very similar to how we said use BPM before for
use beats per minute. We can say use a synth. So we can say use underscore. Synth, hit Spacebar,
we hit the colon, and then we type in the
name of the synth we want. So just for this one, we're going to use tech
underscore source. You can see the onscreen help
is coming up to prompt us. And when I press Run now, you'll hear that it's
going to play R, C major triad using
the texts. Awesome. A much, much more
interested in sound. Now, I could use any,
any symptom here. So all I need to do is hit the codon and just
type another one in. So for a three or three, for example, I could
say TB three or three. And there's all sorts
of great since in here. So for the 1800s
we've got a profit. And as I say, there
are a lot since in here now, as I
mentioned earlier, the help section inside Sonic
Pi is absolutely fantastic. Included in here for you. If you go down to
the bottom left, you'll see this little
tab called sense. Again, if you don't have the
help section open right now, go up to the top and use this button to
toggle it on or off. And then in here we've
got the sense there is a complete list of all
the sense in here. So let's have a look at blade. So I can just go down here. I just need to type the name. Heavier. We can just copy and
paste this over here. So you can see there's a
whole list of syncing here, which is exactly the same
list as I just showed you on the previous slide. Go ahead. You've got your little bit of music that you've been playing
with, with the play. Come up, go ahead
and have a play around with the sense and see what interesting sounds
that are in there.
12. Applying synth filters: Okay, So one of the things that we think about
when we think about, since we think about filters. And there are filters built
into the sense in Sonic Pi. So one of the common things to do with a synth filter
do with the cut-off. And we set these in using the options in the
same way that we set amplitude and pan earlier. So let's start from
a clean slate here. And so we're going to
use the tech sources. So use underscores synth,
codon, tech source. And then we're going to play,
I'm playing an E three. So an E on the third octave.
That sounds like this. If I were to set the
cutoff of the filter, then I simply put a comma, I taught cutoff a colon, and then I'll set
the cutoff at 70. And this is what
that sounds like. Okay, so this is setting
the cost off on the filter. You can hear that That's really adjusting the way
that note sounds. So let's, let's add another, another E3 here so you can
difference of put asleep. This is going to
play the E3 without the cutoff of the filter
cutoff being set. And the, and then the
E3 with a cutoff. There we are. And again, over on
the right-hand side, you can see in the log window exactly what's,
what's happened here. We've played tech soars with the note at 52, which is an E3. Then we have played the texts
orders with a note at 52, with a cut off at 70. And you can see that
the time we pay that, this time part of the logs here, this is when the sound
was played or when the action occurred in relation to when we press the Run
button, the start of the piece. So straightaway at time 0 is 0. We played 52, and then
two seconds later, we played the textiles again, again at 50 to 70. So that this part of the law
can also be really useful for to see what happened in what order
and when it happened. And again, it's really
simple to work that out now with a
simple piece of code that has a code
gets more complex, you'll come to find the
log more and more useful. We've been talking
about synthesisers and the concepts of
synthesizers like filters, and they're applying filters. And in a second we're going
to look at resonance. If these concepts
are new to you, I definitely recommend you
check out my other course that complete beginners guide to
synthesis and sound design. That course will
take you through these concepts and
much, much more detail. But for now, let's move on and have a look at the
resonance. Very briefly. A resonance is just giving a bit of a peek in the filter
just before the cutoff. We set the residents just
using another option. Like I said, we can just
add our options by, by putting a comma after
the current option. So let's, let's do the same again so we can make sure that we can hear
the differences. So let's do an E3. We'll set the cutoff the same. So to set the
residents, I just add another option. So I hit comma. And I'm going to set
the resonance by using the option raise, RES, hit the colon. Now resonances are set
as a value between 01. You can't set a one. So one. The residents could be anything
below one and above 0. So in this instance, the texts or sent, if I look down here
in the help section, I look at sensor like a tech source and I
click on resonance. I can see that by default
the resonance is set to 0.7 for this synthesizer, that it may be different
for different synthesizers. Let's just change that. Let's set that to
null 0.9 for this. And you'll hear a
subtle difference in the filter for
this synthesizer. There we are. So that's how
to set the filter cutoff and resonance is for
synthesizers have a play around. These effects will
be drastically different for the
different types and sizes. So change this up here, play, play with different types
of synthesizers and change these cut-off and
resonance values here. And to really experiment
with these features. In the next section,
then we're gonna look at another popular
part of synthesis, and that is envelopes.
13. Envelopes: Okay, Before we dive
into some code, let's have a look at
what envelopes are. Now, we'll run through a
brief introduction here, but again, if you want
more information, then please do look at
my complete beginners guide to synthesis and
sound design course. An envelope is really
just a way of describing the amplitude or the volume
of a sound over time. Just to find it. Where to
find it on this graph here. So on this graph we
have the y-axis, which is amplitude or volume. On the x-axis is then the time. So the first part of the
envelope is the a for attack. And often you'll refer,
you're here the term ADSR. Now this is just another
way of naming and envelope. So if people are
talking about ADSR, they're talking
about an envelope. There are various different
types of envelope, but ADSR is the most common. So a stands for the attack, and this is just
simply the amount of time it takes to get from 0 amplitude to
the maximum amplitude. When we, when we trigger a note. D then stands for the decay. And this how long it
takes to get from the maximum amplitude
at the end of the attack phase to the level at which we want to sustain
the note which is the S and the S. The sustain is set in terms of volume or amplitude rather than
in terms of time. The release is how
long it takes to get from that sustain level down, back down to 0 amplitude
at the end of the note, one note is released. So a DNR are all determined
by a time period. And S, the sustain is determined
in as an amplitude or is declared as an amplitude
or a volume rather than, rather than a time
period in Sonic Pi. Then we also have
three other elements, which are the attack
level, the decay level, and the sustain level, and
these are also volumes. So let's go over to
the code and see how we can use this
to affect our sound. Okay, so here we are
back over and Sonic Pi. Let's have a look at ADSR envelopes and how we can configure those
within Sonic Pi. So let's start off with
a simple play command and we'll just play a C4. Okay, so to set the envelope or the
configure the envelope, set the parameters
of the envelope. We just add options on the
same as we did with Pam, level cutoffs,
resonances, et cetera. So exactly the same. Again, it's nice and simple. It's really been designed very
well to be very standard. So you can kind of
hacky way round and follow the same pattern for
four different options. So again, we hit
the comma. In here. We're going to set different
parts of the envelopes. We're starting with the release. So I think it's the
easiest to here. So it will set the
release, release codon. That's a force that's going
to be two for four beats. Again, because we're on
a BPM of 60 by default, this means that we're going
to release over four seconds. So let's play that. So you can hear that it took
four seconds to get from the sustained amplitude
down to an amplitude of 0. I say that again. We can set the parameters of the ADSR envelope in
very much the same way. So we might want
to set a attack. So we can just go in here. We can add another comma. And we'll say this time we're
going to set the attack. I will set the attack to 2.5th on our ADSR envelope. Then it took 2.5th to get from 0 amplitude up to
maximum amplitude. And then it releases over
four seconds or four beats. But as I said, we've
got the attack decay, sustain, and release
that we can all set. We can also set
the attack level, the decay level, and
the sustain level. And just to remind you that the attack is the time taken to get from 0 amplitude
to the attack level. The decay is the time to move from the attack level
to the decay level. The sustain is the time taken to move from the decay
level to sustain level. And the releases the time to move from the
sustain level to 0. So let's, let's, let's configure our notes them
with all of those options. So let's stick with
the attack of 0.5, but we're going to
say our attack level is going to be one. So what will set that?
So we can see again, I could just use
the arrow keys to move up and down in this
code completion window here. And then when I got the one, I want to just hit Enter and
it will put it in for me. We'll set the attack
level to one. We'll set that to k. So we're going to set
decay to one as well. We'll set the the decay level. We'll set that to be not 0.7. We will set the sustainable. I will set that as no 0.4. We'll set the
sustained to be two. This is actually brought
me to a good point. So it really doesn't matter in Sonic Pi where it kind of
ignores carriage return. So if I get to a line here, and because my font is very big, if it gets her
slide here, that's kind of scoring off the screen. I can scroll left and
right, but actually, it's probably easier
just to hit Return. And you'll see it there,
put it onto a new line. That's perfectly fine. If you just want to organize
your code in that way, it will ignore carriage
returns or the Enter key. So back here I've got a missing comma
here for the sustain. So let's run that. So we've taken a sound
which just to demonstrate, I'll add another play the
same sound here so as to a C4 and sleep for two. So this is going to play
the default sound is going to sleep for two beats. And then it's going
to play this one with the envelope that we've
set up in the way we want. So you can really
hear the difference. And again, I can
combine this with other things that we've
learned within Sonic Pi. So I'll use a
synthesizer for this. So let's, let's use, Let's use the synth profits. So there we are. That's, that's envelopes within Sonic Pi, nice and easy to do. Again, we're just adding it as, as additional options
after our play command. The thing to do now is to experiment with
different sense but also with different envelopes and see what interesting
sound gene come up. Try and go for some
percussive sounds with a very short attack
and a shortish release, which will give you a much
more percussive sounds. I would try some really
pad like sounds by setting the attack and
release to be very long. So have a play around with
the parameters inside there. Don't worry, you
can't break anything. And I should just show you
through the error commands. So if for example, I set the lesson it something that's going to
give me a sure-fire error. So if I take the attack
level two minus one, so it attempted to play, but he got his gotten as far as the attack level and
then we hit an error. So I can see in here
then the value of the option attack level must be 0 or greater and it
got a minus one. So this is really,
really helpful, Eric commands inside,
inside Sonic Pi. If you do get these
kind of pink lines come up or these error
messages shown, you can dig down into
much more detail in here. But in general, if
you read these, these kind of big bold error
messages that come up, That's going to give you a
really good indication as to where exactly in your
code the error has occurred. And as I said before, is a
really nice, safe environment. You can't do any harm to your computer or to any
other running programs. Really do. Feel free to experiment inside
Sonic Pi. Try stuff out. If it doesn't work,
it's gonna give you a nice readable error message which will point you in
the right direction.
14. Playing samples: Okay, so we've looked at
the default play command, which plays that beep noise. We've looked at
being able to change that sound both with the
ability to use a different built in synthesisers within
Sonic Pi and being able to change various options like the volume or the
amplitude, the pan. Apply filters and
cut with cutoffs and resonances and being able
to adjust the envelopes. So hopefully you've had a chance to have a really
good play with those and really understand how
that's all working. But there is another way to
play sound within Sonic Pi, and that is through
the use of samples. Now there are a number of built-in samples
within Sonic Pi, and you can see all those down
in the help section here. If you click on this
tab for samples, it'll give you a list
of sample categories. And then you can jump into these and play the different samples. Now, as I said, the
help section within Sonic Pi is
absolutely fantastic. If you go through
here, you'll see all the different samples
that you can use. And actually if I just
go and choose one here, if you choose this
little arrow next to it, That's actually a play button. And so you can audition the samples within
the health section. So if I play next to
this skinny boom, for example, hit
this Play button. There are lots and lots of other high-quality samples
built into, into Sonic Pi. Now to use them, I just
use the sample keywords, so I simply type
the word sample. Then I hit the colon and the name of the sample
that I want to use. So there's a one
which is guitar, which is an E minor ninth. So if that's the sample, I'm going to use that
and like that press Run. Again, I can apply
the same options as I have done to the plague of n. So if I go to the end here
and I can set the amplitude, for example, that's an 0.5 and we'll panel all
the way to the left, which again is a minus one pan. And play that. So there we've heard a half volume sample pan all the way
over to the left ear. There are lots and lots
of samples built in and I would encourage you to
have a dig through here. So if we go down and have a look at some of
these sounds when looping, for example, we can see
the Amen break here. So if I, if I
auditioned a sample, if I want to play that within
or use that within my code, I can either go and type it
in or I can actually just go and copy that in with Command C, Control C. Or I can
right-click and copy. And I can just take that
and paste it up here. So that's going to
play a sample at the speed that it
was recorded that. But I can actually
change the rate of samples again just
with another option. I said that option using
again a comma at the end, I can set the rate, which is the speed
of the sample. Now, by default, all the samples played with
a rate of one and that is the rate or the speed at
which they were recorded. But I can set that to
play at half the speed. So 0.5. I could get it to play at twice
the speed or rate of two. I could play at a 1.5. Or interests me if I
take a negative number, if I play a rate of minus
one, this is what happens. I play in the sample in reverse. Let's set that back
to a rate of one. If you're going to play
stuff at a rate of one, you can just remove this option. I'll leave it there for now. But everything
about everything by T fault rather plays
at a rate of one. But I can also use
external sample. So there are lots and lots and lots of samples
built into Sonic Pi. I definitely spent five minutes now just having a
play around inside. Lots of really,
really useful sound. So I don't know. We've got the, the lunar
landing, an ambient sound. There were lots of kind
of built-in drum samples. For example. There are some more drum samples and here they're a bass sounds. Glitchy sounds, snare drums. There are, again lots of loops and a bunch of vinyl sounds for adding
a lo-fi filter music. There's a whole bunch in
there, so I definitely encourage you just to
spend five minutes now pause this video and have a dig through the
samples and audition a few and play around with them and play around with the rate and see what
they sound like, reversed or sped
up or slowed down. Now there the built-in samples, but actually we can use samples that we've
recorded ourselves from, just load, load them in
from our hard drive. So let's go here. And the way we do that,
we just specify a path. So this will be
slightly different on Windows on a Mac, I'm on a Mac. So to do it, then, all I need to
do is press sample. And then inside quotes, I just need to tell Sonic
Pi where the sample is. Now, if you're on Windows, is going to be probably see colon forward slash something
or C colon backslash. And then the path of wherever your sample is. I'm on a Mac. So my sample is on my desktop. So I'm going to go to Users, Steve, onto my desktop. And then I have a
sample called beat one. And there we are. So
that's all I need to do to tell it to play a sample, that's to load a sample. And from my hard-drive, again, I can change the rate of
a sample I've loaded in. Like so. This is obviously going to take
a long time to play. So this is a good example
of using the Stop button or pressing Command or
Control S on your keyboard. There we are. So we can start, stop it halfway through a run. And again, I can play that in reverse stock that I can play it at twice
speed in reverse. Okay, so there's another option for playing samples as well. We can just point to a folder
and we can use an index to, to, to say which one to play. So this is really
useful if you've got a sample library or a
folder on your hard drive, this has got a bunch
of samples in it. And so we just, we just tell it which sample we want
to play with in a folder. So we can just remove this here. We can say, okay, play
the first sample. Now, here's something
to point out to you. So when we are programming, it's very, very common. In fact, almost universal within programming
languages that the first item in the
collection is the 0th item. So counting within
a computer always, always starts at 0, certainly within
Ruby and Sonic Pi. As I said before, Sonic
Pi is based on Ruby. So when I say I want to use
sample 0 within this folder, this means play me the first
sample within this folder. Now I've only got one sample in this folder on my desktop, so it's going to play the
same ones we had before. Now, you will see later on that this can be
really useful because we can use codeine to
determine which sample we want to play without
having to know the name of every single sample. We can just say Play
me sample five, play me sample three,
sample ten, et cetera. So that's just a different
way to access samples. But again, if I just wanted
to access a specific sample, I just type the full
path and the name to it after the sample keyboard. Now, envelopes for samples work in exactly the same way
as they do for sense. So, for example, we could set
the attack of this sample. We can say, I want
this, the attack for the sample to take four weeks. Let's play that. So we can see from there that it
took four beats to get from 0 amplitude once we
trigger the sample up to the maximum amplitude. Now, sustain for samples
is slightly different, so the sustain is automatically set to the
length of the sample. So remember the sustain
is the only part of the envelope that we did that we defined in terms of time, the rest of the defined
in terms of amplitude. But the sustain is automatically set to the length of the sample. Or we can set it as usual. So I can set the sustained
to be Let's say two lists. Let's remove this
attack just to make sure it's very clear. There we are. So because I told us to sustain
for two beats, it played that sample
for two beats. So I can also set the start and finish
point to the sample. And I tell it how far into
the sample I want to go. This is a value between 01. So it's kinda, if you'd like, percentage through the, through the sample that I
want to start and finish. So I could say, let's start at nought 0.2 of
the way through the sample. Let's finish at no point to six. So that's played out
here that we start into the sample and we
finished before the end. There we are. So that's
sampling or playing of samples within Sonic Pi. In the next section, we're going to have a
look at program flow and start to build up
more complex programs, to start to produce more
complex and interest in music.
15. Program flow: So what do we mean
by program flow? Well, program flow is just
a way of determining in which order the instructions within our program are executed. And it's really down to
three basic concepts. That is sequence,
selection and iteration. Sequence is just the execution
of instructions in order. And that's what we've
been seeing so far. So for instance,
we played a note, we slept and we place
them another nodes. Then we slapped ME,
played another note. This is just the execution
of those instructions from the top of our code file to the bottom in the order
that we typed them in. Selection is just a
way of being able to determine which action to take within our code
based on something else. So we might say that
if this has happened, then do this otherwise do
something else and that will become much
clearer and I explain conditionals later on. The third part iteration
is just being able to do the same thing over
and over and over again a number of times. Now this may go on an infinite number of times or a predetermined number of times. But say for example, we had a, the C major triad that we started with right at the
beginning of the course. Now, we could play
that C major triad 16 times by typing that same code in 16 times,
asleep between each. So we might do a C major
triad sleep for a beat. Another C major triad
sleep for a beat. But every time we do that, well, that's four
commands, isn't it? So there's three
play commands to get our three note
snarl, triad and asleep. If we want to do that,
ten times x for example, let's say, for example,
keep them nice and simple. If we wanted to. We wanted to play that, that
C major triad ten times, we'd have to repeat
those same four lines, the three plays and asleep
ten times within our code. In order to play that same code, ten times iteration, it
would be a great way. I've been able to
just say, okay, well here's those
four lines of code. Just do those ten times. And that's what we're
going to look at next.
16. Loops: Okay, so if we think right back to the beginning of
the course and we had a small piece of
code which played us a C major triad and
it looked like this. So as I said before,
if we wanted to play the C major
triad ten times, you might want to do
something like this. So let's sleep for one beat and then we can type
our C major triad again. And then we can do that
another eight times. So we might get smarter
and we might say, or we can copy and paste, right? So we can a copy
that Motors keep patient that as three
times four times 5678910. So there we have our ten major or tenancy major
triads in a row. And this is using
the sequence part of the sequence selection
iteration program flow that we learned about
in the previous lesson. So it's just executing every
single instruction in order. I got to use the stop button. Or you can use Command
S or Control S to stop it through
the program flow. We don't need to hear all that. Now this works perfectly fine. It's absolutely fine. We'll operate and it's
perfectly fine to do this, except that you can see that to produce music of
any kind of length, you're going to end up with a, an awfully long program
and an awful lot of repeated code that's
very, very hard to read. So the way around this
is to remove this. The way around this is to use
a construct called on loop. And this is where we move into the iteration parts
of the program flow. So in Sonic Pi, the keyword for a loop, I used to do things round
and round and round again. Lucas, actually a really useful
way to use because we use loops in music anyway to mean
something that just plays, well, that can be played round
and round and round again. So we can say, okay, well, so let's look this one. I'm going to type this in
and I'm going to explain it. So what we said here is we use the keyword
loop and then we say do, is loop, do. Then everything before the end. We're going to loop around and round and round
and round again. This will just keep going forever. So I'm
going to stop it. Are the reasons can
keep going forever. Is it, it's gonna, it's
gonna say loop do. And it's going to play these, this triad, going to sleep
for 1 second or one beat. And then it's going to hit
the end and it will go back round to the loop, do and do it again, play the triathlete
for a second, hit the end, go back
up to the loop, do, and then just keep going forever and ever
and ever and ever. However, what we can do is
a different type of loop. We can say to Sonic Pi that we want to play something a
certain number of times. The way we do this
is very simple. So we replaced the loop keyword with the number of times
that we want to repeat. So we're going to do this
three times so we can see it through to the n. So we just say the
number of times. So three dot times, do, so, do this three times. And there we are. So then, then our program
flow is going to revert back to the
sequence part. So we could say play
this three times. And then we'll just
make another chord. So let's do a, a G major. So we're gonna go,
we'll say colon, G4, a before. And a. The five should give us a, a G major triad. And there we are.
So we can see that that would have taken an
enormous amount of code to do. At least we can
work it out, right? So we've got these four
that would have been repeated three
times. So that's 12. And then another four
repeated three times. So that would've been
24 lines of code. And we reduce that down to this. And we can see
that this is much, much easier to
read, particularly if I use a code comments. So I can say, oh, excuse me. So I can put a comment
in here to say, to say this is a C
major and then this is a G-major Nebula. We can see we've got a much, much more readable
piece of code. This number of times
doesn't have to be three. It could be anything
you want. It could be 60 and it can be 20, could be a 100, whatever,
whatever you want it to be. The one important thing
to remember about loops is that every loop
must contain asleep. And in fact, if we just
remove this for now, if I remove this sleep, then what happens is
the computer so fast, it loops through three times. You heard that was
very distorted. But it actually done
is it played that triad three times all
at the same time. And that's why we
must put asleep into every loop because
the computer so, so fast that it
will loop through those three times in a
fraction of a second. We must remember to
put the sleep command into, into every loop.
17. Nested loops: Now we can also nest loops, uneven loops of different
kinds inside of each other. So we know we've got the
loop do and we've got the three dot times du or the 16 times do we can nested
inside each other. And I'll show you a bit of an example here so
we can say loop, do we know that we're
going to need an end? Now, you'll notice that
when you run things, it formats the code and puts the indentations in to
make it easier to read. Another way of doing that
without having to wait for it to run as to press
Command or Control M, four M for mother. And that will just format
the code nicely for you. So I can say here, sample
little play the bass drum, sample, BDI, underscore house. Again, Control, Enter. Control, Control or Command
M will format that for you. So that's playing
outside one loop. If I play that now, it's
going to play it once. And the reason that it's failed as there's no sleep
inside that loop. So during the plague
of audits, it's fine. It's just going to
play them all at once. But actually, as I said before, Sonic Pi is very much geared towards learning and
to save you from doing something that could
potentially use up a lot of processor and memory
on your computer actually has given us an error here to say
we didn't sleep, because playing samples is much, much more intensive on your system resources
than just using, just using the play command. In automate this to work,
we want to put asleep. And here, this is just
going to loop forever. Play in that sample with a
snip of quarter of a beat between a stop that
less and less. And lets nest another
loop inside this. Inside this, we can say every time we go around that loop, we're going to play
that sample once. And then we're going
to play for hi-hat. So for every kick drum, every bass drum that
we play with this BD, how sample we want
for high hats, quite a common for
to the floor beat. So let's say for dot times do. How will play a
hi-hat sample here, omega one n that loop. Let's press Command
M to format that. And then inside this loop, we're going to play
a hi-hat sample. So we've got one built into, built into Sonic Pi. So we're going to say
drum symbol close. That's the one we want.
Then we're going to sleep for nought, 0.25 of beats. So four, we're going
to end up with four closed hi-hat per beat
and then one kick drum. So let's sleep. Sleep for quarter of beats. Before we play it. Let's have a read through this to make sure that we
fully understand. So we're going to loop
forever on this outer loop. And within that outer loop, we're first going to play
the BD house sample, which is a bass drum kit sample. And then after that
sample is played, although as I said, it computes so fast, it will be the same time
we're going to play for closed hi-hat with
a quarter of a beat, sleep between each one. Then once he's played
the four hi-hats, we're going to loop
back around to the top. Play the Keq for high hats, play the kick for high hats. So we play the kick
and this loop. And then we play
the four hi-hats. We can see that these are what is referred to
as nested loops. So let's play there. We are. There's our first basic
beats within Sonic Pi.
18. To infinity, but not beyond!: One last thing to
say about loops is just to warn you a little
bit about infinite loop. So let's, let's add another, another sample command here. And let's just say we're going
to play the, the skinny. Boom. So let's listen to
what that sounds like. I'm going to stop
it there, but it would have gone on forever. Okay, so the, the, this sample here on line
nine never gets played because this loop is just going round and round and round again. So we never kicked back to the sequence part of
the program flow. So we never actually get to line nine at
all because we're going from line one to
line seven endlessly. So I would warn you
against using loop do and only use loop do if
you really, really mean it. So I would say to set the number of
times whenever you can. So we might say for dot times. So it's going to play this
outer loop four times, the inner loop four times
within each one of those. So we're going to
play for kick drums, and they're gonna
play 16 hi-hats before we play
this final sample. So this will now actually
get to line nine. Okay? So to practice this and what I'd like you to do is to take the code that you
can see on the screen. Now, it's hard to
get that working and then play around
with the beats. So everything there is something that you
understand well. So I guess the next thing to
do would be to try and to add a snare sound
into that beat.
19. Enhancing your beat: Okay, So perhaps you've
ended up with something that looks something similar
to what we've got here. Let's play this. And we can see that we're looping
around four times. You're playing the kick drum. We play two hi-hats, limit play in this snare sample, another two hi-hats, and then we loop back around to
the kick drum again. Don't worry if
yours doesn't look exactly like this
and it probably doesn't look exactly like this. As long as you
kind of understand how the loops and
how the program flow works with the sequence
of the iterations. And you've managed to
get out a pleasing beat. It's definitely
worthwhile spending a little bit of time
with this and thinking about our b2 you want to
produce in your head and then seeing if you can get that
down expressed as code.
20. Randomisation: Okay, So I mentioned
earlier the use of midi note numbers rather
than, than the mini number. So using 60 instead of C4, for example, can actually be, although counter-intuitive,
really useful at times. I'm one of those
times is when we're using a random number generator. Now, randomization can be really useful for kind of
generative music or for having the computer generate
or create some music for you based on random numbers that you just wouldn't
come up with yourself. Whether that's actually for part of your composition
written into code, or whether it's a
kind of inspiration, just play with some
random values and give me some inspiration towards
a melody or a baseline, or whatever it is
I'm looking for. Generating random numbers in Sonic Pi is really,
really simple. And because we can play a note
number rather than a name, it means that we can generate a random number and
then play that note. So the way we do that is
with the rand command. Let's see how that works. So we know the,
we know the play. Come on already. We got play 60 as
we've used many times. Well, that's just going to place a note with the
note value of 60. But we can say, Play me a
note with a random value. So I can use the rand command and I can say in here
inside brackets. So I can say, Play
me a random note between number 50, number 100. Okay? So if I look over
in the log here, I can see this plate
me a note at 87.5031. If you type that into your code window and run that
code and look at your log. And I can also
guarantee that you will generate a random
number or random node, which will be 87.5031. Now, this may seem odd. This may seem odd because
it's not truly random, is it? If you're able to put in
the same code as me and on your computer a
different time and place, generate the same random
number, same random notes. It's not truly random now
this is done for a reason. The reason being that
you want to be able to share this code on all, play this code on your
computer a later date, and guarantee for it
to be the same so that every performance
is the same. So have a play with this, generates some
different random notes. So again, to change this, we might say, okay, generate me a random number between 4080. There's a different random node. So in order to generate
a different random note, what I would need to do is
to set the random seed. Now, again, this is
done on purpose. This is a deliberate
design choice within Sonic Pi to ensure that if you come up with a piece of code that uses
random notes that you really, really like the sound of. That it will be the
same every time. So you can see it's a
deliberate design choice. But to change the randomization, I just need to use
a simple command which is used random seed, use underscore,
random underscore C. And I can type
in any number here. And it really, really
doesn't matter. And you'll see,
we can use this a little bit later
and we'll change the random seed to generate
different random patterns. But I could, for example, change in, use random
seed here to 40. You'll notice that the
last time I ran this, I generated note 70.0024. That's interesting in
itself because the notes in Sonic Pi don't need
to be whole numbers. So actually shows you that
you could write programs in Sonic Pi to produce micro
tonal compositions. But we can set this random seed. Like I said, it doesn't really
matter what the number is. 99 is fine. When I run this now. Now I've got a note
which is 68.63. And again, if you
use that random seed and this round command
exactly like this, on your computer, with
the random seed of 99, your jet, you will also
generate that same note. And again, it's so
that you can save this composition and
you know that it's going to play in exactly
the same way every time. So let's take a little bit further and see how we can
use this to produce melody.
21. Generating melodies with randomisation: So let's just get
rid of this for now. We'll say, okay, Play me a random note between
between 5100. But we'll, we'll
wrap this in a loop. So as we saw before, but just do loop, do an end. We need to remember
to put asleep. And so let's put asleep of
one in here and press Run. And if we can call
that a melody, then you will have produced the same melody as I did if you run that
code on your computer. We could also
randomize the sleep. Because sleep is just
a number between, between 0 and whatever
we want it to be. Let's say rand. Generate me asleep
between nought 0.25. So quarter a beat, 1.5
beats. And let's run that. Okay, so there we can see we've, we've randomized the, not only the note but
the time between nodes. So we could swap the play
command for a sample. So let's look at that
so we can play sample. Let's do B glass rub. So here we were playing
the same sample, but we're randomizing the
time between samples. But don't forget, we can use the rate option of a sample
to speed up or slow it down. So we can do exactly the same with
the random value there. So we can set the rate
to be a random value between 0.52, for example. So that'd be honest. So we can use the
randomization functions to create random values to go in any option
which takes a number, which is why it's so useful
that Sonic Pi has been designed in such a way that we set the options with numbers, and therefore we can
use random values in the vast majority of them. So have a play around
with different, you might want to look
at the envelopes, filter cutoffs, resonances,
patterns, and amplitudes. Just insert some random values
using the rand function. And you'll start to create
truly generated music, which as I say, you might, either, you
might either want to use in your composition directly
or use them as I do. Occasionally is just to
play some random values, play around with
different options and different random values in each one to provide some
inspiration for a composition.
22. Other random functions: Awesome. Other randomization
functions within Sonic Pi, which can be used to produce
slightly different values. So let's start off with a loop. This loop will just play a C4. We're going to set the
amplitude simply to rand. And then we will sleep
for half a beat, the rand function and
then Sonic Pi will always produce a
value between 01. So let's play that. This is just a shorthand way of writing this which would
be exactly the same. We can also tell it
to return an integer. So if we wanted to
have exact midi notes, we could say round
underscore i, between 5000. You'll notice that
when we play this, if I look in the log, then we
only have whole notes here. So a whole integer values. So nothing after the, after the decimal point. So we know that
there's something on that, the midi scale. So again, have a play around
with the random function. We looked at our
round and round. Remember that aren't I, it will give us an integer. Rand will give us a floating
point number, or a number, perhaps with something after
the decimal place and round, which will give us a
number between 01. Have a play around with those, put them into
different parameters, play some different nodes, sleeps in different
lengths of time. Just play with
different amplitudes and envelope parameters and really get used to the effect that
randomization can have. On your note, the
interesting kind of generative
possibilities that you can have within your code. Once you're done playing with the randomization
functions, we'll move on to
the next section, which is going to cover
the final part of program flow, which
is selection.
23. Selection: To work with the final
parts of program flow, which is selection,
we're going to need to understand a couple of
programming concepts. Let's have a look at them in
the next couple of slides. So the first thing
we're going to look at is a thing called
comparison operators. Comparison operators
just allow us to compare one thing
against another. So when we're looking
at selection, we need to be able to determine if if one thing is true
or another is false. So for example, we
want to be able to execute a certain
part of code if something is true or a
different part of the code if that comparison is false. So in order to, in order to determine
that we have a number of
comparison operators. You can see them on the screen
here. There's only six. I'll explain each
of these in turn, but they're fairly
simple concept. So the first
comparison operators is a double equals sign. And this is equal to, now, it's a common error and
I still do it myself. I've been doing this
for a programming for over 20 years and I
still do this myself. So don't worry, but when
we are doing a comparison, we want to see if a compare
one thing to another. We need to use the
double equals sign. And that is because we use the single equals sign
for something else. So although normally in your mathematics we would use a single equal sign for
comparison in programming, we use the double equals. And I, when I type this in
my head, I say equal to. So there's two words, two equals equal to two equals. So if we want to
see if one thing is equal to another,
double equals sign. If he wants to say that, if the thing is
equal, the two sides of that equation, if you like, are true or are equal, then it will be true and we can execute
code based on that. The next comparison operator
then is the not equal to. So if this side is not
equal to this side, or if a less left side is
not equal to the right side, then it will return true. If the two sides are equal, then it will return false. That we then have the greater than and less than operators. So if the left side, left side is greater than the right side, it returns true. Or if the, if the
left side is less than the right-hand side,
then it returns true. We then have a
final two operators which are very similar, but they include the
middle bit is less than or greater than or equal to or less
than or equal to. So we could say if a certain value is
less than or equal to, or greater than or equal to the other value,
then return true. Otherwise it returns false. This, I know this is if you've not done any
programming before, this is a, can be
a little bit odd. It will become much, much clearer when
we look at some code examples and
we'll do plenty. So I'm probably a good
idea to note these down. So we've got the equal to, not equal to, greater than, less than, greater than or equal to and less than or equal to. There may be an
occasion where we want to chain these together. So we want to say,
if this is equal, if a is equal to b and c is
greater than d, for example, or if a is equal to b or c
is greater than t. Again, this is going to be
much, much easier to explain and to understand
once we see some code. But just, just to say
that we also have these combining operators
or logical operators. So this is how we combine
the comparisons together. Again, a double ampersand or
a double and signed means, and a double pipe means all. And you'll find the
pipe sign on a Mac at least just above
shift and backslash. But these will
become much clearer. We'll jump over into,
into Sonic Pi now, we'll write some code
using these kinds of operators and you'll see
how they work much better. Okay, So the way we do
selection inside Sonic Pi is with the use of
the if keyword. It's very simple to understand. So let's just dive in and write some code and you'll see how
all these operators work. So let's start off
with a simple example. So we can say, if one is
equal to one, then play. I didn't know the
Amby glass rubber. As with all the code blocks
within side Sonic Pi, we need to put an N
on the thing here. So this is saying if
one is equal to one, which is always true, one is always equal to one,
then play this sample. So we should hear
that sample play. Okay? And we can prove this worked by. We can say if one
is equal to two, then this sample
should not play. Okay? And we can see
over in the log, that's our run started
and completed. But the sampled in play, because one is not equal to two. So we can look at some of
the other operators here. So we can say if one
is not equal to two, then what would we
expect to happen here? Yeah, we'd expect the sample to play because one is
not equal to two. And there we go. So the other operators
we might use are if one is greater than 21,
is not greater than two. So we won't expect the
sample to play him. If we look over in the
log, you see the runs starts and completes and
the sample doesn't play. But if we say if one
is less than two, then we can press, run. The sample will play. You can see that it's a very simple concept
and it's just, it really is that selection. So if this thing evaluates as true is that if this
expression and we call this an expression here, this expression
evaluates to true, then carry out the
code with inside it.
24. if ... else: So let's have a look at
what we might do otherwise. So we can have two
execution paths. So we can say, if this is true, do this, otherwise, do this. So let's leave that as it is, and we can see the keyword for
the second path, the fall. If the first expression
evaluates to false, we can create a
second path and we use the keyword else for that. And I'll just play us a
different sample here. So something that's
very different. So let's, let's pick, let's pick an age, a weight
based on a weight-based room. So we can say, if the first
expression evaluates to true, play this sample, let's make
this nice and simple again. So if if one equals
one, so if one, if one equals one
evaluates to true, which it will play the ambiguous Rob else play the kick drum. So let's run that. And we would expect to
hear the glass rod. So for this second part
of the code to execute, this expression after the f would need to
evaluate to false. So we can do that
simply by saying if one equals two. Let's run that. And we should hear the kick
drum play because this will, this will be false or a loop immediately jumped
down to the else. Ignore this line here, jumped down to the else and play what's in the else block. We can hear the kick drum play. Okay, so what else
can we do with that? Because this is, seems
a little bit simple. Well, we could use
some random values. So let's, let's change
this to something, make something a little
bit more easily here. So let's just get
a hard base drum. And let's change this one to a. Let's see, a open hi-hat. So there's the bass drum
because we one doesn't equal to two and we executed
what was in the else. If we set this to
true, There we are. There's our open hi-hat,
so we've got two sounds. It nice and easy to hear. Very clearly different
so we'll be able to fully understand
what's going on. So this expression here
is rather simplistic. Amino always execute to true. But some, perhaps we
could do something else to make this a bit
more interesting. So while we know we've got the randomization functions we looked at in the
previous lesson. So perhaps it might be
interesting to you some of those. So let's say we've got
the rand function which returns a random value between
01. So we could use that. So we can say if r1 is
greater than naught 0.5, this will produce a random
value between naught and one. If that, if that value is
greater than naught 0.5, then we'll play the open hi-hat. Open symbol. Otherwise, else will play the bass drum.
So let's play that. Okay, so in this case, the random value must have
been greater than naught 0.5. And so we played this here. We can put as many
lines of code as we want to within these blocks. So we could have, we could
play multiple samples, we can play multiple notes, whatever we wanted to do within the if block and
within the else block.
25. Combining comparisons: Okay, so how do we
go about comparing? So we looked at the logical
comparison operators, But then we said we
could combine, rather, we could combine those
logical operators. We might want to say
if this is true and this is true or this is true or this is true, let's
have a look at that. So let's go back to
our simple example. So if one is equal to one, if one is equal to one play, the open hi-hat is equal to one. So the open hi-hat plays. We can combine that
with another one. So this isn't an, so we can use the double ampersand and we can say if one
is equal to 12, is equal to two, then
play the open hi-hat. But this will only
play the open hi-hat. This piece of code inside
the if block here will only be executed if both of
these expressions are true. We can chain as
many of these ones. You can have as many
and's and or's as you want to have within
your IF expression. So if I change
either one of these, then to be false. So if two is, we can say
if two is equal to three, well this is gonna be false. So therefore, one-on-one
will always be true. This will, this will be false. So therefore, this, this, and this are not true because this is true,
but this is not. So therefore the
base rumble play. Now, what about if I
change this to an OR? So this is the double
pipe, remember? So this is basically saying if one is equal to one or
two is equal to three, then play, then play the symbol. Otherwise play the bass drum. Well, one is equal to one. So it doesn't even need to go, it doesn't even actually
evaluate this bit. It just says y is equal to one. This is an or. So. It doesn't really matter about what's here. This is irrelevant
because only one of these things needs to be true in order to play this symbol. And again, if I change
to two is equal to two. If this is true or this is true, play the symbol, otherwise
play the bass drum. And they're both,
they're both true. So that's completely fine. What happens if I change? One is equal to 22
is equal to three. In this case, we'd expect
the bass drum into play because neither this nor
this were true in this case. Okay, so that's a
real quick look at how we do selection
with inside Sonic Pi.
26. The one_in randomisation function: Let's combine this with some of the randomization
functions perhaps to make something a little
bit more interesting. So let's perhaps do this so we could do a loop. We'll
just run it forever. But again, just to remind you, it really will run forever. So be cautious about using
them in your compositions. And we'll go back to
our random function. So if rand is greater
than 0.5, so the, again, the rand
function is going to give us a value
between naught and one. If it's greater than naught,
0.5, play the symbol, otherwise play the bass Trump. Let's play that. Here
you can see an error. My mistake. I didn't put
asleep inside the loop and that's exactly
what it's telling you said loop did not sleep or sink. So let's put asleep in
there and run again. Okay? So there is another, another randomization
function which we haven't seen yet but, but could be useful in
this kind of situation. And that is the one in randomization function.
Let me show you that. So we say if one underscore
in, let's put a two here. So basically what one does
is it returns a true with a probability that you put
inside these brackets here. So one in two times, it will return true in a purely random
in a random fashion. If I was to put a
tenant here one in ten times, this
will return true. If I put a one in two, we would expect an
even distribution between the symbols and the bass drum. So
let's listen to that. Okay, So they're playing
about the same amount now, obviously in a
random pattern, but, but about the same number
of symbols as bass drums. And actually, if we went
over to the login and scroll through the log
and counted them all up. We can see the bass drum playing and we can play the
symbols played. If we went through
and counted those, we'd end up with about
the same number. But if I change
this to one in ten, I would expect hear
the bass drum to play a lot more often
than the simple, because one in ten times I would expect the
symbol to play. And every other time else, I would expect the bass drum to play. So let's
listen to that. Okay, so we can see here that
using these IF operator, the selection
withinside, Sonic Pi, combined with the
randomization function, we can really start to
quickly build some kind of generative functions of
some generative music. Because of course, we could, we could play different chords, different notes, whatever
we wanted to do, different samples within,
within patterns such as this.
27. The simple if: There is a slightly
simpler way of writing this code and that is like this. Let's get rid of
this, get rid there. So we can say. So rather than having an if statement
in which looks like this. So let's change this
to one in four, so 14 times we expect
the symbol to play. Otherwise we'll just asleep
and go back around the loop. So this is done so often inside the code that we
use to generate music, There's a bit of
a shortcut to it. So it just means that we
can remove this end here. And we can just cut
that from there. We can put it on
the end of here. So let me just read
this through to you. So this is going to loop
around, around, around forever. And it's going to say, play this sample drum symbol
open if one in four. And it's just a
bit of a shortcut, a bit of a quicker
way of writing it. So we end up with
the same result, but it's just makes the code a little easier to read perhaps. Oh, maybe we can just
mess about here and just, let's just change our code. So let's play a, play a cow, a cow bell every one in six. So what this is gonna
do is it's going to, let me just command
M to do that. It's going to just
make this a symbol close just to make
it a little less ringy if that's a word. So we're going to loop around
every corner of a beach. We're going to play
a closed symbol. And then one in six times, we're going to
play the cow bell. Okay, and that really is it for selection inside Sonic Pi. So have a play, but look at the
air from the L and the shortened version of F
that we got here have a play with the one in
randomization function and the other randomization
functions that we looked at in
the previous lesson. And look at the
conditional operators and combining those operators
together just to look at different ways we can
combine these and use them to make music which
is unpredictable.
28. Variables: Okay, it's time to have a
look at some variables. Now, a variable is just a
fancy name for a label really. It's just a way of
giving names to things that we can
refer to them later. The easiest way to show you
is just to write some code, but it really is just a
way of giving something a name so that the
computer can remember it. And when we asked for it later, it can
give it back to us. That's all a variable is. Variables inside
Sonic Pi, a very, very simple to use, but we
use for them the equal sign. And this is why we had to use the double equals inside
the comparison operators. This is what the equals
is reserved for. So we say the name of
the thing and then equals and then whatever
value we want to store, the value can be anything. So we might say, for
example, number equals 99. And then whatever we
asked for number later, we can retrieve it
using the word number. So let's, let's just
make that really clear. So my number is
99, and if I say, if My number is greater than 98, just play 60. Otherwise aren't. In
fact we just end. So we can say that we
store the number or the value 99 inside a variable which we've
called my number. And then later on we can
use that. In our instance. We just can use a
simple if statement to say if my number
is greater than 98, play 60, so we would
expect them to sound. There we go. So very, very simple to
use and so Sonic Pi, but actually really
useful because we can refer to this in
many, many places. And when we want to
change the value of it, we only got to go to
one place to change it rather than change it
all over our code. So let's look at
a simple example. So one thing we might wanna do is named some of our samples so that we
can refer to them later. And if we want to
change that sample, then we can just change
it in one place. This, let's see a good example. So let's create a
variable called hi-hat. And inside that variable
we're going to store the a sample name. So drum, symbol, close. So this is a closed hi-hat. Let's create another
variable called snare. And we'll make that the, the sample or an
underscore Zoom. And we'll create a
variable called cake. And we will call that will store in that the
name of the sample. Bdi underscore house. The use of variables
become very clear now because if I create a loop, inside that loop, I will say, okay, for plenty of sample,
play me the hi-hat. Then play me the sample kick. And then sleep for
Quarter, repeat. Play me another harm,
another hi-hat. And then sleep again. And play me another hi-hat. Sleep again. Sleep again. And then play me another
hi-hat and sleep again. Let's play that. Okay, so maybe then on the third beat we want to
bring in a snare as well. So let's play a snare and here, so let's play a snare or
three, citizen to that. But what if I want to change
the kick drum we're using? So if I want to change
your kicked around, we're using while I've
only got to go and change them on place.
So it's not so bad. But want to change the
high hat that we're using, I would have to go
throughout my code and change if I'd use, if I've done it like this. For example, I'd have to go to every place in my code and change the hi-hat
that I'm using. So let's just undo
that. In our example. We can just change
it in one place. So we will just change
this to an open hi-hat. We can change it in one place. We don't need to change it
anywhere else in our code. And there we are. So that's a good reason
to use variables, but we use them quite a lot
in the course from now on. But it's really just a matter of giving a name to something. You can store absolutely
anything in a variable. One thing I will say
about variables is always try to give them
a meaningful name. Like if I had a call this a, B, and C, it would have
been fine using it, using those now and I
replaced it leaves a, B, and C would've been fine now, I ever would have remembered as I was writing the thing now. But actually if I was to
pick up this piece of code in three months time and go and copy this piece of
code out into somewhere else. You use them in a new
song that I was writing. Or even just to open
this and read this. And it would have been very, very difficult to understand, keeps a meaningful names
and it will make your code so much easier to read. And we spend a lot more time reading code than
we do writing it. So it's always worth bearing that kind of
readability in mind.
29. Loop counters: Another common use of
variables is to keep track of where we are as
we execute a program. For example, one of the
things we might want to keep track of is where
we are in a lupus, that loop is iterating. So let's have a look
at our way to do that. So we could start
with a variable called counter and
we set that to 0. Then we have a loop. So it will limit this
loop to 30 dot times. So 30 times du. And then we'll put
an end in here. Now I always find it's really helpful to put the
type the end after I, after I type the du. So if I'm, if I'm
using an Air for, if I'm doing something like
a loop with a DO on the end, and we'll see lots of
other examples later. I always find it handy just to put the end in straight
away and then, and then write my
code in the middle. This saves me forgetting to
end a code block later on, coming up with some
weird bug which can sometimes be
difficult to find. So that's what I prefer to do. But anyway, so what
we're gonna do is we're going to loop through this loop. And for each time through
we're going to play a note. So we're going to play 50 plus. The counter will then
sleep for a beat. And then we will, we will
increment the counter by one. So it will say the counter
is whatever the counter is now, plus one. Okay, so let's just walk or talk our way
through this if you like. So the first thing we do
is set the counter to 0. Then we say, do this 30 times. The first time
through this loop, we play 50 plus the
counter, which is 0. So we play 5050 plus 0 is 0. We then asleep for
quarter of a second. We add one to the counter and we go back around this
time through the loop. Then we play 50 plus one. We sleep for quarter of a
second, we add one to that. So the counters now to go back through the counters to
so he play 50 plus two. So we play 52 and sleep. And then we add one to the
counter, so it's now three. We go back round, we play 5353, then we sleep for quarter or
second quarter of a beat, and then we add one to it
with 54 and so on and so on. And we do that 30 times. So what we should
here is as we move, as we saw earlier, as we move up a number in the midi note value. So this number here, this 50, that should move that ball
that does move up a semitone. So what we should
here then is we should start at 50
and then we should, every quarter of a beat,
we should move up. We should play a note of
this up one semitone. So let's hear that. There we are. So that works exactly
as we expected. Now, this is, again, such a common thing to do that Sonic Pi provides
us with a shortcut. And this works like this, so this will work
perfectly fine and it's absolutely fine to use this if you've got
this in your head and it's easier for you to read, is absolutely the
right thing to do. But there is a shorter version. I'll show it to
you now so we can get rid of this
counter variable. Basically, we can place it here. So we can say in-between
two pipes, like so. And we can get rid of this here. So you can see this makes
it much, much shorter. But we can say 30 times do. We can say, okay,
include this counter. This counter will
always start at 0. And every time we go
through this loop, it will, it will add one to. It is such a common thing to do. There's a built-in function. It looks a bit odd. It's
not as easy to read. I appreciate that, but it is, if you get used to it, it does save you quite
a bit of code. Of course, this counter could be called anything you want is quite common actually encode
to see this called I. This is just a convention across seemingly all
programming languages. So I've used this in tons and tons of different
languages over the years, but it's quite commonly called IAC could be called counter, you could call it
whatever you wanted. You could call it Steve. So let's let's hear this. Again. Just a shorter version
of what we did before. We can call this
whatever we like, we just need to remember
that it needs to be the same name inside the loop. So that is that. Okay, so just have a little
play around with that and just make sure you really
understand what's going on. Remember, move on to the next
section where we're going to look at a few more
programming concepts. So this time around some data structures which
are built into Sonic Pi.
30. Lists: Okay, So there are a number of data structures
built into Sonic Pi. It's a complicated name for
a fairly simple concept. So we'll go through
each one bit by bit. And they really are designed to just make things a
little bit easier for you. Inside of Sonic Pi, There's lots of really
useful building things, but we're going to explore
them within this section. So you can see on the screen
here that I've got a very, very simple program which
is going to play a chord. Now, another way of doing this, just to save a little bit of
time at a few lines of code, we could use a thing
called a list. Now a list is just
takes a number of values and puts them together, separated by commas
inside square brackets. So let me just show you here. So let's put a, let's
put asleep here. So we can have a list
which is, which is here. So we have square brackets and then we put all the values
we want inside that list. And then everything in that
list will be we operate on, so it will play
everything in the list. We could say we could
just take the same value. So an A4, I, C-sharp five, C-sharp
five, and a E5. If we execute this, but we're going to play
this chord and then we're going to seek one beat. And then we're going to
play this chord and we will see that there's
exactly the same output. Let me just separate this byte. Two seconds. I think
one was hanging on. Okay? So this is exactly
the same as this. But we are, we've just put all our values
insider inside of list. That means that we can
move three lines of code onto one. We can equally. I've replaced this with
midi note numbers. So we could say the
equivalent here, which is sixty nine, seventy three, and seventy six. There we are. So it's exactly
the same. So this is just a list of things. And in this case, we're asking that when asked him
to play command, to play this list, that list contains
all those things, but there are other
things that we can do. So let's have a look at some interesting
things that we can do. So let's create a loop. Let's leave that like
that for now and then choose and make sure
we put our ending. Now. It's a loop
several need asleep. So it will sleep
for half a beat. Now, what this is gonna do is if I just looked
this like this, it's going to play this chord. Sleep for half of
each. Play it again, sleep after we play it again. Now, I'm actually
something that might be useful if we could
pick one of these at random to play each time
we went through the loop, we know we'd have a
note within that chord. But it's just going to
pick one of the things at that list of play rather than
playing them all at once. The way we do that is with another
randomization function. And we use randomization a lot in computer
programming in general, but particularly this kind of music making code
because it makes, it makes for some
really interesting melodies and patents. So let's use the choose Kiba. So we've just put the list
inside of parentheses. How many say, okay, well, choose me something that
from that less than plant. So that's basically what
this code is saying. Let's listen to this. Okay, so you can see that it's picking something
from that lesson. You can see quite
easily how something a little bit more complex or
maybe a slightly longer list, might provide you with some
interesting inspiration from for music and ideas. Now, I don't think we
could do is we could, we could create a variable. So we could just outside here. We could speak and say, Oh, we could do it
inside or outside. It doesn't matter, but just to demonstrate the
use of variables. So we can say, let's create a variable
called scale underscore list is equal to, and then let's cut
out from them. Put this outside. Then we
can say play something from scale, this scale list. This will work in
exactly the same way, but we've just pulled this
out now into a variable. So why is this useful?
Why we might want to use this in various
different places. We might say, might want to change this scale into
a different scale. In which case we could just
go and change them once and we could refer to it
throughout our program. But just another example
of using variables to store values. So
this is our list.
31. Indexes: Okay, so what if we want to play a particular
note about lists? And lists can be of
an arbitrary length. We could have
hundreds of notes in there if we wanted to, or a 100, you can store anything
less than our case was just storing numbers
and then playing them, but we can store
anything in there we wanted by you can have hundreds of items
within your list. How do you choose
which one you want to play if you want to
play a particular one. This is a thing called indexing. Or an index is, is it's just
a way for us to tell the, tell the program which item
in the list we want to play. And we could do it
simply like this. So let's get rid of this
randomization for now. So let's get rid of, Let's get rid of this
loop completely. So if I play this now, is going to play all
three of these accord. But if I wanted only to
play this middle note here, then I would just put in
square brackets a one. I can equally do
this like this list. Maybe, maybe this is
even simpler to see. So let's put this down here, the way that we had
the list originally. So you can see I've got my list and I'm saying, this is my list. Just play me this item
here. So this is a one. Now, why is this a one while
Lissa are always 0 base? Let's have a quick look at
a slide to explain this. Okay, So as I mentioned earlier, computers start counting at 0. So normally as we
started counting, if you asked a chart account, they would count 1234, etc. Computers always
start counting at 0. This is called a cross, just about every
programming language. There are exceptions, but just about every
programming language. So this is why the middle value within the three item
list that we just saw. That's why in order to
get the middle value, we actually chose index one because index 0
would have been 69. Index 173, an index to 76. So this is the 0 index. This is the index one, and this is index number two. Indexes always start at 0
the same as everything else. So whenever we do any
county in size Sonic Pi. Okay, so when I
execute this program, then we should hear
indeed the number 73. So just to prove that, Let's, let's play a 73. And then we will sleep
for a couple of beats. And then we'll play the index
number one from this list. That we can quite clearly see that they are the same note. If I wanted to change that, I could play the first
item in the list. I want, I can play the
last item in the list. What happens if I try to play something outside of the list? Well, nothing happens. It's rather than
throwing an error, It's simply, if we look
over here on the logs, we simply it plays a rest. Now, there are other
ways to play RESA. So we've looked at,
let's remove this. So there's a kind of thing
built into Sonic Pi. So we can play a
restaurant there. So we could play, let's say a C3, C4, C4. I'm just making stuff up now. A E4. And then we can use
this symbol here, this codon, that means arrest. And then we can play, let's say another three, A4. Okay, so now this is, this is not going to work in this form
because we're gonna, we're gonna just going to
play these four notes and nothing here because it's going
to play a role as a core. So let's maybe go back to a
less so we will have a scale, or this could be
called anything. So my list is equal to this. And then maybe we can use that loop construct
we had before. So we could say five. We've got five things, yeah, five times do we will
use our counter. Again, we'll use AI by
convention. There's our end. So we can say play my list. And then in square
brackets we can tell it which index
we want to play. The index we want to play
is based on the counter. So again, this could
be called counter, it could be called
anything you want. So as we look through
this first time, the counter is going to be 0. So it's going to play the
0th item in the list item, item 0, the first item. And then we'll go
round again counter we incremented it will
play this item here. And then the counter
will be incremented. Replay this item here. Then we'll play this
which is arrest, and then we'll play a four. Now, wanting to put
asleep in here. Let's listen to this area. So two things that are ready. One is that we can use this
special symbol inside, sorry, pi to indicate a rest. And secondly, putting
this list inside a variable and then
using the counter, which we saw as part
of the iterations, using this variable
name here to use the index to pick that
item, offer less. So just have a look at this. This is quite commonly used. This kind of code is
quite commonly used. So make sure you
fully understand that before we move on
to the next section, where we look at using some
of the concepts we use so far to create a
simple drum sequencer.
32. Making a drum sequencer: Okay, So we're gonna use some of the things we've seen so far to create a simple
drum sequencer. So none of the concepts in
here should be new to you, but they're probably
the first time that we've really combined quite a lot of them to create
something really useful. And this will help
you to really begin to see the power of sight pi. Once you combine all these
concepts, we've got, we've still got a lot
more to learn, but, but we've got everything we need to build a drum sequencer now. So let's start off with creating some
variables which will hold the sample names for the samples that we want to use. Very similar to what
we've done before. So we'll just say
hi hat is equal to drum underscore symbol,
underscore closed. We'll create a snare, which we will call SN zone. So this is just the sample
name that we're going to use. And we'll create a kick, which we'll use BD house, which is the name of
the built-in samples. Then we're going to
use for the kick drum. So the next thing we're
gonna do is we're going to create three
more variables, and these are going to contain the patterns for our drumbeat. So when we create this pattern, we're going to create a string and I'll explain
that in a second. And it's going to contain
x's and dashes or hyphens. So basically what we want to do is we're going to write a
bit of code after that says, wherever we see an
X play the sample, if we don't see an x don't
play the sample and this will be the basis of
our, of our sampler. So let's create the
pattern for the hi-hat. So we're going to
create a variable called high hat underscore. Underscore pattern. In here we're going
to create a string. Now, a string is
just a type of value that we enclosed inside
double quotes like this. This says that this
means that we can use spaces and whatever
we want inside. But it's basically
just a way of saying, treat this as a whole value. Even if there are spaces or
other carriers in there, this is a whole valley. In here. We're going to
put our drum sequence. We're going to make
sure that we've got 16 characters inside here, because we're going
to create a sequence. So that's got 16 steps, so 16 step sequencer. So let's have a look here.
So we're going to create 16. Character says 123456789101112. Oh, no, I've countered
that very wrong. 123456789101112131415. I'm going to end up with that. We'll end with a double
kicks. So we've got 16 steps are, I
went wildly wrong. There was only and the x's I think we're going to go kick, rest, kick, rest, kick, rest, kick rest, all the way along, then end up with a double-click. So we've got 16
characters there. We then create our
snare pattern. So we're going to have a snare pattern which
looks like this. So let's create a variable
called snare pattern. And again, we want 16 items
within our snare pattern. So we're gonna go
hyphen, hyphen, hyphen, hyphen hyphen X
hyphen hyphen hyphen, hyphen, hyphen, hyphen, hyphen. We can see because
the font used inside the code editor is
a monospaced font, meaning that every
single character takes up the same
amount of space. We can see that because we
know we've got 16 here. If these line up,
we've got 16 here too. But creates our kick pattern. As I said before. Sonic Pi really doesn't
mind about whitespace. You can put spaces or carriage returns wherever you
want to, just ignore them. So what I'm gonna
do is I'm going to just add an extra spaces. So this all lines up nicely. We're going to create
a snare pattern, something like this. Okay? And it really
doesn't matter what your hi-hats narrow kick
pattern looks like. This is this is what I'm
going to go with for now. And then underneath here
we're going to create a loop ending Command M or
Control M to format the code. And then inside this we're
going to create a nested loop. So we want to loop forever, but we want to have a 16
times loop inside that, which is going to step
through this and decide whether we play a high hat, a snare, or a kick. Okay, So let's create our
16 times, 16 times du. And then we're going to
use a counter in here. So again with the pipe. Remember we could do
this by initializing the counter and doing a counter equals counter plus one or, or, or whatever in here. But this is the
shortcut we're going to use because it's such a
commonly done thing within, within Sonic Pi code. So let's create our end. We need to remember to put
asleep inside our loop. Will sleep for a quarter
of a beat in here. Then we're just going to use the simple F to
determine whether. We should play each drum or not. So let's just say sample hi-hat. So we're going to play
this, the hi-hat sample, which is going to play
this variable here. So drum symbol close, but we're going to play
if the hi-hat pattern, I can't spell hi-hat,
high hat pattern. And then we're going to
look at the index of it is equal to x. Now let me explain this to you. So the first time through the
counter is going to be 0. And so we're going to say
play the hi-hat sample, but only if the hi-hat
pattern for index 0. So we're going to look
at this hi-hat pattern. We're going to look at
the first character within the hi-hat pattern. If that's an X,
play the high hat, we will second time round the counter's going to
increment the count is now one. This time round we're
going to say play the psi hi-hat sample
if the character at position one within
the hi-hat pattern is an x well positioned
one with 0 based. So it's the second character
while it's not an x. So we're not going to
play the high hat. So we can do this and let's
listen to the hi-hat pattern. You should be able to recognize the hi-hat pattern from this string that we've
got the top here. So it's going to play hi hat, rest, hi-hat rest, hi-hat rest, hi-hat rest all
the way to the end until we hit two hi-hats. Because we're looping round, this is effectively going to be three hi-hats and row. So
let's listen for that. Okay? So that's our
basic sequencer. So all that remains to do is to, is to do exactly the same thing for the snare and for the kick. So all we say is play
the snare sample. If the snare pattern at the position that
we're at within the, determined by the counter,
the index of the rat. So by the counter is an x. And let's listen to that. And finally, we can do
the same for the kick. So we can say play
the sample kick. If the kick pattern index
of counter is equal to x. And again, every time
we go around this loop, counter is going to increase,
going to start off at 0. But every time we
go around the loop, the counter is going
to increase by one. So every time we go through the counselor
increase by one. So if there's an x, that position within
the hi-hat pattern, the snare pattern or
the kick pattern. If that is an x that is going to play the relevant sample. Now it's going to do
this is why we put the 16 times counter inhibitors. So we've got our
loop, which is me, we're going to loop forever. But we're gonna do the
16 times loop inside, which means that
we're going to do it. 12345678910111213141516
times that by which time this loop has ended. And we'll hit this one, we'll go back to the top
and hit this will start a new 16 times loop with the
counter reset, reset at 0. So the counter will be
0123456789101112131415. Once it hits 15, has been
through the leap 16 times. Remember we're zero-based
when we count, it will go back to the top and then the counter
will be reset to 0. So we go back to the
beginning of the string and we'll just go round
and round and round again. So let's listen to our
sequencer in action. And of course, we can change
our pattern really quickly. Now, you're beginning
to see the power of loops and variables
of selection. So if I had just program
that drum pattern in by playing samples are
just using a sequence. So just sample, sample, sample we would have written
are lots and lots of code. And if I wanted to change
the bass drum sound, for example, or the, or the snare sound. I would've had to
go and change that. And an awful, awful lot of
places would have also been very difficult to keep track of. Where should I be playing? High hat and where
shouldn't buy? Where should I be playing a
kicker? Where should I put? By using this simple
pattern here, just using some of the concepts that
we've learned so far. We've got a really nice,
very easily readable, but most importantly, it really easily changeable piece of code. Very easy for me to now go and change the
pattern of my kick. So let's add a kick in there. Instead. We run that. We've got a different
kick pattern. We could change the snare
drum to be something else. So I think there's one
called snare generic. So again, very easily
readable code, but also easily readable and understandable and
easily changeable. So there we are. So it make sure you
really understand this, have a play
around with it. Change some of the patterns, change some of the
sample sounds. And why not go and introduce another drum
into the sequence. So perhaps introduce
a cow bell or a, or an open symbol into that pattern and
see how you get on.
33. Playing patterns: Okay, So earlier on we looked
at a way of using a loop to iterate over a list or list of notes to play
them each in order. But actually there
are a couple of different ways that you can
do this inside Sonic Pi. And as you'd expect, Sonic
Pi has got you covered with all the common programming tasks that might be useful for music. So actually there's a couple of built-in functions called play
pattern and play pattern, which will allow us to
achieve what we want to do. So let's have a look here. So we had a list array which
adds some values in it. So we could call this, let's call it my pattern again. So we just create a list. Remember our list is
just a bunch of comma separated things within
these square brackets. So we'll just choose
some numbers here. Sixty nine, sixty
three, seventy six. I'm pretty sure that's
what we had before. And then we can say play
underscore pattern. Play underscore pattern. My pattern. So let's listen to that. This is exactly the equivalent
of doing this. So let's just comment this out. So this is not going to execute, so it's exactly the same. It's just that it's sometimes a bit easier to store these things into a variable. But either way is fine. So what this is gonna do is by default, it's going to simply play every note within that
pattern, within that list. And it's going to
sleep for one beat between every note
that it plays. If I want to change, I can
use a different method called play pattern
underscore, timed. And then after the,
after the list, I just need to give
it a value for how long I wanted to
sleep between each note. So I said just say
comma nought 0.25. And this is going to play
this list here in order and rest for nought
0.25 between each note. Okay, there we are
pretty simple. And again, we could do much
more complex things there. So we could say we could introduce a rest
like we did before. And then we could do
something like what? We could do the scale
back down, right? So we'd do 7673. Well, the
arpeggio back down and 69. So this is gonna
play all the way up. It's going to restaurant a quarter beat and
then all the way back down again with a coral
reef between each. Note. That we are pretty simple. So let's have a bit of
fun. So let's use a synth, and we're going to
use a synth profit. We're going to create
a loop command M, and we're going to play a time
pattern, but inside that, so let's play comScore
pattern, underscore timed add. We will create a lesson
with an r square brackets. And inside that we're going to create a, a series of notes. So let's go for this. Let's go for S3, v3, g3, G3, B3, and a C4. So those of you with some
music theory knowledge may have spotted that that
is a C Major seven arpeggio. Well done if you
did. So we're gonna go up the arpeggio and then
we're gonna go back down. So a B3, patrick G3, and an E3. I'm just going to loop
around, around, around that. And we're going to
rest for nought 0.2 of a beat in-between
each thing that we play. And we'll end up with something
that may sound familiar. A bit of fun with, with
with patterns. There.
34. Chords: Another thing that
we have built into Sonic Pi, our courts. So let's have a look.
To play a chord. We can simply say play
a chord and we just need to tell it which
color we want it to play. Let's play a D3. Then we need to
tell it what type of core we wanted to play. So there are a whole
list here and you can see it's come up
in the code complete. So there are a whole bunch of cores that are available
to us and it really is a kind of extensive list
of chords are going through. But for now, we can
just say, okay, plays a major chord.
Let's play that. There we are. So that's
played as a D major chord. There are lots of
types in there, so we might want to
play a minor chord. We could play a minor seventh, some sort of diminished chord. Okay, so there are a
whole bunch in there. And as you can see, the code complete is
really excellent. So as soon as you
start to type equal, it will give you all these. So have a play around, look at the different types of chords in here and this saves you create in that
list and working out. Values are the notes that
need to be within each chord. So let's say we've got a D3. We're gonna do a, a
major seventh chord. Now we can actually
use indexes to tell us which note
in the core to play. So if I was to put an
index of one on this, this is going to
play the second note in the D3 major seventh chord. Again, if I change
this index to be okay, so I can use, use code here, use indexes to pull out
the notes within courts. I can also play in
versions of chords. So let's get rid of
this index for now. Let's change this
to a minor chord. And I can say, okay, well, play me the first
inversion of this. Play the second inversion. The third inversion.
There we are. So lots of really useful things, really useful functions
built into the courts. I could also play the chord
as a, as an arpeggio. So let's just remove this
to keep it nice and simple. But instead of saying
play the chord, I can say play,
play pattern cord. By default per play
pattern is going to leave a rest of one beat
between each note. But if I want to change
the speed of the arpeggio, I can say Play button, tide. And I just need to put the
end here so we'll say five, so quarter a beat
between each note. One more thing I can do with play pattern Simon is
I can actually give it different values for the time that I want to
respiratory notes. What this is gonna do is it's going to alternate
between the two. So it's going to sustain for
0.25 for the first note, 2.5th for the half a beat
for the second note, quarter for the third
half of the fourth. And we'll just, we'll
just flip between these two as I go up the arpeggio. And you can see
that reflected in the log over here on
the right-hand side. We also have the concept
of chord degrees. So if you've done
much music theory, you will know about
core degrees. So sometimes when we talk
about cause we talk about the common chord progression. So we talked about maybe 156 for being a common
chord progression. These are actually
built into Sonic Pi. Let's just write
a little example just to demonstrate this. So let's set the BPM to
be a bit, a bit higher. We're going to use a piano. And then we're going to create a variable which is going
to store up aggression. So our chord progression
is going to be a ring. Now, don't worry about
this word ring for now. We will cover it later on. Just for now, just type
in the word Reagan. I'll explain exactly
what this does later on. But basically it's a list
that goes round and round. So we just type in these which are kind
of common symbols, right? So we use Roman numerals for our four chord progressions when we talk about music theory. And then we'll create a loop and we'll go round eight times. Inside the loop, we are going
to need to remember to end. Let's remember to put
our sleeping as well. So, so in here we're going to, we're going to play
the chord degree. So I'll explain this
as I, as I typed. So we're going to
say chord degree, which is a built-in
function much like chord or others that we're
going to see in a minute. Am I going to say play, play, play the next value
in our chord progression. So this tick will see
it again later on. But basically, just to, just very quickly, a ring
is basically like a list, but instead of going off
the end and get nothing, if it gets the only goes
back around to the start. So we'll go round
and round and round. And tick is just a way
of telling it, saying, get me the next thing from
the list or from the ring. We're gonna be in S3. This is gonna be the key that we're in. We want to be in a major key. I can spell major. And then we're just going to add
one more option to there. So we'll set the release
remember from the ADSR envelope. So if we looked up before,
we'll set the release of four. So what this should
do is it should, using the synth piano
is going to play. Each note is going to
release over four beats, which is why we've got
the sleep for here. We're just going to play
on a C3 major scale, or C3 major key. We're going to play
the first chord, the sixth chord, the
second, and then the fifth.
35. Scales: Okay, so on to scale. So some scales are
built into Sonic Pi. Actually quite a
lot of scales are built on psi prime.
You'll see that now. So let's start off with
a play pattern time. So we're going to want to
play every note in the scale. So we're going to play a scale. And then inside
there we need to say what is going to be
the root of our scale. So we're going to see a C3, and then we're going
to choose from this certainly long
list of scales. So there's a huge
amount in there. We can see all sources
as blues scales. There's all kinds of
different world music scales inside here, or metric scales. There's modes of seeing. Eolian. There's the
blue scales again. Chinese girls, crotchet
scales, diatonic, diminished, Dorian
mode, Egyptian. There's a, there's
just a lot in here, so it's definitely worth having a split through this list. We can see down here we've
got all sorts of things. So we're going to choose
a common one here. So we will choose the
major pentatonic here. Then we can select how many
octaves we want in our scale. Do that just with a num octaves. So we say num octaves
and we'll say we want three oxygens
with large-scale. I'm going to say we're playing
patent time to remember so into say how long we want
to rest between each note. So that's nought 0.5. I must set the, the release of the notes that
we're going to play. But set that nice and
short to nought 0.25, just so if we don't do that, then all the nodes will
run into each other. We weren't here. A
nice crisp scale being played, so
let's play that. Okay, so that's the scale. So there are a whole
bunch of built-in. Now, let's just comment this.
I'll show you one thing. So there's command within Sonic Pi is a Ruby command, but, but then Sonic Pi called
puts and puts is going to allow us to right what
we want into the log. So for example, if
I was to say butts, Sonic Pi is great. When I run this, it's going
to output that to the log. There we go. So we
can see in there. Now, this can be really handy points during your programs just to output some it's an OK so you
know where you are. So you know, when you're
inside a loop or when you're outside of your particular
part in your program. There are some other things
that you can do with put, so you couldn't get the outputs of some
built in functions. So for example, if I wanted
to say output round, this is going to output to the log of value
between naught and one. If I create a variable, let's call it message
equals hello. And then I output
or puts my message. Now we are, so it's
grabs the value of that variable and an
output that into the log. The reason I got here anyway, I've gone off on a
bit of a side quest. But the reason I put
this here is actually I can get all the scale names out into the log by
doing, doing this. So I can say output scale NEEPS. We'll put scale
names. There we are. So what will end up
with in the log is a list of all the scale names. And you can see there are lots
and lots and lots of them. I'm probably going through
a bit too quickly, but if I didn't, we'd be scrolling for days. So you can see in
there. So definitely have a look through that list. You can use the code
that we've got here. Just uncomment this thing here. Come on that for now. Use this kind of CO2. Just, just listened to,
listen to some of the scales, perhaps play some of them with different sense to see what interesting
things you can get up. That is that so one thing that we could do
with the scales, for example, is we could randomly play some
things up the scale. So let's have a
quick look there. So we could say, let's take the C3 major pentatonic
three octaves and will lead us all
exactly the same. But let's choose not to
play the whole pattern, but just to choose
something from that. So we'll need to just change
this because we're not play a patent timed anymore. Let's just make it nice
and simple. Let's do that. And then let's sleep
for half a beat. So let's put it all in
a loop and run that. Again. If you've typed this code into your computer
and you play this, it will play exactly the same sequence of
nodes that I get. This is because the
randomization side, Sonic Pi is kind of
pseudo randomization. So that we're sure
that we always play the same every
time if we want to. If I want to change that, I can, I can change the, the
randomization seed. So choose the random seed, I can just make that 606. And this time we'll
get a different, I can make it 99
different shapes. But again, as long as that random seeds
stays the same, it will be the same
tune every time.
36. Rings: We mentioned brings before.
Let's have a look at rings. So I bring is a way of ensuring that we don't run off the
end of the list. So let's demonstrate that. So let's, let's use
the puts ground. We can output stuff to
the log and see it now. So let's say if I create a list, so 606467, this is the
one we used before. I think I want to output to the, to the, to the log the
item number one, so 01. So this should output to the
log number 64. There we are. So we can see the
number 64 output to the log as we
would have expected. But what happens if I asked for Item number nine
out of this list? We can see I got a nil. And the reason for that is
that there's only three items, so item 0, item one, item two. So nine is out of range, it doesn't exist, it doesn't
exist within that list. So it tells me it's nil. Now Sonic Pi, when you
using the play command, actually handles this
really nicely and gives you a rest instead of
throwing an error. But we can say this could
easily catch us out. So for example, let's, let's put this
into a nine times. Do we're going to use that
shortcut again to get the counter and pull, bring this down into here. So what I am expecting
to see here is for it to output 60 on the
first time round 64, then 67, and then six Nils. And there we are. So 606467
and then a bunch of nails. So how could we do it? So that when 606467
and then background, and you can see that this is, this could be a really
useful thing as we create a selection of
notes that we wanted. Now we want to just loop round and round
that selection of notes in a short sequence. Well, we can do that by
making this list a ring. And there's a couple of
ways we can do this. We could say, we could
put dot ring after it. And what I bring is it's just basically the
same as the list. But when it gets to the end, when you ask for the item off the right hand
side of the list, it loops back around and
brings you the first one. So it just goes round
and round and round. So what I'm expecting
to see here, 606467 output three
times. And there we are. So we can see it's gone through the list and then background
and then background again. And it will just keep going
and going and going forever, round and round around the list. So that's really useful. Another way that you
could write this is, is you could just create the list in a
slightly different way. So instead of using
square brackets, use parentheses and just
say this is a ring. This is exactly equivalent
to the code we had before, and it will run it and it
will run exactly the same. It's just a different syntax if you'd like a different
way of writing, so you can use whichever one, whichever one you prefer. Okay, so let's just, just to prove a
point, let's just, let's play that instead
of putting it and then we'll we'll put asleep
imagery the two in-between them.
And that we are. So we can see that that
brain just went around, around, around three times. If it wasn't a ring, we would
have ended up with this. I would have tried to
play from this list. We don't play the
three notes and then, and then had six rests. There we can see the
outlet recipe and output. So by making that
ring either using the format we had before
or by saying dot ring. So actually scales and
chords are both rings. So we looked at scales
and chords before. They are both defined as ring. So you can just go round
and round and round, both scales and chords. And this is why we made the chord progression in the
previous session a ring, because we wanted to go around that chord progression twice. So we could do the same
way as we've done here. So we could say the same
as we did with the scale. So instead of doing this, we could say play patterned
or play Pat and timed. Both of those things
are work on a ring. And then we can again no, 0.25225 to tell it how long
to slip between each one. And just, just to
reinforce this, this is exactly equivalent
to create an art ring in, in this way, just with the
keyboard or the front. It's really up to you
which one you prefer.
37. Ring functions: Okay, So there are a number of things that
we can do tutoring. So let's, let's just
make our ring a little bit longer so I can show
you some of these things. There's some additional
functions that we can we could use. So 606264 and then
we'll go 656769717072. And that should give us this. That beeping is getting
a little annoying. So let's pick an
A-list change out. So let's use a piano. Okay, So there are a number of things we can do with a ring. There's a bunch of functions built in that can be
really useful musically. And we just add them
onto into the ring. So we can say play pattern time, use this ring and we say use
this ring, but dot reverse. This is going to play
the ring backwards. We could shuffle. So this is going to play
every note within the ring, but it's going to play
them in a random order. But it'd be the same order
every time because we, we've got the pseudo
randomization within Sonic Pi. Again, if I want to
change that order, I can set the randomization seed to
be something different. I can just only play the
first five elements. So I can say just take the first five elements and from this ring and play those. I could say I dropped
the first five elements. When I say dropped the
first five elements, it means don't play these and
just play, just play this. There are other things
I could use stretch. So this is going to repeat elements that stretch can be
whatever I want it to be. So let's say three this time. If I want to repeat
the whole ring, I can say repeat and say, let's repeat this one twice. And again, I can make this any
number I want inside here. I can use Mirror. Mirror is interesting.
Mirror is going to play all the way up the ring, or in our case is a scale, but the ring could be anything. It doesn't have to
be in this order, but I've made it a ascending scale just to make it nice
and clear what's going on. So it's going to play
all the way through the ring and then
it's going to play all the way back through
the ring in reverse. Now you'll notice that it played 60 sixty two, sixty four, sixty six, sixty
seven sixty nine, seventy one, seventy two. And then it played 72 again and seventy one sixty
nine, sixty seven. So if I don't want
which is quite common, I don't want to play
this one twice. I just want to go all the way up and then straight back down, but not play this the middle one or the end one depends on which way you look at it twice. I can use the word reflect. I can use the word reflect. This is only going
to play the 72 once. Okay? So there are a whole
number of functions. These are the most common ones. And you can dig
through the dock, through the docks
in the bottom here to look for the rest. But one thing you can do is to chain these things
together so I could say, okay, So I'm going to, I'm going to place
one in reverse. But then I want to reflect that. So I'm going to reflect, reflect the reversed ring. So it's playing from
the end all the way down, all the
way back up again. And I want to repeat
that three times. We are. So again, a ring is incredibly useful. Data structure is the final data structure
that we're going to look at within
Sonic Pi for now, it is exactly the
same as a less than we can access things
through indexes, etc. But it just goes
round and round and round so we can never run
off the end of a ring. Hence the name, lots of really
useful functions to it. And I'm sure that you
can see there's lots of musical applications
to the functions that we can apply two rings. So these are functions
we can apply two rings. In the next section,
we're going to look at functions that we can
create for ourselves.
38. Custom functions: So now we're going to
look at functions, which is another way to
organize our code to keep it nice and readable and
keep chunks of it reusable. Now basically a
function is a way of organizing a piece of
code and giving it a name, but that Coburn actually
run until we ask it to. So let's dive straight in
and see how to do this. So let's go into the
code editor here, and I'm getting a bit fed
up with that beep noise. So let's use a synth. So we'll use the profits in. And we'll start by
creating a function. So what we're gonna do is we're going to
create two functions, one called verse and
one called chorus. What are some
unlabeled us to do is to define averse and of course, for our song, and
then we'll be able to call it. That way. We'll be able to
organize our song in the way we want it
to do without having to repeat the same
bit of code many times for each
first, for example. So let's start with
defining the person. So to define a function, we use the keyword defined. Then we need to give
our function a name. So in our case, we're going
to call it the verse. We finished with the do. And because we're going
to do, we must have an end. So there we are. Now, anything that we put inside this block is not gonna be
executed when we run the code. When we, when we
click the Run button until we call that
particular piece of code. So we'll keep the reverse, nice and simple
the code nice and simple inside our function. We'll just go through
a timed pattern. So let's say play pattern timed. And let's create a list
inside are less than. We will record. Our code will be a D4. And this is gonna
be a major chord. And that'll be followed
by a, another chord. And this time we'll
do a, a C chord. And this will be a major chord. And then finally, we
will have a G chord. Okay? Am I going to play each of these quarters or
is a timed pattern? So we've used play pattern time. So we need to tell
what Sonic Pi, how long to asleep between each, each
part of the pattern. So we're going to
sleep for two beats. If I run this code now,
nothing will happen. All this happened and we
can look over and the log here is that we have
defined the function first, but we've never
actually asked it to execute the
code inside there. So to execute it, or we simply need to do
is type the word verse. And that is saying to it, please execute this
function called verse here. And this is exactly the same way that the other functions
that are built into Sonic Pi define things like play in play pattern and
play pattern, tiny, etc. They're just, they're
just functions that we're asking you to asking
it to execute. So now when I press play or run, Here we are. So it defines the,
the verse here. And then when I call verse, it will execute the
code within side. So I can define another one. So let's define one called chorus end. And inside there
we will just play another pattern, but
we'll play different one. So same again, but we'll
use in different courts. So inside our core us will
have an A4, a major chord, followed by a C, again a major, and then a D major chord. And we'll keep the same, the same sleep in-between each call to keep
the same tempo. So now we have a chorus
so we could call him, instead of calling verse, we could call our chorus. Okay, so now we can construct a song simply by
calling our function. So maybe we'll have averse, followed by another verse and chorus and then
a final verse. Quite a simple book, but
common song construct. The first versus
the second verse. Now chorus. And the final. Now to reorder or solve, we can just change the order in which we call the functions. And to change the course, perhaps we think that
A4 is a little high. So let's change that to an A3. And now when I play
it, and again, we can, we can reorder this so we
can cut this from him. Maybe verse chorus
and then two versus. Now we're going to get a chorus. Our course is changed.
Then finish with to go ahead and do the same and create a verse and the chorus. And what you could
do also is to create a midline or a pre-chorus
or another function. And use this to construct a short song like
I've done here.
39. Function parameters: Now we can also pass parameters to our functions and we do that like so, so in averse. So here we've got a verse
and we've repeated twice. But another way to do it
might be to say, okay, Play me diverse twice or
play with reverse once. So I can go to
verse here and say, very similar to how we did
this with loops and counters. We can just inside pipes here, we can just give a variable
name so we can say repeats. And so this variable will be passed to the
function when we call it, and we'll see how to do that in a second. It's very simple. And then we can use that
variable inside the function. So we can say repeats
dot times du. Then we can end here. So it's going to repeat
the number of times that we pass to this function. So in here we can say we
just play this first once. And then here, instead of
having a second verse, we can say, okay, now I want you to
play the first twice, twice. Great. So one last
thing that we can do is to give a default value. So for example, if I was to forget to call verse
or pass a one to this, to say just repeat this first. Once. The following
is going to happen, we can see we've got the
wrong number of arguments. The arguments are what
we've, what we've got here. So these are, these
are, these are the arguments that we
pass to the function. We can see here that we expected one argument to be passed
either number of repeats, but we actually got 0 because we forgot to pass the number repeats
of the function. One way to fix
that is just to go and put that number back in. Another way is to say, well,
if I don't pass anything, then just play it once. And we can do that by setting a default parameter, and
it's very simple to do. So we can say where we declare the parameter up here
for the function. We can just say equal to one. Well that's gonna do is say, if I don't pass any parameters, than just assign the value one to the variable of repeats. And if I do partially a
value, then use that value. So let's go back to our
original configuration, where we had two verses, a chorus and then one verse. But we're not going to pass
a parameter this time, and we're just going to rely on this default
parameter being here. There we go. So obviously
we could do the same to our course
if we wanted to. We could call it repeats,
we can call it times, we can call it whatever
we want to really. Again, we'll declare
a default value here. And then again, we'll say
repeat stop times, do. And then we'll need
an end for that loop. There we go. So that's how
we define a function and assign parameters
to that function or declare parameters
for that function, parse them in and how we set default parameters
for what we want to do if we don't
pass a parameter or a value for a
particular parameter. So you can see here,
there's many, many uses. This very simple example
where there are many, many uses for functions from our code has just a way
of organizing our code, making easy to change. We don't need to make
the change in one place. For example, if I want to change the verse
and instead of a C, we want to put an a,
just make that change. And every time I call
the first function, that change will be reflected. So a great way to make your code really nice and readable. I can easily see that this
is the verse and the chorus. I can easily see the
structure of my song. Like I said, this is one simple example of
using functions, but I'm sure you can imagine
many other ways to do it. So have a go at reorganizing
your code and using functions to make
it really nice and clean and readable and reusable. So we've been doing a
lot of programming. So in the next section, we're going to take a little
break and we're going to get back to some sound design.
40. Effects in Sonic Pi: So as well as being able to use synthesized and samples
within Sonic Pi, There's also a whole bunch
of built-in effects. And these are very much like the effects that
you would apply to a track or two and
instruments in your DAW. Or if you prefer to play
analog instruments, perhaps using guitar effects, pedals, that kind of thing. But you can see there's well over 40 different effects
built into Sonic Pi. So let's have a look
at how we use them. To demonstrate these effects. We're going to use
the sample that we used earlier that
I've gotten my desktop. So let's remind ourselves
how to do that. So we're going to
play the sample, which is in users. Steve. It's on my desktop and
it's called b21 dot. Let's just remind ourselves
of what that sounds like. So to apply effects to this, all we need to do is wrap
it with a width FX blocks. So Let's go to the
beginning here, we say with underscore effects, and then we give it the name of the built-in effects
that we want to use. You can see all the effects
down here in the bottom. And you can see
here's the same list of effects I showed you before. So we just need to
give it the name. In this case, we're
going to use a river. So we can say with
effects codon, reverb, do we need
to end that block? And so when I play
it now you're here, that's a reverb effect has
been applied to that sample. So it doesn't need
to be a sample. It could be a synthesizer, it could be a simple plane command. But this sample, particularly,
because it's a drumbeat, it shows off the effects
particularly well, they're particularly
easy to hear. But we could change
this affects to be this effect to be
anything we want. So we can look down through the list and
find something we might want to apply a
flanger, for example. So let's change the
reverb to be a flanger. Or we could change it to be a distortion effect
for a dirtier Sam.
41. FX options: So as with many of the items
we find inside Sonic Pi, there are a number of
parameters that we can apply to effects in order to
customize the sun we get. So let's start with
adding an echo effect. This is like a delay. So
we'll say width affects echo. Do. We'll end that block. And then to keep this
nice and simple, let's, let's just
use a simple place. So we'll, we'll play a note, a 55 will sleep for two. Maybe let's use a sample. We could use the cow bell. We'll sleep again, and then
we'll play one more note. So we'll play, I don't know, 67. So let's listen to
what that sounds like. Okay, so that's what an echo applied to all of those
notes and samples. But we can actually change
some of the parameters. And you'll find that as we look down here,
we can, in this list, you'll see that every
Effects has got its own set of different
parameters that you can apply. So let's just look
in here for echo. Okay, and we can see
in here that we've got things like the phase, the amplitude, and
mix the decay. So if we look at, look down
this list and we can say, we can see that the phase
sets the time and echoes, or the sign between
echoes in beats. So let's change that. So all we need to do the same as every other parameter that
we've been passing around. So we hit comma, we then say, let's set the phase equal to, and we'll set it to half a beat. Let's listen to that.
And there we are. So a much slower
repeats on the echo. There.
42. Chaining effects: Now we can nest effects as well. So when we nest affects, all we're gonna do is very
much like nesting loops. We're just going to put that
block inside another block. So let's add a reverb and
I'll show you how to do it so we can add another effect
on the outside of this. So we'll add a reverb this time. I will need another
end on the outside. We can see that we've
got this affects block, which is the echo
that we just created. And now we've wrapped
that inside a reverb. And you should think
about the audio flowing from the inside out. So the first thing
it's gonna do is going to apply the echo effect, the delay effects
the echo effect. And then it's going to apply all of that to the outer block. So it's going to add
a reverb to the echo. The echo be applied first
and then the reverb. This is very much like the way we chain effects pedals or, or effects units
together on audio. So you can use really, really deep nesting
for some really, really crazy or
innovative sounds. However, applying the
effects uses quite a lot of system resources
from your computer. So just a little warning if you apply too many facts you were early or you may notice some performance
issues. But to spine. So let's run this and we'll
hear now that we've got an echo with a Reverb on top.
43. Taking control: So on occasion, we
may want to be able to control a sentence
already running. In order to do that,
there's a function built into Sonic
Pi called control. In order to use that, the first thing we're
going to do is capture the output of the sent
into a local variable. So we'll create a
variable called my synth. We'll create a variable
called myosin. Into that we will
capture the output of a play command will
play a midi note 40, and we'll set the
release to five. This note will still play, but
the output of it will also be captured into that
my synth variable. We can then do a little
sleep, take a little break, and then we can use
the control function to change things about that synthesized so we
can say my sin. We could then set a
whole bunch of values. In this case, we're going to change the notes and
we're going to say, okay, now play a 45, will sleep again, will
control the synth again. We'll change the note
to be a 47 this time. Then we'll take a longer sleep. And finally, we will change
the note again to a 40. Now this is, this is a particularly useful function to use because if you remember, we set pan and amplitude and cutoffs and things like that
before or when we set that, we said that it only applies
to the current function. So when I do that, if I was to do a play 14, set the panel the
way to the left, I would need to set
that pattern for every single note that I played. Now I can, I can
create my sense store. It, creates this release,
for example, here. I can store that in
the output by center. Now I can control my synth. I don't need to define
the release every time. And you can imagine if I had a complex envelope and I said
a lot of values in there, it means that I only need to
set that on the first note, the first time
That's int is used, capture the output of
that into a variable, and then I can just
make the adjustments that I see fit probably just to change the
notes rather than having to set all those
parameters every time. So let's listen to
that. So the reason this is particularly
useful is that early Rome, when we look to
the play command, we talked about
amplitude pounds. We looked at filters as well with cutoffs and
resonances, et cetera. And we said that, that
those parameters will only apply to the particular play command that's
been executed. So if I wanted everything pan to the left and I wanted to use the play command,
for example, I would need to add a pan minus one to every
single note that was played. Whereas now I can set
that on the original, on the first note, capture that the output of
the synth into a variable, and then I can use
that throughout. So I don't mean to set an envelope on every
single every single night. If I want to keep the
envelope the same, the power and the cutoff, the, the filter
resonance, et cetera. So let's demonstrate
that a little bit. Let's use a sentence. So synth will use this base
foundation and we need to do, and then we will end
this synth block. So now it's gonna do
exactly the same, but it will use this
base foundation synth. So I can add my
parameters in here. So I might say the, for example, I can set the
patterns or minus one. And what this is gonna do is
rather than having to have powered minus one after
every single play Command, I now set it here. It's captured within
this variable and the parameters that
I've applied here, I can control throughout
or applied throughout. Now there is a slight
restrictions to this. So things like AMP for
amplitude with the volume, the cutoff, pan, things like that can be changed once
a synthase started. But you can't change ADSR
envelope parameters. So I can't change
the release once a, once a synthase started. But I can control other items. So like the pan. I could in here, I could say control my synth and then I can
set the note of 40. But on the final one, I might pan it all the way to the right. You can see again, this is
another way of using Sonic Pi to take shortcuts to stop
you having to repeat yourself all the time and really control the synthesis playing. So have a play around with
the options in there. And I think you'll
find it. Like I said, it's quite an advanced function, but I think you'll
find it's very useful.
44. Controlling note slide: Another thing that
we have when we use the control function as we can use a thing called note slide. And this is kind of like a glide or report
them into effect. So we can add this when we declare the
original variables. So let's, let's add it here. So it's just a matter
of added another parameter or another option. We can say note
underscore slide. And we set one. So again, everything in Sonic Pi when we prefer to time,
It's the number of beats. So in this case
it's going to take one beat slide from
one node to the next. So let's hear what
that sounds like. Necessarily. Again, I can make this
really long or much shorter. We can hear a slight in, much more quickly
between notes. Now.
45. Controlling effects: As well as controlling sense, I can also control effects. So let's, let's try that. So let's apply an effect. So exactly as we did before. Let's apply this
one's quite good. We'll apply the wobble effect. Here. We need to use the
pipe operators to provide a variable name. This is how this
control works with effects slightly different to the way it works
with synthesizers. So we just give it a variable. It doesn't really matter
what their variables called. I'm just going to call it f x. So I will have an
n block as well, or we will end the
block as well. Then inside there we
will use a synth. So we'll say with synth will use the profits n for that one. Then we'll just add
a little bit of code inside this with synth block. The block works in
exactly the same way, really is the huge synth that we use in command that
we've used earlier. You sent me tend to place near the top of our code and it will use that same
throughout with synth. Just says, okay, just use this synth between the do
and the end of this block. So it's just a way of
constraining that really. So let's say in here
will play a 40 with a release of four. We will then sleep for four, and we will then
control that effect. So what we're gonna do, in fact, let's just play that before
we start controlling things. So you can hear the wobble
effect as it is by default, will then begin to
control that affects same, same method name. So we'll say control. This time we need to pass
it this variable here. So this variable that
we declared at the top. So it knows which affects or effect that
we are talking about. This time, we will set
the mix to not want to. So this is the
amount of wet signal that is going to be output. Will control the effects
on them, will play again. We'll play a
different note with, again with a release of four. So you'll be able to
hear the change in the mix of the effects are how much of the effect is output between the first
and the second note. So you can hear that much
more of the dry signal got through in the second
note that was played. We also have some options
for sliding effects. So let's just, let's
just remove this. In this case, we
can set a few of the parameters that are found
inside the wobble effect. So again, down in the Help panel here we've got a list of all the
list of all the effects. When we click on it, we can see all the parameters
that we can set. So let's set a couple
of parameters. So let's set the phase,
the face to one. We could also set a thing
called the Face slide. And we'll set that to six. So inside here
then we'll, we'll, we'll play our synth will just make that lasts
a little bit longer so we can hear the whole
of the face slide. Let's hear that. Now. Then we can control
that. So we can say control the effect
as it's playing. And we can set the face down to something
much, much shorter. Okay, So as I said, the effects are
slightly different. We need to give it
a variable name between the pipes when
we declare the effect. But you can really hear
that last example that the effect is being controlled
as, as it's happening. So we only play one note, but the effect, because we set the release to
be a long time, the effect is actually being changed as the note is played.
46. Live loops: Okay, so time to talk
about live performance. So there is a particular co-constructed that's
built into Sonic Pi, which really does enable
live performance. Let's, let's consider a loop that we might have
used in the past. So let's say due and then end. Then in there, we'll
do something simple. So we'll, we'll play 60
animals sleep for one. Let's, let's play that. Now this is going to
keep going forever. But what happens if
I change this note? Let's change this to an 80. I'm just reminding. You can see that the loops
continued to play and just another loop is added
on top, on top, and on top. Now this is not ideal
for live performance is the thing that we
really want to do when we're performing live. And Sonic Pi is to be able
to go and make changes to our code and have those
changes reflected live. So not separate loops playing
on top of each other, but actually change the loopless
running as it's running. So the way we do that is
through the use of lively. So let's do that. So all we do is very similar
constructs in the loop, but we use the word live
underscore loop instead. How about we do this? We
need to give this a name. So let's just call this foo. So it'll become clearer later why we need to
give them a name. But now when I run this, I'm doing exactly as you expect, looping around playing
60 monks rather. If I change it to 60, listen to what happens.
If I change it to 70. So cleverly, Sonic
Pi is able to detect the change and make
that change live as, as my program is running. Now this has got, this opens huge possibilities for,
for live performances. And you'll notice
it was very clever that it didn't make the
change immediately. It waited until
the right points. So if I change this
to asleep for 234234. Now if I go make this
change and changes to 55, and I do it immediately
after a note. You'll notice that it waits and continues
to sleep and doesn't actually restart the loop until the right moment to see
if I can hit it right. So we'll always keep that internal timer
running and we'll continue the loop and won't make that change until the
next time they executes, rather than executing
again immediately. So this gives us
great possibility. So we could, for example, let's set this to
something a bit more affordable unless that sleep back to a shorter period. So we could, we could do all sorts of
heroes were replaying live. So we can say sand can change
this to three or three. And we can talk as much
code in here as we want to inform us and it won't actually be executed until I press Command R or press
the Run button again. Slowing us down. I'm so sorry. Sorry. The facts. Just riba. Change the notes. The notes. So you can see what's
happened here is I haven't I've added another note, but I haven't been asleep. So it's effectively playing both these notes
at the same time. Another synth. And there we go. You can see how we
are able to make changes to our code
as much as we like. And then when we press Command or Control R
or hit the Run button, then the next time round
that loop is executed, then the changes
will be made life. So again, a fantastic way to kinda be able
to perform live. Start with a initial code base, our initial piece of code, and then go and make
your changes life to really add a performance
element to it. So we can have multiple live loops
running at the same time. So remember before, if we
had something like this, if we had a loop do
hidden here, we, let's, let's, let's just
play a note and then end. Then we might have another loop, which might play a, play a cow bell. So what's going to happen
here? Hoping each but asleep. The same here. Now of course, the second
loop never actually placed. We never get to
hear the cow bell. And that is because
this loop is going round and round
and round forever. So the sequence of
the program flow never actually makes it
down to the second loop. Lively. Does this
slightly differently. So if I change this
to be a live loop, and we can, again, we
need to call it a name. So let's call this one foo, and change this one to a
live loop and call this one. Bar. Will now see that both loops
play at the same time. So let's just make sure that
we can hear the sounds. Let's just change the
sleep inside here. There's gonna be a bit
of a weird rhythm, but it will mean that we can hear both sounds
playing at the same time. So this means that we can have multiple loops run
at the same time. And you can see this
would be really useful for live performance. So where we want to
have a, perhaps a, a drum pattern play a melody, maybe some chords or baseline. And we can have all of those playing independently
within their own loops. At the same time. It keeps the code nice and clean,
really easily, readable. And we're able to change it in real time as we're performing.
47. Live performance with live loops: Okay, So earlier on we wrote a sequencer which looks
a little like this. Let's just remind ourselves
of what this sounds like. This is great, but I'm not ever so useful for live performance. So how can we take this code and convert it into
something that might be a little bit more useful
and then perhaps add on a baseline or something. So let's have a look
at what we could do. So obviously, we need to start off with a
lively per mil core. This Trump's. So that's all changed. We need to do now so I can go
in here and I can run this. I can change the pattern live. So let's add three kicks at the end. We can hear them. As part of our performance, we change the kickback. So let's add another live loop. This time, I'll add a baseline. So let's create a live loop. Do we need to give it a name? So let's call this
the library base. Let's remember c, n the loop. And in, inside this loop
then we'll use a synth. So we will use, you will use the superstore. And then what we'll
do is we'll have a, a loop in here which
looks 16 times. And we will end the loop. And then inside this loop, we will play a note from the minor pentatonic,
minor pentatonic scale. So we will play from a scale
based on midi note 40. We will play a minor
pentatonic scale. And we'll just choose a
note from that scale. A couple of other parameters just to make it
sound a bit better. So we'll set the
release to be 0.3. And we'll say only
play if one in two, so with a probability of one and to play one of the notes. So just choose a note at random from the minor pentatonic scale. But then need to sleep
because we're in a loop. So we will sleep for
0.25 or quarter repeats. And here we go. So let's just, let's just run this and
hear what it sounds like. That sounds fine because we are playing at the same kind of
rhythm and both the sink, because both started
to play together. However, one of the things that you might
want to do in, in, in a live performance
is to add a new lipid, or quite commonly the
Live loops you might construct beforehand and then comment out and then uncomment. But let's, let's pretend I could just cut this into my clipboard for now and
we'll start this one running. So let's pretend
I typed this back in now and I'm going
to hit the Run button. It doesn't sound as
good this time round. It's not in sync with
the, with the trumps. The bass sounds out of
time with the drums. Now this is a really, really simple way to fix this, and it's built into Sonic Pi. And all we need to do is inside, are inside our libraries. And this is why we give
our live loops and name. We just say simply sick
this with the drums. Sick this with the drums. So now when I introduced
this live loop, if I just cut this to the
clipboard again, paste it in. When I press the Run button, it's going to wait
until the right point in the library to
start the baseline. So there's always stays in sync in a matter of
when I press Run. So now I'm like
performance is underway. We could choose to
change a few things. So maybe you want to
change a baseline. So one easy way to
do that might be to change the random
seed that we're using. So let's say you use an underscore random
seed press Run. We might want to change the
one invaluable be using. Now we're getting less
notes and the baseline. You can remove this
one a1 altogether. So now we're play every note. We can introduce a
different kettle, different snare. There we go. And we can keep
on making change as the, as the music is playing outline. So you can really see how
you can use Live loops and sinking between live
loops to make sure everything stays in
time with each other. And just be able to change
your code as you wish, as the performance is going on.
48. MIDI in: Okay, So as well as using
code to play music, we can also take input in
from a midi controller. So we need to set up a couple of things inside their preferences
to enable this. So if we go over to the
Preferences window here, if we go to I0, we can see here that
we've got this enabled. So minus minus takes yours
might be disabled here. So we need to make
sure that we enable incoming cuz then you can see that I've got my my
midi keyboard enabled here. So let's close that.
And we'll see that. This is another
instance where the, the cues panel can be
particularly useful. So for example, if I press
a note on my keyboard now, you'll see that logged in here is the name of the controller. And it's telling us that
my archery or key step 37, which is the name of
my midi controller. There was a note off,
a note on event, followed by a note off events. And what this is telling us is that the notes on was a note 60, which is a middle seat. This second part of this
list here is saying 100s. That is the velocity with
which I press that note, if I press it again, I'll
get different velocity. So there we are. That was a 112. A different note will give
me a different number. So this was a note 67, which was a G, And I hit
that with a velocity of 115. So we can use this
information that's coming in from our
midi keyboard to play some music using perhaps a synthesizer or a sound that we've created inside Sonic Pi, but be able to play
it on our keyboard. So this is how we go
about doing that. So first of all, let's create a lively work. Just call this one midi example. That's fine. Let's end that. Then in here, I need to
do a couple of things. So I need to create two variables so we
can separate these variables. So these are the most of velocity and this is
what we're going to get from this list that we
see in the queue here. So this is the note
number and the velocity. We're going to say
that a sync this to a. Now we need to give it the name of the event that's happening. So in our case then, in quotes, we're going to say exactly as it's written in
the queue panel. And here we are. So it's going to pick it up from the
queue panel for us. But we're going to
say middy, colon are shari'a key step 31371. And this is the note on the pen. So we want to say,
when we get a note on, I want to use a synth. I'm going to use the piano. Piano. And I'm going to
pass it the note that came in from
the midi keyboard. And I'm going to pass that to the note parameter
or the no option. I'm going to set the amplitude to be
whatever the velocity was divided by 127. The reason for that is
because the amplitude that comes from Midea is
a value between 0127. But the amplitude parameter or the amplitude option within Sonic Pi is set as a value
between usually between 01. So we're just going
to take that, take that velocity that comes in divided by 127 and that'll give us a suitable
amplitude for site Pi. So let's run that. And now by pressing
notes on my keyboard, I'm able to play the piano synth from with inside of Sonic Pi. And again, if I'd
added any filters, envelopes, and he kind
of ADSR parameters, etc. They will be reflected as I, as I play my midi keyboard. However, if you've got a
midi keyboard connected and you have just
used this example, obviously replacing this part
here with whatever your, your keyboard is called
from the cues panel. You'll notice that there is
a great deal of latency. Now this latency
actually exists on purpose and we can remove it, but the latency exists. I can guarantee that when
you press this button, there is exactly 2.5th
between new pressing a key. And you can actually see that if you look in the accused panel, there's a 2.5th delay between
when you press a key. And when they
actually sounds out. Now, this, this latency is built into Sonic
Pi on purpose. And it really helps with the
timing because computers, depending on what else is
going on on the computer, computers can run a
very varying speeds. So in order to be able
to have things sink and work in a steady rhythm is we want to in a piece
of music normally, depending on what's
happening on the computer, this 2.5th delay
is introduced on purpose to be able
to counter that. So it's really simple to remove that latency if we
want to play in real time. And we do that by just
a simple command. So we just say use
underscore real time. Now when I press Run, the notice sounded
immediately that I pressed the relevant key on my
midi controller keyboard. So this is all well and good. And you may say, Well
Steve, that's great, but I can already
play a synthesizer. I've got what it
might door, I've got a standalone synthesizer
that I can use. But actually now we
can apply some of the programming that
we've learned to our, to our synthesizer as it gets
some interesting results. So we could say
something like this. So instead of using this synth, we could say, okay, well, when I press a note
on my keyboard, just maybe notebook,
but excuse me, something at random from a scale that's defined by
the note that's passed in. And then just play me
something and random on the major pentatonic scale. Depending on the note
that I've chosen. Anywhere within three octaves. And set the, as we did before. Let's set the amplitude to the, to be the velocity
that's passed in. So how hard or how fast we hit the keyboard divided by a 127. Don't worry, if you miss
the amplitude setting off. You'll just play at
the default amplitude of one no matter how
hard you hit the key. So it worked perfectly fine. Without it, you'll lose the velocity sensitivity
of your keyboard. So what's going to happen now is whatever I play
a note is going to choose a note at the
major pentatonic scale, somewhere in three octaves for the notes that I have pressed. So I'm going to press
a middle C or S3. And so when I click Run here, every time I press this note, it's going to play me a note from the major pentatonic scale. You can see in the
queue is here on the, on the, on the cues panel. I've just been pressing
middle C 60 throughout. But it emits a different note. Somewhere within the
major pentatonic scale, within three octaves of
the note that I played. Now, it's a good example
to be able to show you that perhaps we can achieve
some useful things with code. But let's have a
look at perhaps a more and more useful example. Let's just remove this. Play again. This time, we'll use a synth, so we'll use the fluxes. Well, we'll keep this code. This code is perfectly good. This is just saying, okay, this is just creating
a live loop, is saying to use real time
and to capture the notes and the velocity from the note
on event from our keyboard. But this time we'll
do something a little bit more interesting. So let's say every
time I press a note, I want to play a timed pattern. So instead of just
playing one note will play a series of notes. So let's again get the
scale from the note. From the notes that we, that we received
from the keyboard. And we'll use the minor
pentatonic again. But this time we're
going to reflect it. So we'll play the whole
scale up and down. And because we use in
play pattern timed, we need to tell it
how long we want to pause between, between notes. So we'll set this
to be very short. And then we'll again
set the amplitude to be the velocity divided by one
hundred and twenty seven. Twenty-seven. So let me just move this over a little bit so we can
see the whole line. So as I play a note
on my midi keyboard, it's going to play me the
minor pentatonic scale, based on the note
that I've pressed. And it's going to play it very fast all the way up and then back down again at the
velocity that I pass in. So let's hear how that sounds. So you can see that I'm
just pressing in OneNote. We play in that whole
pentatonic scale all the way up and all
the way back down again. And of course I can add
another object to this so I could say octaves. Very good. So you
can see that we can really write
some code that is triggered when we
press a note on our midi keyboard to do a whole range of
different things. And people have used this to really great effect
joined by performances, particularly with different
types of midi controllers, to be able to trigger different functions based on
the note that's played in. So if you have a
midi controller, whether it's a keyboard
or whether it's a PAD, have a play around
is quite easy to set up as we saw inside of Sonic Pi. And again, there's
more help for you available in the Help panel
around setting this up. But it's really
quite simple to do. And it's a really, really powerful live
performance device. So not only do have
the ability to change code live within
Live loops as you perform. But also you can use a
midi controller to add some different dynamics
to your live performance.
49. MIDI out: Okay, so that covers how
we get into Sonic Pi. But Sonic Pi can
also emit muddy. So we can control
other midi devices or send midi to our
DAW from our code. So to demonstrate this,
I'm going to use a synthesized as a fantastic
free synthesizer called vital. It's a synthesizer that I
use on my complete beginners guide to synthesis and
sound design course. So if you want to learn
more about vital, please do go have a
look at that course. I'm just going to load up
a preset that I created the other day called
the Skynet quiet. So this is what
that sounds like. Okay, so that's synthesized running and I can play
with my midi keyboard, but I can also play
it using code. So I can see that
in the preferences that I have a connected output, which is my archery
a key step 37. Now, this is not something
I can figure out. This is something that
Sonic Pi was able to pick up as it opened
based on the, the devices that I had
connected to my computer. So I can set my default
midi output channel. I just leave that set
to all and we can control which channel
we can use encode. And this can be useful
if you're using something like contact
where you could have multiple instruments
running at once and send different commands out to different Midi
channels to be able to control different contact
instruments, for example. But we'll keep it
nice and simple. We use vital. So let's
write a little bit of code. So all we need to do is
use the command midi, midi note on to start the
midi note playing or to send a midi note on command
to midi output device, our keyboard in this case. And then go off to say, okay, now really subtle. So let's, let's run a little bit code so we
can say midi note on. There we go. So we can say emitting light on. Let's play an E three. It actually doesn't
matter whether use a lowercase or an
uppercase here. But I'm just using
applications to keep it consistent throughout. We can say, then
we're playing E3 and we will play it
at a velocity of 50. And we will send this
out to midi channel one. We're then going to
sleep for four beats. And then we'll send
the midi note off command, midi note off. And again, we'll need to say
which note to switch off. So we're going to switch off
the E3 that we just sent. And again, this is gonna be a command that we're going to send on channel number one. Let's, let's run that. And you can hear that
coming out the synthesizer. Now if I run that again, you can see actually the bottom of the center
I bought my vital. You can see on the keyboard
midi note actually been sent. So it'd been sent through
my midi controller. And backups are vital. As I said, with different
virtual instruments, you could certainly and I have controlled contact directly from within Sonic Pi based on the midi
channels that I send it. However, I've just
choose, chosen to use vital in this
instance because it's a fantastic and free synthesiser so everybody can follow along. So let's add another
note as well. So let's send a midi note. On. This time we're
going to send it an A4. And again, we'll use
a velocity of 50 and we'll send it on channel one. Will sleep for. And then we'll suddenly
really know off. And we'll tell it
to switch off no, a4 on channel one. And let's press Play and then, or rum and then
flick over to vital. There we go. So a
fairly simple example, but it does demonstrate
how you can send midi out of Sonic Pi and into whatever instrument or virtual instruments
you want to connect to. And it's certainly one
great use for this might be to control and an
external analogue synth. So you might want
to connect this to some sort of external
synthesizers that you've got out from your
computer through a midi cable and then
send midi commands out of Sonic Pi to
control whatever. Since that you might have.
50. Live audio: Okay, and there's one
more way that we can enhance our live
performances with Sonic Pi, and that is through
the use of audio. So we can actually
take audio in from a microphone or an external
instrument like a guitar, and actually access
that through Sonic Pi. And we can apply a
bunch of effects and write code around
the input that we get. To set that up, you need
to go to Preferences. Go to the audio section, make sure that you have
enabled audio inputs here. So in this panel down
the bottom here, if it is disabled, just click that to
enable the audio inputs. So Sonic Pi can take audio input from a number
of different places. So it could take it from the microphone on your
computer by default. It can take it from an
external sound card or an audio interface. And if like me, you
have an audio interface with multiple channels on it, then Sonic Pi is going to
take the audio input from the first channel on your audio interface into the first channel on the
audio interface that I have, I have plugged in my guitar to play that through Sonic Pi, I simply need to use the
live audio commands. So I can just say
live underscore audio and I need to give
this live audio and name. So I'm going to
call it a guitar. And now with this command
when I press Run, you should now be able
to hear the guitar coming through,
through Sonic Pi. Then we are, we can see over in the scope and the
top right here, we can see the spectrum
analysis of the audio input. So let's press stop
there for now. And as I said, this doesn't need to be guitar,
could be a base, could be a keyboard, could
be a microphone, etc. The exciting thing is it enables us to add effects, for example. So we can just wrap this
with an effects loop. So let's say with
underscore effects, Let's add a reverb. So now when I, when I run this, I should have my guitar
sound as I did before, but with some reverb, I can add some
distortion press Run. And of course I can next these
effects as it did before, but as I said earlier, just be cautious with this. If you start adding
too many effects, you will find that
you start to suffer with a bit of performance,
with some performance issues. So, but we can add a reverb, for example, on the
outside of here, and we need another end loop. Let's format that and run that. And now I should have a
distorted guitar with revert. Okay, let's get some
really interesting by performance possibility. Flick over into this buffer rather than typing this all in. I've, I've, I've saved this into a different buffer and I'll
talk you through the code. So at the top here
I've got exactly the same as we had in
the last section. So just the live audio coming in from the guitar through my
audio interface and just applying some distortion
and some reverb so that we then set the BPM to 96. Just for this
example. We've then got a live loop which is playing a drum sequence in a very similar way to what we've seen before in
previous sections. So just using this
drum pattern here that we've described in these strings to play
our three drum samples. We then got a loop, another live loop going on, which is just
playing a bass part. So this is using a
cynical base foundation, and it is just looping
16 times and choosing a note from the minor
pentatonic scale or the E minor pentatonic scale, choosing a random row
for that and it's playing one note
every half a beat. And then we've got
another library, which is called keys. And this is using
the piano synth. And again, it's choosing from the E minor pentatonic scale, but three octaves above this one or two
authors mother on, and it is playing a
note every quarter of a beat and that's going
round 16 note loop. Then on top of that, because
we have the live audio, I can play input through
my audio interface. On top of the sound is being
produced with Sonic Pi. And I can actually
record this out to a audio file with Sonic Pi playing my
code in the background. And then with the lipids are on top by pressing the
Record button here. And then pressing Run. And then stop the recording. And it lasts me where I
want to save this file too. So I can save this to my
desktop, for example, audio. Click save. And then
over on my desktop, the file has been
output as a WAV file. And I can listen to that
through the Mac audio player.
51. Wrapping up: Okay, so that's it
for this course. We've seen some of the fantastic possibilities are
opened up when you use Sonic Pi to write
code to create music. But there are about 250 different separate
commands in Sonic Pi me, we've only really just
scratched the surface. So look in the lung
section of the, of the health panel and really have a
dig around in there. All the commands have got
really great documentation. On that note. I'd like to encourage you to
look in the examples panels. So if you look in
the health panel, look under examples
and you'll see some really great examples that have been provided
with Sonic Pi. I would certainly
encourage you to have a look at some of those and dig through that code and really read through
it and understand it. I can recommend a good, one. Good place to start might be
something like Tilburg two, which is one of the
examples in there. You simply click
on the example in the health panel and then
you can copy and paste the code out into one
of the buffers in the code window in inside, inside Sonic Pi, you
can play it and make changes to it and
really experiment. Remember, there's no mistakes. You can't break anything by, by experimented inside Sonic Pi. And who knows some of these
experiments might turn into your next
great musical idea, your next great musical output. So it's a really great way for just experimented and
discovering new music. Just don't forget to save
your work regularly. As I said, Sonic Pi, we'll store it inside the
buffer when you reload it. But, but just to be sure, I always like to when I'm really particularly
happy with something, take a separate copy and save
at ways of separate file. And there's always
the undo button. If you do, if you do experiment and you go along the path you don't
particularly like, then you can always
undo your way out or revert to a
previous safe states. But that really is it. So have some fun and I really encourage you
to try some live performing, even if it's just yourself in
your room performing a log, maybe in front of some
families and friends, or when you get
really good at it, go ahead, stage, go and
show off what you've got. Have a look for algo rave. So just a few Google
algorithm will send you to the algorithm
website and you can see where some other people who've perhaps in your area or putting on some
live performances. It just takes a bit of practice. This is the same as
any other instrument. And so I really
encourage you to spend your time each day
the same as you would if you were learning
the guitar or the piano, the harp, or any
other instruments, just spend your time, a little bit of time each
day practicing Sonic Pi, practicing a live performance, trying out different bits of code and different experiments, that little bit of practice
each day we'll get you proficient in
no time at all. I'm sure. Be shorter you to share your code and your music
with the rest of the world, either through the community
on the Sonic Pi website or however else you feel free, you feel comfortable to do so. I love to hear from you again, so please do share
your code with me. Do share it on this website. If you'd like to learn
more about some of the other courses and the other
things I've got going on. Then please do
head over to Steve live with music.com
and you'll find out everything you need to know that it's been fantastic to have you Thank you so much for watching and I'll
see you again soon.