AudioRecord在Android L Developer Preview中记录断断续续的声音 [英] AudioRecord records intermittent sound in Android L Developer Preview

查看:129
本文介绍了AudioRecord在Android L Developer Preview中记录断断续续的声音的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在以PCM16LE格式,8000Hz,1声道的AudioRecord录制声音.在Android 2.3.3-4.4.4版中可以正常记录,但在Android L(5.0)Developer Preview(在nexus 5,nexus 7和模拟器上)中记录奇怪的间歇声音.

I'm recording sound with AudioRecord in PCM16LE format, 8000Hz, 1channel. It records ok in Android versions 2.3.3-4.4.4, but records strange intermittent sound in Android L(5.0) Developer Preview (on nexus 5, nexus 7 and emulator).

以下是录制的声音的样本(上半部分-录制,下半部分-播放): https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error. m4a?dl = 0

Here is the sample of recorded sound (the first half - recording, the second half - playback): https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error.m4a?dl=0

我尝试使用不同的采样率(4000、16000)和8bit播放录制的声音,但声音始终是断断续续的.这种声音可能是什么问题?

I tried to play recorded sound using different sample rate (4000, 16000) and as 8bit but sound keeps to be intermittent. What the problem could be with this sound?

我正在使用此AudioRecordTask通过getAudioRecord()录制音频以初始化输入(操作过程中未返回任何错误;接收大小等于internalBufferSize值的音频块)

I'm using this AudioRecordTask to record audio with getAudioRecord() for initializing input (no errors returned during operation; receiving audio chunks sized equally to internalBufferSize value):

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

推荐答案

这是Android L开发者预览版中的错误:https://code.google.com/p/android-developer-preview/issues/detail?id=1492

It's a bug in Android L Developer Preview: https://code.google.com/p/android-developer-preview/issues/detail?id=1492

AudioRecord.read为short []缓冲区参数返回的值以字节为单位,而不是短裤的值.

AudioRecord.read for short[] buffer argument returns value in bytes instead of value in shorts.

作为解决方法,将AudioRecord.read与byte []缓冲区一起使用.

As a workaround use AudioRecord.read with byte[] buffer.

这篇关于AudioRecord在Android L Developer Preview中记录断断续续的声音的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆