1. 程式人生 > 其它 >【語音合成】基於matlab語音訊號變調【含Matlab原始碼 566期】

【語音合成】基於matlab語音訊號變調【含Matlab原始碼 566期】

一、簡介

基於matlab語音訊號的變調

二、原始碼

clear all; clc; close all;

[xx,fs]=wavread('C7_4_y.wav');                     % 讀取檔案
xx=xx-mean(xx);                           % 去除直流分量
x=xx/max(abs(xx));                        % 幅值歸一化
lx=length(x);                             % 資料長度
time=(0:lx-1)/fs;                         % 求出對應的時間序列
wlen=240;                                 % 設定幀長
inc=80;                                   % 設定幀移的長度  
overlap=wlen-inc;                         % 重疊長度
tempr1=(0:overlap-1)'/overlap;            % 斜三角窗函式w1
tempr2=(overlap-1:-1:0)'/overlap;         % 斜三角窗函式w2
n2=1:wlen/2+1;                            % 正頻率的下標值
X=enframe(x,wlen,inc)';                   % 按照引數進行分幀
fn=size(X,2);                             % 總幀數
T1=0.1; r2=0.5;                           % 端點檢測引數
miniL=10;                                 % 有話段最短幀數
mnlong=5;                                 % 母音主體最短幀數
ThrC=[10 15];                             % 閾值
p=12;                                     % LPC階次
frameTime=FrameTimeC(fn,wlen,inc,fs);     % 計算每幀的時間刻度
in=input('請輸入基音訊率升降的倍數:','s');  % 輸入基音訊率增降比例
rate=str2num(in);

for i=1 : fn                              % 求取每幀的預測係數和增益
    u=X(:,i);
    [ar,g]=lpc(u,p);
    AR_coeff(:,i)=ar;
    Gain(i)=g;
end

% 基音檢測
[voiceseg,vosl,SF,Ef,period]=pitch_Ceps(x,wlen,inc,T1,fs); %基於倒譜法的基音週期檢測
Dpitch=pitfilterm1(period,voiceseg,vosl);       % 對T0進行平滑處理求出基音週期T0

if rate>1, sign=-1; else sign=1; end
lmin=floor(fs/450);                       % 基音週期的最小值
lmax=floor(fs/60);                        % 基音週期的最大值
deltaOMG = sign*100*2*pi/fs;              % 根值順時針或逆時針旋轉量dθ
Dpitchm=Dpitch/rate;                      % 增減後的基音週期
% Dfreqm=Dfreq*rate;                        % 增減後的基音訊率

tal=0;                                    % 初始化
zint=zeros(p,1); 
for i=1 : fn
    a=AR_coeff(:,i);                      % 取得本幀的AR係數
    sigma=sqrt(Gain(i));                  % 取得本幀的增益係數

    if SF(i)==0                           % 無話幀
        excitation=randn(wlen,1);         % 產生白噪聲
        [synt_frame,zint]=filter(sigma,a,excitation,zint);
    else                                  % 有話幀
        PT=floor(Dpitchm(i));             % 把週期值變為整數
        if PT<lmin, PT=lmin; end          % 判斷修改後的週期值有否超限
        if PT>lmax, PT=lmax; end
        ft=roots(a);                      % 對預測係數求根
        ft1=ft;
%增加共振峰頻率,實軸上方的根順時針轉,下方的根逆時針轉,求出新的根值
        for k=1 : p
            if imag(ft(k))>0, 
                ft1(k) = ft(k)*exp(j*deltaOMG);
	        elseif imag(ft(k))<0 
                ft1(k) = ft(k)*exp(-j*deltaOMG);
	        end
        end
        ai=poly(ft1);                     % 由新的根值重新組成預測係數

        exc_syn1 =zeros(wlen+tal,1);      % 初始化脈衝發生區
        exc_syn1(mod(1:tal+wlen,PT)==0)=1;% 在基音週期的位置產生脈衝,幅值為1
        exc_syn2=exc_syn1(tal+1:tal+inc); % 計算幀移inc區間內的脈衝個數
        index=find(exc_syn2==1);
        excitation=exc_syn1(tal+1:tal+wlen);% 這一幀的激勵脈衝源
        
        if isempty(index)                 % 幀移inc區間內沒有脈衝
            tal=tal+inc;                  % 計算下一幀的前導零點
        else                              % 幀移inc區間內有脈衝
            eal=length(index);            % 計算脈衝個數
            tal=inc-index(eal);           % 計算下一幀的前導零點
        end
        gain=sigma/sqrt(1/PT);            % 增益
        [synt_frame,zint]=filter(gain,ai,excitation,zint);%用激勵脈衝合成語音
    end
    
    if i==1                               % 若為第1幀
            output=synt_frame;            % 不需要重疊相加,保留合成數據
        else
            M=length(output);             % 重疊部分的處理
            output=[output(1:M-overlap); output(M-overlap+1:M).*tempr1+...
                synt_frame(1:overlap).*tempr2; synt_frame(overlap+1:wlen)];
        end
end

三、執行結果

四、備註

版本:2014a
完整程式碼或代寫加1564658423