matlab声音信号分析与合成

该博客详细介绍了如何使用MATLAB解析和重构声音信号,通过快速傅里叶变换(FFT)分析音频的幅值、频率和相位信息。作者展示了从读取音频文件到时域、频域和相频分析的完整过程,并实现了信号的合成与过滤。此外,还讨论了FFT在还原声音信号时的局限性及其对人耳感知的影响。
摘要由CSDN通过智能技术生成

任何一种声音信号都可以表示为

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;

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值