Our final project’s visual composition was inspired by the idea of planets and the vastness of the universe.
We began by creating a glitching effect through combining the layer, luma, and colorama functions. First, we generated a layer of flashing dots modulated by an oscillator, saved to the o1 layer. By applying the luma function, the dots drift across the visuals in o0, simulating falling stars. Adding colorama on top produced an unexpectedly stunning comet-like effect, which we stored as visual 6 in our array. Elora described it as comets falling on the dinosaurs, and children gazing into the bewildering depths of the universe, which became the thematic anchor of our performance.
Building on the universe theme, we introduced a rotating sphere shader as a planet. Drawing from a previous solo session and with the help of Claude AI, we developed two shader variants: one that rotates with dynamic shading, and another that remains a solid, stable sphere throughout. Yihan noted that blending oscillation and noise with the shader gave it the appearance of Mars with a more divergent color palette. These two shaders formed the visual foundation of our performance.
From a single planet, we expanded outward. By applying the repeat and blend functions, the sphere multiplied into planets of varying sizes. As the blending parameter increased, an unexpected grid and strip filter emerged, layering over the infinite planets. These three visuals — the falling stars, the rotating sphere, and the multiplying planets — formed the backbone of our performance. Our approach was to manipulate them gradually using MIDI values, building variation and tension while maintaining visual cohesion.
The main challenge we encountered during our final sync session was smoothing the transition between the falling star effect and the sphere visuals. After extended technical exploration, we discovered that layering the falling star effect over the rotating sphere created a natural bridge between the two.
Hearing Elora and Yihan’s music, the kids’ sample made me think back to when I was a kid and how I was obsessed with the moon and the crescent shape and how magically it changes throughout the month. I thought about the old mythology of the moon and all the mysterious in its shape, lumination. I thought of using a function to manipulate the shader’s X and Y axis and by changing the speed of the filling of the sphere maybe I could achieve that effect. To my surprise, the moon effect was also created, even though I still couldn’t explain the math behind it and was so surprised by the spontaneous visual change. We decided to add the moon in the end and let it vanish as the music vanishes beside the kid sample, and I also love this part.
For the visual composition of our final project we were inspired by the idea of planets and the bewilderment of the universe.
From the idea of creating a glitching effect through using the layer, luma and colorama function combo, we first created a layer of flashing dots modulated by an oscillator saving it to o1 layer, and through using the luma function, we let the flashing dots moves around over the current visuals in o0 to create the effects of “falling stars”. Thinking about adding colors to it, we then attached the colorama function, and out of our expectation it created this splendid falling star effect (stored in array as visual 6).
I remembered Elora mentioned that this visual reminded her of the comets falling on the dinosaurs, as well as the kids looking into the deep bewilderment of the universe. This visual became our base and drives us to further explore the theme of kids and the universe.
Starting from the idea of the universe, we thought of introducing a sphere as a planet and blend it in with effects of modulation. In the previous solo practice session, I discovered the shader of a rotating sphere with the help of Claude AI. When brainstorming what could we do with the manipulation of the shader, Yihan mentioned that the blending of oscillation and noise function with the shader made it look like the shape of Mars yet more divergent in color. In order to make the planet get a more dynamic effect, we wanted to create two shaders where one rotates with shades while the other remains as a full sphere throughout. Thus, after “consulting” Claude AI again, we managed to achieve making the original rotating shader become a solid 3D sphere. We decided to keep the version as the base of our performance.
From one planet we generated more. Through simply adding the repeat and blend function, the one planet split into more planets that varies in size in visual and when the blending parameter became larger in number, I was surprised to see how it generated a filter of strips and grids that layers on top of the infinite planets and we thought about this could slowly be matching with the built and drop part of the melody and decided to keep it in our tool knit when finally compositing it.
These three visuals formed the base of our performance and we thought about through manipulation of the three visuals with different midi values and slowly creating built up and variation we would manage to achieve a cohesive performance.
What came to us as our surprise in our final meet up to sync, we struggled a bit with how to make the transitions between the visuals smooth and made visible a connection between the visual of the falling stars and sphere. I thought that in the most brutal way, if we could layer the falling star effect on top of the sphere yet in a way that the sphere would be the accumulation of light yet still remain in its shape, then the sudden transition from spheres to falling stars wouldn’t be so sudden and random. After spending a long time in technical exploration, the rotating sphere in the falling star visual came to us and we decided that it’s so beautiful that we’ll keep it in the middle with the simplest sound where everything drops except the star melody. This sudden quiet and ambience to me really brings in a deep sense of wonderness and it is my favorite part of the performance.
Hearing Elora and Yihan’s music, the kids’ sample made me think back to when I was a kid and how I was obsessed with the moon and the crescent shape and how magically it changes throughout the month. I thought about the old mythology of the moon and all the mysterious in its shape, lumination. I thought of using a function to manipulate the shader’s X and Y axis and by changing the speed of the filling of the sphere maybe I could achieve that effect. To my surprise, the moon effect was also created, even though I still couldn’t explain the math behind it and was so surprised by the spontaneous visual change. We decided to add the moon in the end and let it vanish as the music vanishes beside the kid sample, and I also love this part!
For the rest of the visual, we just slowly built it up corresponding with the music, changing one midi value at a time to make the transitions smooth and not too dramatic. We also put all the visuals in an array so that all the visuals can correspond to midi value change in order to assure that the music and visuals are perfectly aligned.
Tidalcycles (Elora & Yihan)
We initially approached our composition by coding separate sections of music and trying to piece them together, but found that the results from this were incohesive and clunky. We were heavily inspired by this composition by students from a previous live coding class. Its minimalist style generated high energy while still allowing for the sound to be stripped to its hollow, liquid bones. By keeping a melodic core intact, they achieved evolution by adding and subtracting beats, creating a seamless musical experience. Wanting to emulate this dynamism, we started the final draft by composing its melodic skeleton, and building upon it. Whereas before we had struggled to juggle multiple genres, we decided to establish a single tone and develop it further. Several references helped me decide what emotions we would evoke for this piece. I recently read about the difficult production behind Katy Perry’s “Teenage Dream.” Songwriter Bonnie Mckee said:
I thought about my own adolescent years, my own first love. I thought about watching Baz Luhrmann’s Romeo and Juliet and putting on a little mini discoball light and just dreaming of Leo. I thought about me and my friends sitting around at slumber parties in the ’90s, giddy even just THINKING about boys….. I thought about what Benny said and I listened to the song again, and I was like the Teenagers….. that’s such a great word, Teenager. It is a very descriptive word; it packs a lot of emotion and imagery into three syllables….. I couldn’t believe after all of our agonizing over ‘youth’ themes, that we had overlooked such an obvious one – the teenage condition.
I thought about the song I shared with the class at the beginning of the semester, Teenagers by French 79. How often have I listened to this song and repeated the word, forgetting myself as crests of synth broke over me like waves? This made me think about Kids by MGMT and childhood by daniel.mp3. About Just Kids by Pattie Smith on Robert Mapplethorpe. Like ‘teenagers,’ the word ‘kids’ raises indescribable feelings in all of us. We reminisce on the reckless, blind joys of the past, about what has been lost, and what is impossible to return to. For this composition, we wanted to deliver senses of playfulness and melancholy.
Like the aforementioned student group we were inspired by, we structured our code into do-blocks for legibility and easy execution. Yihan created a series of chords that served as the basis for the melody, which we made by using the ‘supervibe’ sample, a vibraphone sound often associated with childhood. After setting the tone, we gradually progressed the composition by bolstering the high melody with a bassline, and adding various beats. We discovered we could create a song simply by reducing elements and reintroducing them again. It wasn’t necessary to continually introduce new patterns and sounds into the composition––in fact, it became quite congested and messy when we tried that. We added a “supersaw” arpeggiated sequence chock-full of reverb to create a dreamlike atmosphere, and then suddenly dropped the other elements to create a sense of ‘floating’ in space. By layering a low bassline and the original melody on top of the synths, we created a sound that the audience could ‘sit’ in. It is my favorite part of the composition.
We interrupted the bridge by adding beats, and integrated a sample I found on freesound of kids laughing. Both MGMT and daniel.mp3 applied delay and echo effects to their samples of kids’ voices to create a sense of melancholic nostalgia. I did the same. We introduced a second “supersaw” arpeggiated sequence and immediately subtracted it, reducing the composition to the beats to generate tension. During our live performance in class, I let this sequence escalate for longer than I do in the video, and wish I had recorded it. We then added a third “supersaw” sequence, a second sample of kids yelling, and quickened the beat. Making the drop was the most difficult part of this assignment. We felt like we were stuck in a loop of building tension and struggled to think of a way to resolve it. Rather than try to code a dramatic transition, we created a slower, more muted sequence of notes that felt like they could stand on their own, with hints of the original melody to create a feeling of having circled back. We discovered that shifting from the high-tension beats to this block worked well, and achieved the resolution we had been looking for. My second favorite part of the composition is when the flying moon dissolves with the ending laugh sample, but Yutong can tell you about that.
Hydra Code
//visual script
//!!!visual array
visuals = [ //first visual-> purple sphere ()=>{setFunction({ name: 'sphereShaderglow', type: 'src', inputs: [ { type: 'float', name: 'locX', default: 0.5 }, { type: 'float', name: 'locY', default: 0.5 }, { type: 'float', name: 'diameter', default: 0.3 }, { type: 'float', name: 'r', default: 0.5 }, { type: 'float', name: 'g', default: 0.4 }, { type: 'float', name: 'b', default: 0.7 }, { type: 'float', name: 'm1', default: 0.2 }, { type: 'float', name: 'm2', default: 0.5 }, { type: 'float', name: 'm3', default: 0.8 }, ], glsl: ` vec2 uv = _st * resolution; vec2 center = vec2(locX * resolution.x, locY * resolution.y); float dist = distance(uv, center); float radius = (diameter * resolution.x) / 2.0; vec3 moonColor = vec3(r, g, b); // --- Glow halo (additive, outside AND inside the sphere) --- float glowRadius = radius * 1.8; // how far the glow reaches float glowStrength = 0.9; // peak brightness of halo float glowFalloff = 3.5; // higher = tighter glow float glowDist = max(dist - radius, 0.0); // distance beyond sphere edge float glow = glowStrength * exp(-glowFalloff * glowDist / radius); vec3 glowColor = moonColor * glow; // glow tinted to moon color // Outside the sphere: just the glow halo if (dist > radius) { return vec4(glowColor, 1.0); } // --- Sphere surface shading --- float normX = (uv.x - center.x) / radius; float normY = (uv.y - center.y) / radius; float z = sqrt(max(0.0, 1.0 - normX*normX - normY*normY)); vec3 normal = normalize(vec3(normX, normY, z)); vec3 lightDir = normalize(vec3(m1, m2, m3)); float light = max(dot(normal, lightDir), 0.0); // Additive rim glow on the lit edge of the sphere float rimGlow = pow(1.0 - z, 3.0) * light * 0.6; vec3 color = moonColor * light; color += moonColor * rimGlow; // add rim highlight color += glowColor * 0.3; // bleed inner glow into surface return vec4(color, 1.0); ` }) // Orbiting moon version let rotSpeed = 0.5 sphereShaderglow( 0.5, () => (Math.sin(time * rotSpeed) / 10+0.5), 0.3, 0.5, 0.4, 0.9, // r, g, b — cool blue-white moon color () => Math.sin(time * rotSpeed), -0.3, () => Math.cos(time * rotSpeed), ).out(o3) //visual 1-> one singular ball osc(24,0.1,0.5).modulateRotate(noise(2),()=>cc[0]).mask(o3).color(5,4,1).hue(0.5).blend(src(o0),0.9).out(o0)}, //------------------------------------ //visual 2-> spheres with bigger ossilation ()=> {osc(24,0.1,0.5).modulateRotate(noise(2),()=>(cc[0]*5)).mask(o3).color(5,4,1).hue(0.5).blend(src(o0),0.9).out(o0)}, //----------------------------------------- //visials 3 bigger ossilation sphere with color change ()=> {osc(24,0.1,0.5).modulateRotate(noise(2),()=>(cc[0]*5)).mask(o3).color(2,4,1).hue(()=>cc[1]*2).blend(src(o0),0.9).out(o0)}, //------------------------------------------- //visuals 4 change ball size ()=>{let rotSpeed = 0.5 sphereShaderglow( 0.5, () => (Math.sin(time * rotSpeed) / 10+0.5), ()=> cc[3], 0.5, 0.4, 0.9, // r, g, b — cool blue-white moon color () => Math.sin(time * rotSpeed), -0.3, () => Math.cos(time * rotSpeed), ).out(o3) osc(24,0.1,0.5).modulateRotate(noise(2),()=>(cc[0])).mask(o3).color(2,4,1).hue(()=>cc[1]*2).blend(src(o0),0.9).out(o0)}, //-------------------------------------------------- //visuals 5 add another layer of effects scrollX ()=>{osc(24,0.1,0.5).modulateRotate(noise(2),()=>(cc[0])).mask(o3).color(2,4,1).hue(0.35).blend(src(o0).modulateScrollX(o0),0.9).out(o0)}, //----------------------------------------------------- //visuals6-> multiple spheres in blender ()=> {osc(24,0.1,0.5).modulateRotate(noise(3),()=>(cc[0])).mask(o3).color(4,2.5,1.5).hue(()=>cc[2]).blend(src(o0),0.5).repeat(2,2).layer(src(o1)).out(o0)}, //------------------------------------------------ //visuals7->falling Stars wihtout planets ()=> { osc(24, 5, .7) .mask(shape(100, 0.02, 0.01).scale(1, () => window.innerHeight / window.innerWidth)) .repeat(100, 100) .modulate(noise(1, 0.5), 0.5).colorama(0.25) .rotate(() => cc[0] * Math.PI, 0.03) .out(o1) // osc(24,0.1,.7).mask(shape(10,0.01,0.02).scale(1,()=>window.innerHeight/window.innerWidth)). // repeat(100,100).modulate(noise(1,0.5,3),0.5).out(o1) src(o0) .modulate(voronoi(100,0.1,1.5).modulate(noise(5),1).brightness(0.03) ,0.003).layer(src(o1)).luma(0.2).colorama(0.5).out(o0)}, //--------------------------------------------------- //visuals 8->falling stars with a spheres ()=> { setFunction({ name: 'sphereShader', type: 'src', inputs: [ { type: 'float', name: 'locX', default: 0.5, }, { type: 'float', name: 'locY', default: 0.5, }, { type: 'float', name: 'diameter', default: 0.3, // in normalized space, 0.3 = 30% of screen }, { type: 'float', name: 'r', default: 0.5, }, { type: 'float', name: 'g', default: 0.4, }, { type: 'float', name: 'b', default: 0.7, }, { type: 'float', name: 'm1', default: 0.2, //1st parameter of the 3D vector the direction that the sphere faces }, { type: 'float', name: 'm2', default: 0.5, //2nd parameter of the 3D vector the direction that the sphere faces }, { type: 'float', name: 'm3', default: 0.8, //3rd parameter of the 3D vector the direction that the sphere faces } ], glsl: ` // current pixel in screen space vec2 uv = _st * resolution; // mouse in screen space vec2 center = vec2(locX * resolution.x, locY * resolution.y); // distance from center float dist = distance(uv, center); // convert diameter to screen space radius float radius = (diameter * resolution.x) / 2.0; // outside the circle = black if (dist > radius) { return vec4(0.0, 0.0, 0.0, 1.0); } // sphere surface math float normX = (uv.x - center.x) / radius; // -1 to 1 float normY = (uv.y - center.y) / radius; // -1 to 1 float z = sqrt(1.0 - normX*normX - normY*normY); // depth // surface normal vec3 normal = normalize(vec3(normX, normY, z)); // light direction vec3 lightDir = normalize(vec3(m1, m2, m3)); // how much does surface face the light float light = max(dot(normal, lightDir), 0.0); // color vec3 color = vec3(r, g, b); return vec4(color * light, 1.0); ` }) let rotSpeed = 0.5 // how fast it rotates // m1 and m3 trace a circle over time = light orbits the sphere! sphereShader( 0.5, //() => (Math.sin(time * rotSpeed)/15+0.5), 0.5, 0.4, 0.5, 0.4, 0.9, //0.2, () => Math.sin(time * rotSpeed)*2, // m1 — light X orbits //() => Math.sin(time * rotSpeed)*0.5,// m2 — light Y stays fixed 0.8, () => Math.cos(time * rotSpeed)*2, // m3 — light Z orbits ).out(o3) osc(24, 5, .7) .mask(shape(100, 0.02, 0.01).scale(1, () => window.innerHeight / window.innerWidth)) .repeat(100, 100) .modulate(noise(1, 0.5), 0.5).colorama(0.25) .rotate(() => cc[0] * Math.PI, 0.03) .out(o1) // osc(24,0.1,.7).mask(shape(10,0.01,0.02).scale(1,()=>window.innerHeight/window.innerWidth)). // repeat(100,100).modulate(noise(1,0.5,3),0.5).out(o0) src(o0) .modulate(voronoi(100,0.1,1.5).modulate(noise(5),1).brightness(0.03) ,0.003).layer(src(o1)).luma(0.2).colorama(0.5).out(o2) src(o3).layer(o2).luma(0.02).brightness(0.02).hue(0.8).out(o0)}, //----------------------------------------------- //visual 9 falling start in moon ()=> { let rotSpeed = 0.5 // how fast it rotates // m1 and m3 trace a circle over time = light orbits the sphere! sphereShader( () => (Math.sin(time * rotSpeed)/15+0.5), () => (Math.sin(time * rotSpeed)/15+0.5), 0.35, //diameter 0.4, //r 0.5, //g 0.4,//b 0.9, //0.2, () => Math.sin(time * rotSpeed)*2, // m1 — light X orbits () => Math.sin(time * rotSpeed)*0.5,// m2 — light Y stays fixed //0.8, () => Math.cos(time * rotSpeed)*2, // m3 — light Z orbits ).out(o3) osc(24, 5, .7) .mask(shape(100, 0.02, 0.01).scale(1, () => window.innerHeight / window.innerWidth)) .repeat(100, 100) .modulate(noise(1, 0.5), 0.5).colorama(0.25) .rotate(() => cc[0] * Math.PI, 0.03) .out(o1) // osc(24,0.1,.7).mask(shape(10,0.01,0.02).scale(1,()=>window.innerHeight/window.innerWidth)). // repeat(100,100).modulate(noise(1,0.5,3),0.5).out(o0) src(o0) .modulate(voronoi(100,0.1,1.5).modulate(noise(5),1).brightness(0.03) ,0.003).layer(src(o1)).luma(0.2).colorama(0.5).out(o2) src(o3).layer(o2).luma(0.02).brightness(0.02).hue(0.8).out(o0)}, //------------------------------------- //visual 10 pulsing purple sphere with fixed color ()=>{ // Orbiting moon version let rotSpeed = 0.5 sphereShaderglow( 0.5, () => (Math.sin(time * rotSpeed) / 10+0.5), 0.5, 0.5, 0.4, 0.9, // r, g, b — cool blue-white moon color () => Math.sin(time * rotSpeed), -0.3, () => Math.cos(time * rotSpeed), ).out(o3) // //1 one singular ball osc(24,0.1,0.5).modulateRotate(noise(2),()=>cc[0]).mask(o3).color(5,4,1).hue(0.5).blend(src(o0),0.9).out(o0)}, //----------------------------------------------------- //visual 11 multiple sphers in blender with a filter ()=> {osc(24,0.1,0.5).modulateRotate(noise(3),()=>(cc[0])).mask(o3).color(4,2.5,1.5).hue(()=>cc[2]).blend(src(o0),0.9).repeat(6,6).layer(src(o1)).out(o0)}, //visua//visuals6-> multi ]
whichVisual = 0 visuals[8]()
visuals[whichVisual]()
// can use update and switch case with midi: update = () =>{ if (ccActual[5]==24){ visuals[8]() } // very important! only change source once, when necessary if (whichVisual != ccActual[1]){ whichVisual = ccActual[1]; visuals[whichVisual]() }, }
--add percussion--change color-- do d3 $ slow 2 $ stack [ s "808:1 ~ 808:1 ~" # gain 0.9 # speed 0.65, s "808:1(3,8)" # gain 0.7 # speed 0.9 # nudge 0.02, s "808:1(5,16)" # gain 0.7 # speed 0.8 # pan (slow 4 sine), s "~ 808:1 ~ 808:1" # gain 1.1 # speed 0.45 # room 0.3 ] d14 $ qtrigger $ slow 4 $ struct "t(3,8)" $ ccv ((segment 128 (range 127 0 saw))) # ccn "1" # s "midi" --for color ccn 1 d13 $ ccv "2" # ccn 1 # s "midi" --for # of visuals
--add beat 1--change ball size-- tone down oscillator-- do d4 $ s "909 909 909 <909, 808:1>" # gain 1 # size 0.4 d13 $ ccv "3" # ccn 1 # s "midi" --for # of visuals d15 $ struct "t t t <t, t>" $ ccv ((segment 128 (range 30 20 rand))) # ccn "3" # s "midi" --pulsing
--only beat 2--- combine with another texture, remove color -- let's stay with this color thenn do d3 silence d2 silence d5 $ s "808:3*4" # gain 0.7 # krush 2 d13 $ ccv "4" # ccn 1 # s "midi" --for # of visuals
--add the percussion back in-- d3 $ stack [ s "808:1 ~ 808:1 ~" # gain 1.8 # speed 0.65, s "808:1(3,8)" # gain 1 # speed 0.9 # nudge 0.02, s "808:1(5,16)" # gain 1.6 # speed 1.3 # pan (slow 4 sine), s "~ 808:1 ~ 808:1" # gain 0.8 # speed 0.45 # room 0.3 ]
Last CallA live audiovisual performance — TidalCycles + Hydra
Concept
The piece is built around a single, mundane Friday night, the kind that becomes something else entirely once you’re inside it. You’re outside a club at 11 pm. The line moves. You get in. What follows is less a narrative than a physiological arc: the disorientation of the crowd, the moment the music takes over your body before your brain consents, the peak where individual people stop being people and become just movement and light, and then the long slow return to yourself at the bar.
The theme is about losing and finding your own interiority in a public space. Clubs are interesting because they’re designed to dissolve the self and most people go willingly. The piece tries to make that process felt rather than described. The visuals fragment the webcam feed in parallel with that arc: the face starts legible and gradually becomes unrecognizable, kaleidoscoped and consumed by feedback, before reassembling into something quieter at the end. The music does the same thing rhythmically by stacking complexity until the breakbeats hit and the tempo feels almost hostile, then unwinding back to the same four chords it started on.
The ending is deliberately small. After everything, someone just asks for water. That felt true.
Structure
The audio is built around a four-chord progression in F♯ minor (F♯min7 → Dmaj7 → Amaj7 → Emaj7) that runs through the whole piece. Tempo climbs across three breakpoints — 135, 145, then 175 bpm — using a custom interpolation function (ct_) that ramps the clock gradually rather than cutting hard. Percussion layers stack progressively via xfadeIn, so the density of the mix builds in parallel with the narrative.
The visuals use the live webcam feed (s0) as their spine throughout. It gets thresholded, kaleidoscoped, color-shifted, and eventually fed back into itself depending on the scene. The core Hydra technique is a self-referencing feedback buffer: src(o0) reads the previous frame back into the pipeline, scaled fractionally below 1 and modulated by noise, so the image accumulates history rather than refreshing clean. At the peak scenes, this creates a sensation of the visuals consuming themselves.
MIDI CC signals bridge the two environments. TidalCycles sends continuous controller values via p “housemidi” and p “breakmidi”, which Hydra reads as cc[] arrays — so in several scenes, musical parameters are directly steering visual ones (camera zoom, threshold cutoff, blend amounts).
Biggest hurdle: Recording
The hardest part of the process had nothing to do with the code. We were recording across four machines and spent a significant amount of time trying to sync the video outputs with the webcam feeds in post. We tried manual timecode alignment, clap-sync markers, and various export-timing approaches — nothing held reliably. Frame rates drifted, audio latency was inconsistent across machines, and the camera feeds introduced their own additional delay. We eventually abandoned the sync attempt and submitted without it. The live performance is the real artifact; the recording is a best-effort document of it.
Roles:
Ahmed and Linus – Tidal-side, recording and concept
Our live-coding performance explores the tension between collective harmony and individual expression through the integration of TidalCycles for audio and Hydra for GLSL visuals. Bound together by a shared MIDI “nervous system,” the performance is anchored by a collective foundation featuring a unified 171 BPM clock and Euclidean rhythmic structures. Against this synchronized framework, distinct individual “personalities” emerge, ranging sonically from organic world percussion to digital Moog bass, and visually through specialized shaders (ritualBalls and gloopFace) that interpret the same data through entirely different aesthetic lenses. As the piece unfolds, the performance dynamically evolves from minimalist geometry into a complex, reactive 3D climax, symbolizing how diverse, autonomous components can seamlessly merge into a singular, high-energy experience.
Salem — Made the main visual shader (ritualBalls) and connected the music to the visuals so they react together. Tewoflos — Came up with the visual idea and style that Salem built on. Lincoln — Helped write the music in TidalCycles and helped build the second shader (gloopFace, the 3D face). Reginald — Helped write the music in TidalCycles and helped build the second shader (gloopFace, the 3D face).
Our project channels a creepy and unsettling feeling, with the visuals as well as sound. We wanted to capture a moment that is fleeting and uncertain through our work, with the use of darker visuals and eerie sounds. Inspired by Orwell’s 1984, we wanted to mimic the idea of being surveilled and trapped within a world where there is no sense of autonomy.
Process and Contributions:
The visuals begin at a calm tone with a light blue screen subtly oscillating waiting for the performance to begin. When the music begins to get a more steady beat so do the visuals as they shift steadily from one direction to the other. The integration of layers of noise and oscillation were with an intention to capture the visual randomness of noise within the visual order of the oscillator. The result was an almost flowing maze look, which tied in well with the theme as it evoked a feeling of entrapment. With this we wanted to create a visual that is fleeting in a way, changing its flow every time it looks like it’s about to drift away. At this point the visuals are a bright red colour, with an aim to evoke the creepy and unsettling feeling the music is pushing through. When the bass comes the visuals begin to momentarily shift to a greyscale version, creating a break in the visuals. Following that when the chaos in the audio increases so does the chaos in the visuals with the use of modulateRotate for some feedback.
For sound, we started by bringing the two piano sounds that we really liked during our group practice session. After working on it for a while, we had different sounds playing at the same time which was a bit noisy and messy to hear. Therefore, to make the sounds more cohesive, we used mask and whenmod pattern control functions throughout the composition to create a consistent rhythmic structure. For example, we used a mask on d2 and d10 so they alternate and play one after another. This created a more defined rhythmic pattern in our performance. Later, we removed one of the piano sounds then introduced a mi-UGens and bass sound to create a more creepy and unsettling vibe. Throughout the sound creation process, we continuously searched for and experimented with different samples and sounds. That is when we found the f sharp and c notes for the bass, they were a perfect fit for the unsettling atmosphere we wanted to create.
Regarding the contributions Lujain worked on the visuals while Buka and Zeina worked on sound.