Assignment 5: Arrays: Signal Processing with the Fourier Transform

Your assignment is to write a program that will determine, given a sample of sound from a piano key, what key (1-88) and note (A-G#) it is.

The *x* axis is the number of seconds from the time the key was
struck; as
you can see, we are considering only 1/20 of a second of time.
This piano key happens to be the A above middle C, tuned at 440 Hertz
(abbreviated Hz). That means the string vibrates 440 times per second.
The *y* axis plots the amplitude of the compression of air around a
microphone
connected to my computer; you can think of it as a voltage level.
As you can see from the plot, the voltage level, or *signal*, spikes
once every 1/440 of a second.

Sound is a continous signal, so how do we reprent it inside the computer?
One way is to take a sample of the amplitude of
the signal once every, say, 1/8000 of a second. We can store
these samples in a large array. Whenever we want to look at the signal
at time *t*, where *t* is in seconds, we just multiply
*t* by 8000,
find the closest integer, and look in the array at that point. In fact,
this is exactly the way sound is stored on an ordinary CD, with samples
taken every 1/44000 of a second.

How do you determine the frequency of a sampled sound? This situation
is complicated by the fact that in most situations, including the piano
key strike, there are many frequencies superimposed on each other. For
example, the A above also vibrates at 880 Hz, 1320 Hz, and other frequencies,
although these show up at a lower amplitude. These *harmonic*
frequencies are what give the piano,
other instruments, your voice, and pretty much every other sound its
characteristic texture. However, we are now only interested in determining
the *fundamental* frequency.

The data are given to us in the *time domain*, i.e., we know, for any
given time, what the amplitude will be. It would be nicer if the data
were in the *frequency domain*, where we would know, for any given
frequency, what the amplitude will be. Then we can just look for the
frequency with the highest amplitude, and that's the fundamental frequency
(usually; it works for the middle part of the piano, at least).
The *Fourier Transform* of a function takes a function *y(t)*
in the time domain and ``transforms'' it into a function *Y(f)* in the
frequency domain. It works for any periodic continuous function.
The Fourier Transform, for your amusement, looks like this:

If you don't know what this means, don't worry; you don't have to.

You can use a special version of the Fourier Transform called the

Once you have determined the fundamental frequency of the piano sound, you need to convert it to a number from 1-88, representing the number of the key on the piano. A simple formula for the conversion from a frequency

key = the closest integer to (the log base 2^(1/12) of (f / 27.5)) + 1

where 2^(1/12) means "two to the one twelfth power." Remember, to find the logarithm base

Once you have the key, the final task is to decide which note it is. There are twelve symbols for notes, repeating every twelve notes. Your program should print the notes as

cfft (complex_array, 8192)where

$(CC) -o piano piano.c cfft.o -lmin your

CFLAGS = -g -Wall LDLIBS = -lm CC = gcc all: piano piano: piano.o cfft.o complex.o $(CC) -o piano piano.o complex.o cfft.o $(LDLIBS) piano.o: piano.c cfft.h complex.h complex.o: complex.h complex.cYou should do all your work in a subdirectory called

- Read the sample file named on the command line into an array of 8192 complex numbers.
- Do a Fast Fourier Transform on the data (one line in C).
- Find the array element with largest magnitude and convert that array index to a frequency in Hz.
- Find the key number for that frequency.
- Find the letter symbol (A, A#, B, C, and so forth) for that key.
- Print the results.

runner% piano 1.dat maximum amplitude is 55.04 at 155.27 Hz, key = 31 key letter is D# runner% piano 2.dat maximum amplitude is 33.75 at 330.08 Hz, key = 44 key letter is E runner% piano 3.dat maximum amplitude is 143.59 at 310.55 Hz, key = 43 key letter is D#To turn in this program, do exactly this from the prompt on

% cat piano.c > output % piano ~djimenez/cs1713/1.dat >> output % piano ~djimenez/cs1713/2.dat >> output % piano ~djimenez/cs1713/3.dat >> output % piano ~djimenez/cs1713/4.dat >> output % piano ~djimenez/cs1713/5.dat >> output % piano ~djimenez/cs1713/6.dat >> output % piano ~djimenez/cs1713/7.dat >> output % piano ~djimenez/cs1713/8.dat >> output % piano ~djimenez/cs1713/9.dat >> output % piano ~djimenez/cs1713/10.dat >> output % Mail -s "piano program" djimenez@ringer.cs.utsa.edu < outputThis will run your program on all the files and send me the output. (If you have written other files beside

This program can be done in about 70 lines of C code, not including comments. It is not as difficult as it sounds, but it is by no means easy, so you should get started right away.

This assignment is due Monday, March 3, 1997 at midnight.