使用C语言实现卷积运算及移动平均滤波器

文章目录

  • 课题目标
  • 一、首先实现功率为1的白噪声
  • 二、卷积运算头文件
  • 三、主函数
  • 四、结果及结论


课题目标

  1. 使用C语言和卷积运算实现N点移动平均滤波器程序。
    输入信号如下所示:
    ( 1 )      x [ n ] = s i n ( π n / 64 ) (1)\;\;x[n]=sin(\pi n/64) (1)x[n]=sin(πn/64)
    ( 2 )      x [ n ] = s i n ( π n / 64 ) + 0.2 s i n ( 10 π n / 64 ) + 0.1 s i n ( 20 π n / 64 ) (2)\;\;x[n]=sin(\pi n/64)+0.2sin(10\pi n/64)+0.1sin(20\pi n/64) (2)x[n]=sin(πn/64)+0.2sin(10πn/64)+0.1sin(20πn/64)
    ( 3 )      在 x [ n ] = s i n ( π n / 64 ) 中 添 加 功 率 为 0.2 的 噪 声 (3)\;\;在x[n]=sin(\pi n/64)中添加功率为0.2的噪声 (3)x[n]=sin(πn/64)0.2
    N点分别设定为6,12,18,画出波形图。

一、首先实现功率为1的白噪声

白噪声通过一个头文件和源文件实现,代码如下:
rnd.h

#ifndef ___RND_H
#define ___RND_H

class UnitRand{
protected:
	unsigned int	RandKernel;		
	double			RandMax;		
public:
	void		ChangeKernel(unsigned int);		
	double		Urand(void);					
	UnitRand();							
};
class NormRand : public UnitRand{
private:
	int			Norm_f;
	double		Norm_k,
				Norm_q;
public:
	double		Nrand(void);			
	NormRand();							
};
#endif

rnd.cpp

#include "rnd.h"
#include 
#include 
#include 
#include 

#define DOUBLE_PI (atan(1.0) * 4.0)

UnitRand::UnitRand(){
	RandKernel = (unsigned int)time(NULL);
	RandMax = (double)UINT_MAX+1.0;				
}

void UnitRand::ChangeKernel(unsigned int NewKernel){
	RandKernel = NewKernel;
}

double UnitRand::Urand(void){
	RandKernel *= 0x5D21DB81U;	
	RandKernel++;				
	return((double)RandKernel/RandMax);
}

NormRand::NormRand() : UnitRand(){
	Norm_f = 0;
}

double NormRand::Nrand(void){
	if( Norm_f ){
		Norm_f = 0;
		return( Norm_k*sin(Norm_q) );
	}
	Norm_f = 1;
	Norm_k = sqrt(-2.0*log(1.0-Urand()));
	Norm_q = 2*DOUBLE_PI*Urand();
	return( Norm_k*cos(Norm_q) );
}

main.cpp

#include
#include
#include
#include

int main()
{
	NormRand sig;
	sig.ChangeKernel(2);
	int x = 0, i = 0;
	for (x = 0; x < 256; ++x)
	{
		double a = sig.Nrand();
		printf("%f\n", a);
	}
}

结果使用matlab画图:
使用C语言实现卷积运算及移动平均滤波器_第1张图片

t1x=xlsread('noise.xlsx');
t1 = linspace(0,256,256);
y1=t1x(:,1);
 plot(t1,y1);
xlabel('Time');
ylabel('Power');
legend('noise');
set(0,'defaultfigurecolor','w')

二、卷积运算头文件

卷积运算的设计思路有两种,如图例题所示,以下头文件中代码为第一种设计思路。

conv.h

#include
#include
#define N 18

void conv(double* input1, double* input2, double* output, int mm, int nn)
{
	for (int i = 0; i < mm + nn - 1; i++)
	{
		output[i] = 0;
	}
	for (int i = 0; i < mm; i++) 
	{
		for (int j = 0; j < nn; j++) 
		{
			output[i + j] += input1[i] * input2[j];
		}
	}
	for (int i = 0; i <256; i++) 
	{
		printf("%lf\n", output[i]/N);
	}
}

三、主函数

main.cpp

#include
#include
#include
#include
#include"D:\DOCUMENT\T1\Project1\conv.h"

#define N 18
double score[256];
double score2[N] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
double score3[256];

int main()
{
	NormRand sig;
	sig.ChangeKernel(2);
	int x = 0, i = 0;	
	double y = 0;
	for (x = 0; x < 256; ++x)
	{
		double a = sig.Nrand();
		//y = sin((3.14159 * x) / 64);
		//y = sin((3.14159 * x) / 64)+ 0.2*sin(10*(3.14159 * x) / 64) + 0.1 * sin(20 * (3.14159 * x) / 64);
		y = sin((3.14159 * x) / 64)+0.2*a;
		//printf("%f\n", y);
		score[x] = y;
	}
	conv(score, score2, score3, 256, N);
}

四、结果及结论

输出结果如下图所示,可以看到N值越多,滤波效果越好,但由于卷积造成的延迟问题也越严重。

使用C语言实现卷积运算及移动平均滤波器_第2张图片
使用C语言实现卷积运算及移动平均滤波器_第3张图片

使用C语言实现卷积运算及移动平均滤波器_第4张图片

t1x=xlsread('1.xlsx');
t1 = linspace(0,256,256);
y1=t1x(:,1);
t2x=xlsread('2.xlsx');
t2 = linspace(0,256,256);
y2=t2x(:,1);
t3x=xlsread('3.xlsx');
t3 = linspace(0,256,256);
y3=t3x(:,1);
t4x=xlsread('4.xlsx');
t4 = linspace(0,256,256);
y4=t4x(:,1);

 plot(t1,y1);
 hold on
 plot(t2,y2);
 hold on
 plot(t3,y3);
 hold on
 plot(t4,y4);
xlabel('Time');
ylabel('Power');
legend('original','N=6','N=12','N=18');
set(0,'defaultfigurecolor','w')

你可能感兴趣的:(dsp,算法,c语言)