Voltage Programmer's Guide 1.0.6

Download as pdf or txt
Download as pdf or txt
You are on page 1of 100

Voltage Modular Programmer’s Guide

Version 1.0.6

Written by Dan Goldstein and Russ Cary

www.cherryaudio.com
Table of Contents

Theory of Operation 4
Processing Samples 4
Technical Specifications 5

Installing the Module Designer 6

Configuring the Module Designer 8


Audio Settings 8
Code Editor 9
Miscellaneous 9

Creating a Module 11

Module Functions and Variables 16


User Variables & Functions 16
public void Initialize() 16
public void Destroy() 16
public boolean Notify( VoltageComponent component, ModuleNotifications notification,
double doubleValue, long longValue, int x, int y, Object object ) 17
public void ProcessSample() 17
public String GetTooltipText( VoltageComponent component ) 18
public void EditComponentValue(VoltageComponent component, double newValue) 19
public byte[] GetStateInformation() 19
public void SetStateInformation(byte[] stateInfo) 19
public void OnUndoRedo( String undoType, double newValue, Object optionalObject ) 20

Module Programming Example 22

Module Examples Included In Developer Kit 31

Module Controls 32

Library Classes 33

Module Designer Features 34


Theory of Operation
Voltage is a modular synthesizer in the truest sense. A Voltage module is a stand-alone object,
capable of producing any sound a programmer can dream up. Every module in Voltage is a
self-contained unit, with its own processing code, artwork, and resources. Its capabilities are
practically limitless - from filters to oscillators, from complex effects to MIDI arpeggiators, from
mixers to sequencers, the sky's the limit.

Voltage Modules are written in Java, and all code is Java 8 SE compliant. All of the capabilities
of the Java language are at your disposal, including multithreading, encryption, networking
capabilities, and more. Voltage is powered by a highly optimized “hot spot” virtual machine that
compiles the Java functions directly to machine language, so modules run at essentially the
same speed as compiled native code.

Processing Samples
The ​Initialize()​​ function gets called once, when a module is first created. Any default values can
be set up in this function. For example, filters and oscillators can be configured, effect
algorithms can be set to their default values, lists can be populated, etc.

For every sample that is generated by Voltage Modular, a module’s ​ProcessSample()​​ function
is called. This is the most important function of any module, as it does the core work of the
module. Typically, the primary operation of a module involves reading one or more input signals
from input jacks, processing these signals, and outputting the processed values to output jacks.
Of course, some modules, such as oscilloscopes, may not have output jacks, and other
modules, such as simple oscillators, may not have input jacks.

While controls such as knobs, sliders, jacks, buttons, etc., are drawn natively by the Voltage
application, they are created by calls from the Java code, and notifications are sent to the Java
module when controls are modified. By processing these notifications, controls such as gain
knobs, frequency sliders, etc. can alter the sound of a module. The​ Notify() ​function gets called
whenever controls are modified. In addition, notifications can be sent for mouse events,
connecting and disconnecting cables, GUI updating, and other events.

Initialize()​​, ​ProcessSample()​​ and ​Notify()​​ are the critical functions necessary to build almost
any module. However, there are additional functions that you can use to save and restore
custom settings, format custom tooltip text, handle custom undo/redo commands, and more.
With many simple modules it may not be necessary to write code for these additional functions,
but advanced modules will find that these extra functions will allow you to customize your
modules in many useful ways.
Technical Specifications
All samples within Voltage module are 64-bit floating-point doubles at 48Khz. Audio coming into
and going out of Voltage will be seamlessly resampled to match the sample rate of the host
application with a high-quality resampling algorithm.

Floating-point denormals are deactivated (flushed-to-zero) on the CPU level by Voltage, so your
DSP code does not need to worry about correcting for denormals.

Voltage modules are designed to process a nominal input and output range of +/- 5.0 “volts.”
Incoming audio is mapped from (-1.0, 1.0) to (-5.0, 5.0) and outgoing audio is mapped from
(-5.0, 5.0) to (-1.0, 1.0) when it is returned to the sound device or to your DAW. Modules can
certainly output higher or lower voltages - there is no limit - but some modules, such as filters,
are likely to clip when signals above (-5.0, 5.0) are received.

In this way, audio and control signals can be used completely interchangeably. LFOs and
oscillators output (-5.0, 5.0) and audio signals coming in to Voltage have the same range. You
can use audio to modulate values, or run an LFO through a filter to create an unusual wave
shape. There should be no distinction whatsoever between audio signals and control signals,
and your modules should function with any signals.
Installing the Module Designer
Installing the Module Designer tool requires two main steps:

1. Running the Module Designer Installer.


2. Install the Java Development Kit for Java SE 8.

You can download the Java SE 8 Development Kit here:

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

The current JDK SE 8 is Build 8u181. Be sure to download and install the correct JDK version
for your computer. “macOS” and “Windows x64” will be the most common downloads.

Please note: ​Windows Users will need to modify their Path to point to the Java JDK’s bin folder.
Please see
https://docs.oracle.com/javase/7/docs/webnotes/install/windows/jdk-installation-windows.html​ for
instructions. You’ll want to add something like ​C:\Program Files\Java\jdk1.8.0_181\bin​ to your
Path environment variable.

Once you’ve run the JDK installer, open a Command Prompt in Windows or a Terminal on OSX,
and type in the following command:

java -version

You should see something like this in response:

java version "1.8.0_181"


Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

Next, type in this command:

javac -version

You should see something like this in response:

javac 1.8.0_181
Be sure the version shown in both of these tests is at least 1.8. ​If the java or javac
commands cannot be found, there may be an issue with your installation. If you’re using
Windows, you probably forget to add the Java folder to your system path. See the link above for
instructions.

Please note: ​If you have a newer Java JDK installer, that’s probably OK, ​but be careful not to
use any JDK9+ commands in your Java module,​ because they won’t run in our Java 8 virtual
machine.

If your Java version is correct, and you’ve installed the Voltage Module Designer, then you’re
done! Let’s start building modules!
Configuring the Module Designer
Before we begin programming, let’s first configure the Module Designer’s settings. To do so,
click on the Edit menu and select Preferences.

Audio Settings
In the Audio Settings section, you’ll select your Input and Output devices, set your sample rate
and buffer size/latency, and choose any MIDI devices that you want to use when testing a
module.
Code Editor
The Code Editor preferences allow you to customize your font and spacing choices.

Miscellaneous
The Miscellaneous settings allow you to choose a JDK location and modify some additional
settings. Note that it is not necessary to choose a JDK location unless you wish to use a JDK
other than the default JDK installed on your system.
Creating a Module
The basic steps for creating a module are:

1. Setting the basic parameters for a module, including module name, Java class name,
Package Name, module width, etc.

2. Choosing a background graphic, known as a “skin”, for the module.

3. Placing controls, such as jacks, knobs, buttons, text labels, etc. onto the module.

4. Writing the Java code for the module to hook up all the controls.

To configure the basic properties of a module, click on the background of a module and you will
see the Module Properties in the Properties Pane. (If you don’t see the Properties Pane, click
View->Properties Pane to ensure that it is visible.)

Module Name
This is the full name of the module. The module will be listed in a user’s module library and in
the Voltage Module Store with this name.

Java Class Name


This is the name of the main Java class for your module project. It must be a valid Java class
name, and cannot contain any spaces. Because, in this example, the class is named
PolyCVConverter, the first line of the class will read:

Public class PolyCVConverter extended VoltageModule

Package Name
This is the name of the unique package that this specific module belongs to. The package for
every module you create should be unique. Java package naming conventions ​can be found
here.

Manufacturer
This should be your name, or the name of your company. Modules will be listed in a user’s
module library and in the Voltage Module Store with this manufacturer name.

Type of Module
This allows you to choose one of five main categories for your module. The categories are:

Sources -​ oscillators, noise generators, percussion modules, etc.


Processors -​ filters, wave shapers, etc.
Controllers ​- envelope generators, sequencers, keyboards, MIDI-to-CV, etc.
Effects ​- reverb, delay, phaser, chorus, etc.
Utilities ​- mixers, gates, multipliers, amplifiers, etc.

It is very important that you select the best category for your module. Modules will be listed in a
user’s module library and in the Voltage Module Store with this selection. In addition, choosing
the correct module type helps Voltage mix audio in the most efficient manner.

Width & Height


Voltage modules are sized according the the Eurorack specification. Eurorack modules are all
128.5 millimeters high, or approximately 5” high. The width of a module is measured in units
called Horizontal Pitch, or HP. One HP is .2” wide. Voltage module sizes are always in integer
units of HP. The Width dropdown will allow you to select the width in inches, and it will also
show you the size in HP and in pixels.

The module shown is 3.2 inches wide, which is 16 HP. At 100% zoom, the module will be 230
pixels wide by 360 pixels high. You can use these dimensions to create custom background art
for your module.
Background
This launches a dialog that lets you select your module’s background. It can be either a solid
color or an image file.

Extra Resources
This lets you embed additional resources (such as audio files in a sampling module, to name
one likely example) in your module. Use the GetBinaryResource function to obtain ByteBuffers
resources you’ve added to the Extra Resources section.

Additional Java and JAR Files


These allow you to add extra Java and JAR files to your project. Any extra Java files you add
can be edited in the module designer’s code editor.

Copyright
This field allows you to declare a copyright statement that will be embedded in your published
module.

Notes
You can use this field to store any notes about this module. These notes won’t be added to your
published module; they’re there strictly for your benefit.

Placing Controls

To place controls onto your module, make sure that the Controls Pane is visible. If it isn’t, click
View->Controls Pane to show the pane.
On the Controls Pane, you will see a list of various controls that can be added to a module.
Adding these controls is as simple as dragging and dropping them onto your module.

For example, to add a knob to your module, simply click on the “Knob” text and drag the control
onto your module. When you release the mouse button, a knob will be created on your module.

The red outline indicates that this control is currently selected. To resize the control, click on the
red outline and drag in any direction. Note that some controls, such as jacks, cannot be resized,
and other controls, such as knobs, will always have a fixed ratio of width to height. Controls in
Voltage use vector graphics, so it is safe to resize them to any size that you want.

When a control is selected, the control’s properties will be shown in the Properties Pane.
Every control will have the following properties:

Name
This is the visible name of the control. It is important to name every control well, because these
names are often visible to the user. For example, a volume control should be given a
descriptive name, such as “Master Volume”. ​Note that every control name must be unique.
In addition, once you have published your module, you should not change the control
names, as they are used to save & restore the settings of a module.​ So please take care to
name every control well from the start.

Variable Name
Every control is represented by a variable in the Java code. To make programming easier, it is
recommended that you give controls a descriptive variable name. For example, a volume
control might be given a variable name of volumeKnob. A variable will be automatically created
for each control. It will look like this:

private VoltageKnob volumeKnob;

Left
This is the X position of the control on the module.

Top
This is the Y position of the control on the module.

Width
This is the width of the control.

Height
This is the height of the control.
There are multiple ways to change the position of a control. You can drag it with your mouse;
you can select it and use your arrow keys to position it; or you can manually type in new values
into the Left and Top property fields.

Likewise, there are multiple ways to resize a control. You can drag the red outline to resize a
control; or you can type new size values into the Width and Height property fields.

Every control will have automatically-generated code that creates the control, sets its position,
and sets any flags and properties. When you change any property of a control, including its
variable name, all of the automatically generated code will be instantly updated to match the
new settings.

Each controls type will have many additional properties that will be discussed in more detail in
the documentation for each control type.
Module Functions and Variables
While the code to create a module’s controls is automatically generated, it is up to the
programmer to write the code that makes the module actually do something useful. The
following functions are available to the module programmer.

User Variables & Functions


This section of the Source Code is where programmers can define any member variables and
custom functions for their class. For example, if you want to store the current volume in a
variable, you might write:

private int volume;

If you wanted to create your own function to set the current volume, you might write:

private void SetVolume(double newVolume)


{
this.volume = newVolume;
}

public void Initialize()


This function gets called when a module is first created. It is very useful for setting up default
values, as well as initializing effects algorithms, oscillators, filters, etc.

If we have a knob called masterVolume, we might write the following Initialize code to read the
start position of the knob:

public void Initialize()


{
// add your own code here
This.volume = masterVolume.GetValue(); // This gets the current value of the knob
}

public void Destroy()


This function is called when a module is deleted. Typically, it is not necessary to write any code
in the Destroy() function, because Java will automatically free any member variables. However,
for more complex modules, it might be desirable to end timers, close network connections, close
files, etc.

public boolean Notify( VoltageComponent component,


ModuleNotifications notification, double doubleValue, long
longValue, int x, int y, Object object )
This important function is used to receive notifications from Voltage when:

● Controls are altered


● Mouse events occur
● Cables are connected or disconnected from jacks
● Canvas controls are about to paint, or are finished painting
● A GUI Update Timer has fired

It is likely that many additional notifications will be added to Voltage Modular over time.

A typical use case would be to receive a notice when a knob is turned:

public boolean Notify( VoltageComponent component, ModuleNotifications notification, double


doubleValue, long longValue, int x, int y, Object object )
{
// add your own code here
switch(notification)
{
case Knob_Changed:
{
if (component == masterVolume) // If the Master Volume knob is turned..
this.volume = doubleValue; // ..then store its new value in our volume variable.
}
}
}

public void ProcessSample()


This function gets called once for every sample that gets generated by Voltage. Typically, this
function will read input signals from input jacks, process the audio through a DSP algorithm, and
write output signals to output jacks.
All audio generated by Voltage is fixed at 48 kHz, regardless of the sample rate of the host
application. As a result, you can build fixed sample-rate DSP algorithms that do not need to
adjust for sample rate changes.

It is always a good idea to write intelligent and efficient code in your ProcessSample() algorithm.
If a module is not connected to any outputs, for example, it may be possible to skip sections of
CPU-intensive DSP processing. You will always want to write a value of 0 to any outputs, even
if you’re skipping DSP processing, so that values do not get “stuck” on a cable when a module’s
inputs are disconnected.

A typical example of a ProcessSample() function might look like this:

public void ProcessSample()


{
// add your own code here
double inputSignal = inputJack.GetValue();

// Adjust the input signal by our volume value


double outputSignal = inputSignal * this.volume;

outputJack.SetValue(outputSignal);
}

public String GetTooltipText( VoltageComponent component )


Voltage will automatically generate a tooltip whenever a knob or slider is adjusted. If a knob has
a range of 0 to 1.0, that exact value will be shown in the tooltip. However, if the “Display Values
In Percent” flag is set for a knob or slider, then the value will be multiplied by 100 and displayed
with a percent sign, so a value of 1.0 will be displayed as 100%.

In some cases, you may wish to show a different value. For example, you may wish to show a
value with particular units. Or, for example, filter cutoff frequency knobs work best when they
operate logarithmically instead of linearly. In these cases, you can add code to the
GetTooltipText() function to return a custom tooltip for a specific control.

A typical example of a GetTooltipText() function might look like this:

public String GetTooltipText( VoltageComponent component )


{
if ( component == null )
return super.GetTooltipText( component, bChanging );
// add your own code here
If (component == frequencyKnob) // If the Frequency Knob is about to show a tooltip..
{
return String.format("%.1f Hz", frequencyKnob.GetValue()); // Return tooltip with unit “Hz”
}

return super.GetTooltipText( component );


}

public void EditComponentValue(VoltageComponent component,


double newValue)
A Voltage user can choose to type in an exact value on a knob and slider instead of just moving
the control. If a knob has a range of 0 to 1.0, then the user can type in a value between 0 and
1.0, and that value will be set in the knob. However, if the “Display Values In Percent” flag is set
for a knob or slider, then the value types in will be divided by 100. So, for example, if the user
types in 100, the value will be set to 1.0.

As in GetTooltipText, certain controls may display tooltip values that do not line up directly with
the minimum and maximum values of the control. For example, a filter knob may have a min of
0 and a max of 1.0, but may display values from 20 to 20000, with a logarithmic response. In
these cases, if a user types in a frequency that they want to set the knob to, e.g. 10000, this
function can be used to map the value that is typed in to the correct linear mapping. For
example, the value 10000 may map to a linear value of .20 on a knob.

In this case, your code must change the ​newValue ​variable to a correct linear mapping between
the Min and Max values of the control.

public byte[] GetStateInformation()

public void SetStateInformation(byte[] stateInfo)


When saving a preset, Voltage will store the position of every knob and slider in your module,
the state of all toggle buttons, and the state of all cables that are plugged into any of the
module’s jacks. These values will be restored when the user loads the preset. For many
modules, this means that the entire state of a module will be automatically saved and reloaded.

However, many more complex modules have have controls that affect internal values. For
example, there might be buttons for transposing an octave setting up or down, or for setting a
MIDI channel, or for loading a sample. In these cases, storing the knob, slider, and toggle button
positions won’t be enough to restore the state of a module.
In these cases, additional module information, such as the selected octave, MIDI channel, file
path, etc., can be saved and restored using the GetStateInformation() and SetStateInformation()
functions. GetStateInformation() returns a byte array that can contain any sort of information
that you want to store, in any format. SetStateInformation() receives that same byte array back
and must decode it.

We recommend using the ​java.util.Properties​​ class to easily store various properties for your
module, and the ​java.io.ByteArrayOutputStream ​and ​java.io.ByteArrayInputStream​​ classes
to convert the Properties object into a byte array, and later convert the byte array back to a
Properties object. However, you can use any method you’d like to store and restore the data.
For example, a String can be turned into a byte array as follows:

String fileName = “sound.wav;


byte[] byteArray = fileName.getBytes(StandardCharsets.UTF_8);

The byte array can be turned back into a string as follows:

String decodedFileName = new String(byteArray, StandardCharsets.UTF_8);

In addition, the ​java.io.ByteArrayOutputStream ​and ​java.io.ByteArrayInputStream​​ classes


can be used to turn any ​serializable​​ class into a byte stream, so you could easily create your
own serializable class to store module data.

Note: ​any Java imports that you wish to add to the project, such as

import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;

can be placed in the “User Imports” section of the Source Code.

public void OnUndoRedo( String undoType, double newValue,


Object optionalObject )
Voltage will automatically create Undo and Redo events whenever a knob, slider, or toggle
button is changed. However, more complex modules may have situations where custom undo
operations are required. For example, using buttons to change a MIDI channel, change a
transpose setting, or load a sample should generate custom undo events. Fortunately, this is
very easy to accomplish using the CreateUndoNode() functions that are built in to every module.
There are two of these functions:

public native void CreateUndoNode(String undoType, String description, double


previousValue, double newValue);
public native void CreateUndoNode(String undoType, String description, Object
previousValue, Object newValue);

The first function stores the previous value and the new value as a double. The second function
allows you to store the previous value and new value as a generic Object. You can pass in any
object, such as a String.

When incrementing a MIDI channel, you might call:

CreateUndoNode(“changeMidiChannel”, “Change Midi Channel”, currentChannel,


currentChannel + 1);

That’s all you need to do. The first string, “changeMidiChannel”, identifies the undo operation.
This label will be passed in to OnUndoRedo() as the ​String undoType.​ The second string,
“Change Midi Channel”, is the description of the undo event, and is shown to the user if they
hover over Voltage Modular’s undo or redo buttons. Finally, ​currentChannel​ and
currentChannel+1​ are the “before” and “after” values. The “before” value will be passed in to
OnUndoRedo() when a user hits Undo. The “after” value will be passed in to OnUndoRedo()
when a user hits Redo.

Here is a typical example of using this function:

public void OnUndoRedo( String undoType, double newValue, Object optionalObject )


{
// add your own code here
if (undoType == “changeMidiChannel)
currentChannel = newValue;
}
Module Programming Example
Perhaps the simplest module that we could build would be a simple Volume module. This
module will take an input signal, modify its volume, and output the new modified signal.

To create this simple module, we will start by setting the module’s properties. We will give the
module a name (“Volume Module”), a Java Class Name (“VolumeModule”), a package name
(“com.cherryaudio.volumemodule” in our case -- but you would want to use your own package
name), and set its width (10 HP, or 2.0 inches). If you want to add a custom background skin,
you can, but for this example we’ll just use the default grey background.

We will drag in a knob, an input jack, and an output jack. We’ve also added three text labels,
which read “Volume”, “Input”, and “Output”:

Next, we’ll set up the properties for the Input Jack and the Output Jack. We’ll want to name the
jacks (“Input Jack” and “Output Jack”) and give them proper variable names (“inputJack” and
“outputJack”) as shown:
Likewise, we’ll configure the volume knob. We’ll name it (“Volume Knob”) and give it a variable
name (“volumeKnob”). We’ll choose a skin for it, too (we’ve chosen “Cosmo Large”).

Now, we’ll want our volume module to go from 0 to 200%, so we’ll set the Min Value to 0.0 and
the Max Value to 2.0. We’ll also check the “Display Values In Percent” checkbox so that tooltips
will multiply the number by 100 and display the volume in percent (0 to 200%):
In the ​User Variables & Functions​ section of the Source Code, we’ll create a private variable
called ​volumeValue,​ of type double, to store the current volume value:

Next, we’ll modify the Initialize function. We want the volumeValue variable to be set to the
volume knob’s default value when the module is first created. We can call the ​GetValue()
function on the knob to get its current value:
Now, when the user turns the Volume Knob, our module’s ​Notify() f​ unction will get called. The
notification will be ​Knob_Changed,​ the specific component (volumeKnob) that changed will be
passed in to the ​Notify() f​ unction’s ​component​ variable, and the new value will be passed in to
the ​Notify() f​ unction’s ​doubleValue​ parameter.

We’ll modify the ​Notify() f​ unction to check for a ​Knob_Changed ​message coming from our knob
with the variable name of ​volumeKnob. ​If this notification comes in, we’ll store the new volume
value, which will be between 0 and 2.0, in our ​volumeValue v​ ariable.

Now that all of the elements are in place, we just need to write our ​ProcessSample()​ function!
This function needs to read a signal from the input jack, adjust the signal’s volume, and write the
modified signal to the output jack. Since adjusting a signal’s volume is just a matter of
multiplying the signal by the volume, this can be very easily accomplished with just a few lines
of simple code:
At this point, we should have a fully functioning Volume module. Let’s compile it to make sure
our code is correct. To compile the module, we’ll click on the Build menu and select the “Build”
menu option. If everything worked correctly, we should see something like this in the Output
Pane:

However, if there’s an error, the output pane will show you exactly what’s wrong. ​If you don’t
see any output at all​​, then there is an issue with your Java Development Kit installation.
Please follow the instructions in the “Installing the Module Designer” section to resolve this
issue.

Once the module builds correctly, we’ll want to test it. To do this, click on the Build menu and
select “Run without Debugger”. This will compile the module and then actually load and run your
module in a test environment. This will allow you to instantly test your module to make sure it
works. Pretty cool, right?

If the module builds correctly, it should show up next to the Module Design’s Test Module, which
creates test signals that you can use to test your module. Connect the “L” or “Mono” Test Signal
Output to your Volume Module’s input jack, and connect your Volume Module’s output jack to
the “Audio Ret To Host” L jack, as shown below. Make sure the Square Wave output is
selected, and adjust the Oscillator Frequency knob to something audio, perhaps around 100 Hz.
If you’ve done everything correctly, you should now be hear a square wave. And, you should be
able to turn your Volume knob to increase or decrease its volume, or to silence it altogether.

When you’re done, click on the Build menu and select “Stop Running” to end test mode.

Improving Our Design

Now that we have a functional module, let’s discuss two ways that we can improve the design of
this module.

When running this module in Test Mode, you may notice that the volume can jump from one
value to another pretty quickly, especially if you turn the volume knob very fast. Quick changes
in volume can create unpleasant distortion in the sound, and the module might not feel as
professional as it could be.

To correct this, we’re going to use a SmoothValue object, one of the many helpful tools that
you’ll find in Voltage’s Audio Processing library. You’ll find SmoothValue and many other tools
listed in the “Library” section of the Source Code Pane, as shown:
SmoothValue is a very useful tool. We call ​SetValue() ​to change the SmoothValue’s value, and
GetSmoothValue()​ to read its value. The SmoothValue class will then glide quickly from one
value to another. The glide is, by default, very fast (25 milliseconds), but it will ensure smooth
changes from one value to another.

To use SmoothValue, we’ll replace our volumeValue variable, which was a double, with a
SmoothValue object:

​ n the new SmoothValue object:


Next, we’ll change our Initialize() function to call ​SetValue() o

Likewise, we’ll modify the Notify() function to do the same thing:


And finally, we’ll modify our ProcessSample() function to call ​GetSmoothValue(​ ) on our
SmoothValue object:

With these changes made, we can select “Build and Run” in the Build menu and test our
module. No matter how quickly we move the Volume knob, volume adjustments will always be
smooth.

For our second improvement, let’s make the ​ProcessSample() f​ unction more efficient. There are
two key improvements we can make:

1. We can eliminate our inputSignal and outputSignal variables entirely.


2. We can avoid doing any of the processing if nothing is plugged into our output jack.

#2 is particularly interesting. If there’s no cable plugged into the Output jack, then there’s no
reason to perform any calculations at all in this module. We can save valuable CPU resources
by checking to see if anything is connected to the output jack, and skipping our signal
processing if there’s nothing there. The new code looks like this:
It’s always a good idea to write efficient ProcessSample() code. Remember, your module will be
sharing the CPU with dozens, or maybe hundreds, of other modules in a patch. There’s no
reason to use CPU resources if the module isn’t doing anything useful.

Functions like IsConnected() can be found in the “Library” section of the Source Code Pane,
under GUI Controls, VoltageAudioJack:

There are all sorts of useful functions available that you can call on various components. In fact,
you can even drag these functions from the library directly into your code. You can also hover
the cursor over any function name in the library to see a tooltip listing its return and argument
types.
Module Examples Included In Developer Kit
In the Sample Modules folder in the Voltage Developer Kit, you’ll find several useful demo
projects that will show you how to use various aspects of the software.

● LFO Demo Module​​ - This simple demo module shows how to use Voltage’s LFO class
to generate a square wave and triangle wave LFO signal. The module demonstrates
how to light an LED and how to use a knob to change the frequency of an oscillator.

● Filter Module ​- Demonstrates how to use the SaturatedAnalogFilter class to filter audio.
Features adjustable cutoff and resonance, and both a lowpass and highpass output.
This module also includes a modulation input with modulation amount knob, and
demonstrates how to read a CV signal and use it as a modulation source.

● Limiter Module​​ - This demo shows how to incorporate additional class files into a
Voltage Module project. The audio limiter DSP is contained in a class called
SignalLimiter in the file SignalLimiter.java, and has been added to the Addition Java
Files list in the module properties. The module features an adjustable limit level and an
optional volume boost button.

● GUI Update Timer​​ - This less-than-practical example module demonstrates how to use
a GUI timer to update graphical elements of a module. An LFO running at 1 Hz is used
to generate values from 0 to 1.0. A GUI timer fires every 100 milliseconds and sends a
GUI_Update_Timer message to the module’s Notify function. When this message is
received, we set all these controls to the LFO’s current value.

● VU Meter ​- A simple demo, illustrating how to use a GUI timer to update an Analog VU
Meter. We store the highest amplitude signal that comes into the input and use its value
to update the meter when the GUI timer fires.

● Oscilloscope ​- This project demonstrates how to use a Canvas object to draw custom
artwork from Java. Waveform data is stored in a buffer, and a GUI timer is used to draw
the waveform onto the Canvas control.

● Sound File Player​​ - This project demonstrates how to binary embed resources into a
module - in this case, an MP3 file - and how to use the VoltageSound class to decode
the MP3 to access the raw samples. When the module is switched to On, it will decode
the MP3 in a continuous loop. The VoltageSound class ensures the audio is decoded to
stereo audio at Voltage’s internal sample rate.
Module Controls

Properties Common to Nearly All Controls:

Name:​​ the name of the control as it will appear in Voltage Modular when it’s used in automation
or gets mapped to the Performance Module. As mentioned earlier, it’s also used when saving &
restoring the control’s state when your module gets saved in a Voltage Modular preset, so avoid
changing this name after you’ve published the module.

Variable Name:​​ the control’s Java variable name. It needs to meet Java standards for variable
names or your code won’t compile.

Left, Top, Width, and Height:​​ The control’s size and position. Some controls (notably audio
and MIDI jacks) don’t allow you to change their sizes.

Lock Size: ​If checked, you won’t be able to change the control’s size

Lock Position:​​ If checked, you won’t be able to move the control

Lock Aspect Ratio:​​ If checked, changing the control’s width will also automatically change its
height (and vice versa) to match the control’s skin’s original aspect ratio.

Skin:​​ The skin that governs the control’s appearance. Voltage Module Designer comes with a
variety of skins for most control types, and you can use the Skin Editor Dialog (accessible from
the Edit menu) to add skins of your own.

Notes:​​ A catch-all repository for any notes to yourself about the control. (These notes won’t be
part of the published module.)
Knobs

Java Class Name:​​ VoltageKnob

Notable APIs:

void SetValue( double newValue )​ : This will set the knob’s value. ​newValue​ should be within
the knob’s min and max ranges.

double GetValue() :​ Retrieves the knob’s current value.

Notifications:

A ​Knob_Changed​ notification will arrive in Notify() whenever a knob’s value changes:


Save/Restore State:​​ Voltage Modular automatically saves and restores knob states when
users save and load presets. When a preset loads, you’ll get a ​Knob_Changed​ notification at
startup (just after your Initialize() function has run) for each knob on your module.

Display Values in Percent: ​If checked, tooltips that display the knob’s value will multiply the
knob’s actual value by 100 and display it as a percentage (i.e., if the knob value is 0.5, the
tooltip will say “50%”). If unchecked, tooltips will display the knob’s actual value.
Tooltip Units:​​ If you enter text here, it’ll get appended (with an intervening space) to the knob’s
tooltip. If you set it to “volts”, for instance, and the knob’s value is 4.2, its tooltip will be “4.2
volts”.

Has Outer Dial:​​ if checked, the knob will have a dial ring around it that changes color to reflect
the knob’s current value.

Dial Skin:​​ the skin for said dial.

Ring Levels Start From Center:​​ If unchecked, dial ring colors will progress from min to max. If
checked, they’ll progress from center out.

Min, Max, and Default Values: ​the valid range of values for the knob and the default value for
a brand new knob. Max must be greater than Min and Default should be somewhere in the
range from Min to Max.

Num Discrete Steps:​​ Set this to a value of two or larger if you want your knob to have a finite
number of fixed settings instead of scrolling continuously. If your knob is a waveform selector
with sine, saw, and triangle settings, for instance, set ​Num Discrete Steps​ to 3, and the knob will
effectively act as a three-state switch and only allow you to switch between three possible
values. If Min Value is set to 0 and Max Value to 2 in this case, the knob’s value will always be
0, 1, or 2.

Start and End Angles:​​ These specify the angles to which the knob will be rotated when set to
its min and max values, respectively. Angles progress clockwise in degrees starting from zero at
12 o’clock (straight up).
Sliders

Sliders are basically knobs that have been uncurled and laid out in a line, so they share nearly
all their properties with knobs. They tend to get less love from module designers than knobs do
because they take up more space, but they’re awesome if you’ve got room for them - just ask
the designers of some of the vintage ARP synthesizers like the Odyssey and the Axxe, which
eschewed knobs for sliders entirely. Sliders are well suited for when you need to compare a
series of values at a glance, as happens with the track volumes on a mixer, or when you need a
series of controls to display a graph-like value, such as with an ADSR envelope.

Java Class Name:​​ VoltageSlider

Notable APIs:

void SetValue( double newValue )​ : This will set the slider’s value. ​newValue​ should be within
slider’s min and max ranges.

double GetValue() :​ Retrieves the slider’s current value.

Notifications:

A ​Slider_Changed​ notification will arrive in Notify whenever a slider’s value changes:


Save/Restore State:​​ Voltage Modular automatically saves and restores slider states when
users save and load presets. When a preset loads, you’ll get a ​Slider_Changed​ notification at
startup (but after your Initialize() function has run) for each slider on your module that’s set to
something other than its default value.
Vertical:​​ If checked, this will be a vertical slider (i.e., it’ll have a vertical track that you drag the
slider thumb up and down along to change the slider value). If unchecked, it’ll be a horizontal
slider.

See the ​Knobs​ section above for descriptions of several additional properties.
Buttons

“Button” controls are conventional push buttons that depress when you click on them and return
to their unpressed states when you stop clicking on them. If you want a button that stays down
after you stop clicking (and possibly one that’s part of a set of radio buttons), use the “Toggle
Button” control instead. While toggle buttons are great for showing state, regular buttons are
better options if you want to start an action - play or stop buttons, for instance.

Java Class Name:​​ VoltageButton

Notifications:

A ​Button_Changed​ notification will arrive in Notify() whenever a button gets pressed or


unpressed:

Save/Restore State:​​ Voltage Modular doesn’t save or restore the states of regular buttons
when users save presets. If your button has some custom state - maybe you’ve called
SetValue(1) to set it permanently down (though you probably want a toggle button instead if this
is the case) or you’re using button presses to cycle through a series of states - you’ll need to
save the state in internal variables and add code to GetStateInformation() and
SetStateInformation() to save/restore.
Auto Repeat: ​If checked, holding down the button will send out continuous button up & button
down notifications at a regular interval. We added this so that we could put up & down buttons
next to digital counter controls and continuously increment or decrement the counters by holding
one of the arrow buttons down (in a case like this, you’d increment the counter’s value each
time you received a button-down notification).

Has Image Overlay:​​ If checked, you can select an image that will display on top of the button,
such as a ‘play’ or ‘stop’ icon. The module designer comes with a variety of overlays (all the
overlays that are used in any of Cherry Audio’s modules, basically), and it will also add to the
“Image Overlay” dropdown any image files that you copy to the user overlays folder (requires
version 1.06 or higher). On Windows, this folder will be [my documents]\Voltage Module
Designer\Resources\Overlays . On the Mac, this will be Documents/Voltage Module
Designer/Resources/Overlays.

Image Overlay:​​ The dropdown that lets you select an image overlay for the button (only visible
if “Has Image Overlay” is checked.

Overlay Has Custom Rect:​​ By default, image and text overlays will occupy a bounding
rectangle the size of the button. Image overlays will get centered within that rectangle and text
overlays will get aligned within that rectangle according to the text orientation settings. If you
want to position the image or text in a particular location on top of the button, you can specify a
custom rectangle in which the overlay will display. For image overlays, this can also result in
reducing the size at which the overlay displays, depending on how much smaller than the
original button you make the overlay’s custom rectangle.

Overlay Left, Top, Width, and Height:​​ If you’ve enabled a custom rectangle for an overlay,
these settings will size and position that rectangle relative to the button’s upper left corner.

Preserve Overlay Image Aspect Ratio:​​ If the button has an image overlay and this option is
checked, the image overlay’s original aspect ratio will always be preserved when it gets resized
to fit on the button. If unchecked, the overlay image could get stretched or squashed.

Has Text Overlay:​​ If checked, you can add text to display on the button.

Overlay Text: ​ The text to display on the button when you’ve checked the “Has Text Overlay:
option.

Font, Font Height (pixels), Bold, Italic, and Text Color:​​ If you’ve checked the “Has Text
Overlay” option, these controls will let you edit the basic properties of your text overlay’s
appearance.
Horizontal and Vertical Orientation:​​ specifies alignment for the text in a text overlay, either
within a custom overlay rectangle, if you’ve specified one of those, or within the entire button if
you haven’t.
Toggle Buttons

Toggle buttons will stay clicked when you click on them, making them handy as the interfaces
for features that are always either on or off - the “loop” button on the module designer’s Test
Signals module, which turns loop mode on or off, is a typical example. You can also use the
“Group ID” field to group multiple toggle buttons as radio buttons, with the result that clicking on
any toggle button in the group will unclick all other toggle buttons in the group.

Java Class Name:​​ VoltageToggle

Notifications:

A ​Button_Changed​ notification will arrive in Notify() whenever a toggle button gets pressed or
unpressed:

Save/Restore State:​​ Voltage Modular will save and restore the states of any toggle buttons
that get saved in presets. When Voltage Modular loads a preset, it’ll send a ​Button_Changed
notification at module startup (but after your Initialize function has been called) for each of your
toggle buttons, with doubleValue = 1 (the button is down) or doubleValue = 0 (the button is up).
Most of the toggle button properties are shared with the regular button control (above), so we’ll
just list the ones that are unique to toggle buttons here:
Group ID: ​If you want this button to be part of a group of radio buttons, set the Group ID to a
number larger than zero. Clicking on any toggle button with a group ID > 0 will automatically
unclick any other toggle buttons with the same group ID.

Is Initially Toggled:​​ If checked, this button will be in its toggled state when your module gets
added to a Voltage Modular cabinet. (Though if you save a preset with the button untoggled, it’ll
still be untoggled when you reload that preset.)
Audio Input and Output Jacks

Java Class Name:​​ VoltageAudioJack

Notable APIs:

boolean IsConnected() :​ This function will return true if any cables are connected to this jack.

void SetValue( double newValue )​ : sets a new value for this jack (only applicable to output
jacks); if another module has an input jack connected to this jack, they can call GetValue() to
retrieve the value you’ve set. Audio jack GetValue and SetValue calls are the primary way that
modules communicate with each other. You’ll generally want to check the values of any input
jacks and set the values of any output jacks (at least if they’ve changed) in every call to
ProcessSample().

double GetValue()​ : retrieves the current value arriving at the jack (only applicable to input
jacks).

Notifications:

A ​Jack_Connected​ notification will arrive in Notify() whenever a new cable gets connected to a
jack, and a ​Jack_Disconnected​ notification will arrive when all cables have been disconnected
from a jack:
Save/Restore State:​​ When loading a preset, Voltage Modular will reconnect any cables that
were attached to a jack when the preset got saved.
VU Meters

VU Meters have a valid range from 0 to 1, but you can set the value to be interpreted in either
linear or logarithmic fashion.

Java Class Name:​​ VoltageVUMeter

Notable APIs:

void SetLinearMode( boolean linMode )​ : Set this to true for the meter to operate in linear mode,
false for it to behave logarithmically.

void SetValue( double newValue )​ : Sets the meter’s value, valid range is from 0 to 1.

double GetValue() :​ Retrieves the meter’s current value.

Save/Restore State:​​ Voltage Modular doesn’t save state for VU meters.


Analog VU Meters

Analog VU Meters start at 0 and will redline at 1, with the needle maxing at 2.

Java Class Name:​​ VoltageAnalogVUMeter

Notable APIs:

void SetValue( double newValue )​ : Sets the meter’s value.

double GetValue() :​ Retrieves the meter’s current value.

Save/Restore State:​​ Voltage Modular doesn’t save state for analog VU meters.
LEDs

Java Class Name:​​ VoltageLED

Notable APIs:

void SetValue( double value )​ : This sets the LED “brightness” (actually a state image), with a
valid range from 0 to 1. If it’s a simple on/off LED skin, it’ll be in the ‘off’ state if the value is less
than 0.4 and in the ‘on’ state otherwise. If the LED skin has more than two states, the state to
display will be the number of states multiplied by the LED value and then rounded off to an
integer, which will be used as a zero-based index into the array of state images. Here’s a
screenshot of a module showing the “Red” LED skin, which only has on and off states, and the
“Blue and Red” skin, which has off, red, and blue states, with each skin at various values from 0
to 1:
double GetValue() :​ This returns the LED’s current value.

void SetMomentaryBlink( int milsToBlink )​ : This turns the LED on for ​milsToBlink​ milliseconds,
then turns it off again.

void SetBlinkEvery( int blinkIntervalMils, int blinkOnMils )​ : Makes the LED blink. The blink cycle
will be ​blinkIntervalMils​ milliseconds long, and the LED will be lit for ​blinkOnMils​ milliseconds of
the cycle. The button-lit intensity will be whatever the value was in your last call to SetValue(),
so call SetValue() just before calling SetBlinkEvery() to make sure it lights up during the blink-on
part of the cycle.

void StopBlinking() :​ Stops the LED from blinking.

Save/Restore State:​​ Voltage Modular doesn’t save state for LEDs.


MIDI Input and Output Jacks

Java Class Name:​​ VoltageMidiJack

Notifications:

A ​Jack_Connected​ notification will arrive in Notify() whenever a new cable gets connected to a
jack, and a ​Jack_Disconnected​ notification will arrive when all cables have been disconnected
from a jack:

Save/Restore State:​​ When loading a preset, Voltage Modular will reconnect any cables that
were attached to a jack when the preset got saved.
Digital Counters

Java Class Name:​​ VoltageDigitalCounter

Notable APIs:

void SetValue( double newValue )​ ​: This sets the number (truncated to an integer) displayed in
the counter. If you set it to a number larger than the counter can hold, it’ll display all 9’s.

double GetValue()​ : returns the current value of the counter.

void SetBarsForDigit( int digitIndex, EnumSet<Flags> flags )​ : This lets you turn off and on
individual segments of a digit so you can emulate things other than numbers. For instance,
here’s the code that Voltage Modular’s MIDI Out module uses to make the MIDI channel
selector say “All”:

digitIndex​ starts from 0 at the rightmost digit and increases from right to left.

To use ​SetBarsForDigit,​ you’ll need to either use the fully qualified name for EnumSet or import
java.util.EnumSet:
void ClearBarsForDigit( int digit )​ : This clears the custom bar art you set via SetBarsForDigit for
a given digit.

Save/Restore State:​​ Voltage Modular doesn’t save state for digital counters.
Canvases

A canvas is a control that, in its default form, doesn’t do anything at all. It’s up to you to paint it
and handle any mouse interactions that occur. Use a canvas when you want to draw something
(a graph or waveform, for instance), create a custom control, or just generally do something that
the module designer’s native controls aren’t capable of. Voltage Modular’s Oscilloscope module,
to cite one example, uses a canvas control to draw a graph of the input signal.

Java Class Name:​​ VoltageCanvas

If you’re using a canvas, you’ll want to handle the canvas notifications that arrive in the ​Notify
function. At least some of these will be important to you:

Here’s a simple example of a function that clears a canvas to a solid color - you’d call this
function from your Canvas_Painting handler (and ONLY from your Canvas_Painting handler):
Though the setRenderingHint call isn’t necessary here, it gives us a chance to mention that if
the things you’re drawing in your canvas seem aliased and pixelated, inserting the
setRenderingHint call listed above is likely to help.

The Graphics2D object in the above code is native to Java, rather than Cherry Audio; you can
find more information about it at
https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html​ .

For any of the mouse-related notifications shown above, the x and y parameters to Notify() will
contain the mouse’s current position relative to your canvas’s top left corner.

Save/Restore State:​​ Voltage Modular doesn’t save state for canvases. Like everything else to
do with these controls, it’s a roll-your-own affair. Add your own code to save & load data in
GetStateInformation & SetStateInformation if you need to store data with your canvas.
Switches

Java Class Name:​​ VoltageSwitch

Notable APIs:

void SetValue( double value ) :​ Sets the switch’s position. For a 2-stage switch, the valid values
are 0 and 1; for a 3-stage switch, the valid values are 0, 1, and 2, etc.

double GetValue() :​ Returns the switch’s current position.

Notifications:​​ A ​Switch_Changed​ notification will arrive in Notify() whenever a switch’s value


changes:

Save/Restore State:​​ Voltage Modular will save & restore the states of switches when users
save & load presets. When a preset loads, you’ll receive ​Switch_Changed​ notifications at
module startup (just after your Initialize() function has run) for each of the switches on your
module that aren’t set to their default states.
Images

The image control displays a still image on your module. If you’re displaying a raster-based
image (JPG, PNG, etc.), we recommend you use an image with double the dimensions of your
display size so that it won’t look pixelated at higher zoom levels - so if you want an image to
display at width of 100 and height of 150, for instance, use a 200 x 300 image as the source.
The API will likely change to allow you to provide separate low and high-resolution images at
some point.

Java Class Name:​​ VoltageImage

Notable APIs:​​ Both images and animations use the VoltageImage class, so you could
technically use VoltageImage’s APIs to write code to add multiple frames and animate them, but
if you want to do that, it would be much easier to just use an Animation control instead.
Animations

Java Class Name:​​ VoltageImage

Notable APIs​​:

Animate(boolean bLoop) :​ Starts your animation playing. Only necessary if you don’t have the
“Auto Play” option checked.

void StartAnimation( AnimationMode animMode, boolean bLoopAnimation, int milsPerFrame, int


startImage )​ : Also starts your animation playing.

SetAnimateMode( AnimationMode animMode)​ : Sets the animation direction. Valid values for
animMode​ are ​Forward,​ ​Backward,​ ​ForwardAndBack,​ and ​BackAndForth.​

int GetNumberOfFrames() :​ Returns the number of frames (images) in your animation.

void SetCurrentFrame(int curFrame) :​ Sets the current foreground frame for the animation.
curFrame is a zero-based index into the array of total frames in the animation.

void SetCurrentImage( String resourceName )​ : Also sets the current foreground frame, but
takes a resource name instead of a frame index.

int GetCurrentFrame() :​ Returns the index of the current foreground frame.

void Clear()​ : Removes all frames from the animation.

void SetAnimationSpeed( int milsPerFrame, boolean bReset )​ : Sets the animation speed, in
milliseconds per frame.

void AddNewImage( String resourceName )​ : Adds a new image to the animation.

void AddImageFromMemory( byte[] data )​ : Adds a new image to the animation from a memory
buffer. The buffer should be the contents of an image file (PNG, JPG, etc.) rather than a table of
pixels.
Frame Rate:​​ The rate at which the animation will animate. Note that this is in milliseconds/frame
rather than the conventional frames per second.

Auto Play:​​ If checked, the animation will start playing as soon as your module gets instantiated.
If not, you’ll have to start animation yourself by calling ​StartAnimation() ​or​ Animate()​.
Text Labels

Java Class Name:​​ VoltageLabel

Notable APIs:

void SetText( String newText ) :​ Sets the text for the label.

String GetText() ​: Returns the label’s text.

void SetColor( Color color )​ : Sets the text color. ​color​ is a Java Color object and can include an
alpha value.

void SetBkColor( Color color )​ : Sets the background color for the label control (by default, it has
an alpha value of zero).

void SetBorderColor( Color color )​ : Sets the color of the control’s border (alpha = zero by
default).

void SetBorderSize( int pixSize )​ : Sets the width of the border, in pxiels.

void SetFont( String typeface, int fontSize, boolean bBold, boolean bItalic )​ : Sets various
properties of the control’s font. ​fontSize​ is height in pixels.

void SetJustificationFlags( Justification justificationFlag )​ : Sets the text’s horizontal and vertical
justification.

void SetMultiLineEdit( boolean bMultiLineEdit )​ : Set to true to make this a multi-line text control.

void SetHorizontalScale( double scale )​ : Allows you to change the widths of the characters in
the text control. 1.0 = normal, 2.0 = double width, 0.5 = half width, etc.

Save/Restore State:​​ Voltage Modular doesn’t save or restore state information for text labels
with presets.
Text:​​ The text that will be displayed in the label.

Font, Font Height, Bold, and Italic:​​ These set basic font properties for the text. The ​Font
dropdown will only show typefaces that are preinstalled on both Windows and Mac computers..

Horizontal and Vertical Orientation:​​ How the text will be aligned within its bounding rectangle.
Multi Line:​​ if checked, the text can be more than one line tall.

Text Color:​​ the text color and opacity.

Background Color:​​ color and opacity for the background of the text label’s bounding rectangle.

Border Color:​​ color and opacity of a border drawn around the text label’s bounding rectangle.

Border Width​​: width, in pixels, of the text label’s border. Only applicable if the ​border color
property specifies a non-zero opacity.
Editable Text Labels

Editable text labels are nearly identical to regular text labels, with the important exception that
users can edit the text in them. All the knob and button labels on Voltage Modular’s
Performance Module are editable text labels, for instance. Voltage Modular will automatically
handle save/restore when user change an editable text label’s text and then saves a preset.

Java Class Name:​​ VoltageLabel

Notable APIs:

void SetEditTextColor( Color color )​ : Sets the text color to use during edit mode.

void SetEditBackColor( Color color )​ : Sets the color to use for the control’s background during
edit mode.

void SetEditOutlineColor( Color color )​ : Sets the color to use for the control’s border during edit
mode.

See also the APIs section for non-editable text labels, above.

Notifications:​​ A ​Label_Changed​ notification will arrive in Notify() whenever a user has changed
the contents of an editable text label:

Save/Restore State:​​ Voltage Modular will save the text in an editable label and restore it when
users save and restore presets.
Start Editing On:​​ This lets you specify whether single clicking or double clicking on the control
initiates editing mode.
Edit Mode Text, Background, and Border Colors:​​ Colors used when the control enters
editing mode.

See the ​Text Label ​control above for descriptions of the other properties.
Library Classes
Module Designer Features

Using the Debugger:

To test your module with the debugger, choose the “Debug” option from the “Build” menu. The
module designer will build your module and, assuming no compile errors, launch a child process
with a cabinet containing your module and the Test Signals module:

The Test Signals Module contains a variety of inputs and outputs to help you test your module.
It includes five sections, from top to bottom:

From Host:​​ A variety of CV and MIDI inputs from the MIDI devices you’ve chosen in the
module designer’s Preferences dialog.
File Playback:​​ If you specify the “File” option from the Sound Source section (just below this
one), you can use this section to load an audio file (MP3, WAV, OGG, FLAC, or AIFF) and use it
as a sound source for processing in your module.

Sound Source:​​ This lets you choose an audio source for sending to the module via the “Test
Signal Outputs” section below. You can use a square wave, a sine wave, an audio file, or an
external input such as a microphone (see the module designer’s Preferences dialog for
available inputs). If you select the sine or square waves, the “Osc Freq” knob sets the
waveform’s frequency.

Test Signal Outputs:​​ This section contains mono and stereo output jacks for sending your
chosen sound source to your module.

Audio Ret To Host:​​ Hook the output from your module back to these input jacks; they’ll get
routed to the audio outputs (your speakers, probably) specified in the module designer’s
Preferences dialog.

The Child Process’s Menu

The menu in the debugger child process lets you test your module’s undo/redo capabilities (via
the “Edit” menu) and how it looks at varying zoom levels (via the “View” menu). The “Add
Modules” menu allows you to add other Voltage modules to your test cabinet:
The module designer will remember your cable connections, extra modules, and control settings
from session to session. If you need to clear them, select the “Clear Test/Debug Mode Settings”
option from the module designer’s “Build” menu.

Note that if you hit a breakpoint or otherwise pause debug execution, it’ll halt execution of the
entire debugger child process, including the interface thread, so the ​Edit/View/Add Modules
menus won’t be accessible when execution is paused.

When the debugger launches, the title bar for the output pane (the pane at the bottom of the
module designer in the default setup) will sprout a series of tabs along its left edge:

and a row of buttons along the right:

When execution of your module has paused due to hitting a breakpoint, pausing, etc., the
buttons allow you to resume execution in various ways:
resume:​​ resumes execution unconditionally, either until another breakpoint is hit or you pause
execution via the “Pause” option on the Debug menu.

step in:​​ If the line of code where execution is paused includes a function call, step into the
function. If it doesn’t, skip to the next line of code.

step over:​​ execute the current line of code without stepping into any function calls it contains

step out:​​ execute code until execution has exited the current function.

The Row of Tabs:

The “Output” tab shows the normal contents of the Output pane, including the results of any Log
statements in your code:

“Oscillator”: This tab will be labeled with your module’s variable name and will show the values
of all the variables in your module:
The first column shows variable names, the second column their values, and the third column
their types. Most non-primitive types will have empty value columns; click the little expansion
arrows to the left of their names to show all their child members, which will have filled-in value
columns if they’re not themselves complex types.

The “Locals” tab has the same layout as the Module tab, but shows values for all the local
variables at the current point of execution:

The “Threads” tab shows all the active threads and the call stacks for each, with threads in the
left column and the selected thread’s call stack, if available, in the right column:
Click on a stack frame and then switch to the Locals tab to see local values for that stack frame,
if any are available.

The Module, Locals, and Threads tabs will be disabled unless debug execution is paused.

Breakpoints:​​ To set a breakpoint at a particular line of code, either click in the line’s left margin,
right-click and select the “Toggle Breakpoint” option, or click the toggle-breakpoint hotkey (F9 on
Windows, Command-Backslash on Mac). A red circle will appear in the left margin to indicate
that the line has a breakpoint:

Use the same process to remove breakpoints. There’s also a “Remove All Breakpoints” option
on the Debug menu.

When execution stops at a breakpoint, the line will be highlighted in the code editor and a yellow
arrow will appear in the margin:
The Module Background Dialog

Use Solid Color:​​ Check this item to use a color rather than an image for your module’s
background. The “Choose Color” button will launch a color-chooser dialog. This option won’t
actually result in a background rendered with a single color; instead, it’ll have a slight gradient
that darkens the bottom and a thin black border, both so that it will more closely match the
appearance of Cherry Audio’s own modules.

Use Image:​​ Choose this item to use images for your module’s background. You should add
two versions of your background image, one at normal resolution (360 pixels tall) and one at
high resolution (720 pixels tall and twice the module’s original width). The high-resolution
version will be used on retina displays and when the zoom level is > 100%. Modules without
hi-res backgrounds tend to look fuzzy at high zoom. If your source image is an SVG file with no
embedded bitmaps, you only need to specify one background image.

Add Screws:​​ This will add screws to the corners of your module to keep it from falling out of
the cabinet. This is optional - if your module is magnetized or has wads of gum on the back or
something else equally effective, you can leave this unchecked.
The Skin Editor Dialog

The Skin Editor Dialog lets you create your own skins for the module designer’s various control
types. Once you’ve created a skin and saved it, it’ll appear in the “Skin” dropdown for that
control type along with all the presupplied skin types.

We highly recommend that you use SVG files for your skins so that they’ll scale to any size
without aliasing.

New Skin​, ​Open Skin,​ and ​Save Skin​ Buttons:​​ These allow you to save your skins and open
existing skin projects. On Windows, your skins will get saved in Documents\Voltage Module
Designer\Resources\Skins, On Mac (version 1.06 and higher) they’ll get saved in
Documents/Voltage Module Designer/Resources/Skins. The skin editor will copy any source
image files it needs to the save folder, so you don’t need to keep copies of them in their original
locations in order for the skin to keep working.

Control Value:​​ This allows you to emulate SetValue() calls to LED and VU meter skins so you
can see how your skin looks throughout its range. This control will also work on knob and slider
skins, though you can just click on the knobs and sliders themselves, and will even work on
button and switch skins in the unlikely event you want to use a slider to turn them on and off.
For other kinds of control skins, it’ll have no meaningful effect (technically, you can use it to
count from 0 to 1 on a digital counter).

Skin Type:​​ The module designer currently supports user skins for audio and MIDI jacks,
regular and toggle buttons, knobs, horizontal and vertical sliders, digital counters, LEDs,
switches, and VU meters.

Skin Name: ​ This is the name your skin will have in the property panel’s “Skins” dropdown.

Default Width and Height:​​ When you set a control to use this skin, the control will
automatically get reset to this size if you don’t have its “Lock Size” option set.

STANDARD ART STATES:

Normal:​​ used when a given control is enabled and the user isn’t interacting with it in any way
(clicking on it or hovering the mouse over it being the most common sorts of interactions).

Hover:​​ used when the mouse is hovering over a given control.

Disabled:​​ used when the control is disabled. The disabled state is currently only used for audio
and MIDI jacks, but will probably get added for other kinds of controls in an upcoming release.
Skin Editor - Audio Jacks

Normal:​​ the image to use when the jack is enabled and the user isn’t currently interacting with
it.

Hover:​​ the image to use when the mouse is hovering over the jack.

Disabled:​​ the image to use when the jack is disabled. When a user is dragging a cable from an
input jack, all other input jacks will be drawn in their disabled states, and likewise for output
jacks when a user is dragging a cable from an output jack.
Skin Editor - Buttons

Normal:​​ the image to use when the button is enabled and the user isn’t interacting with it.

Hover:​​ the image to use when the mouse is hovering over the button.

Pushed:​​ the image to use when the user has clicked on the button.

Disabled:​​ used when the button is disabled. There’s currently no interface for disabling
buttons, but this will probably get added at some point.
Skin Editor - Digital Counters

Back:​​ the image to use for the counter’s background.

Numbers, 0 - 9 and Off:​​ the images to use for the various integers.

Lines:​​ the images to use for drawing individual line segments (see the SetBarsForDigit() API,
discussed in the controls|digital counters section above).
Skin Editor - Horizontal Sliders

Back:​​ art to use for the slider’s background.

Filled:​​ art to use for portions of the slider background that are to the left of the slider thumb, for
cases in which you want a slider with a progress-bar-style appearance. (See the file-playback
slider on the Test Signals module for an example.)

Handle:​​ art to use for the slider thumb.


Skin Editor - Knobs

Back:​​ Art to use for the knob’s background, which will remain stationary.

Top:​​ Art to use for the knob’s top, which will rotate as the knob’s value changes.
Skin Editor - LEDs

Off:​​ art to use when the LED is off.

On:​​ art to use when the LED is lit up.

Extra States:​​ These controls allow you to add art for intermediate states between off and on,
such as for an LED that glows at varying intensities.
Skin Editor - MIDI Jacks

Normal:​​ image to use when the MIDI jack is enabled and the user isn’t interacting with it.

Hover:​​ image to use when the mouse is hovering over the jack.

Disabled:​​ image to use when the jack is disabled (when the user is dragging a cable from a
MIDI input jack, all other MIDI input jacks will be disabled; likewise with MIDI output jacks when
user is dragging a cable from a MIDI output jack).

MIDI jacks have a fixed size of 57 x 57 pixels.


Skin Editor - Switches

Switch Direction:​​ determines whether this will be a vertical or horizontal switch.

States:​​ Lets you specify how many states the switch has - two for a simple on/off switch, etc.

state0 - n:​​ The images to use for each of the switch states.
Skin Editor - Toggle Buttons

Up and Down states:​​ art to display when the button is in its off and on states, respectively.
Note that the ‘pushed’ states are created by buttons in the opposite state - i.e., when the button
is in its down state and you click on it, it’ll switch to the up-state pushed art, and when the button
is in its up state and you click on it, it’ll switch to the down-state pushed art.
Skin Editor - Vertical Sliders

Back:​​ art to use for the slider’s background.

Filled:​​ art to use for portions of the slider background that are to the left of the slider thumb, for
cases in which you want a slider with a progress-bar-style appearance.

Handle:​​ art to use for the slider thumb.


Skin Editor - VU Meters (Analog)

Background Image:​​ the image to use for the meter background. This should include
everything but the needle.

Needle Color:​​ color to use for the meter’s needle.

Needle Size:​​ width of the needle, in pixels.


Skin Editor - VU Meters (Vertical)

Base Image:​​ the background image for the meter.

Signal Image:​​ the foreground image showing the amount of signal preset. At a control value of
0, the signal image will be completely invisible. At a control value of 1, the signal image will
completely cover the background image.
Assorted Shortcuts and Hotkeys

In the Design Pane:

Alt-drag​​ any control to create a duplicate of it (and any other selected controls as well); hold
down the shift key during this process to limit the initial drag to either the horizontal or vertical
directions.

Hold down the ​shift key while dragging​​ ​any control​​ to restrict its movement to either the
horizontal or vertical directions.

Select a control and ​press the up/down/left/right arrow keys​​ to move the control 1 pixel in
those directions; hold down the ​shift key while pressing​​ ​the arrow keys​​ to move the control
by 10 pixels per click instead. If you have the grid visible and horizontal or vertical snap-to-grid
options selected (right-click or, on the Mac, control click, on the module background to set grid
options), the arrow keys will move the control by units of the grid size (i.e., if the grid size is set
to 20 pixels, controls will move 20 pixels per key press).

Select a control, hold down the ​control key, and press the left/right/up/down arrow keys​​ to
resize the control by one pixel per key press - right and down arrows to make it larger, left and
up arrows to make it smaller. This won’t resize the control if its size is locked or if it’s a control
for which resizing isn’t allowed, such as audio and MIDI jacks.

Select a control and press the ​tab key​​ to make the next control in the z-order the selected
foreground control. ​Shift-tab​​ cycles in the opposite direction.

Hold down the ​control key while clicking on a control ​to select it without deselecting any
other selected controls.

Click on the module background and drag​​ to generate a bounding rectangle; after releasing
the mouse button, any controls partially or fully within that rectangle will be selected. ​Hold down
the control key while dragging​​ to select controls inside the bounding rectangle without
deselecting controls outside the rectangle.

Click on a control and ​press the “Delete” key​​ (on the Mac, the Delete key on the numeric
keypad) to delete the control.
Right-click or control-click (Mac) on a control​​ for a popup menu that lets you bring the
selected control to the front or back of the z-order, lock or unlock the control’s position or size,
duplicate or delete the control, and link selected controls so that selecting one will always select
the other as well.

Right-click or control-click (Mac) on the module background​​ for a popup menu that lets you
lock or unlock the sizes or positions of all controls on the module at once; edit grid visibility, size,
and snap-to-grid settings; or select all the controls on the module.

In the Code Editor:

F9 (Windows) or command-backslash (Mac)​​ to toggle a breakpoint at the current line of code

Ctrl-F (Windows) or Command-F (Mac) ​to open the search interface

F3 (Windows)​​ ​or Command-G (Mac)​​ to select the next search result; ​Shift-F3 (Windows) or
Command-Shift G (Mac)​​ to select the previous one. Only applicable when the search interface
is open.

Ctrl-C (Windows) or Command-C (Mac)​​ to copy the currently selected text

Ctrl-V (Windows) or Command-V (Mac)​​ to paste text from the clipboard

Ctrl-X (Windows) or Command-X (Mac)​​ to cut the currently selected text

Ctrl-Z (Windows) or Command-Z (Mac)​​ to undo text editing; ​Ctrl-Y (Windows) or


Command-Y (Mac)​​ to redo.

Tab (WIndows) or Command-] (Mac)​​ to indent selected text if the current selection
encompasses multiple lines; ​Shift-Tab (Windows) or Command-[ (Mac)​​ to unindent in the
same circumstances

Ctrl-A (Windows) or Command-A (Mac) ​to select all text

Home​​ key to go to the beginning of a line; ​End​​ key to go to the end of it

Ctrl-Home (Windows) or Command-Home (Mac)​​ to go to the top of the document; ​Ctrl-End


(Windows) or Command-End (Mac)​​ to go to the end of it.

You might also like