Sending audio stream over TCP, UnsupportedAudioFileException

前端 未结 2 826
北恋
北恋 2021-01-04 19:13

I have succeeded with sending and reading text and images data over TCP sockets. But I am unable to sending and reading audio stream data.

sample code at server:

相关标签:
2条回答
  • 2021-01-04 19:50

    The Server: The server just streams the bytes of a sound file. No AudioSytem involved. Pass the sound file as argument:

    java AudioServer "C:/Users/Public/Music/Sample Music/adios.wav"
    

    Code for class AudioServer:

    import java.io.*;
    import java.net.*;
    
    public class AudioServer {
        public static void main(String[] args) throws IOException {
            if (args.length == 0)
                throw new IllegalArgumentException("expected sound file arg");
            File soundFile = AudioUtil.getSoundFile(args[0]);
    
            System.out.println("server: " + soundFile);
    
            try (ServerSocket serverSocker = new ServerSocket(6666); 
                FileInputStream in = new FileInputStream(soundFile)) {
                if (serverSocker.isBound()) {
                    Socket client = serverSocker.accept();
                    OutputStream out = client.getOutputStream();
    
                    byte buffer[] = new byte[2048];
                    int count;
                    while ((count = in.read(buffer)) != -1)
                        out.write(buffer, 0, count);
                }
            }
    
            System.out.println("server: shutdown");
        }
    }
    

    The client: The client can play a soundfile passed via the command-line for testing if it works:

    java AudioClient "C:/Users/Public/Music/Sample Music/adios.wav"
    

    Called with no argument it connects to the server and plays the file received via an Socket:

    java AudioClient
    

    Code:

    import java.io.*;
    import java.net.*;
    import javax.sound.sampled.*;
    
    
    public class AudioClient {
        public static void main(String[] args) throws Exception {
            if (args.length > 0) {
                // play a file passed via the command line
                File soundFile = AudioUtil.getSoundFile(args[0]);
                System.out.println("Client: " + soundFile);
                try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(soundFile))) {
                    play(in);
                }
            }
            else {
                // play soundfile from server
                System.out.println("Client: reading from 127.0.0.1:6666");
                try (Socket socket = new Socket("127.0.0.1", 6666)) {
                    if (socket.isConnected()) {
                        InputStream in = new BufferedInputStream(socket.getInputStream());
                        play(in);
                    }
                }
            }
    
            System.out.println("Client: end");
        }
    
    
        private static synchronized void play(final InputStream in) throws Exception {
            AudioInputStream ais = AudioSystem.getAudioInputStream(in);
            try (Clip clip = AudioSystem.getClip()) {
                clip.open(ais);
                clip.start();
                Thread.sleep(100); // given clip.drain a chance to start
                clip.drain();
            }
        }
    }
    

    A utility class used by AudioServer and AudioClient:

    import java.io.File;
    
    public class AudioUtil {
        public static File getSoundFile(String fileName) {
            File soundFile = new File(fileName);
            if (!soundFile.exists() || !soundFile.isFile())
                throw new IllegalArgumentException("not a file: " + soundFile);
            return soundFile;
        }
    }
    
    0 讨论(0)
  • 2021-01-04 19:51

    The bytes will be received completely as TCP is reliable. There is another small issue. You need to play the received audio from the audio stream, only creating an audio input stream will not play it. There can be different possible techniques for playing the audio received. You can use a Clip or SourceDataLine from the Java Sound API. Also, do not create the AudioInputStream multiple times. Simply create it once and use it.

    Here's one of the possible solution you can use for playing the received audio.

    public class RDPPlayAudioBytes {
    
    private static Socket socket;
    private static BufferedInputStream inputStream;
    
    /**
     * @param args
     * @throws javax.sound.sampled.LineUnavailableException
     */
    public static void main(String[] args) throws LineUnavailableException {
        // TODO Auto-generated method stub
        // SocketAddress socketAddress = new InetSocketAddress("172.19.1.50", 4444);
        try {
            socket = new Socket("127.0.0.1", 6666);
    
            if (socket.isConnected()) {
    
                inputStream = new BufferedInputStream(socket.getInputStream());
    
                Clip clip = AudioSystem.getClip();
                AudioInputStream ais = AudioSystem.getAudioInputStream(inputStream);
                clip.open(ais);
                clip.start();
    
                while (inputStream != null) {
                    if (clip.isActive()) {
    
                        System.out.println("********** Buffred *********" + inputStream.available());
    
                    }
                }
    
            }
    
        } catch (IOException | UnsupportedAudioFileException e) {
            System.err.println(e);
        }
    }
    }
    

    You may need a different implementation based on your requirement. This is just a demonstration on how you can use the AudioInputStream for playing audio using Clip. You may notice quite a few changes in the code I have posted. I hope you understand this well.

    You may refer the Java Sound API docs to dive into the basics of playing audio.

    NOTE:

    1. Just for your knowledge, you may need to implement a listener so that the program do not get closed before the audio clip finishes playing. In the current implementation it won't happen due to the loop used. But it is better to use a listener. You may refer this post.

    2. You can also read the audio data into byte[] and then play it as soon as it is received. The implementation would change slightly.

    0 讨论(0)
提交回复
热议问题