Overview
uvi-script provides asynchronous operations to prevent blocking the real-time audio thread when performing file I/O, loading samples, or other time-consuming tasks.
All asynchronous operations run on background threads and communicate their results back to the script thread safely, ensuring real-time audio processing is never interrupted.
Common Patterns
Callback Pattern
All async functions accept a callback that will be called upon completion. This is the recommended pattern for most use cases:
if task.success then
print("Selected: " .. task.result)
else
print("Operation cancelled or failed")
end
end)
function browseForFile(mode, title, initialFileOrDirectory, filePatterns, callback)
launch a file chooser to select a file to open or save
Definition api.lua:32
The callback receives an AsyncTask object with the following properties:
task.success - Boolean indicating if the operation succeeded
task.result - The result data (file path, loaded data, etc.)
task.finished - Boolean indicating completion status
Polling Pattern
Alternatively, you can poll the task status in a loop. This is useful when you need to perform other work while waiting:
-- Continue doing other work
while the
purge happens
while not task.finished do
print("Purging samples...")
wait(100) -- Check every 100ms
end
print("Purge complete!")
A Patch that represents a monotimbral instrument.
Definition Engine.cpp:238
table layers
Layer list for this Program (1-indexed, use Program.layers to get the count)
Definition Engine.cpp:247
function purge(target, callback)
purge an/several element(s)/oscillator(s) from its/their content in order to release memory.
Definition api.lua:350
function wait(ms)
suspend the current thread callback execution for the given number of samples.
Definition wrapper.lua:39
Available Async Operations
File Dialogs
Use browseForFile to let users select files without blocking audio:
-- Open file dialog
browseForFile(
"open",
"Select Audio File",
"",
"*.wav;*.aif", function(task)
if task.success then
local filepath = task.result
print("User selected: " .. filepath)
end
end)
-- Save file dialog
browseForFile(
"save",
"Save Preset",
"MyPreset",
"*.preset", function(task)
if task.success then
end
end)
function saveData(data, path, callback)
save data to file.
Definition api.lua:228
Sample Management
Loading and purging samples can take time. Use async operations to avoid audio glitches:
-- Purge samples from a layer
-- Optionally
wait for completion
while not task.finished do
end
print("
Layer purged successfully")
A layer of sounds.
Definition Engine.cpp:255
State Management
Save and restore the entire ScriptProcessor state, including widget values and custom data stored via onSave / onLoad :
- saveState — serialize the processor state to a file
- loadState — restore processor state from a file
-- Let the user pick a destination, then save state
browseForFile(
"save",
"Save State",
"MyState",
"*.state", function(task)
if task.success then
if t.success then print("State saved") end
end)
end
end)
-- Restore state from a user-selected file
browseForFile(
"open",
"Load State",
"",
"*.state", function(task)
if task.success then
if t.success then print("State restored") end
end)
end
end)
function saveState(path, callback)
save state from file.
Definition api.lua:110
function loadState(path, callback)
load state to file.
Definition api.lua:95
Custom Data I/O
Save and load arbitrary data to and from files:
JSON encoding does not support cyclic references or userdata values. Only plain Lua types (numbers, strings, booleans, and nested tables) are serialized.
-- Save a preset table as JSON
local preset = {name = "Warm Pad", cutoff = 800, resonance = 0.6}
saveData(preset,
"/path/to/preset.json", function(task)
if task.success then print("Preset saved") end
end)
-- Load it back
loadData(
"/path/to/preset.json", function(task)
if task.success then
local p = task.result
print("Loaded preset: " .. p.name)
end
end)
-- Save raw text
saveTextData(
"some config line\nanother line",
"/path/to/config.txt", function(task)
if task.success then print("Text saved") end
end)
-- Load raw text
if task.success then
print("Contents: " .. task.result)
end
end)
function saveTextData(data, path, callback)
save string to file.
Definition api.lua:162
function loadTextData(path, callback)
load string from file.
Definition api.lua:193
function loadData(path, callback)
load data from file.
Definition api.lua:134
Sample Loading
Load audio files into oscillators and configure their playback parameters:
- loadSample — load an audio file into an oscillator
- setPlaybackOptions — set start, end, loop points, and direction (units are in samples; loopType: 0=None, 1=Forward, 2=Alternate, 3=OneShot)
- unpurge — reload previously purged samples
-- Load a sample and configure loop points
loadSample(osc,
"/path/to/kick.wav", function(task)
if task.success then
-- Set playback: start=0, end=44100, loop Forward from 1000 to 40000, forward
if t.success then print("Playback configured") end
end)
end
end)
-- Reload purged samples
if task.success then print("Samples reloaded") end
end)
function setPlaybackOptions(oscillator, start, end_, loopType, loopStart, loopEnd, playForward, callback)
set playback options inside the oscillator
Definition api.lua:81
function loadSample(oscillator, path, callback)
load a sample inside the oscillator
Definition api.lua:56
function unpurge(target, callback)
unpurge an/several element(s)/oscillator(s) content in order to load their memory.
Definition api.lua:384
Oscillator Introspection
After loading a sample, you can query the oscillator for metadata:
-- Sample information (available on sample-based oscillators)
local info = osc.sampleInfo
if info then
print("Name:", info.name)
print("Duration:", info.duration, "ms")
print("Sample rate:", info.samplerate, "Hz")
print("Channels:", info.channels)
end
-- Slice information (available on Slice oscillators)
if osc.numSlices > 0 then
for i = 1, osc.numSlices do
local slice = osc:getSliceInfo(i)
print("Slice", i, "start:", slice.start, "ms", "duration:", slice.duration, "ms")
end
end
See Oscillator for the full list of properties including purged, looplabInfo, and numSlices.
MIDI File Operations
Load, create, and save MIDI files:
-- Load a MIDI file and iterate its events
loadMidi(
"/path/to/pattern.mid", function(task)
if task.success then
local seq = task.result
for i, event in ipairs(seq.events) do
print("Event " .. i .. ": type=" .. event.type
.. " note=" .. (event.note or ""))
end
end
end)
-- Create an empty Type-1 MIDI file at 480 PPQ with 2 tracks, then save
if task.success then
local seq = task.result
saveMidi(seq,
"/path/to/output.mid", function(t)
if t.success then print("MIDI file saved") end
end)
end
end)
function createMidiFile(maxNumTracks, maxNumEvents, callback)
create a midi file asynchronously
Definition api.lua:264
function loadMidi(path, callback)
load a midi file asynchronously
Definition api.lua:249
function saveMidi(midifile, path, callback)
save a midi file asynchronously
Definition api.lua:285
Impulse Response Loading
Load impulse response files into a IReverb effect:
loadImpulse(reverb,
"/path/to/hall.wav", function(task)
if task.success then print("IR loaded") end
end)
table inserts
all InsertEffect for this node
Definition Engine.cpp:243
SampledReverb.
Definition Engine.cpp:192
function loadImpulse(reverb, path, callback)
load and impulse response inside the reverb.
Definition api.lua:316
Thread Safety
- Background Execution
- All async operations execute on background threads, completely separate from the real-time audio thread. This ensures audio processing is never interrupted.
- Callback Execution
- The completion callback is executed on the script's main thread, making it safe to access script variables and call uvi-script API functions.
- Data Sharing
- Data passed between threads is safely copied. You don't need to worry about race conditions or locks when using async operations.
Best Practices
- Check Success Status
- Always verify the operation succeeded before using results:
if task.success then
-- Safe to use task.result
print("File: " .. task.result)
else
-- User cancelled or error occurred
print("No file selected")
end
end)
- See also
- Async, AsyncTask, browseForFile, purge
-
spawn, wait, onSave, onLoad