录音器 AudioRecorder
实现录音器有两种方式可以选择:
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的更多相关文章
- Android 录音器
Android自带的mediarecoder录音器不含pause暂停功能,解决方法:录制多个音频片段,最后合成一个文件. 参照 : http://blog.csdn.net/a601445984/ar ...
- 用swift实现自动录音器
基本介绍 自动录音与一般录音区别在:不用像微信那样按下录音-松手结束,而是根据说话声音的大小自动判断该录音和该停止的点,然后可以做到结束录音之后马上播放出来.类似于达到会说话的汤姆猫那样的效果. 在自 ...
- PJMEDIA之录音器的使用(capture sound to avi file)
为了熟悉pjmedia的相关函数以及使用方法,这里练习了官网上的一个录音器的例子. 核心函数: pj_status_t pjmedia_wav_writer_port_create ( pj_pool ...
- IOS 实现 AAC格式 录音 录音后自动播放
废话不说了 不知道aac可以百度一下 下面直接上代码,一个h文件 一个m文件 搞定! #import <AVFoundation/AVFoundation.h> #import <U ...
- Android MP3录音实现
给APP做语音功能,必须考虑到IOS和Android平台的通用性.wav录音质量高,文件太大,AAC和AMR格式在IOS平台却不支持,所以采用libmp3lame把AudioRecord音频流直接转换 ...
- ios开发——实用技术篇Swift篇&录音
录音 // MARK: - 录音 /*----- 录音 ------*/ var recorder:AVAudioRecorder? //录音器 var player:AVAudioPlayer? / ...
- 【Android】20.4 录音
分类:C#.Android.VS2015: 创建日期:2016-03-13 一.简介 利用Android提供的MediaRecorder类可直接录制音频. 1.权限要求 录制音频和视频需要下面的权限: ...
- IOS中录音后再播放声音太小问题解决
1.AVAudioSessionCategory说明 1.1 AVAudioSessionCategoryAmbient 或 kAudioSessionCategory_AmbientSound 用于 ...
- JavaScript 实现页面中录音功能
页面中实现录音需要使用浏览器提供的 MediaRecorder API,所以前提是需要浏览器支持 MediaStream Recording 相关的功能. 以下代码默认工作在 Chrome 环境中. ...
随机推荐
- WIN10 常用bug解决办法
1.没开始菜单,点不出来,无法关机 建立批处理,右键管理员运行. shutdown -s -t 0 2.没开始菜单,点不出来,无法重启 建立批处理,右键管理员运行. shutdown -r -t 0 ...
- 捷微jeewx , 免费开源(java)微信公众账号管家系统发布
JeeWx, 微信管家平台,简称"捷微". 捷微是一款免费开源的JAVA微信公众账号开发平台. 平台介绍: 一.捷微Jeewx简介 Jeewx是一个开源.高效.敏捷的微信开发平台 ...
- WDA-1-环境配置
1.Internet Communication Manager 确认ICM中提供的HTTP/HTTPS运行正常. Tcode: SMICM -> Display service. ICM在SA ...
- 【380】python 获取列表排序后的索引列表
参考:Equivalent of Numpy.argsort() in basic python? - Stack Overflow 通过 enumerate 实现 [i for i,v in sor ...
- sublime text3 激活码——许可证
亲测: 现在是公元2018年6月4日.晴 ``` ----- BEGIN LICENSE ----- sgbteam Single User License EA7E-1153259 8891CBB9 ...
- C# 获取汉字转拼音缩写-简写,不是全拼
///<summary> /// 汉字转拼音缩写 /// Code By ] -'\0')); if ( i <0xB0A1) return"*" ...
- 吴裕雄 python神经网络(8)
# -*- coding=utf-8 -*-import numpy as npimport kerasfrom keras.models import Sequentialfrom keras.la ...
- hdu1215-七夕节-(埃氏筛+唯一分解定理)
七夕节 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- base64 压缩图片
//图片处理 afterimg(err, photos) { var _this = this; if(err && err != null && err != '') ...
- matlab 矩阵拼接
E=[a,b]%水平方向上的拼接 E=[a :b] %垂直方向上的拼接