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

The approach I took to creating a composition was a reverse engineering build-up where I found sounds and combinations that I enjoy and after finding those who sounded cohesive joined them into a composition. I wanted to create a more whimsical or alien-like energy to the work when choosing the sounds that I liked as I noticed several of the dirt samples had a high-pitched noise that went well really together. There was a main part that I thought brought together the composition which ended up being my A that is repeated. With that I integrated the other parts, creating the pattern A-B-A-C pattern. I tried to experiment with several of the techniques we learnt in class to find which ones fit into my work which helped out a lot in getting a hang of them, I think the part I focused the most on was creating a visual and audio fade out which was initially a transition, but then ended up looking like a great way end the work on a high instead. Which you see at the end when the screen goes fades into fight with a rising sound matching the rise in brightness in part C.

Hydra code

render()

shape(100, ()=> 0.65-cc[3])
  .scale(1,1,() => window.innerWidth / window.innerHeight)
  .scroll(0.5,()=> -0.5+cc[1])
  .invert(()=>cc[0])
  .modulateKaleid(voronoi(55))
  .colorama(1.2).posterize(4).saturate(0.7).contrast(6)
  .blend(
    shape(4, 100),()=>cc[5]
  )
  .blend(osc(30,0.0001,0.75)
      .colorama(0.5)
      .mult(osc(20,0.0001,0.2).modulate(noise(3,1)).rotate(0.4))
      .modulateScrollY(osc(2)).modulate(osc().rotate(),.011), ()=>cc[8]
  )
  .rotate(11,()=>cc[6]/127)
  .blend(shape(10,0.5).modulatePixelate(osc(25,0.5),100).colorama(0.5),()=>cc[7])
  .out(o0)

shape(100, ()=> 0.65-cc[3])
  .scale(1,1,() => window.innerWidth / window.innerHeight)
  .scroll(0.5,()=> -0.5+cc[1])
  .invert(()=>cc[0])
  .modulateKaleid(osc(55))
  .colorama(1.2).posterize(4).saturate(0.7).contrast(6)
  .blend(
    shape(4, 100),()=>cc[5]
  )
  .out(o0)

shape(100, ()=> 0.65-cc[3])
  .scale(1,1,() => window.innerWidth / window.innerHeight)
  .scroll(0.5,()=> -0.5+cc[1])
  .invert(() => 1 - cc[0])
  .color(() => 0.2 + cc[2], 0, 1)
  .modulateKaleid(osc(55),0.1,1)
  .blend(
    shape(4, 100),()=>cc[5]
  )
  .out(o1)


shape(100, ()=> 0.65-cc[3])
  .scale(1,1,() => window.innerWidth / window.innerHeight)
  .scroll(0.5,()=> -0.5+cc[1])
  .invert(() => 1 - cc[0])
  .color(() => 0.2 + cc[2], 0, 1)
  .modulateKaleid(osc(55),0.1,1)
  .blend(
    shape(4, 100),()=>cc[5]
  )
  .out(o2)

shape(100, ()=> 0.65-cc[3])
  .scale(1,1,() => window.innerWidth / window.innerHeight)
  .scroll(0.5,()=> -0.5+cc[1])
  .invert(()=>cc[0])
  .modulateKaleid(osc(55),0.1,1)
  .colorama(1.2).posterize(4).saturate(0.7).contrast(6)
  .blend(
    shape(4, 100),()=>cc[5]
  )
  .out(o3)

hush()

Tidal Code

--A
d1 $ stack[
  s "bass1 ~ <bass1 dr_few:2> ~" # room 0.4,
  s "bd bd*4 bd ~" # room 2,
  s "hh*8" # gain 0.75,
  ccv "0 127" # ccn "0" # s "midi",
  ccv (segment 128 $ range 0 127 saw) # ccn "1" # s "midi",
  s "feelfx*8" # note (scale "major" "1 1 3 5"-24) # room 1,
  s "tink:1 tink:2 tink:4 tink:5" # room 2,
  ccv "0 30 60 127" # ccn "2" # s "midi",
  ccv "0 60" # ccn "8" # s "midi"
]

xfade 1 silence

--B
d1 $ stack [
  ccv "60" # ccn "8" # s "midi",
  s "pluck:2 pluck:3",
  ccv "0 127" # ccn "6" # s "midi"
]

d1 $ qtrigger $ seqP [
  (0, 10, ccv "0 127" # ccn "6" # s "midi"),
  (0, 10, ccv "0 0 0 60 60 0 0 0" # ccn "7" # s "midi"),
  (0, 10, ccv 0 # ccn "8" # s "midi"),
  (0, 4, s "feelfx*8" # note (scale "sine" "0 0 0 2 2 0 0 0"-24) # room 0.8),
  (0, 4, s "pluck:2 pluck:3" # distort 0.2 # room 0.8),
  (4, 6, s "feelfx*8" # note (scale "sine" "0 0 0 2 2 0 0 0"-24) # room 0.6),
  (4, 6, s "pluck:2 pluck:3" # distort 0.2 # room 0.6),
  (6, 8, s "feelfx*8" # note (scale "sine" "0 0 0 2 2 0 0 0"-24) # room 0.4),
  (6, 8, s "pluck:2 pluck:3" # distort 0.2 # room 0.4),
  (8, 10, s "feelfx*8" # note (scale "sine" "0 0 0 2 2 0 0 0"-24) # room 0.2),
  (8, 10, s "pluck:2 pluck:3" # distort 0.2 # room 0.2)
]

--A

d2 $ stack[
  s "bass1 ~ <bass1 dr_few:2> ~" # room 0.4,
  s "bd bd*4 bd ~" # room 2,
  s "hh*8" # gain 0.75,
  ccv "0 127" # ccn "0" # s "midi"
]

d1 $ stack[
  ccv (segment 128 $ range 0 127 saw) # ccn "1" # s "midi",
  s "feelfx*8" # note (scale "major" "1 1 3 5"-24) # room 1,
  s "tink:1 tink:2 tink:4 tink:5" # room 2,
  ccv "0 30 60 127" # ccn "2" # s "midi"
]

--C

d2 $ stack [
  "reverbkick!4" # room 1.2,
  "realclaps*8" # room 1,
  fast 8 $ ccv (segment 128 $ range 0 127 tri) # ccn "3" # s "midi"
]


d1 $ qtrigger $ filterWhen (>0) $ seqP [
  (0, 2, s "juno:9" # room 0.2),
  (2, 4, s "juno:9" # room 0.65),
  (4, 6, s "juno:9" # room 0.85),
  (6, 8, s "juno:10" # room 1),
  (6, 10, slow 4 $ ccv (segment 128 $ range 0 127 saw) # ccn "5" # s "midi"),
  (8, 10, fast 2 $ s "juno:9*16" # room 1.2)
]

xfade 2 silence

hush

d1 $ stack [
  ccv 0 # ccn "0" # s "midi",
  ccv 0 # ccn "1" # s "midi",
  ccv 0 # ccn "2" # s "midi",
  ccv 0 # ccn "3" # s "midi",
  ccv 0 # ccn "4" # s "midi",
  ccv 0 # ccn "5" # s "midi",
  ccv 0 # ccn "6" # s "midi",
  ccv 0 # ccn "7" # s "midi",
  ccv 0 # ccn "8" # s "midi"
]

Demo

I originally had a very different idea in mind for my composition project, but after everything happening around us, I found myself lacking inspiration and creativity. To combat that, I decided to go through the dirt samples again. I went back to our class basics and ran lines on the class examples of week 2. This led me to combine sounds I liked and then figure out how to put them together into a nice beat. I was aiming for something groovy. A lot of my process involved trying to sound out a tune I like, then trying to translate that into Tidal.

I think a lot of the time in class we tend to shift towards more EDM or Tech music, but I found myself enjoying myself more with groovier beats as they sound more like songs I often listen to. After I had almost finalized my sounds, I needed to tackle visuals. For my visuals, I was thinking of contrasts, and one of the artists that I listen to, Kaytranada, tends to have album covers with a lot of contrast, so that was something I wanted to incorporate.

As for song structure, I would say I followed A-B-C-A, but I wouldn’t say I have a classic build or drop within my composition. I was kind of testing the different sounds until I found something I liked listening to, essentially playing it by ear, mostly. Every time I attempted the classic build, then drop structure, I felt like it was too generic, and I thought that might’ve been due to me not listening to a lot of EDM, so I decided to do a composition with a music style I am more familiar with, and would enjoy playing around with more.

Tidal Code:

--a 
d1 $ slow 3 $ sound "[bd sn sn][bd bd sn]" # gain 0.7 # room 0.5
d7 $ ccv "[0 20 64 127]" # ccn "0" # s "midi"

d3 $ struct "t(3,8)" $ sound "hc*4" # gain 0.7 # room 0.4
d9 $ struct "t(3,8)" $ ccv "[0 64 127 64]" # ccn "1" # s "midi"

d2 $ slow 2 $ s "padlong" # gain 0.5


d4 $ s "pluck" <| n (run 8) # gain 0.8 # room 0.4
d8 $ ccv "[0 20 20 64 64 127]" # ccn "2" # s "midi"

--b
d1 $ fast 2 $ sound "bd*4" # gain 0.7  # room 0.4
d7 $ fast 2 $ ccv "[127 0 127 0]" # ccn "0" # s "midi"

d2 $ sound "sn*4" # gain 0.7 # room 0.7
d9 $ struct "t(3,8)" $ ccv "[127 127 0 127]" # ccn "1" # s "midi"

d3 $ struct "t(3,8)" $ sound "hc*8" # gain 0.7 # room 0.4
d9 $ struct "t(3,8)" $ ccv "[64 127 64 127]" # ccn "1" # s "midi"

d6 $ struct "t(3,8)" $ sound "bass3" <| n "[c2 c2 c2 c2]" # gain 0.7 # room 0.9
d11 $ struct "t(3,8)" $ ccv "[0 127 0 127]" # ccn "3" # s "midi"

d4 $ s "pluck" <| n (run 11) # gain 0.9 
d8 $ struct "t(3,8)" $ ccv (segment 8 (range 0 127 saw)) # ccn "2" # s "midi"

d5 $ s "msg" <| n (run 4) # gain 0.9 # room 0.4


-- c
d1 $ slow 3 $ sound "[bd sn sn][bd bd sn]" # gain 0.6 # room 0.5
d7 $ ccv "[0 20 0 20]" # ccn "0" # s "midi"

d2 $ struct "t(3,8)" $ sound "hc*4" # gain 0.6 # room 0.4
d9 $ struct "t(3,8)" $ ccv "[0 127 0 127]" # ccn "1" # s "midi"

-- a
d3 $ slow 2 $ s "padlong" # gain 0.5
d10 $ ccv "[64 127 64 0]" # ccn "3" # s "midi"

d4 $ s "pluck" <| n (run 8) # gain 0.8 
d8 $ ccv (segment 8 (range 0 127 saw)) # ccn "2" # s "midi"

d6 silence 
d5 silence


hush

Hydra Code:

osc(() => 150 + cc[0]*50, 0.05 + cc[3]*0.05, 1)
  .rotate(() => time*0.5 + cc[3]*0.2)      
  .scale(() => 1 + cc[1]*0.5)             
  .color(() => cc[0], () => cc[1], () => cc[2])
  .modulate(
    noise(() => cc[0]*10 + cc[2]*5 + cc[3]*5, 0.3)
  )  .layer(
    osc(() => 80 + cc[2]*40, 0.1, 1)
      .luma(() => cc[1]*0.8 + cc[3]*0.3, 0.05)
      .pixelate(() => 2 + cc[0]*15, () => 2 + cc[1]*15)
      .color(() => cc[0], 0.5, () => cc[1])
      .modulate(noise(() => (cc[0]+cc[1])*8 + cc[3]*3, 0.25))
  )
  .layer(
    noise(() => cc[1]*8 + cc[3]*5, 0.15)
      .pixelate(() => 3 + cc[2]*15, () => 3 + cc[0]*15)
      .color(() => cc[2], () => cc[0], () => cc[1])
      .modulate(
        osc(20, 0.1, 1).luma(() => cc[3]*0.8 + cc[2]*0.2, 0.05)
      )
  )
  .modulate(
    osc(10 + cc[3]*20, 0.02 + cc[3]*0.05, 1)
      .rotate(time*0.2 + cc[3]*0.2)
      .modulate(noise(time*0.2, 0.2 + cc[3]*0.1))
  )
  .contrast(1.8 + cc[3]*0.5)
  .saturate(1.6 + cc[3]*0.5)
  .blend(o0, 0.6 + cc[3]*0.3)
  .out(o0)


hush()

Demo:

My composition is based on a more rave and kind of eerie style. The basic structure I have it follow is an intro where we bring in different elements, a breakdown, where everything goes silent and only a synth remains, that is followed by a little buildup and dropping everything back in. After letting that play for a while , each element is removed until all sounds are gone. The visuals based on different variations of the voronoi effect with different parameters being changed by the midi notes throughout the composition. I utilized darker and more muted colors as i thought it fit with the eerie vibe of the composition more. When the beat drops, a oscillator is applied over the original voronoi with some additional parameters that results in a sort of glitchy effect where there are pauses between the showing of the visual.

For this composition I created an audiovisual piece using TidalCycles for sound and Hydra for visuals.

The piece is structured into five sections:

intro

buildup

breakdown

beatdrop

outro

Each of them are triggered manually in Tidal by evaluating a named do block. The sound is built around tabla samples layered with glitch percussion, with each section adding or removing layers to create a sense of tension and release. The visual side was built in Hydra with four scenes that match each compositional section. I chose tabla specifically because I wanted to bring in a sound that felt personal and culturally grounded and pairing it with glitch electronics felt like an interesting contrast between something organic and something digital.

Composition Video:

Code Snippet:

setcps (130/60/4)

intro = do
 d1 $ slow 2 $ degradeBy 0.6 $ s "tabla" # n (irand 4) # gain 0.8 # room 0.95 # size 0.9 # speed 0.5
 d2 $ degradeBy 0.8 $ s "glitch" # crush 12 # gain 0.6 # pan rand
 d3 $ s "space" # gain 0.5 # room 0.5 # size 0.5 # speed 0.5
 d8 $ ccv 0 # ccn 0 # s "midi"

buildup = do
 d1 $ s "tabla*2" # n (irand 8) # gain 1.0 # room 0.6 # speed (choose [1, 1.5, 0.75])
 d2 $ whenmod 4 3 (stutter 2 0.25) $ s "glitch*4" # crush 8 # gain 0.75 # pan rand
 d3 $ every 4 (fast 2) $ s "tabla" # n (irand 8) # gain 0.9 # room 0.8 # speed 0.75
 d4 $ degradeBy 0.8 $ s "glitch" # crush 6 # gain 0.7 # speed (choose [1, 2])
 d8 $ ccv 42 # ccn 0 # s "midi"

breakdown = do
 d1 $ slow 2 $ degradeBy 0.4 $ s "tabla" # n (irand 4) # gain 1.1 # room 0.95 # size 0.9 # speed (choose [0.5, 0.75])
 d2 $ whenmod 8 7 (density 4) $ s "glitch*2" # crush 4 # gain 0.85 # pan rand
 d3 $ silence
 d4 $ every 2 (# speed 0.5) $ s "glitch" # crush 3 # gain 0.9 # room 0.7
 d8 $ ccv 84 # ccn 0 # s "midi"

beatdrop = do
 d1 $ s "tabla*4" # n (irand 16) # gain 1.3 # room 0.2 # size 0.3 # speed (choose [1, 1.5, 2, -1])
 d2 $ whenmod 4 3 (stutter 4 0.125) $ s "glitch*8" # gain 0.9 # crush 6 # speed (choose [1, 2, -1]) # pan rand
 d3 $ every 3 (fast 2) $ s "tabla" # n (irand 16) # gain 1.1 # room 0.9 # size 0.8 # speed (choose [0.5, 1, 2])
 d4 $ whenmod 8 7 (density 4) $ s "glitch" # crush 8 # gain 0.8 # pan rand
 d5 $ fast 2 $ s "tabla*2" # n (irand 8) # gain 1.2 # crush 5 # speed (choose [1, -1, 2])
 d8 $ ccv 127 # ccn 0 # s "midi"

outro = do
 d1 $ degradeBy 0.7 $ slow 2 $ s "tabla" # n (irand 4) # gain 0.7 # room 0.95 # size 0.9 # speed 0.5
 d2 $ degradeBy 0.8 $ s "glitch" # crush 12 # gain 0.5
 d3 $ s "space" # gain 0.4 # room 0.5 # size 0.5 # speed 0.5
 d4 $ silence
 d5 $ silence
 d8 $ ccv 0 # ccn 0 # s "midi"

stop_it = do
 d1 $ silence
 d2 $ silence
 d3 $ silence
 d4 $ silence
 d5 $ silence
 d8 $ silence

intro
buildup
breakdown
beatdrop
outro
stop_it
ccActual = [0,0,0,0,0,0,0,0]
whichVisual = 0
visuals = [
  ()=>{noise(2,0.1).color(0.2,0.1,0.5).modulate(osc(4,0.01,0.5),0.2).scale(1,innerHeight/innerWidth).add(src(o0).scale(1.005).brightness(-0.02),0.92).out(o0)},
  ()=>{shape(()=>Math.floor(Math.sin(time)*4+5),0.3,0.02).scale(1,innerHeight/innerWidth).color(0.8,0.2,1).modulate(osc(20,0.05,2),0.4).rotate(()=>Math.sin(time*0.5)*3).add(src(o1).scale(0.99),0.85).out(o1);src(o1).blend(o0,0.3).out(o0)},
  ()=>{osc(60,0.1,3).color(1.5,0.2,0.8).pixelate(()=>Math.floor(Math.random()*32+4),()=>Math.floor(Math.random()*32+4)).modulate(noise(8,1.2),0.5).diff(src(o0).scale(1.005)).add(src(o0).brightness(-0.3),0.7).out(o0)},
  ()=>{noise(()=>Math.sin(time)*8+10,0.4).color(2,0.5,1.5).modulate(osc(30,0.2,1).rotate(()=>time*0.3),0.6).scale(1,innerHeight/innerWidth).add(src(o0).scale(1.008).rotate(0.02).color(1.5,0.8,2),0.92).out(o0)}
]
visuals[0]()
update = ()=>{
  if(whichVisual != ccActual[0]){
    whichVisual = ccActual[0]
    visuals[whichVisual]()
  }
}
navigator.requestMIDIAccess().then(midiAccess=>{
  midiAccess.inputs.forEach(input=>{
    input.onmidimessage=msg=>{
      const [status,cc,value]=msg.data
      if((status&0xf0)===0xb0){
        ccActual[cc]=Math.round(value/127*3)
      }
    }
  })
  console.log('MIDI connected!')
}).catch(err=>console.log('MIDI error:',err))