annotate 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
rev   line source
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