From gos.ukc.ac.uk!harrier.ukc.ac.uk!ukc!mcvax!uunet!husc6!mailrus!cwjcc!abvax!gfs Fri Dec 9 18:09:45 GMT 1988
Article 865 of rec.music.synth:
Path: gos.ukc.ac.uk!harrier.ukc.ac.uk!ukc!mcvax!uunet!husc6!mailrus!cwjcc!abvax!gfs
>From: gfs@abvax.icd.ab.com (Greg F. Shay)
Newsgroups: rec.music.synth
Subject: DSP Experimentors
Keywords: FFT lesson #1, Wave synthesis
Message-ID: <507@abvax.icd.ab.com>
Date: 1 Dec 88 15:59:07 GMT
Organization: Allen-Bradley Company, Inc; Industrial Computer Division, Highland Heights, OH
Lines: 200
Here is the first of promised information on how to use the FFT for
musical application. I will assume you have received the FFT code I posted
and managed to get it running. If anyone missed it and wants it, email me.
Since synthesis is the name of the game, I'll start with using the FFT for
waveform synthesis first.
As a notational convention, I will precede any line that I intend to be
understood as a command line with a >.
SOME BASICS:
The FFT program takes waveform data and converts it into
frequency data. The IFFT (inverse FFT) correspondingly takes frequency data
and outputs waveform (also called time-domain) data.
A simple example:
> cat anything.dat | fft | ifft > output.dat
And you will find that output.dat is identical to anything.dat.
A word on the data file format. All of the programs use a common data file
format that you can generate by hand or write programs to generate (like the
gen1.c or genwin.c program).
A data file consists of
1) First character, first line, either 'r' or 'c'. An 'r' declares
the data to be real only. A 'c' declares the data to be complex (both real
and imaginary numbers for each data point are included.)
2) The next line has a number which encodes the size of the data file.
The number is the logorithm, base 2 of the data size, i.e. 8 means 256 data
points, 4 means 16 etc. If x is the size number, there are 2^x data points
following.
3) The data follows, one number per data point if a real file, two
per point if complex. The data does not have to be one point per line, it may
be compacted (some programs output 8 points per line.)
Examine the output of the gen1.c program for an example.
CONVERTING COMPLEX DATA TO REAL:
In general, most data files are complex. In the output of the fft, the
real componants correspond to in-phase (cosine) waves and the imaginary
componants correspond to the 90degree out of phase (sine) waves. The
program 'magonly' converts a complex file into a real file by replacing
each complex data point with its magnitude. (You can extract the phase
information with a slight modification of the 'magonly' program but I have
not had a use for the phase information as such).
WAVEFORM SYNTHESIS:
Firstly, you must become familiar with a few special features of a frequency
spectrum data file as generated by fft and used by the ifft. The basic
procedure we will use is:
> cat freqfile.dat | mirror | ifft | magonly > synthwave.dat
once we properly put the data into the 'freqfile'. The mirror program takes
the first half of the frequency data, flips and mirrors it into the second half
of the frequency data. This is one of the special properties of the ifft,
in order to end up with real data only (all real, no imaginary) you MUST input
data with EVEN SYMMETRY. The trailing magonly eliminates the zeros in the
imaginary componants and results in a simple real data file.
DATA IN THE FREQ FILE:
Consider a data file of any size which is a power of 2. I'll use 64 for
example.
1) The FIRST data point represents the DC componant of the wave, the offset
from 0. Most of the time you will want this to be equal to 0. The first
imaginary componant must equal 0.
2) The MIDDLE data point (or more exactly, the data point immediately after the
center of the data set) represents the frequency componant at exactly 1/2
the sampling frequency. In a complex frequency file, there is NO out of phase
componant at this frequency, only the in-phase componant. Generally, you
will set this value to 0 also. The middle imaginary componant must be 0.
3) The rest of the data will be mirror imaged (repeated but in reverse order)
from the first half to the second half. In addition, the imaginary data is
reflected about 0 as well (changed sign).
An example for a sample data file size of 64, numbered 0 through 63:
Sample 0 real is the DC offset. Sample 0 imaginary MUST be 0.
Sample point 1 real equals 63 real, 1 imag equals -63 imag.
2r == 62r, 2i == -62i.
3r == 61r, 3i == -61i.
etc.. continuing
30r == 34r, 30i == -34i.
31r == 33r, 31i == -33i.
and..
Sample 32r is the componant at exactly 1/2 the sample frequency. There is
no mirror of 32r, as there is no mirror of 0r (the DC componant). The
sample data 32i MUST be 0, as 0i MUST be zero, these have no physical
interpretation. (If you try and set 32i or 0i nonzero or violate any of the
above mirror restrictions, the output of the ifft will have some non zero
imaginary data which has no physical meaning. All actual time domain data
is real.)
You now are glad that the 'mirror' program takes the first half of the
frequency file data and properly mirror images it according to the above
rules, aren't you! --)
AN EXAMPLE OF WAVEFORM SYNTHESIS:
Lets say we want to synthesize a waveform with the following spectrum:
All frequencies out of phase (90 degree shift).
Fundamental at amplitude 1.0;
Third harmonic (3x the fundamental) at 0.5;
Fifth harmonic at 0.3;
Seventh harmonic at 0.1;
Ninth harmonic at 0.03;
Using a data size of 64, the input file looks like: (Do not include comments
in a actual data file).
c ; A complex file
6 ; 2^6 = 64
0 0 ; No DC
0 1 ; Fundamental
0 0 ; Second harmonic = 0
0 0.5 ; 3rd = 0.5
0 0 ; 4th
0 0.3 ; etc as above
0 0
0 0.1
0 0
0.03
0 0
Note the mirror program will fill in the remaining zeros as well as the mirror
imaging. I arbitrarily am setting all phases to 90 by declaring imaginary data
only. If I wanted to set other phases of the harmonics, I would have entered
some real values instead of or as well as imaginary values.
Now run:
> cat test | mirror | ifft | disp > output
And you get in the output file:
| ** ** |
| * * * * |
| |
| * ** ** * |
| *************** |
| |
|* * |
| |
| |
| |
| |
*_______________________________*______________________________|
| |
| |
| |
| * *
| |
| *************** |
| * ** ** *|
| |
| * * * * |
| ** ** |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
****************************************************************
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
Note that the imaginary data output of the ifft is all zero, this is good.
I knew ahead of time that the sum of odd harmonics of sine wave (sine
wave are 90 degrees out of phase) is a square wave. The result is not
an exact square wave because I just guessed at the coefficients (1.0,.5,.3,
.1,0.03) and because I did not go beyond the ninth harmonic.
Try the same harmonic amplitudes in-phase (set the real values to the numbers
and the imaginary ones to 0). Note how different the waveform looks. This
is called phase distortion, and is why audio people take great pains to
eliminate it.
Well, that is all for now, have fun synthesizing waves.
A note, I found a few bugs in the 'disp.c' program that relate to smaller screen
sizes. If you are having trouble getting output and cannot fix them yourself,
I can repost the modified disp.c.
Greg Shay
..pyramid!
.. uunet!abvax!gfs
.. decvax!
Received: from kestrel by gos.Ukc.AC.UK Over Ring with SMTP id aa27623;
15 Dec 88 8:54 GMT
Received: from mcvax by kestrel.Ukc.AC.UK via EUnet with authorised UUCP
id aa23452; 15 Dec 88 8:54 GMT
Received: by mcvax.cwi.nl via EUnet; Thu, 15 Dec 88 09:50:33 +0100 (MET)
Received: from abvax.UUCP by uunet.UU.NET (5.59/1.14) with UUCP
id AA05468; Wed, 14 Dec 88 11:08:19 EST
Received: by abvax.icd.abnet.com (5.59/1.16);
id AA08154; Wed, 14 Dec 88 10:00:05 EST
From: "Greg F. Shay"
Message-Id: <8812141500.AA08154@abvax.icd.abnet.com>
To: mg@ukc.ac.uk
Subject: FFT code
Date: Wed, 14 Dec 88 10:00:04 EST
Martin,
Hands across the water, Heads across the sky... Here it is.
Greg
------------------------------
A number of topics covered here:
1) The hardware design direction is shaping up. I have 56000 information now
as well as the TI 320xx series that I have worked with previously. The
56000 is more expensive but more powerful. I need votes, are you willing
to pay an extra $100 for the 56000 vs about 1/2 to 1/3 the power in the 32010?
2) I am compiling the names of everyone who has answered me so far and will
send this out so you can see if you have been heard.
3) Here are sources for fft and related programs that form a experimental
DSP set. I have run them on Unix machines as well as my IBM PC. (Note the
disp.c program will not switch the IBM PC display to 132 column mode, so
you must keep data sizes to 64 for the PC.) I am kind of rushing these out
so I'm sure other terminals can be supported.
Try to compile the programs here. I will be sending out instructions and
examples of how to use them as soon as I get time. Briefly, the programs are
all modules that process data coming in the standard in and going out standard
out. The data file is either a real or complex data set.
An example run:
gen1 | fft | magonly | disp
This takes the fft of the data file generated by gen1, converts to magnitude
throwing away phase, and shows it to you.
The programs here can be used for spectral analysis, harmonic analysis,
DSP FIR filter synthesis, waveform synthesis, convolutions, arbitrary filter
processing, and more. Stay tuned, I promise I'll show you how.
Greg Shay
..uunet !
..decnet !abvax!gfs
..pyramid!