AudioRecord记录在Android的大号断续声 [英] AudioRecord records intermittent sound in Android L

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

问题描述

我录音与AudioRecord在PCM16LE格式,8000Hz的,1路。它记录确定在Android的版本2.3.3-4.4.4,但奇怪的记录声音断断续续在Android的L(上承上启下5,承上启下7和仿真器)。

下面是录制的声音(上半场 - 记录,下半场 - 回放)的示例: <一href="https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error.m4a?dl=0">https://www.dropbox.com/s/3wcgufua5pphwtt/android_l_sound_record_error.m4a?dl=0

我试着用不同的采样率(4000,16000),并为8位,但声音一直是断断续续的播放录制的声音。有什么问题可以用这种声音?

我用这个AudioRecordTask录制音频getAudioRecord()用于初始化输入(操作过程中没有返回错误;接收的音频数据块大小同样为internalBufferSize值):

 公众最终诠释SAMPLING_RATE = 8000;

私人AudioRecord getAudioRecord(){
    INT internalBufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT); //返回640

    internalBufferSize = 8000; //还试图返回的值(640)和值2560,30000  - 无变化

    最终诠释来源;
    如果(Build.VERSION.SDK_INT&所述; 11){
        来源= MediaRecorder.AudioSource.MIC;
    } 其他 {
        来源= MediaRecorder.AudioSource.VOICE_COMMUNICATION;
    }

    AudioRecord纪录=新AudioRecord(SOURCE,
            采样率,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT,
            internalBufferSize);

    INT状态= record.getState();
    如果(状态!= AudioRecord.STATE_INITIALIZED){
        尝试 {
            record.release();
        }赶上(例外五){
        }
        返回null;
    }

    如果(record.getState()== android.media.AudioRecord.STATE_INITIALIZED){
        record.startRecording();
    } 其他 {
        record.release();
        返回null;
    }
    返回记录;
}

私有类AudioRecordTask扩展的AsyncTask&LT;虚空,虚空,虚空&GT; {
    最终诠释PARTIAL_BUFFER_SIZE = SAMPLING_RATE;
    最终诠释NECESSARY_BUFFER_SIZE = 15 * PARTIAL_BUFFER_SIZE * Short.SIZE / 8;
    最终诠释FULL_BUFFER_SIZE = NECESSARY_BUFFER_SIZE * 2; // XXX:* 2时,系统会返回比需要更多的数据的情况下
    短[] mBuffer;
    INT mTotalSize;
    INT mTotalSizeInBytes;
    布尔mResult;
    私有对象MLOCK =新的对象();

    @覆盖
    在preExecute保护无效()
    {
        mIsRecording = TRUE;

        mBuffer =新的短[FULL_BUFFER_SIZE]
        mTotalSize = 0;
        mTotalSizeInBytes = 0;
        mResult = FALSE;
    }

    @覆盖
    保护无效doInBackground(虚空......为arg0){
        同步(MLOCK){
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
            AudioRecord纪录= getAudioRecord();
            如果(记录== NULL){
                mResult = FALSE;
                返回null;
            }

            的for(int i = 0; I&LT; 15 * 100;我++){// XXX:* 100来记录足够的数据(系统可以返回较小的比需要的)
                INT DATALEN = record.read(mBuffer,mTotalSize,PARTIAL_BUFFER_SIZE);
                如果(DATALEN大于0){
                    mTotalSize + = DATALEN;
                    mTotalSizeInBytes = mTotalSize * 2;
                } 其他 {
                    Log.w(,错误+ DATALEN +在AudioRecord.read);
                }
                如果(isCancelled()|| mTotalSizeInBytes&GT; NECESSARY_BUFFER_SIZE){
                    打破;
                }
            }
            如果(record.getRecordingState()== AudioRecord.RECORDSTATE_RECORDING){
                record.stop();
            }

            record.release();
            mResult = TRUE;
            返回null;
        }
    }

    @覆盖
    保护无效onPostExecute(空R){
        同步(MLOCK){
            mIsRecording = FALSE;
            鳍();
        }
    }

    @覆盖
    保护无效onCancelled(){
        // XXX:老机器人(如2.3.3)onCancelled被调用时doInBackground仍在运行
        同步(MLOCK){
            mIsRecording = FALSE;
            如果(mAbort){
                返回;
            }
            鳍();
        }
    }

    私人无效鳍(){
        如果(mResult&安培;&安培; mTotalSizeInBytes大于0){
            sendRecordedAudioToServer(mBuffer,mTotalSize,mTotalSizeInBytes);
        } 其他 {
            showError(空);
        }
    }
}
 

解决方案

这是在Android的大号开发preVIEW一个错误:的 HTTPS://$c$c.google.com/p/android-developer-$p$pview/issues/detail? ID = 1492

AudioRecord.read为以字节为单位,而不是短裤值短期[]缓存参数返回值。

作为一种解决方法使用AudioRecord.read用byte []的缓冲区。

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

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

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