1

我目前正在开发一个应用程序来传输音频。我有两个服务正在运行,一个接收它,一个发送它。发件人的重要内容如下所示:

            final DatagramSocket dSocket = new DatagramSocket();

            android.os.Process
                    .setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

            Log.d(TAG, "Thread starting...");
            int buffersize = AudioRecord.getMinBufferSize(11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);

            AudioRecord arec = new AudioRecord(
                    MediaRecorder.AudioSource.MIC, 11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, buffersize);

            byte[] buffer = new byte[buffersize];
            Log.d(TAG, "Starting to record, buffersize=" + buffersize);
            arec.startRecording();

            while (isRunning && !isInterrupted()) {

                try {
                    Log.d(TAG, "Recording..");
                    arec.read(buffer, 0, buffersize);
                    DatagramPacket dPacket = new DatagramPacket(buffer,
                            buffersize);

                    for (Peer cur : mPeers) {
                        if(cur.isSelf) continue;

                        dPacket.setAddress(InetAddress
                                .getByName(cur.IP_ADDRESS));
                        dPacket.setPort(Config.UDP_PORT);
                        dSocket.send(dPacket);
                    }

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

此代码工作并提交音频数据包。

接收器服务如下所示:

            // DatagramSocket dSocket = new DatagramSocket();
            DatagramChannel dChannel = DatagramChannel.open();
            DatagramSocket dSocket = dChannel.socket();

            dSocket.setReuseAddress(true);
            dSocket.setSoTimeout(2000);
            dSocket.bind(new InetSocketAddress(Config.UDP_PORT));

            Log.d(TAG, "DatagramSocket open.");

            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

            int buffersize = AudioRecord.getMinBufferSize(11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);

            AudioTrack aTrack = new AudioTrack(
                    AudioManager.STREAM_VOICE_CALL, 11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, buffersize,
                    AudioTrack.MODE_STREAM);

            DatagramPacket dPacket = new DatagramPacket(
                    new byte[buffersize], buffersize);
            Log.d(TAG, "Packet with buffersize=" + buffersize);
            aTrack.play();
            Log.d(TAG, "Playing track..");

            byte[] buffer = new byte[buffersize];

            while (isRunning && !isInterrupted()) {
                try {
                    dSocket.receive(dPacket);
                    buffer = dPacket.getData();

                    aTrack.setPlaybackRate(11025);
                    aTrack.write(buffer, 0, buffer.length);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            aTrack.stop();

这也有效,但是在发送超过几秒钟后,会有很大的延迟,数据包仍然会到达但速度很慢,并且音频播放只是“滞后” - 我能做些什么来提高质量?这是一个直接的点对点连接,不涉及服务器。我应该增加缓冲区大小吗?当前缓冲区大小是我从 Android 获得的最小缓冲区大小,在我的设备(两个 Galaxy Nexus)上为 1024。顺便说一句,启动另一个线程的服务,其优先级设置为“紧急”(我相信这是最高可用的)。出于我的目的,mPeers 列表只有一个对等点,所以我猜“for”循环并没有真正延迟这一点。

4

2 回答 2

2

您是否检查过删除发送者循环的网络相关部分时会发生什么?即,来自麦克风的 read() 调用是否立即返回?另外,您描述了数据包到达缓慢,但是您是否检查过它们发送之间是否也有很大的延迟?

我问的原因是您描述的现象可能是由发送套接字阻塞引起的,因为它的缓冲区已满。如果套接字阻塞,send() 调用将需要很长时间才能完成。除非您有非常高的带宽流量或非常慢的 CPU,否则 UDP 套接字不应该发生这种情况(它们通常是触发后忘记),但值得检查。

为了避免阻塞,创建一个非阻塞套接字。我对 Java 网络不太熟悉,但似乎需要DatagramChannel来执行此操作。

于 2013-04-04T20:27:38.210 回答
0

好的,所以延迟消失了。我所做的是我只是增加了 UDP 数据包的缓冲区大小。我从 Android 收到的最小缓冲区大小是(在我的设备上)1024 字节。现在我做这样的事情:

int maxBufferSize = 4096; // my value. see what's working best for you.
int minBufferSize = AudioRecord.getMinBufferSize(11025,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);
int actualBufferSize = Math.max(minBufferSize, maxBufferSize);

4 KB 缓冲区,音频传输非常好,绝对没有延迟。

于 2013-04-11T08:53:45.670 回答