我用PCM16LE格式的AudioRecord录制声音,8000Hz,1声道。它在Android版本2.3.3-4.4.4中记录正常,但在Android L(5.0)开发人员预览版中记录了奇怪的间歇性声音(在nexus 5,nexus 7和仿真器上)。
以下是录制声音的样本(前半部分录制,后半部分录制): https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error.m4a?dl=0
我尝试使用不同的采样率(4000,16000)和8bit播放录制的声音,但声音保持间歇性。这个声音会出现什么问题?
我使用此AudioRecordTask来记录带有getAudioRecord()的音频,用于初始化输入(操作期间没有返回错误;接收的音频块大小与internalBufferSize值相同):
public final int SAMPLING_RATE = 8000;
private AudioRecord getAudioRecord() {
int internalBufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT); //returns 640
internalBufferSize = 8000; //also tried returned value (640) and values 2560, 30000 - no changes
final int SOURCE;
if (Build.VERSION.SDK_INT < 11) {
SOURCE = MediaRecorder.AudioSource.MIC;
} else {
SOURCE = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
}
AudioRecord record = new AudioRecord(SOURCE,
SAMPLING_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
internalBufferSize);
int state = record.getState();
if (state != AudioRecord.STATE_INITIALIZED) {
try {
record.release();
} catch (Exception e) {
}
return null;
}
if (record.getState() == android.media.AudioRecord.STATE_INITIALIZED) {
record.startRecording();
} else {
record.release();
return null;
}
return record;
}
private class AudioRecordTask extends AsyncTask<Void, Void, Void> {
final int PARTIAL_BUFFER_SIZE = SAMPLING_RATE;
final int NECESSARY_BUFFER_SIZE = 15 * PARTIAL_BUFFER_SIZE * Short.SIZE / 8;
final int FULL_BUFFER_SIZE = NECESSARY_BUFFER_SIZE * 2; //XXX: * 2 for the case when system returns more data than needed
short[] mBuffer;
int mTotalSize;
int mTotalSizeInBytes;
boolean mResult;
private Object mLock = new Object();
@Override
protected void onPreExecute()
{
mIsRecording = true;
mBuffer = new short[FULL_BUFFER_SIZE];
mTotalSize = 0;
mTotalSizeInBytes = 0;
mResult = false;
}
@Override
protected Void doInBackground(Void... arg0) {
synchronized (mLock) {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
AudioRecord record = getAudioRecord();
if (record == null) {
mResult = false;
return null;
}
for (int i = 0; i < 15 * 100; i++) { //XXX: * 100 to record enough data (system can return lesser than needed)
int datalen = record.read(mBuffer, mTotalSize, PARTIAL_BUFFER_SIZE);
if (datalen > 0) {
mTotalSize += datalen;
mTotalSizeInBytes = mTotalSize*2;
} else {
Log.w("", "error " + datalen + " in AudioRecord.read");
}
if (isCancelled() || mTotalSizeInBytes > NECESSARY_BUFFER_SIZE) {
break;
}
}
if (record.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
record.stop();
}
record.release();
mResult = true;
return null;
}
}
@Override
protected void onPostExecute(Void r) {
synchronized (mLock) {
mIsRecording = false;
fin();
}
}
@Override
protected void onCancelled() {
//XXX: on old Androids (e.g. 2.3.3) onCancelled being called while doInBackground is still running
synchronized (mLock) {
mIsRecording = false;
if (mAbort) {
return;
}
fin();
}
}
private void fin() {
if (mResult && mTotalSizeInBytes > 0) {
sendRecordedAudioToServer(mBuffer, mTotalSize, mTotalSizeInBytes);
} else {
showError(null);
}
}
}
答案 0 :(得分:4)
这是Android L开发者预览版中的一个错误:https://code.google.com/p/android-developer-preview/issues/detail?id=1492
用于short []缓冲区参数的AudioRecord.read以字节为单位返回值,而不是短路值。
作为解决方法,使用带有byte []缓冲区的AudioRecord.read。