comparison Code/Descriptors/Matlab/MPEG7/FromWeb/VoiceSauce/func_GetHNR.m @ 4:92ca03a8fa99 tip

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