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

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. leetcode41

    package main import ( "fmt" ) func firstMissingPositive(nums []int) int { m := make(map[in ...

  2. docker 2 容器数据卷

    docker 启动tomcat docker run -it -p 8888:8080 tomcat 提交一个容器使之成为一个镜像 docker commit -a=“作者” -m=“提交信息” 模板 ...

  3. delphi多语言

    LoadLangFromStrings http://docwiki.embarcadero.com/Libraries/Berlin/en/FMX.Types.TLang http://blog.c ...

  4. FDQuery多表更新生成sql语句的问题

    query.sql='select  a,b,c,d,e from a,b,c where ....'; 来源3个表, 设计时添加字段列表,每个字段有Origin属性 分别是a.a,b.b,c.c格式 ...

  5. 机器学习进阶-图像特征harris-角点检测 1.cv2.cornerHarris(进行角点检测)

    1.cv2.cornerHarris(gray, 2, 3, 0.04)  # 找出图像中的角点 参数说明:gray表示输入的灰度图,2表示进行角点移动的卷积框,3表示后续进行梯度计算的sobel算子 ...

  6. ejs 用到的语法

    1.ejs 服务端渲染模板 2.语法: 01. <%= 变量名 %> -原样输出,不解析标签 02. <% js代码 %> 03. <%- 变量名%> -解析标签 ...

  7. vue:vue引入组建的多种写法

    vue的路由组件中,引入模块的两种写法:(@等价于..)死的写法:不是按需加载1:import Index from '@/components/Index'(import Index from '. ...

  8. 2:if 语句

    if 语句 语法形式: 第一种,只有两个分支: if 表达式: something else: something 第二种,有多个分支: if 表达式1: do something 1 elif 表达 ...

  9. Haskell语言学习笔记(77)Data.HashSet

    安装 unordered-containers $ cabal install unordered-containers Installed unordered-containers-0.2.9.0 ...

  10. 447. Add Strings

    原文题目: 447. Add Strings 解题: 字符串的当做整数来做加法,其实就是大数加法的简化版本 思路: 1)考虑不同位数,如"1234"+“45”,需要先处理低两位,再 ...