The objective of this lab is to explore JES's musical capabilities.
playNote
takes three arguments: the
note that should be played, the duration of the note in milliseconds,
and the volume of the note specified as a number from 0-127.
Individual notes are expressed as integer values from the MIDI music
encoding. You can find out which number corresponds to which musical
note be referring to the table on the following
website: Note
names, MIDI numbers and frequencies . The note numbers are in the
column on the left hand side of the keyboard graphic. The following
command would play a C note lasting one second at full volume:
>>> playNote(60, 1000, 127)Experiment with passing different values to the
playNote
function
until you have a feel for how it works.
playNote
. In practice, it is
cumbersome to make so many function calls. It would be more
convenient to be able to make a single function call that would play a
series of notes. The following function makes this possible:
#playNotes - Play a series of musical notes at a given volume. #notes - an array of integers: [note#1, dur#1, note#2, dur#2...] #volume - a volume from 1-127 def playNotes(notes, volume): for noteNum in range(0, len(notes), 2): playNote(notes[noteNum],notes[noteNum+1], volume)The first argument to this function,
notes
, is a list of
numbers that represents subsequent notes that should be played, along
with their durations in milliseconds. For example, the following
function call will play three C notes in a row, the first for .5
seconds, the second for one second, and the third for 1.5 seconds:
>>> playNotes([60, 500, 60, 1000, 60, 1500], 127)Notice the brackets that are used to denote the beginning and end of the list.
Copy and paste the playNotes
function
into JES. Experiment with this function.
playNotes
function. The following function plays Frere
Jacques:
def brotherJohn(dur, vol): bar1 = [55, dur, 57, dur, 59, dur, 55, dur] bar2 = [59, dur, 60, dur, 62, dur * 2] bar3 = [62, dur/2, 64, dur/2, 62, dur/2, 60, dur/2, 59, dur, 55, dur] bar4 = [55, dur, 50,dur, 55, dur * 2] playNotes(bar1, vol) playNotes(bar1, vol) playNotes(bar2, vol) playNotes(bar2, vol) playNotes(bar3, vol) playNotes(bar3, vol) playNotes(bar4, vol) playNotes(bar4, vol)In this function
dur
is the duration of a quarter note in
milliseconds, so dur * 2
represents the length of a half
note, and dur / 2
represents an eighth note. Changing
the value of dur
changes the tempo of the song.
brotherJohn
write your own song function. You can try to recreate a tune you
know, or you can just use your imagination. It doesn't have to sound
beautiful. Don't compose your song by stringing together one long
series of notes. Most songs have repeated structure that can be
handled as they are in brotherJohn
or by using loops.
Your song function needs to have a tempo parameter similar to
dur
in brotherJohn
. You will make use
of that parameter in the final exercise of the lab.
playNote
function is that it doesn't
actually return a sound, it just plays the note. That means that it
can't be used to make a sound that can be saved to a file. We've
provided a set of functions that solve that problem. Copy the
functions from this page into your
.py file. There is a lot of code there, but you shouldn't panic.
Many of these are functions we've already written in previous labs.
Some of these are helper functions that we won't be calling directly.
returnNote
and returnNotes
. These work just like
the playNote
and playNotes
functions except
instead of playing the notes they return them. The following function
call will return the first bar of Frere Jacques:
>>>sound = returnNotes([55, 200, 57, 200, 59, 200, 55, 200], 127)Try it out.
playNote
, we could string one note after
another just by calling playNote
multiple times. When working with
returnNote
, we need a different way to string notes together. This
could be done by making multiple calls to the appendSound
function. An easier way is to use the appendSounds
function.
This function takes a list of sounds and sticks them together end to
end to make one longer sound. The following function shows
how appendSounds
can be used:
def returnBrotherJohn(dur, vol): bar1 = [55, dur, 57, dur, 59, dur, 55, dur] bar2 = [59, dur, 60, dur, 62, dur * 2] bar3 = [62, dur/2, 64, dur/2, 62, dur/2, 60, dur/2, 59, dur, 55, dur] bar4 = [55, dur, 50,dur, 55, dur * 2] n1 = returnNotes(bar1, vol) n2 = returnNotes(bar2, vol) n3 = returnNotes(bar3, vol) n4 = returnNotes(bar4, vol) s = appendSounds([n1, n1, n2, n2, n3, n3, n4, n4]) return sTry out
returnBrotherJohn
and then make a version of
your own song function that returns the song instead of playing it.
You might also want to try out the returnSquareNotes
function. This returns notes made with square waves instead of sine
waves. They have more of a sci-fi sound.
Hint: It may be helpful to generate an initial sound object with a single sample, so that you have something to append your first verse to. For example, before your for loop you might have a line like the following:song = makeEmptySound(1)
This lab was optional, so there is nothing you need to submit.
You may now start on Programming Project #3: Audio Collage.