业务场景
最近遇到了一个需求中涉及到了音频的录制与播放。功能大体如下:有四个mic,可以任选其中一个先进行录音,然后进行播放。
我的做法是首先录制出一份完整的原始音频文件,然后将其拆分为四份,最终保存在车机系统中。经过上面所说的做法,最终会生成5个pcm文件,其中一个是完整的,另外4个是拆分的。
复现问题代码
while (isRecording) {
int read = mRecorder.read(data, 0, buffersize);
Log.d(TAG, " recording read: " + read);
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
try {
for (int i = 0; i < (read / 8); i++) {
data1[i * 2] = data[i * 8];
data1[i * 2 + 1] = data[i * 8 + 1];
data2[i * 2] = data[i * 8 + 2];
data2[i * 2 + 1] = data[i * 8 + 3];
data3[i * 2] = data[i * 8 + 4];
data3[i * 2 + 1] = data[i * 8 + 5];
data4[i * 2] = data[i * 8 + 6];
data4[i * 2 + 1] = data[i * 8 + 7];
}
os.write(data);
os1.write(data1);
os2.write(data2);
os3.write(data3);
os4.write(data4);
Log.d(TAG, "run-----data ");
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Write data to record file error !");
}
}
}
出现问题的关键代码如上。后来测试的时候发现,在播放录音时会偶发出现二倍速播放的情况和音频缺少只播放一点声音的情况。
对比正常log与异常log,发现read值的总和不同,初步判断在录音时就出现了问题。当时猜想会不会是缓存数据的数组大小不足,导致数据缺失。之后我将buffersize的大小设置为一个更大的值,测试后发现问题依旧存在。
解决问题
既然不是数组大小的事,那上述代码中就还剩下5个写入操作需要考虑了。仔细分析,上面的代码是存在问题的,当标志位不变时(正在录音),while循环中的代码会反复运行,每一次都要进行5个文件的写入操作,效率是低下的,可能某一次写入出现了问题就导致异常情况的发生。
因此我们需要将写入操作提到while循环的外面。
while (isRecording) {
int read = mRecorder.read(data, 0, buffersize);
Log.d(TAG, " recording read: " + read);
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
for (int i = 0; i < read; i++) {
dataHolder[capacity + i] = data[i];
}
capacity += read;
}
}
Log.d(TAG, "run------capacity : " + capacity);
try {
for (int i = 0; i < (capacity / 8); i++) {
data1[i * 2] = dataHolder[i * 8];
data1[i * 2 + 1] = dataHolder[i * 8 + 1];
data2[i * 2] = dataHolder[i * 8 + 2];
data2[i * 2 + 1] = dataHolder[i * 8 + 3];
data3[i * 2] = dataHolder[i * 8 + 4];
data3[i * 2 + 1] = dataHolder[i * 8 + 5];
data4[i * 2] = dataHolder[i * 8 + 6];
data4[i * 2 + 1] = dataHolder[i * 8 + 7];
}
os.write(dataHolder, 0, capacity);
os1.write(data1, 0, capacity / 4);
os2.write(data2, 0, capacity / 4);
os3.write(data3, 0, capacity / 4);
os4.write(data4, 0, capacity / 4);
Log.d(TAG, "run-----data has been written !");
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "Write data to record file error !");
}
最后经过测试,不再出现异常情况,问题解决。