snd_pcm_oss_change_params
==> snd_pcm_plug_alloc
==> snd_pcm_plugin_alloc
static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
{
struct snd_pcm_plugin_format *format;
ssize_t width;
size_t size;
unsigned int channel;
struct snd_pcm_plugin_channel *c;
if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) {
format = &plugin->src_format;
} else {
format = &plugin->dst_format;
}
if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width;
size = frames * format->channels * width; // frames次完全采样,所需存储空间总大小[luther.gliethttp]
if (snd_BUG_ON(size % 8))
return -ENXIO;
size /= 8;
if (plugin->buf_frames < frames) { // 如果plugin插件预先申请的采样次数buf_frames小于这里指定的采样
vfree(plugin->buf); // 次数frames,那么释放plugin插件预先申请音频数据缓冲区
plugin->buf = vmalloc(size); // 重新申请size大小的音频缓冲区
plugin->buf_frames = frames; // 当前音频缓冲区可以填充frames次采样数据[luther.gliethttp]
}
if (!plugin->buf) {
plugin->buf_frames = 0;
return -ENOMEM;
}
c = plugin->buf_channels;
if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
// 读写交叉模式
for (channel = 0; channel < format->channels; channel++, c++) {
c->frames = frames; // 该声道数据存储空间所能存储的最大采样次数
c->enabled = 1;
c->wanted = 0;
c->area.addr = plugin->buf; // 该模式下,所有声道的的数据存储地址都为起始地址
// 具体存储流成为addr + first存入本声道数据,然后first += step;这样first指向本声道
// 下一次采样数据存储地址[luther.gliethttp]
c->area.first = channel * width; // 数据存放的收地址
c->area.step = format->channels * width; // 步进大小,很明显是为了first += step;完成下一个存储地址的跳转.
}
} else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
// 读写非交叉模式
if (snd_BUG_ON(size % format->channels))
return -EINVAL;
size /= format->channels; // size等于一个声道进行frames次采样后所需存储空间大小
for (channel = 0; channel < format->channels; channel++, c++) {
c->frames = frames; // 该声道数据存储空间所能存储的最大采样次数
c->enabled = 1;
c->wanted = 0;
c->area.addr = plugin->buf + (channel * size); // 很明显这样设置之后,允许一个声道从
c->area.first = 0; // first开始之后的连续size个字节存储空间都归该声道使用
c->area.step = width;// 因为一个声道采样frames次,就会产生size大小的音频数据[luther.gliethttp]
}
} else
return -EINVAL;
return 0;
}
阅读(1026) | 评论(0) | 转发(0) |