RayTone Documentation
01. Menu Panels
You can open the settings menu panel using the gear button in the top-right corner of the screen.
Volume: Global audio volume
BPM: Beats-per-minute (BPM) for sequencers
Resolution: Graphics resolution (low, mid, high, ultra)
Post Processing: Enable/disable post processing
Load: Load a project
Save: Save a project
Rescan: Rescan MIDI devices + ChucK source directory
Source Directory: Open the source directory in file browser. You can use this to locate template scripts for Voice unit and VFX unit.
Dual Display: Display a full-screen view of the canvas if there is a second monitor available.
02. Mouse + Shortcut Keys
Mouse Commands 🖱️
Left-click: Select and move a unit
Ctrl/Cmd/Shift + left-click: Select and move multiple units | Use selection box tool
Right-click + drag: Shift camera
Scroll wheel: Zoom in/out
General Shortcut Keys ⌨️
~: Open / close console
Space: Re-sync sequencer steps
Delete: Destroy selected units
Escape: Deselect selected units / Exit performance mode
N: Spawn a number box
E: Enter edit mode of selected unit (if applicable)
M: Open submenu of the unit in edit mode (if applicable)
Arrow keys: Shift camera
+/-: Zoom in/out
Menu Shortcut Keys ⌨️
C: Control Selection Panel
V: Voice Selection Panel
G: Graphics Selection Panel
Ctrl/Cmd Shortcut Keys ⌨️
Ctrl/Cmd + A: Select all units
Ctrl/Cmd + C: Copy selected units
Ctrl/Cmd + X: Cut selected units
Ctrl/Cmd + V: Paste copied units
Ctrl/Cmd + Z: Undo
Ctrl/Cmd + Y: Redo
Ctrl/Cmd + S: Save a project
Ctrl/Cmd + P: Load a project
Ctrl/Cmd + T: Toggle "performance" mode
Ctrl/Cmd + R: Randomize all steps in sequencer edit mode
03. Unit References
Below is a list of available units in RayTone by category. In this documentation, the following symbols are used to represent the unit socket types.
➡️: control-rate inlet
↩️: control-rate outlet
➡️🔊: audio-rate input
↩️🔊: audio-rate output
Additionally, the following symbol is used if a unit has a submenu panel for editing additional properties. You can either double click on the unit or click on the edit key on the right side of the screen to enter the edit mode.
🎚️: unit submenu panel
Control Units
GUI
Monitor
A GUI unit for monitoring a number every frame.
➡️: value to monitor
Number
A GUI unit for setting a constant number. Click on the box to edit the value.
↩️: value
Sequencer
A circular step sequencer that outputs a value every step. Double click or click on the edit key on the right side of the screen to enter the edit mode. Use left and right arrow keys to select a step to edit. Use up and down arrow keys to edit the step value.
Ctrl/Cmd + up or down key to move all steps.
Shift + up or down key to move in increments of 10.
Ctrl/Cmd + R to randomize all steps within the range specified in submenu.
↩️: step value
🎚️: submenu panel
Step: number of steps. Change this to experiment with polymeters.
Clock: clock division to control the sequencer tempo. Change this to experiment with polyrhythms. By default, the slider changes the clock division by powers of 2. Alternatively, click on the number to manually specify the value.
min: minimum step value
max: maximum step value
delta: step value increment
Slider
A GUI slider.
↩️: value between 0 and 1
Toggle
A GUI toggle button.
↩️: 0 or 1 (lit).
Trigger
A GUI button. Use this to manually send a trigger.
↩️: trigger on click
Math
Absolute
➡️: value
↩️: absolute value of inlet1
Add
➡️: value1
➡️: value2
↩️: inlet1 + inlet2
Ceil
➡️: value
↩️: nearest integer equal to or higher than value of inlet1
Clamp
➡️: value
➡️: min
➡️: max
↩️: clamped value
Cos
➡️: radian angle
↩️: cos(inlet1)
Divide
➡️: numerator
➡️: denominator
↩️: inlet1 / inlet2. 0 if inlet2 = 0.
Equal
➡️: value1
➡️: value2
↩️: 1 if value1=value2. 0 if not.
Floor
➡️: value
↩️: nearest integer equal to or lower than value of inlet1
Ftom
➡️: frequency value
↩️: inlet1 converted to midi note number
Greater
➡️: value1
➡️: value2
↩️: 1 if value1 > value2. 0 if not.
Lerp
➡️: from
➡️: to
➡️: weight
↩️: clamped linear interpolation between From and To values using weight (0-1).
Log
➡️: value
➡️: log base
↩️: loginlet2(inlet1)
Max
➡️: value1
➡️: value2
↩️: maximum value between inlet1 and inlet2
Min
➡️: value1
➡️: value2
↩️: minimum value between inlet1 and inlet2
Mtof
➡️: midi note number
↩️: inlet1 converted to frequency
Multiply
➡️: value1
➡️: value2
↩️: inlet1 * inlet2
Pi
↩️: π ≈ 3.14159...
Power
➡️: value
➡️: exponent
↩️: inlet1 raised to the power of inlet2
Round
➡️: value
↩️: inlet1 rounded to the nearest integer
Sin
➡️: radian angle
↩️: sin(inlet1)
Sqrt
➡️: value
↩️: square root of inlet1
Subtract
➡️: value1
➡️: value2
↩️: value1 - value2
Time
Average
Take the exponential moving average of the inlet value. Use this unit to smoothly interpolate between discrete values.
➡️: value
➡️: average time (ms): default is 500ms
↩️: inlet1 averaged over inlet2.
BPM
Set and get current global BPM. Use this unit in a project to explicitly set its BPM when loaded.
➡️: new BPM
↩️: current BPM
Day
↩️: current day of the month
Elapsed
Return the elapsed time in seconds since RayTone application started OR the last reset time. Use this unit to obtain a value that linearly increases over time.
➡️: reset (trigger)
↩️: elapsed time
Hour
↩️: current hour in 24-hour format
Millisecond
↩️: current millisecond
Minute
↩️: current minute
Month
↩️: current month
Second
↩️: current second
Year
↩️: current year
Utilities
KeyInput
Monitor a computer key press either continuously or as one-shot. This unit is useful for updating canvas parameters (Voice, VFX, etc.) in live performance and debugging settings.
↩️: key status (0 or 1).
🎚️: submenu panel
Key: computer key to monitor; default is 'A'
Continuous: whether to treat a key press as held/released (lit) or as a single click.
MIDI_CC_R
Receive MIDI CC value at specified channel and CC number. Use this unit to communicate with audio and graphics hardware.
↩️: Incoming MIDI CC value.
🎚️: submenu panel
MIDI channel: default is 1
CC Number: default is 60
MIDI_CC_S
Send MIDI CC value at specified channel and CC number. Use this unit to communicate with audio and graphics hardware.
➡️: CC value to send
🎚️: submenu panel
MIDI Channel: default is 1
CC Number: default is 60
OSC_R
Receive OSC floating point value at specified port and OSC address. Use this unit to communicate with other audio and graphics software.
↩️: OSC value.
🎚️: submenu panel
port: default is 5001
OSC address: default is /raytone/osc-r
OSC_S
Send OSC floating point value at specified IP address, port and OSC address. Use this unit to communicate with other audio and graphics software.
➡️: value to send via OSC every frame.
🎚️: submenu panel
IP address: default is localhost 127.0.0.1
port: default is 5000
OSC address: default is /raytone/osc-s
Rand
➡️: trigger
↩️: random value between 0 and 1 on trigger
Select
A "switch" unit that returns the value at the specified "key" index (starting with 0). This unit is useful for creating scene states, such as which sequencer and texture are actively used.
➡️: 0
➡️: 1
➡️: 2
➡️: 3
➡️: 4
➡️: 5
➡️: 6
➡️: 7
➡️: key
↩️: value at the key index
Tick
↩️: trigger every step. This is equivalent to a sequencer with all steps at 1 with clock division=1.
Volume
Set and get current global volume. Use this unit in a project to explicitly set its volume when loaded.
➡️: new volume
↩️: current volume
Voice Units
🎚️: every voice unit has a submenu panel
volume: local volume to DAC. Note that this value is not effective if the unit is connected to another voice unit since only the second unit would have audio output to DAC.
spatialize: turn on/off panning. When turned on, the placement of the voice unit relative to the camera pans the output signal. Turn this off for sounds that you don't want to pan.
01.Sources
Bow
➡️: freq
➡️: bow pressure
➡️: bow position
➡️: vibrato frequency
➡️: vibrato depth
↩️🔊: A digital waveguide bowed string model. https://chuck.stanford.edu/doc/reference/ugens-stk.html#Bowed
Bow_Q
Same as Bow, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
FM
➡️: carrier frequency
➡️: modulator frequency ratio to inlet1
➡️: FM index of modulation
↩️🔊: 2-operator frequency modulation synthesis.
FM_Q
Same as FM, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
Noise
↩️🔊: white nosie
OSC
➡️: frequency
↩️🔊: sinusoidal oscillator
OSC_Q
Same as OSC, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
Pulse
➡️: frequency
➡️: duty cycle width
↩️🔊: pulse width oscillator
Pulse_Q
Same as Pulse, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
Sampler
➡️: trigger
➡️: rate (1 if cable not connected)
↩️🔊: .wav sample playback sampler
Saw
➡️: freq
➡️: whether sawtooth wave is to fall (0) or rise (1)
↩️🔊: sawtooth oscillator
Saw_Q
Same as Saw, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
Square
➡️: frequency
↩️🔊: square wave oscillator
Square_Q
Same as Square, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
Tri
➡️: frequency
➡️: width of triangle wave (ratio of rise time to fall time)
↩️🔊: triangle wave oscillator
Tri_Q
Same as Tri, except that all inlets are read once a step. Use this version for accurate timing unbounded by frame-rate.
02.Effects
BPF
➡️🔊: signal in
➡️: cutoff frequency
➡️: filter Q
↩️🔊: input signal => bandpass filter
Chorus
➡️🔊: signal in
➡️: chorus frequency
➡️: chorus depth
↩️🔊: input signal => chorus
Echo
➡️🔊: signal in
➡️: delay time (ms)
➡️: feedback (0-1)
↩️🔊: input signal => feedback delay
HPF
➡️🔊: signal in
➡️: cutoff frequency
↩️🔊: input signal => highpass filter
LPF
➡️🔊: signal in
➡️: cutoff frequency
↩️🔊: input signal => lowpass filter
Pitchshift
➡️🔊: signal in
➡️: degree of pitch shifting
↩️🔊: input signal => pitchshifter
Reverb
➡️🔊: signal in
➡️: dry/off (0-1). 0.03 if cable is not connected.
↩️🔊: input signal => beloved John Chowning reverb
03.Gain
Add4
➡️🔊: signal1 in
➡️🔊: signal2 in
➡️🔊: signal3 in
➡️🔊: signal4 in
↩️🔊: input1 + input2 + input3 + input4
Env
➡️🔊: signal in
➡️: trigger (open envelope)
➡️: attack (ms)
➡️: release (ms)
↩️🔊: input signal => AR enveloped VCA. Use this unit to shape the envelope of a signal with attack and release stages.
Gain
➡️🔊: signal in
➡️: gain multiplier. 0 if cable not connected.
↩️🔊: input signal => gain
Multiply
➡️🔊: signal1 in
➡️🔊: signal2 in
↩️🔊: sample-by-sample multiplication of input1 and input2.
05.Analyzers
Centroid
Use this unit to analyze the spectral centroid (center of mass of spectrum) of audio signals from another voice unit (or a chained series of voice units).
➡️🔊: signal in
↩️🔊: N/A
↩️: Spectrum centroid of input1.
Pitch
Use this unit to estimate the fundamental frequency of audio signals from another voice unit (or a chained series of voice units). By combining with other voice units (oscillators), this can be used to resynthesize and harmonize with a sound file.
➡️🔊: signal in
↩️🔊: N/A
↩️: Estimated fundamental frequency of input1.
RMS
Use this unit to analyze loudness of audio signals from another voice unit (or a chained series of voice units) and apply the result to control / graphics unit inlets, such as a VFX inlet.
➡️🔊: signal in
↩️🔊: N/A
↩️: RMS analysis of input1.
STON
Signal to Number Converter. Use this unit to convert audio signals from another voice unit (or a chained series of voice units) to a floating point value and apply the result to control / graphics unit inlets, such as a VFX inlet.
➡️🔊: signal in
↩️🔊: N/A
↩️: An audio sample of input1 converted to a floating point value every 1ms.
Write your own voice units!
You can write your custom voice units using Chuck! Open the RayTone source directory from the settings panel (top right corner) and take a look at the template.ck file in ChucK/User folder to get started. New .ck files in this folder will appear as new voice units after clicking on Rescan button from the settings panel . Additionally, you can create new voice unit categories by adding folders parallel to this User folder.
Use the following macros to define voice unit sockets:
RAYTONE_DEFINE_INPUTS("signal1", "signal2"); audio-rate input names with double quotation marks separated by commas.
RAYTONE_DEFINE_INLETS("dry/wet 0-1", "Inlet2Name..."); control-rate inlet names with double quotation marks separated by commas.
RAYTONE_DEFINE_OUTLET(true); set to true to add a control-rate outlet
RAYTONE_LOADFILE(false); set to true open a file browser to load a .wav file to this script. (For example, Sampler voice unit uses this feature.)
In order to send a signal to DAC and the output socket, you must add the following to your signal chain:
(Your Signal Chain) => RAYTONE_OUTPUT => dac;
Inside the ChucK script, you can read input and inlet values using the following macros:
RAYTONE_INPUT(0) Use an index starting at 0 inside the parentheses to access an input defined by RAYTONE_DEFINE_INPUTS().
RAYTONE_INLET(0) Use an index starting at 0 inside the parentheses to access an inlet defined by RAYTONE_DEFINE_INLETS().
You can send a float variable to the control-rate outlet using the following macro only if RAYTONE_DEFINE_OUTLET() is set to true:
RAYTONE_OUTLET
If RAYTONE_LOADFILE() is set to true, you can access the file path that is loaded to a voice unit using the following macro:
RAYTONE_FILEPATH
The tick in RayTone is defined as a ChucK global event:
RAYTONE_TICK
Putting this all together... the following code is an example taken from the Sampler voice unit:
//-----------------------------------------------------------------------------
//Define RayTone inputs & inlets & file requirement
RAYTONE_DEFINE_INPUTS();
RAYTONE_DEFINE_INLETS("trigger", "rate");
RAYTONE_DEFINE_OUTLET(false);
RAYTONE_LOADFILE(true);
//-----------------------------------------------------------------------------
// DSP chain
SndBuf buf => RAYTONE_OUTPUT => dac;
RAYTONE_FILEPATH => buf.read;
0 => dac.gain;
// infinite loop
while (true)
{
// Wait for tick
RAYTONE_TICK => now;
// Check for trigger
if(RAYTONE_TRIG(0) == 1)
{
RAYTONE_LOCAL_GAIN => buf.gain;
// Read rate inlet; set to 1 if not connected
if (RAYTONE_INLET_STATUS(1) == 1)
{
RAYTONE_INLET(1) => buf.rate;
}
else
{
1 => buf.rate;
}
// Read playback position in ms
(RAYTONE_INLET(2) / (buf.length() / 1::ms) * buf.samples()) $ int => buf.pos;
}
}
Graphics Units
Image
Load a .png or .jpg image on canvas. The image can be passed as a texture to the VFX shader when it is connected to an inlet of Textures unit.
➡️: width
➡️: height
➡️: opacity
Text
Double click on the purple circle and use keyboard to edit text. Use this to write comments in your patch...
➡️: size
➡️: opacity
Textures
Load RayTone Graphics Assets (Image, Video, Webcam units) as textures to the GLSL fragment shader in the VFX unit. Use RAYTONE_TEXTURE(0-7) and RAYTONE_TEXTURE_RESOLUTION(0-7) (where the value in parentheses is the texture index starting at 0) in the fragment shader to read a texture and its resolution from RayTone.
*Only a single Textures Unit is allowed in a RayTone patch.
➡️: texture1
➡️: texture2
➡️: texture3
➡️: texture4
➡️: texture5
➡️: texture6
➡️: texture7
➡️: texture8
VFX
Load a GLSL fragment shader to display on canvas. Use RAYTONE_INLET(0-7) (where the value in parentheses is the inlet index starting at 0) in the fragment shader to read an inlet value from RayTone.
*Only a single VFX Unit is allowed in a RayTone patch.
➡️: inlet1
➡️: inlet2
➡️: inlet3
➡️: inlet4
➡️: inlet5
➡️: inlet6
➡️: inlet7
➡️: inlet8
Video
Load an .mp4 video on canvas. The video can be passed as a texture to the VFX shader when it is connected to an inlet of Textures unit.
➡️: play trigger
➡️: playback rate (default: 1, max: 10)
➡️: playhead position in milliseconds (only set on play trigger)
➡️: loop ("on" if value is larger than 1)
➡️: width
➡️: height
➡️: opacity
Webcam
Capture the default webcam device on OS as a dynamic image on canvas. The webcam can be passed as a texture to the VFX shader when it is connected to an inlet of Textures unit.
➡️: width
➡️: height
➡️: opacity
The following is a template GLSL fragment shader code that you can use with the VFX unit.
#version 410
//-----------------------------------------------------------------------------
//RAYTONE HEADER
uniform vec3 iResolution;
uniform float iTime;
uniform float inlets[8];
uniform sampler2D textures[8];
uniform vec3 textureResolutions[8];
#define RAYTONE_RESOLUTION iResolution
#define RAYTONE_TIME iTime
#define RAYTONE_INLET(i) inlets[i]
#define RAYTONE_TEXTURE(i) textures[i]
#define RAYTONE_TEXTURE_RESOLUTION(i) textureResolutions[i]
//-----------------------------------------------------------------------------
out vec4 fragColor;
void main()
{
// Define UV coordinates based on canvas resolution
vec2 uv = gl_FragCoord.xy / RAYTONE_RESOLUTION.xy;
// Read inlet 0 to create yellow columns
float r = sin(uv.x * RAYTONE_INLET(0) * 100);
float g = sin(uv.x * RAYTONE_INLET(0) * 100);
float b = uv.y * (sin(RAYTONE_TIME) * 0.5 + 0.5); // flashing blue
// Define texture coordinates based on its resolution
vec2 tex1_uv = gl_FragCoord.xy / RAYTONE_TEXTURE_RESOLUTION(0).xy;
// Sample texture
vec4 tex1 = texture(RAYTONE_TEXTURE(0), tex1_uv);
// Output is RGB + texture
fragColor = vec4(r, g, b, 1.0) + tex1;
}