The objective of this lab is to explore JES's musical capabilities.
playNotetakes 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
playNotefunction 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
into JES. Experiment with this function.
playNotesfunction. 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
duris the duration of a quarter note in milliseconds, so
dur * 2represents the length of a half note, and
dur / 2represents an eighth note. Changing the value of
durchanges the tempo of the song.
brotherJohnwrite 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
brotherJohnor by using loops.
Your song function needs to have a tempo parameter similar to
brotherJohn. You will make use
of that parameter in the final exercise of the lab.
playNotefunction 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.
returnNotes. These work just like the
playNotesfunctions 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
playNotemultiple times. When working with
returnNote, we need a different way to string notes together. This could be done by making multiple calls to the
appendSoundfunction. An easier way is to use the
appendSoundsfunction. This function takes a list of sounds and sticks them together end to end to make one longer sound. The following function shows how
appendSoundscan 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
returnBrotherJohnand 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
returnSquareNotesfunction. 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)
shiftfunction, and the
echoesfunction from the previous mini-lab, as well as the song you composed in this lab. You should also include a link to the increasing tempo version of your song. For shift and echo, you should include the original sound and the modified sound. Since we do not have pictures to look at, it is even more important now that you add some text to describe what the viewer will be listening to. You might consider using a table to organize your sounds. Remember that to add sounds to your web page, you can just add them as you do links.
.wav) files that should be on it to your personal web space on
kzoo.edu. (You may want to review the instructions in Lab 1 if you've forgotten how to do this.)
You may start on Programming Project #3: Audio Collage anytime after finishing this lab.