Chorus

Everyone in a room opens one URL. Their phones become a single, room-sized speaker array.

Start here

There are two roles. One person hosts from a laptop or tablet — that screen shows the QR code and the Start button. Everyone else joins as a player, and their phone becomes one speaker in the array.

If you are running it

Host a room

Opens the host screen with a QR code and a 4-character room code. This is the only screen with Start and Stop.

Host a room
If you are joining

Join a room

Normally you just scan the host's QR code. Use this if you would rather type the room code by hand.

Join a room
The host screen lives at /?host=1 — the plain address always opens the join screen. That is the one thing worth remembering; bookmark the host link if you will run this more than once.

Running a performance

  1. Open the host screen

    Go to /?host=1 on a laptop, tablet, or a screen everyone can see. A QR code and a 4-character room code appear within a second or two. Codes never contain 0, O, 1, or I, so there is nothing ambiguous to read aloud.

  2. Everyone scans the code

    Phones land on the join screen with the room code already filled in. Each person taps Join and allows microphone access. Anyone who cannot scan can open the site directly and type the code.

  3. Wait for the dots to turn green

    Each phone shows its position number and a coloured status dot. The host's roster lists every device and a running tally — “3 locked · 1 syncing · 0 unsynced · 0 playback-only”. Green means that phone has locked onto the shared clock.

  4. Optionally add the host as a speaker

    The host is not a speaker until you tap Enable audio (join as player). Browsers only allow audio and microphone access from a direct tap, which is why this is a separate button.

  5. Press Start

    Playback begins about five seconds later on every device at once — the coordinator schedules a start time slightly in the future so everyone can hit it together. Stop ends it. You can start and stop as often as you like.

    Start plays an improvised piece. To play a song of your own instead, use Upload an MP3 and Play track — see playing your own music.

What you'll hear

Start improvises — it does not play a song. Each time you press Start, the server picks a random seed and every phone generates the same notes from it independently. No audio is streamed and no music file is involved. If you want a specific song instead, see playing your own music below.

Press Start again and you get an entirely different piece. The same seed would reproduce the same piece exactly, note for note, on every device.

Give it thirty seconds before you judge it
The opening is deliberately bare: one long note that walks slowly from one end of the array to the other, so you can hear the sound physically travel across the room. It stays sparse for the first few seconds, then builds — more melody, a low pulse, and quiet sustained chords — reaching full density after about half a minute. If it sounds like almost nothing is happening at first, that is the piece working as designed, not a fault.
It plays until you stop it
New material is generated continuously in eight-second sections. There is no end; press Stop when you have had enough.
Numbers matter
With one or two phones you will barely hear the spatial effect, because there is no array for sound to move across. Six or more unlocks the low pulse voice, and a dozen spread around a room is where it starts to feel like a single instrument.
Under the hood
A minor pentatonic scale at 96 BPM, played on simple synthesized tones. Each note carries a position — fixed, or sweeping across the array — and each phone plays it at a volume set by how close that note is to its own place in the room. That is the whole trick.

Playing your own music

You can also hand the array an MP3 instead of letting it improvise. On the host screen, tap Upload an MP3, pick a file, and wait for the name to appear. Every phone downloads and decodes it in the background, then Play track starts it on all of them at the same instant.

Unison, or sweeping
By default every phone plays the whole track together — the room becomes one large speaker. Tap Sweep and the track keeps playing everywhere, but a band of emphasis travels back and forth across the array, so the music moves through the crowd. You can flip the toggle mid-song; it will not interrupt playback.
Latecomers are fine
A phone that joins, or finishes downloading, after the track has started does not wait for the next one — it drops in at exactly the right point, already aligned with everyone else.
Keep it short and small
The limit is 20 MB, and shorter is safer: every phone holds the whole decoded track in memory, so something over about six minutes risks running older phones out of RAM. A normal three or four minute song is comfortable.
The track and the generative score take turns
Starting a track stops the improvised piece, and vice versa — they would otherwise play over each other. Uploading a new file also stops whatever is currently playing.
Anyone with the address can upload. There is no password on this demo, so treat the box as public and don't put anything sensitive through it. Uploads are deleted automatically after a few hours.

Reading the status dot

The dot appears on each player's screen and beside every row of the host's roster.

A phone that reads playback only could not hear the sync chirps — usually a covered microphone or aggressive echo cancellation. It still plays, timed over the network instead of acoustically, so it is roughly twenty milliseconds looser than the rest. A few of these in a crowd is fine.

The other controls

Balance
Plays a steady reference tone on every phone at once so you can walk the room and even out the volume levels. Players see “Balancing — playing reference tone” while it runs. Tap it again to switch it off before starting the piece.
Your position number
The large number on a player's screen is that phone's place in the array, out of the room total. Position decides which voices that phone plays and where it sits in the sound field, so the music can sweep across the crowd. Numbers are reassigned as people join and leave, and changes take effect at the next musical section.
Debug readout
Triple-tap anywhere to toggle a technical overlay — clock state, sync quality, connection status, round-trip time, audio context details — plus a trim slider to nudge that one device's output by up to 6 dB. Triple-tap again to dismiss it.

Getting a good result

If something goes wrong

“Join” fails, or the microphone was blocked
Chorus cannot run without microphone access — it is the timing mechanism, and no audio is recorded or transmitted anywhere. If you dismissed the permission prompt, allow the microphone for this site in your browser settings and reload. On iOS, Safari will not re-prompt until you reload the page.
A dot sits on amber and never turns green
Usually the microphone is obstructed or the room is very loud. Uncover the mic and hold the phone up. If it settles on playback only, that phone will still play — just slightly less tightly.
Nothing happens when the host presses Start
Start stays greyed out until the room exists, and a phone only plays once it has joined and unlocked audio. Check the roster shows the devices you expect. Remember the host itself is silent until you tap Enable audio (join as player).
A phone shows an “Update” screen
That device is running an older version than the room. Tap Reload and rejoin.
Everyone dropped out at once
Rooms are held in memory on the server, so if it restarts they are gone. Reload the host screen to create a fresh room and have everyone scan the new code.

A note on privacy

The microphone is used only to listen for the inaudible sync chirps the phones play to each other. Microphone audio is never recorded, stored, or sent to the server. Improvised music is generated on each device, so nothing is streamed for it. An MP3 you upload is the one exception: it is stored on the server so the other phones can download it, and it is deleted automatically after a few hours. Anyone who knows the address can upload to this demo.