matlab怎么把音频变成信号_matlab音频信号处理

本文介绍了如何使用MATLAB处理音频信号,从读取音频文件到绘制信号图,理解频率、时间的关系。讨论了分帧的概念、帧移的意义,并通过enframe函数进行分帧处理。接着探讨了如何计算自相关系数,以及在MATLAB中实现LPC预测信号和计算预测增益的过程。
摘要由CSDN通过智能技术生成

首先来认识一下什么是音频信号

通过matlab我们可以直接读入一个音频文件,同时直接绘图

但是此时的横坐标和纵坐标是什么呢?

>> [y,fs] = audioread('5num.wav');

>> plot(y)

不断放大信号:

得到了这样一幅图

image

这时候纵坐标我们可以理解成幅度,但是横坐标其实什么也不是

或者说就是一系列点而已,我们可以对这些点进行一定的组合,比如每160个点作为一组,这就是分帧

那频率呢?

matlab在读取一个音频的时候还会返回一个频率呀,这个频率,也就是那个fs,到底是干嘛的,有什么意义呢?

不妨来计算一下:

我的这段音频是29s,

>> length(y)/fs

ans =

29.4400

此时用点的个数除以频率fs,得到的就是时间!

这样想,频率的物理意义就是一秒钟振动的次数,8khz就是一秒钟要震动8000次,一个点震动一次,那么235520个点就要震动29.4400s!

同时可以知道这段音频是16位量化的

可是我们老是说量化量化,量化究竟代表什么含义呢?

其实就理解成每一个点用16个bit来表示

那么,235520个点,每一个点都是16位的,相当于一个点就是2byte

那么就是 235520*2 字节

等价于460KB

查看文件大小

正好是460KB!!

现在理解这几个参数的含义了吧

于是上面那幅图我们需要改进一下

>>t = (0:length(y)-1)/fs;

>> plot(t,y);

>> xlabel('时间(.sec)')

>> ylabel('幅度')

这样就能得到每一个时刻对应的幅度了

分帧?

到底什么是分帧呢?

首先需要确定分帧的长度:

比如采样率是11025

语音信号每20ms分成一段

怎么想,一秒钟有11025个点震动,那么20ms内就是大概220个点了,于是帧长为220,帧移默认就是一半110

问:为什么分帧?

答:语音信号是瞬时变化的,但在10~20ms内是相对稳定的,即在一小段内是相对稳定的,分帧就是将语音分成一段一段的。

问:问什么要有帧移呢?

答:帧移后的每一帧信号都有上一帧的成分,防止两帧之间的不连续。语音信号虽然短时可以认为平稳,但是由于人说话并不是间断的,每帧之间都是相关的,加上帧移可以更好地与实际的语音相接近。

如果采样率都是8000hz,并且20ms为一帧

相当于160个点为一个帧

但是调用enframe函数返回的结果又是什么呢?

5885*160的矩阵

每一行,有160列

每一列,有5885行

你想啊,我是每160个点为一个帧,那么总共有多少个帧呢?

这个不难算

那么我可以单独取出其中的一个帧来看

a = X(2000,:);

plot(a)

当然这里只是知道有160个点,但是对应的时间段却是不知道的

也就是说每一行其实就是一个帧的数据了

之所以这张图有点奇怪

横坐标代表第多少帧,纵坐标代表振幅

因为有很多根曲线是重叠的

问题在于分帧之后,如何求自相关系数等

可不可以每一个帧求一次自相关系数呢?

补充一点,调用enframe函数如果不指定第三个参数那么帧之间就不会重叠的

如何求自相关系数?

首先试如何理解自相关系数

比如:

>> A = [1 2 3]

A =

1 2 3

>> xcorr(A)

ans =

3.0000 8.0000 14.0000 8.0000 3.0000

>>

这个口算应该没问题的

就是求出A的自相关系数

但是这个呢?

>> xcorr(A,4)

ans =

1 至 7 列

0 0 3.0000 8.0000 14.0000 8.0000 3.0000

8 至 9 列

0 0

是不是可以理解成延展了

按照规律来说是没问题的,xcorr(A,4) 相当于两个5列的向量

得到的就是2*5 - 1= 9个

解读代码

先把代码放上来吧,方便你们copy

[y,fs] = audioread('5num.wav');

N = length(y);

t = (1:N-1)/fs; %生成时间序列

win = hamming(N) %加窗

y = y.*win;

X = enframe(y,160); % 160个点为一帧,就没要重叠了

% 然后就可以查看某个帧了

%%

% 求出自相关

num_frame = length(X);

ms2 = floor(fs/500);

ms20 = floor(fs/50);

F0 = zeros(num_frame,1);

% 直接对每一帧进行循环

for i=1:num_frame

% 每一帧都可以求出自相关的系数

r = xcorr(X(i,:), 160);

r = r(floor(length(r)/2):end);

[maxi,idx]=max(r(ms2:ms20));

F0(i) = fs/(ms2+idx-1);

end

figure(1);

plot(F0); %横坐标代表帧

xlabel('帧')

ylabel('基音频率')

% 经过探测我读0时候的基音位于第210帧

%% 选出第210帧的数据

figure(2)

y210 = X(211,:);

subplot(311);

plot(y210);

xlabel('点');

ylabel('振幅');

title('210帧原始信号')

ai = lpc(y210, 10);

est_x=filter([0 -ai(2:end)],1,y210);%估计信号

subplot(312);

plot(est_x);

xlabel('点');

ylabel('振幅');

title('210帧估计信号');

err = y210-est_x;

subplot(313);

plot(err);

xlabel('点');

ylabel('振幅');

title('预测误差');

%%

% 求预测增益

En=zeros(1,160);

for i=1:160

u=err(i);%取出一样点

u2=u.*u;%求出能量

En(i)=sum(u2);%对每一样点累加求和

end

%计算原始能量

En1=zeros(1,160);

for i=1:160

u=y210(i);%取出一样点

u2=u.*u;%求出能量

En1(i)=sum(u2);%对每一样点累加求和

end

CA=zeros(1,160);

for i=1:160

en1=En1(i);%取出一样点

en=En(i);

CA(i)=abs(en1)/abs(en);

end

figure(3);

subplot(311);plot(En1);xlabel('取样点数/个');ylabel('En');title('短时能量');title('E0');

subplot(312);plot(En);xlabel('取样点数/个');ylabel('En');title('短时能量');title('Ep');

subplot(313);plot(CA);xlabel('取样点数/个');ylabel('En');title('短时能量');title('预测增益');

1. 加窗分帧

[y,fs] = audioread('5num.wav');

N = length(y);

t = (1:N-1)/fs; %生成时间序列

win = hamming(N) %加窗

y = y.*win;

X = enframe(y,160); % 160个点为一帧,就没要重叠了

其实加窗的过程也不是很难理解,就是生成一个函数然后去乘就好了

然后通过enframe函数进行分帧处理

返回的是一个矩阵,行数代表了帧数,列数代表了每一帧有多少个点

2. 求自相关

num_frame = length(X);

ms2 = floor(fs/500);

ms20 = floor(fs/50);

F0 = zeros(num_frame,1);

% 直接对每一帧进行循环

for i=1:num_frame

% 每一帧都可以求出自相关的系数

r = xcorr(X(i,:), 160);

r = r(floor(length(r)/2):end);

[maxi,idx]=max(r(ms2:ms20));

F0(i) = fs/(ms2+idx-1);

end

这个过程也不是很难理解

得到的图形是这样子的

横坐标就是每一个帧,纵坐标代表对应的基音频率

其实这个图确实有点奇怪,因为它是倒过来的

我后来仔细想了想,周围没有声音的时候,基音频率反而是最大的

然后又去翻书,发现人的声音基音频率大概也就是200~500hz左右,而且男声本来就低,所以这个图显然是没问题的

而且我总共只读了5个音,0 1 2 3 4

基本正确地反映出来了

然后通过肉眼观察,嗯,我读0的那个帧就是210帧了

3. 通过LPC预测信号,同时计算增益

预测增益的方法就是LPC

增益系数我暂时不太清楚怎么求,就直接抄同学的了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值