HACKING
=======
Some notes on spettro's internal functioning.

Screen geometry
---------------

X-sizes-->  freq_axis_width      max_x-min_x+1   note_name_axis_width
                _|_  ________________________________  /\
               /   \/                v               \/  \
                _________________________________________
disp_height-1->|    27.5-14kHz 9 OCT   96DB KAISER@5Hz   |\_top_margin     ^
               |     ________________________________    |/                |
       max_y-->|    |                |               |   | ^               |
               |10k-|                |               |-E9| |               |
               |    |                |               |   | |               |
               |    |                |               |   | |    disp_height|
               | 1k-|                |               |-B5| |               |
               |    |                |               |   | max_y-min_y+1   |
               |    |                |               |   | |               |
               |100-|                |               |-G2| |               |
       min_y-->|    !________________|_______________|   | v               |
               |    2:57.67       3:00.48 [ ]  3:03.51   |\time_line_height|
               |_________________________________________|/                |
               |   Taylor Dayne - Tell It To My Heart    |\songbar_height  |
           0-->|_________________________________________|/      ^         v
           ^    \__/\________________________________/\__/       |
 Y-coords--'   ^    ^                ^               ^   ^    Y-sizes
               |    |                |               |   |
  X-coords-->  0  min_x         disp_offset        max_x |disp_width-1
                                                         |
               <----------------disp_width-------------->

Global variable "ppsec" is the number of pixel columns that represent one
second of music. For CD-quality audio at the default settings,
one column of the graph represents 882 samples:
    44100 samples per second / 50 pixels per second => 882 samples per pixel
In fact, the colors of the pixels in each column of the graph represent
the result of an FFT of a window of samples centered on the time at the
center of that column.

In the following graphic, four characters represent one screen column.
GGG = the green line, LLL = left bar line, RRR = right bar line

                                   ,----The disp_offset'th column, usually 320
                                 /---\
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
         |   |   |LLL|   |   |   |GGG|   |   |   |   |RRR|   |   |
                   ^                                   ^
                   left_bar_time                       right_bar_time

As for the current moment in time, get_players_time() gives our best estimate
of how far through the piece we are playing, and should fall within the column
painted green. The audio subsystem's reports of playing time tend to be
imprecise because the audio is played in little blocks of data. In SDL's case
we only know when the currently-playing block of data was requested, and the
precision of EFL's idea of the playing time is unknown so instead we take our
idea from the system's real-time wall clock, checking it against what the audio
player says the time is and correcting our idea if it drifts by more than a
twentieth of a second. In practice, with SDL2, this happens about once a minute.

The {left,right}_bar_times are measured in seconds and are set to the time
represented by the center of the pixel column the user clicked in
or to our idea of the current playing time if they pressed 'l' or 'r'.

The lifetime of an FFT calculation
----------------------------------
Spettro has a main thread which initializes everything and then loops
receiving notifications of key presses and mouse events and acts on them.
All screen updating is done from the main thread.

There is also a periodic timer which sends a "do-a-scroll" event to the main
loop, usually 25 times a second (the default frame rate in variable "fps").

Audio playing is another autonomous thread managed by the audio-playing
toolkit. When SDL needs more audio data it calls a callback which gives it
the data it requires. If you're using the Emotion audio player instead,
it does this on its own from the audio file without our intervention.

The heavy-work calculation of FFTs happens in several asynchronous threads.
and they communicate like this:

When the main loop is told to refresh columns of the screen, it schedules
the columns to be calculated by adding them to a linked list of calc_t
structures.

When a calculation thread falls idle, it calls get_work(), which gives it
the next most pressing column's data from the list of scheduled events.
The calculation in progress is remembered by moving the calc_t in question
from the list of work to be done to a list of calculations being performed
("jobs in flight").
When the FFT thread has finished, it sends an event to the main loop with
the spectral data filled into the calc_t structure and when the main loop
processes that event, it finally paints the appropriate column of the screen
and removes the calc_t from the list of calculations in progress.

The source files are:

alloc.c         A malloc wrapper that checks for memory allocation failure.
args.c          Decodes command-line arguments and prints the help text.
audio.c         A wrapper for the selected audio toolkit, to do play/pause/seek.
audio_cache.c   Keeps a copy of audio data in and near the visible region
                to avoid having to decode rge same data repeatedly.
audio_file.c    Stuff to read and decode the audio file.
axes.c          Calculates and displays the frequency and time axes.
barlines.c      Overlays the display with bar- and beat-lines.
caca_text.c     A better version of text.c to draw characters using libcaca's
                internal fonts.
cache.c         Keeps a copy of FFT results from which screen columns are made.
calc.c          Converts a time into the audio file into an FFT result.
colormap.c      Turns FFT results into a range of colours.
convert.c       Utility functions to map various forms of frequency and time.
do_key.c        Given an internal key code, calls the functions to perform them.
dump.c          Writes the current screen to a PNG file (-o option and O key).
gui.c           A wrapper for the Graphical Toolkit being used.
interpolate.c   Maps linear FFT results onto the logarithmic vertical axis.
key.c           Maps key names received from the GUI to internal key names.
libav.c         A wrapper for when libav* are being used to decode audio files.
                Only used if USE_AV is defined. See audio_file.c header comment.
libmpg123.c     A wrapper for when libmpg123 is being used to decode MP3 files.
libsndfile.c    A wrapper for when libsndfile decodes all other audio files.
lock.c          A wrapper for whichever resource locking library is being used.
main.c          Initialize spettro, sets it running and responds to events.
mouse.c         Code to handle mouse clicks and drags.
overlay.c       Does the manuscript score lines, guitar strings and piano keys.
paint.c         Handle updating of the graph's on-screen columns, scrolling etc.
scheduler.c     Keeps a list of FFTs to perform, those in progress, and assigns
                new work to the FFT calculation threads when they want some.
spectrum.c      Code ripped from libsndfile-spectrum to create linear spectra.
text.c          Draw text on the screen, used by axes.c
timer.c         Code to handle the periodic timer interrupts.
ui.c            All variables that control what the screen should look like.
ui_funcs.c      Routines to perform the actions required by keypresses.
window.c        Various window functions applied to audio before FFTing it.
