Dawn@4
|
1 function [HNR05, HNR15, HNR25, HNR35] = func_GetHNR(y, Fs, F0, variables)
|
Dawn@4
|
2 % N = func_GetHNR(y, Fs, F0, variables, textgridfile
|
Dawn@4
|
3 % Input: y, Fs - from wavread
|
Dawn@4
|
4 % F0 - vector of fundamental frequencies
|
Dawn@4
|
5 % variables - global settings
|
Dawn@4
|
6 % textgridfile - this is optional
|
Dawn@4
|
7 % Output: N vectors
|
Dawn@4
|
8 % Notes: Calculates the Harmonic to noise ratio based on the method
|
Dawn@4
|
9 % described in de Krom, 1993 - A cepstrum-based technique for determining a
|
Dawn@4
|
10 % harmonic-to-noise ratio in speech signals, JSHR.
|
Dawn@4
|
11 %
|
Dawn@4
|
12 % Author: Yen-Liang Shue, Speech Processing and Auditory Perception Laboratory, UCLA
|
Dawn@4
|
13 % Copyright UCLA SPAPL 2009
|
Dawn@4
|
14
|
Dawn@4
|
15 N_periods = variables.Nperiods_EC;
|
Dawn@4
|
16 sampleshift = (Fs / 1000 * variables.frameshift);
|
Dawn@4
|
17
|
Dawn@4
|
18 HNR05 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
19 HNR15 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
20 HNR25 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
21 HNR35 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
22
|
Dawn@4
|
23
|
Dawn@4
|
24 for k=1:length(F0)
|
Dawn@4
|
25 ks = round(k * sampleshift);
|
Dawn@4
|
26
|
Dawn@4
|
27 if (ks <= 0 || ks > length(y))
|
Dawn@4
|
28 continue;
|
Dawn@4
|
29 end
|
Dawn@4
|
30
|
Dawn@4
|
31 F0_curr = F0(k);
|
Dawn@4
|
32 N0_curr = 1 / F0_curr * Fs;
|
Dawn@4
|
33
|
Dawn@4
|
34 if (isnan(F0_curr))
|
Dawn@4
|
35 continue;
|
Dawn@4
|
36 end
|
Dawn@4
|
37
|
Dawn@4
|
38 ystart = round(ks - N_periods/2*N0_curr);
|
Dawn@4
|
39 yend = round(ks + N_periods/2*N0_curr) - 1;
|
Dawn@4
|
40
|
Dawn@4
|
41 if (mod(yend - ystart + 1, 2) == 0) % length is even, make it odd
|
Dawn@4
|
42 yend = yend - 1;
|
Dawn@4
|
43 end
|
Dawn@4
|
44
|
Dawn@4
|
45 if (ystart <= 0)
|
Dawn@4
|
46 continue;
|
Dawn@4
|
47 end;
|
Dawn@4
|
48
|
Dawn@4
|
49 if (yend > length(y))
|
Dawn@4
|
50 continue;
|
Dawn@4
|
51 end;
|
Dawn@4
|
52
|
Dawn@4
|
53 yseg = y(ystart:yend);
|
Dawn@4
|
54
|
Dawn@4
|
55
|
Dawn@4
|
56 hnr = getHNR(yseg, F0_curr, Fs, [500 1500 2500 3500]);
|
Dawn@4
|
57
|
Dawn@4
|
58 HNR05(k) = hnr(1);
|
Dawn@4
|
59 HNR15(k) = hnr(2);
|
Dawn@4
|
60 HNR25(k) = hnr(3);
|
Dawn@4
|
61 HNR35(k) = hnr(4);
|
Dawn@4
|
62
|
Dawn@4
|
63 end
|
Dawn@4
|
64
|
Dawn@4
|
65
|
Dawn@4
|
66 % main processing function
|
Dawn@4
|
67 function n = getHNR(y, F0, Fs, Nfreqs)
|
Dawn@4
|
68
|
Dawn@4
|
69 NBins = length(y);
|
Dawn@4
|
70 N0 = round(Fs / F0);
|
Dawn@4
|
71 N0_delta = round(N0 * 0.1); % search 10% either side
|
Dawn@4
|
72
|
Dawn@4
|
73 y = y .* hamming(length(y));
|
Dawn@4
|
74 Y = fft(y, NBins);
|
Dawn@4
|
75 aY = log10(abs(Y));
|
Dawn@4
|
76 ay = ifft(aY);
|
Dawn@4
|
77
|
Dawn@4
|
78 % find possible rahmonic peaks
|
Dawn@4
|
79 peakinx = zeros(floor(length(y)/ 2 / N0), 1);
|
Dawn@4
|
80 for k=1:length(peakinx)
|
Dawn@4
|
81 ayseg = ay(k*N0 - N0_delta : k*N0 + N0_delta);
|
Dawn@4
|
82 [val, inx] = max(abs(ayseg));
|
Dawn@4
|
83 peakinx(k) = inx + k*N0 - N0_delta - 1;
|
Dawn@4
|
84
|
Dawn@4
|
85 % lifter out each rahmonic peak
|
Dawn@4
|
86 s_ayseg = sign(diff(ayseg));
|
Dawn@4
|
87
|
Dawn@4
|
88 % find first derivative sign change
|
Dawn@4
|
89 l_inx = inx - find((s_ayseg(inx-1:-1:1) ~= sign(inx)), 1) + 1;
|
Dawn@4
|
90 r_inx = inx + find((s_ayseg(inx+1:end) == sign(inx)), 1);
|
Dawn@4
|
91
|
Dawn@4
|
92 l_inx = l_inx + k*N0 - N0_delta - 1;
|
Dawn@4
|
93 r_inx = r_inx + k*N0 - N0_delta - 1;
|
Dawn@4
|
94
|
Dawn@4
|
95 % lifter out the peak
|
Dawn@4
|
96 ay(l_inx:r_inx) = 0;
|
Dawn@4
|
97
|
Dawn@4
|
98 end
|
Dawn@4
|
99
|
Dawn@4
|
100 % put the signal back together
|
Dawn@4
|
101 midL = round(length(y) / 2) + 1;
|
Dawn@4
|
102 ay(midL : end) = ay(midL - 1: -1 : midL - 1 - (length(ay) - midL));
|
Dawn@4
|
103
|
Dawn@4
|
104 Nap = real(fft(ay));
|
Dawn@4
|
105 N = Nap;
|
Dawn@4
|
106 Ha = aY - Nap; % approximated harmonic spectrum
|
Dawn@4
|
107
|
Dawn@4
|
108 % calculate baseline corrections
|
Dawn@4
|
109 Hdelta = F0 / Fs * length(y);
|
Dawn@4
|
110 for f=Hdelta+0.0001:Hdelta:round(length(y)/2)
|
Dawn@4
|
111 fstart = ceil(f - Hdelta);
|
Dawn@4
|
112
|
Dawn@4
|
113 Bdf = abs(min(Ha(fstart:round(f))));
|
Dawn@4
|
114 N(fstart:round(f)) = N(fstart:round(f)) - Bdf;
|
Dawn@4
|
115 end
|
Dawn@4
|
116
|
Dawn@4
|
117 % calculate the average HNR for Nfreqs
|
Dawn@4
|
118 H = aY - N; %note that N is valid only for 1:length(N)/2
|
Dawn@4
|
119 n = zeros(length(Nfreqs), 1);
|
Dawn@4
|
120 for k=1:length(Nfreqs)
|
Dawn@4
|
121 Ef = round(Nfreqs(k) / Fs * length(y)); % equivalent cut off frequency
|
Dawn@4
|
122 n(k) = 20*mean(H(1:Ef)) - 20*mean(N(1:Ef));
|
Dawn@4
|
123 end
|
Dawn@4
|
124
|
Dawn@4
|
125
|
Dawn@4
|
126
|
Dawn@4
|
127
|