for lots of useful documentation on pygame: http://www.pygame.org/docs/
A Brief tutorial on keyboard5.py
Part I - the stuff common to all the sounds
keyboard5.py synthesizes its sounds when you start the program. Each sound is synthesized from scratch with a paragraph of code like the one below. The type of sound varies with the math in guts of the loop and we'll examine that in detail, but first let's look examine the code that is common to all the sounds.
# sound 0 --------------------
length = Fs * 1.5 # 1.5 seconds
freq = 440.0
amp = 16.0
tmp = []
for t in range(int(length)):
v= amp * Numeric.sin(t*freq/Fs*2*Numeric.pi)
tmp.append(v)
sound.append(pygame.sndarray.make_sound(Numeric.array(tmp,Numeric.Int0)))
length = Fs * 1.5 # 1.5 seconds
In class we talked about about sound waves propagating through various media. One thing which we didn't get to is that sound energy dissipates gradually as it travels around. For example: strike a bell with a frozen chicken. The sound reverberates throughout the metal and the air for a while and eventually stops. In low-level digital audio, e.g. synthesis from scratch we often think about the duration of sound in terms of the number of samples. You're probably more used to thinking about the duration of sound in seconds, so this simple line converts from the number of seconds into the number of samples. (length in samples = (#samples/second) * (# of seconds)
freq = 440.0 # Hz, sometimes known as cycles per second (cps)
In this simple example, we're synthesizing 1.5 seconds of a simple sinusoid. The two most important numbers used when describing a sinusoid are its frequency and its volume. The frequency, usually measured in Hertz (Hz), describes how high or low it sounds, and which part of the basilar membrane is excited. The human hearing range is roughly from 20Hz to 20,000 Hz, so a frequency of 440 Hz is somewhere near the middle. To relate frequencies to piano key notes, see
http://www.phys.unsw.edu.au/jw/notes.html
amp = 16.0
We didn't discuss amplitude at great length in the class, but will turn out to be very familiar to you. The amplitude of a sinusoid is simply it's volume. In other words, the bigger the amplitude, the louder it sounds. I'm pretty new to pygame, but from my initial experiments, 16 is middle volume range, 1 is really quiet, and 64 is pretty loud.
tmp = []
This line tells python we're going to have an array called tmp. An array essentially means a list. We're going to write a bunch of numbers into this array, and it's going to represent a sound.
for t in range(int(length)):
This line sets up a loop. That means the next indented lines will run multiple times - once for each sample.
v= amp * Numeric.sin(t*freq/Fs*2*Numeric.pi)
This is the mathematical guts of the program. For a full description, see Part II, "The magic of sin(). Basic, the magnitude of the waveform at every instant of time is calculated.
tmp.append(v)
After the last line computed the sample v, this line adds v to the list of samples.
sound.append(pygame.sndarray.make_sound(Numeric.array(tmp,Numeric.Int0)))
You don't have to understand this line in order to make music. Briefly, it converts the temporary array of numbers we just rendered (tmp[]) into a python Sound object. In other words, whereas you used to have just a list of numbers which could represent a sound, now, the computer is ready to actually play it. What goes on in between? First, your python array gets turned into a Numeric array. Then, that Numeric array gets turned into a Sound, then that Sound object is added to the growing of sounds.