|
a |
|
b/Wiener.m |
|
|
1 |
function [output,time] = Wiener(signal,fs,type,IS) |
|
|
2 |
|
|
|
3 |
if (nargin<4 || isstruct(IS)) |
|
|
4 |
IS=.25; %Initial Silence or Noise Only part in seconds |
|
|
5 |
end |
|
|
6 |
|
|
|
7 |
W=fix(.025*fs); %Window length is 25 ms |
|
|
8 |
SP=.4; %Shift percentage is 40% (10ms) %Overlap-Add method works good with this value(.4) |
|
|
9 |
wnd=hann(W); |
|
|
10 |
|
|
|
11 |
pre_emph=0; |
|
|
12 |
signal=filter([1 -pre_emph],1,signal); |
|
|
13 |
|
|
|
14 |
NIS=fix((IS*fs-W)/(SP*W) +1);%number of initial silence segments |
|
|
15 |
|
|
|
16 |
y=segment(signal,W,SP,wnd); % This function chops the signal into frames |
|
|
17 |
Y=fft(y); |
|
|
18 |
YPhase=angle(Y(1:fix(end/2)+1,:)); %Noisy Speech Phase |
|
|
19 |
Y=abs(Y(1:fix(end/2)+1,:));%Specrogram |
|
|
20 |
numberOfFrames=size(Y,2); |
|
|
21 |
FreqResol=size(Y,1); |
|
|
22 |
|
|
|
23 |
N=mean(Y(:,1:NIS)')'; %initial Noise Power Spectrum mean |
|
|
24 |
LambdaD=mean((Y(:,1:NIS)').^2)';%initial Noise Power Spectrum variance |
|
|
25 |
alpha=.99; %used in smoothing xi (For Deciesion Directed method for estimation of A Priori SNR) |
|
|
26 |
NoiseCounter=0; |
|
|
27 |
NoiseLength=9;%This is a smoothing factor for the noise updating |
|
|
28 |
G=ones(size(N));%Initial Gain used in calculation of the new xi |
|
|
29 |
Gamma=G; |
|
|
30 |
|
|
|
31 |
X=zeros(size(Y)); % Initialize X (memory allocation) |
|
|
32 |
|
|
|
33 |
h=waitbar(0,'Wait...'); |
|
|
34 |
|
|
|
35 |
for i=1:numberOfFrames |
|
|
36 |
%%%%%%%%%%%%%%%%VAD and Noise Estimation START |
|
|
37 |
if i<=NIS % If initial silence ignore VAD |
|
|
38 |
SpeechFlag=0; |
|
|
39 |
NoiseCounter=100; |
|
|
40 |
else % Else Do VAD |
|
|
41 |
[NoiseFlag, SpeechFlag, NoiseCounter, Dist]=vad(Y(:,i),N,NoiseCounter); %Magnitude Spectrum Distance VAD |
|
|
42 |
end |
|
|
43 |
|
|
|
44 |
if SpeechFlag==0 % If not Speech Update Noise Parameters |
|
|
45 |
N=(NoiseLength*N+Y(:,i))/(NoiseLength+1); %Update and smooth noise mean |
|
|
46 |
LambdaD=(NoiseLength*LambdaD+(Y(:,i).^2))./(1+NoiseLength); %Update and smooth noise variance |
|
|
47 |
end |
|
|
48 |
%%%%%%%%%%%%%%%%%%%VAD and Noise Estimation END |
|
|
49 |
|
|
|
50 |
gammaNew=(Y(:,i).^2)./LambdaD; %A postiriori SNR |
|
|
51 |
xi=alpha*(G.^2).*Gamma+(1-alpha).*max(gammaNew-1,0); %Decision Directed Method for A Priori SNR |
|
|
52 |
Gamma=gammaNew; |
|
|
53 |
|
|
|
54 |
G=(xi./(xi+1)); |
|
|
55 |
|
|
|
56 |
X(:,i)=G.*Y(:,i); %Obtain the new Cleaned value |
|
|
57 |
|
|
|
58 |
waitbar(i/numberOfFrames,h,num2str(fix(100*i/numberOfFrames))); |
|
|
59 |
end |
|
|
60 |
|
|
|
61 |
close(h); |
|
|
62 |
output = OverlapAdd2(X,YPhase,W,SP*W); %Overlap-add Synthesis of speech |
|
|
63 |
output = filter(1,[1 -pre_emph],output); %Undo the effect of Pre-emphasis |
|
|
64 |
|
|
|
65 |
num = [0.00247553277809987,0.00495106555619995,0.00247553277809975]; |
|
|
66 |
den = [1,-1.80098109524571,0.810883226358106]; |
|
|
67 |
|
|
|
68 |
output = filter(num,den,output); |
|
|
69 |
time = (0:1/fs:(size(output,1)-1)/fs); |
|
|
70 |
|
|
|
71 |
if type == 1 |
|
|
72 |
output = 100.*output; |
|
|
73 |
end |
|
|
74 |
|
|
|
75 |
|
|
|
76 |
function ReconstructedSignal=OverlapAdd2(XNEW,yphase,windowLen,ShiftLen) |
|
|
77 |
|
|
|
78 |
if nargin<2 |
|
|
79 |
yphase=angle(XNEW); |
|
|
80 |
end |
|
|
81 |
if nargin<3 |
|
|
82 |
windowLen=size(XNEW,1)*2; |
|
|
83 |
end |
|
|
84 |
if nargin<4 |
|
|
85 |
ShiftLen=windowLen/2; |
|
|
86 |
end |
|
|
87 |
if fix(ShiftLen)~=ShiftLen |
|
|
88 |
ShiftLen=fix(ShiftLen); |
|
|
89 |
disp('The shift length have to be an integer as it is the number of samples.') |
|
|
90 |
disp(['shift length is fixed to ' num2str(ShiftLen)]) |
|
|
91 |
end |
|
|
92 |
|
|
|
93 |
[FreqRes, FrameNum]=size(XNEW); |
|
|
94 |
|
|
|
95 |
Spec=XNEW.*exp(1i*yphase); |
|
|
96 |
|
|
|
97 |
if mod(windowLen,2) %if FreqResol is odd |
|
|
98 |
Spec=[Spec;flipud(conj(Spec(2:end,:)))]; |
|
|
99 |
else |
|
|
100 |
Spec=[Spec;flipud(conj(Spec(2:end-1,:)))]; |
|
|
101 |
end |
|
|
102 |
sig=zeros((FrameNum-1)*ShiftLen+windowLen,1); |
|
|
103 |
weight=sig; |
|
|
104 |
for i=1:FrameNum |
|
|
105 |
start=(i-1)*ShiftLen+1; |
|
|
106 |
spec=Spec(:,i); |
|
|
107 |
sig(start:start+windowLen-1)=sig(start:start+windowLen-1)+real(ifft(spec,windowLen)); |
|
|
108 |
end |
|
|
109 |
ReconstructedSignal=sig; |
|
|
110 |
|
|
|
111 |
function Seg=segment(signal,W,SP,Window) |
|
|
112 |
|
|
|
113 |
if nargin<3 |
|
|
114 |
SP=.4; |
|
|
115 |
end |
|
|
116 |
if nargin<2 |
|
|
117 |
W=256; |
|
|
118 |
end |
|
|
119 |
if nargin<4 |
|
|
120 |
Window=hamming(W); |
|
|
121 |
end |
|
|
122 |
Window=Window(:); %make it a column vector |
|
|
123 |
|
|
|
124 |
L=length(signal); |
|
|
125 |
SP=fix(W.*SP); |
|
|
126 |
N=fix((L-W)/SP +1); %number of segments |
|
|
127 |
|
|
|
128 |
Index=(repmat(1:W,N,1)+repmat((0:(N-1))'*SP,1,W))'; |
|
|
129 |
hw=repmat(Window,1,N); |
|
|
130 |
Seg=signal(Index).*hw; |
|
|
131 |
|
|
|
132 |
function [NoiseFlag, SpeechFlag, NoiseCounter, Dist]=vad(signal,noise,NoiseCounter,NoiseMargin,Hangover) |
|
|
133 |
|
|
|
134 |
if nargin<4 |
|
|
135 |
NoiseMargin=3; |
|
|
136 |
end |
|
|
137 |
if nargin<5 |
|
|
138 |
Hangover=8; |
|
|
139 |
end |
|
|
140 |
if nargin<3 |
|
|
141 |
NoiseCounter=0; |
|
|
142 |
end |
|
|
143 |
|
|
|
144 |
FreqResol=length(signal); |
|
|
145 |
|
|
|
146 |
SpectralDist= 20*(log10(signal)-log10(noise)); |
|
|
147 |
SpectralDist(SpectralDist<0)=0; |
|
|
148 |
|
|
|
149 |
Dist=mean(SpectralDist); |
|
|
150 |
if (Dist < NoiseMargin) |
|
|
151 |
NoiseFlag=1; |
|
|
152 |
NoiseCounter=NoiseCounter+1; |
|
|
153 |
else |
|
|
154 |
NoiseFlag=0; |
|
|
155 |
NoiseCounter=0; |
|
|
156 |
end |
|
|
157 |
|
|
|
158 |
% Detect noise only periods and attenuate the signal |
|
|
159 |
if (NoiseCounter > Hangover) |
|
|
160 |
SpeechFlag=0; |
|
|
161 |
else |
|
|
162 |
SpeechFlag=1; |
|
|
163 |
end |