Smart pointers, sample tables, ring buffer for input processing

This is the same pull request as before, with fixes for all the demos and more illustration of the new features.

#### Smart Pointers

- Templated reference counting smart pointer `TonicSmartPointer` that is used instead of duplicate code in several places
- `BufferFiller` and all its subclasses are now true `Generator` subclasses wrapped in smart pointers, and can also be used as Generators (see SynthsAsGenerators.cpp for example)
- `Synth` no longer needs to be directly heap-allocated now that it's wrapped in a smart pointer. All demos and objects handling `Synth` instances now store as value rather than pointer.
   - Default constructor for `Synth` uses a passthrough generator, so uninitialized instances will produce no output

#### Sample Tables and Input

- Using a new class `SampleTable` to wrap instances of `TonicFrames` with shared data access, so the same data can be accessed in multiple places.
- `TableLookupOsc` uses these to provide the lookup table. Can be provided externally (`ArbitraryTableLookupSynth`) or by a subclass (`SineWave`).
- `RingBuffer` is a very simple ring buffer with over/underrun detection, based on `SampleTable`. Can be used to acquire/process input from a mic, etc (see the input demo - it will glitch out in the simulator fairly quickly, but that's a known simulator bug).

#### Misc

- `TonicDictionary` is an easier way to work with `std::map` for storing/retrieving objects keyed by strings.
- Mutexes removed from Generator level for performance reasons, no hot-swapping supported right now. Currently living in `BufferFiller`
   - Another approach is in [this branch](https://github.com/TonicAudio/Tonic/tree/ND-MutexOptim). Uses smart pointer for `SynthContext`, which owns the mutex and passes down to Generators. This approach needs review. @Dewb would you mind providing some feedback here? We can chat about it offline, too.