xmms-compress v1.1 (2002/07/31)
(c)2002 trikuare studios (http://trikuare.cx)

Introduction
============

xmms-compress is a simple dynamic range compressor for XMMS.
Technically it's not really a compressor, but a volume normalizer, but
the end result is the same as having a compressor with a very long
attack and decay.

If you don't understand that terminology, don't worry.  Basically,
what this plugin does is tries to keep the volume of XMMS' playback
more or less steady, without making it painfully obvious that the
volume is being changed.

I wrote it because I was disappointed with xmms-volnorm, in terms of
its overall quality.  In my opinion, it went about the problem the
wrong way, and tried making a "global maximum" for the entire song,
which meant that if a song started quiet and then got loud for a
little bit and then quiet again, it'd start out being over-amplified,
would distort badly while the amplification ramped down, and then
would be too quiet after the loud bit.  In the meantime, it also
didn't even do any interpolation of the gain, so there was very
obvious audible "clicking" between levels.

Also, xmms-volnorm doesn't seem to be the most efficient code around;
for example, it converts the audio data to floatingpoint and back!
(All of xmms-compress' math is done in fixed-point, which takes
immensely less CPU time, especially on older CPUs, and it's arguably
more accurate for stuff like this.)

How it works
============

xmms-compress works very simply.  It keeps a history of the last few
seconds and sets the amplification so that the loudest peak within
that time will be the reference for normalizing the sound (i.e. that
peak will be amplified to full power).  The amplification is smoothly
interpolated and goes up relatively slowly, and if there's a very
sudden loud burst, the amplification is dropped quickly (which
typically isn't noticeable).  If you want to see what it's doing
internally, there's a few ways of monitoring the amplification.  More
on that later.

Installing
==========

Linux
-----

Simply run 'make' to execute the included makefile.  This plugin is
pretty simple; it doesn't do anything unnecessary (it doesn't even
have a proper about box or a configuration window, though I
half-heartedly intend to change that eventually).  It only depends on
having glib and Xlib installed (and since XMMS requires both of them,
you hopefully have them already).  The build environment is pretty
simple and is hardcoded to my Linux machine at home, but fixing it for
other systems should be pretty trivial (if it's even necessary, which
it probably isn't unless your system keeps the X libraries and
includes in a weird place).

MacOS X
-------

See above, only you run 'make -f Makefile.OSX' instead.

Other OS
--------

Modify the Makefile to do whatever it is that your UNIX needs to put out a
shared library.  I'm too lazy to just use autoconf, sorry.  Feel free to email
me an appropriate Makefile for your own OS, though, or to autoconfify it for
me. :)

After Compilation
-----------------

After you compile it, either put the libcompress.so into your own XMMS
Effects (~/.xmms/Plugins/Effects) or, with access to whoever owns the
installation of XMMS (usually root), run 'make install'.  Then restart
XMMS, go to the 'effect/general plugins' tab in the configuration
window, and then select libcompress.so (as of this writing, its name
is given as "KOMPRESSOR KRUSH XMMS").

Note that you have to exit and restart XMMS if you recompile and
reinstall.  XMMS is pretty crappy when it comes to its shared
libraries being changed out from under it.

Configuration
=============

Show monitor window - When this is set, a window is displayed, showing
what's going on.  The black peaks show the actual signal, the yellow
peaks show the amplified signal, the horizontal blue line shows the
current uncorrected peak level, and the red trace shows the corrected
peak level.  Also, inside the black peaks small amounts of red will
appear if any clipping happens, though in the display it is greatly
exaggerated.

Aggressive clipping protection - If this is set, then when the sound
peaks, the volume will be cut instantly; otherwise, it will ramp down
just in time for the peak.  This shouldn't have to be set, but some
people with "golden ears" might claim they can tell the difference.

Target audio level - Lowering this value gives a bit more dynamic
range for peaks, but will make the overall sound quieter.  Must be at
most 32768 (higher values make baby Jesus cry).

Maximum gain - The maximum amount to amplify the audio by.  Just to
keep it from amplifying the noise floor or making truly-quiet passages
too loud.

Gain smoothing - This defines how smoothly the volume will ramp.  A
lower number is more aggressive but the effect will be more audible.
The number affects the smoothness exponentially - increasing this by
one will cause a volume ramp to take twice as long.

Buckets - How long of a history to maintain.  A higher number will
make the volume changes less responsive, and will also make the
monitor window bigger.

Potentially Asked Questions
===========================

Why does the audio playback lag from the monitor display?

  The monitor display shows the bit which is being computed by the
  audio plugin at this very instant; typically it buffers and queues
  up a bunch of sound to remain responsive under a heavy system load
  (for example, I have my mp3 plugin set to have a 128KB buffer, which
  is about 3/4 of a second at 44Khz 16-bit stereo).

Nothing seems to be happening!

  If you mean you can't hear anything happening, that's kind of the
  whole point - it's supposed to be subtle, and just prevent you from
  needing to fiddle with your volume control all the time.

  If you mean that nothing's being displayed in the monitor window or
  stats output or anything, it could be that you have an odd
  configuration.  Right now the plugin only does anything when it
  receives 16-bit audio in the computer's native endianness, since I'm
  too lazy to deal with byte swapping.  In *theory*, this should never
  be a problem, but in some exotic configurations (on exotic sound
  hardware) with some odd player plugins it might cause the plugin to
  do nothing.  Don't worry, in that case the audio will just be
  unprocessed.

Why do some songs still sound quieter than others?

  This plugin only normalizes based on waveform peak, and not sound
  power level.  Unfortunately, things which aren't properly equalized
  will either sound quieter (if normalized based on voltage) or will
  clip badly (if normalized based on power).  The only proper fix for
  bad equalization is to fix the equalization.  Maybe someday someone
  will make an automatic "maximum sound power level" equalizer, but
  I'd much rather see audio engineers actually learn what they're
  doing (rather than destroy actual quality audio work)... also, some
  would (quite rightly) claim that automatically "fixing" the
  equalization will totally change the character of the sound...
  However, you can always just manually tweak song equalization and
  then use the 'auto' feature to have it save the equalization on a
  per-song basis.

  Someday I may make a general-type plugin which will do things like
  automatic equalization and silence skipping.  Unfortunately, effect
  plugins don't have access to the things needed to do this properly.
  And even more unfortunately, the XMMS plugin layer isn't documented
  *at all* - there arn't even comments in the headers!  So the only
  way to figure out the API is to parse through the headers and
  experiment with random calls and return values and so on, and
  referring to other plugins' sourcecode.  And most other plugins
  aren't very well-coded, either.  (Not that a callback model really
  makes for very clean code to begin with, but that's a whole other
  rant...)

Why does the sound "rattle" sometimes?  Can't this plugin help that?

  The most common cause of rattling in the sound is clipping.  This
  plugin does whatever it can to avoid clipping, and if you have it
  configured with aggressive clipping avoidance, then it should never,
  ever clip at all (and even without ANTICLIP, the only time that it
  could clip is if the sound is nearly-silent and then suddenly
  spikes, which is a situation where you're not likely to notice it
  anyway).

Why does it take a few seconds for a quiet song to get up to full
volume?

  This is because the normalization is based on the peak over the last
  few seconds.  Unfortunately, there's no way to tell the difference
  between a quiet song and a dramatic fadein.  Furthermore, if a song
  is mastered quietly, it might be that the audio engineer wanted it
  to actually be quiet compared to other songs, and so by having it
  slowly fade in you'll still get this effect when coming from a loud
  song.

  Basically, there's no way for the effect plugin to deal with this in
  a universally-reasonable way.  If it really bothers you, try
  lowering your history length, but be warned that this will ruin
  fades (it'll sound as though it fades in much more quickly, and
  songs which fade out will tend to start to fade back in before they
  finish fading out).

Can I use another effect plugin at the same time as this one?

  Unfortunately, XMMS doesn't directly support this, for reasons which
  are likely a mystery to everyone but the XMMS developers.  However,
  there are certain other plugins which allow you to have more than
  one effect plugin; for example, xmms-crossfade lets you add in one
  more to the chain.  If you're using xmms-crossfade (which is a
  wonderful plugin that I highly recommend), you probably want to put
  xmms-compress into XMMS' internal effect plugin slot and the other
  effect into xmms-crossfade's.

  There's probably "meta-plugins" which allow you to turn on multiple
  effect plugins (preferrably to be applied in a certain order), but
  at this time I don't know of any.

When I try to close the monitor window, XMMS crashes!

  This is due to a limitation in both Xlib and the way that effect
  plugins are handled.  There's no really clean way for an effect
  plugin to deal with its own window, as XMMS doesn't really expect
  effect plugins to have a window.  As such, if you try to close the
  window yourself, at best nothing will happen, and at worst some
  window managers will go ahead and just kill the window itself,
  leaving xmms-compress with no window to draw to, causing an
  exception in Xlib which XMMS doesn't trap, causing Xlib to kill
  XMMS.

  Short answer: Only close the monitor window from the plugin
  configuration.  Sorry.

Acknowledgements
================

I have to thank Baruch Even for doing xmms-volnorm, since it was
disliking its functionality which made me finally get around to coding
this.  Also, it made a fairly decent reference for a few of the silly
minuti of writing XMMS plugins (since I didn't feel like spending
several hours trying to find the XMMS plugin documentation, especially
for something so trivial to program).

Also, many many thanks to Javier Conde Rueda for writing the GUI code.

Contact Information
===================

Bug reports, patch submission, etc.: magenta at trikuare.cx
Latest version: http://trikuare.cx/~magenta/projects/xmms-compress.html
XMMS homepage: http://www.xmms.org/
