annotate userProgramsASRforDummies/cJob.m @ 38:c2204b18f4a2 tip

End nov big change
author Ray Meddis <rmeddis@essex.ac.uk>
date Mon, 28 Nov 2011 13:34:28 +0000
parents
children
rev   line source
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