AudioRecord 录音时有两种读取模式,一种是AudioRecord.READ_BLOCKING,另外一种是AudioRecord.READ_NON_BLOCKING,但是对这两种模式的定义却比较模糊

/*** The read mode indicating the read operation will block until all data* requested has been read.*/
public final static int READ_BLOCKING = 0;/*** The read mode indicating the read operation will return immediately after* reading as much audio data as possible without blocking.*/
public final static int READ_NON_BLOCKING = 1;

只说一种是会阻塞直到数据读取成功,另外一种是立刻返回尽可能多的数据而不阻塞。那么假设我选择READ_NON_BLOCKING模式,会不会导致读取到的数据长度是变化的?这两种模式究竟有什么区别?

我们跟踪安卓的源码,AudioRecord.read最终会调用到frameworks/av/media/libaudioclient/AudioRecord.cpp:

ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking)
{if (mTransfer != TRANSFER_SYNC) {return INVALID_OPERATION;}if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {// Validation. user is most-likely passing an error code, and it would// make the return value ambiguous (actualSize vs error).ALOGE("%s(%d) (buffer=%p, size=%zu (%zu)",__func__, mPortId, buffer, userSize, userSize);return BAD_VALUE;}ssize_t read = 0;Buffer audioBuffer;while (userSize >= mFrameSize) {audioBuffer.frameCount = userSize / mFrameSize;status_t err = obtainBuffer(&audioBuffer,blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);if (err < 0) {if (read > 0) {break;}if (err == TIMED_OUT || err == -EINTR) {err = WOULD_BLOCK;}return ssize_t(err);}size_t bytesRead = audioBuffer.size;memcpy(buffer, audioBuffer.i8, bytesRead);buffer = ((char *) buffer) + bytesRead;userSize -= bytesRead;read += bytesRead;releaseBuffer(&audioBuffer);}if (read > 0) {mFramesRead += read / mFrameSize;// mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.}return read;
}

可以看到,java层传过来的参数最终转换成布尔值blocking。在正常读取的时候,无论是否blocking,都会等到读取userSize之后再返回;在读取出错时,假设读取到了数据,无论是否blocking,最终也都会返回已读取的这部分数据。唯一的区别点在于obtainBuffer的传参,blocking等待时间为:ClientProxy::kForever,即INT_MAX sec,non_blocking等待时间为ClientProxy::kNonBlocking,即0。

const struct timespec ClientProxy::kForever = {INT_MAX /*tv_sec*/, 0 /*tv_nsec*/};
const struct timespec ClientProxy::kNonBlocking = {0 /*tv_sec*/, 0 /*tv_nsec*/};

需要注意的是,这个地方只是默认值,在obtainBuffer内部某些case下blocking也会被修改为non_blocking,例如

同时,在obtainBuffer内部也会进行一些状态判定,例如如果是未初始化等,无论是否blocking,都会直接返回error,只有状态正常,但是未能读取到数据时该参数才会生效


综上:

  1. 无论是否blocking,正常状态下都会读取到我们设置的bufferSize然后再返回;
  2. 无论是否blocking,在一些异常状态下都会不阻塞直接返回,例如状态错误等;
  3. 出错时无论是否blocking,都会返回已read的这部分size,有可能小于我们设置的bufferSize;
  4. 只有在状态正常但是数据未读取到时,blocking模式会进行阻塞等待,non_blocking直接返回WOULD_BLOCK的错误;

实际项目中验证发现情况4出现的概率还挺高的,会导致录音概率性有空白,推荐使用阻塞模式。

AudioRecord READ_BLOCKING 与 READ_NON_BLOCKING的区别相关推荐

  1. FFmpeg3.3.2+SDL2实现流媒体音频播放

    我的视频课程(基础):<(NDK)FFmpeg打造Android万能音频播放器> 我的视频课程(进阶):<(NDK)FFmpeg打造Android视频播放器> 我的视频课程(编 ...

  2. Android音频录制方案,Android录音,录制其他App播放的声音

    Android录音,录制其他App播放的声音 从Android10(SDK 29)版本开始,可以设置录音App的源为其他App,这样就可以录制其他App播放的声音 此方案有以下注意几点 设置了源为其他 ...

  3. Android录音并播放(mp3或amr格式)

    Android项目中媒体是很多人头疼的一个问题,不仅仅因为处理起来很麻烦,而且不同的手机差别很大(和硬件,系统都有关系),今天就总结一下Android中的录音和播放,可保存成mp3或amr格式. 小米 ...

  4. Android如何将采集到的音频PCM文件转为WAV并保存

    1.Android音频采集 添加权限 <uses-permission android:name="android.permission.RECORD_AUDIO" /> ...

  5. MediaPlayer/MediaRecorder与AudioTrack/AudioRecord区别(三十九)

    android audio 生产者与消费者 简介 全面接触生产者/消费者问题是在操作系统原理中,并发性原理讨论的问题 生产者/消费者问题.最近的工作偏向音频,接着上一篇文章,用生产者,消费者模型来理解 ...

  6. android录音mediaRecord\AudioRecord\openSL\PCM tinyalsa总结和优缺点

    常规录音 可以参考传送门_2learn MediaRecord 传统的android上,最简单的录音方式,莫过于MediaRecord. mMediaRecorder = new MediaRecor ...

  7. low latency playback、deep buffer playback、compressed offload playback的区别 学习学习

    low latency playback.deep buffer playback.compressed offload playback的区别 https://blog.csdn.net/u0101 ...

  8. Android 音视频开发(一) -- 使用AudioRecord 录制PCM(录音);AudioTrack播放音频

    前言,音视频这块,确实比较难入门,本着学习的态度,我这边也跟着 Android 音视频开发入门指南 打怪升级,留下个脚印,大家共勉. 音视频 系列文章 Android 音视频开发(一) – 使用Aud ...

  9. 音视频开发系列(27)AudioRecord录制PCM音频

    目录 音频采集API AudioRecord和MediaRecorder介绍 PCM的介绍 AudioRecord的使用(构造.开始录制.停止录制.其他细节点) ffplay播放pcm pcm转为wa ...

最新文章

  1. python程序实例源代码-python下10个简单实例代码
  2. 【堆栈】最近有兴趣的几个问题
  3. HDU - 5459 Jesus Is Here(思维+非线性递推)
  4. [Abp 源码分析]后台作业与后台工作者
  5. docker容器状态跟踪及疑惑
  6. Linux群常见问题整理(一)[转]
  7. 数据结构二叉树的建立代码_二叉树就是这么简单
  8. HTML案例登录页面
  9. java调用cmd命令
  10. 云更新网吧系统服务器,云更新网吧服务器环境要求
  11. 解决 java 程序中 CPU 占用率过高问题
  12. c语言 日期加减天数返回日期 闰年,日期计算器(多图)
  13. Python初学(2)—— 基本数据类型
  14. 洛谷 P3817 小A的糖果
  15. SPP (Spatial Pyramid Pooling)
  16. 什么是3D摄影机,与普通摄影机有什么不同?
  17. 每天不知道吃什么,于是我做了个随机选择的小程序
  18. android系统锁屏锁怎么解决方法,忘了图案锁?这是你如何解锁Android模式锁定屏幕!...
  19. 安装实例中出现的ORA-27123和ORA-12532的错误
  20. 为王菲写的第二首歌《山河》

热门文章

  1. 计算光学成像(COI)实验室技能——matlab控制thorlabs位移平台(ActiveX控件)
  2. ios xib 初始化高度_iOS xib自定义,高度减少64
  3. 一个女孩从软件测试工程师到主管的成长
  4. ffmpeg处理音视频相关命令
  5. nutch+solor+elcipse安装配置
  6. html5 ios cookie,iOS cookie
  7. 安全学院“传承文化”暑期实践团参观秦始皇兵马俑
  8. 独立成分分析及Demo
  9. Angular5.x入门教程1
  10. 读《DevOps实践指南》笔记一