matlab数字信号处理

2018-09-01  本文已影响393人  Savior2016

前言:这一篇是研究matlab数字信号处理(音频)的一个学习总结。在数学方面天赋有限,理解了一些,但是没有做到最后,有兴趣的话可以拿去借鉴做得更完美一些。
这篇的主要目的是分析男女声音的区别,终极目标是实现男女声音的辨识,借鉴了很多人的程序,会在末尾注明参考链接。


1 matlab傅里叶变换

第一步是搞明白傅里叶变换是怎么工作的,原理这里不说了,只看方法和结果,参考的是matlab早期的一个官方文档,现在的文档已经做了改进,稍微复杂一些,道理差不多。
程序如下:

%模拟一个数字信号
t=0:0.001:0.6;  %时间序列
x=sin(2*pi*50*t)+sin(2*pi*120*t);%数字信号,两个频率成分,分别为50Hz和120Hz
y=x+2*randn(size(t));%添加随机噪声
%绘制原始信号时域图
figure(1);
plot(1000*t,y);
title('原始信号');
ylabel('amplitude');
xlabel('time(s)');
%快速傅里叶变换
Y=fft(y,512);%此处取前512个采样点
Pyy=Y.*conj(Y)/512;%求能量值,conj是求共轭的意思
%绘制频谱图
figure(2);
f=1000*(0:511)/512;
plot(f,Pyy);
%绘制一半的频谱图
figure(3);
fh=1000*(0:256)/512;
plot(fh,Pyy(1:257));

原始信号:

原始信号
频谱图:
频谱图.png
毫无疑问,频谱图是对称的。记得研一听懂这部分的时候,我兴奋了一下午,但是我真的想不起来为什么是对称的了,反正显然它是对称的。右边是因为求了复数的模才出来的。实在想知道怎么回事,自己去看吧:与时间无关的故事
所以这里我们显示一半的频谱看一下:
50
120
是不是堪称完美,学到这里我都迫不及待了,觉得分析音频肯定也就这么
回事。如果不考虑终极目标,是差不多。

2 音频分析

这里不提供完整的多人音频分析的内容,只单个分析。
首先是音频的来源,本来想着录音的,但是没有合适的环境,给女朋友录音倒是可以找个安静的地方是吧。但是给别的女生录音……不过最后找到了一个很好的素材,王者荣耀的英雄语音包。英雄语音包下载(密码:vfn3)

先上程序:

[y,fs]=audioread('G:\matlab_homework\matlab_home\audio\张良1.mp3');%读取音频,y数据,fs是采样率
%时域波形图
ft=y(:,1);%读取一个声道的音频
len=length(y);
t=(0:len-1)/fs;%时间序列
%原始信号时域图
figure(1);
plot(t,ft);
title('time');
xlabel('time(s)');
ylabel('amplitude');
%频域波形图
plen=len/32;%改成1就是整个图谱,这里只看前一部分
yf=fft(y,len);
yff=yf.*conj(yf)/len;
tf=(0:len-1)*fs/len;
figure(2);
plot(tf(1:plen),yff(1:plen));
title('fft');
xlabel('Hz');
ylabel('amplitude');

先来看看张良的,先看一下整个频域的图谱:


张良1

呦呵,图大了看不清,愚蠢的人类:


前1/32
大概这么一看,张良作为一个男孩子,他的声音频率主要集中在100-800Hz的样子。
迫不及待的翻出一个女孩子看看:
甄姬

哇塞,一看甄姬妹子的,好个性。仔细看看跟张良的分别,突然觉得这个任务很简单。

3 更进一步

首先看到这两张图,想到了人的声音肯定是有频率范围的,再者,想知道是不是已经有男女声音辨识的方法了。
于是找到了这张图:


男女声音频率分布

看上面的频谱,好像的确是这个样子。

这里有两个不认识的字,叫基音频率。据说基音就是物体整体发声的声音频率,它可以作为辨识男女声音的一项标准。
于是找到了以下程序:

%filename:manwoman.m 
%different man from woman. 
%=========================================================== 
clear; 
% [x,fs,bits]=wavread('d.wav', [1 5000]);       % 读入声音文件(*.wav)   
[y,fs]=audioread('G:\matlab_homework\matlab_home\audio\张良2.mp3');       % 读入声音文件(*.wav)  
sound(y,fs);                % 数据通过声卡转换为声音 
x=y;%fir_lpf(y,fs,400,50);%下面给出滤波函数
%=========================================================== 
% pause; 
data1=x(:,1); 
n=0:length(x)-1; 
time=n/fs; 
subplot(3,1,1)                                        % 绘制2行1列的第1张子图 
plot(time,data1)                                      % 以时间为横轴,数据为纵轴作图 
xlabel('Time (sec.)')                                 % 标注横坐标 
ylabel('Signal Level (Volts)')                        % 标注纵坐标 
grid on                                               % 添加网格 
% pause; 
% 对采集数据作滤波处理 
blocksize =length(data1);                             % 计算窗函数长度  
window = hanning(blocksize);                   % 计算汉宁窗函数(此函数为MATLAB自带) 
data2=window.*data1;                                  % 对数据先作加窗处理 
wp=400;                                             %100Hz--400Hz 
wp=wp*2/fs; 
%wp=3000*2/fs; 
[b,a]=ellip(4,0.1,20,wp);                      % 构造椭圆滤波器 
data=filter(b,a,data2);                               % 求加窗处理后的数据经过滤波器的响应 
subplot(3,1,2)                                        % 绘制2行1列的第1张子图 
plot(time,data)                                      % 以时间为横轴,数据为纵轴作图 
xlabel('Time (sec.)')                                 % 标注横坐标 
%ylabel('Signal Level (Volts)')                        % 标注纵坐标 
grid on                                               % 添加网格 
% pause; 
[xmax,index]=max(data1); 
timewin=floor(0.015*fs); 
xwin=data1(index-timewin:index+timewin); 
[y,lags]=xcov(xwin); 
subplot(3,1,3) 
plot(lags,y) 
grid on 
ylen=length(y); 
halflen=(ylen+1)/2 +30; 
yy=y(halflen: ylen); 
[ymax,maxindex] = max(yy); 
fmax=fs/(maxindex+30); 
disp(['Maximum occurred at ', num2str(fmax), ' Hz'])

f=fmax; 
justify=f;   %Hz 
if justify<180  %limitHz以下判断是男的 
    display '男' 
else 
    display '女' 
end

这个程序主要是通过自相关函数来求取基音频率,然后根据基因频率来辨识男女,我增加了一个低通滤波器,正确率大概有个百分之七八十吧。
低通滤波函数:

function [y]=fir_lpf(x,Fs,fs,fp)
%该函数采用hanning窗实现低通滤波
%x为输入信号,fs,为采样频率
%fs,fp分别为阻带截至频率和通带截至频率
%20150615 by boat


%求对应角频率
ws=fs*2*pi/Fs;
wp=fp*2*pi/Fs;


%求滤波器的最小阶数
B=ws-wp;   %过渡带宽取二者中较小的
N=ceil(6.2*pi/B);


%计算滤波器系数
wc=(ws+wp)/2;
hn=fir1(N-1,wc,hanning(N));
y=filter(hn,1,x);


%freqz(hn)

3 翻船了

正当我开心的准备复制粘贴我的结果的时候,翻船了,因为我测试了达摩和露娜的音频。
达摩作为一个纯爷们,给了我这样的图谱:


达摩

能量最高的频率超过了500,这部分不管它,但是大多数峰值都在200以后。
所以说我感觉只寻找基音频率这个方法还是有些问题的,只适用于大多数情况。如果你对比多个人的音频频谱,会看到其实男生声音普遍会从比较低的频率就开始出现,通常在多个频率上能量比较高。
就这么多了,详细的看下面链接学习吧。

参考文献

与时间无关的故事
男女声音识别
基音周期提取
matlab傅里叶变换

上一篇下一篇

猜你喜欢

热点阅读