Bytebeat-inspired live coding thingie for waveshaping synthesis.
Runs on modern browsers using the WebAudio API.
Check out the tutorial if you want to learn how to use Tilt while also learning a little bit about sound synthesis :-)
To make some audio, define the value of the variable o
. It must be a number
between 0 and 1. For this, you can use the t
parameter, which is an
always-increasing counter.
For example, to make a sine wave at 440hz:
o = sine(t);
Evaluate code by pressing the Play button, or Ctrl+Enter (or Command+Enter). You can stop sound by pressing the Stop button, or Ctrl+..
You can make all sorts of simple (and more complex) waveforms:
// saw wave
let q = 2 * pi;
o = (t % q) / q;
// square wave
let q = 2 * pi;
o = (t % q) / q > 0.5;
// pulse wave with pulse-width modulation
let q = 2 * pi;
o = (t % q) / q > seq(256, 64) / 64;
// triangle wave
let ramp = (t % q) / q;
o = ((ramp > 0.5 ? ramp : 1 - ramp) - 0.5) * 2;
These simple waveforms are also already defined as functions. Read below.
There is also a parameter K
which is static and represents the number of
samples in a cycle. It is used to make rhythm. See the function seq
or
randInt
, as they use it internally.
A more complex example, using some of the functions described below:
o = sine(t / (randInt(8, 32) + 1)) * env(8, 1) * 0.75;
o +=
sine((t * aseq(16, [2, 3, 2, 7, 8])) / 4 + sine((t / aseq(8, [1, 2])) * 1.0001)) *
invEnv(seq1(32, 8), seq1(4, 8) + 1) *
0.75;
Remember that o
should be a number between 0 and 1. If you add multiple
waveforms, you should scale them down to mix them properly. For example,
instead of:
o = sine(t) + tri(t);
You should do something like this:
o = sine(t) * 0.5 + tri(t) * 0.5;
Why 0.5? Because both sine(t)
and tri(t)
output values from 0 to 1. If
you multiply them with 0.5 (or divide them by 2), they should range between 0
and 0.5, which when both are added up, they end up ranging from 0 to 1.
Code is written in JavaScript, but there are some useful constants and functions available.
Most of the functions from Math
object in JavaScript are defined as globals,
but the following are the most useful:
pi
: Pi constant.two_pi
: 2 times Piabs(arg)
: Returns the absolute value of a number.sin(arg)
: Returns the sine of a number.tan(arg)
: Returns the tangent value of a number.tanh(arg)
: Returns the hyperbolic tangent value of a number.floor(arg)
: Returns the largest integer less than or equal to a given number.ceil(arg)
: Returns the smallest integer greater than or equal to a given number.pow(arg)
: Returns base to the exponent power.round(arg)
: Returns the value of a number rounded to the nearest integer.sqrt(arg)
: Returns the positive square root of a number.
Note: sin
returns a number from -1 to 1, there is also sine
which
returns a number from 0 to 1, suitable as audio output.
These functions all return numbers from 0 to 1, so they can be used directly as audio output.
sine(t)
: Sine waveformsaw(t)
: Saw waveformpulse(t, width)
: Pulse waveformsquare(t)
: Square waveform (same as Pulse with width 0.5)tri(t)
: Triangle waveform
seq(subdiv, subdiv)
: Returns a number from 0 tolength - 1
insubdiv
subdivisions of a cycle (defined byK
).seq1(subdiv, length)
: Same asseq
, but number range from 1 tolength
. subdivisions of a cycle (defined byK
).aseq(subdiv, array)
: Returns values fromarray
insubdiv
subdivisions of a cycle. Basically, sequences an array.
env(subdiv, curve, smooth)
: Generates an exponential envelope that lastssubdiv
subdivisions of a cycle, with an exponentcurve
. The optionalsmooth
argument is a 0-1 number that splits the envelope into an increasing linear ramp for a smoother attack (0=no smoothing, 1=linear ramp).invEnv(subdiv, curve, smooth)
: Same asenv
but generates an inverse exponential envelope. Thesmooth
argument controls a decreasing ramp at the end of the envelope.
rand(subdiv, seed)
: Returns a random number between 0 and 1. The number is held duringsubdiv
subdivisions of a cycle. When using the sameseed
you can generate the same sequence of random numbers.randInt(subdiv, max, seed)
: Same asrand
but generates a integer numbers from 0 tomax
.
These functions generally replace the use of the t
counter variable for musically-related concepts:
f(frequency)
: Generates a counter at the specified frequency (e.g.sine(f(440)) == sine(t)
).m(midinote)
: Generates a counter at the specified MIDI note (e.g.sine(m(69)) == sine(t)
, because 69 is the A4, which is 440Hz).
GPL 3+. Refer to LICENSE.txt
Icons:
- Play by Eagle Eye from the Noun Project
- Stop by vectoriconset10 from the Noun Project