Android录制WAV文件- 带去回声

来源:互联网 发布:常见的hash算法有哪些 编辑:程序博客网 时间:2024/04/30 18:36

http://blog.csdn.net/hewenhao2014/article/details/50704473




 分类:

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

一)AudioRecord录制PCM数据

[java] view plain copy
  1. // default: mSampleRate = 8000  
  2. int channelConfig = AudioFormat.CHANNEL_IN_MONO;  
  3. int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;  
  4. minBufferSize = AudioRecord.getMinBufferSize(mSampleRate, channelConfig, audioEncoding);      
  5. Log.i(LOG_TAG, "minBufferSize: " + minBufferSize);  
  6.   
  7. mRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,   
  8.                 mSampleRate,  
  9.                 channelConfig,   
  10.                 audioEncoding,        
  11.                 minBufferSize*2);  
  12. mAudioSessionId = mRecord.getAudioSessionId();  


二)保存WAV文件

[java] view plain copy
  1.                   
  2. File f = new File(mRecordfile);  
  3. if(f.exists()){  
  4. f.delete();  
  5. }  
  6.                   
  7. randomAccessWriter = new RandomAccessFile(mRecordfile, "rw");     
  8. initWavHeader(randomAccessWriter, (short)channelConfig, (int)mSampleRate, (short)16);  
  9. payloadSize = 0;  


//初始化WAV文件头

[java] view plain copy
  1. static void initWavHeader(RandomAccessFile randomAccessWriter, short Channels, int SamplesPerSec, short BitsPerSample){   
  2.         try {  
  3.         randomAccessWriter.setLength(0);  
  4.         // Set file length to 0, to prevent unexpected behavior in case the file already existed  
  5.             randomAccessWriter.writeBytes("RIFF");  
  6.             randomAccessWriter.writeInt(0); // Final file size not known yet, write 0   
  7.             randomAccessWriter.writeBytes("WAVE");  
  8.             randomAccessWriter.writeBytes("fmt ");  
  9.             randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM  
  10.             randomAccessWriter.writeShort(Short.reverseBytes((short1)); // AudioFormat, 1 for PCM  
  11.             randomAccessWriter.writeShort(Short.reverseBytes((short1));// Number of channels, 1 for mono, 2 for stereo  
  12.             randomAccessWriter.writeInt(Integer.reverseBytes(SamplesPerSec)); // Sample rate  
  13.             randomAccessWriter.writeInt(Integer.reverseBytes(SamplesPerSec*BitsPerSample*Channels/8)); // Byte rate, SampleRate*NumberOfChannels*BitsPerSample/8  
  14.             randomAccessWriter.writeShort(Short.reverseBytes((short)(Channels*BitsPerSample/8))); // Block align, NumberOfChannels*BitsPerSample/8  
  15.             randomAccessWriter.writeShort(Short.reverseBytes(BitsPerSample)); // Bits per sample  
  16.             randomAccessWriter.writeBytes("data");  
  17.             randomAccessWriter.writeInt(0); // Data chunk size not known yet, write 0  
  18.         } catch (IOException e) {  
  19.             // TODO Auto-generated catch block  
  20.             e.printStackTrace();  
  21.     }   
  22. }  

//读取PCM写入WAV文件

[java] view plain copy
  1. byte[] pcmData = new byte[minBufferSize*2];  
  2.             final Object threadLock = new Object();  
  3.             Thread.currentThread().setPriority(MAX_PRIORITY);  
  4.             Thread.currentThread().setName("AudioSourceMicr");  
  5.             mRecord.startRecording();  
  6.               
  7.             synchronized (threadLock)   
  8.             {  
  9.                 while (mThreadLoop && !Thread.currentThread().isInterrupted())  
  10.                 {  
  11.                     if (mPauseFlag) continue;  
  12.                       
  13.                     int bufferReadResult = mRecord.read(pcmData, 0, minBufferSize*2-512);  
  14.                     Log.i(LOG_TAG, "bufferReadResult = "+bufferReadResult);  
  15.                       
  16.                     if (bufferReadResult > 0){  
  17.                         saveWaveData(pcmData, bufferReadResult);  
  18.                     }  
  19.                     else{  
  20.                         Log.i(LOG_TAG, "Error to read pcm from AudioRecorder.");  
  21.                     }  
  22.                 }      
  23.             }  
  24.               

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

[java] view plain copy
  1. randomAccessWriter.seek(4);  
  2. randomAccessWriter.write(Integer.reverseBytes(36+payloadSize));  
  3. randomAccessWriter.seek(40);  
  4. randomAccessWriter.write(Integer.reverseBytes(payloadSize));  
  5. randomAccessWriter.close();  

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

[java] view plain copy
  1. if (mAudioSessionId != 0 && android.os.Build.VERSION.SDK_INT >= 16)  
  2.         {  
  3.             if (NoiseSuppressor.isAvailable())  
  4.             {  
  5.                 if (mNoiseSuppressor != null)  
  6.                 {  
  7.                     mNoiseSuppressor.release();  
  8.                     mNoiseSuppressor = null;  
  9.                 }  
  10.                   
  11.                 mNoiseSuppressor = NoiseSuppressor.create(mAudioSessionId);  
  12.                 if (mNoiseSuppressor != null)   
  13.                 {  
  14.                     mNoiseSuppressor.setEnabled(true);  
  15.                 }  
  16.                 else  
  17.                 {  
  18.                     Log.i(LOG_TAG, "Failed to create NoiseSuppressor.");                                  
  19.                 }  
  20.             }  
  21.             else  
  22.             {  
  23.                 Log.i(LOG_TAG, "Doesn't support NoiseSuppressor");                                
  24.             }     
  25.               
  26.             if (AcousticEchoCanceler.isAvailable())  
  27.             {  
  28.                 if (mAcousticEchoCanceler != null)  
  29.                 {  
  30.                     mAcousticEchoCanceler.release();  
  31.                     mAcousticEchoCanceler = null;  
  32.                 }  
  33.                   
  34.                 mAcousticEchoCanceler = AcousticEchoCanceler.create(mAudioSessionId);  
  35.                 if (mAcousticEchoCanceler != null)  
  36.                 {  
  37.                     mAcousticEchoCanceler.setEnabled(true);  
  38.                     // mAcousticEchoCanceler.setControlStatusListener(listener)setEnableStatusListener(listener)  
  39.                 }  
  40.                 else  
  41.                 {  
  42.                     Log.i(LOG_TAG, "Failed to initAEC.");     
  43.                     mAcousticEchoCanceler = null;  
  44.                 }  
  45.             }  
  46.             else  
  47.             {  
  48.                 Log.i(LOG_TAG, "Doesn't support AcousticEchoCanceler");                               
  49.             }  
  50.   
  51.             if (AutomaticGainControl.isAvailable())  
  52.             {  
  53.                 if (mAutomaticGainControl != null)  
  54.                 {  
  55.                     mAutomaticGainControl.release();  
  56.                     mAutomaticGainControl = null;  
  57.                 }  
  58.                   
  59.                 mAutomaticGainControl = AutomaticGainControl.create(mAudioSessionId);  
  60.                 if (mAutomaticGainControl != null)   
  61.                 {  
  62.                     mAutomaticGainControl.setEnabled(true);  
  63.                 }  
  64.                 else  
  65.                 {  
  66.                     Log.i(LOG_TAG, "Failed to create AutomaticGainControl.");                                 
  67.                 }  
  68.                   
  69.             }  
  70.             else  
  71.             {  
  72.                 Log.i(LOG_TAG, "Doesn't support AutomaticGainControl");                               
  73.             }  
  74.         }  


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


0 0