static int choose_rate(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, unsigned int best_rate)
{
struct snd_interval *it;
struct snd_pcm_hw_params *save;
unsigned int rate, prev;
save = kmalloc(sizeof(*save), GFP_KERNEL);
if (save == NULL)
return -ENOMEM;
*save = *params; // 预先保存一份params的拷贝到save,然后对params进行尝试性修改,如果修改成功,那么
// 将直接返回成功数据,如果万一失败,那么使用*save恢复params到原始数据.
// 使用save中的it,下面将对it进行只读操作[luther.gliethttp]
// 在snd_pcm_oss_change_params==>_snd_pcm_hw_params_any中
// 已经将所有it范围定义在了[0, UINT_MAX]区间[luther.gliethttp]
it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE);
/* try multiples of the best rate */
rate = best_rate; // 这里以采样率8000为例
for (;;) {
// 如果rate比it->max都大,那么没有可以选择的了
// openmin和openmax表示开集,如果2个全为1,那么就表示,range范围为(min,max)
// openmin为1,openmax为0,range范围为(min,max]
// integer等于1,表示it不是一个范围区间,而是一个固定的interger整型值
if (it->max < rate || (it->max == rate && it->openmax))
break;
// 执行到这里表示rate小于it->max
if (it->min < rate || (it->min == rate && !it->openmin)) {
// 表示rate >= min,所以可以进行采样率数值最佳匹配尝试[luther.gliethttp]
int ret;
// 设置params的SNDRV_PCM_HW_PARAM_RATE参数为integer整型数值rate,(dir=0表示为integer整型)
ret = snd_pcm_hw_param_set(substream, params,
SNDRV_PCM_HW_PARAM_RATE,
rate, 0);
if (ret == (int)rate) { // 是否成功设置为rate
kfree(save);
return rate;
}
*params = *save; // 如果没有将params成功设置为rate整型值,那么说明rate设置失败
} // 数据回滚,恢复*save中的内容到*params[luther.gliethttp]
prev = rate;
rate += best_rate; // 将rate*n,即再次尝试n倍rate的速率[luther.gliethttp]
if (rate <= prev) // 整型溢出成为负数了,那么这是一定要强行退出的.
break;
}
/* not found, use the nearest rate */
// ok, 那就没有办法了,就连n倍rate的数值都不能设置,那么进行如下近似计算[我感觉不会发生下面的情况]
kfree(save);
return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
《浅析alsa声卡驱动snd_pcm_hw_param_near函数》}
阅读(1005) | 评论(0) | 转发(0) |