原谅我上课走神了,,结果用了更多的时间去补偿自己上课浪费的时间。。。
以后课前一定做好预习,课后及时做好反馈,整个下来其实花的时间也不是很多,归根结底还是自己tcl
录音,自己读5个数字0-4,然后录下来转成单声道的wav文件
求基音
基音的求法可以比较简单,就是通过加w=20ms,160个样点的汉明窗,然后计算出短时自相关函数,取最大值就是基音的频率
通过LP,求预测增益,画出数字0的预测增益
matlab
[y,fs] = audioread('5num.m4a');
audiowrite('5num.wav', y(:,1), 8000)
这样就转成了wav格式的文件
当然我比较偷懒,本来双声道应该是要做一点处理再变成单声道的,但是为了方便就直接变好了
这里当然我是不知道写代码的,所以用了别人的代码,下面好好分析一下:
说实话我有点晕不知道应该是怎么说比较好
x = audioread('5num.wav');
figure(1);
stem(x, '.');
n=160; %每一帧160个样点
for m=1:length(x)/n;%帧的个数
for k=1:n;%一帧有160个点
Rm(k)=0;
% 求自相关函数
for i=(k+1):n;
Rm(k)=Rm(k)+x(i+(m-1)*n)*x(i-k+(m-1)*n);
end
end
p=Rm(30:n);
[Rmax,N(m)]=max(p);
end
首先读入音频,然后分帧,每一帧是160个样点,取出每一帧来,通过
for i=(k+1):n;
Rm(k)=Rm(k)+x(i+(m-1)*n)*x(i-k+(m-1)*n);
end
这是公式,计算出短时自相关函数
同时之后求出其中的最大值及其索引存起来
这样画出的其实就是基音频率了
figure(2);
stem(T,'.');
axis([0 length(T) 0 20]);
xlabel('frame(n)');
ylabel('period(ms)');
title('');
fig1如下:
当然之后还可以做一次中值滤波
T1=medfilt1(T,5); % 中值滤波函数
figure(3);
stem(T1,'.');
axis([0 length(T1) 0 20]);
xlabel('frame(n)');
ylabel('period(ms)');
我在这个链接这里也找到了代码,效果如下
%%
[x, fs] = audioread('5num.wav');
frame_length = 30
frame_overlap = 20
nsample = round(frame_length * fs / 1000); % 转换 ms 到 point
noverlap = round(frame_overlap * fs / 1000); % 转换 ms 到 point
N = length(x);
pos = 1;
i = 1;
while (pos+nsample < N)
frame = x(pos:pos+nsample-1);
frame_length = length(frame);
% 加窗
window = hanning(frame_length);
frame = window.*frame;
frame = frame - mean(frame); % 去除中值
R(:,i) = xcorr(frame, fs, 'coeff');
% R(:,i) = spCorrelum(frame, fs);
% 搜2ms (=500Hz)到20ms (=50Hz)内的最大值
F0(i) = spPitchCorr(R(:,i), fs);
r = R(:,i);
% 搜2ms (=500Hz)到20ms (=50Hz)内的最大值
ms2=floor(fs/500); % 2ms
ms20=floor(fs/50); % 20ms
% 反应真实信号
r = r(floor(length(r)/2):end);
[maxi,idx]=max(r(ms2:ms20));
f0 = fs/(ms2+idx-1);
pos = pos + (nsample - noverlap);
i = i + 1;
end
% 求出对应的横坐标 帧长nsample 重叠 noverlap,如果noverlap为0那么就是直接每隔nsample取值
T = (round(nsample/2):(nsample-noverlap):N-1-round(nsample/2))/fs;
% 画出波形
subplot(2,1,1);
t = (0:N-1)/fs;
plot(t, x);
% plot(x);
legend('Waveform');
xlabel('Time (s)');
ylabel('Amplitude');
xlim([t(1) t(end)]);
% 画出 F0跟踪
subplot(2,1,2);
plot(T,F0);
legend('pitch track');
xlabel('Time (s)');
ylabel('Frequency (Hz)');
xlim([t(1) t(end)]);
但是为什么得到的图是倒过来的呢??。。
[y,fs] = audioread(input);
%设置帧长20ms
wlen=160;inc=40;%inc为帧移
win=hamming(wlen);%给出汉明窗
N=length(y);%信号长度
X=enframe(y,win,inc);%分帧
%frame=X(850:851,:);
figure;
subplot(211);plot(X);xlabel('帧');ylabel('分帧加窗后的矩阵');
加窗之后可以看到如下:
或者说这幅图又代表了什么呢?
局部放大之后可以看到
可以看到我读0的时候的帧大概是第520帧
可以单独提取出来
%[x,fs]=audioread(input);
n=160;%一帧的样点数
p0=40;%帧重叠的部分
x1=buffer(y,n,p0);
m=521;%第几帧
y1=x1((m-1)*n+1:m*n);%选出一个帧的数据
%p=10;%
subplot(212);plot(y1);xlabel('520帧');ylabel('分帧加窗后的矩阵');
但是这幅图又代表什么呢emmm
之后开始计算预测系数
ar=lpc(y1,10);%预测系数
est_x=filter([0 -ar(2:end)],1,y1);%估计信号
e=y1-est_x;%预测误差
以及:
%%求预测增益
%计算残差能量
En=zeros(1,160);
for i=1:160
u=e(i);%取出一样点
u2=u.*u;%求出能量
En(i)=sum(u2);%对每一样点累加求和
end
%计算原始能量
En1=zeros(1,160);
for i=1:160
u=y1(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