实现录音器有两种方式可以选择:

1.AudioRecord(基于字节流录音)
优点:可以实现语音的实时处理,进行边录边播,对音频的实时处理。
缺点:输出的是PCM的语音数据,如果保存成音频文件是不能被播放器播放的。要用到AudioTrack这个去进行处理。

2.MediaRecorder(基于文件录音)
已集成了录音,编码,压缩等,支持少量的音频格式文件。
优点:封装度很高,操作简单
缺点:无法实现实时处理音频,输出的音频格式少。

权限:

<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

AudioRecorder录音工具类代码如下:

package com.example.m_evolution.Utils;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.util.Log; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date; public class AudioRecoderUtils { //文件路径
private String filePath;
//文件夹路径
private String FolderPath; //录音的线程
private Thread mThread; // private MediaRecorder mMediaRecorder;
private AudioRecord audioRecord;
private boolean isRecording;
private int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
private int sampleRate = 44100;
private int bufferSizeInBytes; private final String TAG = "fan";
public static final int MAX_LENGTH = 1000 * 60 * 10;// 最大录音时长1000*60*10; private OnAudioStatusUpdateListener audioStatusUpdateListener; /**
* 文件存储默认sdcard/record
*/
public AudioRecoderUtils(){ //默认保存路径为/sdcard/record/下
FolderPath = Environment.getExternalStorageDirectory()+"/record/";
bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRate,
channelConfiguration, audioEncoding); // need to be larger than size of a frame audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleRate, channelConfiguration, audioEncoding,
bufferSizeInBytes); //麦克风
} public void startRecord(){
mThread = new Thread(new Runnable() {
@Override
public void run() {
/* 获取开始时间* */
startTime = System.currentTimeMillis();
//设置录制指标
isRecording = true;
//自动更新界面
updateMicStatus();
//设置存储路径
filePath = FolderPath+getCurrentDate("yyyyMMddHHmmss") + ".wav";
File recordingFile = new File(filePath);
OutputStream out = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
audioRecord.startRecording();
byte[] buffer = new byte[bufferSizeInBytes];
int bufferReadResult = 0;
while (isRecording) {
bufferReadResult = audioRecord.read(buffer, 0,
bufferSizeInBytes);
if(bufferReadResult>0){
baos.write(buffer, 0, bufferReadResult);
}
}
Log.i(TAG, "stop recording,file=" + recordingFile.getAbsolutePath());
buffer = baos.toByteArray();
Log.i(TAG, "audio byte len="+buffer.length);
out = new FileOutputStream(recordingFile);
out.write(getWavHeader(buffer.length));
out.write(buffer);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(baos!=null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
mThread.start();
} public void stopRecord(){
stopRecording();
audioStatusUpdateListener.onStop(filePath);
filePath = "";
} public byte[] getWavHeader(long totalAudioLen){
int mChannels = 1;
long totalDataLen = totalAudioLen + 36;
long longSampleRate = sampleRate;
long byteRate = sampleRate * 2 * mChannels; byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) mChannels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * mChannels); // block align
header[33] = 0;
header[34] = 16; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff); return header;
} private long startTime;
private long endTime; public static String getCurrentDate(String pattern) {
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
String timestamp = formatter.format(curDate);
return timestamp;
} public void stopRecording() {
try {
isRecording = false;
audioRecord.stop();
audioRecord.release();
audioRecord = null;
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleRate, channelConfiguration, audioEncoding,
bufferSizeInBytes); //麦克风
} catch (Exception e) {
e.printStackTrace();
}
} private final Handler mHandler = new Handler();
private Runnable mUpdateMicStatusTimer = new Runnable() {
public void run() {
updateMicStatus();
}
}; private int SPACE = 100;//显示时间的间隔时间 public void setOnAudioStatusUpdateListener(OnAudioStatusUpdateListener audioStatusUpdateListener) {
this.audioStatusUpdateListener = audioStatusUpdateListener;
} /**
* 更新麦克状态
*/
private void updateMicStatus() { if (isRecording) {
if(null != audioStatusUpdateListener) {
audioStatusUpdateListener.onUpdate(System.currentTimeMillis()-startTime);
}
mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
}
} public interface OnAudioStatusUpdateListener {
/**
* 录音中...
* @param db 当前声音分贝
* @param time 录音时长
*/
public void onUpdate(long time); /**
* 停止录音
* @param filePath 保存路径
*/
public void onStop(String filePath);
} }

录音器 AudioRecorder的更多相关文章

  1. Android 录音器

    Android自带的mediarecoder录音器不含pause暂停功能,解决方法:录制多个音频片段,最后合成一个文件. 参照 : http://blog.csdn.net/a601445984/ar ...

  2. 用swift实现自动录音器

    基本介绍 自动录音与一般录音区别在:不用像微信那样按下录音-松手结束,而是根据说话声音的大小自动判断该录音和该停止的点,然后可以做到结束录音之后马上播放出来.类似于达到会说话的汤姆猫那样的效果. 在自 ...

  3. PJMEDIA之录音器的使用(capture sound to avi file)

    为了熟悉pjmedia的相关函数以及使用方法,这里练习了官网上的一个录音器的例子. 核心函数: pj_status_t pjmedia_wav_writer_port_create ( pj_pool ...

  4. IOS 实现 AAC格式 录音 录音后自动播放

    废话不说了 不知道aac可以百度一下 下面直接上代码,一个h文件 一个m文件 搞定! #import <AVFoundation/AVFoundation.h> #import <U ...

  5. Android MP3录音实现

    给APP做语音功能,必须考虑到IOS和Android平台的通用性.wav录音质量高,文件太大,AAC和AMR格式在IOS平台却不支持,所以采用libmp3lame把AudioRecord音频流直接转换 ...

  6. ios开发——实用技术篇Swift篇&录音

    录音 // MARK: - 录音 /*----- 录音 ------*/ var recorder:AVAudioRecorder? //录音器 var player:AVAudioPlayer? / ...

  7. 【Android】20.4 录音

    分类:C#.Android.VS2015: 创建日期:2016-03-13 一.简介 利用Android提供的MediaRecorder类可直接录制音频. 1.权限要求 录制音频和视频需要下面的权限: ...

  8. IOS中录音后再播放声音太小问题解决

    1.AVAudioSessionCategory说明 1.1 AVAudioSessionCategoryAmbient 或 kAudioSessionCategory_AmbientSound 用于 ...

  9. JavaScript 实现页面中录音功能

    页面中实现录音需要使用浏览器提供的 Media​Recorder API,所以前提是需要浏览器支持 MediaStream Recording 相关的功能. 以下代码默认工作在 Chrome 环境中. ...

随机推荐

  1. enum使用方法

    DK1.5引入了新的类型——枚举.在 Java 中它虽然算个“小”功能,却给我的开发带来了“大”方便. 用法一:常量 在JDK1.5 之前,我们定义常量都是: publicstaticfianl... ...

  2. golang 操作redis 错误:failed redigo: unexpected type for String, got type int64

    报错的代码: isExist,err := redis.String(conn.Do("EXISTS", key)) 这个操作返回的应该是bool类型,所有改成 isExist,e ...

  3. day39-异常处理

    一.程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 def test: pass ...

  4. 26个Jquery使用小技巧(转)

    下面列出了一些Jquery使用技巧.比如有禁止右键点击.隐藏搜索文本框文字.在新窗口中打开链接.检测浏览器.预加载图片.页面样式切换.所有列等 高.动态控制页面字体大小.获得鼠标指针的X值Y值.验证元 ...

  5. Django下的templates 和 static静态文件

    如果Django顶层目录中没有templates的话,就自己新建一个Directory ,这个文件是存放html文件的 1)如果在views里面用render(request,"" ...

  6. google event

    一目了然,也不用多说了,随便记录下,内部实现基于观察者模式 TestEvent public class TestEvent { private final int message; public T ...

  7. linux查询硬件信息

    硬件信息查询 sudo dmidecode -t baseboard

  8. java.util.Arrays$ArrayList addAll报错

    执行下面代码时报错: List<String> centerList = WebConstants.SUPPORT_BIG_CENTERS_LIST; // WebConstants.SU ...

  9. ReactiveX 学习笔记(13)基础类型

    Key Types and Life Management 本文主题是 Rx 中的基础类型 Subject 类及其生命周期的管理. 公共代码 RxNET private static void Wri ...

  10. ReactiveX 学习笔记(3)转换数据流

    Transforming Observables 本文的主题为转换 Observable 的操作符. 这里的 Observable 实质上是可观察的数据流. RxJava操作符(二)Transform ...