Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1307079
  • 博文数量: 860
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-20 19:57
个人简介

对技术执着

文章分类

全部博文(860)

文章存档

2019年(16)

2018年(12)

2015年(732)

2013年(85)

2012年(15)

我的朋友

分类: LINUX

2015-03-14 17:12:45

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;
}
阅读(606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~