COS 461 Final Project Report - Philip Nikolov

Data Compression
(implemented by Philip Nikolov)

Data compression is an important factor in handling network latency and bandwith constraints.
The scheme we employed was U-LAW. This is a standard encoding format
in the U.S. This lossy algorithm converts a single data sample from 16 bits
to 8 bits by making use of the fact that the human ear is more sensitive
to sound fluctuations at low volumes.

The basic compression calls were made through the SGI Data Compression
Library . Convenient wrappers around those calls were provided by the
Compressor and Decompressor classes. For more information on the
facilities we used, do "man clIntro". (Compressor.H , Decompressor.H ,
Compressor.CDecompressor.C )

Even if the compression/decompression code does not look like a lot
of lines, it took quite some programming time to get right. There were
at least three undocumented "features" of the library, with which we
had to deal (one example). The appeal of the library was that it was going to provide
us with an accepted industry standard - thus opening the door to
porting and interoperability. The disadvantage was that during the time we
fought with the library we could have implemented our own compression.
 
In fact, Boris Kerbikov implemented a simple compression scheme based
on averaging of neighboring values in the array of data samples.
The idea was given by Tim Milliron and tests showed that we could
achieve a comression ratio of 2 without losing much in sound quality.
We decided not to use that idea because by that time we had figured
out the peculiarities of the SGI compression library.
 

Data Interpolation
(idea Tim Milliron, implemented by Philip Nikolov)

The UDP data connection does not guarantee arrival of every packet.
If a relatively small amount of sound data gets lost we should be able
to do something intelligent to fill in the gap. This is the job of the
Interpolate class. Linear interpolation is very simple and worked well
for us. Assume that we received packet A1, missed the next packet A2,
then received A3.  Fist we decompress the data.  All packets have the
same size of N bytes, so after decompression we get two arrays of N
shorts (sample width is 16). We want to make up N "reasonable" samples
of sound data. (We are in MONO mode). Let S1 be the average of the
last several shorts in the data from A1 and S3 be the average of the
first few shorts from A3. We fill in the gap of N shorts by
linearly interpolating between S1 and S3.
( Interpolate.HInterpolate.C )
 



One of the Problems with the SGI Compression Library
None of the manual pages inform you that the call clCompress() can only
be invoked with a desired number of frames smaller than 50. Compressor objects
often need to compress more than this amount of data. So a generic class
was created to split  up the compression of N frames into manageable-size pieces.
( FrameCounter.H , FrameCounter.C  )