音频延迟-Java程序到Android程序

时间:2018-07-04 21:23:10

标签: java android audio

我有两个Java Thread,一个是我的计算机,另一个是在Android手机上。我想通过UDP数据包(对等连接)将从计算机上的音频线获得的音频流传输到Android的电话。

一切正常,除了有时音频滞后和我遇到的主要问题是延迟。我尝试了不同的采样频率和不同的缓冲区大小,但两个设备之间仍然存在延迟(1-2秒)。

那是我的代码。

Java Audio Sender

(new Thread(() -> {

            while (true) {
                   System.out.println(">>"+status);
                while (status) {

                    try {

                        int size = tdl.read(buffer, 0, buffer.length);
                        if(size>0){
                        DatagramPacket sendPacket
                                = new DatagramPacket(buffer, size, hostAddress, port);
                        socket.send(sendPacket);
                        }
                    } catch (IOException ex) {
                        Logger.getLogger(AudioSender.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (java.lang.NullPointerException ne) {

                    }
                }
            }

        })).start();

 public static void setUpAudioDriverInput() throws LineUnavailableException {
    if (tdl != null) {
        tdl.close();
    }

    int channels = 1;
    int sampleSize = 16;
    boolean bigEndian = false;

    format = new AudioFormat(rate, sampleSize, channels, true, bigEndian);

    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

    Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();

    Mixer mixer = AudioSystem.getMixer(mixerInfoFinal.get(lineIndex));

    tdl = (TargetDataLine) mixer.getLine(info);
    tdl.open(format);
    tdl.start();

}

Java Android音频接收器

  public void getStreaming(){


       getThread = new Thread(new Runnable() {
        @Override
        public void run() {

            try {

                System.out.println("Thread Streamer is Starting..  status2"+ status2);

                int rate = Integer.parseInt(((Spinner) findViewById(R.id.rateSpinner)).getSelectedItem().toString());
                int bufferSize = Integer.parseInt(((Spinner) findViewById(R.id.bufferSizeSpinner)).getSelectedItem().toString());

                String payload = ((EditText) findViewById(R.id.nameEditText)).getText().toString();
                payload += "#" + rate;
                payload += "#" + bufferSize;
                payload += "#";

                System.out.println(">>>"+payload);

                InetAddress address = InetAddress.getByName(((EditText) findViewById(R.id.ipAddressEditText)).getText().toString());
                DatagramPacket dp = new DatagramPacket(payload.getBytes(),payload.length(),address,8088);
                socket.send(dp);

               byte[] buffer = new byte[bufferSize];

                AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, rate, channelConfigOUT, audioFormat, buffer.length, AudioTrack.MODE_STREAM);
                audioTrack.play();


                DatagramPacket receivedPacket = new DatagramPacket(buffer,buffer.length);

                System.out.println("BufferSize "+ bufferSize);




                boolean skip=false;

                while(status2 && !Thread.currentThread().isInterrupted()){
                    try {
                        socket.receive(receivedPacket);
                    }catch(SocketTimeoutException ste){
                        skip=true;
                        Thread.currentThread().interrupt();
                        stopStreaming();

                    }
                    if(!skip) {
                        buffer = receivedPacket.getData();
                        audioTrack.write(buffer, 0, buffer.length);
                        System.out.println("aaa" + Thread.currentThread().getName());

                    }
                }

            } catch (SocketException e) {
                e.printStackTrace();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }



        }
    });

    getThread.start();

}

谢谢。

更新 我发现这是我正在尝试超级转发数据包的网络。对于另一个网络,延迟实际上减少了不到半秒。昨天我可以用它看电影,并且延迟是极限。我会让您知道我是否会改进系统。

1 个答案:

答案 0 :(得分:0)

您不应使用TargetDataLine读取大小来创建DatagramPacket。 创建的数据包太多。

最好是读取几千字节的数据(即多次tdl读取),然后将它们发送到一个“大” DatagramPacket中。