Skip to content
ndonald2 edited this page Mar 4, 2013 · 4 revisions

The development of Tonic follows these guiding principles, which should always be considered when discussing features and architecture.

Flexibility

Users of Tonic should be able to patch, route, and message to their hearts' content. All developments to the underlying architecture should reflect this guideline, by adhering to the following:

  1. Any parameter should be controllable by something else. For Generators, this means that any parameter that makes sense to be controlled by a signal-rate input should expose itself as an input for another Generator, and any parameter for which a control-rate value will suffice should expose itself as an input for a ControlGenerator.

  2. Any parameter that is intended to be controlled from an external source - whether a UI or somewhere else in the program - should be registered as a named parameter, so that it may be set using a string and a value rather than via a member function. This also allows the same name to be used to control multiple parameters simultaneously.

Simple Syntax

In order to make patching and signal-chain building as easy and readable as possible, Tonic uses a very simple syntax, with overloaded operators standing in for common signal chain operations (add, multiply, route in, etc). Additionally, the use of instance variables in Synth subclasses is discouraged. Rather, the "smart-pointer" capability of Generators (and other core objects) allows for signal chains to be built in-line without worrying about allocation:

Example:
// This produces a frequency-modulated square wave fed through a lowpass filter with a controllable cutoff
outputGenerator = (RectWave().freq( 440 + (100 * SineWave().freq( addParameter("ModFreq", 100).ramped()) ) >>
                   LPF24().cutoff( addParameter("Cutoff", 800).ramped() )* 0.8;

Performance and Efficiency

In order to be on-par with (or better than) other portable synthesis libraries, performance optimizations are key in the development of Tonic. After writing and testing stable DSP code, always profile it and perform necessary optimizations to ensure high-performance.

Where possible, the use of the Accelerate framework (Apple only) can greatly improve performance of mathematical signal-vector operations, but its usage should be conditionally compiled only when the target OS is Mac OSX. An equivalent version of the same task should be written without using Accelerate so the library remains completely portable.

Openness

Tonic is, and should always be, an open-source project. Anyone with interest and knowledge should be welcome to contribute to the library and share examples, projects, etc.