% --- 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);