音频文件在播放时出现声音断断续续,一卡一卡的或类似“爆破”(Pop-Click)杂音的现象,称之为 Xrun(可以是 underrun,也可以是 overrun)。

分析:

alsa driver使用了环形缓冲区对dma buffer进行管理,如下图。

播放时,应用程序把音频数据源源不断地写入dma buffer中,然后相应platform的dma操作则不停地从该buffer中取出数据,经dai送往codec中,当写入的数据慢,播放的数据快时声音会出现断断续续,一卡一卡的现象。

录音时,codec源源不断地把A/D转换好的音频数据经过dai送入dma buffer中,而应用程序则不断地从该buffer中读走音频数据,当写入的数据快,播放的数据慢时,当数据量较多buffer有可能被冲掉,声音会出现类似“爆破”(Pop-Click)杂音的现象。

[RK3288][Android5.1] 调试如下:

1、播放的数据快,写入的数据慢时,触发DMA中断,将音频数据写入dma buffer中,出现一卡一卡的现象!检查codec和machine的采样频率,设置ASoc框架的Codec驱动和Machine驱动的输出freq = 12288000。

//设置codec dai的主时钟,采样率
static int xvf3500_set_dai_sysclk(struct snd_soc_dai *codec_dai,int clk_id, unsigned int freq, int dir)
{
...freq = 12288000;switch (freq) {
...case 12288000:case 16934400:case 24576000:case 33868800:xvf3500->sysclk_constraints = &constraints_12288;xvf3500->sysclk = freq;return 0;
...}return -EINVAL;
}
//在machine设置codec dai采样率,保持codec驱动采样率一致
static int rk29_xvf3500_init(struct snd_soc_pcm_runtime *rtd)
{
...ret = snd_soc_dai_set_sysclk(codec_dai, 0,12288000, SND_SOC_CLOCK_IN);if (ret < 0) {printk(KERN_ERR "Failed to set xvf3500 SYSCLK: %d\n", ret);return ret;}
...return 0;
}

2、当写入的数据快,播放的数据慢时,当数据量较多buffer有可能被冲掉,声音会出现类似“爆破”或“呲呲”杂音的现象。通过调整硬件抽象层的period_size和period_count,来改变dma的传输数据量。


struct pcm_config {unsigned int channels;unsigned int rate;unsigned int period_size;unsigned int period_count;enum pcm_format format;unsigned int start_threshold;unsigned int stop_threshold;unsigned int silence_threshold;int avail_min;
};

合理的pcm_config可以做到更好的低时延和功耗。解释一下结构中的各个参数,每个参数的单位都是frame(1帧 = 通道*采样位深):

  • period_size. 每次传输的数据长度。值越小,时延越小,cpu占用就越高。
  • period_count. 缓之冲区period的个数。缓冲区越大,发生XRUN的机会就越少。
  • format. 定义数据格式,如采样位深,大小端。
  • start_threshold. 缓冲区的数据超过该值时,硬件开始启动数据传输。如果太大, 从开始播放到声音出来时延太长,甚至可导致太短促的声音根本播不出来;如果太小, 又可能容易导致XRUN.
  • stop_threshold. 缓冲区空闲区大于该值时,硬件停止传输。默认情况下,这个数 为整个缓冲区的大小,即整个缓冲区空了,就停止传输。但偶尔的原因导致缓冲区空, 如CPU忙,增大该值,继续播放缓冲区的历史数据,而不关闭再启动硬件传输(一般此 时有明显的声音卡顿),可以达到更好的体验。
  • silence_threshold. 这个值本来是配合stop_threshold使用,往缓冲区填充静音 数据,这样就不会重播历史数据了。但如果没有设定silence_size,
  • avail_min. 缓冲区空闲区大于该值时,pcm_mmap_write()才往缓冲写数据。这个 值越大,往缓冲区写入数据的次数就越少,面临XRUN的机会就越大。Android samsung tuna 设备在screen_off时增大该值以减小功耗,在screen_on时减小该 值以减小XRUN的机会。

在不同的场景下,合理的参数就是在性能、时延、功耗等之间达到较好的平衡。

//修改HAL层的period_size 和 period_count路径...hardware/rockchip/audio/tinyalsa_hal/audio_hw.h
//播放
struct pcm_config pcm_config = {.channels = 2,.rate = 48000,.period_size = 2048,.period_count = 4,.format = PCM_FORMAT_S16_LE,};
//录音
struct pcm_config pcm_config_in = {.channels = 2,.rate = 48000,.period_size = 128,//1024.period_count = 32,//4.format = PCM_FORMAT_S16_LE,};

调试技巧:实时录音会有呲呲噪音问题,修改pcm_config_in的period size和period_count大小,使其period_size * period_count的乘积为4096不变。

总结:

这种方法通过增加或减少音频数据的 period_count或period_size来进行补偿。但这样也会使音频播放/录音的数据准备时间变长,增加音频操作的延迟。

解决Android 音频Xrun问题相关推荐

  1. 解决Android5.1系统下音频Xrun(underrun或overrun)问题

    基于RK3288解决Android5.1系统下音频Xrun(underrun或overrun)问题 2018年11月23日 16:35:06 21cnhui 阅读数:38 标签: Android  a ...

  2. Android 音频tinyalsa开发

    Platform: AIO-3399J OS: Android 7.1 Kernel: v4.4.83 在开发完音频驱动后,通过tinyplay.tinycap测试音频驱动的播放和录音功能正常,但使用 ...

  3. Android音频子系统(十四)------耳机杂音问题解析

    你好!这里是风筝的博客, 欢迎和我一起交流. 背景介绍: [前提条件]OPPO的模拟有线耳机 [操作步骤]打开全民K歌进行任意一首音乐K歌的时候 [实际结果]耳机里面有滋滋的杂音 [期望结果]耳机里面 ...

  4. Android 音频系统:从 AudioTrack 到 AudioFlinger(全)

    Android 音频框架概述 Audio 是整个 Android 平台非常重要的一个组成部分,负责音频数据的采集和输出.音频流的控制.音频设备的管理.音量调节等,主要包括如下部分: Audio App ...

  5. android音频降噪webrtc

    在音频处理的开源项目中,webrtc是一个很不错的例子.它包含降噪,去回声,增益,均衡等音频处理.这里我讲讲我所使用到的如何使用降噪方式.当然,具体它是如何降噪的,大家可以细看源码处理了.好了,线上源 ...

  6. 一次搞懂 Android 音频开发

    在接触Android音频开发后,陆陆续续的看了不少的文章,如果说查缺补漏把这些文章梳理清楚,然后逐个整合,那么确实也能完整的推导出音频开发需要掌握的技术.但是对于初学者来说,可能在开发中产生很多障碍以 ...

  7. Android 音频技术开发总结

    转载地址:https://yq.aliyun.com/articles/8637 摘要: 在文章开头,我们先来了解几个概念,这样有利于对后面内容的理解. 1.概念理解 采样率:即采样频率,百科的解释是 ...

  8. Android音频改进设想及PulseAudio

    在这里先说明,本人并没有仔细地去看Android和PulseAudio的音频具体源代码和实现,欢迎指正. 从硬件用料上看,Android能不能做好音质?答案当然是可以的!MOTO的手机音质就做得不错. ...

  9. Android音频系统的改进设想和展望 PulseAudio介绍

    http://www.soomal.com/doc/10100002871.htm 在这里先说明,本人并没有仔细地去看Android和PulseAudio的音频具体源代码和实现,欢迎指正. 从硬件用料 ...

最新文章

  1. 你哪来这么多事(三):学生信息删除
  2. 强化学习(十七) 基于模型的强化学习与Dyna算法框架
  3. 卸载unixodbc_完全卸载旧的unixODBC并在redhat 6.3中安装2.3.2 unixODBC
  4. c语言到底写什么系统,用C语言写关于操作系统的一个问题。
  5. (转)《崩坏3》画面效果为何惊艳?看米哈游怎么做卡通渲染的你就明白了
  6. 3-1 Aruba交换机实用配置-VSF 2020
  7. unity摄像机镜头平滑处理
  8. Java笔记 - 黑马程序员_07(多线程,线程同步,线程池,网络编程入门,UDP通信原理,TCP通信原理,commons-io工具类)
  9. 服务器日志显示意外关闭,服务器多次异常关闭,错误日志:计算机已经从检测错误后重新启动。。检测错误: - Microsoft Community...
  10. NGUI|如何做出用鼠标滚动切换武器的效果
  11. MacBook Pro电池维修记
  12. Java企业级开发框架(一):概述
  13. 传感器模组:手机摄像头模组-1亿像素是如何实现的?
  14. Java使用阿里邮箱生成excle邮件附件发送
  15. 公众号名称搜索排名多久更新
  16. FDFS_Ubuntu部署fdfs测试上传文件不成功
  17. ios heic格式照片批量转jpg工具
  18. 电脑硬盘误格式化怎么恢复?
  19. [附源码]计算机毕业设计JAVA电子病历信息管理系统
  20. 开源项目-学生成绩查询分析管理系统

热门文章

  1. [转]ie6下CSS存在的BUG
  2. bzoj 3527 [Zjoi2014]力——FFT
  3. Cocos Creator 获取当前URL取参数
  4. 20165334 《java程序设计》第5周学习总结
  5. jQuery 遍历 - prev() 方法
  6. 如何使用CHM 绕过Device guard
  7. JVM性能优化, Part 5:Java的伸缩性
  8. java ByteBuffer flip()和limit()的理解
  9. build_doxygen_报找不到iconv.....
  10. asp.net mvc Autofac 依赖注入框架 使用