卷积运算及实现

本文介绍卷积运算及实现。

1.定义

线性时不变系统的输出是输入样本与系统的冲激响应的卷积。这里假设输入样本为x(n),系统冲激响应为h(n),系统输出为y(n),则

y(n)=h(n)*x(n)=\sum_{l=0}^{\infty}h(l)x(n-l)

线性卷积计算过程包含以下4个步骤:

1)折叠,关于l=0,折叠x(l)得到x(-l)

2)移位,将x(-l)向右移动n个样本得到x(n-l)

3)相乘,对于所有l,将h(l)和x(n-l)重叠部分相乘得到h(l)x(n-l)的乘积

4)相加,将所有乘积相加得到在时刻n的输出y(n)

重复步骤2至4,计算系统在其它瞬时n的输出,注意:输入信号长度M和冲激响应长度L的卷积结果为一个长度为L+M-1的输出信号。

例:

x(0)=a_{0},x(1)=a_{1},x(3)=a_{2},x(4)=a_{3}

h(0)=b_{0},h(1)=b_{1},h(2)=b_{2}

y(0)=a_{0}b_{0}

y(1)=a_{0}b_{1}+a_{1}b_{0}

y(2)=a_{0}b_{2}+a_{1}b_{1}+a_{2}b_{0}

y(3)=a_{1}b_{2}+a_{2}b_{1}+a_{3}b_{0}

y(4)=a_{2}b_{2}+a_{3}b_{1}

y(5)=a_{3}b_{2}

这里y(n)的输出长度为4+3-1=6个数据。

2.性质

卷积运算具有如下性质:

1)交换律,x*h=h*x

2)结合律,x*(h*g)=(x*h)*g

3)分配律,h*(x+g)=h*x+h*g

4)时域卷积定理,F(g*h)=G(\omega)\cdot H(\omega),2个信号卷积的傅里叶变换是它们各自傅里叶变换的逐点乘积,即时域卷积对应于频域相乘

5)频域卷积定理,F(g\cdot h)=\frac{1}{2\pi }G(\omega)*H(\omega),2个信号逐点乘积的傅里叶变换是它们各自傅里叶变换的卷积(这里有个系数\frac{1}{2\pi }),即频域卷积对应于时域相乘

3.实现

这里基于C语言来实现。参考代码如下:

static void conv(float *pSrcA, uint32_t srcALen, float *pSrcB, uint32_t srcBLen, float *pDst);


static void conv(float *pSrcA, uint32_t srcALen, float *pSrcB, uint32_t srcBLen, float *pDst)
{
    float *pIn1 = pSrcA;        /* inputA pointer */
    float *pIn2 = pSrcB;        /* inputB pointer */
    float sum = 0;              /* Accumulator */
    uint32_t i = 0;             /* loop counter */
    uint32_t j = 0;             /* loop counter */
    
    if ((pSrcA == NULL) || (srcALen == 0) || (pSrcB == NULL) || (srcBLen == 0) || (pDst == NULL))
    {
        return ;
    }
   
    /* Loop to calculate convolution for output length number of times */
    for (i = 0U; i < ((srcALen + srcBLen) - 1U); i++)
    {
        /* Initialize sum with zero to carry out MAC operations */
        sum = 0.0f;
        
        /* Loop to perform MAC operations according to convolution equation */
        for (j = 0U; j <= i; j++)
        {
            /* Check the array limitations */
            if ((((i - j) < srcBLen) && (j < srcALen)))
            {
                /* z[i] += x[i-j] * y[j] */
                sum += pIn1[j] * pIn2[i - j];
            }
        }
        /* Store the output in the destination buffer */
        pDst[i] = sum;
    }    
}

main函数:

int main()
{
    float x[] = {1, 2, 3, 4};
    float y[] = {4, 3, 2, 1};
    float z[7] = {0};
    uint32_t i = 0;

    conv(x, 4, y, 4, z);

    for (i = 0; i < sizeof(z) / sizeof(z[0]); i++)
    {
        printf("%f ", z[i]);
    }

    printf("\r\n");

    return 0;
}

输出结果:

作为对比,在Matlab命令行下输入:

x=[1,2,3,4];
y=[4,3,2,1];
z=conv(x,y);

查看结果和用C语言实现的是一致的。

总结,本文介绍了卷积运算及实现。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值