I really enjoy the sound of drums and low-pitched tones because they feel closer to a heartbeat. Throughout this project, I spent a lot of time searching for different low-pitched sounds to combine with each other. Initially, it was quite difficult to find the right combination because many of the sounds were too similar. To add more variation, I applied heavy distortion effects (using krush and squiz) to most of them. This helped create distinct textures and added more character to the overall composition.

I started the project using a Tidal file and then tried to connect the sound with Hydra. Since many of the music blocks were built from various rhythms, it was quite difficult to represent them visually in Hydra. One solution I came up with was to make each sound trigger a different visual change in Hydra. I especially enjoyed experimenting with basic shapes and movements, and I tried out different ways to make those shapes move in response to the sound.

It was quite challenging to bring everything together into a cohesive composition because I wasn’t sure how to create a strong drop. I ended up starting with a verse, which repeats a few times throughout the piece, then gradually layered in different drums and bass sounds to build the chorus. To create a bridge, I used a variation of the verse, which helped lead into the buildup and eventually the drop. I finished the piece by working backwards, transitioning from the drop back into the chorus, and ending with a softer, more minimal sound to bring the composition to a close.

Hydra code:

noise(20)
  .pixelate(50, 50) //()=>ccActual[4]
  .blend(
    osc(10, 0.001, 1)
      .hue(() => cc[4])
  ).blend(solid(), 0.5) //()=>cc[3]
  .out(o1)

gradient([1,2,4])
  .mult(osc(40, 0, 1).color(()=>cc[1]*2, ()=>cc[1], 1))
  .modulate(noise(()=>cc[1] + cc[0]*3))
  .brightness(0.4)
  .mask(shape(3, 0.2, 0.1).rotate(()=>cc[0]).scrollY(-0.25)) //()=>cc[2]/3
  .modulate(voronoi(25, 2, 0.5), 0.1)
  .add(
    shape(3, 0.2, 0.1) //()=>cc[2]/3
      .rotate(()=>(-(1-cc[0])))
      .color(()=>cc[1], ()=>cc[1], ()=>cc[1])
      .scrollY(0.25)
      .modulate(voronoi(25, 2, 0.5), 0.1)
  )
  .luma(0.05)
  .out(o0)

src(o1).layer(src(o2)).out(o0)

TidalCycle Code:

d1 $ slow 4 $ note "c3*4 d4*4 a3*8 g3*4" # s "superhammond:5" # legato 0.5
d4 $ ccv "[50 120] [50 120] [100 80 60 40] [50 120]" # ccn "0" # s "midi"

do
  d5 $ s "clubkick*4" # gain 0.8 # legato 1 # speed (slow 4 $ range 0.5 1 saw)
  d6 $ ccv "80 20 50 120" # ccn "1" # s "midi"

do
  d4 $ note "c3*2 d4*2 a3*4 g3*2" # s "arpy" # room 0.95 # gain 0.8 # speed "1.5 1"
  d3 $ ccv "80 40 [100 40] 120" # ccn "0" # s "midi"

do
  d1 $ s "~ cp" # gain 1.2 # room 0.5
  d4 $ s "<coins(3,8) hh(5,8,1)>" # room 1.2 # speed "2 1" # gain 1.3 # squiz 1.1 # up "-2"
  d3 $ struct "<t(3,8) t(5,8,1)>" $ ccv ((segment 128 (range 127 0 saw))) # ccn "0" # s "midi"

do
  d1 $ s "[glitch*4(3,8)]" # n (run 5) # vowel "a e i o" # room 0.45 # speed (slow 4 ("<2.5 1>")) # gain 1.2
  d6 $ ccv "[50 ~ ~ 120 ~ ~ 70 ~](3,8)" # ccn "0" # s "midi"
  d4 $ s "[sd <sd cp> ~ cp, hh*8]" # room 0.45 # speed (slow 4 ("<2.5 1>"))
  d7 $ ccv "50 <100 70> ~ 40" # ccn "1" # s "midi"

--verse 2 ADD cc[2] in hydra
do
  d1 $ degradeBy 0.4 $ s "808bd:1*8" # legato 1 # speed "1.5 1" # room 0.75
  d3 $ slow 4 $ note "c3*4 d4*4 a3*8 g3*4" # s "superhammond:5" # legato 0.5 # gain 1.1
  d4 $ ccv "[100 50] [100 50] [100 80 60 40] [100 50]" # ccn "2" # s "midi"
  d7 $ struct "t*8" $ ccv ((segment 128 (range 127 0 saw))) # ccn "0" # s "midi"
  d6 $ ccv "120" # ccn "1" # s "midi"

built_up = do {
  d3 $ qtrigger $ filterWhen (>=0) $ seqP [
  (0,1, s "[drum:5*4, hh*8]" # room 0.55),
  (1,2, s "[drum:5*4, hh*8]" # room 0.65),
  (2,3, s "[drum:5*4, hh*8]" # room 0.75),
  (3,4, s "[drum:5*4, hh*8]" # room 0.85),
  (4,5, s "[drum:5*4, hh*8]" # room 0.95)
] # speed (slow 5 (range 2 3 saw)) # gain (slow 5 (range 0.5 1.5 saw));
  d4 $ qtrigger $ filterWhen (>=0) $ seqP [
  (0, 5, struct "[t*50]" $ ccv (range 127 0 $ slow 5 saw) # ccn "3" # s "midi")
  ]
}

-- change hydra to cc[3]
built_up

bass = (stack[s "clubkick:5(3,8)", s "bassdm:22(3,8)"] # room 0.95 # speed ("<1 1.5>") # gain 1.2 # squiz 2 # up "-2" # krush 10)

do
  d2 $ bass
  d3 $ s "<bassdm:22(5,8) drumtraks:2(3,8,1)>" # room 0.95 # speed (slow 4 ("<1 1.5>")) # gain 1.1 # squiz 1.1
  d1 $ slow 4 $ note "c3*4 d4*4 a3*8 g3*4" # s "arpy:5" # legato 0.5 # gain 1.2
  d5 $ struct "<t(3,8) t(5,8,1)>" $ ccv ((segment 128 (range 127 20 saw))) # ccn "4" # s "midi"
  d4 $ ccv "[100 50] [100 50] [100 80 60 40] [100 50]" # ccn "2" # s "midi"

do
  d1 $ s "[<drumtraks:6(3,8)>, hh(5,8,1)]" # room 0.95 # krush 4 # speed (slow 4 ("<2 2.5>")) # up "-2"
  d2 $ s "stomp:5*4" # room 0.55 # krush 5 # speed (slow 4 "<2 1 1.5 2>")
  d3 $ struct "<t(3,8)>" $ ccv ((segment 128 (range 127 0 saw))) # ccn "2" # s "midi"
  d4 $ ccv "0 20 100 70" # ccn "0" # s "midi"

do
  d1 silence
  d5 $ s "clubkick*4" # gain 0.8 # legato 1 # speed (slow 4 $ range 0.5 1 saw)
  d6 $ ccv "80 20 50 120" # ccn "1" # s "midi"

do
  d4 $ note "c3*2 d4*2 a3*4 g3*2" # s "arpy" # room 0.95 # gain 0.8 # speed "1.5 1"
  d3 $ ccv "80 40 [100 40] 120" # ccn "4" # s "midi"

hush
d1 silence
d2 silence
d3 silence
d4 silence

Demo

Sorry, I can not get the embedding to work. Here is the link.

This is a version I did after class, with the right progression of the visuals:

This version is the spontaneous version; I played lines by lines without a specific order, the overall music sounds a little bit unstructured compared to the first video I posted.

For this version, I put everything into cycles with the purpose of timing everything rather than playing patterns one by one, so that’s why it’s a bit faster.

Inspiration:

My inspiration came a little bit randomly. A few days before the composition progress update, I stumbled upon this song from the electronic band Cash Cash called “How To Love” and the song, especially the synth riff, was stuck in my head for a while. I thought to myself, this riff sounds really cool and nostalgic, so let me try to create a composition piece inside TidalCycle based on it. Figuring out the code for the RHYTHM of the riff inside TidalCycle was challenging — it is easy to hum but not to construct them in codes — so I had to ask professor Aaron on Tuesday.

The time signature is a 4 4 so putting all the elements together was not too challenging. I enjoyed the process of writing the elements. The mixing, arranging, adding filters and effects part took me a lot of time. I had to make sure at least everything fit together and nothing gets left behind.

Hydra code — I experimented mainly with the concept of painting the canvas, from line to color:

solid().out()

s0.initImage("https://upload.wikimedia.org/wikipedia/commons/8/88/Hieronymus_Bosch_-_The_Garden_of_Earthly_Delights_-_Garden_of_Earthly_Delights_%28Ecclesia%27s_Paradise%29.jpg")
src(s0).out()

gradient(1)

.diff(src(s0),1)
.modulate(noise(()=>(cc[1])*4,.1))
.kaleid(2).kaleid(3)
.colorama (0.4)
.diff(noise(10,.10).thresh(.12,.12).rotate(()=>(cc[2])*14,.1))

.thresh(.2)

.out()

TidalCycles code — structured version:

hush
--40 80
--0 40 80 120
--0 20 40 60 80 100 127  

  d2 $ ccv "0 20 40 60 80 100 120 127" # ccn "1" # s "midi"
  d1 $ qtrigger $ filterWhen (>=0) $ seqP [
  --verse
  (0,16, s "arpy" >| note ((scale "major" "<[2@3 2@3 2@3 2@2 2@1 4@4] [1@3 1@3 1@3 1@2 1@2 4@4] [0@3 0@3 0@3 0@2 0@2 4@4] [-2@3 -2@3 -2@3 -2@2 -2@2 4@4]>")) # room 0.8 #lpf 1500),
  (4,23, s "~ hand:15 ~ hand:15" # gain 2 #room 0.1 #lpf 5000),
  (8,24, slow 4 $ s "superpiano" <| note "c'maj g'maj a'min f'sus2" #room 0.5),
  (16,24, s "superpiano" <| note "<[f'maj*4] [a'min*4] [g'maj*4] [g'maj*4]>" #room 0.1 #gain 1 #lpf 1500),
  (16,24, slow 4 $ s"superpiano" <|note "c6 c6 d6 g5" #room 0.1 # gain 1.5),
  (12,24, s "bassdm:14*4" #gain 1.5),
  (12,24, slow 2 $ sound "bassdm*4" #gain 1.5),

  --build-up
  (24,32, s "superpiano" <| note "<[f'maj*4] [a'min*4] [g'maj*4] [c'maj*4]>" #lpf 150 #gain 3),

  --riser-
  (24,29, s "bassdm:14*4" # room 0.5 #gain 1.5),
  (29,30, s "bassdm:14*8" # room 0.5 #gain 1.5),
  (30,31, s "bassdm:14*16" # room 0.5 #gain 1.5),
  (31,32, s "bassdm:14*32" # room 0.5 #gain 1.5),

  --drop
  (32,48, s "arpy" >| note ((scale "major" "<[2@3 2@3 2@3 2@2 2@2 4@4] [1@3 1@3 1@2 1@2 1@2 4@4] [0@3 0@3 0@3 0@2 0@2 4@4] [-1@3 -1@3 -1@3 -1@2 -1@2 4@4] [-2@3 -2@3 -2@3 -2@2 -2@2 4@4] [-1@3 -1@3 -1@3 -1@2 -1@2 4@4] [0 1 2 4 5] [4 5 7 8 7 8]>")) # room 0.8 #lpf 2000),
  (32,48, sound "clubkick:5*4" # room 0.5),
  (40,48, struct "<t(4,8) t(4,8)>" $ s "[arpy]" # note "<[c'maj*4] [g'maj*4] [a'min*4] [f'sus2*4]>" # gain 1.2 # orbit 5),
  (40,48, struct "<t(4,8) t(4,8,3)>" $ s "[reverbkick]" # note "f'maj a'min g'maj g'maj" #krush 0.5 # orbit 6 #speed 0.5)
]

TidalCycles code — unstructured version:

hush

  d10 $ ccv "40 80" # ccn "1" # s "midi"

do
  d1 $ s "arpy" >| note ((scale "major" "<[2@3 2@3 2@3 2@2 2@1 4@4] [1@3 1@3 1@3 1@2 1@2 4@4] [0@3 0@3 0@3 0@2 0@2 4@4] [-2@3 -2@3 -2@3 -2@2 -2@2 4@4]>")) # room 0.8 #lpf 1500

  d2 $ s "~ hand:15 ~ hand:15" # gain 2 #room 0.1 #lpf 5000

  d3 $ slow 4 $ s "superpiano" <| note "c'maj g'maj a'min f'sus2" #room 0.5

  d4 $ s "bassdm:14*4" #gain 1.5

  d5 $ slow 2 $ sound "bassdm*4" #gain 1.5

  d6 $ s "superpiano" <| note "<[f'maj*4] [a'min*4] [g'maj*4] [g'maj*4]>" #room 0.1 #gain 1 #lpf 1500

  d7 $ slow 4 $ s"superpiano" <|note "c6 c6 d6 g5" #room 0.1 # gain 1.5

d1 silence
d2 silence
d3 silence
d4 silence
d5 silence
d6 silence
d7 silence

    d11 $ ccv "0 40 80 120" # ccn "1" # s "midi"

do
  d1 $ s "superpiano" <| note "<[f'maj*4] [a'min*4] [g'maj*4] [c'maj*4]>" #lpf 150 #gain 3

  d2 $ s "bassdm:14*4" # room 0.5 #gain 1.5

  --riser--
  d3 $ qtrigger $ filterWhen (>=0) $ seqP [
  (0,1, s "bassdm:14*4" # room 0.5 #gain 1.5),
  (1,2, s "bassdm:14*8" # room 0.5 #gain 1.5),
  (2,3, s "bassdm:14*16" # room 0.5 #gain 1.5),
  (3,4, s "bassdm:14*32" # room 0.5 #gain 1.5),

  --buildup--
  (4,240, s "arpy" >| note ((scale "major" "<[2@3 2@3 2@3 2@2 2@2 4@4] [1@3 1@3 1@2 1@2 1@2 4@4] [0@3 0@3 0@3 0@2 0@2 4@4] [-1@3 -1@3 -1@3 -1@2 -1@2 4@4] [-2@3 -2@3 -2@3 -2@2 -2@2 4@4] [-1@3 -1@3 -1@3 -1@2 -1@2 4@4] [0 1 2 4 5] [4 5 7 8 7 8]>")) # room 0.8 #lpf 2000),
  (4,240, sound "clubkick:5*4" # room 0.5)]


    d12 $ ccv "0 20 40 60 80 100 127" # ccn "1" # s "midi"

  d4 $ struct "<t(4,8) t(4,8)>" $ s "[arpy]" # note "<[c'maj*4] [g'maj*4] [a'min*4] [f'sus2*4]>" # gain 1.2 # orbit 5

  d5 $ struct "<t(4,8) t(4,8,3)>" $ s "[reverbkick]" # note "f'maj a'min g'maj g'maj" #krush 0.5 # orbit 6 #speed 0.5

d1 silence
d2 silence
d3 silence
d4 silence
d5 silence

Composition Project Video: https://youtu.be/q6csr5kvDCk

Visual Code:

Sound Code:

Code – Part 1.

Code – Part 2.

I found this composition project particularly challenging, especially since we had to create a sound piece that evolves like a song while simultaneously developing visuals. Visuals, in particular, have always been a struggle for me. I think I got a bit blindsided by my motivation to create something that looked cool rather than ensuring it aligned with the overall vibe and tone of my sound.

In terms of the sound, the process was incredibly draining. I had structured the first section as the initial verse and the second section as the buildup, intending to include a transition between the two and then a beat drop after the buildup. However, I hit a wall—I was completely burnt out and couldn’t figure out a smooth way to transition between them. Eventually, I decided to make the second section the beat drop instead. That still left me struggling to find the right transition, though, because while the first and second sections felt similar in some ways, I also found them to be vastly different. I would just stare at my screen for hours, unsure of how to bridge them. Lines I initially planned to use for the transition ended up working better as supplementary elements for either section. In the end, I found that gradually fading out sounds one by one and then reintegrating and layering them into the second section was the best solution.

I knew that sound was my stronger suit, so I definitely put more time and effort into it. Looking back, I wish I had managed my time better so I could have balanced both the sound and visuals more equally. I also think the transition could still be improved—right now, when all the sounds in the second part are introduced, the superhoover sound is too overpowering, which diminishes the effect of a transition. Despite the challenges, I always find coding music really fun. That said, with all the midterm assignments piling up, I’m glad we’re getting a break from coding this week!

I started this project by focusing on the sound first and then creating visuals to match. I had a bunch of ideas—I wanted some acid 303s, amen break drums, and to incorporate elements from my first demo in class. But I also wanted it to have a techno feel. So, I built all these sounds and then started stitching them together into a composition.

The biggest challenge was that some of the sounds didn’t really fit together. To fix that, I made some ambient sounds and drums that suited the composition better, which ended up making the track slower than I originally planned. I was aiming for more of an ambient techno vibe—something faster. I also wanted to use the amen break throughout the whole track, but it didn’t quite fit, so I just included it right before the chorus.

For me, the defining sound of this piece is the 303s—I’m a huge fan of them. They have this raw, chaotic energy, which is what I love about them. That’s also why I wanted the visuals to feel chaotic. The visuals have three sections, all messy and intense, which was exactly what I was going for. I usually focus more on sound, but this time, I actually had more fun working on the visuals.

Overall I am very happy with the composition. As for the sound, the drop right now feels a little too “stiff” (if that makes sense) but I find it to be a good transition to the superhoover.

Here is the code:

Tidal

setcps(120/60/4)


start = fast 2 $ s "feelfx"
  >| note (scale "<india>" ("[<-7 -3 -1>,0,2]*<1>") + "[c1,c2]")
  #legato 1
  #end 0.3
  #lpf(segment(100/0.75) $ fast (8/0.75) $ range 200 400 $ sine) #lpq 0.3 #hpf 200

start2 = slow 4 $ swingBy (1/10) 8 $ s "<dbs*198 dbs*386 dbs*780>" # gain "[1 0.8 1.3 0.8]*4" #lpf (segment(100/0.75) $ fast (8/0.75) $ range 200 400 $ sine) # amp 2
hush
--drums
sdrums = stack[struct ("1 1 1 [1 0 <0 0 1 0> <0 1>]") $ s "dbs:3" # gain 1.2 #room 2, whenmod 16 15 (stut 4 1 0.065) $ n "~ 12 ~ 10" # s "dbs:2" # legato (choose[0.2,1]) # gain 1] # gain 1.2
d12 $ fast 4 $ ccn "2*128" # ccv "<100 0 8 0 10 0>" # s "midi"

sfx = stack[sound "808bd [bd [bd dbs:1]] <dbs:1 dbs:1:2> [~ ~ <~ bd> bd]" # n "1" # speed "<1 1 1 0.8>",sound "~ glitch ~ [dbs:3 [glitch glitch]]" # n "2 2 2 4 " # speed "1.3" # pan sine,sound "[~ glitch ~ glitch] [~ hc] [~ [hc hc]] [glitch hc] " # n "[0 <9 7> 0 <8 9>] 0 0 [1 3] ",sound "glitch(<9 5 12>,16)" # n "0 1 2 3 4 5 6 7" #speed "<3 1> 2 1 1 <5 2>" # pan saw] #shape 0.2 # hpf 2000 #krush 4

acidfx =  whenmod 24 20 (# speed "1.2") $ every 2 (rev) $ whenmod 8 6 (stut' 6 0.065 (|* speed 0.2)) $ sometimesBy 0.1 (# room 0.9) $ struct ("1(5,16,<0 1 2>)") $ randslice 2 $ s "<acid:1 acid:0 acid:2>" |+ n "5!6 <14 0>" # legato (choose[0.6,0.8]) # sz 0.3 #room 0.3 #hpf 400 #gain 1
d13 $ ccn "3*128"  # ccv "< 50 127 <100 127> 10 100 12 45 25 90 >"  # s "midi"


--ambient
do{
d1 $ start;
d10 $ slow 12 $ ccn "0*128" # ccv (segment(100/0.75) $ fast (8/0.75) $ range 200 400 $ sine) # s "midi"
}

hush

--dbs
do{
d2 $ start2;
d11 $ slow 64 $ ccn "1*128" # ccv (segment(100/0.75) $ fast (8/0.75) $ range 200 400 $ saw) # s "midi"
}

d2 silence

--DRUMS
do{
d3 $ sdrums;
d12 $ fast 4 $ ccn "2*128" # ccv "<100 0 8 0 10 0>" # s "midi"
}

hush

--acid fx
do{
d4 $ acidfx;
d13 $ ccn "3*128"  # ccv "< 50 127 <100 127> 10 100 12 45 25 90 >"  # s "midi"
}

--sfx
 d5 $ sfx

-- takeout drums
do{
d3 $ silence;
d12 $ silence
}

--takeout sfx
d5 $ silence

-- takeout  dbs
do{
d2 $ silence;
d11 $ silence
}

--takeout acid (not before riser)
do{
d4 $ silence;
d13 $ silence
}

-- superhoover (last)
 d15 $ silence

--takeout acid + riser
do{
  d1 $ silence; 
  d9 $ qtrigger $ filterWhen (>=0) $ seqP [
    (0, 1, randslice 2 $striate 8 $ s "acid:0"),
    (1, 2, randslice 2 $striate 8 $ s "acid:0"),
    (2, 3, randslice 2 $striate 8 $ s "acid:0*2"),
    (3, 4, randslice 2 $striate 8 $ s "acid:0*4"),
    (4, 5, randslice 2 $striate 8 $ s "acid:0*8"),
    (5, 7, randslice 2 $striate 8 $ s "acid:0*16" #pan saw),
    (7,18, slow 2 $ s "amenbrother:1" #gain 1.2)
  ]  #cut 5;
}

-- This is drop part I
 d15 $ s "superhoover" >| note ((scale "major" "<2 4 0 6>" + "f4")) #distort 1
 #lpf(range 200 600 $ sine) #hpq 1


-- Drop part II
do{
  d10 $ slow 12 $ ccn "0*128" # ccv (segment(100/0.75) $ fast (8/0.75) $ range 200 400 $ sine) # s "midi";
  --dbs
  --d2 $ start2;
  d11 $ slow 64 $ ccn "1*128" # ccv (segment(100/0.75) $ fast (8/0.75) $ range 200 400 $ saw) # s "midi";
  --DRUMS
  d3 $ sdrums;
  d12 $ fast 4 $ ccn "2*128" # ccv "<100 0 8 0 10 0>" # s "midi";
  --acid fx
  d4 $ acidfx;
  d13 $ ccn "3*128"  # ccv "< 50 127 <100 127> 10 100 12 45 25 90 >"  # s "midi";
  --sfx
   d5 $ sfx;
}

d1 $ silence


hush

Hydra



//start without dbs
speed = 0.5
shape(2,0.2,0.9)
.color(10,0,()=>cc[0],100)
.scale(0.4)
.repeat(1.0009)
.modulateRotate(o0, ()=>cc[0]*-5)
.scale(0.9).modulate(noise(()=>cc[0],2))
.rotate(3) // DBS ->>>.diff(src(o0).scale(0.9).mask(shape(4,0.9,0.01)).rotate(()=>cc[1]**2))
.out(o0)

hush()

//DRUMS
s0.initImage('C:/Users/Zakarya/Downloads/LARRY.gif')
src(s0).blend(src(s0).diff(o1).scale(1.01),1.0005)
.layer(
  src(s0)
  .scale(()=> 0.09 + ccActual[2]*0.01)
  .luma(.2)
  .invert()
  .contrast(2)
  .scrollX(.1, -0.01)
  //.modulatePixelate(src(s0), [250, 500, 10001]
)
.out(o0);

hush()

//ACID
speed = 0.5
shape(2,0.02)
.modulate(noise(1, 10))
.color(10,0,()=>Math.random(),100)
.scale(0.09) //interesting (0.09) & scale (100)
.repeat(1.9)
.modulateRotate(s0,()=>ccActual[3]*-50)
.scale(10).modulate(noise(()=>cc[3]**1001,1))
.rotate(1)
.diff(src(o0).scale(0.9).mask(shape(2,0.999,0.01)).rotate(()=>cc[3]*0.01))
//.pixelate(1,1000)
.out(o0)


hush()

I started this project with the music first and then creating and matching with the visuals.

At first, I followed Aaron’s instructions and just wrote some random blocks of compositions. Some of them are bright, some of them are creepy (is this the right word?) and they sounds irrelevant to each other. (Then I need to give credit to my amazing roommate that I got inspired from what she told me that it sounds like an agent lurking)

Then I basically applied three steps: I first adjust the samples to be the similar instruments, and then try to adjust the scale from major to minor, or other scales that I experiment to make them have similar styles. Lastly I fine-tuned some notes to make them more like a coherent whole. I also read through the documentation of the music structure and learned a bit of the power of silence between the build up and the drop so I kept it, but then to add relevance to the theme I added the female voice of “Warning”. Since this is like a story telling project to me, I added also a little bit of narrative samples and an opening ending to the structure.

For the visual part, I am always a fan of simple, red and black stuff, so I kept doing that. I have decided at a very early point to stick to one main visual and evolve different form over time. This cone-like visual gives me a sense of a tunnel/terminal where the agent is lurking around. Part of the visual evolution is due to how the sound sounds like, but an even bigger part of the visual is actually determined by the story in my mind (Agent enter the terminal -> terminal is like a maze with multiple entrance -> agent found the terminal and got in -> agent pull out the gun and break into the secret place -> the fight begin -> open ending) I made the visuals follow the basic plot and create them based on my imagination. Lastly, I tried to match them with the midi communication between Tidal and Hydra.

My Tidal Code

setcps(135/60/4)

hush

-- reset everything
do
  d11 $ ccv 0 # ccn 1 # s "midi"
  d12 $ ccv 1 # ccn 2 # s "midi"
  d13 $ ccv 0 # ccn 3 # s "midi"
  d14 $ ccv 0 # ccn 4 # s "midi"

do
  d1
    $ qtrigger $ filterWhen(>=0)
    $ struct "<[[t@3 t] t t@2]>" $ s "808hc"
    # cut 1
    # room 0.4
    # speed "<0.8 1 0.8 0.5>"
  d11 $ ccv 0 # ccn 1 # s "midi"

do
  d2
    $ qtrigger $ filterWhen(>=0)
    $ s "<hh(3,8,1) hh(5,8)>"
  d3 $ qtrigger $ filterWhen (>=0) $ s "~ 808hc*2 ~!2" # note (scale "minor" "<15 21 15 3>") # room 0.6
  d11 $ qtrigger $ ccv "<20 1>" # ccn 1 # s "midi"
  d12 $ ccv "1" # ccn 2 # s "midi"



do
  d4
    $ qtrigger $ filterWhen (>=0)
    $ struct "t!6 f [t t@2 f]"
    $ whenmod 4 3 ((# note (scale "minor" "[0,2,4]!4 [0,2,6] [0,2,4]!3"-12)))
    $ s "808hc"
    # note ((scale "minor" "<[<<22 20> 15> 7 3 1]>")-12)
    # legato 0.6
    # gain (range 0.7 1.3 sine)
    # room 0.6
  d11 $ qtrigger $ filterWhen (>=0) $ ccv "<<40 60> <40 60>>" # ccn 1 # s "midi"
  d12 $ ccv "<1 <2 3>>" # ccn 2 # s "midi"

hush

do
  d5 $ stack [
    s "bass3*8" # speed ("<1.2 1>") # room 0.4,
    slow 2 $ s "glitch:3(3,8) glitch:2"
    ]
  d6 $ s "hh*8"
  d12
    $ qtrigger $ filterWhen (>=0)
    $ ccv "<127 20 60 [[50 35] [20 10] [40 10] 10]>" # ccn 1 # s "midi"


do
  d1 silence
  d6 silence
  d8 $ s "bass3(12,16)" # speed ("<1.2 1>") # room 0.4
  d5 $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,8, s "sharp:2*4"
      # lpfbus 1 (segment 1000 (slow 8 (range 100 7000 saw)))
      # lpq 0.3
      # gain  (slow 8 (range 0.4 2 saw))
      -- # speed (range 0.3 4 saw),
      # room 0.3)
    ]
  d9 $ stack [
    slow 2 (s "~ glitch:3"),
    struct "t!2 [f t] [t f]" $ s "[909 sd]!2"  # room 0.6,
    qtrigger $ filterWhen (>=0) $ slow 4 $ s "hh*<4 8 16 32>"
    ]
  d6 $ s "~!3 <sharp:6 ~>" # room 0.3 # gain (slow 2 "<1 1.5>") # (slow 2 (lpf "<1000 10000>"))
  d11 $ qtrigger $ filterWhen (>=0) $ ccv (slow 8 (segment 8 (range 10 127 saw))) # ccn 1 # s "midi"
  d12 $ qtrigger $ filterWhen (>=0) $ ccv "<1 2 4 8 12 18 23 100>" # ccn 2 # s "midi"
  d13 $ qtrigger $ filterWhen (>=0) $ ccv "<0.1 1>" # ccn 3 # s "midi"


hush

do
  d2 silence
  d3 silence
  d9 silence
  d8 silence
  d7
    $ qtrigger $ filterWhen (>=0) $ seqP [
    (1,25, every 2 (fast 2) $ s "bass3(5,8)" # note ("1..2") # room 0.3),
    (25,30, every 2 (fast 2) $ s "bass3(5,8)" # note ("1..2") # room 0.3 # gain (slow 12 (range 1 0.1 saw)))
    ]
  d6
    $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,1, s "sharp:3" # gain 1.5 # room 1 # krush 5),
    (1,25, s "sharp:2*2" # speed "0.7" # gain (slow 25 (range 1.3 0.8 saw))),
    (1,17, slow 2 $ s "hardkick:5" # gain "<<2 1.3> 1.3 1.5 1.3>" # room 0.8 # lpf ("<10000 10000 800 10000>")),
    (1,20, s "909*4" # room 0.3 # gain 1.3),
    (1,25, s "hh*16" # gain (range 1 1.2 perlin)),
    (25,30, s "sharp:2*2" # speed "0.7" # gain (slow 8 (range 0.8 0 saw))),
    (31,33, s "<sharp:7 [~!3 sharp:9]>" # room "<1 1.5>" # gain "<1 1.2>")
    ] # room 0.5
  d4
    $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,30, slow 2 $ chop "<32 16>" $ "ade:6"
    # speed ("<2 3>")
    # room 0.2 # gain (range 1 1.8 saw))
    ]
  d11 $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,25, ccv (segment 16 (range 100 1 saw))),
    (25,30, slow 5 $ ccv (segment 5 (range 100 0 saw))),
    (30,33, ccv "0")
    ] # ccn 1 # s "midi"
  d12
    $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,1, ccv "1 0!64"),
    (1,10, ccv "<1 4 10 20>"),
    (25,30, ccv "1"),
    (30,33, ccv "1")
    ] # room 0.5 # ccn 2 # s "midi"
  d14
    $ qtrigger $ filterWhen (>=0) $ seqP [
    (0,1, ccv "1"),
    (1,2, ccv "0"),
    (3,17, slow 2 $ ccv "1 0!12")
    -- (25,33, ccv "1")
    ] # ccn 4 # s "midi"

hush

My Hydra Code

hush()

// intro
shape(30,()=>cc[1]*1.3)
.scale(1,()=>window.innerHeight/window.innerWidth,1)
.colorama(1)
.scrollY(0.1,0.1)
.diff(src(o1).scale(0.9),0.5)
// comment out for the 4th part
// .luma(0.12)
// .repeat(()=>ccActual[2],()=>ccActual[2])
.out(o1)
render(o1)

// build up
src(o1)
.repeat(()=>ccActual[2],()=>ccActual[2])
.modulate(noise(()=>ccActual[2]/3,()=>cc[2]*5))
.colorama(()=>ccActual[3])
.invert(()=>ccActual[4])
.out(o2)
render(o2)

//drop
src(o1)
.repeat(()=>ccActual[2],()=>ccActual[2])
.modulate(noise(()=>ccActual[2]/3,()=>cc[2]*5))
.hue(()=>cc[1]*50)
.colorama(()=>ccActual[3])
.modulateScale(noise(3,()=>cc[1]))
.invert(()=>ccActual[4])
.out(o2)



// final
shape(4,100).out(o0)
render(o0)



hush()

The hardest part of the composition for me was actually settling on what to include and what to exclude from the final piece. I had so many ideas but I only wanted to include ones that made sense together in my mind. My main goal for this project was to see how far I can push one single line of code (for visuals). I started with one line and then I manipulated it a bit to create the different sections that give off different vibes. I also tried to change little things within each section to make it feel different (live! and improvised-ish). As I mentioned earlier, the hardest part was to actually decide on what to include and what to tweak because I realized that there’s so much one can do with just a single line of code.

Initially I had a beat drop, but when I was going over my composition piece again I decided to remove it. I wanted my piece to have a more steady curve rather than a peak and a base line. 

My composition is structured in sections. Some sections are of similar vibes whereas other sections are contrasting. 

This is the general sequencing of the sections, however I tweak things around as I go so the sections aren’t very definite:

Visuals: A – B – C – D – B

Audio:  A – (A+B) – (A’+C) – C – A 

I am layering the sounds and slowly removing some of the layers towards the end. I am also editing the visuals in each section to create transitions.

The code:

Hydra:


osc(2,0.01,1).rotate(1.8).layer(osc(10,0,1).color(4,0,10).luma(()=>cc[0]*9,10)).modulate(noise(()=>(cc[0])*2,.2)).rotate(()=>cc[0]*0.2).out(o0)
// ......................................10.....................
//..4.................................................
//.................................................0...100....


osc(1,.01,1).layer(osc(5,.01,5).color(0,0,20).rotate(1.2)).modulate(noise(()=>(cc[0])*6,.9)).rotate(()=>cc[0]*.5).out(o0)
//play around with color end at 1,1,20

//.....................50
//.....................500


osc(2,0.1,1).layer(osc(20,0,1).color(1,1,4)).modulate(noise(()=>(cc[0])*10)).out()
//play around with color, end at 12,2,5


osc(4,0.01,1).color(1,1,0).rotate(1).layer(osc(5,0,1).color(1,1,10).luma(()=>cc[0]*8,9)).modulate(noise(2,.2)).out(o0)
//40
//400

hush()

Tidal:


d3 $ ccv "0 20 64 127" # ccn "0" # s "midi"
first

second

third
d2 silence

d4 silence

first
d1 silence

hush


second= do
  d1 $ qtrigger $ filterWhen (>=0) $ slow 2 $ s "peri:8"
    >| note (scale "<minor major enigmatic>" ("[<2 5 -3 8>]*8") + "[c5,c9]")

first = do
  d2 $ qtrigger $ filterWhen (>=0) $ s "bd sd bd"
  d4 $ qtrigger $ filterWhen (>=0) $ s "808bd:2 cp ~ cp" # speed 3

third = do
  d1 $ sound "[<techno:1 glitch(3,8) sundance:2>, ~ bd*2]" # room 1.2 # crush 8

Demo:

My project draws inspiration from the tragic beauty of human ambition and its inevitable unraveling. It mirrors the story of Itachi Uchiha and the Akatsuki—a tale of sacrifice, idealism, and the fragile line between unity and destruction.

The first act symbolizes Itachi’s life: a solitary figure burdened by impossible choices. Like a bird caged by duty, he sacrificed his own peace to protect others, yet became a villain in the eyes of those he loved. This duality—the hidden cost of “greater good”—fuels the emotional core of the piece.

The second act shifts to Akatsuki’s founding philosophy: a desperate belief that peace could be forced through control. Their vision wasn’t born from cruelty but from the scars of war—a distorted hope that unity might emerge if humanity was stripped of free will. It’s a reflection of how trauma can twist even noble intentions into something monstrous.

The third act honors the group’s origins—three orphans who dreamed of healing a broken world. Their early bonds were pure, a fragile alliance against suffering. But as power grew, so did divisions. Greed, ego, and conflicting ideologies poisoned their unity, mirroring how movements often lose their way when scale replaces purpose.

The final collapse isn’t just about failure—it’s a warning. Societies built on suppression, even with grand ideals, crumble when empathy dies.

Live Demo

TidalCycle Code

do
  d1 $ ccv "0 20 64 127" # ccn "0" # s "midi"
  d2 $ rotL 1 $ every 4 (# ccv (fast 2 (range 127 0 saw))) $ ccv (segment 128 (range 127 0 saw)) # ccn "1"  # s "midi"
  d3 $ ccv (segment 128 (slow 4 (range 127 0 saw))) # ccn "2" # s "midi"
  d10 $ ccv "10 40 80 127" # ccn "3" # s "midi"

hush

d11 $ s "birds:3" # gain 0.5

d4 $ slow 4 $ note "c'maj d'min a'min g'maj" # s "superpiano"
  # legato 1
  # djf 0.3
  # gain 0.85
  # sustain 1.75

d11 silence

d5 $ slow 4 $ note "c3*4 d4*4 a3*8 g3*4" # s "superhammond:5"
  # legato 0.5

xfade 4 $ "bd <hh hh*2 hh*4> sd <hh [hh bd]>"
  # room 0.2

d6 $ s "~ cp" # gain 1

once $ s "auto:3"

d7 $ jux rev $ slow 4 $ arp "up down diverge converge" $ note "c'maj'4*2 d'min'4*2 a4'min'4*2 g4'maj'4*2" # s "supervibe"

d8 $ hurry 2 $ s "bd hh sd hh"

do {
  d6 silence;
  d8 silence;
  d1 $ qtrigger $ filterWhen (>=0) $ seqP [
      (0,1, s "[bd*2] [hh cp]"),
      (1,2, s "[bd*4] [hh cp]")
  ] # gain (slow 4 (range 0.8 1 saw));
  once $ s "auto:3";
  d5 $ qtrigger $ filterWhen (>=0) $ seqP [
    (0, 1, s "~ cp"),
    (1, 2, s "~ cp*2")
  ] # speed (slow 4 $ range 0.5 2 tri)
    # pan (slow 8 $ sine);
  d3 $ qtrigger $ filterWhen (>=0) $ seqP [
    (0, 2, s "hh*8")
  ] # gain (slow 4 $ range 0.7 1.2 saw);
  d4 $ qtrigger $ filterWhen (>=0) $ seqP [
  (0, 1, s "~ arpy"),
  (1, 2, s "arpy(3,8)"),
  (2, 3, s "arpy(5,8)"),
  (3, 4, s "arpy(8,8)"),
  (4, 5, fast 0.5 $ s "superhoover" >| note (arp "updown" (scale "minor" ("<5,2,4,6>"+"[0 0 2 5]") + "c4")) # room 0.3)
] # note (scale "minor" $ run 8)
  # cutoff (slow 4 $ range 300 3000 sine)
  # resonance 0.2 # gain 1.2;
  hush
}

Hydra Code

s0.initVideo("birds.mp4")

src(s0)
  .thresh(0.3, 0.04)
  .invert()
  .blend(solid(0, 0, 0), () => {
    // Calculate the fade amount based on video progress
    const video = s0.src
    const fadeStartTime = video.duration - 5 // Start fading 5 seconds before the end
    const fadeAmount = Math.max(0, (video.currentTime - fadeStartTime) / 5)
    return fadeAmount
  })
  .rotate(() => Math.sin(time))
  .out()

osc(40,-0.01,1)
  .modulate(voronoi(3))
  .contrast(1)
  .kaleid(360)
  .mask(shape(40, .6).scale(1,1))
  .out(o0)
src(o0)
  .rotate(1.57, 0.2)
  .modulate(noise(() => cc[3] * 40, 0.1))
  .add(src(o0), () => 0.01 + cc[1])
  .scale(1 + .5, .7).saturate(-0.5)
  .scale(() => 1 + Math.sin(time / 15) * 0.2)
  .saturate(0.1)
  .rotate(0,-0.1)
  .out(o1)
render(o1)

voronoi(10,1,5)
  .brightness(()=>Math.random()*0.15)
  .modulatePixelate(noise(()=>cc[2]*20,()=>cc[0]),100)
  .out()

voronoi(10,1,5).brightness(()=>Math.random()*0.15)
  .modulatePixelate(noise(()=>cc[2]*20,()=>cc[0]),100)
  .color(()=>0,5,3.4).contrast(1.4)
  .add(shape(7),[cc[0],cc[1]*0.25,0.5,0.75,1])
  .out(o0)

voronoi(10,1,5).brightness(()=>Math.random()*0.15)
  .modulatePixelate(noise(cc[0]+cc[1],0.5),100)
  .color(()=>0,0.5,0.4).contrast(1.4)
  .out(o0)

hush()