When I was working on my compositions with hydra and tidal, I found myself always leaning toward glitch sounds and the visual effects that matched them. Somehow, I found them to be clean and straightforward effects that everyone is familiar with. The reading was written in 2009-2010 by Rosa Menkman. I understand that at that time, people might have leaned toward “perfection” in technology by integrating sharper images, faster speeds, and invisible interfaces. However, since then, people have become more experimental with technology by playing around with glitches, noises, and colors. So, I believe that what she stated about bringing unfamiliarity and the unexpected through effects such as glitches is something we see very often today.

Menkman said that “The main subject of most glitch art is critical perception. Critical in this sense is twofold: either criticizing the way technology is conventionally perceived, or showing the medium in a critical state. Glitches release a critical potential that forces the viewer to actively reflect on the technology.” This made me realize that when I watch videos with glitches, they somehow make me concentrate more, as I start thinking about how and when the glitch is happening. I think this has a strong engagement effect on the audience. This solidifies that while watching glitch art, the audience perceives glitches without knowing how they came about, which gives them an opportunity to focus on their form to interpret their structures and learn more from what can actually be seen.

While reading, I also liked how the text was organized, with glitch effects added between sections and experiments with text indentation. This further reinforced what she is saying about breaking continuity and linearity. I also watched a video by the author where she experimented with glitch effects in many different ways. I realized that although I have used glitch effects before, I have never really explored them beyond simple techniques. This gave me new ideas on how I can use glitch effects in more creative ways.

Rosa Menkman’s Glitch Studies Manifesto is an interesting read but it can feel overwritten at times. That said one argument genuinely stuck with me and it was the idea that a glitch is not just a mistake but a moment that exposes what a technology actually is beneath its polished surface. When something breaks you suddenly see the system and its assumptions and limits. I think that framing makes a lot of sense.

Working in TidalCycles and Hydra I think about this a lot. When Im live coding and something goes wrong like a pattern fires off rhythm or a Hydra function produces something completely unexpected there is this brief moment of panic but also genuine curiosity. Like what just happened and why did it do that? Menkman would probably call that the acousmatic quality of glitch where you are confronted with an output you cannot fully trace back to a source. In my project I was deliberately layering tabla samples with glitchy electronic sounds and the tension between those two things felt like exactly what she was describing. I feel like the interruption becomes the point.

Where Im less convinced is her claim that intentional glitch art still counts as true glitch. I think once you are designing the error you have already domesticated it. There is a real difference between a glitch that surprises you and one that you planned. The shock is what makes it what it is.

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)

I gradually built up the piece from my first week’s demo and wanted to experiment combining acoustics with electronics. I used mostly built-in sound sources, and it mainly consists of two major parts, yet it does not follow a strict structure. Starting with a piano loop that kind of feels nostalgic, I started to add more electronic sounds that keep getting layered on top of one another. Then it transitions to the second stage where it felt like expanding, gradually getting more chaotic when some random piano is added. Eventually it vanishes into a supersine cluster sound.

tidal:


piano_opening1 = slow 1.5
  $ n "c4 g4 d5 ds5 [d5,bf5] ~ ~ ~ ~ ~ ~ ~ c6 ~ ~ ~"
  |+ n 7
  # s "superpiano"
  # velocity "0.8 0.6 0.75 0.45 0.5 ~ ~ ~ ~ ~ ~ ~ 0.7 ~ ~ ~"
  # detune 0.1
  # gain 0.7
  # lpf 2000
  # lpq 0.2         -- filter smooth
  # sustain 5
  # room 0.95
  # size 0.7
  # pan (slow 4 sine)

piano_opening2 = slow 1.5 $ n "f4 a4 d5 ds5 f5 ds5 d5 a4 g5 ~ ~ ~ a5 ~ ~ ~"
   |+ n 7
   # detune 0.1
    # s "superpiano"
    # velocity "0.8 0.6 0.55 0.45 0.5 0.45 0.35 0.6 ~ ~ ~ 0.7 ~ ~ ~"   --strike
    # gain 0.8
    # lpf 2000
    # lpq 0.2         -- filter smooth
    # sustain 5
    # room 0.95
    # size 0.7
    # pan (slow 4 sine)

hush

d1 $ piano_opening1
d1 $ piano_opening2

d1 $ qtrigger $ filterWhen (>=0) $ seqP [
   (0, 3, slow 1.5 $ n "c4 g4 d5 ds5 [d5,bf5] ~ ~ ~ ~ ~ ~ ~ c6? ~ ~ ~"
     |+ n 7 # velocity "0.8 0.6 0.75 0.45 0.5 ~ ~ ~ ~ ~ ~ ~ 0.7? ~ ~ ~"),
  (3, 6, slow 1.5 $ n "f4 a4 d5 ds5 f5 ds5 d5 a4 g5 ~ ~ ~ a5 ~ ~ ~"
     |+ n 7 # velocity "0.8 0.6 0.75 0.45 0.5 0.45 0.35 0.6 ~ ~ ~ 0.7 ~ ~ ~")
 ]
 # s "superpiano"
 # detune 0.1
 # gain 0.8
 # lpf 2000
 # lpq 0.2
 # sustain 2
 # room 0.8
 # size 0.9
 # pan (slow 4 sine)

d1 silence

hush

d1 silence

d2 $ slow 2 $ n "[a6|e6]*8"
  |+ n 5
  # detune 1.2
  # gain 0.4
  # s "supersaw"
  # decay 0.2
  # sustain 5
  # distort 1.2

d2 silence

d5 $ jux (rev) $
  struct "t*16?" $
  n (irand 36 + 24)
  # s "supervibe"
  # bandf (range 500 8000 $ rand) 
  # bandq 15
  # hpf (range 0 2000 $ rand)
  # sustain 0.05
  # detune 1.2
  # room 0.8 # size 0.9
  # gain (range 0.3 0.5 $ rand)
  # pan rand
  # squiz 5

d5 silence

d3 $ s "superstatic*16"
    # n (irand 12)
    # sustain 0.01
    # accelerate 20
    # pitch1 2000
    # room 0.9
    # gain (range 0.15 0.3 $ rand)

d3 silence

d4 $ slow 4 $
    n "c4 g4 d5 f5"
    |+ n 5
    # s "supersiren"
    # sustain 8
    # voice 0.3
    # hpf 500
    # lpf 2000
    # detune 0.2
    # room 0.9 # size 0.9
    # gain 0.4 
    # distort 2.0
    

d4 silence
d1 silence


d7 $ slow 4 $ s "moog:2"
  >| note (scale "<minor>" ("[<-7>,0,2]*<1>") + "[c5,c6]")
  # legato 1
  # lpf 500
  # lpfbus 1 (segment 64 (slow 4 (range 100 3000 saw)))
  # lpq 0.4
  # gain 0.4

d7 silence

d8 $ fast 4 $ sometimesBy 0.4 (shuffle 8) $ s "simplesine"
  >| note ((scale "pelog" "<-2 .. 10>"))
  # hpf 1200
  # lpf 3000
  # room 0.4
  # gain 0.5

d8 silence

hush

  d1 silence

 d10 $ qtrigger $ filterWhen (>=0)
   $ cat [
       repeatCycles 2 $ scramble 8 $ n "c4 g4 d5 ds5 [d5,bf5] ~ ~ ~ ~ ~ ~ ~ c6? ~ ~ ~"
         |+ n 7 # velocity "0.8 0.6 0.75 0.45 0.5 ~ ~ ~ ~ ~ ~ ~ 0.7? ~ ~ ~",
       repeatCycles 2 $ scramble 8 $ n "f4 a4 d5 ds5 f5 ds5 d5 a4 g5 ~ ~ ~ a5 ~ ~ ~"
         |+ n 7 # velocity "0.8 0.6 0.75 0.45 0.5 0.45 0.35 0.6 ~ ~ ~ 0.7 ~ ~ ~"
   ]
   # s "superpiano"
   # detune 0.1 # gain 0.7 # lpf 2500 # sustain 2 # room 0.9 # size 0.9 # pan 0.4

d10 silence

 d11 $ qtrigger $ filterWhen (>=0)
   $ cat [
       repeatCycles 2 $ scramble 8 $ fast 2 $ n "c4 g4 d5 ds5 [d5,bf5] ~ ~ ~ ~ ~ ~ ~ c6? ~ ~ ~"
         |+ n 19 # velocity "0.8 0.6 0.75 0.45 0.5 ~ ~ ~ ~ ~ ~ ~ 0.7? ~ ~ ~",
       repeatCycles 2 $ scramble 8 $ fast 4 $ n "f4 a4 d5 ds5 f5 ds5 d5 a4 g5 ~ ~ ~ a5 ~ ~ ~"
         |+ n 19 # velocity "0.8 0.6 0.75 0.45 0.5 0.45 0.35 0.6 ~ ~ ~ 0.7 ~ ~ ~"
   ]
   # s "superpiano"
   # detune 0.1 # gain 0.6 # lpf 2500 # sustain 2 # room 0.5 # size 0.6 # pan 0.7

d11 silence

hush

hydra:

	shape(4, 0.7, 0.01)
  .color(0.6, 0.7, 1)
  .repeat(2, 2)
	.modulateScale(osc(3, 0.1).rotate(1.5), 0.5)
  .layer(
    src(o0)
      .mask(shape(4, 0.9, 0.5))
			.scale(() => 1.01 + (0.5* 0.05))
      .rotate(() => Math.sin(time * 0.1) * 0.02)
      .luma(0.2, 0.1)
  )
  .modulatePixelate(
    noise(20, 0.5),
		() => 0.5 * 1024
  )
	.brightness(() => -0.15 + (0.5 * 0.1))
  .contrast(1.2)
  .scrollX(() => Math.sin(time * 0.2) * 0.05)
  .out();

	shape(4, 0.7, 0.01)
	  .color(0.6, 0.7, 1)
	  .repeat(2, 2)
	  .contrast(1.5)
	  .modulateScale(osc(3, 0.1).rotate(() => time * 0.2), 0.5)
	  .layer(
	    src(o0)
	      .mask(shape(4, 0.9, 0.5))
	      .scale(() => 1.01 + Math.sin(time) * 0.02)
	      .rotate(() => Math.sin(time * 0.1) * 0.05)
	      .luma(0.2, 0.1)
	  )
	  .modulatePixelate(
	    noise(20, 0.5),
	    () => [1024, 512, 128, 2048][Math.floor(time % 4)]
	  )
	  .brightness(() => -0.15 + Math.random() * 0.05)
	  .hue(() => Math.sin(time * 0.05) * 0.1)
	  .scrollX(() => Math.sin(time * 0.2) * 0.05)
	  .out();

hush()

In my composition project, I tried to work with different strcuture to craft a pience, but I find out dispite having a st

I recently worked on a live-coding piece where I ne main build and then started another. Figuring out how to bring it to a proper ending turned out to be harder than I expected. I tried fading elements in and out, layering piano, bass, and percussion, and even syncing chords with claps using MIDI—but it never quite lined up the way I imagined.

Some parts worked better than others, and the misalignments actually gave the piece some unexpected character. It was a good reminder that live coding isn’t just about making things “perfectly in sync”—it’s about experimenting, feeling how layers interact, and learning from what doesn’t go as planned.

Even though the final MIDI sync didn’t work out, the process taught me a lot about structure, timing, and how to play with musical ideas in real time.


start = do{
d1 $ qtrigger $ filterWhen (>=0) $ seqP [
(3,6, s "hh*1 hh*2 ~808:3" # gain (slow 4 (range 1.25 1.5 saw))),
(6,8,  s "[808mc:1(5,8), hh*1? hh*2 ~808:3]" # gain (slow 4 (range 1.25 1.5 saw))),
(8,30,  s "[<808mc:2(7,8) 808mc:1(5,8)>, hh*2? hh*4 ~808:3]" # gain (slow 4 (range 1.25 1.5 saw)))];
d6 $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,3, ccv "<0 31 64 127>" # ccn "0" # s "midi"),
    (3, 6, slow 2 $ ccv (segment 128 $ range 0 127 tri) # ccn "1" # s "midi"),
    (6, 8, struct "t(5,8)" $ ccv (segment 128 $ range 0 127 tri) # ccn "1" # s "midi"),
    (8, 30, struct "<t(7,8) t(5,8)>" $ ccv (segment 128 $ range 0 127 tri) # ccn "1" # s "midi"),
    (3,30, ccv "0 0 0 127" # ccn "0" # s "midi"),
    (5,8,struct "t(5,8)" $ ccv (range 127 0 tri) # ccn "3" # s "midi"),
    (8,30,struct "<t(7,8) t(5,8)>" $ ccv (range 127 0 tri) # ccn "3" # s "midi"),
    (4, 50, struct "~ ~ ~ t" $ ccv "<5  60>" # ccn "4" # s "midi")
    --(5, 9, fast 2 $ ccv "0 64 127 64" # ccn "1" # s "midi"),
    -- (9, 50, ccv (slow 2 $ range 0 127 saw) # ccn "1" # s "midi")
    ];
-- os there a way to fade the beats in
hush
d2 $ qtrigger $ filterWhen (>=0) $ slow 4 $ s "superpiano*4" # note "[c4,e4,g4,b4] [a3,c4,e4,g4] [f3,a3,c4,e4] [g3,b3,d4,a4] [d4,f4,a4,c5,e5]"+"c3" # legato 2.8 # room 0.8 # lpf (range 600 800 (slow 4 saw))
# speed (range 1.995 3.005 (slow 10 saw)) # pan (range 3 9 (slow 10 saw))

}
build =do{
  xfade 2 $ qtrigger $ filterWhen (>=3) $ s "superpiano*8" # note "[c4,e4,g4,b4]  [a3,c4,e4,g4] <[f3,a3,c4,e4] [g3,b3,d4,a4]> [d4,f4,a4,c5,e5]"+"c3" # legato 2.8 # room 0.8 # lpf (range 600 800 (slow 4 saw))
  # speed (range 1.995 3.005 (slow 10 saw)) # pan (range 3 9 (slow 10 saw));
  d3 $ qtrigger $ filterWhen (>=0) $ seqP[
  (0,5, s "tabla*8" # n (irand 12) # room "0.4" # hpf 300),
  -- (1,5, every 8 (fast 0.1) $ s "tabla2*8" # n (irand 46) # room "0.4"),
  (5, 15, stack [s "tabla*8" # n (irand 12) # room "0.4",
  s "jungbass*5" # note "1 0 1 0 0" # speed 0.25 # room 0.7]),
  (15, 30, s "jungbass*8" # note "1 0 1 0 0" # speed 0.8# room 0.8 # gain 2)];
}



build2=do{
  xfade 1 $ qtrigger $ filterWhen (>=0) $ s "[808sd:7*3, <808bd:3*2, 808bd:1*4>, hh*2]" # room "0.25" # nudge 0.2 # speed (range 1 1.5 (slow 2 saw))# gain 2;
  d2 $  qtrigger $ filterWhen (>=0) $ seqP[
  (0,5, s "superhoover">| note (scale "major" "<[0 4 0] [0 6 0]>" + "c4")# room 0.8 # gain 0.8 # legato 2.5 #speed (range 1.4 1.5 (slow 2 saw)) #lpf 400),
  (5,15,  s "superhoover">| note (scale "major" "<[0 5 6] [0 7 0]>" + "c4")# room 0.8 # gain 0.8 # legato 2.5 #speed (range 1.4 1.5 (slow 2 saw)) #lpf 500),
   (15,20, s "superhoover">| note (scale "major" "<[0 6 7] [7 6 0]>" + "c4")# room 0.8 # gain 0.8 # legato 2.5 #speed (range 1.4 1.5 (slow 2 saw)) #lpf 600)
   ] # hpf (slow 4 (100*saw + 100)) # speed (slow 4 (range 1 4 saw));
   d6 $ qtrigger $ filterWhen(>=0) $ seqP[
   (0,15, ccv (range 0 64 tri) # ccn "1" # s "midi"),
   (0,30, ccv (range 0 32 tri) # ccn "2" # s "midi")]    
 }


hush

start

build

do
  xfade 1 silence
  xfade 2 silence


  xfade 6 silence

build2

xfade 3 silence

xfade 1 silence

hush

shape(3, () => 0.1 + cc[1] * 0.2, 0.2).rotate(() => cc[0] * 3.14)
.invert(0.9).modulatePixelate(noise(()=>2+cc[3]3, 0.5), 100, 1).color(0.65,0.86,()=>2-cc[4]5).scale(1,()=>window.innerHeight/window.innerWidth,1).out()

shape(3, () => 0.1 + cc[1] * 0.2, 0.2)
.repeat(2, 2)
.rotate(() => cc[0] * 3.14)
.modulatePixelate(noise(() => 2 + cc[3]*3, 0.5), 100, 1)
.invert(0.9)
.color(
() => 0.65 + Math.sin(time) * 0.1,
() => 0.86 + Math.cos(time*1.2) * 0.1,
() => 2 - cc[4]*5
)
.repeatX(4) // 4 across
.repeatY(2) // 2 d
.scale(1, () => window.innerHeight/window.innerWidth, 1)
.out()

  // reactive Hydra visual for build2
osc(30, () => cc[1], 0)                                      
  .modulatePixelate(
    shape(4, 0.9)                                             
      .rotate(() => cc[1] * Math.PI),                        
    100, 1                                                  
  )
  .repeat(8, 8)                                               
  .color(3,5,8)                                                                                                               // green multiplier                                                         
  .hue(() => cc[2]*0.2)                                      
  .colorama(() => cc[2]*0.8)                                  
  .blend(o0, 0.5)                                             
  .out(o0)                                                   


osc(30, ()=>cc[0], 0).modulatePixelate(shape(4, 0.9).rotate(() => cc[2] * 3.14)).repeat(8, 8).color(3,5,8).hue(()=>cc[1]*0.2).colorama(() => cc[2] * 0.8).blend(o0,0.5).out()

“Matar” (مطر — Rain)

Audio/Visual Composition — TidalCycles + Hydra

Concept

Rain is very rare in the UAE desert, sometimes only 2 or 3 rainy days per year. When it comes, it is considered a blessing. This piece takes you through the full cycle of a rainstorm: from bright sun, to clouds forming, to a full storm with thunder and lightning, to wind clearing the sky, and finally the sun returning peacefully.

This is a 3-minute audio/visual composition about a UAE rainstorm, built with TidalCycles and Hydra.

The piece has 7 sections that follow the story of rain:

A (sun slow) → B (sun bright) → C (clouds form) → D (storm) → E (wind) → F (sun returns) → G (fade out).

Each section adds or removes sound layers and switches the Hydra visuals automatically through MIDI. The audio uses hijaz and bayati scales with tabla for an Arabian feel, and bubble samples for rain, wind samples, and a low 808 kick for thunder. The visuals show a sun that pulses with the drums, clouds that grow, rain streaks falling, trees swaying in the wind, and the sun returning at the end.

Video:

Tidal Code block :



setcps (85/60/4)


sunTone = struct "t(3,8)" $ s "simplesine" >| note (scale "hijaz" "<0 3 5 0>" + "c5") # gain 0.75 # room 0.7

sunBright = struct "t(5,8)" $ sometimesBy 0.2 (shuffle 4) $ s "simplesine" >| note (scale "hijaz" "<0 3 5 7 3>" + "c5") # gain 0.8 # room 0.6

sitar1 = slow 4 $ s "sitar" # n (irand 8) # gain 0.5 # room 0.85 # speed 0.75

drumSlow = every 4 (# n "30 20 10 6") $ s "tabla2(3,8)" # n "2 12 20" # gain 0.75 # room 0.6

drumFast = sometimesBy 0.3 (# speed "1.5 0.8 2") $ s "tabla2(5,8)" # n "3 7 12 20 5" # gain 0.8 # room 0.5

cloudStart = s "bubble(3,16)" # n (irand 8) # gain 0.7 # room 0.7 # speed 0.6

cloudGrow = s "bubble(5,8)" # n (irand 8) # gain 0.75 # room 0.6 # speed "<0.6 0.8 1 0.5>" # lpf (range 800 4000 $ slow 4 saw)

cloudDrum = s "tabla2(3,8)" # n "5 15 25" # gain 0.7 # room 0.5 # speed 0.9

waterDrop = degradeBy 0.2 $ s "bubble*8" # n (irand 8) # gain 0.6 # room 0.8 # speed (range 0.4 1.2 rand)

waterHeavy = s "bubble*16" # n (irand 8) # gain 0.65 # room 0.85 # speed (range 0.3 1 rand)

windCont = s "wind:3" # gain 0.75 # room 0.5 # cut 1 # legato 2

windGust = s "wind:5 wind:3" # gain 0.85 # room 0.4 # cut 2 # legato 2 # speed 1.2

thunder = s "808bd:4(3,8)" # gain 1.1 # room 0.9 # lpf 300 # speed 0.5 # krush 3

stormTab = s "[tabla2*7, tabla2*5]" # n (irand 30) # gain 0.7 # room 0.35

stormMel = fast 2 $ s "simplesine" >| note (arp "pinkyup" (scale "bayati" "[0,1,5,8]" + "<0 -3 2 4>") + "c5") # gain 0.55 # room 0.5 # lpf (range 400 3500 $ slow 2 sine) # pan (slow 3 sine)

earth = slow 4 $ s "simplesine" >| note "c3" # gain 0.35 # lpf 400 # room 0.95

birds = slow 8 $ s "birds" # n (irand 10) # gain 0.55 # room 0.8

endMel = slow 2 $ s "simplesine" >| note (arp "converge" (scale "hijaz" "[0,3,5]" + "<0 4>") + "c5") # gain 0.45 # room 0.9 # delay 0.4 # delaytime 0.3 # delayfeedback 0.4


sec1 = do {
  d1 $ sunTone;
  d2 $ drumSlow;
  d3 $ sitar1;
  d4 silence;
  d5 $ ccv 0 # ccn 0 # s "midi";
  d6 $ ccv (stitch "t(3,8)" 60 15) # ccn 1 # s "midi";
  d7 $ ccv (stitch "t(3,8)" 90 0) # ccn 2 # s "midi"
}


sec2 = do {
  d1 $ sunBright;
  d2 $ drumFast;
  d3 $ sitar1 # gain 0.35;
  d4 silence;
  d5 $ ccv 1 # ccn 0 # s "midi";
  d6 $ ccv (stitch "t(5,8)" 90 25) # ccn 1 # s "midi";
  d7 $ ccv (stitch "t(5,8)" 110 0) # ccn 2 # s "midi"
}


sec3 = do {
  d1 $ sunTone # gain 0.25;
  d2 $ stack [cloudStart, cloudDrum];
  d3 $ cloudGrow;
  d4 $ stack [windCont # gain 0.3, waterDrop # gain 0.3];
  d5 $ ccv 2 # ccn 0 # s "midi";
  d6 $ ccv (segment 32 (range 20 100 saw)) # ccn 1 # s "midi";
  d7 $ ccv (stitch "t(3,8)" 70 0) # ccn 2 # s "midi"
}

sec4 = do {
  d1 $ thunder;
  d2 $ stormTab;
  d3 $ stack [waterHeavy, stormMel];
  d4 $ windCont;
  d5 $ ccv 3 # ccn 0 # s "midi";
  d6 $ ccv (stitch "t(7,8)" 110 40) # ccn 1 # s "midi";
  d7 $ ccv (stitch "t(3,8)" 100 0) # ccn 2 # s "midi"
}



sec5 = do {
  d1 $ earth;
  d2 silence;
  d3 $ waterDrop # gain 0.2;
  d4 $ windGust;
  d5 $ ccv 4 # ccn 0 # s "midi";
  d6 $ ccv (segment 32 (range 80 20 saw)) # ccn 1 # s "midi";
  d7 $ ccv 0 # ccn 2 # s "midi"
}



sec6 = do {
  d1 $ slow 2 $ sunTone # gain 0.5 # room 0.9;
  d2 $ drumSlow # gain 0.5;
  d3 $ birds;
  d4 silence;
  d5 $ ccv 5 # ccn 0 # s "midi";
  d6 $ ccv (segment 32 (range 40 10 saw)) # ccn 1 # s "midi";
  d7 $ ccv (stitch "t(3,8)" 50 0) # ccn 2 # s "midi"
}


sec7 = do {
  d1 $ endMel;
  d2 silence;
  d3 silence;
  d4 silence;
  d5 $ ccv 6 # ccn 0 # s "midi";
  d6 $ ccv (segment 32 (range 10 0 saw)) # ccn 1 # s "midi";
  d7 $ ccv 0 # ccn 2 # s "midi"
}


sec1
sec2
sec3
sec4
sec5
sec6
sec7
hush

Hydra code block :


hush()
navigator.requestMIDIAccess().then(function(m) { for (var i of m.inputs.values()) { i.onmidimessage = function(msg) { var arr = msg.data; cc[arr[1]] = arr[2] / 127.0; ccActual[arr[1]] = arr[2]; } } }); var cc = Array(128).fill(0.5); var ccActual = Array(128).fill(0);


loadScript('/Users/salemalshamsi/Desktop/liveCoding/COMPOSITION/matar_visuals_load.js')


visuals[0]()


var whichVisual = 0
update = () => { if (whichVisual != ccActual[0]) { whichVisual = ccActual[0]; if (whichVisual < visuals.length) { visuals[whichVisual]() } } }

Visual load code block :

visuals = [


  () => {
    solid(0.05, 0.03, 0.12).modulateRotate(noise(1, 0.005), 0.02).out(o2)
    shape(99, () => 0.12 + cc[2] * 0.08, 0.4).color(1, 0.85, 0.3).brightness(() => cc[2] * 0.3).out(o1)
    src(o2).layer(src(o1)).out(o0)
    render(o0)
  },


  () => {
    solid(0.08, 0.05, 0.15).modulateRotate(noise(1, 0.008), 0.03).out(o2)
    shape(99, () => 0.18 + cc[2] * 0.1, 0.5).color(1, 0.9, 0.4).brightness(() => cc[2] * 0.4).out(o1)
    gradient(0.3).color(0.9, 0.6, 0.2).mult(shape(99, 0.4, 0.6)).hue(() => Math.sin(time * 0.3) * 0.02).out(o3)
    src(o2).layer(src(o3).mult(solid(1,1,1), 0.15)).layer(src(o1)).out(o0)
    render(o0)
  },


  () => {
    solid(0.1, 0.1, 0.16).out(o2)
    shape(99, 0.05, 0.2).color(0.6, 0.5, 0.2).scrollY(-0.12).out(o1)
    noise(2.5, 0.04).color(0.8, 0.8, 0.85).thresh(() => 0.75 - cc[1] * 0.4, 0.12).modulate(voronoi(8, 0.02, 0.05), 0.02).scrollY(-0.1).out(o3)
    src(o2).layer(src(o1)).layer(src(o3).mult(solid(1,1,1), 0.75)).out(o0)
    render(o0)
  },


  () => {
    solid(0.05, 0.06, 0.15).out(o2)
    osc(100, 0, 0).thresh(0.9, 0.004).scrollY(0, 0.25).color(0.75, 0.78, 0.88).out(o1)
    noise(3, 0.06).color(0.4, 0.4, 0.48).thresh(0.4, 0.15).scrollY(-0.18).modulatePixelate(noise(5, 0.05).pixelate(20, 20), 512).out(o3)
    src(o0).diff(src(o2), 0.3).blend(src(o3), 0.06).layer(src(o1).mult(solid(1,1,1), 0.45)).brightness(() => cc[2] * 0.1).contrast(1.2).out(o0)
    render(o0)
  },


  () => {
    solid(0.22, 0.28, 0.35).out(o2)
    noise(2, 0.05).color(0.5, 0.52, 0.56).thresh(0.5, 0.12).scrollX(0, 0.1).scrollY(-0.2).out(o3)
    shape(3, 0.15, 0.02).color(0.15, 0.4, 0.12).rotate(() => Math.sin(time * 2) * 0.25).scrollY(0.22).kaleid(6).scale(0.5).scrollY(0.2).out(o1)
    src(o0).diff(src(o0).scale(0.998), 0.6).blend(src(o2), 0.04).layer(src(o3).mult(solid(1,1,1), 0.45)).layer(src(o1).luma(0.08, 0.02)).out(o0)
    render(o0)
  },


  () => {
    solid(0.12, 0.18, 0.32).out(o2)
    shape(99, 0.13, 0.4).color(1, 0.9, 0.5).brightness(0.15).scrollY(-0.18).out(o1)
    solid(0.25, 0.45, 0.18).mult(shape(4, 1, 0.01).scrollY(0.15)).out(o3)
    shape(3, 0.08, 0.01).color(0.15, 0.38, 0.1).scrollY(0.24).kaleid(4).scale(0.4).scrollY(0.18).out()
    src(o2).layer(src(o3).mult(solid(1,1,1), 0.55)).layer(src(o1)).layer(shape(3, 0.08, 0.01).color(0.15, 0.38, 0.1).scrollY(0.28).scrollX(-0.1).luma(0.08, 0.02)).layer(shape(3, 0.07, 0.01).color(0.15, 0.38, 0.1).scrollY(0.28).scrollX(0.12).luma(0.08, 0.02)).out(o0)
    render(o0)
  },


  () => {
    solid(0.03, 0.03, 0.06).out(o2)
    shape(99, 0.06, 0.5).color(0.7, 0.6, 0.3).brightness(-0.15).scrollY(-0.1).out(o1)
    src(o0).blend(src(o2), 0.1).layer(src(o1).mult(solid(1,1,1), () => 0.5 - time * 0.01)).saturate(0.6).out(o0)
    render(o0)
  }
]

whichVisual = 0