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

标签 java 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;
            }

        }

关于如何加快从套接字的读取速度或防止一般情况下的欠载运行,有什么建议吗?

最佳答案

根本原因分析

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

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);

可能的根本原因

请注意不一致之处:

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

解决方案

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

其他引用文献(可能不需要。)

  1. 针对不同的问题,但它可能有用。问题及其答案:android - AudioRecord: buffer overflow? - Stack Overflow .

关于java - 从蓝牙套接字进行流式传输时,AudioTrack 缓冲区不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46146282/

相关文章:

java - 使用旧版本的 JodaTime 检查 DateTime 是否在未来

java - Maven有Java持续测试插件吗?

android - Flutter 致命异常 : java. lang.RuntimeException : Failure delivering result ResultInfo{who=null, request=1, result=0, data=Intent

android - osmdroid、Maps API v2 和 fragment

python - C 和 Python - 使用套接字进行通信

java - 传递泛型并且必须转换为正确的对象java。不应该转换

java - 如何从azure函数java中的POST请求中提取数据

java - 如何通过点击/单击两个按钮(组合)在文本框中显示文本

c# - 如何为在套接字上发送的文件创建长度前缀?

c - Accept() 改变服务器套接字描述符