我正在开发语音应用程序。
我需要一个某种类型的缓冲队列,以便我在一个线程中连续记录,将缓冲区中的多个字节放入队列并传输到服务器,然后从队列中取出下一个缓冲区。
以下是录制代码:
Queue<byte[]> qArray = new LinkedList<byte[]>();
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
bData = new byte[BufferElements];
while (isRecording) {
recorder.read(bData, 0, BufferElements);
qArray.add(bData);
if (AudioRecord.ERROR_INVALID_OPERATION != 0) {
SendAudio();
}
}
}
}, "AudioRecorder Thread");
recordingThread.start();
但是在将数据发送到服务器时仍然缺少少量byte []数据
以下是向服务器代码发送语音:
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(ServerUrl.url_audio);
// Json Format
JSONObject holder = new JSONObject();
JSONArray jArray = new JSONArray();
try {
byte[] tmparr = qArray.poll();
for (int i = 0; i < tmparr.length; i++) {
jArray.put(i, tmparr[i]);
}
holder.put("Voice", jArray);
我不想错过任何正在录制的数据。
任何帮助都会受到赞赏。感谢
答案 0 :(得分:3)
将byte []放入队列时,需要创建一个新的缓冲区。否则,下一次录制将覆盖相同的缓冲区。只需将bData
的初始化移动到循环中:
Queue<byte[]> qArray = new LinkedList<byte[]>();
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
while (isRecording) {
bData = new byte[BufferElements];
recorder.read(bData, 0, BufferElements);
qArray.add(bData);
if (AudioRecord.ERROR_INVALID_OPERATION != 0) {
SendAudio();
}
}
}
}, "AudioRecorder Thread");
recordingThread.start();
您还应该添加逻辑来限制队列的大小。如果队列溢出,您仍然会丢失数据,但至少不会因内存不足错误而崩溃。
编辑以下是录制循环的修改版本,可以进行正确的错误检查。它使用Queue<ByteBuffer>
代替Queue<byte[]>
:
public void run() {
bData = ByteBuffer.allocate(BufferElements);
while (isRecording && !isInterrupted()) {
int result = recorder.read(bData, 0, BufferElements);
if (result > 0) {
qArray.add(bData);
SendAudio();
bData = ByteBuffer.allocate(BufferElements);
} else if (result == AudioRecord.ERROR_INVALID_OPERATION) {
Log.e("Recording", "Invalid operation error");
break;
} else if (result == AudioRecord.ERROR_BAD_VALUE) {
Log.e("Recording", "Bad value error");
break;
} else if (result == AudioRecord.ERROR) {
Log.e("Recording", "Unknown error");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
break;
}
}
}
当然,在某个地方,您需要致电recorder.startRecording()
,否则您将无法获得任何数据。