Android 音视频技术之录音获取实时音量
一、实时音量相关基础知识
说到获取音量,大家首先想到的应该就是分贝(dB),分贝是一个相对单位(是一个比值,是一个数值,是一个纯计数方法)。
在音频领域dB度量的是声音的强度,其计算的公式如下:
在上面的公式中,分子是测量值的声压,分母是参考值的声压(20微帕,人类所能听到的最小声压)。
在Android设备传感器中,我们能获取到的物理值是振幅值,一般使用下面的公式来计算分贝值:
我们从Android SDK中读取了某段音频数据的振幅后,取最大振幅或平均振幅(可以用平方和平均,或绝对值的和平均),代入上述公式的A1。参考的振幅A0取值定为1(这里取1是为了实现方便,如需更加精确建议拿一个标准分贝计做校准参考),作为 Android 麦克风能听到的最小的声音振幅。这样我们就可以计算出分贝值了。
二、Android 获取实时音量
获取音量之前,我们必须先在AndroidManifest.xml文件里面申请相应的权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
在Android SDK提供的API中,我们能获取到音频方式有两个:android.media.MediaRecorder 和 android.media.AudioRecord。
1. MediaRecorder
MediaRecorder 是用来录制一段完整的音视频并写入到文件系统中的API。通过它,我们能很简单的通过它的无参方法getMaxAmplitude来获取一小段时间内音频源数据中的最大振幅,此方法是很多录音软件计算音量等级所采用的办法。(注:因为是取最大值,所以存在受到极端数据的影响而导致计算的分贝波动值较大的问题)。
使用MediaRecorder.getMaxAmplitude返回的是0到32767范围的16位整型。如果设置参考振幅为1的话,那么计算出来的分贝值域的正常范围应该为 0dB 到 90.3dB。
核心代码:
/**
* 开始录音 使用amr格式
*/
public void startRecord() {
// 开始录音
/* ①Initial:实例化MediaRecorder对象 */
if (mMediaRecorder == null)
mMediaRecorder = new MediaRecorder();
try {
/* ②setAudioSource/setVedioSource */
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
/* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
/*
* ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
* ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
*/
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
/* ③准备 */
mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory().getPath() + File.separator + "111.amr");
mMediaRecorder.setMaxDuration(MAX_LENGTH);
mMediaRecorder.prepare();
/* ④开始 */
mMediaRecorder.start();
updateMicStatus();
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
} /**
* 停止录音
*/
private void stopRecord() {
if (mMediaRecorder == null) {
return;
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
} private void updateMicStatus() {
if (mMediaRecorder != null) {
double ratio = (double) mMediaRecorder.getMaxAmplitude() / 1; // 参考振幅为 1
double db = 0;// 分贝
if (ratio > 1) {
db = 20 * Math.log10(ratio);
}
Log.d(TAG, "计算分贝值 = " + db + "dB");
mHandler.postDelayed(mUpdateMicStatusTimer, 100); // 间隔取样时间为100秒
}
}
2. AudioRecord
此API相对MediaRecorder来说更偏底层一点,我们可以使用AudioRecord获得具体的音频数据。
音源数据通过read(byte[] audioData, int offsetInBytes, int sizeInBytes)方法从缓冲区读取到我们传入的字节数组audioData后,我们便可以对其进行操作,如求平方和或绝对值的平均值。这样可以避免个别极端值的影响,使计算的结果更加稳定。求得平均值之后,如果是平方和则代入常数系数为10的公式中,如果是绝对值的则代入常数系数为20的公式中,算出分贝值。
核心代码:
public void getNoiseLevel() { mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_IN_HZ,
AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE); new Thread(new Runnable() {
@Override
public void run() {
mAudioRecord.startRecording();
short[] buffer = new short[BUFFER_SIZE];
while (isGetVoiceRun) {
//r是实际读取的数据长度,一般而言r会小于buffersize
int r = mAudioRecord.read(buffer, 0, BUFFER_SIZE);
long v = 0;
// 将 buffer 内容取出,进行平方和运算
for (short value : buffer) {
v += value * value;
}
// 平方和除以数据总长度,得到音量大小。
double mean = v / (double) r;
double volume = 10 * Math.log10(mean);
Log.d(TAG, "分贝值 = " + volume + "dB");
synchronized (mLock) {
try {
mLock.wait(100); // 一秒十次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
}
}).start();
}
github地址:https://github.com/renhui/RHAudioVolume/tree/master
Android 音视频技术之录音获取实时音量的更多相关文章
- Android音视频之AudioRecord录音(一)
在音视频开发中,录音当然是必不可少的.首先我们要学会单独的录音功能,当然这里说的录音是指用AudioRecord来录音,读取录音原始数据,读到的就是所谓的PCM数据.对于录音来说,最重要的几个参数要搞 ...
- Android 音视频深入 十七 FFmpeg 获取RTMP流保存为flv (附源码下载)
项目地址https://github.com/979451341/RtmpSave 这个项目主要代码我是从雷神那弄过来的,不愧是雷神,我就配个环境搞个界面就可以用代码了. 这一次说的是将RTMP流媒体 ...
- 了不起的WebRTC:生态日趋完善,或将实时音视频技术白菜化
本文原文由声网WebRTC技术专家毛玉杰分享. 1.前言 有人说 2017 年是 WebRTC 的转折之年,2018 年将是 WebRTC 的爆发之年,这并非没有根据.就在去年(2017年),WebR ...
- Android IOS WebRTC 音视频开发总结(七十)-- 移动端音视频技术优化的七个方向
最近直播很火,很多朋友对背后的技术比较感兴趣,所以今天我们整理一篇关于移动端视频优化的文章,这篇文章是我朋友在一个技术大会上分享过的,更多内容请关注我们的微信公众号:rtcblacker 视频直播为什 ...
- android音视频点/直播模块开发
音视频 版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能,那么作为开发一个小白, ...
- Android音视频点/直播模块开发实践总结-zz
随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能.那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及 ...
- 堪称教科书级别的Android音视频入门进阶学习手册,开源分享!
概述 随着整个互联网的崛起,数据传递的形式也在不断升级变化,总的流行趋势如下: 纯文本的短信,QQ -> 空间,微博,朋友圈的图片文字结合 -> 微信语音 -> 各大直播软件 -&g ...
- Android音视频开发(1):H264 基本原理
前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...
- 手机Android音视频采集与直播推送,实现单兵、移动监控类应用
从安卓智能手机.平板,到可穿戴的Android Ware.眼镜.手表.再到Android汽车.智能家居.电视,甚至最近看新闻,日本出的几款机器人都是Android系统的,再把目光放回监控行业,传统监控 ...
随机推荐
- F#周报2019年第48期
新闻 拥抱可空引用类型 介绍Orleans 3.0 视频及幻灯片 组合的力量 关于.NET:探索新的用于.NET的Azure .NET SDK .NET设计审查:GitHub快速审查 FableCon ...
- scrapy抓取国家社科基金项目数据库
1.明确任务 目标网站:http://fz.people.com.cn/skygb/sk/index.php/Index/seach 抓取任务:抓取近五年某关键词(例如"能源".” ...
- altium designer 20.0.8
altium designer 20.0.8 download : http://dl3.downloadly.ir/Files/Software/Altium_Designer_20.0.8_Bet ...
- .Net Core 3.0 使用 Serilog 把日志记录到 SqlServer
Serilog简介 Serilog是.net中的诊断日志库,可以在所有的.net平台上面运行.Serilog支持结构化日志记录,对复杂.分布式.异步应用程序的支持非常出色.Serilog可以通过插件的 ...
- SpringMVC 前端传递list到后台
---恢复内容开始--- 1.前端获取传入后台的list 2.ajax写法: $.ajax({ type: 'post', url: url, async:false, dataType:" ...
- python 备忘录
1. python 变量 区分大小写 2. 字符串可以用 'X' "X" '''X''' """X""" 3. ...
- 用C在GBA上写光线追踪(0)配置开发编译环境
前段时间用C#写了一个光线追踪程序,可以渲染圆球,平面这种基本图形,反射,光照,阴影,都大致尝试做了一下. ↑ C#实现的光线追踪 ↑ GBA上C实现的光线追踪 然而,在我打算继续深入优化的时 ...
- iOS库的种类
一.什么是库? 库是共享程序代码的方式,一般分为静态库和动态库. 二.静态库与动态库的区别? 静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝. 动态库:链接时不复制,程序运行时由系 ...
- golang包管理的古往今来
https://golang.org/ before GO1.5-GOPATH 在GO1.5之前用GOPATH以及GOROOT这两个环境变量来决定包的位置. GOROOT就是告知当前go的安装位置,编 ...
- 2018HDU多校训练-3-Problem F. Grab The Tree
Little Q and Little T are playing a game on a tree. There are n vertices on the tree, labeled by 1,2 ...