任何一种声音信号都可以表示为
X(n)=Aiinsin(ωit+θi)
其中
ωi=2πfi
Ai为归一化幅值, fi为频率,θi为初始相位角。t 为采样向量矩阵,例如采样率为Fs
每帧音频时间为T,则t为0:1Fs:T的向量矩阵。
我们可以用matlab解析出声音信号的幅值 频率 相位角信息,再带入公式还原声音,也可以将数据存储,还原时根据需求添加改变部分数据,就好比你有了一个人身材的尺寸,就可以为她量身定做各种类型的衣服,此处有缺陷就是采用快速傅里叶,无法百分百还原,但是人耳分辨不出两种声音的区别,以下是源码:
clear;close all;clc;
% %官方
% fs = 44100;
% t = 0:1/fs:1-1/fs;
% x1 = 1*sin(2*pi*15*t+pi/2);
% x2 = 0.6*sin(2*pi*20*t+pi/4);
% x3 = 0.3*sin(2*pi*50*t+pi/5);
% x4 = 0.2*sin(2*pi*70*t+pi/8);
% x=(x1+x2+x3+x4)';
% %figure,plot(t,x,t,x1,t,x2,t,x3,t,x4)';
%读取信号
[x,fs] = audioread('D:\xxx.wav'); %读取音频
sigLen = length(x);
x=x(1:round(sigLen/fs)*fs);
sx=reshape(x,fs,[])';%将源音截取为多行数据 每行为一秒
t = 0 : 1/fs :(sigLen-1)/fs;
[xr,xc]=size(sx);
%sound(x);
%逐行遍历分析每秒数据
figure,
zX=0;%总幅值
thetaX=0;%总相位
for xi=1:1
subplot(xr,3,xi*3-2);
plot(t,x(xr,:));
title('时域');
ylabel('幅值/DB');
xlabel('时间/s');
grid;
y = fft(x(xr,:));
z = fftshift(y);
zX=zX+z;
ly = length(y);
f = (-ly/2:ly/2-1)/ly*fs;
subplot(xr,3,xi*3-1);
stem(f,abs(z)/max(abs(z)));
title('频域');
xlabel 'Frequency (Hz)'
ylabel '|y|'
grid
tol = 1e-6;
z(abs(z) < tol) = 0;%可以忽略的相位 官方数据
theta = angle(z);
thetaX=thetaX+theta;
subplot(xr,3,xi*3);
stem(f,theta/pi);
title('相频');
xlabel 'Frequency (Hz)'
ylabel 'Phase / \pi'
grid
end
%%合成数据
%建立频率 幅值 相位的矩阵
res=[f' abs(zX)/max(abs(zX)) thetaX/pi];
[r,c] = size(res); % 读取行r、列c
s=0;
for i =1:r %遍历矩阵 真实还原数据
if res(i,3) ~= 0 && res(i,1)>0
s=s+res(i,2)*sin(2*pi* res(i,1)*t+(0.5+res(i,3))*pi);%快速傅里叶相谱要减去pi/2 故还原时加上
end
end
ss=0;
for i =1:r %遍历矩阵 过滤还原数据
if res(i,3) ~= 0 && res(i,1)>20 && res(i,1)<100 %0为非初相位
ss=ss+res(i,2)*sin(2*pi* res(i,1)*t+(0.5+res(i,3))*pi);%快速傅里叶相谱要减去pi/2 故还原时加上
end
end
%sound(ss);
figure,subplot 311;
plot(t,x);
title('源音时域');
ylabel('幅值/DB');
xlabel('时间/s');
grid;
subplot 312;
plot(t,s);
title('仿真时域');
ylabel('幅值/DB');
xlabel('时间/s');
grid;
subplot 313;
plot(t,ss);
title('过滤仿真时域');
ylabel('幅值/DB');
xlabel('时间/s');
grid;