Lab 09: Exploring Music
- Learn some fundamentals of sound and music
- Create musical compositions
Having explored and used many of the robot commands by now, you have seen that your robot make beeps when you call the beep() function. For instance, if you execute the following command:
This command tells your robot to play a tone at 880 Hertz for 3 seconds. Hertz is
a unit that measures frequency.
1Hertz = 1cycle / second
Therefore, a beep at 880 Hz represents 880 complete cycles per second. Humans can hear frequencies in the 20 Hz to 20000 Hz (or 20 Kilo Hertz) range and are able to distinguish sounds that differ only by a few Hertz (as little as 1 Hz). This ability varies from person to person.
Try the following commands and see if you can distinguish between the two tones:
beep(1, 440) beep(1, 450)
To make the tones more distinctive, place the commands above in a loop so
that you can repeatedly hear the alternating tones.
Do This: Program your Scribbler to create a siren by repeating two different tones. You will have to experiment with different pairs of frequencies (they may be close together or far apart) to produce a realistic sounding siren. Write your program to play the siren for 15 seconds. The louder the better! You can also have Myro make a beep directly out of your computer, rather than the robot, with the command:
Do This: Try the siren program on your computer instead of on your robot.
In western music, a scale is divided into 12 notes (from 7 major notes:
ABCDEFG). An octave in C comprises of the 12 notes shown below:
C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B
C# (pronounced "C sharp") is the same tone as Db (pronounced "D flat").
Frequencies corresponding to a specific note, for example C, are multiplied (or
divided) by 2 to generate the same note in a higher (or lower) octave. For instance
in the two tones shown below, the second tone is one octave higher than the first:
Therefore in order to raise a tone by 1 octave, you multiply the frequency by 2.
Likewise, to make a tone 1 octave lower, you divide by 2.
Notes indicating an octave can be denoted as follows:
C0 C1 C2 C3 C4 C5 C6 C7 C8
That is, C0 is the note for C in the lowest (or 0) octave. The fifth octave (numbered 4) is commonly referred to as a middle octave. Thus C4 is the C note in the middle octave. The frequency corresponding to C4 is 261.63 Hz.
Try playing it on the Scribbler. Also try C5 (523.25) which is twice the
frequency of C4 and C3 (130.815).
Computing the Scribbler's Range of Tones
In common tuning, the 12 notes are equidistant. Therfore, if the frequency doubles every octave, each
successive note is 21 / 12 apart. That is, if C4 is 261.63 Hz, C# (or Db) will be:
C#4/Db4 = 261.63*2^(1/12) = 277.18
We can then compute all successive note frequencies:
D4 = 277.18 * 2^(1/12) = 293.66
D#4/Eb = 293.66*2^(1/12) = 311.13
Note: In python, the characters that denote the exponent are **. Therefore to raise 2 by the exponent 3, you would type:
The lowest tone that the Scribbler can play is A0 and the highest tone is C8. A0 has a frequency of 27.5 Hz, and C8 has a frequency of 4186 Hz. That's quite a range! See if you can you hear the entire range. Try this:
beep(1, 27.5) beep(1, 4186)
Do This: Write a Scribbler program to play all the 12 notes in an octave using the above computation. You may assume in your program that C0 is 16.35 and then use that to compute all frequencies in a given octave (C4 is 16.35 * 24). Your program should input an octave (a number from 0 through 8), produce all the notes in that octave and also printout a frequency chart for each note in that octave.
Playing songs by frequency can be challenging. Myro contains a set of functions
to make this task a bit more abstract and manageable. A Myro song is a string of characters
composed like so:
NOTE1 [NOTE2] WHOLEPART
where  means optional. Each of these notes/chords is composed on its own
line, or separated by semicolons where:
NOTE1 is either a frequency or a NOTENAME
NOTE2 is the same, and optional. Use for Chords.
WHOLEPART is a number representing how much of a whole note to play.
NOTENAMES are case-insensitive strings. Here is an entire scale of NOTENAMES:
C C#/Db D D#/Eb E F F#/Gb G G#/Ab A A#/Bb B C
This is the default octave. It is also the 5th octave, which can also be written
C5 C#5/Db5 D5 D#5/Eb5 E5 F5 F#5/Gb5 G5 G#5/Ab5 A5 A#5/Bb5 B5 C6
The Myro Song Format replicates the keys on the piano, and so goes from A0
to C8. The middle octave on a keyboard is number 4, but we use 5 as the
default octave. See http://en.wikipedia.org/wiki/Piano_key_frequencies for
additional details. Here is a scale:
"C 1; C# 1; D 1; D# 1; E 1; F 1; F# 1; G 1; G# 1; A 1; A# 1; B 1; C 1;"
Now here is the scale, one octave lower, and played as a polka:
"C4 1; C#4 1/2; D4 1/2; D#4 1; E4 1/2; F4 1/2; F#4 1; G4 1/2; G#4 1/2; A4 1; A#4 1/2; B4 1/2; C4 1;"
There are also a few other special note names, including PAUSE, and REST. You can
leave the octave number off of the default octave notes if you wish. Use #
for sharp, and b for flat.
WHOLEPART can either be a decimal notation, or division. For example:
represents the A flat in the second octave (two below middle). As an example, save the following in a file called mySong.py (or some other name):
c 1 c .5 c .5 c 1 c .5 c .5 e 1 c .5 c .5 c 2 e 1 e .5 e .5 e 1 e .5 e .5 g 1 e .5 e .5 e 2
You can play this song after reading the next section.
You may leave blank lines, and recall that comments should begin with a # sign. Lines can also be separated with a semicolon.
Playing a Song
For the following exercises, you will need to create an object to play the song.
You will be initializing the robot in a slightly different way. Rather than:
robot = Scribbler()
Now that you have a song, you probably will want to play it. If your song is in a file, you can read it, play it on the robot or on the computer using the following commands:
s = readSong(filename) #filename should be a string e.g. s = readSong("mySong.py") robot.playSong(s) computer.playSong(s)
You can also use makeSong(text) to make a song. For example:
s = makeSong("c 1; d 1; e 1; f 1; g 1; a 1; b 1; c7 1;")
and then play it as above.
If you want to make it play faster or slower, you could change all of the WHOLENOTE numbers. But, if we just want to change the tempo, there is an easier way:
The second argument to playSong is the duration of a whole note in seconds. Standard tempo plays a whole note in about .5 seconds. Larger numbers will play slower, and smaller numbers play faster.