Kadent
Kadent is a cross-platform DAW featuring KASL, a domain-specific audio language, and node-graph processing system.
Features
- Create music with familiar track-based UI
- Two track types: Note Track & Audio Track
- Node graph for every track
- KASL language with syntax similar to Swift
The node graph allows you to combine multiple KASL programs to perform much more complex processing.
What Is a Node Graph?
Kadent uses node graph for track processing.
A Node is a processing unit that calculates the output. In node graph, an output of one node can be connected to an input of another node. This allows you to connect multiple inputs and outputs freely to other nodes to create sound.
Then, why did I adopt node graph? KASL programs can have multiple inputs and outputs, and their types may also vary. So placing them in order does not work because the DAW cannot know which output is connected to the specific input. That’s why Kadent uses node graph.
Characteristics of KASL
- Utilizes Cranelift as a backend for quicker JIT compilation
- Specialized type of variables such as
input,outputandstate - Supports fixed-length arrays and structs
- Fixed-count
loopsyntax for predictable execution time - Module system influenced by Python
- Custom infix/prefix/postfix operators (even normal arithmetic operators are defined and provided by
std)
KASL Sample Program
audiomodule is built-in module provided by Kadent. Note that these programs below won’t work outside the DAW.
Gain Node
import audio
import std
input in = audio.zero_sample()
input gain = 0.0
output out = audio.zero_sample()
func main() {
out = in * [gain; audio.max_channels]
}
Mix Node
import std
import std/math/float as f
import audio
input input_1 = audio.zero_sample()
input input_2 = audio.zero_sample()
input factor = 0.0
output out = audio.zero_sample()
func main() {
let clamped_factor = f.clamp(factor, 0.0, 1.0)
let multiplied_input_1: audio.Sample = input_1 * [clamped_factor; audio.max_channels]
let multiplied_input_2: audio.Sample = input_2 * [1.0 - clamped_factor; audio.max_channels]
out = multiplied_input_1 + multiplied_input_2
}
Sawtooth Wave Synthesizer
import audio as a
import std
import std/math/float as f
input notes = a.EventSlot()
input pitch = 1.0
output out = a.zero_sample()
state allocator = a.Allocator()
let base_freq = 440.0
let volume = 0.1
func main() {
allocator.update(notes)
var i = 0
loop a.max_voices {
let voice = allocator.voices[i]
let freq = pitch * base_freq * f.pow(2.0, (voice.pitch - 69.0) / 12.0)
if voice.is_active {
let t = voice.age
let sample = saw(freq: freq, time: t)
out = out + [sample * volume; a.max_channels]
}
i = i + 1
}
}
func saw(freq f = 440.0, time t: Float) -> Float {
return 2.0 * (t * f) % 1.0 - 1.0
}
Installation
Go to the Releases page of my GitHub repository to download the latest precompiled binary, or compile the binary yourself. Detailed installation steps are described in README.
- 23 devlogs
- 229h