static inline void
copy_area(const struct snd_pcm_plugin_channel *src_channel,
struct snd_pcm_plugin_channel *dst_channel,
snd_pcm_uframes_t frames, int format)
{
dst_channel->enabled = 1;
snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
}
int
snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
size_t samples, int format)
{
/* FIXME: sub byte resolution and odd dst_offset */
char *src, *dst;
int width;
int src_step, dst_step;
src = src_area->addr + (src_area->first + src_area->step * src_offset) / 8;
if (!src_area->addr) // 如果没有src地址,那么填充静音数据[luther.gliethttp]
return snd_pcm_area_silence(dst_area, dst_offset, samples, format);
《浅析alsa声卡驱动snd_pcm_area_silence函数》 dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
if (!dst_area->addr)
return 0;
width = snd_pcm_format_physical_width(format); // width为声音数据存储空间占用bit数
if (width <= 0)
return -EINVAL;
if (src_area->step == (unsigned int) width &&
dst_area->step == (unsigned int) width && width >= 8) {
size_t bytes = samples * width / 8; // src和step的step完全一致,同时大小都为8的倍数
memcpy(dst, src, bytes);
return 0;
}
src_step = src_area->step / 8; // src_area->step = 4或者32[luther.gliethttp]
dst_step = dst_area->step / 8; // dst_area->step = 4或者24[luther.gliethttp]
if (width == 4) {
/* Ima ADPCM */
int srcbit = src_area->first % 8;
int srcbit_step = src_area->step % 8; // src_area->step = 4;所以srcbit_step等于4
int dstbit = dst_area->first % 8;
int dstbit_step = dst_area->step % 8; // dst_area->step = 4;所以dstbit_step等于4
while (samples-- > 0) {
unsigned char srcval;
if (srcbit)
srcval = *src & 0x0f; // srcbit等于4,那么低4bits为有效位[luther.gliethttp]
else
srcval = (*src & 0xf0) >> 4; // srcbit等于0,那么高4bits为有效位[luther.gliethttp]
if (dstbit) // dstbit等于4,那么低4bits为有效位[luther.gliethttp]
*dst = (*dst & 0xf0) | srcval;
else
*dst = (*dst & 0x0f) | (srcval << 4); // dstbit等于0,那么高4bits为有效位[luther.gliethttp]
src += src_step; // 因为width=4,所以src_step等于0
srcbit += srcbit_step; // srcbit_step等于4,所以会出现0+4=4或者4+4=8
if (srcbit == 8) {
src++; // 指向下一个字节
srcbit = 0; // 重新从0bit开始[luther.gliethttp]
}
dst += dst_step; // 重复上面src的操作[luther.gliethttp]
dstbit += dstbit_step;
if (dstbit == 8) {
dst++;
dstbit = 0;
}
}
} else {
width /= 8; // width等于32, 而dst_area->step等于24的情况[luther.gliethttp]
while (samples-- > 0) {
memcpy(dst, src, width); // 拷贝4个字节[这里多拷贝的1个字节,应该不会出现最后1次拷贝内存越界问题,因为这是alsa]
src += src_step; // 步进src_step等于32/8=4字节
dst += dst_step; // 步进dst_step等于24/8=3字节
}
}
return 0;
}
阅读(315) | 评论(0) | 转发(0) |