Freq, a spectrum analyzer program for DOS, Linux, Linux/X, and Sun
 
Copyright (C) 1995  Philip VanBaren

This program is free software; with the exception of the sound card
sampling routines, which are copyright by their respective authors,
you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

PROGRAM FILES:

dos/freq.exe     For DOS, with PAS-16, SB, or VESA-AI sound cards
linux_svga/freq  For Linux with SVGA graphics
linux_srgp/xfreq For Linux running X Windows
sun/xfreq        For Sun Sparcstations (not included here)

FREQ.EXE is a program for the ProAudio Spectrum/Studio 16 sound cards,
Soundblater compatible 8-bit cards, and cards supporting the VESA audio
interface BIOS extensions.

The program samples the input, performs an FFT, and graphs the output.
INI file and command line options provide the user with the ability to
select linear/log frequency and amplitude scales as well as sampling rates,
length of the FFT, and windowing functions.  Graphics is done using the VGA
640x480x16 video mode, so a VGA compatible card is required.  The program will
only run on computers with an 80386 or above processor.  A coprocessor is
recommended, but not required.

FREQ.EXE also works with 8 bit Soundblaster and compatible cards.  It looks
for the environment variable "BLASTER=A220 I5 D1" to set the Soundblaster
address, IRQ, and DMA.  If this variable is not available, the default
values (220,5,1) are used.

The source code for version 5 which works under DOS, Linux, and on Sun
workstations will be posted to:
  ftp://sunsite.unc.edu/pub/OS/Linux/apps/sound/freq51.tar.gz
  and oak.oakland.edu:/simtel/msdos/sound/freq51.zip
  and http://bul.eecs.umich.edu/~phillipv/signal/
  and ftp://bul.eecs.umich.edu/pub/linux/freq51.zip

COMPATABILITY:

This program has been tested on the following sound cards:
- ProAudio Studio (PAS mode)
- Logitech Soundman (PAS mode)
- Soundblaster 16 (SB16 mode)
- Soundblaster (SB mode)
- Sound Galaxy 16 NX (SB mode)
- GUS MAX (SB mode with SBOS)
- ??? if it supports VESA AI BIOS extensions

Under Linux:
- ProAudio Studio

RUNNING UNDER LINUX:

The executables which are included here were dynamically linked with the 
standard ELF libraries, and ELF versions of libsrgp (xfreq) and libvga,
libvgagl (freq).  Run "ldd xfreq" and "ldd freq" in the linux subdirectory 
to see if the dynamic linker is finding the libraries.  If you don't have 
these libraries installed on your system you will need to install either 
the SRGP package or the SVGALib package.  Refer to source/readme.txt for
more information on these libraries.

RUNNING UNDER WINDOWS:

I have had problems with running the PAS version of the program under Windows
with some of the PAS drivers (MVSOUND version 3.23 or 3.24).  I don't
remember having any such problems with previous versions of the PAS drivers.
If switching between Windows and Freq causes the screen to be messed up,
use the 'V' command to restore the display.

I have had success running under Windows95 using the MVSOUND drivers, version
3.23 and 3.26.  However, MVSOUND version 3.26 has a bug which prevents
chaning of the microphone input mixer setting.  You could also set up the
PIF file to exit Windows before running the program if you have problems
running from the command prompt window.

COMMAND LINE OPTIONS:

-Cnumber selects the soundcard (0=SB8, 1=PAS16, 2=VESA, 3=SB16)
                            or (0=au format, 1=Linux dsp format)
-Ddevice selects the input file/device (Linux only)
-Odevice selects the output file/device (Linux only)
-Mdevice selects the mixer device (Linux only)
-Snumber sets the sampling rate.
-Fnumber sets the length of the FFT.
-Mnumber sets the scale maximum.
-Bnumber sets the logarithmic base level (in tens of dB).
-Tnumber sets the logarithmic top level (in tens of dB).
-Gnumber sets the dB/octave gain factor.
-Rnumber sets the reference frequency for dB/octave gains.
-LA sets a logarithmic scale for the amplitude axis.
-LF sets a logarithmic scale for the frequency axis.
-W0 selects a Hamming window.  (offset sine) <--default
-W1 selects a Hanning window.  (sine)
-W2 selects a Blackman window. (two sines)
-W3[,alpha] selects a Gaussian window.
-W4 selects a Welch window.    (quadratic)
-W5 selects a Parzen window.   (triangular)
-W6 selects a Rectangular window.
-Wfilename saves the windowing function to the specified file.
-H or -? displays this message.

INI File options:

These options override the program defaults, but are overridden by the
options specified on the command line.  The red,green,blue values for the
colors must be values between 0 and 63.

Soundcard: 0                ( same as -Cnumber )
     0: Soundblaster 8 bit cards, and compatibles (also valid: SB8)
        (in Unix: Linux/Sun audio /dev/audio)     (also valid: MuLaw)
     1: ProAudio Spectrum 16 bit cards            (also valid: PAS16)
        (in Unix: Linux /dev/dsp)                 (also valid: Linux)
     2: VESA audio interface BIOS extensions      (also valid: VESA)
     3: Soundblater 16 bit cards                  (also valid: SB16)
Audio device: /dev/dsp            ( same as -Ddevice)
     Selects the name of the input device (or file)
     This is valid under Unix only.
Mixer device: /dev/mixer           ( same as -Mdevice)
     Selects the name of the mixer device.  /dev/mixer is the default
     This is valid under Linux only.
Output device: /dev/null           ( same as -Odevice)
     Selects the name of the output device (or file)
     The default is to provide no output
     This is valid under Unix only.
Sample rate: 44100          ( same as -Snumber )
     Valid sampling rates are 5000 Hz to 88200 Hz for PAS 16 cards.  For
     Soundblaster cards, values in the same range will be accepted, however
     for the old 8-bit Soundblaster cards (and the Soundblaster section on
     PAS cards) the sampling rate cannot exceed 12000 Hz.  Any value greater
     than this will result in a mis-labelled frequency axis.  For newer
     Soundblaster cards, sampling rates up to (and possibly beyond) 44100 Hz
     are possible.
Rate fudge factor: 1
     Scale factor to adjust for errors in the sampling rate.  In general,
     this value should be left at 1.  If you find that the true sampling
     rate of your card is different from that displayed on the screen, this
     scale factor may be used to correct the error.
FFT length: 1024            ( same as -Fnumber )
     Valid FFT lengths are from 8 to 2048.  Longer FFTs will result in slower
     display updates (maximum update rate will be SampleRate/FFTlength).
     Computers slower than 486DX-33MHz will not be able to reach the maximum
     rate because they cannot perform the calculations in the available time.
Window function: 0          ( same as -Wnumber )
     0 selects a Hamming window.  (offset sine) <--default
     1 selects a Hanning window.  (sine)
     2 selects a Blackman window. (two sines)
     3 selects a Gaussian window.
     4 selects a Welch window.    (quadratic)
     5 selects a Parzen window.   (triangular)
     6 selects a Rectangular window.
Bar display: 1
     0 selects display of the spectrum using a single pixel
     1 selects display of the spectrum using vertical bars
Log freq scale: 0           ( 1 = -LF )
     0 selects a linear frequency scale (equal distances result in equal
       frequency differences)
     1 selects a logarithmic frequency scale (equal distances result in equal
       frequency ratios)
Log amp scale: 1            ( 1 = -LA )
     0 selects a linear amplitude scale
     1 selects a logarithmic (dB) amplitude scale
Base db: 7                  ( same as -Bnumber )
     Sets the base value for the dB amplitude scale
Top db: 2                   ( same as -Tnumber )
     Sets the top value for the dB amplitude scale
Max amp: 1.0                ( same as -Mnumber )
     Sets the top value for the linear amplitude scale
DB/octave gain: 0           ( same as -Gnumber )
     Valid values here are 0,3,6,9, or 12.  This option gives a frequency-
     dependent boost in the displayed amplitudes.  The value specified is
     given in dB/octave.  For example, suppose there are two signals, one an
     amplitude-1.0 signal at 1kHz, and the other an amplitude-0.5 signal at
     2kHz.  Specifying 6dB/octave will result in both of these appearing at
     equal amplitudes.  Specifying 12dB/octave will result in the 2kHz
     appearing to be twice the amplitude of the 1kHz signal.  Since harmonics 
     typically are reduced in amplitude proportional to 1/frequency 
     (6dB/octave) or to 1/frequency^2 (12dB/octave), using this option will
     improve the visibility of the higher harmonics in a signal.
Reference frequency: 1000   ( same as -Rnumber )
     This specifies the frequency of 0dB gain, when a dB/octave gain factor 
     is being used.
Base frequency: 0
     This specifies the minimum frequency displayed on the plot.  This can be
     used to zoom in on a particular section of the spectrum.
Frequency factor: 1.0
     This specifies the zoom-factor for the frequency axis.
Decay mode: 0 
     0 selects no decay mode (display what has just been sampled)
     1 selects decay mode.  In this mode the values at a frequency will decay
       exponentially until a new, larger value appears at this frequency.  The
       decay rate can be set with the following option.
     2 selects exponential decay mode, where both the rise and falls are
       exponential decays.
     3 selects uniform averaging over the past (n) samples
Decay factor: 0.9
     This value selects the rate at which the frequency bins decay in decay
     mode.  The value should be less than 1, and larger than 0.
Averaging count: 8
     This value selects the number of samples used in uniform averaging
Background color: 0,0,20    ( sets the background red,green,blue value )
Clipping warning color: 20,0,0 
     Sets the background color set when clipping occurs.
     WHY DOES THE SCREEN FLASH ALL OF THE TIME?  That is because this color 
     is different from the background color.  The program changes the 
     background color to this color whenever clipping of the signal is
     detected (the sampled signal hits the allowable signal limits.)  This
     clipping will result in a distortion of the frequency plot (look at the 
     spectrum of a pure whistle when clipping occurs.)  The best solution to 
     this problem is to lower the input level so that clipping does not occur.
     If this is not possible, you can set this color to the same value as the 
     background color, and the screen will not longer flash.
Graph color: 30,35,60       ( sets the color for the FFT graph )
Axis label color: 50,20,45  ( sets the color frequency and amplitude labels )
Border color: 40,40,40      ( sets the color for the border and tick marks )
Text color: 55,55,25        ( sets the color for text (other than labels) )
Cursor upper color: 20,20,20 ( sets the color for the upper half of the cursor )
Cursor lower color: 63,63,63 ( sets the color for the lower half of the cursor )

RUNTIME OPTIONS:

While the program is running, the following commands may be used:

E,Q : Exit from the program
F : Change the FFT length
R : Change the sampling rate
S : Save the current state to an INI file.  The default INI file is FREQ.INI, 
    which will be loaded as the default options.  If a filename is given as
    the first parameter on the command line, the settings from that file
    (which can be created using the "S" command) will be used.
L : Toggle logging of the FFT data to a file.  The data format is given as
    rows of integers which alternate real, imaginary parts for the frequency
    bins from 0 up to (fftlen/2)-1.  Successive buffers are stored in the
    rows of the file.  Pressing 'L' again will stop the data logging.
W : Alternate among the windowing functions
P : Toggle peak display mode on/off (shows the frequency of maximum amplitude)
X : Toggle between logarithmic and linear frequency (x axis) scales
Y : Toggle between logarithmic (dB) and linear amplitude (y axis) scales
G : Select 0,3,6,9,12 db/octave gain
V : Redraw the video display
B : Toggle between bar graph and line graph displays
C : Toggle black&white/color display, useful for screen prints.  Note: if you
    want to make a printout of the display, run the DOS program GRAPHICS.COM
    prior to running FREQ.  Before printing, switch to the black&white display,
    and then press Shift-<PrintScreen>.  Refer to your DOS documentation for
    more information on the GRAPHICS program.
A : Select averaging mode.  Averaging mode causes the frequency bin contents
    to be low pass filtered in order to smooth the display resulting from
    sources such as pink noise.  The rate of decay can be
    adjusted using the +/- keys.
+/- : increase/decrease decay rate in averaging mode

<Up> : increase the amplitude scale
<Down> : decrease the amplitude scale
<PgUp> : raise top dB level for log amplitude displays
<PgDown> : lower top dB level for log amplitude displays
<Left> : Shift frequency axis to the left (show higher frequencies)
<Right> : Shift frequency axis to the right (show lower frequencies)
'<' : Contract the frequency axis
'>' : Expand the frequency axis

<space> : freeze display, put up a cursor, and put up a display of frequency,
phase, and amplitude information.  In this mode, the H,J,K,L keys will move
the cursor 10-left,1-left,1-right,10-right, respectively.  Pressing <enter>
will save the data to a file, with one frequency bin per line.  Each line
will contain {frequency} {real part} {imaginary part}.  This data can then
be loaded into a spreadsheet or plotting program for display.  (The FFT
magnitude is found by computing sqrt({real part}^2+{imag part}^2).)
Pressing  <space> will resume data aquisition.

For PAS16, SB16, and SBPro cards the following keys are also available:

(,) Decrease/increase the microphone input level
[,] Decrease/increase the external input level
{.} Decrease/increase the internal (CD) input level

THE WINDOWING FUNCTION:

Several different windowing functions are available.  The windowing function
is a function that is multiplied by the input data to reduce the effects of
the discontinuity at the ends of the data set.  A rectangular window is
actually no window: all data is passed through.  A Parzen (triangular) window
uses a trianglar weighting: the end points are multiplied by 0, the
middle point by 1, with a linear ramp from 0 to 1 and back to 0 again.
A Welch Window uses a quadratic weighting: the end points are multiplied by
0, the middle points by 1, with a [concave down] quadratic function from 0,
up to 1, and back down to 0 again. To see the shapes of the various windows,
used the -Wfilename option, and plot the data in the output file.

The best way to see the effects of windows is to use a logarithmic amplitude
scale, and input a sine wave (an audio test CD works great for this).  If
you don't have any good sine wave sources, whistling into a mic works fairly
well.

KNOWN PROBLEMS: (let me know if you find others)

1) The PAS version of the program does not work if the 'device=mvsound.sys'
line in config.sys contains the switch "u" (this switch allows initialization
of the card, but then the driver is unloaded from memory (not a TSR)).
Removing this switch solves the problem.  My config.sys contains the
following line:
   devicehigh=c:\pastudio\mvsound.sys d:5 q:10 s:1,220,1,7 j:1 t:1 v:0

2) The actual sample rates must be integer divisions of the timer frequency,
which is 1.19318 MHz for PAS cards, and 1.0 MHz for Soundblaster cards.
This means actual sampling rates for PAS cards are:
   91.78kHz, 85.23kHz, 79.55kHz, 74.57kHz, 70.19kHz, 66.29kHz, 62.80kHz,
   59.66kHz, ... , 45.89kHz, 44.19kHz, 42.61kHz, etc.
and the actual sampling rates for Soundblaster cards are:
   45.45kHz, 43.48kHz, 41.67kHz, 40kHz, ... 22.73kHz, 22.22kHz, 21.74kHz, etc.
The program will compute the closest actual sampling rate to the one
requested.

3) The PAS version of the program may crash under Windows when used with
some newer versions of the PAS drivers.  (MVSOUND version 3.23 or 3.24.)
I don't recall having these problems with previous version of the drivers.
There is now an MVSOUND version 3.26 (check out ftp.mediavis.com), but since
I no longer have Windows 3.1 installed, I am not able to see if this driver
works any better.  It does work under Windows95, however.
Also, there is the possibility, depending on the installed drivers, that the
Windows mixer settings will be confused.  This can be corrected by
re-starting the mixer program.

4) The specified sampling rate may be above what a Soundblaster can handle.
If this occurs, the Soundblaster will sample at its maximum rate, and the
frequency axis will not reflect the true frequencies.  Typical 8 bit
Soundblasters will only handle sampling rates up to 12kHz.  Newer
Soundblasters can handle sampling rates of at least 44.1kHz, and may be able
to go beyond.

5) The MIC mixer setting for the PAS card does not work with version 3.26
of the mvsound driver under Windows95.  This is a bug in the driver, so I
would recommend getting a previous version of the driver.  I am currently
using version 3.23, and everything works fine in Win95.

WHAT'S NEW IN VERSION TWO:

1) The FFT routine has been changed to process purely real data, which can be
done in about half of the time it takes to process complex data.  This makes
the FFT routine a little messy, but it is worth the mess!

2) The screen updating routine was changed a bit, and now runs faster
than before.  The main change was setting the mode and color once when the
program starts, instead of every time a line was drawn.  This works
because I am interesting in drawing one color only, and nothing else is
trying to output to the display while the program is running.

3) Changed the square root code to use a Newton-Raphson method.

4) Filled in the gaps in plots (such as log frequency scale).

5) A version is included which runs on only 386+ machines with COPROCESSORS.
This program is even faster than the other version because it was written
in 386/387 assembly code.

6) Removed Bartlett window function (it is essentially the same as the Parzen
window function).

7) Added cursor/amplitude display during paused display.

WHAT'S NEW IN VERSION THREE:

1) Skipped the assembly language version (it is too difficult to keep up with
the changes in two versions of the program).  The version optimized for the
386 runs as fast as the eye can see, anyway, so there was not much gain it
going real time.

2) Added checking so that lines do not go beyond the limits of the display.

3) Added options for 0,3,6,9,12 dB/octave gains so that higher harmonics can
be made more visible (6dB/octave gain will make harmonics whose amplitudes
drop as 1/frequency to have the same amplitude; 12dB/octave will make
harmonics whose amplitudes drop as 1/frequency^2 to have the same amplitude.)

4) Added a bunch of run-time options for modifying the display.

5) Added more information in the header display

6) Added an INI file for setting defaults, so that you don't have to specify
all of your favorite options on the command line.

7) Allow modification of display colors (through the FREQ.INI file).

8) Background flashes a warning color when saturation of the input occurs.
(This flashing can be disabled by setting the background color and the
clipping warning color to the same values in the INI file.)

THE SCORE FOR VERSION FOUR:

1) Added run-time commands for changing of the FFT size and sampling rate.

2) Added a command to save the current state to an INI file.

3) Added a command to toggle between color/black&white displays, so that
screen-prints looked good on black&white printers.

4) Added commands for zooming in on the frequency axis.

5) Added decaying-bin display mode.

6) Added control of mic/ext/int input levels for PAS 16 cards.

7) Added help display.

AND VERSION FIVE:

1) Generalized the code enough so that it could compile under Linux and 
Unix on Sun workstations.

2) Cleaned up the source for general distribution.

3) Added support for VESA audio interface BIOS extensions.

4) Added support for the SRGP, which allows display under X Windows.

5) Improved averaging modes.

6) Added Soundblaster 16 support.

7) Added data logging functions

8) Added a toggle for bar/line graph display mode

CREDITS:

*** Please, don't bother these people with problems you have with my
*** program.  I used some code they they made available on the Internet
*** to provide some of the soundcard support.  However, they did no direct
*** work on this program, and so cannot help you with problems you have
*** with it.  On the other hand, if you are interested in writing programs
*** which support these sound cards, get a copy of their code from the
*** Internet, look it over, and then bother them about it.

The Soundblaster code was written by Heath I. Hunnicutt 
(heathh@cco.caltech.edu).  The source for this code is available via FTP
from: ftp://ftp.inf.tu-dresden.de/pub/ms-dos/sound/program/sb_dsp.zip
and dma_code.zip.  The first file gives the SB8 routines, and the second
file gives the DMA routines.
                             
The Soundblaster-16 code is based on code written by Ethan Brodsky
(ebrodsky@pobox.com), which is available from:
ftp://oak.oakland.edu/simtel/msdos/sound/sb16snd.zip

The VESA AI code comes from the VESA AI SDK, available via FTP from:
ftp.uwp.edu:/pub/msdos/proaudio/vaisdk.zip
The VESA BIOS extensions for PAS16 cards is available from:
ftp.uwp.edu:/pub/msdos/proaudio/vbeai.zip

The PAS16 libraries come from the MediaVision PAS SDK, available via FTP from:
ftp.uwp.edu:/pub/msdos/proaudio/passdk30.zip
garbo.uwasa.fi:/pc/proaudio/pas-sdk1.arj and pas-sdk2.arj

The SVGALIB libraries were written by Harm Hanemaayer, and are available from
sunsite.unc.edu:/pub/OS/Linux/libs/graphics/svgalib126.tar.gz

The SRGP libraries were written by David Sklar, and are available from
sunsite.unc.edu:/pub/OS/Linux/libs/X/srgp.tar.gz

Thanks to Andrew Veliath and his SVGAFFT program for giving me examples
for doing both audio sampling and SVGA graphics output under Linux, making
it easy to port this program to Linux.

Thanks to Ken Schwabe for testing the Soundblaster16 support.

If you have any questions, bug reports, suggestions, or additions to the code,
you can contact me at:

Philip VanBaren
Internet:    phillipv@eecs.umich.edu
