* Create main window
* Create a view for the overall document which contains subviews.
* Create a view class for the wave
* Create document class
* Create class to contain track.
    * sample rate, numsamples, sample array.
    * pass around by references....
* Create class to contain wavelet.
    * wavelet is a 2D array, pass around by references.
    * Can create from track.
x Split view classes make sense
* wavelet transform should be larger than time view...
x Create space for percent bar window
x create percent bar window.
* wavelet transform can be calculated in own thread
* Load a wave file in.
x make a tool bar containing play and stop.
* Play a wavefile.
* Display the wave.
x Can zoom wave.
* Can scroll wave
* Move Cards into utils
* Card window visible in Wavelet Sound Explorer.
* Create card for opening files.
* Clicking on Open beings up File Open box.
* PlayTask should work again.
* Create play button
* Create stop button.
* Add buttons to toolbar.
* fix all memory leaks.
* Remove view complex from menu.
* Auto enhance image.
* create object to represent a selection.
* selection can hold rectangles.
* view menu has options->auto enhance on/off
* move selection to document class.
* create undorecords for add selection
* create undorecords for delete selection
* create undorecords for modify selection
* Make disk sound image.
* Make sound image reader context.
* Create options object
* options object takes care of auto enhance property instead of application.
* Add "release" option to options
* If release code, do not show undeveloped features.
* text should appear steely gray.
* waveform move should invalidate only portion that needs updating.
* Waveform should render only invalidated portion.
* Add Help/Webpage menu
* Webpage menu brings you to the web page.
* handle open file failure due to malloc fail.
* Move SoundImage::alloc into separate stage of document loading.
  WaveletDoc::alloc(Waveform*, SoundImage*);
* Create method to calculate bytes required in wavelet transform.
* Once file is opened, if it is greater than 22050 Hz, then offer to resample
  it.
* Implement waveform resampling.
* Once file is resampled, if resulting sound image is >256 MB, then offer to
  create swap file.
* Abstract task should allow some kind of immediate cancel function.
? CRASH: Open small file. While rendering, open large file that creates disk.
Immediate crash in renderTODib.
  - Can't reproduce.
* resample buttons should fit into window.
* always show resample screen if file is >8000 Hz.
* Cards: Add ability to hide an element by name.
* resample slide only shows sample rates < current.
* Turn AudioThread into a PlayWaveformTask.
* PlayWaveformTask maintained in ScalogramViewWindow.
* PlayWaveformTask/PlayTask should not conflict with eachother.
* Add Edit menu/ Copy view to clipboard.
* Implement Edit/Copy view to clipboard.
* Try to optimize renderToDib(): if shrinking by several times, skip some
samples.
* OverlappedFile has option for no buffering and option for delete on close.
* DiskSoundImage sets "DeleteOnClose" flag.
- Cancel button should work when asked to save to a file.
- SoundImage::getRow should accept offset and length.
* SoundImage::getRow should accept offset and length.
* MemorySoundImage::getRow takes offset
- DiskSoundImage::getRow takes offset,length. Makes reasonable guesses for next
row.
- fix rendering to screen - does not show preview when render task takes over.

- DiskSoundReader takes an offset as a parameter.
- Waveform can be saved to a stream (as floats)
    - format: sampleRate, numSamples, samples
- Waveform can be loaded from a stream
    - Sound Image bands
    - Sound Image mmin
    - Sound Image mmax
    - Sound Image upperScale
    - SoundImage lowerScale
- SoundImage can read/write its header    
- WaveletDoc::save(filename) writes:
    - "WaveletSE0.50\0"
    - <4 bytes> file offset of sound image data.
    - Waveform
    - Sound image header
    - Sound image
    
- move selection drawing to drawselection tool
- can create a selection using the drawselection tool.
- can delete a selection by pressing delete in the drawselection tool.
- can undo/redo create and delete selection.
- when drawn by drawselection tool, selections are adorned with
  sizing squares.
- when drawn by drawselection tool, selections have a circle in the middle.
- moving the cursor near the circle centre changes it to the move cursor.
- moving cursor near the 4 corners changes it to the appropriate sizing arrow.
- can click and drag a selection around.
- can resize a selection.
- create pick tool images.
- add pick tool to toolbar, including event handlers.
- add Selection::getBoundingRect() method.
- add Selection::getRectsOnRow() method
- subclass play task to work with selection.
- Create Help menu containing About, Webpage.
- Create About Dialog.
- About dialog works.
- Webpage link works.
- Create way of saving document
- Create way of loading document
- Disk sound image works.
- when loaded wave file is too large, prompt to create disk file.

- renderToDib should work if diB is larger than sound.

Here are the slides.
---------------------

Welcome to Wavelet Sound Explorer. Open a short .wav file to start.

[Open]
-----------
With the play tool, you can highlight a portion of the image.
Wavelet Sound Explorer will play back only that portion of the sound.
-----------

----------------------
Want a quick preview mode -- for picture making program.

Idea: Wavelet Sound Explorer. Create pictures from sound. Study how sound and
frequency relate to eachother.



Parameters:
- Sound file -- wav or mp3
- image size (small, medium, large)
- frequencies (20Hz to 20000Hz default) 
- colour scheme

Tasks:

- Create a window with a sidebar like photowipe. 
- But instead of sliding menus, we have a scrolling web page like thing.
- As soon as any option is changed, if it is possible to render, we restart
rendering.

"
Select a sound file. You can analyse .wav or .mp3 files. If they are stereo,
they will be reduced to one channel.

Chosen sound file:
(none)

[Choose]    


"Choose the frequencies that you are interested in. 20Hz is the lowest sound
humans can hear, and 20000Hz is thought to be the highest.

High: [20000]

Low: [20]

The wave parameter determines how well we detect frequencies. A high number
distinguishes frequencies well, but where they begin is fuzzy. A low number
detects when frequencies begin well, but the frequencies are fuzzy.

Wave parameter: [10.0] (0.849 to 50) 
"

- Create generic WorkerThread object template and WorkerThreadObserver.
- In constructor, they take observer, which has a workerThreadNotification
function. 
- Inherits from Thread.
- Also has stop(), done() and getPercentDone() function.

- Create ScalogramParams object --
    sound file,
    image size,
    frequencies

* Move colour scheme to separate file.    

- Create SoundImage object
    - alloc( samples, bands ) allocates an image of complex samples of given size.
    - renderAsync( dib, colour scheme ) renders to DIB

- WorkerThreadObserver

- SoundImageCreator Thread, SoundImageCreatorObserver
    - takes given ScalogramParams, notification func,  
    - after thread is done, may return SoundImage reference.
    - Can be interrupted. 
    - Reports significant percent changes

- Make scalogram algorithm work pixel-by-pixel.
- Load an MP3 file in.

--------------------
Goal: Handle 5 minute song, sampled at 44100 Hz mono.

That means there are 
44100 * 60 * 5 = 13 230 000 
samples.

We must analyze frequencies from 20Hz to 20000 Hz. That's:
44100/20 = 2205 samples to 44100/20000 = 2 samples

2205-2 = 2203 different frequencies to measure.

This would create:

13 230 000 * 2203 = 19 145 690 000

about 19 billion samples. If stored as floats, this means we have
7 gigabytes of data.


-----------------------
OK, I really want to do a full wavelet transform..... 

When wavelet transform would exceed 512 MB (configurable), then allocate inside
a memory mapped file.

If processing a single line took a considerable amount of time, then send event
to update percentage.

As we render a line, create a quick preview (maximum 2048xnumbands) The quick
preview consists of maximum of each represented pixel magnitude.

-----------------------
We can reduce this if we note that not all frequencies are used at the same
time usually. So we divide the sound into frames. 

For each frame:
- perform fft on the frame.
- for frequencies that are close to 0, assume spectrogram row is all zeros
  (don't even store)
- for frequencies with some power, perform wavelet analysis.
- hopefully this will save some space!

But before I do this, I need to prove the inverse CWT works... 
- inverse CWT is:
    for all offsets,
        for all scales,
            image(offset, scale) * 1 / sqrt(scale) * wavelet(offset, scale)

- then multiply whole thing by the sum of the fourier transform squared of the
  wavelet, divided by the frequency.
  sum(F(f)^2/f)

  - The admissibility condition is too hard to calculate. Ignore it and use
    normalized waveforms for now.


