我正在做一个应用程序,用于接收运行我编写的Java服务器的Raspberry播放的实时音频,并且必须将其广播到多个客户端。现在我正在使用MulticastSocket来实现它。
到目前为止,问题是收到的音频坏了,我不知道为什么。另一个问题是使用Marshmallow Android,它无法加入一组MulticastSocket,当其他设备加入服务器时,音频会自动从Android切断。
Android方面:
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class Receiver implements Runnable {
private final String SERVER_ADDRESS = "224.0.0.3";
private final int SERVER_PORT = 48824;
private final int SAMPLE_RATE = 32000;
private final int PACKET_SIZE = 1200;
private final int CHANNEL_OUT_MONO = 4;
private final int CHANNEL_OUT_STEREO = 12;
private static boolean stopTrack = false;
public static AudioTrack track;
private static AudioManager am;
private static InetAddress inetAddress;
private static MulticastSocket multicastSocket;
private final int CHANNELS = CHANNEL_OUT_MONO;
@Override
public void run() {
//ESTABLISH CONNECTION
try{
inetAddress = InetAddress.getByName(SERVER_ADDRESS);
}catch(Exception ex){
Log.e("TCP","Error: server probably closed");
ex.printStackTrace();
}
//am = (AudioManager)Context.getSystemService(Context.AUDIO_SERVICE);
//int currentVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
stopTrack = false;
int minSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, CHANNELS, AudioFormat.ENCODING_PCM_16BIT);
Log.e("AUDIO","minSize = " + minSize);
track = new AudioTrack( AudioManager.STREAM_MUSIC, SAMPLE_RATE,
CHANNELS, AudioFormat.ENCODING_PCM_16BIT,
minSize, AudioTrack.MODE_STREAM);
track.play();
try{
multicastSocket = new MulticastSocket(SERVER_PORT);
multicastSocket.joinGroup(inetAddress);
//multicastSocket.setReuseAddress(true);
//multicastSocket.setBroadcast(true);
byte[] buffer = new byte[PACKET_SIZE];
while(!stopTrack){
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
multicastSocket.receive(packet);
track.write(packet.getData(), 0, buffer.length);
//Log.e("ERRO","SOCKET");
}
//multicastSocket.close();
} catch (Exception e) {
Log.e("UDP", "Receiver error", e);
}
}
public static void stopLiveAudioStream(){
track.stop();
multicastSocket.close();
stopTrack = true;
}
}
和UDP服务器:
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Port;
import java.util.*;
import java.net.*;
import java.io.*;
public class MulticastUDPServer {
private static final String INET_ADDR = "224.0.0.3";
private static final int SERVER_PORT = 48824;
private static final int BUFFER_SIZE = 4096;
private static final int PACKET_SIZE = 1200;
private static DatagramSocket socket;
private static InetAddress addr;
public static void main(String[] args){
Mixer.Info minfo[] = AudioSystem.getMixerInfo();
System.out.println("STARTING SERVER!");
try{
addr = InetAddress.getByName(INET_ADDR);
}catch(Exception ex){
System.out.println("ADDRESS ERROR: " + INET_ADDR);
}
try(DatagramSocket serverSocket = new DatagramSocket()){
AudioFormat format = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, format);
DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine sourceDataLine;
TargetDataLine targetDataLine = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
targetDataLine.open(format, BUFFER_SIZE);
targetDataLine.start();
sourceDataLine = (SourceDataLine) AudioSystem.getLine(sourceInfo);
sourceDataLine.open(format, BUFFER_SIZE);
sourceDataLine.start();
byte[] targetData = new byte[PACKET_SIZE];
System.out.println("\n\nBROADCASTING!");
while(true){
targetDataLine.read(targetData,0,targetData.length);
serverSocket.send(new DatagramPacket(targetData, targetData.length, addr, SERVER_PORT));
}
}catch(Exception ex){
ex.printStackTrace();
}
}
private static AudioFormat getAudioFormat() {
float sampleRate = 32000.0F;
int sampleSizeBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleSizeBits, channels, signed, bigEndian);
}
}
提前致谢。