I am trying to record a simple sound bite from a microphone and send it to another computer via a UDP datagram using socket programming. I have all three components developed (the server and client, and the sound recording), and the two main components work independently. I can record the sound and play it back, and I can send text back and forth between client-server, but I don't really know what step to take next to allow the transfer of sound. Can anyone make any suggestions?
I guess it comes down to how is the audio stored, and how that can be placed into the UDP datagram.
AudioCapture:
Client:
Server:
I guess it comes down to how is the audio stored, and how that can be placed into the UDP datagram.
AudioCapture:
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.sound.sampled.*; public class AudioCapture01 extends JFrame{ boolean stopCapture = false; ByteArrayOutputStream byteArrayOutputStream; AudioFormat audioFormat; TargetDataLine targetDataLine; AudioInputStream audioInputStream; SourceDataLine sourceDataLine; public static void main( String args[]){ new AudioCapture01(); }//end main public AudioCapture01(){//constructor final JButton captureBtn = new JButton("Capture"); final JButton stopBtn = new JButton("Stop"); final JButton playBtn = new JButton("Playback"); captureBtn.setEnabled(true); stopBtn.setEnabled(false); playBtn.setEnabled(false); //Register anonymous listeners captureBtn.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e){ captureBtn.setEnabled(false); stopBtn.setEnabled(true); playBtn.setEnabled(false); //Capture input data from the // microphone until the Stop // button is clicked. captureAudio(); }//end actionPerformed }//end ActionListener );//end addActionListener() getContentPane().add(captureBtn); stopBtn.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e){ captureBtn.setEnabled(true); stopBtn.setEnabled(false); playBtn.setEnabled(true); //Terminate the capturing of // input data from the // microphone. stopCapture = true; }//end actionPerformed }//end ActionListener );//end addActionListener() getContentPane().add(stopBtn); playBtn.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e){ //Play back all of the data // that was saved during // capture. playAudio(); }//end actionPerformed }//end ActionListener );//end addActionListener() getContentPane().add(playBtn); getContentPane().setLayout( new FlowLayout()); setTitle("Capture/Playback Demo"); setDefaultCloseOperation( EXIT_ON_CLOSE); setSize(250,70); setVisible(true); }//end constructor //This method captures audio input // from a microphone and saves it in // a ByteArrayOutputStream object. private void captureAudio(){ try{ //Get everything set up for // capture audioFormat = getAudioFormat(); DataLine.Info dataLineInfo = new DataLine.Info( TargetDataLine.class, audioFormat); targetDataLine = (TargetDataLine) AudioSystem.getLine( dataLineInfo); targetDataLine.open(audioFormat); targetDataLine.start(); //Create a thread to capture the // microphone data and start it // running. It will run until // the Stop button is clicked. Thread captureThread = new Thread( new CaptureThread()); captureThread.start(); } catch (Exception e) { System.out.println(e); System.exit(0); }//end catch }//end captureAudio method //This method plays back the audio // data that has been saved in the // ByteArrayOutputStream private void playAudio() { try{ //Get everything set up for // playback. //Get the previously-saved data // into a byte array object. byte audioData[] = byteArrayOutputStream. toByteArray(); //Get an input stream on the // byte array containing the data InputStream byteArrayInputStream = new ByteArrayInputStream( audioData); AudioFormat audioFormat = getAudioFormat(); audioInputStream = new AudioInputStream( byteArrayInputStream, audioFormat, audioData.length/audioFormat. getFrameSize()); DataLine.Info dataLineInfo = new DataLine.Info( SourceDataLine.class, audioFormat); sourceDataLine = (SourceDataLine) AudioSystem.getLine( dataLineInfo); sourceDataLine.open(audioFormat); sourceDataLine.start(); //Create a thread to play back // the data and start it // running. It will run until // all the data has been played // back. Thread playThread = new Thread(new PlayThread()); playThread.start(); } catch (Exception e) { System.out.println(e); System.exit(0); }//end catch }//end playAudio //This method creates and returns an // AudioFormat object for a given set // of format parameters. If these // parameters don't work well for // you, try some of the other // allowable parameter values, which // are shown in comments following // the declarations. private AudioFormat getAudioFormat(){ float sampleRate = 8000.0F; //8000,11025,16000,22050,44100 int sampleSizeInBits = 16; //8,16 int channels = 1; //1,2 boolean signed = true; //true,false boolean bigEndian = false; //true,false return new AudioFormat( sampleRate, sampleSizeInBits, channels, signed, bigEndian); }//end getAudioFormat //===================================// //Inner class to capture data from // microphone class CaptureThread extends Thread{ //An arbitrary-size temporary holding // buffer byte tempBuffer[] = new byte[10000]; public void run(){ byteArrayOutputStream = new ByteArrayOutputStream(); stopCapture = false; try{//Loop until stopCapture is set // by another thread that // services the Stop button. while(!stopCapture){ //Read data from the internal // buffer of the data line. int cnt = targetDataLine.read( tempBuffer, 0, tempBuffer.length); if(cnt > 0){ //Save data in output stream // object. byteArrayOutputStream.write( tempBuffer, 0, cnt); }//end if }//end while byteArrayOutputStream.close(); }catch (Exception e) { System.out.println(e); System.exit(0); }//end catch }//end run }//end inner class CaptureThread //===================================// //Inner class to play back the data // that was saved. class PlayThread extends Thread{ byte tempBuffer[] = new byte[10000]; public void run(){ try{ int cnt; //Keep looping until the input // read method returns -1 for // empty stream. while((cnt = audioInputStream. read(tempBuffer, 0, tempBuffer.length)) != -1){ if(cnt > 0){ //Write data to the internal // buffer of the data line // where it will be delivered // to the speaker. sourceDataLine.write( tempBuffer, 0, cnt); }//end if }//end while //Block and wait for internal // buffer of the data line to // empty. sourceDataLine.drain(); sourceDataLine.close(); }catch (Exception e) { System.out.println(e); System.exit(0); }//end catch }//end run }//end inner class PlayThread //===================================// }//end outer class AudioCapture01.java
Client:
import java.net.* ; /** * A simple datagram client * Shows how to send and receive UDP packets in Java * * @author P. Tellenbach, http://www.heimetli.ch * @version V1.00 */ public class DatagramClient { private final static int PACKETSIZE = 100 ; public static void main( String args[] ) { // Check the arguments if( args.length != 2 ) { System.out.println( "usage: java DatagramClient host port" ) ; return ; } DatagramSocket socket = null ; try { // Convert the arguments first, to ensure that they are valid InetAddress host = InetAddress.getByName( args[0] ) ; int port = Integer.parseInt( args[1] ) ; // Construct the socket socket = new DatagramSocket() ; // Construct the datagram packet byte [] data = "Hello Server".getBytes() ; DatagramPacket packet = new DatagramPacket( data, data.length, host, port ) ; // Send it socket.send( packet ) ; // Set a receive timeout, 2000 milliseconds socket.setSoTimeout( 2000 ) ; // Prepare the packet for receive packet.setData( new byte[PACKETSIZE] ) ; // Wait for a response from the server socket.receive( packet ) ; // Print the response System.out.println( new String(packet.getData()) ) ; } catch( Exception e ) { System.out.println( e ) ; } finally { if( socket != null ) socket.close() ; } } }
Server:
import java.net.* ; /** * A simple datagram server * Shows how to send and receive UDP packets in Java * * @author P. Tellenbach, http://www.heimetli.ch * @version V1.01 */ public class DatagramServer { private final static int PACKETSIZE = 100 ; public static void main( String args[] ) { // Check the arguments if( args.length != 1 ) { System.out.println( "usage: DatagramServer port" ) ; return ; } try { // Convert the argument to ensure that is it valid int port = Integer.parseInt( args[0] ) ; // Construct the socket DatagramSocket socket = new DatagramSocket( port ) ; System.out.println( "The server is ready..." ) ; for( ;; ) { // Create a packet DatagramPacket packet = new DatagramPacket( new byte[PACKETSIZE], PACKETSIZE ) ; // Receive a packet (blocking) socket.receive( packet ) ; // Print the packet System.out.println( packet.getAddress() + " " + packet.getPort() + ": " + new String(packet.getData()) ) ; // Return the packet to the sender socket.send( packet ) ; } } catch( Exception e ) { System.out.println( e ) ; } } }