Skip to content

Instantly share code, notes, and snippets.

@HyCraftHD
Created December 3, 2019 22:29
Show Gist options
  • Save HyCraftHD/4374742d0cc5e6d1c9b111ad52fa2083 to your computer and use it in GitHub Desktop.
Save HyCraftHD/4374742d0cc5e6d1c9b111ad52fa2083 to your computer and use it in GitHub Desktop.
Basic UDP audio transmission (Audio data is encoded with opus)
package test.voicechat;
import java.net.*;
import javax.sound.sampled.*;
import org.concentus.*;
/**
* Use of native java opus port (https://github.com/lostromb/concentus) used in here. Every other opus java wrapper shoud work too.
*/
public class VoiceChat {
private final static String HOST = "echo.udp-server.example";
private static DatagramSocket socket;
private static final AudioFormat format = new AudioFormat(48000, 16, 2, true, false);
private static final DataLine.Info micInfo = new DataLine.Info(TargetDataLine.class, format);
private static final DataLine.Info speakerInfo = new DataLine.Info(SourceDataLine.class, format);
public static void main(String[] args) throws Exception {
socket = new DatagramSocket();
send();
receive();
}
private static void send() {
final Runnable runnable = () -> {
try {
TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(micInfo);
targetLine.open(format);
targetLine.start();
OpusEncoder encoder = new OpusEncoder(48000, 2, OpusApplication.OPUS_APPLICATION_AUDIO);
encoder.setBitrate(96000);
encoder.setSignalType(OpusSignal.OPUS_SIGNAL_MUSIC);
encoder.setComplexity(10);
int numBytesRead;
byte[] targetData = new byte[960 * 2 * 2];
byte[] encodedData = new byte[1000];
while (true) {
numBytesRead = targetLine.read(targetData, 0, targetData.length);
if (numBytesRead >= 0) {
int encodedLength = encoder.encode(targetData, 0, 960, encodedData, 0, encodedData.length);
final DatagramPacket datagramPacket = new DatagramPacket(encodedData, encodedLength, InetAddress.getByName(HOST), 10000);
socket.send(datagramPacket);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
new Thread(runnable).start();
}
private static void receive() {
final Runnable runnable = () -> {
try {
SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(speakerInfo);
sourceLine.open(format);
sourceLine.start();
OpusDecoder decoder = new OpusDecoder(48000, 2);
byte[] decodedData = new byte[960 * 2 * 2];
while (true) {
final byte[] array = new byte[1000];
final DatagramPacket datagramPacket = new DatagramPacket(array, array.length);
socket.receive(datagramPacket);
decoder.decode(array, 0, datagramPacket.getLength(), decodedData, 0, 960, false);
sourceLine.write(decodedData, 0, decodedData.length);
}
} catch (Exception ex) {
ex.printStackTrace();
}
};
new Thread(runnable).start();
}
}
@kmaxii
Copy link

kmaxii commented Sep 7, 2023

Getting this issue with the encoder.encode method:
Required type: short[] Provided: byte[]
Any ideas why mine requires short[] instead of byte[]?

@HyCraftHD
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment