Reading this, what struck me most wasn’t the art or the technology. It was the loneliness embedded in the premise. Shanken is essentially arguing that modern people are so cut off from themselves and each other that we need elaborate workarounds: VR headsets, ayahuasca ceremonies, multimedia installations, just to feel what a Yanomami community apparently felt on an ordinary Tuesday. There’s something almost embarrassing about that, in the best possible way. We’ve built so much, and yet here are serious academics and artists essentially reverse-engineering awe.
What I keep thinking about is Pauline Oliveros describing music moving through her, like she was just the instrument. That’s not a new idea. Monks have said it, jazz musicians have said it, athletes call it flow. The technoshamanism framing just gives it a gallery wall and a footnote. Maybe that’s the real point though. Not that the technology gets us somewhere ancient and sacred, but that naming it, framing it, putting it in a Venice Biennale pavilion, is how a secular culture gives itself permission to want transcendence without apologizing for it.
What struck me reading this paper is that Deadmau5 might actually be the most honest person in the room. He looked at what electronic music performance structurally is, a technology of reproduction, and just said it plainly. Everyone else tends to perform spontaneity to some degree. Live coders project their screens and that gesture matters, but they are still building on pre-written libraries, familiar patterns, layers of abstraction they did not invent mid-set. The paper even admits that coding from scratch is an impossible ideal.
That is where things get interesting to me. Live coding is not trying to be Derek Bailey and deep down it knows it. A lot of live coders want the beat, want people dancing, want the same things Deadmau5 wants. The real difference is not some claim to purity but a willingness to keep the process visible and genuinely uncertain. Showing your screen is not proof that you escaped mediation. It is just an honest account of where the mediation is actually happening. And honestly that might be a more defensible and more interesting thing to offer than any romanticized idea of total freedom from the machine.
demo 1
demo 2
Before reading Rosa Menkman’s Glitch Studies Manifesto, I mostly saw glitches as problems that good programming should prevent. In coding, we are usually trained to build systems that handle failures so smoothly that users never notice them. Because of that, I had always thought of noise as something unwanted. Menkman’s discussion changed that perspective by showing that noise and glitches can do more than interrupt a system — they can expose the hidden structures behind technology and question the idea that digital media must always be clean and flawless.
Even though I still understand why people prefer smooth and reliable devices, the reading made me value noise in a different way. I can see this reflected in today’s renewed interest in vintage cameras and older technologies, where imperfections are often appreciated rather than avoided. Glitch art does something similar: it turns error into expression and gives artists a way to challenge both technological standards and larger social or political systems. What stands out to me most is that meaning depends on perspective. The artist may see intention and structure in the glitch, while the viewer may still experience it as disruption. That made me realize that our idea of a “perfect” program or technology is not fixed, but shaped by how we choose to interpret it.
I originally had a more culturally oriented idea in mind for this composition, which I hope to return to later, but I found myself lacking inspiration and direction at this time. To reset, I went back to the class materials, the dirt samples, and revisited the class basics by running patterns again. From there, the piece began to grow more naturally and shifted into an exploration of buildup. I initially wanted to construct everything from my own sampled slices, but ran into challenges shaping them into clean drops and transitions, so the work became a blend of templates and personal material. This led me to a more open and exploratory process building intensity, compressing into darker moments, and then opening back up again.
Tidal
setcps (135/60/4)
visSec = \n -> ccv (pure $ fromIntegral n) # ccn "0" # s "midi"
visSpd = \p -> ccv p # ccn "1" # s "midi"
visHit = \p -> ccv p # ccn "2" # s "midi"
visDark = \p -> ccv p # ccn "3" # s "midi"
visGeom = \p -> ccv p # ccn "4" # s "midi"
visBus = \sec spd hit dark geom ->
stack
[ visSec sec
, visSpd spd
, visHit hit
, visDark dark
, visGeom geom
]
introDrone =
slow 8 $
slice 40 "3" $ s "sudan"
# speed 0.45
# room 0.8
# legato 2
# gain 0.9
airPad =
n (slow 4 "")
# sound "supersaw"
# legato 1.6
# lpf (range 500 1800 $ slow 6 sine)
# resonance 0.22
# room 0.7
# gain 0.45
# shape 0.18
voiceLine = stack
[ fast 2 $
s "simplesine"
>| note (arp "updown" (scale "minor" ("[0,2,4,6]" + "") + "c4"))
# gain 0.62
# lpf 2600
# room 0.55
, s "simplesine"
>| note (scale "minor" ("[,0,2](3,8)") + "c4")
# gain 0.58
# room 0.6
]
versePerc =
stack
[ s "~ cp" # room 0.45 # gain 0.95
, fast 2 $
s "hh*2 hh*2 hh*2 "
# room 0.65
# gain (range 0.9 1.15 rand)
]
habeshaTop =
slice 40 "18" $ s "habesha:1"
# legato 1
# room 0.55
# gain 0.95
kickMain =
s "[, ~ 808:3]"
# room 0.35
# gain 1.0
leadDrop =
n (fast 2 "")
# sound "supersaw"
# legato 0.2
# lpf (range 160 4200 $ slow 3 sine)
# room 0.28
# gain 0.72
# krush 5
# shape 0.3
# pan (slow 2 sine)
buildHat =
stack
[ s "~ cp" # room 0.45 # gain 1.0
, fast 2 $
s "hh*2 hh*2 hh*2 "
# room 0.65
# gain (range 0.95 1.2 rand)
]
# speed (slow 4 $ range 1 2 saw)
buildSnare =
qtrigger $ filterWhen (>=0) $ seqP
[ (0,1, s "feel:2*4")
, (1,2, s "feel:2*8")
, (2,3, s "feel:2*16")
, (3,4, s "feel:2*32")
]
# room 0.25
# hpf (slow 4 $ (1000 * saw + 200))
# speed (slow 4 $ range 1 3 saw)
# gain 0.95
buildPulse =
s ""
# gain 0.8
# lpf (slow 4 $ range 300 2200 saw)
# room 0.2
buildSynth =
n (slow 2 "")
# sound "supersaw"
# legato 0.8
# gain 0.5
# hpf (slow 4 $ range 200 1600 saw)
# lpf (slow 4 $ range 1200 5000 saw)
# room 0.45
# shape 0.25
kickFill =
s "[808bd:1 [~ 808bd:1*3]] [808bd:1 ~ 808bd:1*2]"
# room 0.45
# speed (range 7.6 2.1 saw)
# krush 10
# gain 1.0
dropKick =
s "[bd*2 ] [~ bd*2]"
# gain 1.15
# room 0.25
# shape 0.32
dropBass =
n ""
# sound "supersaw"
# octave 3
# legato 1
# gain 0.95
# lpf (range 120 700 $ slow 2 sine)
# room 0.2
# krush 6
dropPerc =
s ""
# room 0.85
# speed "2 1"
# gain 1.2
# squiz 1.05
# up "-2"
dropMetal =
s "[~ [hc*4 hc*8] ~ hc*16]"
# gain 0.7
# hpf 3500
# room 0.15
dropStab =
n ""
# sound "supersaw"
# legato 0.15
# gain 0.7
# room 0.25
# lpf 1800
# krush 8
silenceAll = do
d1 silence
d2 silence
d3 silence
d4 silence
d5 silence
d6 silence
d7 silence
d8 silence
section_intro = do
d1 $ visBus
0
(slow 8 $ range 8 20 sine)
(struct "t(3,8)" $ range 10 25 saw)
(slow 8 $ range 95 70 sine)
(slow 8 $ range 10 25 sine)
d2 introDrone
d3 airPad
d4 silence
d5 silence
d6 silence
d7 silence
d8 silence
section_verse = do
d1 $ visBus
1
(slow 6 $ range 18 35 sine)
(struct "t(3,8)" $ range 20 45 saw)
(slow 6 $ range 80 60 sine)
(slow 4 $ range 18 40 saw)
d2 voiceLine
d3 versePerc
d4 airPad
d5 habeshaTop
d6 silence
d7 silence
d8 silence
section_build1 = do
d1 $ visBus
2
(slow 4 $ range 30 75 saw)
(struct "t(3,8)" $ range 35 80 saw)
(slow 4 $ range 65 40 saw)
(slow 4 $ range 35 75 saw)
d2 $ qtrigger $ filterWhen (>=0) $ seqP
[ (0,3, voiceLine)
, (3,4, kickFill)
]
d3 buildHat
d4 buildSnare
d5 buildPulse
d6 buildSynth
d7 silence
d8 silence
section_build2 = do
d1 $ visBus
3
(segment 128 $ range 65 120 $ saw)
(segment 64 $ struct "" $ range 60 127 saw)
(segment 64 $ range 45 20 saw)
(segment 64 $ range 60 120 saw)
d2 buildHat
d3 buildSnare
d4 buildPulse
d5 buildSynth
d6 $ qtrigger $ filterWhen (>=0) $ seqP
[ (0,1, s "feel:2*4")
, (1,2, s "feel:2*8")
, (2,3, s "feel:2*16")
, (3,4, s "feel:2*32")
]
# room 0.2
# speed (slow 4 $ range 1 4 saw)
# hpf (slow 4 $ range 1200 8000 saw)
d7 kickFill
d8 silence
section_drop = do
d1 $ visBus
4
(slow 2 $ range 110 70 sine)
(struct "" $ range 90 127 square)
(slow 2 $ range 18 35 sine)
(slow 2 $ range 85 45 saw)
d2 dropKick
d3 dropBass
d4 dropPerc
d5 dropStab
d6 dropMetal
d7 silence
d8 silence
section_after = do
d1 $ visBus
5
(slow 6 $ range 25 45 tri)
(struct "t(3,8)" $ range 30 55 saw)
(slow 6 $ range 70 55 sine)
(slow 8 $ range 25 40 tri)
d2 kickMain
d3 voiceLine
d4 airPad
d5 habeshaTop
d6 silence
d7 silence
d8 silence
section_outro = do
d1 $ visBus
6
(segment 128 $ slow 8 $ range 40 8 sine)
(segment 128 $ slow 8 $ range 35 5 sine)
(segment 128 $ slow 8 $ range 80 100 sine)
(segment 128 $ slow 8 $ range 35 8 sine)
d2 introDrone
d3 silence
d4 silence
d5 silence
d6 silence
d7 silence
d8 silence
goI = section_intro
goV = section_verse
goB1 = section_build1
goB2 = section_build2
goD = section_drop
goA = section_after
goO = section_outro
goI
goB1
goB2
goD
goB1
goD
goA
goO
silenceAll
hush
Hydra
hush()
const ccv = (n, fallback = 0) => () => {
try {
return (cc[n] !== undefined ? cc[n] : fallback) / 127
} catch (e) {
return fallback / 127
}
}
const SECTION = ccv(0, 0)
const SPEED = ccv(1, 20)
const HIT = ccv(2, 0)
const DARK = ccv(3, 80)
const GEOM = ccv(4, 20)
const W = () => window.innerWidth
const H = () => window.innerHeight
const aspect = () => H() / W()
const colorFold = (src, n = 6) =>
new Array(n).fill().reduce(
(a) => a.colorama(() => 0.002 + GEOM() * 0.02),
src
)
const triGrid = () =>
shape(3, 0.32, 0.001)
.rotate(() => time * 0.04 + SPEED() * 0.4, () => 0.02 + HIT() * 0.08)
.repeat(
() => 2 + Math.floor(GEOM() * 6),
() => 2 + Math.floor(GEOM() * 4)
)
.scrollX(() => 0.02 * Math.sin(time * 0.3))
.scrollY(() => 0.02 * Math.cos(time * 0.2))
.luma(0.15, 0.2)
const quadGrid = () =>
shape(4, 0.45, 0.0001)
.repeat(
() => 2 + Math.floor(GEOM() * 5),
() => 2 + Math.floor(GEOM() * 5)
)
.rotate(() => time * 0.02 + SPEED() * 0.2)
.scale(1, aspect(), 1)
.luma(0.2, 0.15)
const movingOsc = () =>
osc(
() => 8 + SPEED() * 65,
() => 0.015 + SPEED() * 0.08,
() => 0.4 + HIT() * 3.2
)
.posterize(() => 3 + Math.floor(GEOM() * 4))
.kaleid(() => 3 + Math.floor(SECTION() * 8))
.scale(1, aspect(), 1)
.color(
() => 0.5 + DARK() * 0.4,
() => 0.15 + SECTION() * 0.35,
() => 0.35 + GEOM() * 0.4
)
const texture = () =>
noise(
() => 1.5 + GEOM() * 8,
() => 0.02 + SPEED() * 0.03
)
.pixelate(
() => 8 + GEOM() * 50,
() => 8 + GEOM() * 40
)
.luma(0.35, 0.25)
const darkWash = () =>
solid(0, 0, 0)
.add(
osc(
() => 6 + SPEED() * 18,
0.01,
0
)
.rotate(() => time * 0.01)
.luma(0.25, 0.25)
.color(0,0,0),
() => 0.15 + (1 - DARK()) * 0.55
)
const accentLines = () =>
osc(
() => 12 + HIT() * 35,
0.01,
1
)
.rotate(() => Math.PI/4 + time * 0.01)
.luma(0.78, 0.18)
.color(
() => 0.15 + SECTION() * 0.18,
() => 0.25 + DARK() * 0.2,
() => 0.35 + DARK() * 0.25
)
.mult(quadGrid())
.mult(
osc(3,0.02,0)
.rotate(Math.PI/2)
.luma(0.6,0.2)
)
const scene = () =>
colorFold(
movingOsc()
.modulate(
texture(),
() => 0.03 + GEOM() * 0.16
)
.mult(triGrid().add(quadGrid(), 0.5)),
8
)
.add(texture(), () => 0.05 + GEOM() * 0.08)
src(o1)
.modulateRotate(
noise(
() => 1 + GEOM() * 5,
() => 0.01 + SPEED() * 0.02
),
() => 0.003 + HIT() * 0.05
)
.scale(() => 1.0005 + HIT() * 0.01)
.rotate(() => 0.0008 + SPEED() * 0.01)
.blend(scene(), 0.82)
.add(accentLines(), () => 0.04 + DARK() * 0.06)
.add(darkWash(), () => 0.2 + (1 - DARK()) * 0.45)
.saturate(() => 1 + DARK() * 1.2)
.contrast(() => 1.0 + HIT() * 0.3)
.brightness(() => -0.18 + DARK() * 0.18)
.out(o1)
render(o1)