Dawn@4
|
1 function [A1, A2, A3] = func_GetA1A2A3(y, Fs, F0, F1, F2, F3, variables, textgridfile)
|
Dawn@4
|
2 % [A1, A2, A3] = func_GetA1A2A3(y, Fs, F0, F1, F2, F3, variables, textgridfile)
|
Dawn@4
|
3 % Input: y - input signal
|
Dawn@4
|
4 % Fs - sampling frequency
|
Dawn@4
|
5 % F0 - fundamental frequency (vector)
|
Dawn@4
|
6 % F1-F3 - formant frequencies (vectors)
|
Dawn@4
|
7 % variables - settings from VS
|
Dawn@4
|
8 % textgridfile - textgrid filename if available (optional)
|
Dawn@4
|
9 % Output: A1, A2, A3 - uncorrected amplitudes of the spectra at the formant
|
Dawn@4
|
10 % frequencies.
|
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;
|
Dawn@4
|
16 sampleshift = (Fs / 1000 * variables.frameshift);
|
Dawn@4
|
17
|
Dawn@4
|
18 A1 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
19 A2 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
20 A3 = zeros(length(F0), 1) * NaN;
|
Dawn@4
|
21
|
Dawn@4
|
22 if (nargin == 7)
|
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
|
Dawn@4
|
33 if (isnan(F0_curr) || F0_curr == 0)
|
Dawn@4
|
34 continue;
|
Dawn@4
|
35 end
|
Dawn@4
|
36
|
Dawn@4
|
37 N0_curr = 1 / F0_curr * Fs;
|
Dawn@4
|
38
|
Dawn@4
|
39 ystart = round(ks - N_periods/2*N0_curr);
|
Dawn@4
|
40 yend = round(ks + N_periods/2*N0_curr) - 1;
|
Dawn@4
|
41
|
Dawn@4
|
42 if (ystart <= 0)
|
Dawn@4
|
43 continue;
|
Dawn@4
|
44 end;
|
Dawn@4
|
45
|
Dawn@4
|
46 if (yend > length(y))
|
Dawn@4
|
47 continue;
|
Dawn@4
|
48 end;
|
Dawn@4
|
49
|
Dawn@4
|
50 yseg = y(ystart:yend);
|
Dawn@4
|
51
|
Dawn@4
|
52 % proceed if no NaNs detected
|
Dawn@4
|
53 if (~isnan(F1(k)) && ~isnan(F2(k)) && ~isnan(F3(k)) && ~isnan(N0_curr))
|
Dawn@4
|
54 [A1_, fmax] = ana_GetMagnitudeMax(yseg, F1(k), Fs, 8192);
|
Dawn@4
|
55 [A2_, fmax] = ana_GetMagnitudeMax(yseg, F2(k), Fs, 8192);
|
Dawn@4
|
56 [A3_, fmax] = ana_GetMagnitudeMax(yseg, F3(k), Fs, 8192);
|
Dawn@4
|
57
|
Dawn@4
|
58 A1(k) = A1_;
|
Dawn@4
|
59 A2(k) = A2_;
|
Dawn@4
|
60 A3(k) = A3_;
|
Dawn@4
|
61 end
|
Dawn@4
|
62 end
|
Dawn@4
|
63 else
|
Dawn@4
|
64 % use textgrids - get ignore string list
|
Dawn@4
|
65 tbuffer = variables.tbuffer;
|
Dawn@4
|
66 ignorelabels = textscan(variables.TextgridIgnoreList, '%s', 'delimiter', ',');
|
Dawn@4
|
67 ignorelabels = ignorelabels{1};
|
Dawn@4
|
68
|
Dawn@4
|
69 [labels, start, stop] = func_readTextgrid(textgridfile);
|
Dawn@4
|
70 labels_tmp = [];
|
Dawn@4
|
71 start_tmp = [];
|
Dawn@4
|
72 stop_tmp = [];
|
Dawn@4
|
73
|
Dawn@4
|
74 for k=1:length(variables.TextgridTierNumber)
|
Dawn@4
|
75 inx = variables.TextgridTierNumber(k);
|
Dawn@4
|
76 if (inx <= length(labels))
|
Dawn@4
|
77 labels_tmp = [labels_tmp; labels{inx}];
|
Dawn@4
|
78 start_tmp = [start_tmp; start{inx}];
|
Dawn@4
|
79 stop_tmp = [stop_tmp; stop{inx}];
|
Dawn@4
|
80 end
|
Dawn@4
|
81 end
|
Dawn@4
|
82
|
Dawn@4
|
83 labels = labels_tmp;
|
Dawn@4
|
84 start = start_tmp;
|
Dawn@4
|
85 stop = stop_tmp;
|
Dawn@4
|
86
|
Dawn@4
|
87
|
Dawn@4
|
88 for m=1:length(start)
|
Dawn@4
|
89 switch(labels{m})
|
Dawn@4
|
90 case ignorelabels
|
Dawn@4
|
91 continue; % skip anything that is within the ignore list
|
Dawn@4
|
92 end
|
Dawn@4
|
93
|
Dawn@4
|
94 kstart = round((start(m) * 1000 - tbuffer) / variables.frameshift);
|
Dawn@4
|
95 kstop = round((stop(m) * 1000 + tbuffer) / variables.frameshift);
|
Dawn@4
|
96 kstart(kstart <= 0) = 1;
|
Dawn@4
|
97 kstop(kstop > length(F0)) = length(F0);
|
Dawn@4
|
98
|
Dawn@4
|
99 ystart = round(kstart * sampleshift);
|
Dawn@4
|
100 ystop = round(kstop * sampleshift);
|
Dawn@4
|
101 ystart(ystart <= 0) = 1;
|
Dawn@4
|
102 ystop(ystop > length(y)) = length(y);
|
Dawn@4
|
103
|
Dawn@4
|
104 ysegment = y(ystart:ystop);
|
Dawn@4
|
105 F0seg = F0(kstart:kstop);
|
Dawn@4
|
106 F1seg = F1(kstart:kstop);
|
Dawn@4
|
107 F2seg = F2(kstart:kstop);
|
Dawn@4
|
108 F3seg = F3(kstart:kstop);
|
Dawn@4
|
109
|
Dawn@4
|
110 for k=1:length(F0seg)
|
Dawn@4
|
111 ks = round(k*sampleshift);
|
Dawn@4
|
112
|
Dawn@4
|
113 if (ks <= 0 || ks > length(ysegment))
|
Dawn@4
|
114 continue;
|
Dawn@4
|
115 end
|
Dawn@4
|
116
|
Dawn@4
|
117 F0_curr = F0seg(k);
|
Dawn@4
|
118 if (isnan(F0_curr) || F0_curr == 0)
|
Dawn@4
|
119 continue;
|
Dawn@4
|
120 end
|
Dawn@4
|
121
|
Dawn@4
|
122 N0_curr = Fs/F0_curr;
|
Dawn@4
|
123 ysstart = round(ks - N_periods/2 * N0_curr);
|
Dawn@4
|
124 ysend = round(ks + N_periods/2 * N0_curr) - 1;
|
Dawn@4
|
125
|
Dawn@4
|
126 if (isnan(F1seg(k)) || isnan(F2seg(k)) || isnan(F3seg(k)))
|
Dawn@4
|
127 continue;
|
Dawn@4
|
128 end
|
Dawn@4
|
129
|
Dawn@4
|
130 if (ysstart <= 0)
|
Dawn@4
|
131 continue;
|
Dawn@4
|
132 end;
|
Dawn@4
|
133 if (ysend > length(ysegment))
|
Dawn@4
|
134 continue;
|
Dawn@4
|
135 end;
|
Dawn@4
|
136
|
Dawn@4
|
137 yseg = ysegment(ysstart:ysend);
|
Dawn@4
|
138
|
Dawn@4
|
139 [A1_, fmax] = ana_GetMagnitudeMax(yseg, F1seg(k), Fs, 8192);
|
Dawn@4
|
140 [A2_, fmax] = ana_GetMagnitudeMax(yseg, F2seg(k), Fs, 8192);
|
Dawn@4
|
141 [A3_, fmax] = ana_GetMagnitudeMax(yseg, F3seg(k), Fs, 8192);
|
Dawn@4
|
142
|
Dawn@4
|
143 inx = kstart + k - 1;
|
Dawn@4
|
144 if (inx <= length(A1))
|
Dawn@4
|
145 A1(inx) = A1_;
|
Dawn@4
|
146 A2(inx) = A2_;
|
Dawn@4
|
147 A3(inx) = A3_;
|
Dawn@4
|
148 end
|
Dawn@4
|
149
|
Dawn@4
|
150 end
|
Dawn@4
|
151
|
Dawn@4
|
152 end
|
Dawn@4
|
153 end
|
Dawn@4
|
154
|
Dawn@4
|
155
|
Dawn@4
|
156 %------------------------------------------------------------------------
|
Dawn@4
|
157 function [M,fmax] = ana_GetMagnitudeMax(x, Fx, Fs, fftlen)
|
Dawn@4
|
158 % Get maximal spectral magnitude of signal x around position Fx Hz in dB
|
Dawn@4
|
159 % Fx can be a vector of frequency points
|
Dawn@4
|
160 % Note that the bigger fftlen the better the resolution
|
Dawn@4
|
161
|
Dawn@4
|
162 if (isnan(Fx))
|
Dawn@4
|
163 M = NaN;
|
Dawn@4
|
164 fmax = NaN;
|
Dawn@4
|
165 else
|
Dawn@4
|
166
|
Dawn@4
|
167 len = length(x);
|
Dawn@4
|
168 hamlen = min(fftlen, len);
|
Dawn@4
|
169 %X = fft(hamming(hamlen).*x(1:hamlen), fftlen);
|
Dawn@4
|
170 factor = 1; %/length(x); % not exactly Kosher but compatible to dfs_magn()
|
Dawn@4
|
171 X = fft(x,fftlen);
|
Dawn@4
|
172 X(X==0) = 0.000000001; % guard against log(0) warnings
|
Dawn@4
|
173 X = 20*log10(factor*abs(X(1:fftlen/2, :)));
|
Dawn@4
|
174 fstep = Fs / fftlen;
|
Dawn@4
|
175 lowf = Fx-0.1*Fx;
|
Dawn@4
|
176 if (lowf<0) lowf=0; end
|
Dawn@4
|
177 highf = Fx+0.1*Fx;
|
Dawn@4
|
178 if (highf>Fs/2-fstep) highf=Fs/2-fstep; end
|
Dawn@4
|
179
|
Dawn@4
|
180 for cnt = 1:length(Fx)
|
Dawn@4
|
181 [M(cnt),pos] = max(X(1+round(lowf(cnt)/fstep):1+round(highf(cnt)/fstep), :));
|
Dawn@4
|
182 fmax(cnt) = (pos-1+round(lowf(cnt)/fstep))*fstep;
|
Dawn@4
|
183 end
|
Dawn@4
|
184
|
Dawn@4
|
185 end
|
Dawn@4
|
186
|
Dawn@4
|
187 % f=0:fstep:(Fs/2-fstep);
|
Dawn@4
|
188 % plot(f,X); hold;
|
Dawn@4
|
189 % plot(pos, M, 'rx'); hold off;
|
Dawn@4
|
190 % fprintf('End get_magnitude_max()\n');
|