static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
const struct snd_pcm_plugin_channel *src_channels,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
int nsrcs, ndsts, dst;
struct snd_pcm_plugin_channel *dvp;
int format;
if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
return -ENXIO;
if (frames == 0)
return 0;
nsrcs = plugin->src_format.channels; // src声道数目
ndsts = plugin->dst_format.channels; // dst声道数目
format = plugin->dst_format.format;
dvp = dst_channels;
if (nsrcs <= 1) {
// src音频数据源只有1个声道
/* expand to all channels */
for (dst = 0; dst < ndsts; ++dst) {
// 将1个声道的数据分别填充到ndsts个放音声道数据缓冲区中[luther.gliethttp]
// frames为the number of samples采样的样点个数
copy_area(src_channels, dvp, frames, format);
《浅析alsa声卡驱动copy_area和snd_pcm_area_copy函数》 dvp++;
}
return frames;
}
for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) { // dst来计数, 直到ndsts和nsrcs中的最小者[luther.gliethttp]
copy_area(src_channels, dvp, frames, format); // 过程就和上面雷同了[luther.gliethttp]
dvp++; // 移动到dst的下一个chanel
src_channels++; // 移动到src的下一个chanel[luther.gliethttp]
}
if (dst < ndsts) // 如果nsrcs小于ndsts,那么还有ndsts - dst个chanels没有填充数据,
zero_areas(dvp, ndsts - dst, frames, format); // 见后
return frames;
}
static void
zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
snd_pcm_uframes_t frames, int format)
{
int dst = 0;
for (; dst < ndsts; ++dst) {
if (dvp->wanted) // 如果dst的该chanel确实需要数据,又因为route_transfer函数中src的chanel数目小于
// dst的chanel数目,所以这里就必须给它添上静音数据[luther.gliethttp]
snd_pcm_area_silence(&dvp->area, 0, frames, format);
dvp->enabled = 0;
dvp++; // 移动到dst的下一个chanel[luther.gliethttp]
}
}
阅读(2054) | 评论(0) | 转发(3) |