AudioRecord并不总是记录预期的内容

时间:2014-08-04 19:15:06

标签: java android arrays wav audiorecord

我在使用AudioRecord时遇到了问题。

我正在开发一个应用程序,它需要记录一些来自MIC的脉冲响应并用它制作一些DSP。

捕获的音频存储在WAV文件中,然后从此文件中进行绘制。

我创建了一个名为GrabaAudio的类,预计会记录3秒长的wav文件。

问题在于,我没有明确的理由获得3秒和1.5秒的wav文件。

这是我一直想要得到的:

波形:

Image

但实际上,这个结果有时是获得的,而大多数时候这是我获得的结果:

Image

真正好奇的是,当我在情节中获得预期结果时,我播放wav文件以查看实际记录的内容并且我可以听到冲动,但仅仅持续1.5秒而不是因此,获得的样本是预期的一半。

另一方面,当我获得带有重复冲动的情节时,样本数量是预期的,并且wav持续时间是3秒,但我不知道为什么冲动会出现两次。

你们知道我做错了什么吗?

以下是代码的相关部分:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@SuppressLint("NewApi")
public class GrabaAudio {
private static final int RECORDER_BPP = 16;
private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
public int RECORDER_SAMPLERATE = 8000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord recorder = null;
private int bufferSize = 0;
private Thread recordingThread = null; 
public boolean isRecording = false;
public boolean triggered=false, processed=false;
int bufferTotal=0, read=0, indice=0, indice2=0;
byte[] circBuffer=new byte[8192*3];//AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
//RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING)*3
AutomaticGainControl agc;
  File file= new File(getFilename());
CircularArrayList<Byte> circ= new CircularArrayList ((AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
        RECORDER_CHANNELS,
        RECORDER_AUDIO_ENCODING))/2);
int circCapacity=circ.capacity();
Main main;

public GrabaAudio(){
    bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
            RECORDER_CHANNELS,
            RECORDER_AUDIO_ENCODING);
    if (bufferSize <8192){
        bufferSize=8192;

    }
    //boolean tiene=agc.getEnabled();
}
public void startRecording(){

        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                                        RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize*6);
        agc = AutomaticGainControl.create(recorder.getAudioSessionId());
        final boolean agc2=agc.isAvailable();
        int i = recorder.getState();
        if(i==1)
            recorder.startRecording();

        isRecording = true;

        recordingThread = new Thread(new Runnable() {

                @Override
                public void run() {
                        writeAudioDataToFile();
                }
        },"AudioRecorder Thread");

        recordingThread.start();
}



public void writeAudioDataToFile(){
            byte data[] = new byte[6*bufferSize];
            byte arrayBytes[]= new byte [3*bufferSize];
            String filename = getTempFilename();
            FileOutputStream os = null;

            try {
                    os = new FileOutputStream(filename);
            } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }

            if(null != os){
                while(isRecording){
                            read = recorder.read(data, 0, 6*bufferSize);
                            //**************************************
                            arrayBytes=calculateImpulseLevel(data);

                            if(AudioRecord.ERROR_INVALID_OPERATION != read && indice>=(bufferSize*3-3) ){
                                    try {
                                        os.write(arrayBytes);
                                        processed=true;


                                    } catch (IOException e) {
                                            e.printStackTrace();
                                    }
                            }
                    }

                    try {
                            os.close();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            }

    }
    private byte[] calculateImpulseLevel(byte[] array){
        double[] arraySamples=new double[array.length/2];
        for (int i=0,j=0; i<=array.length-2 ;i+=2){
        double sampleAmpl=(double)Math.abs((array[i+1] << 8 | array[i] & 0xff)/32767.0);
            if (sampleAmpl<0.3 && !triggered){
                int s=circ.size();
                if (s<circCapacity){
                    circ.add(array[i]);
                    circ.add(array[i+1]);
                } else {
                    circ.remove(0);
                    circ.add(array[i]);
                    circ.remove(0);
                    circ.add(array[i+1]);
                } 
            } else{
                    if(!triggered){
                        triggered=true;
                    }   indice=indice2+(bufferSize/2);
                    if (indice>3*bufferSize-2){
                        i=array.length;
                    }else{
                    circBuffer[indice]=array[i];
                    circBuffer[indice+1]=array[i+1];
                    indice2+=2;
                    arraySamples[j]=sampleAmpl;
                    }
                }}
        System.arraycopy(toByteArray(circ),0,circBuffer,0,circ.size());
        return circBuffer;
    }

1 个答案:

答案 0 :(得分:1)

我遇到了AudioRecord在读取序列中返回重复数据的问题,通过更改AudioRecord缓冲区的大小来解决,以便不是audiodata缓冲区大小的精确倍数,例如,尝试:

    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
    RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize*9);

您还确定写入始终能够跟上读取吗?我会插入一些日志语句来检查时间。您可能需要将读取的数据复制到内存中并写入另一个线程。