android 录音原始文件_音频采集:Android基于AudioRecord的实现

前言

这篇文章简单介绍下移动端Android系统下利用AudioRecord进行音频采集方法。

按照惯例开始前先提供一份源码 AudioRecordLib 。

AudioRecord采集的核心实现在于 AudioRecordCore.java 这个文件。

权限申请

想要使用AudioRecord这个API,需要在AndroidManifest.xml的配置文件里面增加录音权限:

初始化

AudioRecord的初始化需要先创建一个AudioRecord实例。

构造函数原型如下:

public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig,

int audioFormat,int bufferSizeInBytes)

具体参数说明:

audioSource 这个参数指的是音频采集的输入源,接受的值定义在MediaRecorder.AudioSource里面,一般来说使用DEFAULT或者MIC即可。

sampleRateInHz 指定采集音频的采样频率,比较通用的是44100(44.1kHz),这个值是科学家们通过奈葵斯特采样定理得出的一个人能接受最佳的采样频率值。

channelConfig 指定AudioRecord采集几个声道的声音,预设值定义在AudioFormat中,常用值有 CHANNEL_CONFIGURATION_MONO(单声道) 和 CHANNEL_CONFIGURATION_STEREO(双声道)。

audioFormat 指定采样PCM数据的采样格式,预设值定义在也AudioFormat中,常用值有 ENCODING_PCM_8BIT、ENCODING_PCM_16BIT和ENCODING_PCM_FLOAT,值得强调的是ENCODING_PCM_16BIT可以保证兼容大部分Andorid手机。

bufferSizeInBytes 配置AudioRecord内部的音频数据缓冲区,一般来说缓存区越小,产生的音频延迟也越小;值得注意的是,我们可以利用AudioRecord.getMinBufferSize()这个方法帮我们算出最小的缓存区大小,这个数值最好不要自己计算,毕竟不同厂商可能有不同的缓存区采集实现。

检测AudioRecord当前状态

由于可能存在权限问题导致配置AudioRecord失败,所以我们需要在开始采集前检查一下AudioRecord的状态:

if (mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) {

//todo start

}

如果getState()不等于AudioRecord.STATE_INITIALIZED说明创建AudioRecord失败,这时候应该给用户反馈信息。

完整代码如下:

//获取最低AudioRecord内部音视频缓冲区大小,此大小依赖于各产商实现,最好不要自己计算

mRecordBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);

//初始化AudioRecord实例

mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, mRecordBufSize);

//检测AudioRecord初始化是否成功

if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {

mAudioRecord = null;

mRecordBufSize = 0;

return false;

}

else {

//创建一个位置用于存放后续的PCM数据

mPcmData = new byte[mRecordBufSize];

mState = INIT;

return true;

}

开始采集

创建好了AudioRecord实例,调用如下的方法即可开始麦克风采集:

mAudioRecord.startRecording();

提取数据

调用了开始采集后,我们需要另起一条线程进行PCM数据提取。

我们需要循环不断从AudioRecord的缓冲区里面将数据读取出来,值得注意的是这个过程一定要及时,不然会出现“overrun”的错误,也就是没有及时取走音频数据导致音频缓存区溢出了。

private Thread mReadDataThread = new Thread() {

@Override

public void run() {

int read;

while (mState == RECORDING) {

//读取mRecordBufSize长度的音频数据存入mPcmData中

read = mAudioRecord.read(mPcmData, 0, mRecordBufSize);

//如果读取音频数据没有出现错误 ===> read 大于0

if (read >= AudioRecord.SUCCESS) {

synchronized (AudioRecordRecord.class){

if (mCallback != null)

mCallback.onPCMDataAvailable(mPcmData, read);

}

}

}

}

};

停止采集,释放资源

停止录音我们可以调用AudioRecord的stop方法来实现。

mAudioRecord.stop();

但是我们存在采集(音频提取)线程,所以我们需要更改一个状态变量让线程结束

mState = INIT;

使得 while (mState == RECORDING) 退出循环逻辑。

接着我们需要释放录制器的资源,以便设备的其他应用可以正常使用录音器,我们可以调用AudioRecord的release方法。

mAudioRecord.release();

这样就完整的结束了AudioRecord的采集业务。

播放PCM文件

Audacity这个工具可以导入pcm原始文件,并且提供了波形图查看和播放功能。

操作流程是:

文件 => 导入 => 原始数据 => 设置PCM数据格式 => 导入

具体效果图如下:

p1.png

结语

下一篇博客会介绍一下Android利用OpenSL ES进行录音导出PCM数据。

本文同步发布于简书、CSDN。

End!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring 3和Java EE 6 –不公平和不完整的比较

这篇小文章的初稿标题为“ Spring&Java EE –比较苹果和橙子”。 在撰写本文时,我了解到可以比较Spring Framework和Java EE,但这始终是不公平且不完整的工作。 Java for Enterprise和Spring Framework的发展紧密地联系在一起。 两者相互依存…

xml配置文件推荐方式

1.XML帮助类 /// <summary>/// Xml帮助类/// </summary>public class XmlHelper{/// <summary>/// 保存xml/// </summary>/// <typeparam name"T"></typeparam>/// <param name"path"></param>/// <p…

AFNetWorking https SSL认证

一般来讲如果app用了web service , 我们需要防止数据嗅探来保证数据安全.通常的做法是用ssl来连接以防止数据抓包和嗅探 其实这么做的话还是不够的 。 我们还需要防止中间人攻击&#xff08;不明白的自己去百度&#xff09;。攻击者通过伪造的ssl证书使app连接到了伪装的假冒的…

查看环境列表_Xfce 4.14桌面环境正式发布,想要图形界面又想节省内存?就它了...

1. Xfce 4.14桌面环境正式发布&#xff0c;它有什么新特性&#xff1f;本文主要讲解Xfce 4.14桌面环境正式发布&#xff0c;它有什么新特性。Xfce已经开发了4年多&#xff0c;但是这个周末终于看到了期待已久的Xfce 4.14的发布。Xfce 4.14是这个轻量级桌面环境的最新稳定版本&a…

使用Log4jdbc记录JDBC操作

当我们开发任何应用程序&#xff0c;完成它或结束其任何模块时&#xff0c;我们都会开始优化过程。 大多数应用程序都包含数据库访问权限&#xff0c;并且如果您使用的是ORM &#xff0c;则可能会使用hibernate 。 优化休眠持久层&#xff0c;要求准备阅读&#xff0c;理解和评…

android BluetoothAdapter蓝牙BLE扫描总结

做室内定位的程序员应该都知道&#xff0c;在Android 5.0之后&#xff0c;google推出了蓝牙扫描新接口&#xff0c;我们在实测中发现出一些问题&#xff0c;现在给大家列出&#xff0c;以供参考&#xff1a; 1.android 4.3.1(Build.VERSION_CODES.JELLY_BEAN_MR2)增加的startLe…

卷积神经网络语音识别_用于物体识别的3D卷积神经网络

本文提出了一种基于CNN的3D物体识别方法&#xff0c;能够从3D图像表示中识别3D物体&#xff0c;并在比较了不同的体素时的准确性。已有文献中&#xff0c;3D CNN使用3D点云数据集或者RGBD图像来构建3D CNNs&#xff0c;但是CNN也可以用于直接识别物体体积表示的体素。本文中&am…

段落排版--对齐(text-aliagn)

想为块状元素中的文本、图片设置居中样式吗&#xff1f;可以使用text-align样式代码&#xff0c;如下代码可实现文本居中显示。(那么什么是块状元素呢&#xff1f;后面会讲到呢~) h1{text-align:center; } <h1>了不起的盖茨比</h1> 同样可以设置居左&#xff1a; h…

Java 7:在不丢失数据的情况下关闭NIO.2文件通道

关闭异步文件通道可能非常困难。 如果您将I / O任务提交到异步通道&#xff0c;则需要确保正确执行了任务。 实际上&#xff0c;出于多种原因&#xff0c;这对于异步通道可能是一个棘手的要求。 默认的通道组使用守护进程线程作为工作线程&#xff0c;这不是一个好选择&#xf…

JavaScript封装方法,兼容参数类型为Number和String

/*** 依据Kind确定跳转到目标列表页面。* param kind*/function gobackByKind(kind) {var kindStr String(kind);switch(kindStr){case "1"://跳转到客户列表页面window.location.href/biz/customer/list;break;case "2"://跳转到代理机构列表页面window.…

#获得请求来源ip_以太网数据包TCP、IP、ICMP、UDP、ARP协议头结构详解

以太网首部目地MAC地址(8字节)源MAC地址(8字节)类型(2字节)1、IP头的结构版本(4位)头长度(4位)服务类型(8位)封包总长度(16位)封包标识(16位)标志(3位)片断偏移地址(13位)存活时间(8位)协议(8位)校验和(16位)来源IP地址(32位)目的IP地址(32位)选项(可选)填充(可选)数据(1)字节和…

团队项目第二次冲刺Ⅶ

今天将整体代码的编码方式改了&#xff0c;作业模块基本修改完成 遇到的问题是对于添加问答模块无从下手转载于:https://www.cnblogs.com/brucekun/p/5573312.html

编写Play 2的模块,第2部分:拦截器

在本教程的第一部分中&#xff0c;我们介绍了创建&#xff0c;发布和调用模块的基本知识。 我们创建的模块并没有真正做很多事情&#xff0c;因此现在是时候使用Play的某些功能来扩展功能了。 1.拦截器 拦截器使您可以拦截对控制器的调用&#xff0c;并增强或阻止其行为。 在第…

c# ef报错_C# EF调用MySql出现“未将对象引用设置到对象的实例”错误解决方案

C# EF调用MySql出现“未将对象引用设置到对象的实例”错误解决方案---修改步骤---1.打开Nuget管理包&#xff0c;把Mysql.Data替换为6.10.0以下任意版本。这里选择的是6.8.82.修改完毕后&#xff0c;继续把Mysql.Data.Entity也修改为对应版本6.8.8。3.安装完成后可以看到App.Co…

js格式化时间

Date.prototype.format function(fmt) {var o { "M" : this.getMonth()1, //月份 "d" : this.getDate(), //日 "h" : this.getHours(), //小时 "m" : this.getMinu…

PHP---函数

一.函数定义的四个要素 返回类型&#xff0c;函数名&#xff0c;参数列表&#xff0c;函数体 //1.最简单的定义方式/*function show(){ echo "hello";}show();*///2.有参数的函数定义/*function show($a){ echo $a;}show("bbbbb");*///3.有默认值的函数定义…

ServletRequest startAsync()的有用性有限

前段时间我遇到了Servlet 3.0中AsyncContext.start&#xff08;…&#xff09;的目的是什么&#xff1f; 题。 引用上述方法的Javadoc &#xff1a; 使容器调度线程&#xff08;可能从托管线程池中&#xff09;运行指定的Runnable 。 提醒大家&#xff0c; AsyncContext是Servl…

mysql所支持的比较运算符_mysql比较运算符有哪些?Mysql比较运算符详解

比较运算符可用于比较数字和字符串。今天发一篇Mysql比较运算符详解&#xff0c;希望对初学者有所帮助&#xff0c;虽然现在流行NoSQL&#xff0c;但是MYSQL还是很有用的&#xff0c;数字作为浮点值进行比较&#xff0c;字符串以不区为例进行比较&#xff0c;运算符用于比较表达…

数据结构0类模板的使用

类模板的使用 #include <iostream> #include <conio.h> #include <string> #define N 3 using namespace std;template <class numtype> class Swap{public :Swap(numtype a,numtype b){xa;yb;}numtype ___(){tempx;xy;ytemp;return x;}//testnumtype …

JavaScript 函数

函数 由于JavaScript的函数也是一个对象&#xff0c;所以类似function abs(v){}函数实际上是一个函数对象&#xff0c;而函数名abs可以视为指向该函数的变量。 因此&#xff0c;第二种定义函数的方式如下&#xff1a; var abs function (x) {if (x > 0) {return x;} else {…