Android录制WAV文件
2016-02-20 13:33
477 查看
实现思路:用AudioRecorder录制PCM数据以WAV格式保存
一)AudioRecord录制PCM数据
二)保存WAV文件
//初始化WAV文件头
//读取PCM写入WAV文件
//录制完成之后将数据长度回写到WAV文件头
三)回音消除&去噪(android4.1版本以上支持)
源码工程:http://download.csdn.net/detail/hewenhao2014/9437513
一)AudioRecord录制PCM数据
// default: mSampleRate = 8000 int 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 block e.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
相关文章推荐
- C#实现用于操作wav声音文件的类实例
- android AudioRecorder简单心得分享
- php实现将wav文件转换成图像文件并在页面中显示的方法
- java读取wav文件(波形文件)并绘制波形图的方法
- python使用wxPython打开并播放wav文件的方法
- 回音消除、噪音抑制技术相关知识
- 如何将语音文件转换为Asterisk可以播放的音频格式文件(.wav)
- WP8录制Wav音频文件
- python播放WAV文件的问题
- alsa编程播放wav
- SDL2.0超简单入门 100行代码实现播放wav声音文件
- 基于Kinetis的KL系列之Cortex-M0的WAV音频播放器——PCB打样(3)
- 基于Kinetis的KL系列之Cortex-M0的WAV音频播放器——系统设计(1)
- vc++下给自己的程序添加背景音乐
- PCM音频
- 需求:IOS播放PCM音频流数据
- html/Javascript播放WAV音频文件的方法
- 音频格式详解:WAV
- 使用AudioTrack和MediaPlayer播放声音的区别
- iOS 音频格式WAV和AMR格式转换技术