Chapter 8

From IPRE Wiki
Jump to: navigation, search
US Postal Service R2D2 Mailbox.
In palo Alto, CA

Making Music

If a tree falls in the forest and there is no one to hear it, will it make a sound?
-: Old philosophical question.

If a tree falls in the forest and there is only a robot around to hear it, does that count?
-: New philosophical question.

Don't make music for some vast, unseen audience or market or ratings share or even for something as tangible as money. Though it's crucial to make a living, that shouldn't be your inspiration. Do it for yourself.
-Billy Joel

This chapter will explore the capabilities of the robot for making sounds and music.

Sound

As we have seen, you can have your robot make beeps by calling the beep() function, like so:

beep(1, 440)

This command instructs the robot to play a tone at 440 Hz for a duration of 1 second. Lets us first try and analyze what is in the 440 Hz tone. First, the letters Hz are an abbreviation for Hertz. The name itself comes from a German physicist, Heinrich Rudolph Hertz who did pioneering work in the production of electromagnetic waves in the late 19th century. Today, we use Hertz (or Hz) as a unit for specifying frequencies.

<math> 1 Hertz = 1 cycle/second </math>

The most common use of frequencies these days is in specifying the clock speeds of computer CPU's. For example, a typical PC today runs at clock speeds of a few GigaHertz (or GHz).

<math> 1 GigaHertz = 10^9 cycles/second </math>

Frequencies are related to periodic (or repetitive) motions or vibrations. The time it takes for a motion or vibration to repeat is called its time period. Frequency and time period are inversely related. That is the number of cycles or repetitions in a second is called the frequency. Thus 1 Hertz refers to any motion or vibration that repeats every 1 second. In the case of computer clock frequencies then, a computer running at 4 Gigahertz is repeating 4 billion times a second! Other examples of periodic motions include: the earth's rotation on its axis (1 cycle every <math>24 * 60 * 60 = 86400</math> seconds or at a frequency of 0.00001157 cycles/second), a typical audio CD spins 400 times a second, a CD drive on your computer rated at 52x spins the CD at <math>52 * 400 = 20800</math> times per second, hummingbirds can flap their wings at frequencies ranging from 20-78 times/second (some can go even as high as 200!). Sound is a periodic compression and refraction (or return to its original state) of air (for simplicity, let us assume that the medium is air). One Cycle of a sound comprises one compression and one refraction. Thus, producing a beep at 440 Hz represents 440 complete cycles of compression and refraction. generally, a human ear is capable for hearing frequencies in the 20 Hz to 20000 Hz (or 20 KiloHertz) range. However the capability varies from person to person. Also, many electronic devices are not capable for producing frequencies in that entire range. 20-20KHz is considered hi-fidelity for stereo or home theater audio components. Let us first examine the range of audible sounds the Scribbler can produce.

To make a sound out of the Scribbler, you have to give a frequency and the duration (in seconds) that the sound should be played. For example, to play a 440 Hz sound for 0.75 seconds:


beep(0.75, 440)

The human ear is capable of distinguishing sounds that differ only by a few Hertz (as little as 1 Hz) however this ability varies from person to person. Try the commands:


beep(1, 440)
beep(1, 450)

Can you distinguish between the two tones? Sometimes it is helpful to place these in a loop so you can repeatedly hear the alternating tones to be able to distinguish between them. The next exercise can help you determine what frequencies you are able to distinguish.

Exercise: Using the example above, try to see how close you can get in distinguishing close frequencies. As suggested, you may want to play the tones alternating for about 5-10 seconds. Start with 440 Hz. Can you hear the difference between 440 and 441? 442? etc. Once you have established your range, try another frequency, say 800. Is the distance that you can distinguish the same?

Exercise: You can program the Scribbler to create a siren by repeating two different tones (much like in the example above). 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!

Exercise: You can also have Myro make a beep directly out of your computer, rather than the robot, with the command:

computer.beep(1, 440)

Unfortunately, you can't really have the robot and computer play a duet. Why not? Try this:

beep(1, 440)
computer.beep(1, 440)
beep(1, 880)
computer.beep(1, 880)
beep(1, 440)
computer.beep(1, 440)

What happens? Try your solutions to the above exercises by making the sounds on the computer instead of the Scribbler.

Musical Scales

In western music, a scale is divided into 12 notes (from 7 major notes: ABCDEFG). Further there are octaves. 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 specfific note, say C, are multiplied (or divided) by 2 to achieve the same note in a higher (or lower) octave. On a piano there are several octaves available on a spread of keys. The convention What is the relationship between these two tones:

beep(1, 440)
beep(1, 880)

The second tone is exactly one octave above middle C. To raise a tone by an octave, you simply multiply the frequency by 2. Likewise, to make a tone an 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 refered 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). In common tuning (equal temparament) the 12 notes are equidistant. Thus, if the frequency doubles every octave, each successive note is <math>2^{1/12}</math> apart. That is, if C4 is 261.63 Hz, C# (or Db) will be:

<math> C\#4/Db4 = 261.63 * 2^{1/12} = 277.18 </math>

Thus, we can compute all successive note frequencies:

<math>D4 = 277.18 * 2^{1/12} = 293.66</math>

<math> D\#4/Eb = 293.66 * 2^{1/12} = 311.13 </math>

etc.

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! Can you hear the entire range?

beep(1, 27.5)
beep(1, 4186)

Exercise: 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 <math>16.35 * 2^4</math>). 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.

Making Music

Playing songs by frequency is a bit of a pain. Myro contains a set of functions to make this task a bit more abstract. 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 like:

C5 C#5/Db5 D5 D#5/Eb5 E5 F5 F#5/Gb5 G5 G#5/Ab5 A5 A#5/Bb5 B5 C5

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;"

and 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, 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:

Ab2 .125

or

Ab2 1/8

represents the A flat in the second octave (two below middle).

As an example:

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

Do you recognize it??

You may leave blank lines, and comments should begin with a # sign. Lines can also be separated with a semicolon.

Using a song

For the following exercises, you will need to have an object to play the song. You will need to initialize the robot in a slightly different way. Rather than:

initialize()

do:

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:

s = readSong(filename)

and play it on the robot:

robot.playSong(s)

or on the computer:

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:

robot.playSong(s, .75)

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.

Reference

robot.playSong(song) - have robot play a song

saveSong(song, append = 1) - save a song to a file

readSong(filename) - read in a song file

song2text(song) - convert a song to text format

makeSong(text) - convert text format to a song

text2song(text) - same as above


Previous Chapter: Chapter 7, Up: Introduction to Computer Science via Robots, Next Chapter: Chapter 9