0

I am making a skype like program. I have a "VoiceChat" class to handle the voice chat connections. I have a "ClientAudio" class to handle the client audio output. I also have a "ClientAudioRec" to handle receiving audio from the server and playing it. In the "ClientAudio" class I store the audio data in a buffer until it is full to try and reduce lag. Then I send it to the server. If I have two people in the call it lags unless the buffer is at 1000. When I add another person to the call it lags so much that you can't understand anyone. But I don't want to extend the buffer every time someone else joins because 1000 is already like a two-second delay. If anyone knows how to reduce the lag or make it almost instant that would really help. thank you in advance!!!

VoiceChat (Server Side)

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class VoiceChat extends Thread {
    private Socket s;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private Thread acceptThread;
    private int VoicePort;
    private int num;

    public VoiceChat(Socket sVoice, int VoicePort, Thread acceptThread) {
        s = sVoice;
        this.VoicePort = VoicePort;
        this.acceptThread = acceptThread;
        num = chat.threads.indexOf(this.acceptThread)+1;
        try {
            out = new ObjectOutputStream(s.getOutputStream());
            in = new ObjectInputStream(s.getInputStream());
            if(VoicePort <= 65511) {
                chat.users1_Voice.add(out);
            }else {
                chat.users2.add(out);
            }
        } catch (IOException e) {
            System.out.println("ERROR2");
            e.printStackTrace();
        }

    }
    public void run() {
            int bytesRead = 0;
            byte[] inBytes = new byte[100];
            while(bytesRead != -1) {
                    try {
                        bytesRead = in.read(inBytes, 0, inBytes.length);
                        }catch (IOException e) {
                        System.out.println("ERROR2");
                        if(VoicePort <= 65511) {
                            chat.users1_Voice.remove(out);
                        }else {
                            chat.users2.remove(out);
                        }
                    }
                    if(bytesRead > 0) {
                        System.out.println(chat.users1_Voice);
                            send(inBytes, bytesRead, out);
                            System.out.println("SENDING DATA");
                    }
              }
        }

    public void send(byte[] soundData, int bytesRead, ObjectOutputStream out) {
        if(VoicePort <= 65511) {
            for(ObjectOutputStream o : chat.users1_Voice) {
                try {
                    if(o != out) {
                        o.write(soundData, 0, bytesRead);
                        o.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }else {
            for(ObjectOutputStream o : chat.users2) {
                try {
                    if(o != out) {
                        o.write(soundData, 0, bytesRead);
                        o.flush();
                    }
                } catch (IOException e) {
                }
            }
        }
    }
}

ClientAudio

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;

public class ClientAudio implements Runnable {
    private ObjectOutputStream out = null;
    private AudioFormat af;
    private TargetDataLine microphone;

ClientAudio(AudioFormat af) {
    this.af = af;
}
public void run() {
    try {
        client.voiceSocket = new Socket("***IP***", client.VoicePort);
        Thread car = new Thread(new ClientAudioRec(af));
        car.start();
        out = new ObjectOutputStream(client.voiceSocket.getOutputStream());
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
        microphone = (TargetDataLine)AudioSystem.getLine(info);
        microphone.open(af);
        microphone.start();
        int bytesRead = 0;
        int offset = 0;
        byte[] soundData = new byte[1000];
        while(bytesRead != -1 && client.callRunning == true) {
            bytesRead = microphone.read(soundData, 0, soundData.length);
            if(bytesRead >= 0) {
                offset += bytesRead;
                if(offset == soundData.length) {
                    out.write(soundData, 0, bytesRead);
                    offset = 0;
                }
            }
        }
        microphone.close();
        try {
            client.voiceSocket.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        System.out.println("Client Audio Stopped Because Client Disconnected From Call");
    } catch (IOException | LineUnavailableException e) {
        microphone.close();
        try {
            client.voiceSocket.close();
        } catch (IOException e1) {
            System.out.println("Plug Microphone In...");
        }
        System.out.println("Client Audio Stopped...");
    }
}
}

ClientAudioRec

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class ClientAudioRec implements Runnable {
    private SourceDataLine inSpeaker = null;
    private AudioFormat audioformat;
    private ObjectInputStream in;

ClientAudioRec(AudioFormat af) {
    audioformat = af;
    try {
        in = new ObjectInputStream(client.voiceSocket.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void run() {
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioformat);
    try {
        inSpeaker = (SourceDataLine)AudioSystem.getLine(info);
        inSpeaker.open(audioformat);
    } catch (LineUnavailableException e1) {
        System.out.println("ERROR");
        e1.printStackTrace();
    }

    int bytesRead = 0;
    byte[] inSound = new byte[100000];
    inSpeaker.start();
    while(bytesRead != -1 && client.callRunning == true) {
        try{bytesRead = in.read(inSound, 0, inSound.length);} catch (Exception e){
            inSpeaker.close();
            System.out.println("Speaker Closed");
        }
        if(bytesRead >= 0) {
            inSpeaker.write(inSound, 0, bytesRead);
        }
    }
    inSpeaker.close();
    System.out.println("Speaker Closed Because Client Disconneted From Call");
}
}
Marcus Mardis
  • 59
  • 1
  • 8
  • This comment is probably superficial as I only scanned over your code. I noticed the buffer size in ClientAudioRec is 100_000. Could that be the source of your latency? Also, what sort of audio format are you using? Keeping the sample rate and number of bits down reduces the amount of processing that has to be done. Neat that you got it to work, though, even if it does lag! – Phil Freihofner Sep 06 '16 at 16:35
  • This is my audio format `public AudioFormat af = new AudioFormat(8000.0f,8,1,true,false);` Thanks for your comment – Marcus Mardis Sep 07 '16 at 01:40

0 Answers0