Atari classic tape generator program.  Version March 1999.

Preface.

This program is intended to be used with the wav2cas program that I
wrote in may of 1997.  A lot of the technical hoopla involved in
storing information on cassettes is explained in the documentation
that came with that program.  If you are not familiar with it, I
suggest you first read that stuff.  If you do not have it, download it
from the Umich archives, or send me an E-mail.

Purpose of this project.

The design goal of this project is to convert the digital tape format,
introduced with the wav2cas project, back to a format that will enable
us to re-create a cassette that can then be loaded on a regular
Classic Atari equipped with any of the supported cassette units.  The
data is thus re-saved onto cassette tape.  This can be used to clean
up faulty tapes that contain dropouts, spikes, noise, or other
problems.  Data that is damaged can be restored, or repaired.  The
data on the new tape could be saved at a higher baud rate, thus
slightly reducing the time required to load the tape.  The quality of
the cassette tape can be greatly improved in this way.  The cassette
data is encoded into a .wav file, which should then be played back
through a .wav player program.  The audio can then be recorded onto an
audio cassette using a standard audio cassette recorder.  Since the
cassette data is recorded using only a sound card and some software,
there is no need for an Atari cassette unit.  Data can be retrieved
from, and saved to cassette tapes even if your cassette unit is
broken, unreliable, or otherwise not available.  You will need a
regular audio cassette recorder of course.  If you want to load the
cassette again, you will need an Atari and an Atari cassette unit, but
these do not have to be connected to the PC.  You could go to a friend
with your tapes and process them on her/his PC if you do not have such
a device yourself.

Theory of operation.

Data must be saved onto cassette tape.  To do this, the data must be
converted to some audio format.  Converting the data to an audio
format is accomplished by converting the digital data into a .wav
file, which holds the audio information that results from encoding the
data.  Data is encoded on the cassette tape as a frequency shift
keying audio signal, usually referred to as FSK.  For the
non-technical persons, this means that an audio tone is recorded on
the tape that has either one frequency, referred to as the mark tone,
or another frequency, called the space tone.  Normally, the POKEY chip
within the Classic Atari generates these tones, based on the bits of
the data to be encoded, but this time we do it all in software.  We
add the start bit and the stop bit for each byte.  All the bytes to be
encoded are stored in the cassette records, including the marker bytes
and the checksum.  Data is normally encoded at 600 baud.  The mark
tone is usually 5327 Hertz.  The space tone is usually 3995 Hertz.
This, along with the information stored in the .cas file, enables us
to create a .wav file that contains all the bits encoded in the FSK
audio format.  The bytes to be encoded are stored in the cassette
records within the .cas file.  These records also tell us the length
of the IRG and the PRWT, and the length of the leader.  For
experimental purposes, we can attempt to increase reliability by
tweaking these values, especially if we want to attempt to create a
cassette that is encoded at a non-standard baud rate.

Writing data to a cassette tape.

Once a .wav file is created by the program, we simply play it back
with a .wav player program, and record it onto the cassette tape.
Never ever input this audio signal into the Atari computer DATA IN
line directly, since this might damage your system.  The audio signal
from the cassette tape must be converted to digital data by the Atari
cassette unit, thus we must first record it to a tape with our audio
cassette recorder.  Adjust the recording level as you would with any
other sound.  The data should be recorded on the right channel.  If
you want, you can record some music on the left channel, or whatever
else you would like to hear while loading the tape.  If you like to
hear the FSK tones, you can record the data on both channels.  The
Classic Atari likes this 'music', but you might not particularly like
it, or even call it noise, like your parents did with your music, so
switch off your speakers, or turn the volume down.  If you do not
record anything on the left channel, set the recording level to zero
for the left channel.  You should take care that the length of the
leader does not become excessive.  Some leader is already included in
the .wav file.  If you do not start playing back the .wav file in
time, the leader might become too long.  Do not make it too short
either though.  If you start the player and the cassette deck
simultaneously, you will be able to control the length of the leader
by entering the proper value in the program.

Just a few words about playing back a wave file are in place.  I have
tried a couple of programs to playback a .wav file.  One of the things
to watch is the fact that you will be processing a lot of data.  If
your hard drive is fragmented, the system will need more time to read
the data.  Since the sampling rate is high, this could cause your
player program to skip a few samples while it is busy reading data
from disk.  I did not program that stuff, I would assume the program
continues to play samples from memory, but somehow it looks like the
O.S. disables the interrupts while doing I/O, so it will simply miss a
few samples sometimes.  This might also be caused by the fact that
there are other tasks in the system that are allowed to use the system
resources for a while.  I have seen this happen with an Operating
System that was released in 1998.  You can check this by recording the
audio file to a .wav file again, and then looking at the wave file
with a wave editor.  You should then be able to find the spot where
the system could not keep up, especially if we are generating a very
clean FSK signal.  Since this problem occurs randomly, it is hard to
do anything about it.  You could simply create a 32 meg ram disk and
run DOS, but not everybody is so fortunate to have memory in
abundance.  A fast hard drive is nice too, and it will do most of the
time.  If you cannot avoid this problem, simply record the file again,
until you have a clean copy.  It would be nice to have a utility that
adds music to the left channel, so that we could listen and hear the
bad spot on the tape.  All we would need is a program that takes two
mono .wav files and merge them into one stereo .wav file.  Anyone
interested in writing such a utility?  Maybe such a utility already
exists?

Generating a .wav file.

We want to generate a .wav file.  A wave file starts with a header
that specifies the sampling rate and other technical stuff.  A wave
file is a file in the standard RIFF file format, and documentation on
this subject is available, so I will not go into detail here.  The
RIFF file header is written, then the wave chunk header is written to
the file, and we write the sampling rate and all the other information
about the format of the wave file to the header.  Then we write the
data header.  The headers contain the length of the file, and the
length of the chunk, so we have to memorize the file position where
these numbers are supposed to be.  When we are done writing the file,
we must come back and update these values.  After the headers, we can
start the sample data for the audio level of the wave.  According to
the specifications, if the number of bytes in the chunk is odd, we
will have to add a slack byte to the end.  When we are done writing
the sample data, we add this slack byte if it is required, and then we
update the length of the file and the length of the chunk.

The sample data is a very huge list of PCM values ranging from 0 to
255.  We generate these samples based on the tone we want to
represent, which is dictated by the values of the bits we want to
encode.  We know that we want to write either mark or space tones.
Based on the frequency of these two tones, we generate a table for
each tone.  The table holds the PCM sample data for one second of that
tone.  The mark tone is usually 5327 Hertz.  This means there are 5327
periods in one second.  We want to make a sine wave, because we like
pure tones, so we need to compute the amplitude of the signal as a
function of the time since the start of the tone.  We do this by
computing the sine value of the time since zero.  Now you cannot input
time into a sine function, only degrees or radians, thus we have to
convert the time.  So let us choose radians, for no obvious reason.
One period equals 2 PI radians.  If we had chosen degrees, it would
have been 360 degrees of course.  Now we are generating one second of
sine wave stuff, and over that second, we will generate the sample
value for 44,100 samples.  The frequency tells us how many periods
there are within that second, so this means we have 5327 times 2 PI
radians within one second.  Our sample rate is the time value.  When
we have generated 44,100 samples, one second has passed.  The sample
number is our index into the table we wish to generate.  Now we can
compute the amplitude by multiplying our time value by the number of
radians that one time element represents, and inputting that into the
sine function.  Thus we multiply the index into our table by the
number of radians within one second, divided by the sampling rate.
The output of the sine function is a value from -1 to 1, so we have to
multiply this result by some value to increase the value to a level
which we can use for the PCM sample values.  Also, we have to add 128
in order to make it a positive number.  If we multiply it by too much,
the sound might become distorted a bit, so I choose a value of 64 for
this.  Since we have one second of samples in our table, we know that
for any integer frequency value the end of our table will wrap nicely
around to the start of the table again for a clean sine wave.  The
tables can be used to quickly write a large number of samples to the
.wav file.

We wanted the output to be a clean sine wave form.  This can be
accomplished with the following procedure.  While writing data to the
.wav file, the program keeps track of the value of the tone we were
writing to the .wav file, either mark or space.  If we need to write a
mark tone, and the previous tone we wrote also happened to be a mark
tone, the program continues to write the wave form from where it left
off in the table the last time.  The same is true for the space tone.
Thus, if two consecutive bits have the same value, the wave continues
smoothly on, as if nothing happened.  If the tone is different, the
last sample value we wrote to the file is noted.  Then we determine
whether the wave form was going up or down in amplitude.  Then this
last value is searched for in the table of the other tone.  Of course
the level must also match the fact whether it is rising or falling.
When the match is found, we continue on with the other table from that
point.  This makes a smooth transition from one tone to another.  At
first I had it wait for the level to pass zero before changing over
the tone, but this also works nice, and it results in a more exact bit
length.  Now why did we want a clean wave?  Because it looks nice, or
maybe because it sounds nice.  But our only and most important goal
should be, can we load the tape every time without a load error?  Do
not worry about what it sounds like, check the track record, does it
load okay?  This made me experiment more, and the result is another
way of encoding data in waves.  The key point seems to be to have the
FSK decoder detect when the change in the tone occurs.  We should
therefore make sure that the wave starts and stops exactly where the
bits start and stop, to make it easier for the FSK decoder.
Unfortunately you cannot have it both ways, since if you make the wave
start at a certain point, chances that the period ends when the bit is
supposed to end are close to zero, unless you tamper with the
frequency.  The end of the space tone seemed to cause the most
problems, so I choose to make the waves end when the space tone is
supposed to end, and start when the mark bit is supposed to start.
This makes a clean change from space to mark.  The not so smooth
change over at the change from mark to space seems to have little
effect on the decoded bits, so this looks like it is the best encoding
format.  The way to accomplish this encoding scheme is to write the
requested number of samples from the end of the table for the space
tone, and the beginning of the table for the mark tone.  These tables
are sure to start and end in a way that makes a smooth change.  The
program calls this a transition at the zero level, even though only
one of the two transitions actually occurs at the zero level.

The baud rate can be selected.  If the default baud rate is used, we
find 600 bits per second on a tape.  Since we need 44,100 samples for
each second, a bit will last about 44,100 samples divided by 600 bits,
which is 73.5 samples.  Half a sample does not exist, so we would have
to write 73 samples per bit.  For each bit that we encode, we would
write 73 samples in this case.  This means that in effect, our bit rate
would be slightly off from the selected value.  This is not a problem
for loading the tape, but we can do better.  If we would process the
bits in groups of a byte, we would have to compute how many samples
are required for one byte, and then evenly distribute that over the 10
bits that make up a byte.  This is only important if we want to
generate a tape that exactly matches the baud rate entered.  If we do
not mind that the baud rate is slightly off, this is just extra
complexity that is not needed.

There is another reason why we would create the bits in groups of a
byte though.  I have noticed that if you have a test tape that
alternates between mark and space tones, with bits of equal number of
samples, that the space bits appear to be slightly shorter.  It looks
like the space tone detection takes a little while to kick in.  For
the mark tone, this is really not important, since in the absence of a
space tone, a mark bit value is output by the cassette unit, even if
there is no mark tone present, so the detection of the space tone
appears to be the most crucial.  The mark tone does prevent erroneous
detection of the space tone, but the space tone is just more
important.  If we wanted to compensate for this, we could actually
make the space tone bits on the tape start a little early.  We cannot
simply change the length of the space bit though, since the total
length of the byte should remain the same.  This means we have to
steal a couple of samples from the mark tone following it.  Of course
it takes some time before the decoding circuit detects that the space
tone is gone again.  Again, we can compensate for this, by having the
space tone stop a little early, and give these samples to the mark
tone following it.  However, stopping seems to be very simple.  In
fact it is so simple, that sometimes the last portion of the bit is
not detected as a space tone, and the last few samples are treated as
part of the mark tone following it.  This makes the bit shorter so we
would have to make it longer again.  Confused?  So was I!  I have
played around with this a great deal, and it all seems to be related
to the way the two tones change over.  Compensating for this does seem
to improve reliability at the higher baud rates.  The only problem is
that I suspect that the compensation requirements of various cassette
units might differ.  If so, a tape that would load on one unit, might
fail to load on another.  Don't worry too much though, since these
problems with loading should only occur when the baud rate is around
820 baud.

The maximum baud rate that the standard O.S. will program the POKEY
chip for when doing cassette reads is 820 baud.  If we go beyond that,
we are depending on the POKEY chip to cope with the deviation.  It
does seem to cope with some deviation.  I tried to improve the signal
such that we could even load a tape at 875 baud, a value that seems to
be the limit if you use the CAS2SIO program.  I have experimented a
bit with adjusting the bit sizes and such, but in the end, what you
really end up doing is simply reducing the size of the stop bit.  The
higher baud rate results in a smaller bit size.  As long as the last
data bit is presented at the time that it would be expected at 820
baud, POKEY seems to be able to decode the bit, and then the stop bit
is just a lot shorter.  The Atari has plenty of time to grab the byte
from POKEY and store it somewhere, and then it can even compute the
checksum.  It does not need the time that the stop bit represents.
POKEY also seems to not mind.  So if this is all we wanted, it would
be better to reduce the length of the stop bit, and encode the tape at
820 baud.  I don't think this little extra speed is worth the loss of
reliability.

If we know how many samples to generate per bit, we can now write the
record to the tape.  We begin with the IRG/PRWT, which is specified as
a number of milliseconds.  We have to divide this by 1000 and multiply
it by the sample rate to get the sample count.  This number of samples
is then written to the file, by writing the corresponding piece of
tone data from the mark table.  Then we start encoding the bytes of
the record one by one.  We write the data for the bits from the mark
or space table based on the value of the bits.  We start with the
start bit, then the least significant bit of the data byte, followed by
the other bits one by one, and finally the stop bit.  Since we are
processing bits by the byte, as discussed just now, we sum the length
of the bits if they are alike, adjusting the bit length sometimes to
evenly distribute the samples over the byte, and then compensate for
the space tone delays.

Tapes differ is length, depending on how much data is stored on them.
Some tapes are 16K or less, other tapes are 48K or more.  Most tapes
require roughly 2.5 seconds per block of 128 bytes, which is 20
seconds per kilobyte.  A 16K tape will take about 5 minutes, a 48K
tape could easily take 15 minutes or more.  At a sampling rate of
44,100 samples per second, we will have to write 44,100 bytes of data
for each second of audio, or about 2.5 Megabytes per minute.  A
fifteen minute tape will easily consume over 30 Megabytes of disk
space.  If you do not have that much hard disk space available, you
should backup some data and make space available, or simply buy a
bigger hard disk, since hard disks are very cheap nowadays.  If the
program runs out of disk space, it reports a write error.

Command line options.

Running the CAS2WAV program is easy.  You have two options.  You can
run it interactively, by simply starting it.  It will ask for the
filename.  Once that is entered, it will ask you to enter whether or
not you want the diagnostics to be printed.  This program does not
provide a lot of diagnostics, it will tell you at what offset in the
.wav file a data record starts.  The only time this appears to be
useful is when you sample the created tape again, to see if the .wav
file has been properly transferred to an audio tape.  If you have a
slow computer, this option also shows you that the system is still
busy working, otherwise, you might think that the system crashed.  It
does take a little while sometimes, depending on the size of the file,
and also on the option selected for the way the tone changes over.
If you wish this diagnostic data to be printed, it will be printed to
the screen.  The output can be redirected to a file using the standard
DOS redirection, but that would redirect the prompts to the redirected
output too, so this is only recommended if you use the command line
arguments.  You are then asked to enter various information that is
used for encoding the data on the tape.  If you enter nothing, the
default values for these settings are used.  You only have to enter
something if you want something non-standard.  The wave format of the
tones can be selected, either sine waves or block waves.  There are
two flavors of sine waves, one with an immediate change over, and
one which only changes at the next zero crossing, which is a pure
sine wave so to speak.  If you want the zero crossing to occur at the
time the bit is supposed to end, select the zero crossing option.
This zero crossing works as described earlier.  The baud rate should
be something around 600.  If you want to experiment with higher
speeds, you can enter a higher value.  Values up to 850 baud seem to
work.  Above that, load errors start to occur.  If you enter a fixed
value, the baud rate values stored in the cassette file will be
ignored.  The frequencies used for the mark and space tones can be
altered too.  If you think your cassette unit prefers some other
frequency, you can try adjusting the frequencies a bit.  The standard
frequencies seem to work fine on my cassette units though.  Finally,
the length of the leader tone and the length of the Inter Record Gap
can be set to a fixed value.  If you enter a fixed value, the values
from the cassette file will be ignored and overridden by the values
entered.  The leader value is used for the length of the beginning of
the tape.  The IRG value is used for any IRG on the tape that lasts
less than 3 seconds.  You can enter all this on the command line if
you prefer.  The file to process is the first argument on the command
line.  The printing of diagnostic data is an option switch, which can
be selected by adding /d to the command.  The wave form can be
selected by using the /w switch, specifying sine waves, block waves,
or pure waves.  Add the letter s, b or p after the w.  If you want to
try the zero transition, add the /z switch to the command.  The value
of the baud rate can be selected by using the /b switch, specifying the
desired baud rate.  The frequency for the mark tone can be selected with
the /m switch, for the space tone it is the /s switch.  The length of
the leader can be specified with the /l switch, and the IRG length can
be set using the /i switch.  These last five switches take a decimal
number for setting the value, so setting the baud rate to 820 would
require you to enter /b=820 on the command line.  The equals sign is
optional, but do not insert any spaces between the switch and the value.
There is no check for weird values, so what you enter is what you get.
If you enter very strange values, you might even be able to make the
program crash, or hang, so if you do enter a value like that, don't do
it again.  I am not going to add checks for these values, in order for
people to be able to experiment.

If no command line arguments are given, the program will prompt for
the file.  The program allows the user to exit the interactive request
for data by entering control Z.  On most PC's, pressing control-BREAK
will also terminate the program.  I used the Symantec C++ compiler on
the PC.  If you press control-BREAK, it will terminate the program as
soon as it tries to write to the screen.  If the CAS2WAV program
happens to be in the middle of writing some data, this may take a few
moments though.

There is one special command line option that cannot be selected in
the interactive mode.  The /t option generates a test tape for
examining the quality of the FSK decoder inside the cassette unit.
Any filename that is entered is ignored, since the filename for a test
tape will always be "testtape.wav".  The number after the /t specifies
the length of the tape in milliseconds.  The other options are all
still valid, so you can experiment with various frequencies and
baud rates.  The test tape wave file will contain some form of
alternating mark and space tones, each one bit long.  This is intended
for viewing the output of the FSK decoder on an oscilloscope.  The
signal should be a block form with all bits equal in length.  In order
to make the cassette unit play the tape, you will have to connect it
to an Atari.  You can either try to boot the tape, using the normal
procedure, or you can enter the command from BASIC to start the
cassette motor.  If you enter POKE 54018,52 the motor will be turned
on.  Note that some cassette units draw their power from the computer
via the SIO bus, so another reason to connect it to the computer.  The
cassette output on the DATA IN line is also designed such that you
need to connect it to the computer if you want to measure the result
with an oscilloscope.  The oscilloscope should be connected to the
DATA IN line to view the signal.  If you recorded the audio to both
channels, you can connect the AUDIO IN line to the second input if you
have a dual beam oscilloscope.  By experimenting with this, you can
try to determine what frequency works best.  Of course, it is advised
to use the standard frequencies, but it is fun to experiment with this.
Note that a test tape cannot actually be loaded, since it is not in the
proper format.  It can only be used to test the FSK decoder.  You can
modify the program to generate different test patterns.

I have used this test tape feature a lot to investigate how the FSK
decoder reacts to different ways of changing the tones from mark to
space and back.  At one point I even created a bi-tone signal, where
the mark and the space tone were both present at the same time.  I
only made one of them louder than the other, depending on the bit to
be encoded.  Even then did the FSK decoder generate the correct bits.
I thought that if the space tone is present all the time, the decoder
might not have as much trouble to see the start of the space bit, but
it looks like this does not make a difference, since the space bits
were still shorter sometimes.  Eventually I tried using a block wave,
since at some point I doubted that the FSK decoder really likes sine
waves.  To my amazement, this resulted in a rock solid output.  Using
the diagnostic tape, the edges of the bits were stable, which
indicates that the FSK decoder reacted in a stable way to changing
over from mark to space and back.  So I even wanted to make this the
default wave form, but now it is up to you.  Even though I have spent
a considerable amount of time on research, this area could probably be
explored more.  After all, the tests I did were only with a few
cassette units.  If you feel like playing around with it yourself, let
me know your results.  Incidentally, when connecting the audio to the
second channel of my oscilloscope, I could see that the signal that is
output by the cassette unit is about three periods delayed from the
actual change over in the audio signal.  This might account for the
rather unpredictable behavior that confused us.  Fun stuff to
research.

All this weird behavior is probably caused by the fact that there is
a slight difference in the output circuit of the filters for the mark
and space tones, which is input into the comparator.  There is a small
capacitor, which is charged by the output of the filter.  This charging
takes some time, based on the value of the resistors in the circuit.
Both filters have these resistors in their circuit, however one of these
resistors differs slightly in value.  This is probably because in the
absence of an audio signal, the recorder should output a mark value.
If there is no signal, both filters output the same value, but due to
this difference in the resistor value, the mark tone voltage on the input
of the comparator will be the highest.  This design has one drawback.
The charging time and discharging time of the capacitor is also influenced
by this difference in resistor value.  This causes the space bits to be
shorter.  I wonder if this problem could be solved by replacing the
capacitor in the mark circuit by one of a lesser value.  For now, we will
fix this problem in software.  I do not know whether all this is true for
all the various types that Atari produced.

Troubleshooting.

If, after recording the .wav file to a cassette tape, the tape
produces load errors or boot errors, obviously there must be something
wrong.  Check to see that the audio has been properly recorded.  If
you know where the boot error occurs, check that piece of the
recording.  You might want to turn off any special noise suppressors
that might be on your cassette deck.  For recording Atari stuff, I use
regular tapes, because they are cheap, and because that is what these
machines were designed for.  You should also try some of the other wave
formats to see if that helps.  I had the best results with the zero
transition option.

Sometimes, the playback of .wav data can be suspended due to various
O.S. related issues.  If you feel that a data block has been hit by
this, try recording the tape again.  Most commercial tapes are
recorded on both sides, so we might apply the same tactics here.  If
we record the .wav to both sides, we can try the other side, to see if
the playback of the .wav file was affected by this.  If it is the
case, the bad side of the tape could simply be recorded over again.
If a certain portion of a tape is damaged, or suffers from a dropout,
then the tape is unreliable, and I suggest you do not use it for
recording data.

If you keep having trouble booting the cassette tape, first try
booting the digital image with the CAS2SIO program and a SIO2PC cable.
Like I stated in the WAV2CAS documentation, I have found that some of
the load errors are not caused by the cassette unit at all.  Boot
errors that are caused by timing problems can sometimes be corrected
by specifying a fixed IRG value.  It is helpful to know whether the
.cas file is okay to begin with.

If you are still having troubles with loading a specific tape, make
sure you know what procedure to follow in order to boot these tapes.
The tape might not be compatible with the XL/XE O.S., or you might
need a certain amount of memory.  If you have a program that was
written in BASIC, it will have been saved with the CSAVE command in
BASIC, so use CLOAD instead on these tapes.  Anyway, make sure you
know the proper procedure for the tape.

Another possibility is that there is simply a bug in my program.  If a
load error occurs consistently at the same spot on the tape, even if
you record it again, this might be a problem inside the program.  If
this occurs, send me an E-mail.

Epilog.

Well, we have come to the end of this document, another project done.
I hope this stuff helps some folks to learn to appreciate the cassette
stuff a little more.  After all, if it is more reliable, it is not
half as bad.  Booting a PC nowadays takes several minutes, so booting
an Atari from tape might actually be faster, and lots more fun.  The
source for this program is included, so if you feel you want to
experiment some more, you are welcome to try it out.  Note that I did
not put any of the PC's supposed to be 'C' crap in my source.  I still
cannot find the words FAR and NEAR and such in Kernighan and Ritchie,
so I compile all my sources with some switch that makes the PC choose
the correct pointer stuff.  Select a proper memory model, whatever
that may be, if you want to compile the stuff yourself.  Allocating
two times 44,100 bytes does not make default PC pointer stuff happy so
it seems.  Comments are welcome.  I might ignore them, since I will
spend my time on other things now, but it is always nice to hear
somebody tried to use the stuff.  The terms and conditions are the same
as with the wav2cas stuff.  So, use this stuff at your own risk.  I am
not responsible for any damage that might occur whatsoever.  If you want
to take portions of my program and improve on it, go ahead, provided
that you comply with a few rules.  You have to include in your
documentation that your program was based on this work.  On top of that,
if you charge money for your product, you will have to inform people
that my stuff is available free of charge.  This includes shareware fees
and stuff like that.  I just want people to know that this thing is
available for free.  This means that I myself do not expect people to
send me any money.  So, you get what you pay for with my stuff.  If you
want to drop me a note, there are various options.  For one thing, you can
send me E-mail over the Internet.  You can also send me a regular letter.
Anyway, if you have questions, send them to me.  Please do not send me
.wav files to look at.  It would be crazy to E-mail a file of several
megabytes.  You are welcome to send any comments.  If you think some of
my data or research is in error, let me know.  The address is below.

Ernest R. Schreurs.
Kempenlandstraat 8
5211 VN  Den Bosch
The Netherlands
E-mail: ernest@wxs.nl

Keep those XL's/XE's humming.
Or, I suppose we are talking to the real pioneers here:
Keep those 400's/800's humming.
