Source reference
examples/resources/synthesis/luau/main.luau
--!strict
local byt = require("@bytorio")
local audio, data = byt.audio, byt.data
local tone: byt.Instrument? = nil
local tonePitch, toneCutoff, toneWave = 440, 1200, 0.25
return {
init = function()
local pcm = data.pcm(64, 1)
for i = 0, 63 do
local phase = (i % 32) / 32
local value = if i < 32 then phase * 2 - 1 else (if i % 32 < 16 then 1 else -1)
buffer.writef32(pcm.samples, i * 4, value)
end
local wave = audio.wavetable({ frames = 32, waves = 2 }, pcm)
local instrument = audio.instrument({
{ kind = "wavetable", source = wave },
{ kind = "wavetable", source = wave, frequency_hz = 110 },
{ kind = "lfo", frequency_hz = 5 },
{
kind = "adsr",
attack_frames = 16,
decay_frames = 32,
sustain = 0.5,
release_frames = 64,
},
{
kind = "wavetable",
source = wave,
wave = 0.25,
frequency_input = 1,
fm_depth_hz = 80,
phase_input = 2,
pm_depth_cycles = 0.03,
},
{ kind = "mix", input = 0, other = 4, gain = 0.4, secondary_gain = 0.6 },
{ kind = "gain", input = 5, gain = 0, gain_input = 3, depth = 0.2 },
{ kind = "filter", input = 6, cutoff_hz = 1200, resonance = 0.2 },
{
kind = "delay",
input = 7,
max_delay_frames = 128,
delay_frames = 64,
feedback = 0.25,
wet = 0.35,
},
{ kind = "pan", input = 8, pan = -0.2 },
{ kind = "output", input = 9 },
})
tone = instrument
local noise = audio.instrument({
{ kind = "noise", seed = 1234567 },
{
kind = "adsr",
attack_frames = 4,
decay_frames = 8,
sustain = 0.25,
release_frames = 32,
},
{ kind = "gain", input = 0, gain = 0, gain_input = 1, depth = 0.08 },
{
kind = "filter",
input = 2,
cutoff_hz = 5000,
resonance = 0.1,
filter_mode = "highpass",
},
{ kind = "output", input = 3 },
})
local bus = audio.bus({ gain = 0.8 })
audio.effects(bus, {
{ kind = "input" },
{
kind = "delay",
input = 0,
max_delay_frames = 256,
delay_frames = 96,
feedback = 0.3,
wet = 0.25,
},
{ kind = "filter", input = 1, cutoff_hz = 6000 },
{ kind = "output", input = 2 },
})
local v = audio.voice(0)
audio.note_on(v, instrument, 440, { bus = bus, velocity = 0.8 })
audio.note_on(audio.voice(1), noise, 440, { bus = bus, at = 64 })
audio.node_control(v, instrument, 4, "wave", 1, 128, 64)
audio.node_control(v, instrument, 7, "cutoff", 2400, 256, 128)
audio.effect_control(bus, 1, "feedback", 0.1, 320, 32)
local patch = data.pcm(8, 1)
for i = 0, 7 do
buffer.writef32(patch.samples, i * 4, 0.25)
end
audio.edit_wavetable(wave, 4, patch, 512)
audio.note_off(audio.voice(1), 640)
audio.note_off(v, 1024)
audio.note_on(audio.voice(2), instrument, 220, { at = 1200, velocity = 0.3 })
audio.node_control(audio.voice(2), instrument, 8, "wet", 0.8, 1600, 128)
local samplePcm = data.pcm(8, 1)
for i, value in { 0, 0.25, 0.5, 0.75, 1, 0.75, 0.5, 0.25 } do
buffer.writef32(samplePcm.samples, (i - 1) * 4, value)
end
local sample = audio.sample({ frames = 8, channels = 1, rate = 24000 }, samplePcm)
local sampleInstrument = audio.instrument({
{ kind = "sample", source = sample, loop = true, loop_end = 8 },
{ kind = "gain", input = 0, gain = 0.05 },
{ kind = "pan", input = 1, pan = 0.4 },
{ kind = "output", input = 2 },
})
audio.note_on(audio.voice(3), sampleInstrument, 440, { at = 96 })
local samplePatch = data.pcm(1, 1)
buffer.writef32(samplePatch.samples, 0, -0.5)
audio.edit_sample(sample, 0, samplePatch, 800)
audio.note_off(audio.voice(3), 1800)
local cancelledPcm = data.pcm(2, 1)
buffer.writef32(cancelledPcm.samples, 0, 0.5)
buffer.writef32(cancelledPcm.samples, 4, 0.5)
local cancelled = audio.sample({ frames = 2, channels = 1, rate = 48000 }, cancelledPcm)
audio.edit_sample(cancelled, 0, cancelledPcm)
audio.play_sample(audio.voice(4), cancelled, { at = 2000 })
audio.destroy(cancelled)
buffer.fill(pcm.samples, 0, 0)
end,
update = function(_dt: number)
if byt.pressed("left") then
tonePitch = math.max(110, tonePitch / 2)
end
if byt.pressed("right") then
tonePitch = math.min(1760, tonePitch * 2)
end
if byt.pressed("up") then
toneCutoff = math.min(12000, toneCutoff + 400)
end
if byt.pressed("down") then
toneCutoff = math.max(200, toneCutoff - 400)
end
if byt.pressed("action") then
toneWave = 1 - toneWave
end
local instrument = tone
if instrument then
local v = audio.voice(2)
if byt.pressed("left") or byt.pressed("right") then
audio.node_control(v, instrument, 0, "frequency", tonePitch, nil, 64)
audio.node_control(v, instrument, 4, "frequency", tonePitch, nil, 64)
end
if byt.pressed("up") or byt.pressed("down") then
audio.node_control(v, instrument, 7, "cutoff", toneCutoff, nil, 64)
end
if byt.pressed("action") then
audio.node_control(v, instrument, 4, "wave", toneWave, nil, 64)
end
end
local status = audio.status()
byt.debug_position(status.completed, #audio.completions())
end,
draw = function()
byt.clear(byt.rgb(20, 28, 44))
byt.text("SYNTH: FM / ENVELOPE / FILTER / DELAY", 12, 20, byt.rgb(240, 240, 240))
byt.rect(24, 48, 272, 40, byt.rgb(70, 180, 150))
byt.rect(24, 92, math.floor(tonePitch / 8), 6, byt.rgb(240, 200, 80))
byt.text("LEFT/RIGHT PITCH UP/DOWN FILTER", 12, 110, byt.rgb(240, 240, 240))
byt.text("SPACE: MORPH WAVE", 12, 126, byt.rgb(240, 240, 240))
end,
}
Get started