1. 程式人生 > 其它 >【語音合成】基於matlab線性預測共振峰檢測和基音引數語音合成【含Matlab原始碼 562期】

【語音合成】基於matlab線性預測共振峰檢測和基音引數語音合成【含Matlab原始碼 562期】

一、簡介

基於matlab線性預測共振峰檢測和基音引數的語音合成

二、原始碼

clear all; clc; close all;

[xx,fs]=wavread('C7_3_y.wav');                     % 讀取檔案
xx=xx-mean(xx);                           % 去除直流分量
x1=xx/max(abs(xx));                       % 歸一化
x=filter([1 -.99],1,x1);                  % 預加重
N=length(x);                              % 資料長度
time=(0:N-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;                            % 正頻率的下標值
wind=hamming(wlen);                       % 窗函式
X=enframe(x,wlen,inc)';                   % 分幀
fn=size(X,2);                             % 幀數
Etemp=sum(X.*X);                          % 計算每幀的能量
Etemp=Etemp/max(Etemp);                   % 能量歸一化
T1=0.1; r2=0.5;                           % 端點檢測引數
miniL=10;                                 % 有話段最短幀數
mnlong=5;                                 % 母音主體最短幀數
ThrC=[10 15];                             % 閾值
p=12;                                     % LPC階次
frameTime=FrameTimeC(fn,wlen,inc,fs);     % 計算每幀的時間刻度
Doption=0;                                

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

%% 共振峰提取
for i=1:length(SF)
    [Frmt(:,i),Bw(:,i),U(:,i)]=Formant_Root(X(:,i),p,fs,3);
end
%% 語音合成
zint=zeros(2,4);                          % 初始化
tal=0;
for i=1 : fn
    yf=Frmt(:,i);                         % 取來i幀的三個共振峰頻率和頻寬
    bw=Bw(:,i);
    [an,bn]=formant2filter4(yf,bw,fs);    % 轉換成四個二階濾波器係數
    synt_frame=zeros(wlen,1);
    
    if SF(i)==0                           % 無話幀
        excitation=randn(wlen,1);         % 產生白噪聲
        for k=1 : 4                       % 對四個濾波器並聯輸入
            An=an(:,k);
            Bn=bn(k);
            [out(:,k),zint(:,k)]=filter(Bn(1),An,excitation,zint(:,k));
            synt_frame=synt_frame+out(:,k); % 四個濾波器輸出疊加在一起
        end
    else                                  % 有話幀
        PT=round(Dpitch(i));              % 取週期值
        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
        for k=1 : 4                       % 對四個濾波器並聯輸入
            An=an(:,k);
            Bn=bn(k);
            [out(:,k),zint(:,k)]=filter(Bn(1),An,excitation,zint(:,k));
            synt_frame=synt_frame+out(:,k); % 四個濾波器輸出疊加在一起
        end
    end
    Et=sum(synt_frame.*synt_frame);       % 用能量歸正合成語音
    rt=Etemp(i)/Et;
    synt_frame=sqrt(rt)*synt_frame;
        if i==1                           % 若為第1幀
            output=synt_frame;            % 不需要重疊相加,保留合成數據
        else
            M=length(output);             % 按線性比例重疊相加處理合成資料
            output=[output(1:M-overlap); output(M-overlap+1:M).*tempr2+...
                synt_frame(1:overlap).*tempr1; synt_frame(overlap+1:wlen)];
        end

三、執行結果

四、備註

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