我正在测试 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
值。更好的是,请考虑提取适当的常量或局部变量以将它们重新用于两个方法调用:sampleRate
、channelConfig
、audioFormat
。
其他引用文献(可能不需要。)
- 针对不同的问题,但它可能有用。问题及其答案:android - AudioRecord: buffer overflow? - Stack Overflow .
关于java - 从蓝牙套接字进行流式传输时,AudioTrack 缓冲区不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46146282/