javaandroidaudiostreaming

Stream Audio from Client to Server to Multiple Clients Java


As the title suggests I'm making an application that Streams audio from a client to a server where I store the audio and then distribute it to multiple clients to be played. I've got everything working up until the audio storage, but I can't seem to stream the audio to multiple clients.

Here is my attempt:

Server Code:

class Server {

    static int port = 50005;
    static int listen = 50010;
    static int listenerPort = 50015;
    static DatagramSocket serverSocket, listenSocket,
                            broadcastSocket;
    static byte[] receiveData, listenData;
    static DatagramPacket receivePacket, listenPacket;
    static DataOutputStream out;
    static ArrayList<String> listeners = new ArrayList<String>();
    static File file = new File("recording.bin");
    static boolean active = true;


    public static void main(String args[]) throws Exception {
        //Define the Receiving Datagram Socket
        serverSocket = new DatagramSocket(port);
        //Define the Timeout of the socket
        serverSocket.setSoTimeout(10000);
        //Define the listening socket
        listenSocket = new DatagramSocket(listen);
        listenSocket.setSoTimeout(10000);
        //Define Broadcasting socket
        broadcastSocket = new DatagramSocket();

        //Define data size, 1400 is best sound rate so far
        receiveData = new byte[1400];
        listenData = new byte[256];

        //Define the DatagramPacket object
        receivePacket = new DatagramPacket(receiveData, receiveData.length);
        listenPacket = new DatagramPacket(listenData, listenData.length);

        //Prepare the DataOutputStream to write to file.
        out = new DataOutputStream(new FileOutputStream(file));
        //Write and Broadcast on a separate thread
        Thread t = new Thread() {
            @Override public void run() {
                getPackets();
            }
        };
        t.start();
        //Set up Connection Listener on a separate thread
        Thread l = new Thread() {
            @Override public void run() {
                listen();
            }
        };
        l.start();
    }

    /***
     * Function that gets the audio data packets
     * saves them, and outputs the audio to the speakers.
     */
    public static void getPackets() {
        while (active) {
            try {
                //Wait until packet is received
                serverSocket.receive(receivePacket);
                System.out.println("Receiving Data");
                //Write to Binary file
                out.write(receiveData, 0, receiveData.length);
                //Send data
                sendData(receivePacket.getData());
            } catch (IOException e) {
                active = false;
                //If connection times out close it
                try {
                    out.close();
                } catch (IOException t) {
                    //Do nothing
                }
                System.out.println("Converting to audio");
                //Convert audio file
                new Convert().toWAV();
            }
        }
    }

    /***
     * Function that listens if there are any connections made to
     * the listener port and creates a datagram socket to stream audio
     * to anyone who connects
     */
    public static void listen() {
        while (active) {
            try {
                //Wait until packet is received
                listenSocket.receive(listenPacket);
                listeners.add(listenPacket.getAddress().getHostAddress());
                System.out.println("Client received");

            } catch (IOException e) {
                if(active) {
                    listen();
                }
            }
        }
    }

    public static void sendData(byte[] data) {
        try {
            for (int i = 0; i < listeners.size(); i++) {
                InetAddress destination = InetAddress.getByName(listeners.get(i));
                broadcastSocket.send(new DatagramPacket(data, data.length, destination, listenerPort));
                System.out.println("Sending Data");
            }
        } catch (Exception e) {
            //If it failed to send don't do anything
            e.printStackTrace();
        }
    }
}

And here is the code I run on the multiple clients:

class Receiver {

    static AudioInputStream ais;
    static AudioFormat format;
    static boolean active = true;
    static int port = 50015;
    static DatagramSocket serverSocket, socket;
    static byte[] receiveData;
    static DatagramPacket receivePacket, packet;
    static ByteArrayInputStream bais;
    static int sampleRate = 8000;
    static int time = 10;

    static DataLine.Info dataLineInfo;
    static SourceDataLine sourceDataLine;

    public static void main(String args[]) throws Exception {
        socket = new DatagramSocket();
        InetAddress destination = InetAddress.getByName("server ip address");
        byte[] temp = new byte[256];
        //putting buffer in the packet
        packet = new DatagramPacket(temp, temp.length, destination, 50010);

        socket.send(packet);

        //Define the Receiving Datagram Socket
        serverSocket = new DatagramSocket(port);

        //Define data size, 1400 is best sound rate so far
        receiveData = new byte[1400];
        //Define the format sampleRate, Sample Size in Bits, Channels (Mono), Signed, Big Endian
        format = new AudioFormat(sampleRate, 16, 1, true, false);
        //Define the DatagramPacket object
        receivePacket = new DatagramPacket(receiveData, receiveData.length);
        //Prepare the Byte Array Input Stream
        bais = new ByteArrayInputStream(receivePacket.getData());
        //Now concert the Byte Array into an Audio Input Stream
        ais = new AudioInputStream(bais, format, receivePacket.getLength());

        //Define DataLineInfo
        dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
        //Get the current Audio Line from the system
        sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
        //Open up sourceDataLine and Start it
        sourceDataLine.open(format);
        sourceDataLine.start();

        //Write and play on a separate thread
        Thread t = new Thread() {
            @Override
            public void run() {
                getPackets();
            }
        };
        t.start();
        //Now keep track of time
        while (time > 0) {
            time--;
            Thread.sleep(1000);
            if (time == 0) {
                active = false;
            }
        }
        //Close SourceDataLine
        sourceDataLine.drain();
        sourceDataLine.close();
    }

    /***
     * Function that gets the audio data packets
     * saves them, and outputs the audio to the speakers.
     */
    public static void getPackets() {
        try {
            while (active) {
                System.out.println("Receiving");
                //Wait until packet is received
                serverSocket.receive(receivePacket);
                //Reset time
                time = 10;
                //Send data to speakers
                toSpeaker(receivePacket.getData());
            }
        } catch (IOException e) {
        }
    }

    /***
     * Function that plays the sound bytes with the speakers.
     * @param soundbytes = bytes of sound sent to speakers
     */
    public static void toSpeaker(byte soundbytes[]) {
        try {
            sourceDataLine.write(soundbytes, 0, soundbytes.length);
        } catch (Exception e) {
            System.out.println("Not working in speakers...");
            e.printStackTrace();
        }
    }
}

I've verified that the server does receive the initial connection which I use to get the clients ip address, but the client does not seem to receive any data, and I'm getting no errors on run time.

Any help would be much appreciated.


Solution

  • Ok so after messing around with this for a while I've realized the problem was not the code, but rather that the admins of the building's network where blocking me. So I'm going to go ahead and mark this as answered.