% --- Executes on button press in open_pushbutton.
function open_Call_b2g()
% hObject handle to open_pushbutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[filename pathname]=uigetfile({'*.wav','ALL FILES(*.*)'},'选择声音文件');
if isequal([filename pathname],[0,0])
return;
end
strname=[pathname filename];%选择的声音文件路径和文件名
[data Fs]=wavread(strname);%data表示声音数据 Fs表示频率
handles.y=data;
handles.Fs=Fs;
handles.yoriginal=data;
handles.foriginal=Fs;
%guidata(hObject,handles);
b2g_Call(handles);
% --- Executes on button press in b2g_pushbutton.
function b2g_Call(handles)
% hObject handle to b2g_pushbutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%读取音频信息(双声道,16位,频率44100Hz)
% 定义常数
FL = 80; % 帧长
WL = 240; % 窗长
P = 10; % 预测系数个数
data=handles.y;fs=handles.Fs; % 载入语音数据
data= data/max(data); %归一化
L = length(data); % 读入语音长度
FN = floor(L/FL)-2; % 计算帧数
% 预测和重建滤波器
exc = zeros(L,1); % 激励信号(预测误差)
zi_pre = zeros(P,1); % 预测滤波器的状态
s_rec = zeros(L,1); % 重建语音
zi_rec = zeros(P,1);
% 合成滤波器
exc_syn = zeros(L,1); % 合成的激励信号(脉冲串)
s_syn = zeros(L,1); % 合成语音
last_syn = 0; %存储上一个(或多个)段的最后一个脉冲的下标
zi_syn = zeros(P,1); % 合成滤波器的状态
% 变调不变速滤波器
exc_syn_t = zeros(L,1); % 合成的激励信号(脉冲串)
s_syn_t = zeros(L,1); % 合成语音
last_syn_t = 0; %存储上一个(或多个)段的最后一个脉冲的下标
zi_syn_t = zeros(P,1); % 合成滤波器的状态
% 变速不变调滤波器(假设速度减慢一倍)
hw = hamming(WL); % 汉明窗
% 依次处理每帧语音
for n = 3:FN
% 计算预测系数(不需要掌握)
s_w = data(n*FL-WL+1:n*FL).*hw; %汉明窗加权后的语音
[A E] = lpc(s_w, P); %用线性预测法计算P个预测系数
% A是预测系数,E会被用来计算合成激励的能量
s_f = data((n-1)*FL+1:n*FL); % 本帧语音,下面就要对它做处理
% (4) 用filter函数s_f计算激励,注意保持滤波器状态
[exc1,zi_pre] = filter(A,1,s_f,zi_pre);
exc((n-1)*FL+1:n*FL) = exc1; %计算得到的激励
% (5) 用filter函数和exc重建语音,注意保持滤波器状态
[s_rec1,zi_rec] = filter(1,A,exc1,zi_rec);
s_rec((n-1)*FL+1:n*FL) = s_rec1; %计算得到的重建语音
% 注意下面只有在得到exc后才会计算正确
s_Pitch = exc(n*FL-222:n*FL);
PT = findpitch(s_Pitch); % 计算基音周期PT(不要求掌握)
G = sqrt(E*PT); % 计算合成激励的能量G(不要求掌握)
%方法3:本段激励只能修改本段长度
tempn_syn = [1:n*FL-last_syn]';
exc_syn1 = zeros(length(tempn_syn),1);
exc_syn1(mod(tempn_syn,PT)==0) = G; %某一段算出的脉冲
exc_syn1 = exc_syn1((n-1)*FL-last_syn+1:n*FL-last_syn);
[s_syn1,zi_syn] = filter(1,A,exc_syn1,zi_syn);
exc_syn((n-1)*FL+1:n*FL) = exc_syn1; %计算得到的合成激励
s_syn((n-1)*FL+1:n*FL) = s_syn1; %计算得到的合成语音
last_syn = last_syn+PT*floor((n*FL-last_syn)/PT);
% (13) 将基音周期减小一半,将共振峰频率增加150Hz,重新合成语音,听听是啥感受~
PT1 =floor(PT/2); %减小基音周期
poles = roots(A);
deltaOMG =150*2*pi/fs;
for p=1:10 %增加共振峰频率,实轴上方的极点逆时针转,下方顺时针转
if imag(poles(p))>0 poles(p) = poles(p)*exp(j*deltaOMG);
elseif imag(poles(p))<0 poles(p) = poles(p)*exp(-j*deltaOMG);
end
end
A1=poly(poles);
tempn_syn_t = [1:n*FL-last_syn_t]';
exc_syn1_t = zeros(length(tempn_syn_t),1);
exc_syn1_t(mod(tempn_syn_t,PT1)==0) = G; %某一段算出的脉冲
exc_syn1_t = exc_syn1_t((n-1)*FL-last_syn_t+1:n*FL-last_syn_t);
[s_syn1_t,zi_syn_t] = filter(1,A1,exc_syn1_t,zi_syn_t);
exc_syn_t((n-1)*FL+1:n*FL) = exc_syn1_t; %计算得到的合成激励
s_syn_t((n-1)*FL+1:n*FL) = s_syn1_t; %计算得到的合成语音
last_syn_t = last_syn_t+PT1*floor((n*FL-last_syn_t)/PT1);
end %循环结束,获得变换后语音 s_syn_t
%
% plot(handles.axes3,s_syn_t),
% set(handles.axes3,'Xgrid','on');
% set(handles.axes3,'Ygrid','on');
% xlabel(handles.axes3,'数据序列');
% ylabel(handles.axes3,'频率');
% title(handles.axes3,'变音后的时域图'),XLim([0,length(s_syn_t)]);
%
subplot(1,3,3);plot(s_syn_t),
grid on;
xlabel('数据序列');
ylabel('频率');
title('变音后的时域图'),XLim([0,length(s_syn_t)]);
handles.y=s_syn_t;
% guidata(hObject,handles);
Fs=handles.foriginal;
N=length(handles.y);
y1=fft(handles.y,N);
f1=0:Fs/N:Fs*(N-1)/N;
% plot(handles.axes1,f1,handles.yoriginal);
% title(handles.axes1,'原始时域图');
% xlabel(handles.axes1,'时间');
% ylabel(handles.axes1,'频率');
% set(handles.axes1,'Xgrid','on');
% set(handles.axes1,'Ygrid','on');
%
subplot(1,3,1);plot(f1,handles.yoriginal);
title('原始时域图');
xlabel('时间');
ylabel('频率');
grid on;
% plot(handles.axes2,f1(1:N/2),y1(1:N/2));
% set(handles.axes2,'Xgrid','on');
% set(handles.axes2,'Ygrid','on');
% title(handles.axes2,'频谱图');
% xlabel( handles.axes2,'频率');
% ylabel( handles.axes2,'幅度');
%
subplot(1,3,2);plot(f1(1:N/2),y1(1:N/2));
grid on;
title('频谱图');
xlabel('频率');
ylabel('幅度');
pause(3);
sound(handles.yoriginal);
sound(handles.y);
% 计算一段语音的基音周期
function PT = findpitch(s)
[B, A] = butter(5, 700/4000);
s = filter(B,A,s);
R = zeros(143,1);
for k=1:143
R(k) = s(144:223)'*s(144-k:223-k);
end
[R1,T1] = max(R(80:143));
T1 = T1 + 79;
R1 = R1/(norm(s(144-T1:223-T1))+1);
[R2,T2] = max(R(40:79));
T2 = T2 + 39;
R2 = R2/(norm(s(144-T2:223-T2))+1);
[R3,T3] = max(R(20:39));
T3 = T3 + 19;
R3 = R3/(norm(s(144-T3:223-T3))+1);
Top = T1;
Rop = R1;
if R2 >= 0.85*Rop
Rop = R2;
Top = T2;
end
if R3 > 0.85*Rop
Rop = R3;
Top = T3;
end
PT = Top;
return
% --- Executes on button press in open_pushbutton.
function open_Call_g2b()
% hObject handle to open_pushbutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[filename pathname]=uigetfile({'*.wav','ALL FILES(*.*)'},'选择声音文件');
if isequal([filename pathname],[0,0])
return;
end
strname=[pathname filename];%选择的声音文件路径和文件名
[data Fs]=wavread(strname);%data表示声音数据 Fs表示频率
handles.y=data;
handles.Fs=Fs;
handles.yoriginal=data;
handles.foriginal=Fs;
%guidata(hObject,handles);
g2b_Call(handles);
% --- Executes on button press in g2b_pushbutton.
function g2b_Call(handles)
% hObject handle to g2b_pushbutton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
y=handles.y;
fs=handles.Fs;%读取音频信息(双声道,16位,频率44100Hz)
N=length(y)
% f=0:fs/N:fs*(N-1)/N;
f=[0:N-1]*fs/N;
Y=fft(y,N); %进行傅立叶变换=>Y
%plot(handles.axes2,f(1:N/2),Y(1:N/2));
% title(handles.axes2,'声音信号的频谱');
% xlabel(handles.axes2,'频率');
% ylabel(handles.axes2,'振幅');
subplot(1,3,2);plot(f(1:N/2),Y(1:N/2));
title('声音信号的频谱');
xlabel('频率');
ylabel('振幅');
grid on;
% f1=0:(fs*0.7)/N:(fs*0.7)*(N-1)/N;
f1=[0:N-1]*(fs*0.7)/N;%降低频率为原频率f的0.7
% syms t;
t=[0,9];
R=y*exp(2*pi*300*t);%改变声音数据y=>R
P=fft(R,N);%y =>R , 傅立叶变换=>P
Z=ifft(P);
% z=real(Z);
handles.y=y; % y根本就没有变化啊?
% plot(handles.axes3,f1(1:N/2),Z(1:N/2));
% title(handles.axes3,'变声后的时域图');
% xlabel(handles.axes3,'时间序列');
% ylabel(handles.axes3,'频率')
% set(handles.axes3,'Xgrid','on');
% set(handles.axes3,'Ygrid','on');
subplot(1,3,3);plot(f1(1:N/2),Z(1:N/2));
title('变声后的频谱');
xlabel('频率');
ylabel('幅值')
grid on;
Fs=handles.foriginal;
N=length(handles.y);
y1=fft(handles.y,N);
% f1=0:Fs/N:Fs*(N-1)/N;
f1=[0:N-1]*Fs/N;
% plot(handles.axes1,f1,handles.yoriginal);
% title(handles.axes1,'原始时域图');
% xlabel(handles.axes1,'时间');
% ylabel(handles.axes1,'频率');
% set(handles.axes1,'Xgrid','on');
% set(handles.axes1,'Ygrid','on');
subplot(1,3,1); plot(f1,handles.yoriginal);
title('原始的频谱?');
xlabel('频率');
ylabel('幅值');
grid on;
% plot(handles.axes2,f1(1:N/2),y1(1:N/2));
% set(handles.axes2,'Xgrid','on');
% set(handles.axes2,'Ygrid','on');
% title(handles.axes2,'频谱图');
% xlabel( handles.axes2,'频率');
% ylabel( handles.axes2,'幅度');
figure;plot(f1(1:N/2),y1(1:N/2));
grid on;
title('频谱图');
xlabel('频率');
ylabel('幅度');
pause(3);
%guidata(hObject,handles);
sound(handles.yoriginal);
sound(handles.y,handles.foriginal*0.7);