Android录制WAV文件

来源:互联网 发布:美工设计的工作内容 编辑:程序博客网 时间:2024/05/21 10:16

实现思路:用AudioRecorder录制PCM数据以WAV格式保存

一)AudioRecord录制PCM数据

// default: mSampleRate = 8000int channelConfig = AudioFormat.CHANNEL_IN_MONO;int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;minBufferSize = AudioRecord.getMinBufferSize(mSampleRate, channelConfig, audioEncoding);Log.i(LOG_TAG, "minBufferSize: " + minBufferSize);mRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, mSampleRate,channelConfig, audioEncoding,minBufferSize*2);mAudioSessionId = mRecord.getAudioSessionId();


二)保存WAV文件

File f = new File(mRecordfile);if(f.exists()){f.delete();}randomAccessWriter = new RandomAccessFile(mRecordfile, "rw");initWavHeader(randomAccessWriter, (short)channelConfig, (int)mSampleRate, (short)16);payloadSize = 0;


//初始化WAV文件头

static void initWavHeader(RandomAccessFile randomAccessWriter, short Channels, int SamplesPerSec, short BitsPerSample){        try {randomAccessWriter.setLength(0);// Set file length to 0, to prevent unexpected behavior in case the file already existed        randomAccessWriter.writeBytes("RIFF");        randomAccessWriter.writeInt(0); // Final file size not known yet, write 0         randomAccessWriter.writeBytes("WAVE");        randomAccessWriter.writeBytes("fmt ");        randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM        randomAccessWriter.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM        randomAccessWriter.writeShort(Short.reverseBytes((short) 1));// Number of channels, 1 for mono, 2 for stereo        randomAccessWriter.writeInt(Integer.reverseBytes(SamplesPerSec)); // Sample rate        randomAccessWriter.writeInt(Integer.reverseBytes(SamplesPerSec*BitsPerSample*Channels/8)); // Byte rate, SampleRate*NumberOfChannels*BitsPerSample/8        randomAccessWriter.writeShort(Short.reverseBytes((short)(Channels*BitsPerSample/8))); // Block align, NumberOfChannels*BitsPerSample/8        randomAccessWriter.writeShort(Short.reverseBytes(BitsPerSample)); // Bits per sample        randomAccessWriter.writeBytes("data");        randomAccessWriter.writeInt(0); // Data chunk size not known yet, write 0        } catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} }

//读取PCM写入WAV文件

byte[] pcmData = new byte[minBufferSize*2];final Object threadLock = new Object();Thread.currentThread().setPriority(MAX_PRIORITY);        Thread.currentThread().setName("AudioSourceMicr");mRecord.startRecording();        synchronized (threadLock) {while (mThreadLoop && !Thread.currentThread().isInterrupted()){if (mPauseFlag) continue;int bufferReadResult = mRecord.read(pcmData, 0, minBufferSize*2-512);Log.i(LOG_TAG, "bufferReadResult = "+bufferReadResult);if (bufferReadResult > 0){            saveWaveData(pcmData, bufferReadResult);                    }else{Log.i(LOG_TAG, "Error to read pcm from AudioRecorder.");}} }

//录制完成之后将数据长度回写到WAV文件头

randomAccessWriter.seek(4);randomAccessWriter.write(Integer.reverseBytes(36+payloadSize));randomAccessWriter.seek(40);randomAccessWriter.write(Integer.reverseBytes(payloadSize));randomAccessWriter.close();

三)回音消除&去噪(android4.1版本以上支持)

if (mAudioSessionId != 0 && android.os.Build.VERSION.SDK_INT >= 16){if (NoiseSuppressor.isAvailable()){if (mNoiseSuppressor != null){mNoiseSuppressor.release();mNoiseSuppressor = null;}mNoiseSuppressor = NoiseSuppressor.create(mAudioSessionId);if (mNoiseSuppressor != null) {mNoiseSuppressor.setEnabled(true);}else{Log.i(LOG_TAG, "Failed to create NoiseSuppressor.");}}else{Log.i(LOG_TAG, "Doesn't support NoiseSuppressor");}if (AcousticEchoCanceler.isAvailable()){if (mAcousticEchoCanceler != null){mAcousticEchoCanceler.release();mAcousticEchoCanceler = null;}mAcousticEchoCanceler = AcousticEchoCanceler.create(mAudioSessionId);if (mAcousticEchoCanceler != null){mAcousticEchoCanceler.setEnabled(true);// mAcousticEchoCanceler.setControlStatusListener(listener)setEnableStatusListener(listener)    }else{Log.i(LOG_TAG, "Failed to initAEC.");mAcousticEchoCanceler = null;}}else{Log.i(LOG_TAG, "Doesn't support AcousticEchoCanceler");}if (AutomaticGainControl.isAvailable()){if (mAutomaticGainControl != null){mAutomaticGainControl.release();mAutomaticGainControl = null;}mAutomaticGainControl = AutomaticGainControl.create(mAudioSessionId);if (mAutomaticGainControl != null) {mAutomaticGainControl.setEnabled(true);}else{Log.i(LOG_TAG, "Failed to create AutomaticGainControl.");}}else{Log.i(LOG_TAG, "Doesn't support AutomaticGainControl");}}


源码工程:http://download.csdn.net/detail/hewenhao2014/9437513


2 0