简体   繁体   中英

Send audio over UDP

So, I was looking for a microphone data sending tut, but I haven't found any. So I read Oracles tut about line opening and I am able to record the audio to a ByteArrayOutputStream, but now I have 2 problems!

First: How to play the recorded audio.

Second: if I am recording it to a BAOS how would i dynamically send it. I suppose I would send the data array, but would it be too processor hoggy to write to a BAOS every time I recieve it, or could I do it differently?

Current code:

import java.io.ByteArrayOutputStream;

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 MicrophoneRecorder {
    static boolean stopped = false;

    public static void main(String[] args) {
        AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true);
        TargetDataLine line = null;
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
        if (!AudioSystem.isLineSupported(info)) {
            System.out.println("Not supported!");
        }
        try {
            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format);
        } catch (LineUnavailableException ex) {
            ex.printStackTrace();
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int numBytesRead = 0;
        byte[] data = new byte[line.getBufferSize() / 5];
        line.start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                stopped = true;
            }
        }).start();
        while (!stopped) {
            numBytesRead = line.read(data, 0, data.length);
            out.write(data, 0, numBytesRead);
        }
    }

}

Thanks for any help given. Sincerely, Roberto Anić Banić

PS Seen this, doesn't work http://javasolution.blogspot.com/2007/04/voice-chat-using-java.html PPS Is UDP a good soulution or should I use RTSP

Here's an implementation of sending audio over UDP. Below is the client and server code. Basically the client code sends captured audio to the server, which plays it on receiving. The client can also play the captured audio.

Client code: VUClient.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.sound.sampled.*;

public class VUClient extends JFrame {

boolean stopaudioCapture = false;
ByteArrayOutputStream byteOutputStream;
AudioFormat adFormat;
TargetDataLine targetDataLine;
AudioInputStream InputStream;
SourceDataLine sourceLine;
Graphics g;

public static void main(String args[]) {
    new VUClient();
}

public VUClient() {
    final JButton capture = new JButton("Capture");
    final JButton stop = new JButton("Stop");
    final JButton play = new JButton("Playback");

    capture.setEnabled(true);
    stop.setEnabled(false);
    play.setEnabled(false);

    capture.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            capture.setEnabled(false);
            stop.setEnabled(true);
            play.setEnabled(false);
            captureAudio();
        }
    });
    getContentPane().add(capture);

    stop.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            capture.setEnabled(true);
            stop.setEnabled(false);
            play.setEnabled(true);
            stopaudioCapture = true;
            targetDataLine.close();
        }
    });
    getContentPane().add(stop);

    play.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            playAudio();
        }
    });
    getContentPane().add(play);

    getContentPane().setLayout(new FlowLayout());
    setTitle("Capture/Playback Demo");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(400, 100);
    getContentPane().setBackground(Color.white);
    setVisible(true);

    g = (Graphics) this.getGraphics();
}

private void captureAudio() {
    try {
        adFormat = getAudioFormat();
        DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, adFormat);
        targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
        targetDataLine.open(adFormat);
        targetDataLine.start();

        Thread captureThread = new Thread(new CaptureThread());
        captureThread.start();
    } catch (Exception e) {
        StackTraceElement stackEle[] = e.getStackTrace();
        for (StackTraceElement val : stackEle) {
            System.out.println(val);
        }
        System.exit(0);
    }
}

private void playAudio() {
    try {
        byte audioData[] = byteOutputStream.toByteArray();
        InputStream byteInputStream = new ByteArrayInputStream(audioData);
        AudioFormat adFormat = getAudioFormat();
        InputStream = new AudioInputStream(byteInputStream, adFormat, audioData.length / adFormat.getFrameSize());
        DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, adFormat);
        sourceLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
        sourceLine.open(adFormat);
        sourceLine.start();
        Thread playThread = new Thread(new PlayThread());
        playThread.start();
    } catch (Exception e) {
        System.out.println(e);
        System.exit(0);
    }
}

private AudioFormat getAudioFormat() {
    float sampleRate = 16000.0F;
    int sampleInbits = 16;
    int channels = 1;
    boolean signed = true;
    boolean bigEndian = false;
    return new AudioFormat(sampleRate, sampleInbits, channels, signed, bigEndian);
}

class CaptureThread extends Thread {

    byte tempBuffer[] = new byte[10000];

    public void run() {

        byteOutputStream = new ByteArrayOutputStream();
        stopaudioCapture = false;
        try {
            DatagramSocket clientSocket = new DatagramSocket(8786);
            InetAddress IPAddress = InetAddress.getByName("127.0.0.1");
            while (!stopaudioCapture) {
                int cnt = targetDataLine.read(tempBuffer, 0, tempBuffer.length);
                if (cnt > 0) {
                    DatagramPacket sendPacket = new DatagramPacket(tempBuffer, tempBuffer.length, IPAddress, 9786);
                    clientSocket.send(sendPacket);
                    byteOutputStream.write(tempBuffer, 0, cnt);
                }
            }
            byteOutputStream.close();
        } catch (Exception e) {
            System.out.println("CaptureThread::run()" + e);
            System.exit(0);
        }
    }
}

class PlayThread extends Thread {

    byte tempBuffer[] = new byte[10000];

    public void run() {
        try {
            int cnt;
            while ((cnt = InputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) {
                if (cnt > 0) {
                   sourceLine.write(tempBuffer, 0, cnt);
                }
            }
            //                sourceLine.drain();
            //             sourceLine.close();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(0);
        }
    }
}
}

Server code: VUServer.java

import java.io.*;
import java.net.*;
import javax.sound.sampled.*;

public class VUServer {

ByteArrayOutputStream byteOutputStream;
AudioFormat adFormat;
TargetDataLine targetDataLine;
AudioInputStream InputStream;
SourceDataLine sourceLine;

private AudioFormat getAudioFormat() {
    float sampleRate = 16000.0F;
    int sampleInbits = 16;
    int channels = 1;
    boolean signed = true;
    boolean bigEndian = false;
    return new AudioFormat(sampleRate, sampleInbits, channels, signed, bigEndian);
}

public static void main(String args[]) {
    new VUServer().runVOIP();
}

public void runVOIP() {
    try {
        DatagramSocket serverSocket = new DatagramSocket(9786);
        byte[] receiveData = new byte[10000];
        while (true) {
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            serverSocket.receive(receivePacket);
            System.out.println("RECEIVED: " + receivePacket.getAddress().getHostAddress() + " " + receivePacket.getPort());
            try {
                byte audioData[] = receivePacket.getData();
                InputStream byteInputStream = new ByteArrayInputStream(audioData);
                AudioFormat adFormat = getAudioFormat();
                InputStream = new AudioInputStream(byteInputStream, adFormat, audioData.length / adFormat.getFrameSize());
                DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, adFormat);
                sourceLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
                sourceLine.open(adFormat);
                sourceLine.start();
                Thread playThread = new Thread(new PlayThread());
                playThread.start();
            } catch (Exception e) {
                System.out.println(e);
                System.exit(0);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

class PlayThread extends Thread {

    byte tempBuffer[] = new byte[10000];

    public void run() {
        try {
            int cnt;
            while ((cnt = InputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) {
                if (cnt > 0) {
                    sourceLine.write(tempBuffer, 0, cnt);
                }
            }
            //  sourceLine.drain();
            // sourceLine.close();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(0);
        }
    }
}
}

Here is a sample code that helped me in order to stream and consuming audio via UDP. You can changed the infinite loop in order to limit the duration of the audio stream. Below is the client and server code. The audio input is from microphone.

server:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
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;
import javax.sound.sampled.TargetDataLine;

public class Sender {

public static void main(String[] args) throws IOException {

    AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, true);
    TargetDataLine microphone;
    SourceDataLine speakers;
    try {
        microphone = AudioSystem.getTargetDataLine(format);

        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
        microphone = (TargetDataLine) AudioSystem.getLine(info);
        microphone.open(format);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int numBytesRead;
        int CHUNK_SIZE = 1024;
        byte[] data = new byte[microphone.getBufferSize() / 5];
        microphone.start();


        DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
        speakers = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
        speakers.open(format);
        speakers.start();


        // Configure the ip and port
        String hostname = "localhost";
        int port = 5555;

        InetAddress address = InetAddress.getByName(hostname);
        DatagramSocket socket = new DatagramSocket();
        byte[] buffer = new byte[1024];
        for(;;) {                
            numBytesRead = microphone.read(data, 0, CHUNK_SIZE);
          //  bytesRead += numBytesRead;
            // write the mic data to a stream for use later
            out.write(data, 0, numBytesRead); 
            // write mic data to stream for immediate playback
            speakers.write(data, 0, numBytesRead);            
            DatagramPacket request = new DatagramPacket(data,numBytesRead, address, port);
            socket.send(request);

        }

    } catch (LineUnavailableException e) {
        e.printStackTrace();
    } 
}}

client:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketTimeoutException;   
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;
import javax.sound.sampled.TargetDataLine;

public class UdpClient {

public static void main(String[] args) throws LineUnavailableException {
     AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, true);
    TargetDataLine microphone;
    SourceDataLine speakers;
    microphone = AudioSystem.getTargetDataLine(format);

    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
    microphone = (TargetDataLine) AudioSystem.getLine(info);
    microphone.open(format);

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int numBytesRead;
    int CHUNK_SIZE = 1024;
    byte[] data = new byte[microphone.getBufferSize() / 5];
    microphone.start();

    int bytesRead = 0;
    DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
    speakers = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
    speakers.open(format);
    speakers.start();

    String hostname = "localhost";
    int port = 5555;

    try {
        InetAddress address = InetAddress.getByName(hostname);
        DatagramSocket socket = new DatagramSocket();

        DatagramSocket serverSocket = new DatagramSocket(5555);
        byte[] receiveData = new byte[1024];
        byte[] sendData = new byte[1024];

        while (true) {

            byte[] buffer = new byte[1024];
            DatagramPacket response = new DatagramPacket(buffer, buffer.length);
            serverSocket.receive(response);

            out.write(response.getData(), 0, response.getData().length);
            speakers.write(response.getData(), 0, response.getData().length);
            String quote = new String(buffer, 0, response.getLength());

            System.out.println(quote);
            System.out.println();

            //Thread.sleep(10000);
        }

    } catch (SocketTimeoutException ex) {
        System.out.println("Timeout error: " + ex.getMessage());
        ex.printStackTrace();
    } catch (IOException ex) {
        System.out.println("Client error: " + ex.getMessage());
        ex.printStackTrace();
    }/* catch (InterruptedException ex) {
        ex.printStackTrace();
    }*/
}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM