Android2.3-> Audio-> aplay播放的的问题

解决aplay测试中音乐卡顿问题的代码优化
文章详细介绍了在aplay测试中遇到音乐播放卡顿问题时,通过调整pcm_open调用前的flags变量配置,以及定义AUDIO_HW_OUT_PERIOD_MULT和AUDIO_HW_OUT_PERIOD_CNT宏来优化audiobuffer大小,从而有效解决音乐播放卡顿的方法。
  你在aplay.c文件的play_file函数的pcm_open调用前面加上flags |= (AUDIO_HW_OUT_PERIOD_MULT - 1) << PCM_PERIOD_SZ_SHIFT;
        flags |= (AUDIO_HW_OUT_PERIOD_CNT - PCM_PERIOD_CNT_MIN) << PCM_PERIOD_CNT_SHIFT;

  然后加上#define AUDIO_HW_OUT_PERIOD_MULT 8 

#define AUDIO_HW_OUT_PERIOD_CNT 4这两个宏定义

解决aplay测试的时候, audio buffer过小引起音乐卡的问题


static int soc_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct snd_soc_dai *dai; int i, ret = 0; for_each_rtd_components(rtd, i, component) pinctrl_pm_select_default_state(component->dev); ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream); if (ret < 0) goto pm_err; mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); ret = soc_pcm_components_open(substream); if (ret < 0) goto err; ret = snd_soc_link_startup(substream); if (ret < 0) goto err; /* startup the audio subsystem */ for_each_rtd_dais(rtd, i, dai) { ret = snd_soc_dai_startup(dai, substream); if (ret < 0) goto err; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dai->tx_mask = 0; else dai->rx_mask = 0; } /* Dynamic PCM DAI links compat checks use dynamic capabilities */ if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) goto dynamic; /* Check that the codec and cpu DAIs are compatible */ soc_pcm_init_runtime_hw(substream); soc_pcm_update_symmetry(substream); ret = soc_hw_sanity_check(substream); if (ret < 0) goto err; soc_pcm_apply_msb(substream); /* Symmetry only applies if we&#39;ve already got an active stream. */ for_each_rtd_dais(rtd, i, dai) { ret = soc_pcm_apply_symmetry(substream, dai); if (ret != 0) goto err; } dynamic: snd_soc_runtime_activate(rtd, substream->stream); ret = 0; err: mutex_unlock(&rtd->card->pcm_mutex); pm_err: if (ret < 0) { soc_pcm_clean(substream, 1); dev_err(rtd->dev, "%s() failed (%d)", __func__, ret); } return ret; }
最新发布
11-04
这段代码是 Linux ALSA SoC 子系统中 `soc_pcm.c` 文件的一个核心函数 `soc_pcm_open()`,用于在音频流(播放或录音)开始前初始化 PCM 子系统。以下是详细解析: --- ### 📌 函数功能概述: `soc_pcm_open()` 是 ALSA PCM 子系统中用于打开音频流的回调函数。它负责初始化与音频流相关的组件(如 CPU DAI、Codec 等),并确保音频路径和硬件配置正确。 --- ### 🔍 代码逐行解析: ```c static int soc_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; struct snd_soc_dai *dai; int i, ret = 0; ``` - **获取运行时结构体 `rtd`**:通过 `asoc_substream_to_rtd()` 从 `substream` 获取 `snd_soc_pcm_runtime`,该结构包含音频链路的上下文信息。 - 定义一些变量用于遍历组件和 DAI。 ```c for_each_rtd_components(rtd, i, component) pinctrl_pm_select_default_state(component->dev); ``` - **设置组件的默认引脚状态**:为每个组件选择默认的 pin 控制状态,用于音频初始化。 ```c ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream); if (ret < 0) goto pm_err; ``` - **电源管理**:调用运行时电源管理接口,确保设备处于运行状态;失败则跳转到错误处理。 ```c mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); ``` - **加锁**:防止并发访问 PCM 资源。 ```c ret = soc_pcm_components_open(substream); if (ret < 0) goto err; ``` - **初始化组件**:调用每个组件的 `open()` 接口,执行特定于组件的初始化操作。 ```c ret = snd_soc_link_startup(substream); if (ret < 0) goto err; ``` - **链接初始化**:处理 DAI 链接的启动逻辑,例如设置 DAI 的格式等。 ```c for_each_rtd_dais(rtd, i, dai) { ret = snd_soc_dai_startup(dai, substream); if (ret < 0) goto err; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dai->tx_mask = 0; else dai->rx_mask = 0; } ``` - **DAI 启动**:遍历所有 DAI(Digital Audio Interface),调用其 `startup()` 方法进行初始化。 - 清除 DAI 的发送或接收位掩码(根据当前流方向)。 ```c if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) goto dynamic; ``` - **动态链接或非 PCM 链接**:跳过后续硬件配置。 ```c soc_pcm_init_runtime_hw(substream); soc_pcm_update_symmetry(substream); ``` - **初始化硬件参数**:根据 DAI 的能力设置 PCM 硬件能力。 - **更新对称性**:确保播放和录音的硬件参数匹配(如采样率、通道数等)。 ```c ret = soc_hw_sanity_check(substream); if (ret < 0) goto err; ``` - **硬件检查**:验证当前硬件配置是否合理,失败则跳转错误。 ```c soc_pcm_apply_msb(substream); ``` - **应用 MSB(Most Significant Bit)设置**:用于格式对齐。 ```c for_each_rtd_dais(rtd, i, dai) { ret = soc_pcm_apply_symmetry(substream, dai); if (ret != 0) goto err; } ``` - **再次应用对称性**:确保 DAI 的对称性配置正确。 ```c dynamic: snd_soc_runtime_activate(rtd, substream->stream); ret = 0; ``` - **激活运行时**:标记该流已激活。 ```c err: mutex_unlock(&rtd->card->pcm_mutex); pm_err: if (ret < 0) { soc_pcm_clean(substream, 1); dev_err(rtd->dev, "%s() failed (%d)", __func__, ret); } ``` - **错误处理与清理**:释放锁,清理资源,并输出错误信息。 ```c return ret; } ``` - 返回结果,0 表示成功,负数表示错误。 --- ### 🧠 总结: `soc_pcm_open()` 是 ALSA SoC 子系统中 PCM 流打开阶段的核心函数。它负责协调音频链路中多个组件(如 CPU DAI、Codec)的初始化工作,并确保音频路径和硬件配置正确无误。 --- ### ✅ 示例场景: 当用户通过 `aplay` 播放音频时,系统会调用这个函数来初始化音频设备,为后续的音频数据传输做好准备。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值