A low-latency, real-time audio streaming system built with Java and Netty. SonicNet implements a custom UDP-based protocol optimized for voice communication with adaptive jitter buffering and packet loss concealment.
- Custom Binary Protocol: Efficient 24-byte header with sequence numbers and timestamps
- Adaptive Jitter Buffer: Dynamically adjusts to network conditions (3-10 packets)
- Packet Loss Concealment (PLC): Linear interpolation for smooth audio during packet loss
- Low Latency: ~50-100ms end-to-end latency
- High Performance: Non-blocking I/O with Netty framework
- Network Resilient: Handles up to 10% packet loss gracefully
- Sample Rate: 8 kHz (phone quality)
- Sample Size: 16-bit PCM
- Channels: Mono
- Frame Duration: 20ms (320 bytes/frame)
- Bandwidth: ~125 Kbps
- Java 17 or higher
- Maven 3.6+
- Microphone and speakers/headphones
mvn clean compilemvn exec:java -Dexec.mainClass="com.sonicnet.AudioReceiver"The receiver will start listening on port 9876.
mvn exec:java -Dexec.mainClass="com.sonicnet.AudioSenderRemote" \
-Dexec.args="localhost 9876"Speak into your microphone - you should hear yourself through the speakers with ~100ms delay.
Note: Use headphones to avoid feedback!
sonic-net/
├── src/main/java/com/sonicnet/
│ ├── protocol/ # Custom protocol implementation
│ │ ├── SonicNetPacket.java
│ │ ├── SonicNetPacketEncoder.java
│ │ └── SonicNetPacketDecoder.java
│ ├── buffer/ # Jitter buffer
│ │ └── JitterBuffer.java
│ ├── audio/ # Audio capture/playback
│ │ ├── AudioConfig.java
│ │ ├── AudioCapture.java
│ │ └── AudioPlayback.java
│ ├── handler/ # Netty handlers
│ │ └── PacketHandler.java
│ ├── AudioReceiver.java # Main receiver application
│ └── AudioSenderRemote.java # Main sender application
└── pom.xml
Test audio capture and playback locally:
mvn exec:java -Dexec.mainClass="com.sonicnet.audio.AudioLoopbackTest"Test with simulated network conditions (latency, jitter, packet loss):
# Add 50ms delay + 10ms jitter + 2% packet loss
sudo tc qdisc add dev lo root netem delay 50ms 10ms loss 2%
# Run receiver and sender as usual
# Remove simulation when done
sudo tc qdisc del dev lo rootSend audio to a remote host:
mvn exec:java -Dexec.mainClass="com.sonicnet.AudioSenderRemote" \
-Dexec.args="<remote-host> 9876"Typical Performance (localhost):
- Latency: 50-100ms
- Packet Loss: <2%
- Jitter: 2-5ms
- Buffer Size: 5-7 packets
Under Network Stress (50ms delay, 10ms jitter, 2% loss):
- Latency: 100-150ms
- Packet Loss: 2-3%
- Buffer adapts to 7-10 packets
- Audio quality: Good (PLC active)
Each packet contains:
- Magic Number: 0x534F4E49 ("SONI")
- Version: Protocol version (1)
- Sequence Number: Monotonically increasing
- Timestamp: Nanosecond precision
- Payload Length: Audio frame size
- Payload: Raw PCM audio data
The jitter buffer dynamically adjusts its size based on observed network jitter:
- Reorders out-of-order packets
- Detects and reports packet loss
- Adapts buffer size (3-10 packets) based on jitter
- Provides smooth playback despite network variations
When packets are lost, the system uses linear interpolation between the last two received frames to generate smooth audio, minimizing audible artifacts.
- Netty 4.1.104: High-performance network framework
- Java Sound API: Audio capture and playback
- SLF4J + Logback: Logging
This project is for educational purposes.
Built as a learning project to understand:
- UDP networking and real-time protocols
- Audio signal processing
- Adaptive buffering algorithms
- High-performance Java engineering