从蓝牙套接字流式传输时,AudioTrack 缓冲区不足

KSh*_*hak 6 java sockets android bluetooth audiotrack

我正在测试一个 Android 应用程序的概念,该应用程序允许您通过 RFCOMM(从 PC 到手机)流式传输蓝牙。我可以毫无问题地将音频从我的计算机传输到手机并开始流式传输音频。

问题是音频开始断断续续,我从AudioTrack. 从套接字读取是最耗时的。当我对它计时,当>= 1000读取返回需要几毫秒时就会发生欠载,而平均需要几百次才能返回。这是我的代码如下:

    public ConnectedThread(BluetoothSocket socket) {
        this.setPriority(MAX_PRIORITY);
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;
        // Get the input and output streams; using temp objects because
        // member streams are final.
        try {
            tmpIn = socket.getInputStream();
        } catch (IOException e) {
            Log.e(TAG, "Error occurred when creating input stream", e);
        }
        try {
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
            Log.e(TAG, "Error occurred when creating output stream", e);
        }
        minBuffSize = AudioTrack.getMinBufferSize(48000,  CHANNEL_OUT_MONO,  AudioFormat.ENCODING_PCM_16BIT);
        m_audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT, minBuffSize /* 1 second buffer */,
                AudioTrack.MODE_STREAM);

        mmBuffer = new byte[minBuffSize * 2];
        mmInStream = tmpIn;
        mmOutStream = tmpOut;
//        distream = new DataInputStream(new BufferedInputStream(mmInStream, 1000000));
        distream = new DataInputStream(mmInStream);
    }

    public void run() {

        int numBytes = 0; // bytes returned from read()

        // Keep listening to the InputStream until an exception occurs.

        boolean firstRun = true;

        while (true) {

            try {
                final long startTime = System.currentTimeMillis();
                distream.readFully(mmBuffer);
                final long endTime = System.currentTimeMillis();
                int temp = m_audioTrack.write(mmBuffer, 0, mmBuffer.length);
                System.out.println("Total execution time: " + (endTime - startTime) );
                if (firstRun) {
                    m_audioTrack.play();
                    firstRun = false;
                }
            } catch (IOException e) {
                Log.d(TAG, "Input stream was disconnected", e);
                break;
            }

        }
Run Code Online (Sandbox Code Playgroud)

关于如何加快从套接字的读取速度或总体上防止欠载的任何建议?

Ser*_*nov 1

根本原因分析

让我们考虑一下这段代码:

minBuffSize = AudioTrack.getMinBufferSize(48000,  CHANNEL_OUT_MONO,  AudioFormat.ENCODING_PCM_16BIT);
m_audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, CHANNEL_OUT_STEREO,
        AudioFormat.ENCODING_PCM_16BIT, minBuffSize /* 1 second buffer */,
        AudioTrack.MODE_STREAM);
Run Code Online (Sandbox Code Playgroud)

可能的根本原因

请注意以下不一致之处:

  • AudioTrack.getMinBufferSize()使用该值调用该方法CHANNEL_OUT_MONO
  • 使用该值AudioTrack调用构造函数CHANNEL_OUT_STEREO

解决方案

请考虑对AudioTrack.getMinBufferSize()方法调用使用相同的参数,特别是CHANNEL_OUT_STEREO值。更好的是,请考虑提取适当的常量或局部变量以将它们重新用于两个方法调用:sampleRatechannelConfigaudioFormat

其他参考资料(可能不需要。)

  1. 关于不同的问题,但它可能有用。问题及其答案:android - AudioRecord:缓冲区溢出?- 堆栈溢出