handmade-livecode.txt

An introduction to live coding for Handmade Boston using strudel and hydra.

Table of Contents

My Background

programming
I am a professional game developer, I write C++ at work and try not to hate it. Spent a lot of time writing Rust and recently switched over to Zig.
livecoding
Started a local meetup last year, and I have performed doing visuals locally at Viscera and with livecode.nyc.
handmade
Attended Handmade Boston 2023. Seen some of Handmade Hero and a co-worker gifted me Casey's Performance Course.

Goals

My hope is that this can be a wonderful cross-pollination between the live code and handmade communities.


The handmade community has a lot to offer:

  • Low level insights leading to high level improvements
  • Appreciation of the technical aspects of UX:
    Performance, Simplicity, Reliability
  • Technology that serves the user

The live coding community has a lot to offer:

  • Making technology accessible to non-technical people
  • Alternative perspectives on technology & its meaning
  • Artistic and creative practice and perspectives

Live Coding

verb.
Writing and running code in a live environment, where one is able to run and manipulate the program at the same time.
noun.
A form of performance art using code as the interface to create art with an emphasis on live manipulation of code that is usually visible to the audience. Fully improvised, or party planned.

We usually treat Software development as a practice with a relatively objective goal, with quantifiable results:

  • Means of Production
  • Automation
  • Commerce
  • Permenance

Live Coding requires a shift in mindset:

  • Community
  • Creative Performance
  • Connection
  • Ephemerality

Ethos

The live coding community also carries values of:

  • Software made by people for people
  • On the fly problem solving: No backups!
  • Gender Equality & Diversity
  • Opposition to Heirarchy

And perhaps most importantly…

ALWAYS SHOW YOUR CODE

On Gender Equality, I'd like to shout out some of my fave women and enbies:

Char Stiles
Uses GLSL (hardcore) to create awesome visuals, also proficient in strudel. Also: Char's Tiles
Switch Angel
Very talented strudel developer and live code performer, one of the best out there.
DJ_Dave
A very talented musician who uses sonic-pi.
elle
Talented local visual performer also using Hydra, and de-facto co-organizer for our meetup group.
Heavy Lifting
Musician, contributor to Tidal Cycles, and one of the OGs.
this.xor.that
Visualist with a custom live coding tool called Murrelet

Technical Constraints

Live coding presents intersting technical constraints in needing to write and edit code live. This leads to the use of:

  • Scripting languages: ruby, python, lua
  • javascript and the browser
  • REPLs like haskell's ghci

This has downsides though:

Performance Problems == Performance Problems

I think this is where Handmade can help!

But now, let's make some art.

Javascript

The only special thing you need to know:

let lambda = (x,y) => x.add(y)

We can also get functional freaky

let higher_order = x => y => x.add(y)

higher_order(1)(2)

Strudel

strudel: javascript sound engine and live coding framework.

Represents music as repeating cycles of events.

Making a Sound

Go to strudel.cc and type:

sound("bd")

Press CTRL+Enter to run your program.

SoundDescription
bdBass drum
sdSnare drum
hhHigh-hat
sawtoothA very bright synth sound
xylophone_hard_ffA xylophone sample
- or ~rest

Try changing the sounds!

Mininotation

Everything inside "s is a pattern written in mininotation.

$: sound("bd bd bd bd")

We call each slice of the cycle an arc. The length of the cycle stays the same no matter how many arcs divide up the cycle.

$: sound("bd bd - bd bd -")

Operators

Strudel has mininotation operators:

OperatorEffect
@Elongates
!Repeats
*Speeds up
/Slows down
?Play event 50% of the time
[ ]Create a sub-cycle
< >Alternate

Melody

strudel can play notes as well:

$: note("c ab f bb").sound("piano")
NotationMeaning
[a-g]note (western scale)
a[0-9]+a with octave
a(f|b)a with flat
a(s|#)a with sharp

Transforming Patterns

Apply functions to patterns to alter them:

.fast(n)
Speed up a pattern by a factor of n
.ply(n)
Repeat each event in a pattern n times
.degradeBy(n)
Drop n% of events where 1 is 100%
.transpose(n)
Offset notes by n semitones
.late(n)
Delay a pattern by n cycles
.struct(pat)
For each x in pat, sample data from the left

Higher Order Functions

Apply functions to patterns to alter them:

.superimpose(fn)
Play the pattern on top of itself with fn applied
.off(n, fn)
Like superimpose but with a time offset of n.
when(pat, fn)
When pat is true, apply fn.

Self learning

strudel is an instrument, and requires practice.

  • Try weird combinations of things
  • Look at random stuff from the reference
  • Watch and steal learn
  • Ask for help on club.tidalcycles.org

Hydra

hydra is a javascript tool for generating shaders
inspired by analogue video synthesis.

Represents a shader as a tree (or hydra) of transforms.

We can either open hydra's editor at hydra.ojack.xyz, or directly in strudel's editor with:

await initHydra()

Source

The simplest possible patch:

solid(1,0,1).out()
gradient()
draws a gradient from uv coordinates
shape(n)
draws a shape with n sides
osc()
draws sin(uv.x) with time offset
noise()
Draws smooth noise
voronoi()
Draws voronoi diagram

Color

We can chain functions which modulate the color:

gradient().hue().out()

.hue()
Shift hue by optional amount
.luma()
Set alpha of dark pixels to 0
.saturate()
Multiply color saturation
.constrast()
Increase or decrease contrast

Coord

We can also manipulate the uv coordinates as observed by the shader:

.rotate()
Apply 2d rotation in radians
.scale()
Apply uniform scale
.repeat()
Repeat the image n times
.scollX()
Shift x coordinates
.kaleid()
Apply kaleidescope effect

Modulation

But what about non-uniform transforms?

.modulateRotate(osc(), n)
Rotate each pixel by osc or whatever pattern goes in
.modulateScale(voronoi(), n)
Scale each pixel by voronoi

Generally, each coord function has a "modulate" version.

Combine

We can layer multiple transforms atop one-another:

.add(osc())
Directly add osc, scaled by optional param
.blend(gradient())
Color blend the two branches
.layer(voronoi().luma())
Alpha blending, with optional bias
.diff(shape())
Difference between the two transforms

Feedback

hydra supports up to 4 outputs! o0, o1, o2, o3


We can read and write to the same one to create feedback.

osc().modulate(o0).rotate(0.1).out(o0)

o0 is the default and we can omit it.

Sequencing

[] in hydra create sequences,
similar to strudel but much simpler:

osc(40, 0.1, [0.1, 1, 3]).out()

Uniforms

You can use an javascript lambda to create a uniform:

() => Math.sin(time) * 2

Incompatible with sequence []s.

Audio Reactivity

Reacting to sound can bring so much life into your patch!

a.setBins(4)
a.show() // a.hide()

osc(40, 0.1, () => a.fft[0]* 2).out()

Questions & Demo

  1. Some closing thoughts
  2. Let's jam out!
  3. Shout out your questions

FIN.