【发布时间】:2018-01-17 14:46:27
【问题描述】:
我继承了一个使用snd_pcm_readn() 对音频进行采样的应用程序。
确定与检索到的每个样本相关联的时间戳最可靠的方法是什么?
大概会有某种缓冲发生在 ALSA 或采集卡本身意味着 clock_gettime() 可能有一个变量错误 (尤其是因为这是一个多线程应用程序)。
在我看来应该是这样的:
if((alsa_result = snd_pcm_readn(card->capture_handle,
card->capture_buff,
card->buffer_size)) == 0)
{
snd_pcm_status_t pcm_status;
snd_timestamp_t snd_timestamp; //actually a struct timeval under the hood
if (snd_pcm_status(card->capture_handle, &pcm_status) == 0)
{
snd_pcm_status_get_tstamp(&pcm_status, &snd_timestamp);
// translate timeval into milliseconds
const uint64_t millis = (snd_timestamp.tv_sec * (uint64_t)1000) + (snd_timestamp.tv_usec / 1000);
}
}
但是,snd_timestamp 指的是什么时间?它是检索到的第一个样本还是最后一个样本,我们是否需要考虑自 snd_pcm_readn() 返回以来可能已捕获的样本?
我发现的 ALSA 文档在细节上是粗略的。如果未启用时间戳,使用snd_pcm_status_get_tstamp() 是否有效(例如,请参阅https://www.kernel.org/doc/html/v4.10/sound/designs/timestamping.html)。
参考优秀(最好是在线)ALSA 相关阅读材料的奖励积分。
与此相关,我目前无法编译上面的代码:
error: storage size of ‘pcm_status’ isn’t known
snd_pcm_status_t pcm_status;
我有#include <alsa/pcm.h> 和:
>grep -r _snd_pcm_status /usr/include/
/usr/include/alsa/pcm.h: typedef struct _snd_pcm_status snd_pcm_status_t;
但在明显的位置似乎没有_snd_pcm_status 的定义。
2017 年 8 月 11 日更新
正如所指出的,snd_pcm_status_t 是不透明的,必须由 ALSA 分配。
我仍然无法让 snd_pcm_status_get_tstamp 返回“正确”的时间戳:
//setup code...
if ((alsa_error = snd_pcm_sw_params_malloc(&sw_params)) < 0)
{
//handle error
}
if ((alsa_error = snd_pcm_sw_params_set_tstamp_mode(card->capture_handle, sw_params, SND_PCM_TSTAMP_ENABLE)) < 0)
{
//handle error
}
if ((alsa_error = snd_pcm_sw_params_set_tstamp_mode(card->capture_handle, sw_params, SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY)) < 0)
{
//handle error
}
snd_pcm_sw_params_free(sw_params);
// later on
if((alsa_result = snd_pcm_readn(card->capture_handle,
card->capture_buff,
card->buffer_size)) == 0)
{
time_t timeStamp = 0;
snd_timestamp_t snd_timestamp = {0,0}; //actually a struct timeval
if (snd_pcm_status(card->capture_handle, card->status) == 0)
{
snd_pcm_status_get_tstamp(card->status, &snd_timestamp);
timeStamp = snd_timestamp.tv_sec;
}
}
timeStamp 似乎是单调时钟,而不是像我想的那样获取一天中的时间(ALSA 文档没有具体说明)。
我刚收到“1970-01-11T08:33:42:894822” 符合:
cat /proc/timer_list |现在 grep 现在在 894831565155289 纳秒
我只能得到now - monotonic 的基本时间,但对于声称是 SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY 的时钟来说,这似乎是错误的。所以我得出结论,我的设置代码或理解有问题。
那是我刚刚 readn() 的样本的时间戳吗?
【问题讨论】: