public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)AudioRecord 构造函数 AudioSource 音频源, 常用MediaRecorder.AudioSource.MIC(麦克风音频源) SampleRateInHz 采样率,(采样率用赫兹表示。44100Hz是目前唯一的*保证适用于所有设备的费率) ChannelConfig 音频声道 AudioFormat 返回音频数据格式 BufferSizeInBytes 缓冲区大小 录制流程:
- 构造AudioRecord 对象
- startRecording() 开始采集
- 在线程中将采集数据写入pcm文件
-
stop() 停止采集
public void record(){ mAudioRecord.startRecording(); new Thread(new Runnable() { @Override public void run() { FileOutputStream fileOutputStream=new FileOutputStream(recordFile); byte[] buffer=new byte[mBufferSizeInBytes]; while(isRecording){ int read=mAudioRecord.read(buffer,0,mBufferSizeInBytes); if(AudioRecord.ERROR_INVALID_OPERATION!=read){ fileOutputStream.write(buffer); } } fileOutputStream.close(); } }).start(); } public void stopRecord(){ isRecording=false; if(mAudioRecord.getState()==AudioRecord.RECORDSTATE_RECORDING){ mAudioRecord.stop(); } mAudioRecord.release(); }
使用AudioTrack播放- 构造AudioTrack
- play()
- 在线程中write() 写入pcm文件流
- release()回收资源
public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId)
mAudioTrack.play();
new Thread(new Runnable(){ @Override public void run() { try { FileInputStream fileInputStream=new FileInputStream(filePath); byte[] tempBuffer=new byte[mWriteMinBufferSize]; while (fileInputStream.available()>0){ int readCount= fileInputStream.read(tempBuffer); if (readCount== AudioTrack.ERROR_INVALID_OPERATION||readCount==AudioTrack.ERROR_BAD_VALUE){ continue; } if (readCount!=0&&readCount!=-1){ mAudioTrack.write(tempBuffer,0,readCount); } } Log.e("TAG","end"); } catch (Exception e) { e.printStackTrace(); } } }).start();
实例:使用AudioRecord 采集PCM,AudioTrack 播放
package com.rexkell.mediaapplication; import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaRecorder; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import com.rexkell.mediaapplication.media.MediaConfig; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.concurrent.Executors; /** * author: rexkell * date: 2019/7/22 * explain: */ public class AudioRecordActivity extends AppCompatActivity { boolean isRecording=false; //音频源 MIC指的是麦克风 private final int mAudioSource= MediaRecorder.AudioSource.MIC; //(MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100,目前为常用的采样率,官方文档表示这个值可以兼容所有的设置) private final int SampleRateInHz=44100; //采样率 //输入声道 private final int channelInMono= AudioFormat.CHANNEL_CONFIGURATION_MONO; private final int channelOutMono=AudioFormat.CHANNEL_OUT_MONO; //指定音频量化位数 ,在AudioFormaat类中指定了以下各种可能的常量。通常我们选择ENCODING_PCM_16BIT和ENCODING_PCM_8BIT PCM代表的是脉冲编码调制,它实际上是原始音频样本。 //因此可以设置每个样本的分辨率为16位或者8位,16位将占用更多的空间和处理能力,表示的音频也更加接近真实 private final int mAudioFormat=AudioFormat.ENCODING_PCM_16BIT; //指定缓冲区大小 private int mBufferSizeInBytes; private String filePath; private int mWriteMinBufferSize; private AudioAttributes mAudioAttributes; AudioRecord mAudioRecord; AudioTrack mAudioTrack; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac_audio_record); filePath=getExternalFilesDir("Music").getPath()+"/test.pcm"; initAudioRecord(); } private void initAudioRecord(){ mBufferSizeInBytes=AudioRecord.getMinBufferSize(SampleRateInHz,channelInMono,mAudioFormat); mWriteMinBufferSize=AudioTrack.getMinBufferSize(SampleRateInHz,channelInMono,mAudioFormat); mAudioRecord=new AudioRecord(mAudioSource,SampleRateInHz,channelInMono,mAudioFormat,mBufferSizeInBytes); AudioFormat audioFormat=new AudioFormat.Builder().setSampleRate(SampleRateInHz).setEncoding(mAudioFormat).setChannelMask(channelOutMono).build(); mAudioAttributes=new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build(); mAudioTrack=new AudioTrack(mAudioAttributes,audioFormat,mWriteMinBufferSize, AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE); File recordFile=new File(filePath); if (!recordFile.exists()){ try { recordFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } } public void record(View view){ isRecording=!isRecording; String text=isRecording?"结束":"录制"; ((Button)view).setText(text); if (isRecording){ final File recordFile=new File(filePath); if (recordFile.exists()){ recordFile.delete(); try { recordFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } mAudioRecord.startRecording(); Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { try { FileOutputStream fileOutputStream=new FileOutputStream(recordFile); byte[] buffer=new byte[mBufferSizeInBytes]; while (isRecording){ int read=mAudioRecord.read(buffer,0,mBufferSizeInBytes); if (AudioRecord.ERROR_INVALID_OPERATION!=read){ fileOutputStream.write(buffer); } } fileOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } } }); }else { if (mAudioRecord!=null&&isRecording){ if (mAudioRecord.getState()==AudioRecord.RECORDSTATE_RECORDING){ mAudioRecord.stop(); } mAudioRecord.release(); isRecording=false; } } } public void play(View view){ mAudioTrack.play(); Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { try { FileInputStream fileInputStream=new FileInputStream(filePath); byte[] tempBuffer=new byte[mWriteMinBufferSize]; while (fileInputStream.available()>0){ int readCount= fileInputStream.read(tempBuffer); if (readCount== AudioTrack.ERROR_INVALID_OPERATION||readCount==AudioTrack.ERROR_BAD_VALUE){ continue; } if (readCount!=0&&readCount!=-1){ mAudioTrack.write(tempBuffer,0,readCount); } } Log.e("TAG","end"); } catch (Exception e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { if (mAudioRecord!=null){ mAudioRecord.release(); mAudioRecord=null; } if (mAudioTrack!=null){ mAudioTrack.release(); mAudioTrack=null; } super.onDestroy(); } }