【Android 高性能音频】AAudio 缓冲区控制 ( XRun | 欠载 UnderRun | 超限 OverRun | 获取缓冲区大小 | 设置缓冲区大小 )

简介: 【Android 高性能音频】AAudio 缓冲区控制 ( XRun | 欠载 UnderRun | 超限 OverRun | 获取缓冲区大小 | 设置缓冲区大小 )

文章目录

I . AAudio 音频流 缓冲区控制

II . AAudio 音频流 XRun ( UnderRun | OverRun )

III . AAudio 音频流 当前每次读写帧数

IV . AAudio 音频流 获取最大帧数

V . AAudio 音频流 设置缓冲区大小



注意 : 本文讲的是 AAudio 播放器的音频流缓冲区控制 , 可以将帧数理解成音频采样个数 ;

实际的采样帧数 , 与每帧的采样数 , 每帧的大小 是用户自己控制的 , 向 AAudio 音频流读写多少字节的采样 , 是用户自己控制的 ;



2 个缓冲区 : 播放器缓冲区 和 采样缓冲区 ;


① 播放器缓冲区 : 本文讲解的是 播放器缓冲区 设置与调整 ;

② 采样缓冲区 : 采样缓冲区指的是 , 一次性采集多少个字节的数据 , 写入到播放器中 ;

③ 理解 : 这两个缓冲区是不同的概念 , 注意区分 ;


每帧采样数 : 该值就是通道数 , 如果是单声道 , 每帧只有一个采样 , 如果是 双声道立体声 , 每帧有 2 个采样 ;




I . AAudio 音频流 缓冲区控制


1. 判定现状 : 首先要判定当前的 AAudio 音频流是否需要调整 , 判定的依据是是否出现了 XRun , 即 欠载 ( UnderRun ) 或 超限 ( OverRun ) 的状况 ;


2. 计算缓冲区调整值 : 获取本次的 XRun 值 , 然后与上一次的进行对比 , 如果本次的 XRun 值高于上一次 , 那么增加本次缓冲区的帧数 ;


3. 代码示例 :


 

//获取 欠载 或 超限 计数 , 这里是播放 , 是欠载
    // 该值只是用于判定当前是否欠载
    int32_t underrunCount = AAudioStream_getXRunCount(playStream_);
    // 获取 AAudio 音频流在不阻塞的情况下 , 可以读取 或 写入的最大帧数 ( 文档说法 感觉不对 )
    // 获取 当前缓冲区的值
    aaudio_result_t bufferSize = AAudioStream_getBufferSizeInFrames(playStream_);
    // 欠载数值是否增加
    bool hasUnderrunCountIncreased = false;
    // 是否应该改变缓冲区大小
    bool shouldChangeBufferSize = false;
    // 处理 播放完毕 数据还没来得及写入的情况
    // playStreamUnderrunCount_ 是打开音频流时的 欠载值 , 一般是 0
    // 如果当前的欠载值 大于 上一次的 欠载值
    // 将本次的欠载值 更新
    // 本次的欠载值将作为重新调整缓冲区大小的依据
    if (underrunCount > playStreamUnderrunCount_) {
        // 记录 本次的欠载值
        playStreamUnderrunCount_ = underrunCount;
        // 设置需要更新缓冲区大小
        hasUnderrunCountIncreased = true;
    }
    if (hasUnderrunCountIncreased && bufferSizeSelection_ == BUFFER_SIZE_AUTOMATIC) {
        // 用户没有设置缓冲区大小 , 此时 bufferSizeSelection_ 的值 为 BUFFER_SIZE_AUTOMATIC , 即 0
        /**
         * 这是一个调整缓冲区大小的算法 ;
         * 如果本次的 欠载 ( UnderRun ) 值 与 上一次回时的欠载值进行对比 , 本次高于上次的值 ,
         *  此时需要增加缓冲区的大小 , 增加数值为 单次写出的大小 ( Burst Size ) ;
         *  增加的 Burst Size 会防止未来出现 欠载 情形 , 同时该操作会以增加延迟为代价 ;
         *
         * 欠载 ( UnderRun ) 即 现有数据播放完毕 , 新数据还没有写入 , 出现空档 , 造成电流 ;
         *      无法提供足够的音频采样数据 ;
         */
        bufferSize += framesPerBurst_; // 缓冲区的大小增加 每次写入的帧数大小 Increase buffer size by one burst
        shouldChangeBufferSize = true;
    } else if (bufferSizeSelection_ > 0 && (bufferSizeSelection_ * framesPerBurst_) != bufferSize) {
        // 用户有设置缓冲区大小 , 并且这个大小与之前的大小不一致的情况 , 才修改缓冲区大小数值
        // 用户每次修改缓冲区大小 , 该分支代码逻辑就会执行一次
        // 如果用户修改了缓冲区大小 , 那么执行该逻辑
        bufferSize = bufferSizeSelection_ * framesPerBurst_;
        shouldChangeBufferSize = true;
    }
    //是否修改了缓冲区大小
    if (shouldChangeBufferSize) {
        LOGD("Setting buffer size to %d", bufferSize);
        //设置当前缓冲区是多少帧
        bufferSize = AAudioStream_setBufferSizeInFrames(stream, bufferSize);
        if (bufferSize > 0) {
            //更新当前类中维护的每帧缓冲区大小数值
            bufSizeInFrames_ = bufferSize;
        } else {
            LOGE("Error setting buffer size: %s", AAudio_convertResultToText(bufferSize));
        }
    }



II . AAudio 音频流 XRun ( UnderRun | OverRun )


1. XRun 概念 : XRun 是指 AAudio 音频流的 欠载 ( UnderRun ) 或 超限 ( OverRun ) ;


① 欠载 ( UnderRun ) : 播放音频流时 , 如果当前现有数据已经播放完毕 , 新数据还没有来得及写入 , 此时会发生欠载情况 ;

② 超限 ( OverRun ) : 录制音频流时 , 如果没有及时读取音频流数据 , 并且这些数据没有妥善保存 , 发生溢出 , 导致数据丢失 , 这种情况叫做超限 ;

2. 获取 XRun 数据 : 使用 AAudioStream_getXRunCount() 方法 , 可以获取该 XRun 数值 ;


3. AAudioStream_getXRunCount 函数原型 :


AAUDIO_API int32_t AAudioStream_getXRunCount(

 AAudioStream *stream

)

1

2

3

4. AAudioStream_getXRunCount 方法参数 : 传入 AAudio 音频流 指针类型 , 可以获取该音频流的 欠载 ( UnderRun ) 或 超限 ( OverRun ) 值 ;


5. 欠载 ( UnderRun ) 或 超限 ( OverRun ) 导致的问题 : 会导致出现电流问题 ;


6. 不支持 XRun 统计 的情况 : 某些设备可能不支持统计该数据 , 此时返回的 XRun 值为 0 ;




III . AAudio 音频流 当前每次读写帧数


1. AAudio 音频流 每次读写的帧数 :


① 当前读写帧数查询 : 在 AAudio 音频流读写音频数据时 , 为了达到性能最佳 , 需要查询当前音频流一次性可以读写的帧数 ;

② 查询方法 : 为了达到流读写的最佳性能 , 可以使用 AAudioStream_getFramesPerBurst 方法 , 查询该数值 ;

③ 帧数调整 : 应用中可以向 AAudio 音频流 读写 不同帧数的音频采样数据 , 但是为了避免 欠载 ( UnderRun ) 或 超限 ( OverRun ) , 我们可以增加该值 , 防止出现 数据不足 或 数据溢出 的情况 ;

④ 帧数变动后果 : 实际音频设备一次性读写数据量可能与该帧数不匹配 ; 对于某些音频设备 , 该 Brust ( 一次性读写数据量 ) 大小可以动态改变 ; 该操作可能会增大音频的延迟 ;

⑤ 每帧采样数 : 该值就是通道数 , 如果是单声道 , 每帧只有一个采样 , 如果是 双声道立体声 , 每帧有 2 个采样 ;


2. 获取每次读写帧数的函数 :


① 函数原型 :

AAUDIO_API int32_t AAudioStream_getFramesPerBurst(

 AAudioStream *stream

)

1

2

3

② 方法简介 : 该方法 传入 AAudioStream 指针类型参数 ( 代表 AAudio 音频流 ) , 可以获取该 AAudio 音频流每次读写的帧数 ;

③ 代码示例 :

           // 获取每次写入的帧数

           framesPerBurst_ = AAudioStream_getFramesPerBurst(playStream_);

1

2



IV . AAudio 音频流 获取最大帧数


AAudio 音频流 获取最大帧数 : 调用 AAudioStream_getBufferSizeInFrames() 方法 , 可以获取 AAudio 音频流在不阻塞的情况下 , 可以读取 或 写入的最大帧数 ;


① 方法原型 :

AAUDIO_API int32_t AAudioStream_getBufferSizeInFrames(
  AAudioStream *stream


② 代码示例 :

 

// 获取 AAudio 音频流在不阻塞的情况下 , 可以读取 或 写入的最大帧数 
    aaudio_result_t bufferSize = AAudioStream_getBufferSizeInFrames(playStream_);



V . AAudio 音频流 设置缓冲区大小


1. 函数作用 : 在音频流播放时 , 有可能会产生阻塞 , 即 采样播放完毕 , 新采样还没到达 , 该函数可以 通过 改变 缓冲区大小阈值 , 调整 缓冲区的延迟 , 即 如果出现 阻塞 , 可以增大该缓冲区大小 ( 帧数 ) ;


2. 结合 XRun 值使用 : 通过 AAudioStream_getXRunCount() 方法 , 可以获取 欠载 ( UnderRun ) 或 超限 ( OverRun ) 的值 , 根据该 XRun 值进行缓冲区大小的调整 , 达到为每个音频设备设置合适的延迟的目的 ;


3. 可设置的最大值 : 通过 AAudioStream_getBufferCapacityInFrames() 函数可以获取 缓冲区可设置的最大帧数 , 设置帧数时 , 不能超过该数值 ;


4. 查看当前缓冲区大小 : 调用 AAudioStream_getBufferSizeInFrames() 方法 , 可以查看当前的缓冲区帧数 ;


文档中的说法是 : 获取 AAudio 音频流在不阻塞的情况下 , 可以读取 或 写入的最大帧数 , 理解不通 ;


5. AAudioStream_setBufferSizeInFrames 函数简介 :


① 函数原型 : numFrames 是设置的新的缓冲区帧数 , stream 代表 AAudio 音频流指针 ;

AAUDIO_API aaudio_result_t AAudioStream_setBufferSizeInFrames(
  AAudioStream *stream,
  int32_t numFrames


② 代码示例 :

   

//设置当前缓冲区是多少帧
        bufferSize = AAudioStream_setBufferSizeInFrames(stream, bufferSize);


每帧采样数 : 该值就是通道数 , 如果是单声道 , 每帧只有一个采样 , 如果是 双声道立体声 , 每帧有 2 个采样 ;


目录
相关文章
|
8月前
|
Android开发 开发者
Android设置View是否可用
在Android开发中,有时需要将布局设置为不可点击状态(失去焦点)。常见的解决方法是使用`setOnClickListener(null)`,但本文介绍一种更通用的方式:通过封装`setViewEnabled`方法实现。该方法可递归设置View及其子View的启用状态,支持传入目标View和布尔值(`true`为可用,`false`为禁用)。例如,调用`setViewEnabled(edittext, false)`即可禁用EditText。文章附有源码及示例动图,帮助开发者快速理解与应用。
198 1
|
8月前
|
Android开发 开发者
Android中Dialog位置+样式的设置
本文介绍了在Android开发中如何设置Dialog的位置和样式。通过自定义`MyDialog`类,可以灵活调整Dialog的显示位置,例如将其固定在屏幕底部,并设置宽度匹配父布局。同时,文章还展示了如何模仿Android原生Dialog样式,通过定义`MyDialogStyle`去除标题栏、设置背景透明度、添加阴影效果以及配置点击外部关闭等功能,从而实现更加美观和符合需求的Dialog效果。代码示例详细,便于开发者快速上手实现。
462 2
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
535 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
1138 4
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
679 0
|
Java API Android开发
【Android 高性能音频】高性能音频简介 ( 高性能音频问题引入 | 使用场景 | 相关开发库及技术 )
【Android 高性能音频】高性能音频简介 ( 高性能音频问题引入 | 使用场景 | 相关开发库及技术 )
306 0
|
3月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
389 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
3月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
389 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
3月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
854 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
4月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
649 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡

热门文章

最新文章