AudioRecord records intermittent sound in Android L Developer Preview

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).

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

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?

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

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

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

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

链接地址: http://www.djcxy.com/p/81968.html

上一篇: shinyapps.io和github软件包

下一篇: AudioRecord在Android L Developer Preview中记录间歇性声音