Java - Diffusion de la voix sur Java sockets
J'ai créé un Serveur d'application qui reçoit de son client, j'ai ensuite diffuser ce son qui est stocké comme octets et envoyer les octets de retour pour les clients qui sont connectés au serveur. maintenant, je suis seulement en utilisant un client au moment du test, et le client de la réception de la voix en arrière, mais le son est le bégaiement tout le temps. Peut-on s'il vous plaît dites-moi ce que je fais de mal?
Je crois que je comprends une partie de pourquoi le son n'est pas bien jouer mais ne savent pas comment résoudre le problème.
le code est ci-dessous.
Le Client:
La partie qui envoie la voix de serveur
public void captureAudio()
{
Runnable runnable = new Runnable(){
public void run()
{
first=true;
try {
final AudioFileFormat.Type fileType = AudioFileFormat.Type.AU;
final AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
line = (TargetDataLine)AudioSystem.getLine(info);
line.open(format);
line.start();
int bufferSize = (int) format.getSampleRate()* format.getFrameSize();
byte buffer[] = new byte[bufferSize];
out = new ByteArrayOutputStream();
objectOutputStream = new BufferedOutputStream(socket.getOutputStream());
running = true;
try {
while (running) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
objectOutputStream.write(buffer, 0, count);
out.write(buffer, 0, count);
InputStream input = new ByteArrayInputStream(buffer);
final AudioInputStream ais = new AudioInputStream(input, format, buffer.length /format.getFrameSize());
}
}
out.close();
objectOutputStream.close();
}
catch (IOException e) {
System.exit(-1);
System.out.println("exit");
}
}
catch(LineUnavailableException e) {
System.err.println("Line Unavailable:"+ e);
e.printStackTrace();
System.exit(-2);
}
catch (Exception e) {
System.out.println("Direct Upload Error");
e.printStackTrace();
}
}
};
Thread t = new Thread(runnable);
t.start();
}
La partie qui reçoit les octets de données à partir du serveur
private void playAudio() {
//try{
Runnable runner = new Runnable() {
public void run() {
try {
InputStream in = socket.getInputStream();
Thread playTread = new Thread();
int count;
byte[] buffer = new byte[100000];
while((count = in.read(buffer, 0, buffer.length)) != -1) {
PlaySentSound(buffer,playTread);
}
}
catch(IOException e) {
System.err.println("I/O problems:" + e);
System.exit(-3);
}
}
};
Thread playThread = new Thread(runner);
playThread.start();
//}
//catch(LineUnavailableException e) {
//System.exit(-4);
//}
}//End of PlayAudio method
private void PlaySentSound(final byte buffer[], Thread playThread)
{
synchronized(playThread)
{
Runnable runnable = new Runnable(){
public void run(){
try
{
InputStream input = new ByteArrayInputStream(buffer);
final AudioFormat format = getFormat();
final AudioInputStream ais = new AudioInputStream(input, format, buffer.length /format.getFrameSize());
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
sline = (SourceDataLine)AudioSystem.getLine(info);
sline.open(format);
sline.start();
Float audioLen = (buffer.length / format.getFrameSize()) * format.getFrameRate();
int bufferSize = (int) format.getSampleRate() * format.getFrameSize();
byte buffer2[] = new byte[bufferSize];
int count2;
ais.read( buffer2, 0, buffer2.length);
sline.write(buffer2, 0, buffer2.length);
sline.flush();
sline.drain();
sline.stop();
sline.close();
buffer2 = null;
}
catch(IOException e)
{
}
catch(LineUnavailableException e)
{
}
}
};
playThread = new Thread(runnable);
playThread.start();
}
}
OriginalL'auteur redoc01 | 2011-10-11
Vous devez vous connecter pour publier un commentaire.
Vous divisez le son des paquets en morceaux de 1000000 octets assez aléatoire et la lecture de ces sur le côté client ne tenant pas compte de la fréquence d'échantillonnage et la taille d'image qui vous calculée sur le côté serveur, de sorte que vous finirez par fractionnement des morceaux de son en deux qui vont ensemble.
Vous avez besoin pour décoder les mêmes morceaux sur le serveur l'envoie dès que vous les envoyez sur le côté client. Peut-être qu'il est plus facile de les envoyer à l'aide de http multipart (où de la séparation de données est assez facile), puis de le faire de la façon la plus simple via les sockets. Façon la plus simple pour cela est d'utiliser apache commons client http, jetez un oeil ici: http://hc.apache.org/httpclient-3.x/methods/multipartpost.html
Salut, j'ai enfin (AVEC VOTRE AIDE) réussi à le faire travailler, le son est clair, pas parfait, mais vous pouvez entendre le message assez clair, je voulais juste vous remercier de nouveau. je vais essayer de le tordre pour obtenir la voix beaucoup plus claire mais je suis plus qu'heureux avec ce travail.
OriginalL'auteur HefferWolf
En plus de HefferWolf réponse, j'aimerais ajouter que vous perdez beaucoup de bande passante, par l'envoi d'échantillons audio que vous lisez à partir du microphone. Vous ne dites pas si votre application est limitée à un réseau local, mais si vous allez sur Internet, il est courant de compresser/décompresser les données audio lors de l'envoi/réception.
Communément utilisés dans un schéma de compression est le Le codec SPEEX (une implémentation de Java est disponible ici), ce qui est relativement facile à utiliser malgré la documentation à la recherche d'un peu effrayant si vous n'êtes pas familier avec d'échantillonnage audio/compression.
Sur le côté client, vous pouvez utiliser
org.xiph.speex.SpeexEncoder
pour l'encodage:SpeexEncoder.init()
à l'initialisation d'un codeur (ce qui aura pour correspondre à la fréquence d'échantillonnage, le nombre de canaux et de stockage de votreAudioFormat
) et puisSpeexEncoder.processData()
pour coder une image,SpeexEncoder.getProcessedDataByteSize()
etSpeexEncoder.getProcessedData()
pour obtenir les données codéesSur le côté client d'utiliser
org.xiph.speex.SpeexDecoder
pour décoder les images que vous recevez:SpeexDecoder.init()
, pour initialiser le décodeur en utilisant les mêmes paramètres que le codeur,SpeexDecoder.processData()
pour décoder une image,SpeexDecoder.getProcessedDataByteSize()
etSpeexDecoder.getProcessedData()
pour obtenir les données codéesIl y a un peu plus compliqué que j'ai décrite. E. g., vous aurez à cracher les données dans la taille correcte pour le codage, qui dépend de la fréquence d'échantillonnage, les canaux et le nombre de bits par échantillon, mais vous allez voir une baisse spectaculaire du nombre d'octets que vous envoyez sur le réseau.
OriginalL'auteur edoloughlin