rmeddis@38
|
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
rmeddis@38
|
2 % This program is free software; you can redistribute it and/or modify
|
rmeddis@38
|
3 % it under the terms of the GNU General Public License as published by
|
rmeddis@38
|
4 % the Free Software Foundation; either version 2 of the License, or
|
rmeddis@38
|
5 % (at your option) any later version.
|
rmeddis@38
|
6 %
|
rmeddis@38
|
7 % This program is distributed in the hope that it will be useful,
|
rmeddis@38
|
8 % but WITHOUT ANY WARRANTY; without even the implied warranty of
|
rmeddis@38
|
9 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
rmeddis@38
|
10 % GNU General Public License for more details.
|
rmeddis@38
|
11 %
|
rmeddis@38
|
12 % You can obtain a copy of the GNU General Public License from
|
rmeddis@38
|
13 % http://www.gnu.org/copyleft/gpl.html or by writing to
|
rmeddis@38
|
14 % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
|
rmeddis@38
|
15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
rmeddis@38
|
16
|
rmeddis@38
|
17 classdef cJob
|
rmeddis@38
|
18 %CJOB Responsible for conversion of wav files into recogniser features
|
rmeddis@38
|
19 % Please see the documentation located in a separate file for further
|
rmeddis@38
|
20 % information.
|
rmeddis@38
|
21
|
rmeddis@38
|
22 %% *********************************************************
|
rmeddis@38
|
23 % properties _ _
|
rmeddis@38
|
24 % | | (_)
|
rmeddis@38
|
25 % _ __ _ __ ___ _ __ ___ _ __| |_ _ ___ ___
|
rmeddis@38
|
26 % | '_ \| '__/ _ \| '_ \ / _ \ '__| __| |/ _ \/ __|
|
rmeddis@38
|
27 % | |_) | | | (_) | |_) | __/ | | |_| | __/\__ \
|
rmeddis@38
|
28 % | .__/|_| \___/| .__/ \___|_| \__|_|\___||___/
|
rmeddis@38
|
29 % | | | |
|
rmeddis@38
|
30 % |_| |_|
|
rmeddis@38
|
31 %************************************************************
|
rmeddis@38
|
32
|
rmeddis@38
|
33 %% **********************************************************
|
rmeddis@38
|
34 % Public properties - can be set by user
|
rmeddis@38
|
35 %************************************************************
|
rmeddis@38
|
36 properties(Access = public)
|
rmeddis@38
|
37 wavFolder
|
rmeddis@38
|
38 opFolder
|
rmeddis@38
|
39 noiseFolder
|
rmeddis@38
|
40
|
rmeddis@38
|
41 wavList
|
rmeddis@38
|
42 todoStatus
|
rmeddis@38
|
43
|
rmeddis@38
|
44
|
rmeddis@38
|
45 participant = 'Normal';%'DEMO2_multiSpont';
|
rmeddis@38
|
46 noiseName = '8TalkerBabble';
|
rmeddis@38
|
47 numWavs = 5;
|
rmeddis@38
|
48 noiseLevToUse = -200;
|
rmeddis@38
|
49 speechLevToUse = 50;
|
rmeddis@38
|
50
|
rmeddis@38
|
51 speechLevStd = 0;
|
rmeddis@38
|
52 noiseLevStd = 0;
|
rmeddis@38
|
53 freezeNoise = 0;
|
rmeddis@38
|
54 meanSNR = 20;
|
rmeddis@38
|
55 speechDist = 'None';
|
rmeddis@38
|
56 noiseDist = 'None';
|
rmeddis@38
|
57
|
rmeddis@38
|
58 noisePreDur = 0.0;
|
rmeddis@38
|
59 noisePostDur = 0.0;
|
rmeddis@38
|
60 truncateDur = 0.0; %Dr. RF used 0.550
|
rmeddis@38
|
61
|
rmeddis@38
|
62 currentSpeechLevel
|
rmeddis@38
|
63 currentNoiseLevel
|
rmeddis@38
|
64
|
rmeddis@38
|
65
|
rmeddis@38
|
66 useSpectrogram = false;
|
rmeddis@38
|
67 numCoeff = 9;
|
rmeddis@38
|
68
|
rmeddis@38
|
69 %************************************************************
|
rmeddis@38
|
70 % plotting handles
|
rmeddis@38
|
71 %************************************************************
|
rmeddis@38
|
72 probHaxes = [];
|
rmeddis@38
|
73 probHaxesSM = [];
|
rmeddis@38
|
74 sacfHaxes = [];
|
rmeddis@38
|
75 sacfHaxesSM = [];
|
rmeddis@38
|
76 featHaxes = [];
|
rmeddis@38
|
77 reconHaxes = [];
|
rmeddis@38
|
78
|
rmeddis@38
|
79 %************************************************************
|
rmeddis@38
|
80 % SACF params
|
rmeddis@38
|
81 %************************************************************
|
rmeddis@38
|
82 useSACF = false;
|
rmeddis@38
|
83 SACFacfTau = 2; % > 1 = Wiegrebe mode
|
rmeddis@38
|
84 SACFnBins = 128;
|
rmeddis@38
|
85 SACFminLag = 1 / 4000;
|
rmeddis@38
|
86 SACFmaxLag = 1 / 50;
|
rmeddis@38
|
87 SACFlambda = 10e-3;
|
rmeddis@38
|
88
|
rmeddis@38
|
89 %************************************************************
|
rmeddis@38
|
90 % MAP params
|
rmeddis@38
|
91 %************************************************************
|
rmeddis@38
|
92 MAProot = fullfile('..');
|
rmeddis@38
|
93 MAPplotGraphs = 0;
|
rmeddis@38
|
94 MAPDRNLSave = 0;
|
rmeddis@38
|
95
|
rmeddis@38
|
96 MAPopLSR = 0;
|
rmeddis@38
|
97 MAPopMSR = 0;
|
rmeddis@38
|
98 MAPopHSR = 1;
|
rmeddis@38
|
99
|
rmeddis@38
|
100 MAPparamChanges = {};
|
rmeddis@38
|
101
|
rmeddis@38
|
102 %************************************************************
|
rmeddis@38
|
103 % HTK stuff - writing to HTK recogniser format
|
rmeddis@38
|
104 %************************************************************
|
rmeddis@38
|
105 frameshift = 10; % shift between frames (ms)
|
rmeddis@38
|
106 sampPeriodFromMsFactor = 10000; % appropriate for 10ms frame rate
|
rmeddis@38
|
107 paramKind = 9; % HTK USER format for user-defined features (p73 of HTK book)
|
rmeddis@38
|
108
|
rmeddis@38
|
109 removeEnergyStatic = false;
|
rmeddis@38
|
110 doCMN = false; % Cepstral mean normalisation
|
rmeddis@38
|
111
|
rmeddis@38
|
112 %************************************************************
|
rmeddis@38
|
113 % Portable EssexAid params
|
rmeddis@38
|
114 %************************************************************
|
rmeddis@38
|
115 bwOct = 1/1;
|
rmeddis@38
|
116 filterOrder = 2;
|
rmeddis@38
|
117
|
rmeddis@38
|
118 mainGain = [ 1; 1; 1; 1; 1]; % gain in linear units
|
rmeddis@38
|
119 TCdBO = [40; 40; 40; 40; 40]; %Compression thresholds (in dB OUTPUT from 2nd filt)
|
rmeddis@38
|
120 TMdBO = [10; 10; 10; 10; 10]; %MOC thresholds (in dB OUTPUT from 2nd filt)
|
rmeddis@38
|
121 DRNLc = [ 0.2; 0.2; 0.2; 0.2; 0.2;]
|
rmeddis@38
|
122
|
rmeddis@38
|
123 ARtau = 0.03; % decay time constant
|
rmeddis@38
|
124 ARthresholddB = 85; % dB SPL (input signal level) =>200 to disable
|
rmeddis@38
|
125 MOCtau = 0.3;
|
rmeddis@38
|
126 MOCfactor = 0.5; %dB per dB OUTPUT
|
rmeddis@38
|
127
|
rmeddis@38
|
128 numSamples = 1024; %MAX=6912
|
rmeddis@38
|
129 useAid = 0;
|
rmeddis@38
|
130 end
|
rmeddis@38
|
131
|
rmeddis@38
|
132 %% *********************************************************
|
rmeddis@38
|
133 % Protected properties - inter/ra class communication
|
rmeddis@38
|
134 %************************************************************
|
rmeddis@38
|
135 properties(Access = protected)
|
rmeddis@38
|
136 jobLockFid % File identifier for mutex
|
rmeddis@38
|
137
|
rmeddis@38
|
138 %Nick C comment on this:
|
rmeddis@38
|
139 %OK. The big-endian thing used to work because in the config file
|
rmeddis@38
|
140 %'config_tr_zcpa12' there was a flag called NATURALREADORDER that was set to
|
rmeddis@38
|
141 %FALSE and thus appeared to override x86 standard:
|
rmeddis@38
|
142 %little-endian. Endianess has **!nothing!** to do with win vs *nix
|
rmeddis@38
|
143 byteOrder = 'le'; % byte order is big endian
|
rmeddis@38
|
144 end
|
rmeddis@38
|
145 properties(Dependent = true)
|
rmeddis@38
|
146 jobLockTxtFile
|
rmeddis@38
|
147 end
|
rmeddis@38
|
148
|
rmeddis@38
|
149 %% *********************************************************
|
rmeddis@38
|
150 % methods _ _ _
|
rmeddis@38
|
151 % | | | | | |
|
rmeddis@38
|
152 % _ __ ___ ___| |_| |__ ___ __| |___
|
rmeddis@38
|
153 %| '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
|
rmeddis@38
|
154 %| | | | | | __/ |_| | | | (_) | (_| \__ \
|
rmeddis@38
|
155 %|_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
|
rmeddis@38
|
156 %************************************************************
|
rmeddis@38
|
157
|
rmeddis@38
|
158 methods
|
rmeddis@38
|
159 %% **********************************************************
|
rmeddis@38
|
160 % Constructor
|
rmeddis@38
|
161 %************************************************************
|
rmeddis@38
|
162 function obj = cJob(LearnOrRecWavs, jobFolder)
|
rmeddis@38
|
163 if nargin < 1
|
rmeddis@38
|
164 warning('job:ambiguouscorpus',...
|
rmeddis@38
|
165 'We need to know whether the (L)earning or (R)ecognition corpus is being used, assuming ''L''');
|
rmeddis@38
|
166 LearnOrRecWavs = 'L';
|
rmeddis@38
|
167 end
|
rmeddis@38
|
168 if nargin > 1
|
rmeddis@38
|
169 obj.opFolder = jobFolder;
|
rmeddis@38
|
170 else
|
rmeddis@38
|
171 if isunix
|
rmeddis@38
|
172 if ismac
|
rmeddis@38
|
173 obj.opFolder = '~/ASR/exps/_foo';
|
rmeddis@38
|
174 else
|
rmeddis@38
|
175 obj.opFolder = '/scratch/nrclark/exps/_foo';
|
rmeddis@38
|
176 end
|
rmeddis@38
|
177 else
|
rmeddis@38
|
178 obj.opFolder = 'D:\exps\_foo';
|
rmeddis@38
|
179 end
|
rmeddis@38
|
180 end
|
rmeddis@38
|
181
|
rmeddis@38
|
182 obj = obj.assignWavPaths(LearnOrRecWavs);
|
rmeddis@38
|
183 obj = obj.initMAP;
|
rmeddis@38
|
184
|
rmeddis@38
|
185
|
rmeddis@38
|
186 end % ------ OF CONSTRUCTOR
|
rmeddis@38
|
187
|
rmeddis@38
|
188 %% **********************************************************
|
rmeddis@38
|
189 % Set Wav Paths
|
rmeddis@38
|
190 %************************************************************
|
rmeddis@38
|
191 function obj = assignWavPaths(obj, LearnOrRecWavs)
|
rmeddis@38
|
192 if isunix
|
rmeddis@38
|
193 if ismac
|
rmeddis@38
|
194 lWAVpath = fullfile('demo_wavs', 'TrainingData-Clean');
|
rmeddis@38
|
195 rWAVpath = fullfile('demo_wavs', 'TripletTestData');
|
rmeddis@38
|
196 obj.noiseFolder = fullfile('demo_wavs', 'noises');
|
rmeddis@38
|
197 else
|
rmeddis@38
|
198 lWAVpath = fullfile('demo_wavs', 'TrainingData-Clean');
|
rmeddis@38
|
199 rWAVpath = fullfile('demo_wavs', 'TripletTestData');
|
rmeddis@38
|
200 obj.noiseFolder = fullfile('demo_wavs', 'noises');
|
rmeddis@38
|
201 end
|
rmeddis@38
|
202 else
|
rmeddis@38
|
203 lWAVpath = 'D:\AURORA digits (wav)\TrainingData-Clean';
|
rmeddis@38
|
204 rWAVpath = 'D:\AURORA digits (wav)\TripletTestData';
|
rmeddis@38
|
205 obj.noiseFolder = 'D:\AURORA digits (wav)\noises';
|
rmeddis@38
|
206 end
|
rmeddis@38
|
207
|
rmeddis@38
|
208 if strcmpi(LearnOrRecWavs, 'l')
|
rmeddis@38
|
209 obj.wavFolder = lWAVpath;
|
rmeddis@38
|
210 elseif strcmpi(LearnOrRecWavs, 'r')
|
rmeddis@38
|
211 obj.wavFolder = rWAVpath;
|
rmeddis@38
|
212 else
|
rmeddis@38
|
213 error('First argument to constructor must be ''L'' or ''R''');
|
rmeddis@38
|
214 end
|
rmeddis@38
|
215 end
|
rmeddis@38
|
216
|
rmeddis@38
|
217 %% **********************************************************
|
rmeddis@38
|
218 % mutex related _
|
rmeddis@38
|
219 % | |
|
rmeddis@38
|
220 % _ __ ___ _ _| |_ _____ __
|
rmeddis@38
|
221 % | '_ ` _ \| | | | __/ _ \ \/ /
|
rmeddis@38
|
222 % | | | | | | |_| | || __/> <
|
rmeddis@38
|
223 % |_| |_| |_|\__,_|\__\___/_/\_\
|
rmeddis@38
|
224 %************************************************************
|
rmeddis@38
|
225
|
rmeddis@38
|
226 %% **********************************************************
|
rmeddis@38
|
227 % lockJobList - File mutex protecting from race conditions
|
rmeddis@38
|
228 %************************************************************
|
rmeddis@38
|
229 function obj = lockJobList(obj)
|
rmeddis@38
|
230 lockON = false;
|
rmeddis@38
|
231 while (~lockON)
|
rmeddis@38
|
232 if numel(dir(obj.jobLockTxtFile)) %Check to see if lock already in place
|
rmeddis@38
|
233 wTime = randi(750)+250; %3,000-10,000 ms
|
rmeddis@38
|
234 disp(['File mutex in place. Retrying in ' num2str(wTime) ' ms'])
|
rmeddis@38
|
235 pause(wTime/1000);
|
rmeddis@38
|
236 else
|
rmeddis@38
|
237 obj.jobLockFid = fopen(obj.jobLockTxtFile,'w');
|
rmeddis@38
|
238 disp('Job locked');
|
rmeddis@38
|
239 pause(50/1000);
|
rmeddis@38
|
240 lockON = true;
|
rmeddis@38
|
241 end
|
rmeddis@38
|
242 end
|
rmeddis@38
|
243 fclose(obj.jobLockFid);
|
rmeddis@38
|
244 end% ------ OF LOCKJOBLIST
|
rmeddis@38
|
245
|
rmeddis@38
|
246 %% **********************************************************
|
rmeddis@38
|
247 % unlockJobList - unlocks for other workers
|
rmeddis@38
|
248 %************************************************************
|
rmeddis@38
|
249 function obj = unlockJobList(obj)
|
rmeddis@38
|
250 lockON = logical(numel(dir(obj.jobLockTxtFile)));
|
rmeddis@38
|
251 while(lockON)
|
rmeddis@38
|
252 try
|
rmeddis@38
|
253 delete(obj.jobLockTxtFile);
|
rmeddis@38
|
254 disp('Job unlocked');
|
rmeddis@38
|
255 pause(50/1000);
|
rmeddis@38
|
256 lockON = false;
|
rmeddis@38
|
257 catch %#ok<CTCH>
|
rmeddis@38
|
258 disp('Unjamming lock - retrying immediately')
|
rmeddis@38
|
259 pause(200/1000)
|
rmeddis@38
|
260 end
|
rmeddis@38
|
261 end
|
rmeddis@38
|
262 end% ------ OF UNLOCKJOBLIST
|
rmeddis@38
|
263
|
rmeddis@38
|
264 %% **********************************************************
|
rmeddis@38
|
265 % storeSelf - save a copy of this object in opFolder
|
rmeddis@38
|
266 %************************************************************
|
rmeddis@38
|
267 function storeSelf(obj)
|
rmeddis@38
|
268 doneSaving = false;
|
rmeddis@38
|
269 while(~doneSaving)
|
rmeddis@38
|
270 try
|
rmeddis@38
|
271 save(fullfile(obj.opFolder, 'jobObject'), 'obj');
|
rmeddis@38
|
272 doneSaving = true;
|
rmeddis@38
|
273 catch %#ok<CTCH>
|
rmeddis@38
|
274 wTime = randi(3800)+200; %200-4000 ms
|
rmeddis@38
|
275 disp(['Save collision (THIS IS VERY VERY BAD - have you not used the mutex?). Retrying in ' num2str(wTime) ' ms']);
|
rmeddis@38
|
276 pause(wTime/1000);
|
rmeddis@38
|
277 end
|
rmeddis@38
|
278 end
|
rmeddis@38
|
279 end % ------ OF STORESELF
|
rmeddis@38
|
280
|
rmeddis@38
|
281 %% **********************************************************
|
rmeddis@38
|
282 % loadSelf - load a copy of this object from opFolder
|
rmeddis@38
|
283 %************************************************************
|
rmeddis@38
|
284 function obj = loadSelf(obj)
|
rmeddis@38
|
285 doneLoading = false;
|
rmeddis@38
|
286 while(~doneLoading)
|
rmeddis@38
|
287 try
|
rmeddis@38
|
288 load(fullfile(obj.opFolder,'jobObject'));
|
rmeddis@38
|
289 doneLoading = true;
|
rmeddis@38
|
290 catch %#ok<CTCH>
|
rmeddis@38
|
291 wTime = randi(3800)+200; %200-4000 ms
|
rmeddis@38
|
292 disp(['Load collision (THIS IS VERY VERY BAD - have you not used the mutex?). Retrying in ' num2str(wTime) ' ms'])
|
rmeddis@38
|
293 pause(wTime/1000);
|
rmeddis@38
|
294 end
|
rmeddis@38
|
295 end
|
rmeddis@38
|
296 end% ------ OF LOADSELF
|
rmeddis@38
|
297
|
rmeddis@38
|
298
|
rmeddis@38
|
299 %% *********************************************************
|
rmeddis@38
|
300 % _ _ _
|
rmeddis@38
|
301 % | | | | (_)
|
rmeddis@38
|
302 % | |__ ___ _ _ ___ ___| | _____ ___ _ __ _ _ __ __ _
|
rmeddis@38
|
303 % | '_ \ / _ \| | | / __|/ _ \ |/ / _ \/ _ \ '_ \| | '_ \ / _` |
|
rmeddis@38
|
304 % | | | | (_) | |_| \__ \ __/ < __/ __/ |_) | | | | | (_| |
|
rmeddis@38
|
305 % |_| |_|\___/ \__,_|___/\___|_|\_\___|\___| .__/|_|_| |_|\__, |
|
rmeddis@38
|
306 % | | __/ |
|
rmeddis@38
|
307 % |_| |___/
|
rmeddis@38
|
308 %************************************************************
|
rmeddis@38
|
309
|
rmeddis@38
|
310 %% **********************************************************
|
rmeddis@38
|
311 % get method for dependtent var jobLockTxtFile
|
rmeddis@38
|
312 %************************************************************
|
rmeddis@38
|
313 function value = get.jobLockTxtFile(obj)
|
rmeddis@38
|
314 %Name the MUTEX file here
|
rmeddis@38
|
315 value = [fullfile(obj.opFolder, 'jobLock') '.txt'];
|
rmeddis@38
|
316 end
|
rmeddis@38
|
317
|
rmeddis@38
|
318 %% **********************************************************
|
rmeddis@38
|
319 % checkStatus - see how much of the current job is complete
|
rmeddis@38
|
320 %************************************************************
|
rmeddis@38
|
321 function checkStatus(obj)
|
rmeddis@38
|
322 NOWopen = sum(obj.todoStatus==0); %Starting from R2010b, Matlab supports enumerations. For now, we resort to integers for compatibility.
|
rmeddis@38
|
323 NOWpend = sum(obj.todoStatus==1);
|
rmeddis@38
|
324 NOWdone = sum(obj.todoStatus==2);
|
rmeddis@38
|
325
|
rmeddis@38
|
326 zz = clock;
|
rmeddis@38
|
327 disp([num2str(zz(3)) '-' num2str(zz(2)) '-' num2str(zz(1)) ' ' num2str(zz(4)) ':' num2str(zz(5))])
|
rmeddis@38
|
328 disp(['CURRENT JOB:' obj.opFolder]);
|
rmeddis@38
|
329 disp(' ')
|
rmeddis@38
|
330 disp(['open - ' num2str(NOWopen) ' || pending - ' num2str(NOWpend) ' || complete - ' num2str(NOWdone)])
|
rmeddis@38
|
331
|
rmeddis@38
|
332 % ---- PROGRESS BAR ----
|
rmeddis@38
|
333 pcDone = 100*NOWdone/obj.numWavs;
|
rmeddis@38
|
334 progBarLength = 40;
|
rmeddis@38
|
335 charBars = repmat('=',1,floor(pcDone/100 * progBarLength));
|
rmeddis@38
|
336 charWhiteSpace = repmat(' ',1, progBarLength - numel(charBars));
|
rmeddis@38
|
337 disp(' ')
|
rmeddis@38
|
338 disp([' -[' charBars charWhiteSpace ']- ' num2str(pcDone, '%0.1f') '%'])
|
rmeddis@38
|
339 disp(' ')
|
rmeddis@38
|
340 disp(' ')
|
rmeddis@38
|
341 % -- END PROGRESS BAR ---
|
rmeddis@38
|
342 end% ------ OF CHECKSTATUS
|
rmeddis@38
|
343
|
rmeddis@38
|
344 %% **********************************************************
|
rmeddis@38
|
345 % initMAP - add MAP stuff to path
|
rmeddis@38
|
346 %************************************************************
|
rmeddis@38
|
347 function obj = initMAP(obj)
|
rmeddis@38
|
348 addpath(...fullfile(obj.MAProot, 'modules'),...
|
rmeddis@38
|
349 fullfile(obj.MAProot, 'utilities'),...
|
rmeddis@38
|
350 fullfile(obj.MAProot, 'MAP'),...
|
rmeddis@38
|
351 fullfile(obj.MAProot, 'parameterStore'));
|
rmeddis@38
|
352 end % ------ OF INIT MAP
|
rmeddis@38
|
353
|
rmeddis@38
|
354 %% **********************************************************
|
rmeddis@38
|
355 % assign files to testing and training sets
|
rmeddis@38
|
356 %************************************************************
|
rmeddis@38
|
357 function obj = assignFiles(obj)
|
rmeddis@38
|
358 speechWavs = dir(fullfile(obj.wavFolder, '*.wav'));
|
rmeddis@38
|
359 assert(obj.numWavs <= size(speechWavs, 1) ,...
|
rmeddis@38
|
360 'not enough files available in the corpus'); % make sure we have enough wavs
|
rmeddis@38
|
361
|
rmeddis@38
|
362 randomWavs = rand(1, size(speechWavs, 1));
|
rmeddis@38
|
363 [~,b] = sort(randomWavs);
|
rmeddis@38
|
364 trainFileIdx = b(1:obj.numWavs);
|
rmeddis@38
|
365
|
rmeddis@38
|
366 obj.wavList = speechWavs(trainFileIdx); %This is a record of all of the wavs that should be done
|
rmeddis@38
|
367
|
rmeddis@38
|
368 %Starting from R2010b, Matlab should support enumerated types. For now we
|
rmeddis@38
|
369 %use integers for compatibility.
|
rmeddis@38
|
370 %0=open, 1=processing, 2=done
|
rmeddis@38
|
371 obj.todoStatus = zeros(numel(obj.wavList), 1);
|
rmeddis@38
|
372
|
rmeddis@38
|
373 end % ------ OF ASSIGN FILES
|
rmeddis@38
|
374
|
rmeddis@38
|
375 %% **********************************************************
|
rmeddis@38
|
376 % generate feature
|
rmeddis@38
|
377 %************************************************************
|
rmeddis@38
|
378 function obj = genFeat(obj, currentWav)
|
rmeddis@38
|
379 fprintf(1,'Processing: %s \n', currentWav);
|
rmeddis@38
|
380 if strcmpi(obj.speechDist,'Gaussian')
|
rmeddis@38
|
381 tempSpeechLev = obj.speechLevToUse + obj.speechLevStd*randn;
|
rmeddis@38
|
382 elseif strcmpi(obj.speechDist,'Uniform')
|
rmeddis@38
|
383 % for a uniform distribution, the standard deviation is
|
rmeddis@38
|
384 % range/sqrt(12)
|
rmeddis@38
|
385 % http://mathforum.org/library/drmath/view/52066.html
|
rmeddis@38
|
386 tempSpeechLev = obj.speechLevToUse - obj.speechLevStd*sqrt(12)/2 + obj.speechLevStd*sqrt(12)*rand;
|
rmeddis@38
|
387 elseif strcmpi(obj.speechDist,'None')
|
rmeddis@38
|
388 tempSpeechLev = obj.speechLevToUse;
|
rmeddis@38
|
389 end
|
rmeddis@38
|
390
|
rmeddis@38
|
391 if strcmpi(obj.noiseDist,'Gaussian')
|
rmeddis@38
|
392 tempNoiseLev = speechLev - obj.meanSNR + obj.noiseLevStd*randn;
|
rmeddis@38
|
393 elseif strcmpi(obj.noiseDist,'Uniform')
|
rmeddis@38
|
394 tempNoiseLev = tempSpeechLev - obj.meanSNR - obj.noiseLevStd*sqrt(12)/2 + obj.noiseLevStd*sqrt(12)*rand;
|
rmeddis@38
|
395 elseif strcmpi(obj.noiseDist,'None')
|
rmeddis@38
|
396 tempNoiseLev = obj.noiseLevToUse;
|
rmeddis@38
|
397 end
|
rmeddis@38
|
398
|
rmeddis@38
|
399 disp(['Current speech level = ' num2str(tempSpeechLev)]);
|
rmeddis@38
|
400 disp(['Current noise level = ' num2str(tempNoiseLev)]);
|
rmeddis@38
|
401
|
rmeddis@38
|
402 obj.currentSpeechLevel = tempSpeechLev;
|
rmeddis@38
|
403 obj.currentNoiseLevel = tempNoiseLev;
|
rmeddis@38
|
404 [finalFeatures, ~] = processWavs(obj, currentWav); %discard the output from ANprobabilityResponse and method using ~
|
rmeddis@38
|
405 opForHTK(obj, currentWav, finalFeatures);
|
rmeddis@38
|
406 end % ------ OF GENFEAT
|
rmeddis@38
|
407
|
rmeddis@38
|
408 %% **********************************************************
|
rmeddis@38
|
409 % write o/p in HTK friendly format
|
rmeddis@38
|
410 %************************************************************
|
rmeddis@38
|
411 function obj = opForHTK(obj, currentWav, featureData)
|
rmeddis@38
|
412
|
rmeddis@38
|
413 featureName = strrep(currentWav, '.wav','.map');
|
rmeddis@38
|
414 targetFilename = fullfile(obj.opFolder, featureName);
|
rmeddis@38
|
415
|
rmeddis@38
|
416 % write in a format HTK compliant for the recogniser to use
|
rmeddis@38
|
417 obj.writeHTK(...
|
rmeddis@38
|
418 targetFilename,...
|
rmeddis@38
|
419 featureData,...
|
rmeddis@38
|
420 size(featureData,2),...
|
rmeddis@38
|
421 obj.frameshift*obj.sampPeriodFromMsFactor,...
|
rmeddis@38
|
422 size(featureData,1)*4,...
|
rmeddis@38
|
423 obj.paramKind,...
|
rmeddis@38
|
424 obj.byteOrder);
|
rmeddis@38
|
425 end % ------ OF opForHTK
|
rmeddis@38
|
426
|
rmeddis@38
|
427
|
rmeddis@38
|
428 %% **********************************************************
|
rmeddis@38
|
429 % _ _ _
|
rmeddis@38
|
430 % (_) | | (_)
|
rmeddis@38
|
431 % ___ _ __ _ _ __ __ _| | _ __ _ __ ___ ___ ___ ___ ___ _ _ __ __ _
|
rmeddis@38
|
432 % / __| |/ _` | '_ \ / _` | | | '_ \| '__/ _ \ / __/ _ \/ __/ __| | '_ \ / _` |
|
rmeddis@38
|
433 % \__ \ | (_| | | | | (_| | | | |_) | | | (_) | (_| __/\__ \__ \ | | | | (_| |
|
rmeddis@38
|
434 % |___/_|\__, |_| |_|\__,_|_| | .__/|_| \___/ \___\___||___/___/_|_| |_|\__, |
|
rmeddis@38
|
435 % __/ | | | __/ |
|
rmeddis@38
|
436 % |___/ |_| |___/
|
rmeddis@38
|
437 %************************************************************
|
rmeddis@38
|
438
|
rmeddis@38
|
439 %% **********************************************************
|
rmeddis@38
|
440 % getStimulus - what it says on the tin
|
rmeddis@38
|
441 %************************************************************
|
rmeddis@38
|
442 function [stimulus, sampleRate] = getStimulus(obj, currentWav)
|
rmeddis@38
|
443
|
rmeddis@38
|
444 % getStimulus.m - NC Aug 2010
|
rmeddis@38
|
445 % Modified version of Rob's script to include:
|
rmeddis@38
|
446 %
|
rmeddis@38
|
447 % 1)Signal and noise samples with different sample rate. The component with
|
rmeddis@38
|
448 % lower sample rate is upsampled to the rate of that with the
|
rmeddis@38
|
449 % higher rate.
|
rmeddis@38
|
450 % 2) Clearer level setting
|
rmeddis@38
|
451 % 3) Parameter to change noise intro duration
|
rmeddis@38
|
452 % 4) Noise padding at end of stimulus
|
rmeddis@38
|
453 %
|
rmeddis@38
|
454 % ORIGINAL HEADER:
|
rmeddis@38
|
455 % getStimulus.m
|
rmeddis@38
|
456 %
|
rmeddis@38
|
457 % Robert T. Ferry
|
rmeddis@38
|
458 % 13th May 2009
|
rmeddis@38
|
459
|
rmeddis@38
|
460 % Set levels
|
rmeddis@38
|
461 [speech speechSampleRate] = wavread(fullfile(obj.wavFolder, currentWav ));
|
rmeddis@38
|
462 speech = speech./sqrt(mean(speech.^2)); %Normalize RMS to 1
|
rmeddis@38
|
463 speech = speech * 20e-6 * 10^(obj.currentSpeechLevel/20); %Convert RMS to pascals at desired level
|
rmeddis@38
|
464 %disp(20*log10(sqrt(mean(speech.^2))/20e-6))
|
rmeddis@38
|
465
|
rmeddis@38
|
466 [noise noiseSampleRate] = wavread(fullfile(obj.noiseFolder, obj.noiseName ));
|
rmeddis@38
|
467 noise = noise./sqrt(mean(noise.^2)); %Normalize RMS to 1
|
rmeddis@38
|
468 noise = noise * 20e-6*10^(obj.currentNoiseLevel/20); %Convert RMS to pascals at desired level
|
rmeddis@38
|
469 %disp(20*log10(sqrt(mean(noise.^2))/20e-6))
|
rmeddis@38
|
470
|
rmeddis@38
|
471 % Do sample rate conversion if needed
|
rmeddis@38
|
472 % Will always convert stimulus component with lower rate up to that with
|
rmeddis@38
|
473 % higher rate.
|
rmeddis@38
|
474 if speechSampleRate > noiseSampleRate
|
rmeddis@38
|
475 % disp('S>N')
|
rmeddis@38
|
476 [p,q] = rat(speechSampleRate/noiseSampleRate,0.0001);
|
rmeddis@38
|
477 noise = resample(noise, p, q);
|
rmeddis@38
|
478 noiseSampleRate = speechSampleRate;
|
rmeddis@38
|
479 elseif noiseSampleRate > speechSampleRate
|
rmeddis@38
|
480 % disp('N>S')
|
rmeddis@38
|
481 [p,q] = rat(noiseSampleRate/speechSampleRate,0.0001);
|
rmeddis@38
|
482 speech = resample(speech, p, q);
|
rmeddis@38
|
483 speechSampleRate = noiseSampleRate; %#ok<NASGU>
|
rmeddis@38
|
484 else
|
rmeddis@38
|
485 %DO NOTHING BUT ASSERT
|
rmeddis@38
|
486 assert(speechSampleRate == noiseSampleRate);
|
rmeddis@38
|
487 end
|
rmeddis@38
|
488 sampleRate = noiseSampleRate;
|
rmeddis@38
|
489 dt = 1/sampleRate;
|
rmeddis@38
|
490
|
rmeddis@38
|
491 % mix stimuli
|
rmeddis@38
|
492 % Everything from here down (mostly) is RTF's original
|
rmeddis@38
|
493 silenceStart = floor(obj.noisePreDur*sampleRate);
|
rmeddis@38
|
494 silenceEnd = floor(obj.noisePostDur*sampleRate);
|
rmeddis@38
|
495
|
rmeddis@38
|
496 silencePointsStart = zeros(silenceStart,1);
|
rmeddis@38
|
497 silencePointsEnd = zeros(silenceEnd,1);
|
rmeddis@38
|
498
|
rmeddis@38
|
499 speech = [silencePointsStart; speech; silencePointsEnd];
|
rmeddis@38
|
500
|
rmeddis@38
|
501 stimLength = length(speech);
|
rmeddis@38
|
502 noiseLength = length(noise);
|
rmeddis@38
|
503 if obj.freezeNoise
|
rmeddis@38
|
504 idx = 1;
|
rmeddis@38
|
505 else
|
rmeddis@38
|
506 idx = ceil(rand*(noiseLength-stimLength));
|
rmeddis@38
|
507 end
|
rmeddis@38
|
508 noise = noise(idx:idx+stimLength-1);
|
rmeddis@38
|
509
|
rmeddis@38
|
510 stimulus = speech+noise;
|
rmeddis@38
|
511
|
rmeddis@38
|
512 % add ramps to noise
|
rmeddis@38
|
513 stimInNoiseTime = dt:dt:dt*length(stimulus);
|
rmeddis@38
|
514 rampDuration = 0.100;
|
rmeddis@38
|
515 rampTime = dt : dt : rampDuration;
|
rmeddis@38
|
516 ramp = [0.5*(1+cos(2*pi*rampTime/(2*rampDuration)+pi)) ones(1,length(stimInNoiseTime)-length(rampTime))];
|
rmeddis@38
|
517 stimulus = stimulus'.*ramp;
|
rmeddis@38
|
518 ramp = fliplr(ramp);
|
rmeddis@38
|
519 stimulus = stimulus.*ramp;
|
rmeddis@38
|
520 stimulus = stimulus';
|
rmeddis@38
|
521 %disp(20*log10(sqrt(mean(stimulus.^2))/20e-6))
|
rmeddis@38
|
522
|
rmeddis@38
|
523 % add additional silent period to start of stimulus for model to 'settle down'
|
rmeddis@38
|
524 additionalSilenceLength = round(0.050*sampleRate);
|
rmeddis@38
|
525 additionalSilencePoints = zeros(additionalSilenceLength,1);
|
rmeddis@38
|
526 stimulus = [additionalSilencePoints; stimulus]'; %now rotated.
|
rmeddis@38
|
527 %disp(20*log10(sqrt(mean(stimulus.^2))/20e-6))
|
rmeddis@38
|
528 end% ------ OF GETSTIMULUS
|
rmeddis@38
|
529
|
rmeddis@38
|
530
|
rmeddis@38
|
531 %% **********************************************************
|
rmeddis@38
|
532 % processWavs - do all of the MAP signal processing
|
rmeddis@38
|
533 %************************************************************
|
rmeddis@38
|
534 function [finalFeatures, ANprobabilityResponse] = processWavs(obj, currentWav)
|
rmeddis@38
|
535
|
rmeddis@38
|
536 %**********************************************************
|
rmeddis@38
|
537 % FIRST GET THE STIMULUS
|
rmeddis@38
|
538 %**********************************************************
|
rmeddis@38
|
539 [stimulus, sampleRate] = obj.getStimulus(currentWav);
|
rmeddis@38
|
540
|
rmeddis@38
|
541 %**********************************************************
|
rmeddis@38
|
542 % NOW TO LOAD IN THE HEARING AID
|
rmeddis@38
|
543 %**********************************************************
|
rmeddis@38
|
544 if obj.useAid
|
rmeddis@38
|
545 stimulus = [stimulus; stimulus]'; %EsxAid requires stereo stim
|
rmeddis@38
|
546 stimulus = EssexAid_guiEmulatorWrapper(stimulus, sampleRate, obj);
|
rmeddis@38
|
547 stimulus = stimulus(1,:); %convert back to mono
|
rmeddis@38
|
548 end
|
rmeddis@38
|
549
|
rmeddis@38
|
550 AN_spikesOrProbability = 'probability';
|
rmeddis@38
|
551
|
rmeddis@38
|
552 if obj.useSpectrogram
|
rmeddis@38
|
553 lowestBF=100; highestBF= 4500; numChannels=30;
|
rmeddis@38
|
554 F=round(logspace(log10(lowestBF),log10(highestBF),numChannels));
|
rmeddis@38
|
555
|
rmeddis@38
|
556 nfft = 1024;
|
rmeddis@38
|
557 hopSamples = 64;
|
rmeddis@38
|
558 noverlap = nfft - hopSamples;
|
rmeddis@38
|
559 dt = hopSamples/sampleRate;
|
rmeddis@38
|
560 [~,~,~,P] = spectrogram(stimulus,nfft,noverlap,F,sampleRate);
|
rmeddis@38
|
561
|
rmeddis@38
|
562 ANprobabilityResponse = 10*log10( abs(P) / ((20e-6)^2) ); %now correct [(a^2)/(b^2) = (a/b)^2]
|
rmeddis@38
|
563
|
rmeddis@38
|
564 else
|
rmeddis@38
|
565 [ANprobabilityResponse, dt, myBFlist] = MAPwrap(stimulus, sampleRate, -1, obj.participant, AN_spikesOrProbability, obj.MAPparamChanges);
|
rmeddis@38
|
566 end
|
rmeddis@38
|
567 nChannels = numel(myBFlist);
|
rmeddis@38
|
568
|
rmeddis@38
|
569
|
rmeddis@38
|
570 time_ANresponse = dt:dt:dt*size(ANprobabilityResponse,2);
|
rmeddis@38
|
571 idx = time_ANresponse > obj.truncateDur; %RTF had this @ 0.550
|
rmeddis@38
|
572 ANprobabilityResponse = ANprobabilityResponse(:, idx);
|
rmeddis@38
|
573
|
rmeddis@38
|
574
|
rmeddis@38
|
575 if ~obj.useSpectrogram
|
rmeddis@38
|
576 if obj.MAPopLSR && ~obj.MAPopHSR
|
rmeddis@38
|
577 ANprobabilityResponse = ANprobabilityResponse(1:nChannels, :); %use LSR
|
rmeddis@38
|
578 end
|
rmeddis@38
|
579 if ~obj.MAPopLSR && obj.MAPopHSR
|
rmeddis@38
|
580 ANprobabilityResponse = ANprobabilityResponse(end-nChannels+1:end, :); %or use HSR
|
rmeddis@38
|
581 end
|
rmeddis@38
|
582 if obj.MAPopMSR
|
rmeddis@38
|
583 assert(0,'Not working with MSR at the mo')
|
rmeddis@38
|
584 end
|
rmeddis@38
|
585 end
|
rmeddis@38
|
586
|
rmeddis@38
|
587 % OPTIONAL PLOTTING
|
rmeddis@38
|
588 YTickIdx = 1:floor(numel(myBFlist)/6):numel(myBFlist);
|
rmeddis@38
|
589 YTickIdxRev = numel(myBFlist)+1-YTickIdx;
|
rmeddis@38
|
590 if ~isempty(obj.probHaxes)
|
rmeddis@38
|
591 axes(obj.probHaxes); %#ok<MAXES>
|
rmeddis@38
|
592 imagesc(ANprobabilityResponse); colorbar('peer', obj.probHaxes)
|
rmeddis@38
|
593 set(obj.probHaxes, 'YTick', YTickIdx);
|
rmeddis@38
|
594 set(obj.probHaxes, 'YTickLabel', num2str( myBFlist(YTickIdxRev)' ));
|
rmeddis@38
|
595 ylabel('cf in Hz')
|
rmeddis@38
|
596 end
|
rmeddis@38
|
597
|
rmeddis@38
|
598 % OPTIONAL PLOTTING SMOOTHED
|
rmeddis@38
|
599 if ~isempty(obj.probHaxesSM)
|
rmeddis@38
|
600 axes(obj.probHaxesSM); %#ok<MAXES>
|
rmeddis@38
|
601 anSM=flipud(obj.makeANsmooth(ANprobabilityResponse, 1/dt));
|
rmeddis@38
|
602 imagesc((1:size(anSM,2))./100,1:size(ANprobabilityResponse,1),anSM);
|
rmeddis@38
|
603 set(obj.probHaxesSM, 'YTick', YTickIdx);
|
rmeddis@38
|
604 set(obj.probHaxesSM, 'YTickLabel', num2str( myBFlist(YTickIdxRev)' ));
|
rmeddis@38
|
605 shading(obj.probHaxesSM, 'flat'); colorbar('peer', obj.probHaxesSM)
|
rmeddis@38
|
606 ylabel('cf (Hz)')
|
rmeddis@38
|
607 xlabel('Time (s)')
|
rmeddis@38
|
608 end
|
rmeddis@38
|
609
|
rmeddis@38
|
610
|
rmeddis@38
|
611 %**********************************************************
|
rmeddis@38
|
612 % optional SACF stage
|
rmeddis@38
|
613 %**********************************************************
|
rmeddis@38
|
614 if obj.useSACF
|
rmeddis@38
|
615
|
rmeddis@38
|
616 % A slightly ugly copying is needed
|
rmeddis@38
|
617 SACFparams.lambda = obj.SACFlambda;
|
rmeddis@38
|
618 SACFparams.acfTau = obj.SACFacfTau;
|
rmeddis@38
|
619 SACFparams.lags = logspace(log10(obj.SACFminLag),log10(obj.SACFmaxLag),obj.SACFnBins);
|
rmeddis@38
|
620 SACFparams.lags = linspace(obj.SACFminLag, obj.SACFmaxLag,obj.SACFnBins );
|
rmeddis@38
|
621
|
rmeddis@38
|
622 SACFmethod.dt = dt;
|
rmeddis@38
|
623 SACFmethod.nonlinCF = myBFlist;
|
rmeddis@38
|
624
|
rmeddis@38
|
625 %This is slightly misleading as the ANprob is now a SACF
|
rmeddis@38
|
626 [ANprobabilityResponse, ~, ~, ~] = filteredSACF(ANprobabilityResponse, SACFmethod, SACFparams);
|
rmeddis@38
|
627
|
rmeddis@38
|
628 % OPTIONAL PLOTTING
|
rmeddis@38
|
629 YTickIdx = 1:floor(obj.SACFnBins/6):obj.SACFnBins;
|
rmeddis@38
|
630 %YTickIdxRev = obj.SACFnBins+1-YTickIdx;
|
rmeddis@38
|
631 if ~isempty(obj.sacfHaxes)
|
rmeddis@38
|
632 axes(obj.sacfHaxes); %#ok<MAXES>
|
rmeddis@38
|
633 imagesc(flipud(ANprobabilityResponse)); shading(obj.sacfHaxes, 'flat'); colorbar('peer', obj.sacfHaxes)
|
rmeddis@38
|
634 set(obj.sacfHaxes, 'YTick', YTickIdx);
|
rmeddis@38
|
635 set(obj.sacfHaxes, 'YTickLabel', num2str( 1./SACFparams.lags(YTickIdx)' ,'%0.1f' ));
|
rmeddis@38
|
636 ylabel('Pitch in Hz')
|
rmeddis@38
|
637 end
|
rmeddis@38
|
638
|
rmeddis@38
|
639 % OPTIONAL PLOTTING SMOOTHED
|
rmeddis@38
|
640 if ~isempty(obj.sacfHaxesSM)
|
rmeddis@38
|
641 axes(obj.sacfHaxesSM); %#ok<MAXES>
|
rmeddis@38
|
642 imagesc(flipud(obj.makeANsmooth(ANprobabilityResponse, 1/dt))); shading(obj.sacfHaxesSM, 'flat'); colorbar('peer', obj.sacfHaxesSM)
|
rmeddis@38
|
643 set(obj.sacfHaxesSM, 'YTick', YTickIdx);
|
rmeddis@38
|
644 set(obj.sacfHaxesSM, 'YTickLabel', num2str( 1./SACFparams.lags(YTickIdx)' ,'%0.1f' ));
|
rmeddis@38
|
645 ylabel('Pitch in Hz')
|
rmeddis@38
|
646 end
|
rmeddis@38
|
647
|
rmeddis@38
|
648 end
|
rmeddis@38
|
649
|
rmeddis@38
|
650
|
rmeddis@38
|
651 finalFeatures = obj.makeANfeatures( ...
|
rmeddis@38
|
652 obj.makeANsmooth(ANprobabilityResponse, 1/dt), obj.numCoeff );
|
rmeddis@38
|
653
|
rmeddis@38
|
654 if obj.removeEnergyStatic
|
rmeddis@38
|
655 finalFeatures = finalFeatures(2:end,:);
|
rmeddis@38
|
656 % disp(size(finalFeatures))
|
rmeddis@38
|
657 end
|
rmeddis@38
|
658
|
rmeddis@38
|
659 if obj.doCMN
|
rmeddis@38
|
660 m = mean(finalFeatures,2);
|
rmeddis@38
|
661 finalFeatures = finalFeatures - repmat(m,1,size(finalFeatures,2));
|
rmeddis@38
|
662 end
|
rmeddis@38
|
663
|
rmeddis@38
|
664 % OPTIONAL PLOTTING
|
rmeddis@38
|
665 if ~isempty(obj.featHaxes)
|
rmeddis@38
|
666 pcolor(obj.featHaxes, finalFeatures); shading(obj.featHaxes, 'flat'); colorbar('peer', obj.featHaxes)
|
rmeddis@38
|
667 end
|
rmeddis@38
|
668 if ~isempty(obj.reconHaxes)
|
rmeddis@38
|
669 reconsData = idct(finalFeatures,obj.SACFnBins);
|
rmeddis@38
|
670 axes(obj.reconHaxes); %#ok<MAXES>
|
rmeddis@38
|
671 imagesc(flipud( reconsData ));
|
rmeddis@38
|
672 end
|
rmeddis@38
|
673
|
rmeddis@38
|
674 opForHTK(obj, currentWav, finalFeatures);
|
rmeddis@38
|
675 end % ------ OF PROCESSWAVS
|
rmeddis@38
|
676
|
rmeddis@38
|
677 end % ------ OF METHODS
|
rmeddis@38
|
678
|
rmeddis@38
|
679 %% *********************************************************
|
rmeddis@38
|
680 % _ _ _ _ _ _
|
rmeddis@38
|
681 % | | | | (_) | | | | | |
|
rmeddis@38
|
682 % ___| |_ __ _| |_ _ ___ _ __ ___ ___| |_| |__ ___ __| |___
|
rmeddis@38
|
683 % / __| __/ _` | __| |/ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
|
rmeddis@38
|
684 % \__ \ || (_| | |_| | (__ | | | | | | __/ |_| | | | (_) | (_| \__ \
|
rmeddis@38
|
685 % |___/\__\__,_|\__|_|\___| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
|
rmeddis@38
|
686 %************************************************************
|
rmeddis@38
|
687
|
rmeddis@38
|
688 methods(Static)
|
rmeddis@38
|
689 %% ********************************************************
|
rmeddis@38
|
690 % makeANsmooth - smooth the AN response into hanning windowed chunks
|
rmeddis@38
|
691 %**********************************************************
|
rmeddis@38
|
692 function ANsmooth = makeANsmooth(ANresponse, sampleRate, winSize, hopSize)
|
rmeddis@38
|
693 if nargin < 3
|
rmeddis@38
|
694 winSize = 25; %default 25 ms window
|
rmeddis@38
|
695 end
|
rmeddis@38
|
696 if nargin < 4
|
rmeddis@38
|
697 hopSize = 10; %default 10 ms jump between windows
|
rmeddis@38
|
698 end
|
rmeddis@38
|
699
|
rmeddis@38
|
700 winSizeSamples = round(winSize*sampleRate/1000);
|
rmeddis@38
|
701 hopSizeSamples = round(hopSize*sampleRate/1000);
|
rmeddis@38
|
702
|
rmeddis@38
|
703 % smooth
|
rmeddis@38
|
704 hann = cJob.NRC_hanning(winSizeSamples);
|
rmeddis@38
|
705
|
rmeddis@38
|
706 ANsmooth = [];%Cannot pre-allocate a size as it is unknown until the enframing
|
rmeddis@38
|
707 for chan = 1:size(ANresponse,1)
|
rmeddis@38
|
708 f = cJob.enframe(ANresponse(chan,:), hann, hopSizeSamples);
|
rmeddis@38
|
709 ANsmooth(chan,:) = mean(f,2)'; %#ok<AGROW> see above comment
|
rmeddis@38
|
710 end
|
rmeddis@38
|
711 end% ------ OF makeANsmooth
|
rmeddis@38
|
712
|
rmeddis@38
|
713 %% ********************************************************
|
rmeddis@38
|
714 % makeANfeatures - dct wizardry
|
rmeddis@38
|
715 %**********************************************************
|
rmeddis@38
|
716 function ANfeatures = makeANfeatures(ANrate, numCoeff)
|
rmeddis@38
|
717 % make feature vectors
|
rmeddis@38
|
718 features = cJob.GJB_dct(ANrate);
|
rmeddis@38
|
719 ANfeatures = features(1:numCoeff,:);
|
rmeddis@38
|
720 end % ------ OF makeANfeatures
|
rmeddis@38
|
721
|
rmeddis@38
|
722 %% ************************************************************************
|
rmeddis@38
|
723 % enframe - AVOID SIGNAL PROCESSING TOOLBOX buffer function
|
rmeddis@38
|
724 %**************************************************************************
|
rmeddis@38
|
725 function f=enframe(x,win,inc)
|
rmeddis@38
|
726 %ENFRAME split signal up into (overlapping) frames: one per row. F=(X,WIN,INC)
|
rmeddis@38
|
727 %
|
rmeddis@38
|
728 % F = ENFRAME(X,LEN) splits the vector X(:) up into
|
rmeddis@38
|
729 % frames. Each frame is of length LEN and occupies
|
rmeddis@38
|
730 % one row of the output matrix. The last few frames of X
|
rmeddis@38
|
731 % will be ignored if its length is not divisible by LEN.
|
rmeddis@38
|
732 % It is an error if X is shorter than LEN.
|
rmeddis@38
|
733 %
|
rmeddis@38
|
734 % F = ENFRAME(X,LEN,INC) has frames beginning at increments of INC
|
rmeddis@38
|
735 % The centre of frame I is X((I-1)*INC+(LEN+1)/2) for I=1,2,...
|
rmeddis@38
|
736 % The number of frames is fix((length(X)-LEN+INC)/INC)
|
rmeddis@38
|
737 %
|
rmeddis@38
|
738 % F = ENFRAME(X,WINDOW) or ENFRAME(X,WINDOW,INC) multiplies
|
rmeddis@38
|
739 % each frame by WINDOW(:)
|
rmeddis@38
|
740
|
rmeddis@38
|
741 % Copyright (C) Mike Brookes 1997
|
rmeddis@38
|
742 % Version: $Id: enframe.m,v 1.4 2006/06/22 19:07:50 dmb Exp $
|
rmeddis@38
|
743 %
|
rmeddis@38
|
744 % VOICEBOX is a MATLAB toolbox for speech processing.
|
rmeddis@38
|
745 % Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
|
rmeddis@38
|
746 %
|
rmeddis@38
|
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
rmeddis@38
|
748 % This program is free software; you can redistribute it and/or modify
|
rmeddis@38
|
749 % it under the terms of the GNU General Public License as published by
|
rmeddis@38
|
750 % the Free Software Foundation; either version 2 of the License, or
|
rmeddis@38
|
751 % (at your option) any later version.
|
rmeddis@38
|
752 %
|
rmeddis@38
|
753 % This program is distributed in the hope that it will be useful,
|
rmeddis@38
|
754 % but WITHOUT ANY WARRANTY; without even the implied warranty of
|
rmeddis@38
|
755 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
rmeddis@38
|
756 % GNU General Public License for more details.
|
rmeddis@38
|
757 %
|
rmeddis@38
|
758 % You can obtain a copy of the GNU General Public License from
|
rmeddis@38
|
759 % http://www.gnu.org/copyleft/gpl.html or by writing to
|
rmeddis@38
|
760 % Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
|
rmeddis@38
|
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
rmeddis@38
|
762
|
rmeddis@38
|
763 nx=length(x(:));
|
rmeddis@38
|
764 nwin=length(win);
|
rmeddis@38
|
765 if (nwin == 1)
|
rmeddis@38
|
766 len = win;
|
rmeddis@38
|
767 else
|
rmeddis@38
|
768 len = nwin;
|
rmeddis@38
|
769 end
|
rmeddis@38
|
770 if (nargin < 3)
|
rmeddis@38
|
771 inc = len;
|
rmeddis@38
|
772 end
|
rmeddis@38
|
773 nf = fix((nx-len+inc)/inc);
|
rmeddis@38
|
774 f=zeros(nf,len);
|
rmeddis@38
|
775 indf= inc*(0:(nf-1)).';
|
rmeddis@38
|
776 inds = (1:len);
|
rmeddis@38
|
777 f(:) = x(indf(:,ones(1,len))+inds(ones(nf,1),:));
|
rmeddis@38
|
778 if (nwin > 1)
|
rmeddis@38
|
779 w = win(:)';
|
rmeddis@38
|
780 f = f .* w(ones(nf,1),:);
|
rmeddis@38
|
781 end
|
rmeddis@38
|
782 end % ------ OF ENFRAME
|
rmeddis@38
|
783
|
rmeddis@38
|
784 %% ************************************************************************
|
rmeddis@38
|
785 % GJB_dct - AVOID SIGNAL PROCESSING TOOLBOX
|
rmeddis@38
|
786 %**************************************************************************
|
rmeddis@38
|
787 function b=GJB_dct(a,n)
|
rmeddis@38
|
788
|
rmeddis@38
|
789 if nargin == 0,
|
rmeddis@38
|
790 error('Not enough input arguments.');
|
rmeddis@38
|
791 end
|
rmeddis@38
|
792
|
rmeddis@38
|
793 if isempty(a)
|
rmeddis@38
|
794 b = [];
|
rmeddis@38
|
795 return
|
rmeddis@38
|
796 end
|
rmeddis@38
|
797
|
rmeddis@38
|
798 % If input is a vector, make it a column:
|
rmeddis@38
|
799 do_trans = (size(a,1) == 1);
|
rmeddis@38
|
800 if do_trans, a = a(:); end
|
rmeddis@38
|
801
|
rmeddis@38
|
802 if nargin==1,
|
rmeddis@38
|
803 n = size(a,1);
|
rmeddis@38
|
804 end
|
rmeddis@38
|
805 m = size(a,2);
|
rmeddis@38
|
806
|
rmeddis@38
|
807 % Pad or truncate input if necessary
|
rmeddis@38
|
808 if size(a,1)<n,
|
rmeddis@38
|
809 aa = zeros(n,m);
|
rmeddis@38
|
810 aa(1:size(a,1),:) = a;
|
rmeddis@38
|
811 else
|
rmeddis@38
|
812 aa = a(1:n,:);
|
rmeddis@38
|
813 end
|
rmeddis@38
|
814
|
rmeddis@38
|
815 % Compute weights to multiply DFT coefficients
|
rmeddis@38
|
816 ww = (exp(-1i*(0:n-1)*pi/(2*n))/sqrt(2*n)).';
|
rmeddis@38
|
817 ww(1) = ww(1) / sqrt(2);
|
rmeddis@38
|
818
|
rmeddis@38
|
819 if rem(n,2)==1 || ~isreal(a), % odd case
|
rmeddis@38
|
820 % Form intermediate even-symmetric matrix
|
rmeddis@38
|
821 y = zeros(2*n,m);
|
rmeddis@38
|
822 y(1:n,:) = aa;
|
rmeddis@38
|
823 y(n+1:2*n,:) = flipud(aa);
|
rmeddis@38
|
824
|
rmeddis@38
|
825 % Compute the FFT and keep the appropriate portion:
|
rmeddis@38
|
826 yy = fft(y);
|
rmeddis@38
|
827 yy = yy(1:n,:);
|
rmeddis@38
|
828
|
rmeddis@38
|
829 else % even case
|
rmeddis@38
|
830 % Re-order the elements of the columns of x
|
rmeddis@38
|
831 y = [ aa(1:2:n,:); aa(n:-2:2,:) ];
|
rmeddis@38
|
832 yy = fft(y);
|
rmeddis@38
|
833 ww = 2*ww; % Double the weights for even-length case
|
rmeddis@38
|
834 end
|
rmeddis@38
|
835
|
rmeddis@38
|
836 % Multiply FFT by weights:
|
rmeddis@38
|
837 b = ww(:,ones(1,m)) .* yy;
|
rmeddis@38
|
838
|
rmeddis@38
|
839 if isreal(a), b = real(b); end
|
rmeddis@38
|
840 if do_trans, b = b.'; end
|
rmeddis@38
|
841 end % ----- of GJB_DCT
|
rmeddis@38
|
842
|
rmeddis@38
|
843 %% ************************************************************************
|
rmeddis@38
|
844 % NRC_hanning - AVOID SIGNAL PROCESSING TOOLBOX
|
rmeddis@38
|
845 %**************************************************************************
|
rmeddis@38
|
846 function w=NRC_hanning(n)
|
rmeddis@38
|
847 calc_hanning = @(m,n)0.5*(1 - cos(2*pi*(1:m)'/(n+1))); %cheeky anonymous function - I <3 these
|
rmeddis@38
|
848 if ~rem(n,2)
|
rmeddis@38
|
849 % Even length window
|
rmeddis@38
|
850 half = n/2;
|
rmeddis@38
|
851 w = calc_hanning(half,n);
|
rmeddis@38
|
852 w = [w; w(end:-1:1)];
|
rmeddis@38
|
853 else
|
rmeddis@38
|
854 % Odd length window
|
rmeddis@38
|
855 half = (n+1)/2;
|
rmeddis@38
|
856 w = calc_hanning(half,n);
|
rmeddis@38
|
857 w = [w; w(end-1:-1:1)];
|
rmeddis@38
|
858 end
|
rmeddis@38
|
859 end % ------ of NRC_HANNING
|
rmeddis@38
|
860
|
rmeddis@38
|
861 %% ************************************************************************
|
rmeddis@38
|
862 % writeHTK - convert data to htk format -> by anonymous Sue (2001)
|
rmeddis@38
|
863 %**************************************************************************
|
rmeddis@38
|
864 function retcode = writeHTK(filename, htkdata, nFrames, sampPeriod, SampSize, ParamKind, byte_order)
|
rmeddis@38
|
865 % Write an HTK format file.
|
rmeddis@38
|
866 %
|
rmeddis@38
|
867 % Input parameters:
|
rmeddis@38
|
868 % filename HTK data file
|
rmeddis@38
|
869 % htkdata HTK data read: an m x n matrix with
|
rmeddis@38
|
870 % m = no. of channels
|
rmeddis@38
|
871 % n = no. of frames
|
rmeddis@38
|
872 % The following are from the HTK header (see HTK manual):
|
rmeddis@38
|
873 % nFrames no. of frames (samples)
|
rmeddis@38
|
874 % sampPeriod sample period (in 100 ns units?)
|
rmeddis@38
|
875 % SampSize sample size
|
rmeddis@38
|
876 % ParamKind parameter kind code
|
rmeddis@38
|
877 %
|
rmeddis@38
|
878 % byteorder 'be' for big-endian (typical for Unix) (default)
|
rmeddis@38
|
879 % 'le' for little-endian (typical for MSWindows)
|
rmeddis@38
|
880 %
|
rmeddis@38
|
881 % Output parameters:
|
rmeddis@38
|
882 % retcode 0 if successful
|
rmeddis@38
|
883
|
rmeddis@38
|
884 % Written by Sue 17/12/01
|
rmeddis@38
|
885
|
rmeddis@38
|
886 retcode=-1; % initialise in case of error
|
rmeddis@38
|
887 if nargin < 6
|
rmeddis@38
|
888 fprintf('Usage: %s(filename, htkdata, nFrames, sampPeriod, SampSize, ParamKind [, byte_order])', mfilename);
|
rmeddis@38
|
889 end;
|
rmeddis@38
|
890
|
rmeddis@38
|
891 % Default to big-endian (HTK format)
|
rmeddis@38
|
892 if nargin < 7
|
rmeddis@38
|
893 byte_order = 'be';
|
rmeddis@38
|
894 end;
|
rmeddis@38
|
895
|
rmeddis@38
|
896 fid = fopen (filename, 'w', sprintf('ieee-%s', byte_order));
|
rmeddis@38
|
897 if fid < 1
|
rmeddis@38
|
898 fprintf('%s: can''t open output file %s\n', mfilename, filename);
|
rmeddis@38
|
899 return
|
rmeddis@38
|
900 end
|
rmeddis@38
|
901
|
rmeddis@38
|
902 % Write header
|
rmeddis@38
|
903 fwrite (fid, nFrames, 'int32'); %nSamples in HTK
|
rmeddis@38
|
904 fwrite (fid, sampPeriod, 'int32');
|
rmeddis@38
|
905 fwrite (fid, SampSize, 'int16');
|
rmeddis@38
|
906 fwrite (fid, ParamKind, 'int16');
|
rmeddis@38
|
907
|
rmeddis@38
|
908 % Write actual data
|
rmeddis@38
|
909 fwrite(fid, htkdata, 'float32');
|
rmeddis@38
|
910
|
rmeddis@38
|
911 fclose(fid);
|
rmeddis@38
|
912
|
rmeddis@38
|
913 retcode=0;
|
rmeddis@38
|
914 end% ------ OF WRITEHTK
|
rmeddis@38
|
915
|
rmeddis@38
|
916 %% ************************************************************************
|
rmeddis@38
|
917 % readHTK - just incase you ever want to go backwards
|
rmeddis@38
|
918 %**************************************************************************
|
rmeddis@38
|
919 function [htkdata,nframes,sampPeriod,sampSize,paramKind] = readHTK(filename,byte_order)
|
rmeddis@38
|
920
|
rmeddis@38
|
921 if nargin<2
|
rmeddis@38
|
922 byte_order = 'be';
|
rmeddis@38
|
923 end
|
rmeddis@38
|
924
|
rmeddis@38
|
925 fid = fopen(filename,'r',sprintf('ieee-%s',byte_order));
|
rmeddis@38
|
926
|
rmeddis@38
|
927 nframes = fread(fid,1,'int32');
|
rmeddis@38
|
928 sampPeriod = fread(fid,1,'int32');
|
rmeddis@38
|
929 sampSize = fread(fid,1,'int16');
|
rmeddis@38
|
930 paramKind = fread(fid,1,'int16');
|
rmeddis@38
|
931
|
rmeddis@38
|
932 % read the data
|
rmeddis@38
|
933
|
rmeddis@38
|
934 htkdata = fread(fid,nframes*(sampSize/4),'float32');
|
rmeddis@38
|
935 htkdata = reshape(htkdata,sampSize/4,nframes);
|
rmeddis@38
|
936 fclose(fid);
|
rmeddis@38
|
937 end % ------ OF READHTK
|
rmeddis@38
|
938
|
rmeddis@38
|
939 end % ------ OF STATIC METHODS
|
rmeddis@38
|
940
|
rmeddis@38
|
941 end % ------ OF CLASS
|