GetDunne Wiki

Notes from the desk of Shane Dunne, software development consultant

User Tools

Site Tools


juce_and_parameter_automation

JUCE and parameter automation

In audio-recording parlance, automation refers to the ability of a recording system (traditionally a mixing console, more recently a DAW) to record, and subsequently reproduce, real-time adjustments to parameters such as track volume. In DAW systems, automation extends to cover real-time parameters of plug-ins (e.g. synthesizers and signal processors). To make this work, both DAW and plugin must support bi-directional communication of parameter values, i.e.,

  • Plugin to host: user manipulates GUI controls, changes are recorded by a host DAW.
  • Host to plugin: DAW recreates user's manipulations automatically using playback.

Automation vs. saving/restoring plugin state: DAWs and plugins also use an unrelated non-real-time method of bi-directional communication scheme, to allow the DAW to save the entire state of each plugin as part of a recording project file, in order to later restore that state when the file is reopened for a later editing session. Although this is separate from automation, I consider this an important aspect of plugin parameter management which ought to be integrated into the parameter-handling code. In JUCE, state management is supported through the getStateInformation() and setStateInformation() methods of the AudioProcessor class.

JUCE 5 provides two distinct sets of classes to support parameter automation via an older and a newer approach. The older approach, which pre-dates JUCE version 5, involves instantiating parameter objects based on classes derived from AudioParameter. The newer approach, based around an extensive new class called AudioProcessorValueTreeState, promises more streamlined code and integrated support for undo/redo operations. Neither approach is particularly well-documented, so I decided to investigate both myself.

The older approach: AudioParameter

The older approach, which pre-dates JUCE version 5, involves instantiating parameter objects based on classes derived from AudioParameter:

  • AudioParameterFloat represents a floating-point value, e.g. a value set by a knob or slider. This is the most basic kind of parameter, because floating-point parameters are supported by all plugin hosts, regardless of the specific interface technology.
  • AudioParameterInt represents an integer value, e.g. something like a MIDI note-number or velocity.
  • AudioParameterChoice represents a discrete choice among a defined set of values, e.g. an oscillator waveform type chosen from the set { *sine, triangle, square, sawtooth* }. You could think of this as a specialized form of integer parameter, where the range is restricted to [0, *number_of_choices*-1].
  • AudioParameterBool represents a logical value (*true* or *false*), e.g. whether a certain effect or function is enabled or not. You could think of this a limited form of choice parameter where the available choices is { *false, true* }.

Updates from the plugin to the host are sent by calling AudioParameter methods, of which there are three:

  • beginChangeGesture() alerts the host that a sequence of parameter changes is forthcoming
  • operator= (which itself calls setValueNotifyingHost()) sends the update
  • endChangeGesture() informs the host that this sequence of changes is done

This three-stage approach is obviously designed for use with continuous controls such as knobs or sliders, but is actually required for all kinds of parameters. (If you omit the …ChangeGesture() calls, the host DAW will not receive the changes.)

Updates from the host to the plugin are received as asynchronous calls (callbacks) to the AudioProcessor::setParameter() method, for which the plugin author must provide an override. In JUCE 5, this method has been marked as deprecated, meaning that it will eventually be unavailable, in some future release of the JUCE library. (And at that point, I would expect AudioParameter and its subclasses would disappear also.) Hence this is clearly no longer the recommended approach for parameter automation in JUCE.

I have put together a practical demo of how to apply this approach in a new project on GitHub at https://github.com/getdunne/juce-AudioParameterTest. For more details see AudioParameterTest.

The newer approach: AudioProcessorValueTreeState

JUCE version 5 introduces a new class AudioProcessorValueTreeState, intended for managing both state-saving and automation. Parameter values are represented by new classes defined within AudioProcessorValueTreeState, which are probably intended to replace AudioParameter and its subclasses. These are organized into a ValueTree structure, which supports the option of organizing parameters into some kind of hierarchy, and also the concept of automatic undo and redo actions. There are also new “attachment” classes—again defined within AudioProcessorValueTreeState itself—to connect parameter objects to GUI controls with minimal coding.

This will be the subject of my second exploratory project. See AudioParameterTest2.

More to come…

juce_and_parameter_automation.txt · Last modified: 2017/10/22 20:32 by shane