A modern WebRTC-based cross-device music collaboration application. Send synchronized musical notes from one device (sender) to multiple devices (receivers) in the same room using audio frequency pairing.
- Frequency-Based Pairing: Devices pair automatically by detecting audio frequencies (2000Hz+)
- WebRTC Communication: Low-latency peer-to-peer data transmission
- Synchronized Playback: Accurate time synchronization for multi-device music playback
- Step Sequencer: 16-step, 4-note sequencer for each connected receiver
- Real-time Visualization: Frequency spectrum visualization for pairing feedback
- Modern Stack: Built with Bun, Vite, Svelte 5, TypeScript, and Tone.js
βββββββββββββββββββ ββββββββββββββββββββ
β Sender Device β β Receiver Device β
β β β β
β βββββββββββββ β β ββββββββββββββ β
β β Sequencer β β β β Frequency β β
β β β β β β Detector β β
β βββββββ¬ββββββ β β ββββββββ¬ββββββ β
β β β β β β
β βΌ β β βΌ β
β βββββββββββββ β β ββββββββββββββ β
β β Beeping ββββΌβββββ β β Pairing β β
β β @ freq β β β β β β β
β βββββββββββββ β ββββββΌββΆββββββββββββββ β
β β β β β β
β βΌ β β βΌ β
β βββββββββββββ β β ββββββββββββββ β
β β WebRTC ββββΌββββββββββΌββΆβ WebRTC β β
β β PeerJS β β β β PeerJS β β
β βββββββ¬ββββββ β β ββββββββ¬ββββββ β
β β β β β β
β βΌ β β βΌ β
β βββββββββββββ β β ββββββββββββββ β
β β WebSocket ββββΌββββββββββΌββΆβ WebSocket β β
β βββββββββββββ β β ββββββββββββββ β
βββββββββββββββββββ ββββββββββββββββββββ
β β
ββββββββββ¬βββββββββββββββββ
βΌ
ββββββββββββββββββββββ
β Bun Server β
β β
β ββββββββββββββββ β
β β Room Manager β β
β ββββββββββββββββ β
β ββββββββββββββββ β
β β WebSocket β β
β β Handler β β
β ββββββββββββββββ β
β ββββββββββββββββ β
β β Time Sync β β
β ββββββββββββββββ β
ββββββββββββββββββββββ
- Bun v1.0 or higher
- Modern web browser with WebRTC support
- Microphone access (for receivers)
# Clone the repository
git clone https://github.com/yourusername/digital-orchestra.git
cd digital-orchestra
# Install dependencies
bun install# Start both the Vite dev server and Bun backend
bun run devThis will start:
- Frontend dev server at
http://localhost:5173 - Backend WebSocket server at
ws://localhost:3000/ws
# Build the frontend
bun run build
# Start the production server
bun run startThe server will serve both the static files and WebSocket connections on port 3000.
- Open the app and select "Sender" mode
- Your device will emit a beeping sound at a specific frequency
- Wait for receivers to connect (they'll appear as sequencers)
- Click the steps in the sequencer to create patterns
- Press "Play" to start sending notes to all connected receivers
- Open the app and select "Receiver" mode
- Allow microphone access when prompted
- Place your device near the sender to detect the pairing frequency
- Once paired, you'll automatically connect and be assigned a color
- Notes will play automatically when the sender plays
- Bun: Runtime and package manager
- Native WebSockets: Built-in Bun WebSocket API
- TypeScript: Type-safe server code
- Svelte 5: Reactive UI framework
- Vite: Fast build tool and dev server
- TypeScript: Type-safe client code
- Tone.js: Web Audio synthesis and scheduling
- PeerJS: WebRTC abstraction for peer connections
- Time Synchronization: Custom implementation using performance.now() and server timestamps
- Frequency Detection: Web Audio API with FFT analysis
- State Management: Svelte stores for reactive data
- Responsive Design: Mobile-first CSS with modern layout
digital-orchestra/
βββ src/
β βββ client/ # Frontend code
β β βββ lib/
β β β βββ components/ # Svelte components
β β β βββ stores/ # State management
β β β βββ utils/ # Audio, WebRTC, time sync
β β βββ styles/ # Global CSS
β β βββ App.svelte # Main app component
β β βββ main.ts # Entry point
β βββ server/ # Backend code
β β βββ index.ts # Bun server
β β βββ room-manager.ts # Room/frequency management
β β βββ websocket-handler.ts
β βββ shared/ # Shared types
β βββ types.ts
βββ public/
β βββ audio/ # Audio samples
βββ index.html # HTML template
βββ vite.config.ts # Vite configuration
βββ tsconfig.json # TypeScript config
βββ package.json
# Build the image
docker build -t digital-orchestra .
# Run the container
docker run -p 3000:3000 digital-orchestra- Install Railway CLI:
npm i -g @railway/cli - Login:
railway login - Initialize:
railway init - Deploy:
railway up
- Install flyctl:
curl -L https://fly.io/install.sh | sh - Login:
fly auth login - Launch:
fly launch - Deploy:
fly deploy
For production deployments, set:
PORT=3000
NODE_ENV=productionThe app uses frequencies from 2000Hz to 12000Hz (100Hz increments) for pairing. This range is optimal for mobile device speakers and microphones.
Edit in src/shared/types.ts:
export const FREQUENCY_BASE = 2000;
export const FREQUENCY_INCREMENT = 100;Place audio samples in public/audio/s0/, s1/, s2/, etc. Each folder represents a color and should contain:
1.mp3- F#32.mp3- E33.mp3- C#34.mp3- A3
Adjust sync parameters in src/client/lib/utils/time-sync.ts:
private readonly sampleCount = 10; // Number of samples
private readonly resyncInterval = 30000; // Re-sync every 30sReceivers need microphone access to detect the pairing frequency. Ensure your browser has permission and you're using HTTPS in production (or localhost for development).
- Check that both devices are on the same network
- Ensure PeerJS cloud server is accessible
- For production, consider hosting your own PeerServer
- Ensure audio context is started (requires user interaction)
- Check that audio samples are loaded correctly
- Verify Web Audio API support in your browser
- Increase device volume
- Reduce background noise
- Check microphone permissions
- Adjust detection threshold in
frequency-detector.ts
bun run type-checkbun run buildOutput will be in dist/ directory.
Messages:
register-peer: Register client with peer IDcreate-room: Sender creates a room, receives frequencyfind-room: Receiver searches for room by frequencyleave-room: Client leaves current room
GET /api/time: Get server timestamp for synchronizationGET /api/stats: Get server statistics (connections, rooms)GET /api/health: Health check endpoint
The app uses Tone.js for audio synthesis and scheduling:
- Sender: Schedules notes with Tone.Transport and sends timestamps
- Receiver: Receives timestamps, calculates offset, plays notes at correct time
- Time Sync: Continuously syncs client time with server for accuracy
Contributions are welcome! Please feel free to submit a Pull Request.
ISC
This is a complete rewrite from the ground up. The old code is preserved in the legacy/ folder for reference.
- β Bun replaces Node.js + Express
- β Native WebSockets replace Socket.io
- β Svelte replaces jQuery
- β Canvas API replaces P5.js
- β Custom time sync replaces timesync library
- β TypeScript throughout
- β Modern build tools (Vite)
- β Improved architecture and code organization
The new version is not compatible with v1 clients. All devices must use the new version.
Made with β€οΈ for collaborative music experiences