Mozzi  version v2.0
sound synthesis library for Arduino
Audio Output and Buffering

Documentation on basic Mozzi architecture and output modes

Basic architecture of audio generation, buffering, and output in Mozzi

Mozzi provides support for audio ouput on a range of different boards and CPUs.This page is about the following related topics:
  • adding a custom output method (importantly using external DACs) to your sketch
  • writing sketches that will work on different platforms / with different output methods
  • extending Mozzi for a new architecture
For all of these topics, it is helpful to have a basic understanding of the basic output steps in Mozzi:
  1. Inside the loop() function in your sketch you call audioHook(). 1a. If the audio output buffer is currently filled, this does nothing. 1b. Otherwise, this calls updateAudio(). The generated sample is then added to the audio output buffer. (Also, updateControl() will be called at an appropriate rate, and a few other details that are not important for this discussion.)
  2. A platform-specific timer is triggered at audio rate (usually), takes a sample from the output buffer and sends it to audioOutput().
  3. The audioOutput() function - usually predefined inside Mozzi - takes care of sending the sample to the hardware.
These output steps are not always followed, however. Firstly, when using External audio output output, the audioOutput() funtion is supplied by the user sketch, instead of Mozzi. External audio output output.Some ports will also want to bypass the Mozzi audio output buffer. For instance, an internal DAC may be addressable via an efficient DMA-connected buffer, already, and also have a built-in rate control. In this case, ports will internally set the define BYPASS_MOZZI_OUTPUT_BUFFER to true. Such a port will have to provide a custom definition of canBufferAudioOutput(), returning true, whenever a new sample of output can be accepted. No timer at audio-rate is set up in this case.Finally, the External audio output output mode (MOZZI_AUDIO_MODE MOZZI_OUTPUT_EXTERNAL_CUSTOM) is essentially a combination of the two. Here, the user sketch needs to provide both audioOutput() and canBufferAudioOutput(). The latter is again called from audioHook(), and whenever it returns true, a new sample is generated and passed to audioOutput().

Platform specific audio resolution

Different output methods often support a different resolution of output samples. To provide best performance on slow boards, Mozzi expects your updateAudio() function to return samples in exactly the width that is needed at the output stage. Thus, defining this naively, an updateAudio() function designed for 8 bit output will produce very low volume output on a 16 bit DAC, while the other way around overflows will result in way too loud and heavily distored output. Fortunately, all that is needed to write portable sketches is to specify how many bits your updateAudio() function provides. The (inline) functions in the AudioOutput namespace do just that. Using them makes sure your audio output is shifted if, and as much as needed on all platforms.

See also
MonoOutput::fromNBit(), StereoOutput::fromNBit()

External audio output

Only for MOZZI_AUDIO_MODE set to MOZZI_OUTPUT_EXTERNAL_TIMED or MOZZI_OUTPUT_EXTERNAL_CUSTOM. Most (all?) platforms support output using an "external" function. When using this option, you will need to provide a suitable definition for audioOutput() in your own sketch, yourself. Some understanding of the general Mozzi audio output architecture may be recommendable, when using this mode: See AudioOutput .In the more simple case (MOZZI_OUTPUT_EXTERNAL_TIMED), Mozzi will still take care of buffering the samples, and calling this function at audio rate (hence "timed"). This generally involves use of a timer, which should be detailed in the Hardware and configuration details for your platform.Should you desire even more control - perhaps because your board, or your external DAC already comes with a rate controlled DMA buffer - using MOZZI_OUTPUT_EXTERNAL_CUSTOM also bypasses Mozzis sample buffer. In addition to audioOutput(), you will then need to provide a definition for canBufferAudioOutput(), which will control the rate at which samples are produced. In essence, whenever canBufferAudioOutput() returns true, Mozzi will call updateAudio(), and pass the produced sample to audioOutput(), unbuffered. It is entirely your job to make sure that this actually happens at MOZZI_AUDIO_RATE, and / or an appropriate buffer gets used.One additional configuration setting is MOZZI_AUDIO_BITS, which defaults to 16 bits for this mode, but might be set higher, if your hardware supports it.
See also
Mozzi Configuration options