matlab 变调器,个人改动后的语音变速变调的程序

function ct3

% 定义常数

FL = 80;                % 帧长

WL = 240;               % 窗长

P = 10;                 % 预测系数个数

hw = hamming(WL);       % 汉明窗

%%%%%%

[sl,Fs] = wavread('sunday_2.wav');             % 载入语音s

load('mtlb.mat');

sl=mtlb;

s=buffer(sl,FL);

[~,FN] = size(s);        % 计算帧数

% 预测和重建滤波器

exc = zeros(FL,FN);       % 激励信号(预测误差)

s_rec = exc;              % 重建语音

zi_pre = zeros(P,1);      % 预测滤波器的状态

zi_rec = zeros(P,1);      % 重建滤波器的状态

% 合成滤波器

exc_syn =exc;             % 合成的激励信号(脉冲串)

s_syn = exc;              % 合成语音

last_syn = [];             % 存储上一个帧的最后一个脉冲在下一帧结束的位置

zi_syn = zeros(P,1);      % 合成滤波器的状态

% 变速不变调滤波器

FL_v = 2*FL;              % 假设速度减慢一倍

exc_syn_v = zeros(FL_v,FN);  % 合成的激励信号

s_syn_v = exc_syn_v;      % 合成语音

last_syn_v = [];

zi_syn_v = zeros(P,1);    % 合成滤波器的状态

% 变调不变速滤波器

exc_syn_t = zeros(FL,FN);

s_syn_t = exc_syn_t;

last_syn_t = [];

zi_syn_t = zeros(P,1);

% 记录中间参数

A=zeros(P+1,FN);    %记录每帧提取的预测系数

E=zeros(1,FN);

PT_sf=zeros(1,FN);

PT_rf=zeros(1,FN);     %记录每帧提取的基音周期

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[S,F,T,Psd]=spectrogram(sl,240,160,2048,1);

Pe=pow2db(abs(Psd));

figure;surf(T,F*2048,Pe,'edgecolor','none')

% figure;surf(T,F(1:200)*2048,Pe(1:200,:),'edgecolor','none')

axis tight;

view(0,90);

xlabel('Time'); ylabel('sample');

[w,ind]=max(bsxfun(@minus,Pe(1:200,:),1.03.^(1:200)'));

PT_sf=round(2048./ind);

pind=w

PT_sf(pind)=FL-1; %基音周期置为帧长

figure;hold on;

plot(PT_sf,'r')

% 依次处理每帧语音

for n = 2:FN-1

% 计算预测系数(建立声道的系统模型)

s_f = s(:,n-1:n+1);                    %汉明窗加权后的语音

[A(:,n) Et] = lpc(s_f(:).*hw, P);            %用线性预测法计算P个预测系数

E(n)=Et*WL/sum(hw);

% A是预测系数,E会被用来计算合成激励的能量

% 提取激励,并用激励重建语音

[exc(:,n),zi_pre] = filter(A(:,n),1,s(:,n),zi_pre);% 计算激励

[s_rec(:,n),zi_rec] = filter(1,A(:,n),exc(:,n),zi_rec);% 重建语音

end

for n = 2:FN-1

ex_f=exc(:,n-1:n+1);

ex_f=ex_f(:);

% 提取基音周期,用于人工合成激励

R=xcorr(ex_f,1.5*FL);

Rh=filter(hamming(16),1,R(1.5*FL+1:end));

[~,PT]=findpeaks(Rh(9:end),'s','descend','n',1);

PT_rf(:,n)=PT;

G = sqrt(E(n)*PT);           % 计算合成激励的能量G(不要求掌握)

[~,m]=findpeaks(ex_f(81:160),'s','descend','n',1);

if isempty(m),m=121;end

m=80+m;

a=ceil(PT/2)-1;

b=floor(PT/2);

excf=[ex_f(m-b:m+a)];

excfh=excf(1+mod(b,2):2:end);

% 合成语音

%n

kt=ceil((FL-length(last_syn))/PT);

GG=[last_syn;repmat(excf,kt,1)];

exc_syn(:,n) = GG(1:80);        % 人工生成本帧激励

last_syn=GG(81:end);

%if length(exc_syn)>80,n,end

[s_syn(:,n),zi_syn] = filter(1,A(:,n),exc_syn(:,n),zi_syn); %通过人造激励合成语音

% 合成速度慢,但音调不变的语音。

kt=ceil((FL_v-length(last_syn_v))/PT);   % (不改变基音周期和预测系数,将合成激励的长度增加一倍)

GG=[last_syn_v;repmat(excf,kt,1)];

exc_syn_v(:,n) = GG(1:160); % 人工生成本帧激励

last_syn_v=GG(161:end);

[s_syn_v(:,n),zi_syn_v] = filter(1,A(:,n),exc_syn_v(:,n),zi_syn_v);

% 合成变调不变速的语音

poles = roots(A(:,n));

deltaOMG = 150*2*pi/8000; % 将共振峰频率增加150Hz

A1=poly(poles.*exp(sign(imag(poles))*1j*deltaOMG)); %生成新的声道模型

PT1 =length(excfh);   % 将基音周期减小一半

kt=ceil((FL-length(last_syn_t))/PT1);

GG=[last_syn_t;repmat(excfh,kt,1)];

exc_syn_t(:,n) = GG(1:80); % 人工生成本帧激励

last_syn_t=GG(81:end);

[s_syn_t(:,n),zi_syn_t] = filter(1,A1,exc_syn_t(:,n),zi_syn_t);

end

plot(PT_rf);title('受频域分辨率的影响,70到80帧的精度很差')

xlabel('提高精度可以增加短时傅立叶变换的样点数目(当前是2048)')

%return

xx=reshape(1:FL*FN,FL,FN);

splot(s,exc,s_rec,xx,'重建',Fs)

splot(s,exc_syn,s_syn,xx,'合成',Fs)

xx2=reshape(1:FL_v*FN,FL_v,FN);

splot(s,exc_syn_v,s_syn_v,xx2,'合成慢速',Fs)

splot(s,exc_syn_t,s_syn_t,xx,'合成高调',Fs)

function splot(s,ex,re,x,str,Fs)

figure;

ax(3)=subplot(3,1,1);

plot(s(:));  title('原语音信号')

ax(2)=subplot(3,1,2);

plot(x,ex);  title([str,'激励信号'])

ax(1)=subplot(3,1,3);

plot(re(:));  title([str,'语音信号'])

linkaxes(ax,'xy')

sound(s(:),Fs);

sound(ex(:),Fs);

sound(re(:),Fs);

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值