Real-time neural audio for live guitar. Performed three times, including at NIME 2026; accepted to the AI in Art Conference 2026.
I built a live performance system where I play guitar and neural audio models respond. The clean guitar goes to the amp as normal, while RAVE models react to how I'm playing and add a second, generated layer of sound. Performed three times, including a workshop demo at NIME 2026, and accepted for presentation at the AI in Art Conference 2026, with a research paper to follow.
Technically, the guitar's amplitude is analysed in real time and sorted into three states: quiet, mid and loud. Quiet plays an orchestral RAVE model (Sol Ordinario), loud lets a percussion model dominate, and mid mixes both. Every 20 seconds both models jump to a random point in their latent space, so the sound stays unpredictable for both performer and audience.
A practice assistant that reflects a guitarist's own playing back as live generative visuals. Presented at NIME 2026.
I built a real-time practice system for guitarists that never scores or grades. It compares a musician's live playing to a personal baseline learned from their own recordings, with no external standard, and reflects the result back as a live abstract visual. Built for my MSc thesis at UAL Creative Computing Institute and presented at NIME 2026.
Technically, four features are extracted from the guitar with librosa: loudness (RMS), brightness (spectral centroid), rhythmic activity (onset strength) and phrase continuity (inter-onset intervals). RMS, centroid and onset each pass through their own small autoencoder trained on the musician's recordings, and each result is compared with their baseline. The values are sent by OSC to a Processing sketch that draws a single shape, changing in size, colour, wobble and position.
GANs trained on images of Bucharest and London, exploring memory and migration.
Which Home? is an audiovisual installation about how memories of a place blur and shift after moving countries. A video of GAN-generated frames drifts from Bucharest to London, with two pieces of music built from field recordings of each city.
Two GANs were trained on around 1,500 of my own photos of each city, and frames saved across training show the images moving from abstract to clear. For the sound, pydub and numpy extracted the highest and lowest frequencies and their decibel levels from about 20 field recordings per city. These were mapped to notes in D melodic minor, with loudness as note velocity, and exported as MIDI with MIDIutil.
GAN outputs from the two trainings: Bucharest (left two) and London (right two), from clear to blurred and back to clear.Field recording data mapped to MIDI notes for Bucharest (left) and London (right); bigger dots are louder notes.
Using image clustering to work out the style of mystery paintings.
I came across some paintings and wanted to know what style they were. I used MobileNet to turn over 8,000 famous paintings into numerical features, reduced them with PCA, and grouped them with k-means clustering. Each mystery painting is placed in a cluster and compared with its closest matches. Most landed closest to Impressionism, and the portraits matched with Baroque.
One of the mystery paintings (top left) and its 12 closest matches. The model placed it with Impressionism.A portrait matched with Baroque.The Kaggle dataset of famous paintings, grouped into 10 clusters of visual similarity.
Shaping the energy arc of a DJ set from Spotify data.
I built a tool that helps DJs plan a set from a playlist. It scores each track on energy and danceability, orders them into the arc of a real set, with a build, a peak and a wind-down, and flags the transitions that will need the most work when mixing.
Technically, track features come from the Spotify and ReccoBeats APIs. A peak score combines energy and danceability (weighted 0.6 and 0.4), tracks are sorted by it, and the peak is placed about 70% of the way through the set. A transition cost for each pair of neighbouring tracks combines the BPM difference and the peak score difference.
The generated set: energy builds, peaks, then winds down.Transition cost between neighbouring tracks. The spikes show where mixing needs the most care.
A live race chatbot with simulated laps and LLM-generated commentary.
I built an F1 chatbot that commentates a simulated race lap by lap and answers questions about it, like who is leading, where a driver is or who is in the pits. It started from going to a live Grand Prix and wanting fans to be able to follow along without the commentary or trackside screens.
Technically, the race is a small Python simulation that stores each lap's events in a structured state: pit stops, slowdowns, crashes, tyres and positions. Regex-based intent recognition maps a fan's question to that state, and the Gemini API turns each lap's events into short live commentary. Tested with five users, who all liked the commentary.
Gemini commentary for each lap, and questions answered from the race state.