电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx

上传人:b****6 文档编号:16262424 上传时间:2023-07-12 格式:DOCX 页数:19 大小:34.76KB
下载 相关 举报
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第1页
第1页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第2页
第2页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第3页
第3页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第4页
第4页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第5页
第5页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第6页
第6页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第7页
第7页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第8页
第8页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第9页
第9页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第10页
第10页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第11页
第11页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第12页
第12页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第13页
第13页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第14页
第14页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第15页
第15页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第16页
第16页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第17页
第17页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第18页
第18页 / 共19页
电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx

《电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx》由会员分享,可在线阅读,更多相关《电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx(19页珍藏版)》请在冰点文库上搜索。

电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编.docx

电子科技大学数字信号处理DSP课程设计钢琴音符识别之欧阳育创编

2014级数字信号处理课程设计报告

时间:

2021.02.04

创作:

欧阳育

题目:

钢琴音符识别

姓名:

邱晨曦

学号:

2014010909008

答辩时间:

2016/12/9

一.题目要求:

(1)播放和记录一段钢琴音乐中的音符;

(2)记录到音符以后,找到音符所对应的现代标准钢琴的钢琴键,并分析结果。

二.课程设计思路:

(1)涉及到的知识点:

快速傅里叶变换、钢琴音频信号的时域和频域的特性、能熵比的概念、频率校正、频率与音符的转换关系。

(2)方案分析:

A.预处理部分:

1.直接用audioread函数读出来的原始数据。

优点:

准确率较高;

缺点:

数据量较大,采样频率为44kHz,远大于奈奎斯特采样率。

2.以11kHz的采样率重新采样,并转换为单声道。

优点:

数据量小了很多,易于处理;

缺点:

牺牲了部分的准确率,但对于音符的判断影响可以忽略。

B.端点检测算法:

<1>.双门限法:

1.计算短时能量(高门限)和过零率(低门限);

2.选取一个较高的门限

,语音信号的能量包络大部分都在此门限之上,进行一次初判,语音起止点位于该门限与短时能量包络交点所对应的时间间隔之外;

3.根据噪声能量,确定一个较低的门限

,并从初判起点往左,从初判终点往右搜索,分别找到能零比曲线第一次与门限

相交的两个点,两点之间段就是用双门限方法所判定的语音段;

4.以短时平均过零率为准,从低门限点往左右搜索,找到短时平均过零率低于某阈值的两点,为语音的起止点;

图1:

双门限法示意图

说明:

算法中的阀值是根据实验过程调节的。

该算法在实际应用的过程中发现:

在语音信号频率分布较为集中的时候,端点检测出来的结果比较准确,但当语音信号频率分布比较分散的时候,很难通过控制固定的阀值来检测到每个音符;

<2>.自相关法:

由于两种信号的自相关函数存在极大的差异,可以利用这种差别来提取语音端点。

根据噪声的情况,设置两个阈值

,当相关函数最大值大于

时,便判定是语音;当相关函数最大值大于或小于

时,则判定为语音信号的端点。

该算法同样存在当语音信号频率分布较广的时候,阀值比较难控制的问题。

<3>.基于谱熵的端点检测:

基于谱熵语音端点检测方法是通过检测谱的平坦程度,来进行语音端点检测的,为了更好进行语音端点检测,采用语音信号的短时功率谱构造语音信息谱熵,从而对语音段和噪声段进行区分。

检测思路:

1.对语音信号进行分帧加窗;

2.计算每一帧的谱能量;

3.计算出每一帧中每个样本点的概率密度函数

4.计算出每一帧的谱熵值

(由信息论知识知道,熵值在自变量服从均匀分布的时候,熵值达到最大值,所以噪声的熵值是比较大的,而钢琴音符的熵值是比较小的,由此区别了噪声和音符);

5.设置判决门限;

6.根据各帧的谱熵值进行端点检测。

在实验过程中发现:

依然存在当语音信号频率分布较广时,阀值不太好控制的问题。

因此对该方法进行改进,引入,能熵比的概念:

谱熵值类似于过零率,能熵比的表示为

由于噪声和信号的能熵比差别很大。

因此在能熵比的图像中,每一个“尖刺”就代表了一个特定频率的语言信号。

图2:

能熵比图中的“尖刺”

在检测过程中,依然不能通过简单的设置阀值的办法来进行端点检测,原因是语音频率分布较广时,每个音符的能熵比变化范围差别较大,如下图所示,有的“尖刺”完全在门限之上,而有的则完全在门限之下。

图3:

88阶全音的能熵比图

因此,采用检测能熵比中的“低谷点”(该点比左右两边的一定数目的点的能熵比都小)的方法。

语音信号一定位于两个低谷点之间的部分,再对低谷点进行适当的左右移动作为语音信号的起止点。

如下图所示:

图4:

标记起止点的能熵比图

(绿色为起始点,红色为截止点)

(3)设计框架和流程:

1.用audioread函数读入钢琴音乐,并用sound函数播放;

2.为了方便处理,对信号以11.025kHz的频率进行重新采样,并统一转换成单声道的信号;

3.因为语言信号可以在短时间内认为是平稳的,因此对语音信号进行分帧的处理,设置帧长320,为了减小误差,两帧之间设置重叠部分,因此帧移取80;

4.计算每一帧的能熵比;

5.找到能熵比中的“低谷点”(该点比左右两边的一定数目的点的能熵比都小);

6.如果两个低谷点之间的距离大于miniL(认为持续长度超过一定长度的为音符,最小长度miniL可自行设置)。

则低谷点右移sr(即shiftright,数值可自行调节)帧作为一段信号的起始点,将低谷点左移sl(即shiftleft,数值可自行调节)帧作为截止点[注:

采用该方法的优点是通过调节相关参数能适应多种情况,缺点是检测环境发生较大变化时,需要重新设置参数];

7.将找到的语音段转换成未分帧时对应坐标的语音段,并对每段做快速傅里叶变换;

8.找到每段快速傅里叶变换中的最大值以及最大值所对应的横坐标(fft点),将横坐标转换成相应的频率,得到的频率即为该段音符的频率;

9.利用比值法进行频率的校正,窗函数选择矩形窗;

10.根据检测到的频率确定音符,计算公式为:

为第几个按键,再通过查表得到对应音符;

11.分析结果。

三.具体设计过程:

(1)部分代码(测试部分缺省):

主函数部分:

[x,fs]=audioread('钢琴音频.WAV');

formatshort;

wlen=320;inc=80;%分帧的帧长和帧移

overlap=wlen-inc;%帧之间的重叠部分

sound(x,fs);%播放音乐

x=calsample(x,fs);%为了方便处理,重新以11025Hz的频率采样,并转换成单声道

x=x-mean(x);%消去直流分量

x=x/max(abs(x));%幅值归一化

y=Enframe(wlen,inc,x)';%分帧

fn=size(y,2);%取得帧数

time=(0:

length(x)-1)/11025;%计算时间坐标

frameTime=frame2time(fn,wlen,inc,11025);%计算各帧对应的时间坐标

sr=2;sl=13;miniL=33;%配置左右移动的帧数和要求的最短帧数

[voicesegment,vos,Ef]=get_segment(y,fn,sr,sl,miniL);%获得语音段

[real_f,ft,ax]=get_f(x,voicesegment,vos,wlen,inc);%检测频率的结果

fori=1:

length(real_f)

real_f(i)=roundn(real_f(i),-4);

end

fori=1:

length(real_f)

real_node(i)=get_node(real_f(i))

end

%**********************************绘图部分********************************

subplot211;

stem(real_f);

title('频率检测结果');xlabel('音符/个');ylabel('频率/Hz');

subplot212;

stem(real_node,'r');

title('音符检测结果');xlabel('音符/个');ylabel('对应按键');

figure

(2);

subplot211;

plot(Ef);

title('能熵比图及语音起止点');xlabel('帧数/个');ylabel('能熵比');

fori=1:

length(voicesegment)

text(voicesegment(i).begin,Ef(voicesegment(i).begin),'o','color','g')

text(voicesegment(i).end,Ef(voicesegment(i).end),'o','color','r')

end

subplot212,plot(time,x,'k');title('语音信号端点检测结果')

axis([0max(time)-11]);ylabel('幅值');

fork=1:

vos%标出有话段

nx1=voicesegment(k).begin;

nx2=voicesegment(k).end;

nxl=voicesegment(k).duration;

fprintf('%4d%4d%4d%4d\n',k,nx1,nx2,nxl);

subplot212

line([frameTime(nx1)frameTime(nx1)],[-11],'color','r','linestyle','-');

line([frameTime(nx2)frameTime(nx2)],[-11],'color','r','linestyle','--');

end

其中的用到的子函数:

1.calsample.m(调整采样率和声道)

functionsample=calsample(sampledata,FS)

temp_sample=resample(sampledata,1,FS/11025);%调整采样频率

[~,n]=size(temp_sample);

if(n==2)%转换成单声道

sample=temp_sample(:

1);

else

sample=temp_sample;

end

end

2.Enframe.m(分帧函数)

functionf=Enframe(len,inc,x)%对读入的语音进行分帧,len为帧长,

%inc为帧重叠样点数,x为输入语音数据

fh=fix(((size(x,1)-len)/inc)+1);%计算帧数

f=zeros(fh,len);%设置一个零矩阵,行为帧数,列为帧长

i=1;

n=1;

whilei<=fh%帧间循环

j=1;

whilej<=len%帧内循环

f(i,j)=x(n);

j=j+1;

n=n+1;

end

n=n-len+inc;%下一帧开始位置

i=i+1;

end

3.frame2time.m(坐标刻度转换)

functionframeTime=frame2time(frameNum,framelen,inc,fs)

frameTime=(((1:

frameNum)-1)*inc+framelen/2)/fs;%求对应的时间坐标

4.get_segment.m(端点检测,确定音符段)

function[voicesegment,vos,Ef]=get_segment(y,fn,sr,sl,miniL)

ifsize(y,2)~=fn,y=y';end%把y转换为每列数据表示一帧语音信号

wlen=size(y,1);%取得帧长

fori=1:

fn

Sp=abs(fft(y(:

i)));%FFT取幅值

Sp=Sp(1:

wlen/2+1);%只取正频率部分

Esum(i)=sum(Sp.*Sp);%计算能量值

prob=Sp/(sum(Sp));%计算概率

H(i)=-sum(prob.*log(prob+eps));%求谱熵值

end

hindex=find(H<0.1);

H(hindex)=max(H);

Ef=sqrt(1+abs(Esum./H));%计算能熵比

Ef=Ef/max(Ef);%归一化

[x1,y1]=get_max(Ef);%找到能熵比中的“高峰点”

[x2,y2]=get_min(Ef);%找到能熵比中的“低估点”

voicesegment

(1).begin=x1

(1)-8;%由于仅仅靠低谷点无法检测出第一个音符起始位置,因此将高峰点的第一个值左移8帧作为第一个音符的起始点

voicesegment

(1).end=x2

(1)-sl;%将第一个低谷点作为第一个音符的截止点

voicesegment

(1).duration=voicesegment

(1).end-voicesegment

(1).begin+1;%一个音符的持续帧数

j=1;

fork=2:

length(x2)%将找到的低谷点作为音符的起止点

ifx2(k)-x2(k-1)>=miniL%剔除持续帧长度小于miniL的音符段

j=j+1;

temp1=x2(k-1)+sr;%将低谷点右移sr个帧,作为一个音符的起始点

voicesegment(j).begin=temp1;

temp2=x2(k)-sl;%将低谷点左移sl个帧,作为一个音符的截止点

voicesegment(j).end=temp2;

voicesegment(j).duration=voicesegment(j).end-voicesegment(j).begin+1;%音符持续帧数

end

end

vos=length(voicesegment);%返回音符个数

end

5.get_max.m(找到高峰点)

function[max_x,max]=get_max(x)

l=length(x);%获得数组的长度

max=[];

max_x=[];

j=1;

fori=20:

l-15%找到“峰值点”

if(x(i)>x(i-1))&&(x(i)>x(i-2))&&(x(i)>x(i-3))&&(x(i)>x(i-4))&&(x(i)>x(i-5))...

&&(x(i)>x(i-6))&&(x(i)>x(i-7))&&(x(i)>x(i-8))&&(x(i)>x(i-9))&&(x(i)>x(i-10))...

&&(x(i)>x(i-11))&&(x(i)>x(i-12))&&(x(i)>x(i-13))&&(x(i)>x(i-14))...

&&(x(i)>x(i-15))&&(x(i)>x(i-16))&&(x(i)>x(i-17))...

&&(x(i)>x(i+1))&&(x(i)>x(i+2))&&(x(i)>x(i+3))&&(x(i)>x(i+4))&&(x(i)>x(i+5))...

&&(x(i)>x(i+6))&&(x(i)>x(i+7))&&(x(i)>x(i+8))&&(x(i)>x(i+9))&&(x(i)>x(i+10))...

&&(x(i)>x(i+11))&&(x(i)>x(i+11))&&(x(i)>x(i+12))&&(x(i)>x(i+13))&&(x(i)>x(i+14))...

&&(x(i)>x(i+15))&&(x(i)>x(i+16))...

&&(x(i)>0.1)

max_x(j)=i;%找到后赋值给返回参数

max(j)=x(i);

i=i+1;

j=j+1;

else

i=i+1;

end

end

end

6.get_min.m(找到低谷点)

function[min_x,min]=get_min(x)

l=length(x);%获得数组的长度

min=[];

min_x=[];

j=1;

fori=100:

l-10%寻找低谷点

if(x(i)

&&(x(i)

&&(x(i)

&&(x(i)

&&(x(i)

&&(x(i)

&&(x(i)

&&(x(i)

&&(x(i)

min_x(j)=i;%找到后赋值给返回值

min(j)=x(i);

i=i+1;

j=j+1;

else

i=i+1;

end

end

end

7.get_f.m(确定频率)

function[real_f,ft,ax]=get_f(x,voicesegment,vos,wlen,inc)

fori=1:

vos%横坐标转化,将起止点坐标的单位由帧转换成点

ax(i).begin=(voicesegment(i).begin-1)*inc+1;

ax(i).end=(voicesegment(i).end-1)*inc+wlen;

ax(i).duration=ax(i).end-ax(i).begin+1;

temp=x(ax(i).begin:

ax(i).end);%获得语音段

ft{i}=fft(temp);%做快速傅里叶变换,并将结果保存在元胞矩阵中

ft{i}=abs(ft{i});%将得到的fft去模值

[fm(i),fm_x(i)]=max(ft{i});%找到每个语音段对应的fft中的最大值及最大值对应的横坐标

real_f1(i)=fm_x(i)*11025./ax(i).duration;%进行频率转换,将横坐标乘以分辨率得到真实频率

real_f(i)=Specorrm(x(ax(i).begin:

ax(i).end),11025,ax(i).duration,real_f1(i)-10,real_f1(i)+10);

%利用比值法进行频率修正,窗函数选择矩形窗

end

8.Specorrm.m(频率校正)

functionZ=Specorrm(x,fs,N,nx1,nx2)

%x是被测信号,fs是采样频率N为FFT的长度,nx1和nx2被测信号频率的区间,nx2>nx1

[nx,mx]=size(x);

ifmx==1,x=x';end%转换成行矩阵

[nx,mx]=size(x);

M=fix(N/2)+mod(N,2);

xf=fft(x);

%xf=xf(1:

M)*2/N;

ddf=fs/N;%频率分辨率

n1=fix(nx1/ddf);%将频率转换成fft对应的点

n2=round(nx2/ddf);

A=abs(xf);%取fft的模值

[Amax,index]=max(A(n1:

n2));%找到fft点n1到n2之间幅值的最大值

index=index+n1-1;%移动到n1和n2中间

%比值法

%加矩形窗

indsecL=A(index-1)>A(index+1);%满足条件则为1,不满足则为0

df=indsecL.*A(index-1)./(Amax+A(index-1))-(1-indsecL).*A(index+1)./(Amax+A(index+1));

Z=(index-1-df)*ddf;%修正后的频率

end

9.get_node.m(确定音符)

functionnode=get_node(f)

node=12*log2(f/440)+49;

node=round(node);%四舍五入确定对应按键

end

(2)生成的图与数据等

端点检测结果

序号

起始帧

截止帧

持续帧数

1

40

97

58

2

112

166

55

3

181

235

55

4

250

303

54

5

318

372

55

6

387

441

55

7

456

510

55

8

525

579

55

9

594

648

55

10

663

714

52

11

729

786

58

12

801

854

54

13

869

923

55

14

938

993

56

15

1008

1051

44

16

1066

1122

57

17

1137

1176

40

18

1191

1267

77

19

1282

1337

56

20

1352

1391

40

21

1406

1475

70

22

1490

1513

24

23

1528

1588

61

24

1603

1666

64

25

1681

1730

50

26

1760

1808

49

27

1823

1873

51

28

1903

1944

42

29

1959

2017

59

30

2032

2090

59

31

2105

2136

32

32

2177

2225

49

33

2240

2278

39

34

2317

2340

24

35

2380

2429

50

对数据的分析:

真实按键

真实音符

真实频率/Hz

检测频率/Hz

对应按键

检测音符

绝对误差/Hz

相对误差

52

G♯7/A♭7

523.251

524.8973

52

G♯7/A♭7

1.6463

0.31%

53

G7

554.365

555.0437

53

G7

0.6787

0.12%

54

F♯7/G♭7

587.33

589.8768

54

F♯7/G♭7

2.5468

0.43%

55

F7

622.254

623.1585

55

F7

0.9045

0.15%

56

E7

659.255

659.7079

56

E7

0.4529

0.07%

57

D♯7/E♭7

698.456

699.2968

57

D♯7/E♭7

0.8408

0.12%

58

D7

739.989

741.8503

58

D7

1.861

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2