从蓝牙插座流式传输时,AudioTrack缓冲区欠载

时间:2017-09-10 22:51:42

标签: android sockets 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;
            }

        }

有关如何加快套接字读取或防止欠载的任何建议吗?

1 个答案:

答案 0 :(得分: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);

可能的根本原因

请注意不一致之处:

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

解决方案

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

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

  1. 关于另一个问题,但这可能很有用。问题及其答案:android - AudioRecord: buffer overflow? - Stack Overflow