cpp
/** PCM state */
typedef enum _snd_pcm_state {
/** Open */
SND_PCM_STATE_OPEN = 0,
/** Setup installed */
SND_PCM_STATE_SETUP,
/** Ready to start */
SND_PCM_STATE_PREPARED,
/** Running */
SND_PCM_STATE_RUNNING,
/** Stopped: underrun (playback) or overrun (capture) detected */
SND_PCM_STATE_XRUN,
/** Draining: running (playback) or stopped (capture) */
SND_PCM_STATE_DRAINING,
/** Paused */
SND_PCM_STATE_PAUSED,
/** Hardware is suspended */
SND_PCM_STATE_SUSPENDED,
/** Hardware is disconnected */
SND_PCM_STATE_DISCONNECTED,
SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED,
/** Private - used internally in the library - do not use*/
SND_PCM_STATE_PRIVATE1 = 1024
} snd_pcm_state_t;
1. SND_PCM_STATE_OPEN
- 含义:PCM 设备已打开,但尚未配置任何硬件参数(如采样率、格式等)。
- 触发场景 :调用
snd_pcm_open()
打开设备后的初始状态。
2. SND_PCM_STATE_SETUP
- 含义 :硬件参数已安装(通过
snd_pcm_hw_params()
设置),但尚未准备好传输数据。 - 触发场景 :调用
snd_pcm_hw_params()
成功配置参数后进入此状态。
3. SND_PCM_STATE_PREPARED
- 含义:设备已准备好开始传输数据(如播放或录制),但尚未开始运行。
- 触发场景 :调用
snd_pcm_prepare()
后进入此状态,此时可以安全地启动数据传输。
4. SND_PCM_STATE_RUNNING
- 含义:设备正在活跃地处理数据(例如正在播放音频或录制输入)。
- 触发场景 :调用
snd_pcm_start()
后,设备开始运行。
5. SND_PCM_STATE_XRUN
- 含义 :发生了 underrun(播放时缓冲区数据不足) 或 overrun(录制时缓冲区已满),导致设备停止。
- 触发场景 :
- 播放场景:应用程序未及时填充数据,导致缓冲区耗尽。
- 录制场景:应用程序未及时读取数据,导致缓冲区溢出。
- 处理方式 :需调用
snd_pcm_prepare()
或snd_pcm_recover()
恢复设备。
6. SND_PCM_STATE_DRAINING
- 含义:设备正在排空缓冲区中剩余的数据(仅适用于播放模式)。
- 触发场景 :调用
snd_pcm_drain()
后,设备停止新数据写入,但会继续播放缓冲区中的剩余数据。
7. SND_PCM_STATE_PAUSED
- 含义:设备被显式暂停(例如用户手动暂停播放)。
- 触发场景 :调用
snd_pcm_pause()
并设置暂停标志为1
。
8. SND_PCM_STATE_SUSPENDED
- 含义:硬件因系统事件(如进入省电模式)被挂起。
- 触发场景:系统电源管理事件(如休眠)导致设备暂停。
9. SND_PCM_STATE_DISCONNECTED
- 含义:物理设备已断开连接(例如 USB 音频设备被拔出)。
- 触发场景:硬件被物理移除或断开。
10. SND_PCM_STATE_PRIVATE1
- 含义:ALSA 库内部使用的私有状态,开发者无需关注。
- 用途:用于 ALSA 内部实现,用户代码中不应依赖此状态。
状态转换示意图
OPEN → SETUP → PREPARED → RUNNING → (XRUN/DRAINING/PAUSED/SUSPENDED) → ... → DISCONNECTED
常见问题
Q1: 如何检测并处理 XRUN
状态?
-
调用
snd_pcm_state()
检查状态,若为XRUN
,需恢复设备:if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN) { snd_pcm_prepare(pcm_handle); // 或 snd_pcm_recover() }
Q2: DRAINING
和 PAUSED
的区别?
- DRAINING:设备正在播放剩余数据(仅播放模式)。
- PAUSED:设备完全停止,不会继续处理数据,需显式恢复。
Q3: 如何强制停止设备?
- 调用
snd_pcm_drop()
立即停止设备并丢弃缓冲区数据,状态回到SETUP
。