annotate multithreshold 1.46/nextStimulus.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 3ea506487b3b
children
rev   line source
rmeddis@0 1 function errormsg=nextStimulus(handles)
rmeddis@0 2 % Handles everything concerned with the stimulus presentation
rmeddis@0 3 % called from startNewRun in subjGUI
rmeddis@0 4
rmeddis@38 5 global experiment stimulusParameters withinRuns betweenRuns
rmeddis@0 6 experiment.status='presentingStimulus';
rmeddis@0 7 errormsg='';
rmeddis@0 8
rmeddis@0 9 % interrupt by 'stop' button
rmeddis@29 10 % if experiment.stop
rmeddis@29 11 % disp('******** experiment manually stopped *****************')
rmeddis@29 12 % experiment.status= 'waitingForStart';
rmeddis@29 13 % errormsg='manually stopped';
rmeddis@29 14 % addToMsg(errormsg,1)
rmeddis@29 15 % return
rmeddis@29 16 % end
rmeddis@0 17
rmeddis@0 18 % -----------------------------------------choose catch trials at random
rmeddis@0 19 % catch trials are for subject threshold measurements only
rmeddis@0 20 % this is the only place where withinRuns.catchTrial is set
rmeddis@0 21 if experiment.allowCatchTrials
rmeddis@0 22 if withinRuns.trialNumber==1;
rmeddis@0 23 % first trial is never a catch trial
rmeddis@0 24 withinRuns.catchTrial=0;
rmeddis@0 25 withinRuns.catchTrialCount=0; % reset count on first trial
rmeddis@0 26 elseif withinRuns.trialNumber==2 ...
rmeddis@0 27 && withinRuns.catchTrialCount==0
rmeddis@0 28 % second trial is always a catch trial
rmeddis@0 29 withinRuns.catchTrial=1;
rmeddis@0 30 withinRuns.catchTrialCount=1; % this must be the first
rmeddis@0 31 elseif withinRuns.thisIsRepeatTrial
rmeddis@0 32 % for requested repeats do not change catch trial status
rmeddis@0 33 withinRuns.thisIsRepeatTrial=0; % reset toggle
rmeddis@0 34 else
rmeddis@0 35 % choose whether or not to have a catch trial
rmeddis@0 36 R=rand;
rmeddis@0 37 if R<stimulusParameters.catchTrialRate
rmeddis@0 38 % catch trial
rmeddis@0 39 withinRuns.catchTrial=1;
rmeddis@0 40 addToMsg('Catch Trial',1)
rmeddis@0 41 withinRuns.catchTrialCount=withinRuns.catchTrialCount+1;
rmeddis@0 42 else
rmeddis@0 43 % not a catch trial
rmeddis@0 44 withinRuns.catchTrial=0;
rmeddis@0 45 end
rmeddis@0 46 end
rmeddis@0 47 else
rmeddis@0 48 % no catch trials for statistical evaluations or 2AIFC or (poss) MAP
rmeddis@0 49 withinRuns.catchTrial=0;
rmeddis@0 50 end
rmeddis@0 51
rmeddis@0 52 %------------ during stimulus presentation show appropriate button images
rmeddis@0 53 switch experiment.ear
rmeddis@0 54 case {'statsModelLogistic', 'statsModelRareEvent',...
rmeddis@0 55 'MAPmodel', 'MAPmodelMultiCh', 'MAPmodelSingleCh'}
rmeddis@0 56 % no buttons shown
rmeddis@0 57 otherwise
rmeddis@0 58 switch experiment.threshEstMethod
rmeddis@0 59 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 60 %Except for 2I2AFC
rmeddis@0 61 % For 2I2AFC the buttons on the screen ab initio
rmeddis@0 62 set(handles.frame1,'visible','off')
rmeddis@0 63 set(handles.pushbuttonGO,'visible','off')
rmeddis@0 64 set(handles.pushbuttoNotSure,'visible','off')
rmeddis@0 65 set(handles.pushbuttonWrongButton,'visible','off')
rmeddis@0 66 set(handles.pushbutton3,'visible','off')
rmeddis@0 67 set(handles.pushbutton0,'visible','off')
rmeddis@0 68 set(handles.pushbutton1,'visible','on')
rmeddis@0 69 set(handles.pushbutton2,'visible','on')
rmeddis@0 70 drawnow
rmeddis@0 71 otherwise
rmeddis@0 72 % i.e. single interval/ maxLikelihood
rmeddis@0 73 set(handles.frame1,'backgroundColor','w')
rmeddis@0 74 set(handles.frame1,'visible','off')
rmeddis@0 75 set(handles.pushbuttoNotSure,'visible','off')
rmeddis@0 76 set(handles.pushbuttonWrongButton,'visible','off')
rmeddis@0 77 set(handles.pushbutton3,'visible','off')
rmeddis@0 78 set(handles.pushbutton2,'visible','off')
rmeddis@0 79 set(handles.pushbutton1,'visible','off')
rmeddis@0 80 set(handles.pushbutton0,'visible','off')
rmeddis@0 81 pause(.1)
rmeddis@0 82 end
rmeddis@0 83 end
rmeddis@0 84
rmeddis@0 85 set(handles.textMSG,'BackgroundColor','w', 'ForegroundColor', 'b')
rmeddis@17 86
rmeddis@0 87 % Now the serious business of crafting and presenting the stimulus
rmeddis@0 88 errormsg= stimulusMakeAndPlay (handles);
rmeddis@0 89
rmeddis@0 90 if ~isempty(errormsg)
rmeddis@0 91 % e.g. clipping. subjGUI will service the error
rmeddis@0 92 return
rmeddis@0 93 end
rmeddis@0 94
rmeddis@0 95 % after playing the stimulus, reset the subjectGUI
rmeddis@0 96 switch experiment.ear
rmeddis@0 97 case {'statsModelLogistic', 'statsModelRareEvent',...
rmeddis@0 98 'MAPmodel', 'MAPmodelMultiCh', 'MAPmodelSingleCh'}
rmeddis@0 99 % no changes required if model used
rmeddis@0 100 % NB these changes do occur is 'MAPmodelListen' is selected
rmeddis@0 101 otherwise
rmeddis@0 102 switch experiment.threshEstMethod
rmeddis@0 103 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 104 % buttons already visible
rmeddis@0 105 otherwise
rmeddis@0 106 % single interval now make buttons visible
rmeddis@0 107 set(handles.frame1,'visible','on')
rmeddis@0 108 set(handles.pushbuttoNotSure,'visible','on')
rmeddis@0 109 % set(handles.pushbuttonWrongButton,'visible','on')
rmeddis@0 110 set(handles.pushbutton0,'visible','on')
rmeddis@0 111 set(handles.pushbutton1,'visible','on')
rmeddis@0 112 set(handles.pushbutton2,'visible','on')
rmeddis@0 113 set(handles.pushbutton3,'visible','on')
rmeddis@0 114 end
rmeddis@0 115 end
rmeddis@0 116
rmeddis@0 117 switch experiment.paradigm
rmeddis@0 118 case 'SRT'
rmeddis@0 119 set(handles.frame1,'backgroundColor','w')
rmeddis@0 120 set(handles.frame1,'visible','off')
rmeddis@0 121 set(handles.pushbuttoNotSure,'visible','off')
rmeddis@0 122 set(handles.pushbuttonWrongButton,'visible','off')
rmeddis@0 123 set(handles.pushbutton3,'visible','off')
rmeddis@0 124 set(handles.pushbutton2,'visible','off')
rmeddis@0 125 set(handles.pushbutton1,'visible','off')
rmeddis@0 126 set(handles.pushbutton0,'visible','off')
rmeddis@0 127 set(handles.editdigitInput,'visible','on')
rmeddis@0 128 set(handles.editdigitInput,'string',[])
rmeddis@0 129 pause(.2)
rmeddis@0 130 uicontrol(handles.editdigitInput)
rmeddis@0 131
rmeddis@0 132 otherwise
rmeddis@0 133 set(handles.editdigitInput,'visible','off')
rmeddis@0 134 end
rmeddis@0 135
rmeddis@0 136
rmeddis@0 137 experiment.status='waitingForResponse';
rmeddis@0 138 % home again
rmeddis@0 139
rmeddis@0 140 % ------------------------------------------------------------------------------------------stimulusMakeAndPlay
rmeddis@0 141 function errormsg=stimulusMakeAndPlay (handles)
rmeddis@0 142 global experiment stimulusParameters betweenRuns withinRuns expGUIhandles audio
rmeddis@0 143 % creates the stimulus and plays it; there are two stimuli; cue and test
rmeddis@0 144 % called from nextStimulus
rmeddis@0 145
rmeddis@0 146 errormsg='';
rmeddis@0 147
rmeddis@0 148 % first post the subjects instructions on subjGUI
rmeddis@0 149 set(handles.textMSG,'string', stimulusParameters.subjectText)
rmeddis@0 150
rmeddis@0 151 % select the new levels of the between runs variables
rmeddis@35 152 thisRunNumber=betweenRuns.runNumber;
rmeddis@0 153 cmd=(['stimulusParameters.' betweenRuns.variableName1 '= ' ...
rmeddis@35 154 num2str(betweenRuns.var1Sequence(thisRunNumber)) ';']);
rmeddis@0 155 % e.g. stimulusParameters.targetFrequency= 1000;
rmeddis@0 156 eval(cmd);
rmeddis@0 157
rmeddis@0 158 cmd=(['stimulusParameters.' betweenRuns.variableName2 '= ' ...
rmeddis@35 159 num2str(betweenRuns.var2Sequence(thisRunNumber)) ';']);
rmeddis@0 160 % e.g. stimulusParameters.targetDuration= 0.1;
rmeddis@0 161 eval(cmd);
rmeddis@0 162
rmeddis@35 163 % When variableList2 is 'targetFrequency' targetLevel may vary between runs
rmeddis@35 164 % If so, it is changed at the end of each variableList1.
rmeddis@36 165 if strcmp(betweenRuns.variableName2, 'targetFrequency') && ...
rmeddis@35 166 length(stimulusParameters.targetLevels)>1
rmeddis@35 167 switch experiment.paradigm
rmeddis@35 168 case {'trainingIFMC', 'TMC','TMC_16ms', 'TMC - ELP', 'IFMC','IFMC_8ms','IFMC_16ms'}
rmeddis@35 169 idx=floor(thisRunNumber/length(betweenRuns.variableList1)-0.01)+1;
rmeddis@35 170 cmd=(['stimulusParameters.targetLevel = ' ...
rmeddis@35 171 num2str(stimulusParameters.targetLevels(idx)) ';']);
rmeddis@35 172 eval(cmd);
rmeddis@35 173 if withinRuns.trialNumber==1
rmeddis@35 174 disp(['targetLevel=' num2str(stimulusParameters.targetLevel)])
rmeddis@35 175 end
rmeddis@35 176 end
rmeddis@0 177 end
rmeddis@0 178
rmeddis@0 179
rmeddis@0 180 % for more readable code use shorter variable names;
rmeddis@0 181 % NB these may change below; these are only the starting values
rmeddis@0 182
rmeddis@0 183 targetType= stimulusParameters.targetType;
rmeddis@0 184 targetDuration= stimulusParameters.targetDuration;
rmeddis@0 185 targetLevel= stimulusParameters.targetLevel;
rmeddis@0 186 targetFrequency= stimulusParameters.targetFrequency;
rmeddis@0 187
rmeddis@0 188 maskerType= stimulusParameters.maskerType;
rmeddis@0 189 maskerDuration= stimulusParameters.maskerDuration;
rmeddis@0 190 maskerLevel= stimulusParameters.maskerLevel;
rmeddis@0 191 maskerRelativeFrequency= stimulusParameters.maskerRelativeFrequency;
rmeddis@0 192 maskerFrequency= maskerRelativeFrequency*targetFrequency;
rmeddis@0 193
rmeddis@0 194 gapDuration= stimulusParameters.gapDuration;
rmeddis@0 195
rmeddis@0 196 rampDuration= stimulusParameters.rampDuration;
rmeddis@0 197 AFCsilenceDuration=stimulusParameters.AFCsilenceDuration; % 2I2AFC gap
rmeddis@0 198 backgroundLevel= stimulusParameters.backgroundLevel;
rmeddis@0 199
rmeddis@0 200 % Set level of within runs variable
rmeddis@0 201 % this is the first change to one of the values shown above
rmeddis@0 202 cmd=[stimulusParameters.WRVname '= withinRuns.variableValue;' ];
rmeddis@0 203 % e.g.: maskerLevel= withinRuns.variableValue;
rmeddis@0 204 eval(cmd);
rmeddis@0 205
rmeddis@0 206 % cue and test stimuli are identical except for a single difference
rmeddis@0 207 % depending on the paradigm
rmeddis@0 208 cueTestDifference= stimulusParameters.cueTestDifference;
rmeddis@0 209 % cue characteristics before adding cue differences
rmeddis@0 210 cueTargetLevel=targetLevel;
rmeddis@0 211 cueMaskerFrequency=maskerFrequency;
rmeddis@0 212 cueMaskerDuration=maskerDuration;
rmeddis@0 213 cueMaskerLevel=maskerLevel;
rmeddis@0 214 cueTargetFrequency=targetFrequency;
rmeddis@0 215 cueGapDuration=gapDuration;
rmeddis@0 216
rmeddis@0 217 % ----------------------------paradigm sensitive cue and masker settings
rmeddis@0 218 % switch off unwanted components and base cue on target values
rmeddis@0 219 % for catch trials switch off the target
rmeddis@0 220
rmeddis@0 221 % --- set cueTarget level according to assessment method
rmeddis@0 222 % cue-test difference applies only with singleInterval
rmeddis@0 223 switch experiment.threshEstMethod
rmeddis@0 224 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 225 % For 2IFC the cue stimulus (masker + probe) is the 'no' window
rmeddis@0 226 % and the target stimulus (masker+probe) is the 'yes' window
rmeddis@0 227 % the order of presentation is decided at the last minute.
rmeddis@0 228 cueTargetLevel=-100; % the target is never in the 'no' window
rmeddis@0 229 cueMaskerLevel=maskerLevel; % masker level is the same in both
rmeddis@0 230 otherwise
rmeddis@0 231 % 'single interval' or max likelihood
rmeddis@0 232 switch experiment.paradigm
rmeddis@0 233 % cue target is more audible
rmeddis@0 234 case {'training','absThreshold', 'absThreshold_8', ...
rmeddis@0 235 'TENtest', 'threshold_duration','discomfort',...
rmeddis@0 236 'overShoot','overShootB','overShootMB1', ...
rmeddis@38 237 'overShootMB2', 'OHIO','OHIOabs','OHIOspect'...
rmeddis@38 238 'OHIOrand', 'OHIOtemp', 'OHIOspectemp'}
rmeddis@0 239 cueTargetLevel=targetLevel+cueTestDifference;
rmeddis@0 240
rmeddis@0 241 case {'forwardMasking','forwardMaskingD','trainingIFMC', ...
rmeddis@38 242 'TMC','TMC_16ms', 'TMC - ELP', 'IFMC','IFMC_8ms', ...
rmeddis@38 243 'FMreProbe'}
rmeddis@0 244 % cue masker is weaker to make target more audible
rmeddis@0 245 cueMaskerLevel=maskerLevel-cueTestDifference;
rmeddis@0 246 end
rmeddis@0 247 end
rmeddis@0 248
rmeddis@38 249 % thresholds (in dB SPL) of the single tone with 12 frequencies:
rmeddis@38 250 % 1 2 3 4 5 6 7 8 9 10 11 12
rmeddis@38 251 % 494, 663, 870, 1125, 1442, 1838, 2338, 2957, 3725, 4689, 5866, 7334
rmeddis@38 252
rmeddis@38 253 % 2. ‘OHIOtemp’ is for measuring thresholds for temporally integrated
rmeddis@38 254 % combinations of 2, 4, 8, and 12 tones presented simultaneously.
rmeddis@38 255 % In our experiment, we used 4680Hz frequency.
rmeddis@38 256
rmeddis@38 257 % 3. ‘OHIOspec’ is for measuring thresholds for spectrally integrated
rmeddis@38 258 % combinations of 2(7335 and 5866Hz), 4(7334, 5866, 4680, and 3725Hz),
rmeddis@38 259 % 8(7334, 5866, 4680, 3725, 2957, 2338, 1838, and
rmeddis@38 260 % 1442Hz), and
rmeddis@38 261 % 12(all 12 frequencies) tones presented simultaneously.
rmeddis@38 262
rmeddis@38 263 % 4. ‘OHIOspectemp’ is for measuring thresholds for patterned signals
rmeddis@38 264 % differing in both the spectral and temporal domains.
rmeddis@38 265 % The frequency conditions are the same as that of ‘OHIOspec’.
rmeddis@38 266
rmeddis@38 267 % 5. ‘OHIOrand’ is for measuring thresholds for spectrotemporally varying
rmeddis@38 268 % signals with random frequency presentation.
rmeddis@38 269
rmeddis@38 270 switch experiment.paradigm(1:3)
rmeddis@38 271 case 'OHI'
rmeddis@38 272 targetType='OHIO';
rmeddis@38 273 OHIOtype=experiment.paradigm;
rmeddis@38 274 % 1. ‘OHIOabs’ paradigm is a baseline procedure for measuring absolute
rmeddis@38 275
rmeddis@38 276 nTones=betweenRuns.var1Sequence(betweenRuns.runNumber);
rmeddis@38 277 allFreqs=[494, 663, 870, 1125, 1442, 1838, 2338, 2957, 3725, 4689, 5866, 7334];
rmeddis@38 278 toneLevelBoost= ...
rmeddis@38 279 [1 0 0 1 1 4 8 12 12 14 17 19 ];
rmeddis@38 280
rmeddis@38 281
rmeddis@38 282 % for nTones=nTonesList
rmeddis@38 283 switch experiment.paradigm
rmeddis@38 284 % case ' OHIOabs'
rmeddis@38 285 % % one tone frequency at a time
rmeddis@38 286 % stim.frequencies=allFreqs(1);
rmeddis@38 287 % stim.amplitudesdB=0;
rmeddis@38 288
rmeddis@38 289 case 'OHIOrand'
rmeddis@38 290 % chose nTones frequencies at random
rmeddis@38 291 x=rand(1,12);
rmeddis@38 292 [sorted idx]=sort(x);
rmeddis@38 293 cueTargetFrequency=allFreqs(idx(1:nTones));
rmeddis@38 294 cueTargetLevel=toneLevelBoost(idx)+...
rmeddis@38 295 targetLevel + cueTestDifference;
rmeddis@38 296 targetFrequency=allFreqs(idx(1:nTones));
rmeddis@38 297 targetLevel=targetLevel + toneLevelBoost(idx);
rmeddis@38 298
rmeddis@38 299 case 'OHIOtemp'
rmeddis@38 300 % 4680 Hz repeated nTones times
rmeddis@38 301 cueTargetFrequency=4680*ones(1,nTones);
rmeddis@38 302 cueTargetLevel=repmat(toneLevelBoost(10),1,nTones)+...
rmeddis@38 303 targetLevel + cueTestDifference;
rmeddis@38 304 targetFrequency=4680*ones(1,nTones);
rmeddis@38 305 targetLevel= targetLevel+repmat(toneLevelBoost(10),1,nTones);
rmeddis@38 306
rmeddis@38 307 case {'OHIOspect', 'OHIOspectemp'}
rmeddis@38 308 % nTones frequencies either simulataneously or sequentially
rmeddis@38 309 switch nTones
rmeddis@38 310 case 2
rmeddis@38 311 cueTargetFrequency=[7335 5866];
rmeddis@38 312 targetFrequency=[7335 5866];
rmeddis@38 313 idx=[12 11];
rmeddis@38 314 cueTargetLevel=targetLevel + toneLevelBoost(idx)+cueTestDifference;
rmeddis@38 315 targetLevel=targetLevel + toneLevelBoost(idx);
rmeddis@38 316 case 4
rmeddis@38 317 cueTargetFrequency=[7334, 5866, 4680, 3725];
rmeddis@38 318 targetFrequency=[7334, 5866, 4680, 3725];
rmeddis@38 319 idx=[12:-1:9 ];
rmeddis@38 320 cueTargetLevel=targetLevel + toneLevelBoost(idx)+cueTestDifference;
rmeddis@38 321 targetLevel=targetLevel + toneLevelBoost(idx);
rmeddis@38 322 case 8
rmeddis@38 323 cueTargetFrequency=...
rmeddis@38 324 [7334, 5866, 4680, 3725, 2957, 2338, 1838, 1442];
rmeddis@38 325 targetFrequency=...
rmeddis@38 326 [7334, 5866, 4680, 3725, 2957, 2338, 1838, 1442];
rmeddis@38 327 idx=[12:-1:5 ];
rmeddis@38 328 cueTargetLevel=targetLevel + toneLevelBoost(idx)+cueTestDifference;
rmeddis@38 329 targetLevel=targetLevel + toneLevelBoost(idx);
rmeddis@38 330 case 12
rmeddis@38 331 cueTargetFrequency=allFreqs;
rmeddis@38 332 targetFrequency=allFreqs;
rmeddis@38 333 cueTargetLevel=targetLevel + toneLevelBoost(1:12)+cueTestDifference;
rmeddis@38 334 targetLevel=targetLevel + toneLevelBoost(1:12);
rmeddis@38 335 end
rmeddis@38 336 end
rmeddis@38 337
rmeddis@38 338 otherwise
rmeddis@38 339 OHIOtype='none';
rmeddis@38 340 end
rmeddis@38 341
rmeddis@38 342 switch experiment.paradigm(1:3)
rmeddis@38 343 case 'OHI'
rmeddis@38 344
rmeddis@38 345 switch experiment.threshEstMethod
rmeddis@38 346 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@38 347 % the cue stimulus (masker + probe) is the 'no' window
rmeddis@38 348 % the target stimulus (masker+probe) is the 'yes' window
rmeddis@38 349 % the order of presentation is decided at the last minute.
rmeddis@38 350 cueTargetLevel=-100;
rmeddis@38 351 end
rmeddis@38 352
rmeddis@38 353
rmeddis@38 354 switch experiment.paradigm
rmeddis@38 355 case {'OHIOabs', 'OHIOspect'}
rmeddis@38 356 OHIOtoneDuration=.02+stimulusParameters.stimulusDelay;
rmeddis@38 357 globalStimParams.overallDuration=OHIOtoneDuration;
rmeddis@38 358 otherwise
rmeddis@38 359 OHIOtoneDuration=nTones*0.02+stimulusParameters.stimulusDelay;
rmeddis@38 360 globalStimParams.overallDuration=OHIOtoneDuration;
rmeddis@38 361 end
rmeddis@38 362 end
rmeddis@38 363
rmeddis@0 364 % ----------------------------- catch trial
rmeddis@0 365 if withinRuns.catchTrial
rmeddis@0 366 targetLevel=-100; % no target
rmeddis@0 367 end
rmeddis@0 368
rmeddis@17 369 % ----------------------------- calibration of sound output
rmeddis@35 370 % seperate calibration for each frequency to match headphones
rmeddis@17 371 calibrationCorrectiondB=stimulusParameters.calibrationdB;
rmeddis@17 372 if calibrationCorrectiondB<-50
rmeddis@17 373 if maskerFrequency==targetFrequency
rmeddis@17 374 load 'calibrationFile' % calibrationFrequency calibrationAttenutation
rmeddis@17 375 idx=find(calibrationFrequency==targetFrequency);
rmeddis@17 376 if isempty(idx)
rmeddis@35 377 error('Calibration by file; frequency not found')
rmeddis@17 378 else
rmeddis@17 379 calibrationCorrectiondB=calibrationAttenutation(idx)
rmeddis@17 380 end
rmeddis@17 381 else
rmeddis@17 382 error('calibration by file requested but masker frequency is not the same as target')
rmeddis@17 383 end
rmeddis@17 384 end
rmeddis@17 385
rmeddis@17 386
rmeddis@0 387 % -------------------------------------- Checks on excessive signal level
rmeddis@0 388
rmeddis@0 389 % clipping is relevant only for soundcard use (not modelling)
rmeddis@0 390 switch experiment.ear
rmeddis@0 391 case {'left', 'right', 'diotic',...
rmeddis@0 392 'dichotic', 'dioticLeft', 'dichoticRight'}
rmeddis@0 393 experiment.headphonesUsed=1;
rmeddis@0 394 otherwise
rmeddis@0 395 experiment.headphonesUsed=0;
rmeddis@0 396 end
rmeddis@0 397
rmeddis@0 398 % NB calibration *reduces* the level of the soundCard output
rmeddis@0 399 switch experiment.ear
rmeddis@0 400 case {'left', 'right', 'diotic',...
rmeddis@0 401 'dichotic', 'dioticLeft', 'dichoticRight'}
rmeddis@17 402 clippingLevel=91+calibrationCorrectiondB;
rmeddis@0 403 soundCardMinimum=clippingLevel-20*log10(2^24);
rmeddis@0 404 otherwise
rmeddis@0 405 clippingLevel=inf;
rmeddis@0 406 soundCardMinimum=-inf;
rmeddis@0 407 end
rmeddis@0 408
rmeddis@0 409 % Check for extreme WRV values and abort if necessary
rmeddis@0 410 % WRVname specifies the value that changes from trial to trial
rmeddis@0 411 withinRuns.forceThreshold=[];
rmeddis@0 412 switch stimulusParameters.WRVname
rmeddis@0 413 % check for extreme values. Note that one of the tones might be switched off
rmeddis@0 414 case 'maskerLevel'
rmeddis@0 415 upperLevel=stimulusParameters.WRVlimits(2);
rmeddis@0 416 lowerLevel=stimulusParameters.WRVlimits(1);
rmeddis@0 417 if max(maskerLevel, cueMaskerLevel)> upperLevel
rmeddis@0 418 errormsg=['Level(' num2str(max(maskerLevel,cueMaskerLevel)) ...
rmeddis@0 419 ') is too high ***'];
rmeddis@0 420 withinRuns.forceThreshold=upperLevel;
rmeddis@0 421 withinRuns.forceThreshold=NaN;
rmeddis@0 422 return
rmeddis@0 423 end
rmeddis@0 424 if max(maskerLevel, cueMaskerLevel)< lowerLevel
rmeddis@0 425 errormsg=['Level(' num2str(max(maskerLevel,cueMaskerLevel)) ...
rmeddis@0 426 ') is too low ***'];
rmeddis@0 427 withinRuns.forceThreshold=lowerLevel;
rmeddis@0 428 withinRuns.forceThreshold=NaN;
rmeddis@0 429 return
rmeddis@0 430 end
rmeddis@0 431
rmeddis@0 432 if max(maskerLevel, cueMaskerLevel)> clippingLevel
rmeddis@0 433 errormsg=['Level(' num2str(max(maskerLevel,cueMaskerLevel)) ...
rmeddis@0 434 ') is clipping ***'];
rmeddis@0 435 withinRuns.forceThreshold=clippingLevel;
rmeddis@0 436 withinRuns.forceThreshold=NaN;
rmeddis@0 437 return
rmeddis@0 438 end
rmeddis@17 439
rmeddis@0 440 case 'targetLevel'
rmeddis@0 441 upperLevel=stimulusParameters.WRVlimits(2);
rmeddis@0 442 lowerLevel=stimulusParameters.WRVlimits(1);
rmeddis@0 443 if ~withinRuns.catchTrial
rmeddis@0 444 if max(targetLevel, cueTargetLevel)> upperLevel
rmeddis@0 445 errormsg=['target level (' ...
rmeddis@0 446 num2str(max(targetLevel, cueTargetLevel)) ...
rmeddis@0 447 ') is too high ***'];
rmeddis@0 448 withinRuns.forceThreshold=upperLevel;
rmeddis@17 449 withinRuns.forceThreshold=NaN;
rmeddis@0 450 return
rmeddis@0 451 end
rmeddis@0 452 if max(targetLevel, cueTargetLevel)< lowerLevel
rmeddis@0 453 errormsg=['target level (' ...
rmeddis@0 454 num2str(max(targetLevel, cueTargetLevel)) ...
rmeddis@0 455 ') is too low ***'];
rmeddis@0 456 withinRuns.forceThreshold=lowerLevel;
rmeddis@17 457 withinRuns.forceThreshold=NaN;
rmeddis@0 458 return
rmeddis@0 459 end
rmeddis@0 460 if max(targetLevel, cueTargetLevel)> clippingLevel
rmeddis@0 461 errormsg=['target level (' ...
rmeddis@0 462 num2str(max(targetLevel, cueTargetLevel)) ...
rmeddis@0 463 ') is clipping ***'];
rmeddis@0 464 withinRuns.forceThreshold=upperLevel;
rmeddis@17 465 withinRuns.forceThreshold=NaN;
rmeddis@0 466 return
rmeddis@0 467 end
rmeddis@17 468 end
rmeddis@0 469 case 'maskerDuration'
rmeddis@0 470 % this is odd! but harmless
rmeddis@0 471 if max(maskerDuration, cueMaskerDuration)> ...
rmeddis@0 472 stimulusParameters.WRVlimits(2)
rmeddis@0 473 errormsg=['maskerDuration (' ...
rmeddis@0 474 num2str(max(maskerDuration, cueMaskerDuration))...
rmeddis@0 475 ') is too long ***'];
rmeddis@0 476 withinRuns.forceThreshold=stimulusParameters.WRVlimits(2);
rmeddis@0 477 withinRuns.forceThreshold=NaN;
rmeddis@0 478 return
rmeddis@0 479 end
rmeddis@0 480
rmeddis@0 481 if min(maskerDuration, cueMaskerDuration)...
rmeddis@0 482 < stimulusParameters.WRVlimits(1)
rmeddis@0 483 errormsg=['maskerDuration (' num2str(maskerLevel) ...
rmeddis@0 484 ') too short ***'];
rmeddis@0 485 withinRuns.forceThreshold=stimulusParameters.WRVlimits(1);
rmeddis@0 486 withinRuns.forceThreshold=NaN;
rmeddis@0 487 return
rmeddis@0 488 end
rmeddis@0 489
rmeddis@38 490 case 'gapDuration'
rmeddis@0 491 % legacy programming
rmeddis@0 492 if gapDuration<0
rmeddis@0 493 errormsg=['gapDuration (' num2str(gapDuration) ...
rmeddis@0 494 ') is less than zero ***'];
rmeddis@0 495 return
rmeddis@0 496 end
rmeddis@0 497
rmeddis@0 498 case 'maskerFrequency'
rmeddis@0 499 switch experiment.paradigm
rmeddis@0 500 case 'bandwidth'
rmeddis@0 501 frequency=maskerFrequency';
rmeddis@0 502 if stimulusParameters.WRVstep<0
rmeddis@0 503 lowerLevel=stimulusParameters.targetFrequency;
rmeddis@0 504 upperLevel=stimulusParameters.targetFrequency*2;
rmeddis@0 505 else
rmeddis@0 506 lowerLevel=stimulusParameters.targetFrequency/3;
rmeddis@0 507 upperLevel=stimulusParameters.targetFrequency;
rmeddis@0 508 end
rmeddis@0 509
rmeddis@0 510 if frequency(1)>upperLevel || frequency(1)<lowerLevel
rmeddis@0 511 errormsg=['frequency out of range: ' ...
rmeddis@0 512 num2str(frequency)];
rmeddis@0 513 withinRuns.forceThreshold=frequency;
rmeddis@0 514 return
rmeddis@0 515 end
rmeddis@0 516 otherwise
rmeddis@0 517 end
rmeddis@0 518
rmeddis@0 519 case 'maskerRelativeFrequency'
rmeddis@0 520 if maskerRelativeFrequency<stimulusParameters.WRVlimits(1)
rmeddis@0 521 errormsg=['masker frequency (' ...
rmeddis@0 522 num2str(frequencyDifference) ...
rmeddis@0 523 ') is outside WRV limits ***'];
rmeddis@0 524 withinRuns.forceThreshold=stimulusParameters.WRVlimits(1) ;
rmeddis@0 525 return
rmeddis@0 526 end
rmeddis@0 527 if maskerRelativeFrequency>stimulusParameters.WRVlimits(2)
rmeddis@0 528 errormsg=['masker frequency (' ...
rmeddis@0 529 num2str(frequencyDifference) ...
rmeddis@0 530 ') is outside WRV limits ***'];
rmeddis@0 531 withinRuns.forceThreshold=stimulusParameters.WRVlimits(2) ;
rmeddis@0 532 return
rmeddis@0 533 end
rmeddis@0 534
rmeddis@0 535 end
rmeddis@0 536
rmeddis@0 537 % --------------------------------Ear ----------------------------------
rmeddis@0 538 globalStimParams.ears='specified';
rmeddis@0 539 % ear: 1=left, 2=right
rmeddis@0 540 switch experiment.ear
rmeddis@0 541 case 'left'
rmeddis@0 542 maskerEar=1;
rmeddis@0 543 targetEar=1;
rmeddis@0 544 case 'right'
rmeddis@0 545 maskerEar=2;
rmeddis@0 546 targetEar=2;
rmeddis@0 547 case 'dichoticLeft'
rmeddis@0 548 maskerEar=2;
rmeddis@0 549 targetEar=1;
rmeddis@0 550 case 'dichoticRight'
rmeddis@0 551 maskerEar=1;
rmeddis@0 552 targetEar=2;
rmeddis@0 553 case 'diotic'
rmeddis@0 554 maskerEar=1;
rmeddis@0 555 targetEar=1;
rmeddis@0 556 globalStimParams.ears='diotic';
rmeddis@0 557 case {'MAPmodel', 'MAPmodelMultiCh', 'MAPmodelSingleCh', 'MAPmodelListen',...
rmeddis@0 558 'statsModelLogistic', 'statsModelRareEvent'}
rmeddis@0 559 maskerEar=1;
rmeddis@0 560 targetEar=1;
rmeddis@0 561 end
rmeddis@0 562
rmeddis@0 563 backgroundType=stimulusParameters.backgroundType;
rmeddis@0 564 switch stimulusParameters.backgroundType
rmeddis@0 565 case {'noiseDich', 'pinkNoiseDich'}
rmeddis@17 566 % case 'Dich'
rmeddis@0 567 % dich means put the background in the ear opposite to the target
rmeddis@0 568 backgroundType=backgroundType(1:end-4);
rmeddis@0 569 switch targetEar
rmeddis@0 570 case 1
rmeddis@0 571 backgroundEar=2;
rmeddis@0 572 case 2
rmeddis@0 573 backgroundEar=1;
rmeddis@0 574 end
rmeddis@0 575 otherwise
rmeddis@17 576 % case {'none','noise', 'pinkNoise', 'TEN','babble'}
rmeddis@0 577 backgroundEar=targetEar;
rmeddis@0 578 end
rmeddis@0 579
rmeddis@0 580 % ------------------------------- Make Stimulus -------------------
rmeddis@0 581 % single interval up/down plays cue then target stimulus
rmeddis@0 582 % 2IFC uses cue stimulus as interval with no target
rmeddis@0 583 globalStimParams.FS=stimulusParameters.sampleRate;
rmeddis@0 584 dt=1/stimulusParameters.sampleRate;
rmeddis@0 585 globalStimParams.dt=dt;
rmeddis@0 586 stimulusParameters.dt=dt; % for use later
rmeddis@0 587
rmeddis@17 588
rmeddis@17 589
rmeddis@17 590 globalStimParams.audioOutCorrection=10^(calibrationCorrectiondB/20);
rmeddis@0 591 % the output will be reduced by this amount in stimulusCreate
rmeddis@0 592 % i.e. audio=audio/globalStimParams.audioOutCorrection
rmeddis@0 593 % A 91 dB level will yield a peak amp of 1 for calibration=0
rmeddis@0 594 % A 91 dB level will yield a peak amp of 0.4467 for calibration=7
rmeddis@0 595 % A 98 dB level will yield a peak amp of 1 for calibration=7
rmeddis@0 596
rmeddis@0 597 precedingSilence=stimulusParameters.stimulusDelay;
rmeddis@0 598 % all stimuli have 20 ms terminal silence.
rmeddis@0 599 % this is clearance for modelling late-ringing targets
rmeddis@0 600 terminalSilence=.03;
rmeddis@0 601
rmeddis@0 602 % Now compute overall duration of the stimulus
rmeddis@0 603 % note that all endsilence values are set to -1
rmeddis@0 604 % so that they will fill with terminal silence as required to make
rmeddis@0 605 % components equal in length
rmeddis@0 606 % We need to find the longest possible duration
rmeddis@0 607 duration(1)=precedingSilence+maskerDuration+cueGapDuration...
rmeddis@0 608 +targetDuration+terminalSilence;
rmeddis@0 609 duration(2)=precedingSilence+maskerDuration+gapDuration...
rmeddis@0 610 +targetDuration+ terminalSilence;
rmeddis@0 611 % If the gap is negative we need to ignore it when estimating total length
rmeddis@0 612 duration(3)=precedingSilence+maskerDuration+ terminalSilence;
rmeddis@0 613 globalStimParams.overallDuration=max(duration);
rmeddis@0 614 globalStimParams.nSignalPoints=...
rmeddis@30 615 round(globalStimParams.overallDuration*globalStimParams.FS);
rmeddis@0 616
rmeddis@38 617 % special case
rmeddis@38 618 switch experiment.paradigm(1:3)
rmeddis@38 619 case 'OHI'
rmeddis@38 620 switch experiment.paradigm
rmeddis@38 621 case {'OHIOabs', 'OHIOspect'}
rmeddis@38 622 OHIOtoneDuration=.02+stimulusParameters.stimulusDelay;
rmeddis@38 623 globalStimParams.overallDuration=OHIOtoneDuration;
rmeddis@38 624 otherwise
rmeddis@38 625 OHIOtoneDuration=nTones*0.02+stimulusParameters.stimulusDelay;
rmeddis@38 626 globalStimParams.overallDuration=OHIOtoneDuration;
rmeddis@38 627 end
rmeddis@38 628 end
rmeddis@38 629
rmeddis@38 630
rmeddis@0 631 % ----------------------------------------------cue stimulus
rmeddis@0 632 % cue masker
rmeddis@0 633 componentNo=1;
rmeddis@0 634 precedingSilence=stimulusParameters.stimulusDelay;
rmeddis@0 635 stimComponents(maskerEar,componentNo).type=maskerType;
rmeddis@0 636 stimComponents(maskerEar,componentNo).toneDuration=cueMaskerDuration;
rmeddis@0 637 stimComponents(maskerEar,componentNo).frequencies=cueMaskerFrequency;
rmeddis@0 638 stimComponents(maskerEar,componentNo).amplitudesdB=cueMaskerLevel;
rmeddis@0 639 stimComponents(maskerEar,componentNo).beginSilence=precedingSilence;
rmeddis@0 640 stimComponents(maskerEar,componentNo).endSilence=-1;
rmeddis@0 641 stimComponents(maskerEar,componentNo).AMfrequency=0;
rmeddis@0 642 stimComponents(maskerEar,componentNo).AMdepth=0;
rmeddis@0 643 if rampDuration<maskerDuration
rmeddis@0 644 % ramps must be shorter than the signal
rmeddis@0 645 stimComponents(maskerEar,componentNo).rampOnDur=rampDuration;
rmeddis@0 646 stimComponents(maskerEar,componentNo).rampOffDur=rampDuration;
rmeddis@0 647 else
rmeddis@0 648 % or squeeze the ramp in
rmeddis@0 649 stimComponents(maskerEar,componentNo).rampOnDur=maskerDuration/2;
rmeddis@0 650 stimComponents(maskerEar,componentNo).rampOffDur=maskerDuration/2;
rmeddis@0 651 end
rmeddis@0 652 stimComponents(maskerEar,componentNo).phases=...
rmeddis@0 653 stimulusParameters.maskerPhase;
rmeddis@0 654 stimComponents(maskerEar,componentNo).niterations=0; % for IRN only
rmeddis@0 655 % stimComponents(targetEar,componentNo)
rmeddis@0 656
rmeddis@0 657 % cue target
rmeddis@0 658 componentNo=2;
rmeddis@0 659 precedingSilence=precedingSilence + maskerDuration+cueGapDuration;
rmeddis@0 660 stimComponents(targetEar,componentNo).type=targetType;
rmeddis@38 661 stimComponents(targetEar,componentNo).OHIOtype=OHIOtype;
rmeddis@0 662 stimComponents(targetEar,componentNo).toneDuration=targetDuration;
rmeddis@0 663 stimComponents(targetEar,componentNo).frequencies=cueTargetFrequency;
rmeddis@0 664 stimComponents(targetEar,componentNo).amplitudesdB=cueTargetLevel;
rmeddis@0 665 stimComponents(targetEar,componentNo).beginSilence=precedingSilence;
rmeddis@0 666 stimComponents(targetEar,componentNo).endSilence=-1;
rmeddis@0 667 stimComponents(targetEar,componentNo).AMfrequency=0;
rmeddis@0 668 stimComponents(targetEar,componentNo).AMdepth=0;
rmeddis@0 669 if rampDuration<targetDuration
rmeddis@0 670 % ramps must be shorter than the signal
rmeddis@0 671 stimComponents(targetEar,componentNo).rampOnDur=rampDuration;
rmeddis@0 672 stimComponents(targetEar,componentNo).rampOffDur=rampDuration;
rmeddis@0 673 else
rmeddis@0 674 stimComponents(targetEar,componentNo).rampOnDur=0;
rmeddis@0 675 stimComponents(targetEar,componentNo).rampOffDur=0;
rmeddis@0 676 end
rmeddis@0 677 stimComponents(targetEar,componentNo).phases=...
rmeddis@0 678 stimulusParameters.targetPhase;
rmeddis@0 679 % stimComponents(targetEar,componentNo)
rmeddis@0 680
rmeddis@0 681 % background same ear as target
rmeddis@0 682 componentNo=3;
rmeddis@0 683 stimComponents(backgroundEar,componentNo).type=backgroundType;
rmeddis@0 684 switch backgroundType
rmeddis@0 685 case 'TEN'
rmeddis@0 686 fileName=['..' filesep '..' filesep ...
rmeddis@0 687 'multithresholdResources' filesep ...
rmeddis@0 688 'backgrounds and maskers'...
rmeddis@0 689 filesep 'ten.wav'];
rmeddis@0 690 [tenNoise, FS]=wavread(fileName);
rmeddis@0 691 tenNoise=resample(tenNoise, globalStimParams.FS, FS);
rmeddis@0 692 stimComponents(backgroundEar,componentNo).type='file';
rmeddis@0 693 stimComponents(backgroundEar,componentNo).stimulus=tenNoise';
rmeddis@0 694 end
rmeddis@0 695 stimComponents(backgroundEar,componentNo).toneDuration=...
rmeddis@0 696 globalStimParams.overallDuration;
rmeddis@0 697 stimComponents(backgroundEar,componentNo).amplitudesdB=backgroundLevel;
rmeddis@0 698 stimComponents(backgroundEar,componentNo).beginSilence=0;
rmeddis@0 699 stimComponents(backgroundEar,componentNo).endSilence=-1;
rmeddis@0 700 stimComponents(backgroundEar,componentNo).AMfrequency=0;
rmeddis@0 701 stimComponents(backgroundEar,componentNo).AMdepth=0;
rmeddis@0 702 stimComponents(backgroundEar,componentNo).rampOnDur=rampDuration;
rmeddis@0 703 stimComponents(backgroundEar,componentNo).rampOffDur=rampDuration;
rmeddis@0 704
rmeddis@0 705 [cueStimulus, errormsg]=...
rmeddis@0 706 stimulusCreate(globalStimParams, stimComponents, 0);
rmeddis@0 707 if ~isempty(errormsg) % e.g. limits exceeded
rmeddis@0 708 errormsg
rmeddis@0 709 return
rmeddis@0 710 end
rmeddis@0 711
rmeddis@0 712 % ------------------------------------------ test stimulus
rmeddis@0 713 % masker
rmeddis@0 714 componentNo=1;
rmeddis@0 715 precedingSilence=stimulusParameters.stimulusDelay;
rmeddis@0 716 stimComponents(maskerEar,componentNo).type=maskerType;
rmeddis@0 717 stimComponents(maskerEar,componentNo).toneDuration=maskerDuration;
rmeddis@0 718 stimComponents(maskerEar,componentNo).frequencies=maskerFrequency;
rmeddis@0 719 stimComponents(maskerEar,componentNo).amplitudesdB=maskerLevel;
rmeddis@0 720 stimComponents(maskerEar,componentNo).beginSilence=precedingSilence;
rmeddis@0 721 stimComponents(maskerEar,componentNo).endSilence=-1;
rmeddis@0 722 stimComponents(maskerEar,componentNo).AMfrequency=0;
rmeddis@0 723 stimComponents(maskerEar,componentNo).AMdepth=0;
rmeddis@0 724 if rampDuration<maskerDuration
rmeddis@0 725 % ramps must be shorter than the signal
rmeddis@0 726 stimComponents(maskerEar,componentNo).rampOnDur=rampDuration;
rmeddis@0 727 stimComponents(maskerEar,componentNo).rampOffDur=rampDuration;
rmeddis@0 728 else
rmeddis@0 729 stimComponents(maskerEar,componentNo).rampOnDur=maskerDuration/2;
rmeddis@0 730 stimComponents(maskerEar,componentNo).rampOffDur=maskerDuration/2;
rmeddis@0 731 end
rmeddis@0 732 stimComponents(maskerEar,componentNo).phases=...
rmeddis@0 733 stimulusParameters.maskerPhase;
rmeddis@0 734 stimComponents(maskerEar,componentNo).niterations=0; % for IRN only
rmeddis@0 735
rmeddis@0 736 % target
rmeddis@0 737 componentNo=2;
rmeddis@0 738 targetDelay=precedingSilence+ maskerDuration+ gapDuration;
rmeddis@0 739 stimComponents(targetEar,componentNo).type=targetType;
rmeddis@38 740 stimComponents(targetEar,componentNo).OHIOtype=OHIOtype;
rmeddis@0 741 stimComponents(targetEar,componentNo).toneDuration=targetDuration;
rmeddis@0 742 stimComponents(targetEar,componentNo).frequencies=targetFrequency;
rmeddis@0 743 stimComponents(targetEar,componentNo).amplitudesdB=targetLevel;
rmeddis@0 744 stimComponents(targetEar,componentNo).beginSilence=targetDelay;
rmeddis@0 745 stimComponents(targetEar,componentNo).endSilence=-1;
rmeddis@0 746 stimComponents(targetEar,componentNo).AMfrequency=0;
rmeddis@0 747 stimComponents(targetEar,componentNo).AMdepth=0;
rmeddis@0 748 if rampDuration<targetDuration
rmeddis@0 749 % ramps must be shorter than the signal
rmeddis@0 750 stimComponents(targetEar,componentNo).rampOnDur=rampDuration;
rmeddis@0 751 stimComponents(targetEar,componentNo).rampOffDur=rampDuration;
rmeddis@0 752 else
rmeddis@0 753 stimComponents(targetEar,componentNo).rampOnDur=0;
rmeddis@0 754 stimComponents(targetEar,componentNo).rampOffDur=0;
rmeddis@0 755 end
rmeddis@0 756 stimComponents(targetEar,componentNo).phases=stimulusParameters.targetPhase;
rmeddis@0 757 % stimComponents(targetEar,componentNo)
rmeddis@0 758
rmeddis@0 759 % background same ear as target
rmeddis@0 760 componentNo=3;
rmeddis@0 761 stimComponents(backgroundEar,componentNo).type=backgroundType;
rmeddis@0 762 switch backgroundType
rmeddis@0 763 case 'TEN'
rmeddis@0 764 fileName=['..' filesep '..' filesep ...
rmeddis@0 765 'multithresholdResources' filesep ...
rmeddis@0 766 'backgrounds and maskers'...
rmeddis@0 767 filesep 'ten.wav'];
rmeddis@0 768 [tenNoise, FS]=wavread(fileName);
rmeddis@17 769
rmeddis@0 770 tenNoise=resample(tenNoise, globalStimParams.FS, FS);
rmeddis@0 771 stimComponents(backgroundEar,componentNo).type='file';
rmeddis@0 772 stimComponents(backgroundEar,componentNo).stimulus=tenNoise';
rmeddis@0 773 end
rmeddis@0 774 stimComponents(backgroundEar,componentNo).toneDuration=...
rmeddis@0 775 globalStimParams.overallDuration;
rmeddis@0 776 stimComponents(backgroundEar,componentNo).amplitudesdB=backgroundLevel;
rmeddis@0 777 stimComponents(backgroundEar,componentNo).beginSilence=0;
rmeddis@0 778 stimComponents(backgroundEar,componentNo).endSilence=-1;
rmeddis@0 779 stimComponents(backgroundEar,componentNo).rampOnDur=rampDuration;
rmeddis@0 780 stimComponents(backgroundEar,componentNo).rampOffDur=rampDuration;
rmeddis@0 781 stimComponents(backgroundEar,componentNo).AMfrequency=0;
rmeddis@0 782 stimComponents(backgroundEar,componentNo).AMdepth=0;
rmeddis@0 783
rmeddis@0 784 % timings used when evaluating MAP peripheral model
rmeddis@0 785 % this is the Slope during which spikes are counted
rmeddis@0 786 switch experiment.paradigm
rmeddis@0 787 case 'gapDetection'
rmeddis@0 788 % gap is the 'target' in this case
rmeddis@0 789 stimulusParameters.testTargetBegins=...
rmeddis@0 790 stimulusParameters.stimulusDelay...
rmeddis@0 791 +stimulusParameters.maskerDuration;
rmeddis@0 792 stimulusParameters.testTargetEnds=...
rmeddis@0 793 stimulusParameters.testTargetBegins+withinRuns.variableValue;
rmeddis@17 794 % case 'SRT'
rmeddis@17 795 % set(handles.editdigitInput,'visible','off')
rmeddis@0 796 otherwise
rmeddis@38 797 switch experiment.paradigm(1:3)
rmeddis@38 798 case 'OHI'
rmeddis@38 799 stimulusParameters.testTargetBegins=0;
rmeddis@38 800 stimulusParameters.testTargetEnds=OHIOtoneDuration;
rmeddis@38 801 otherwise
rmeddis@38 802 stimulusParameters.testTargetBegins=targetDelay;
rmeddis@38 803 stimulusParameters.testTargetEnds=targetDelay+targetDuration;
rmeddis@38 804 end
rmeddis@0 805 end
rmeddis@0 806
rmeddis@0 807 % ------------------------------------------------------------- play!
rmeddis@0 808 % Create and play stimulus (as required by different paradigms)
rmeddis@0 809 switch experiment.ear
rmeddis@0 810 case {'statsModelLogistic', 'statsModelRareEvent'}
rmeddis@0 811 audio=[0;0]; % no need to compute stimulus
rmeddis@0 812
rmeddis@0 813 otherwise % create the stimulus
rmeddis@0 814 [targetStimulus, errormsg]= ...
rmeddis@0 815 stimulusCreate(globalStimParams, stimComponents, 0);
rmeddis@0 816
rmeddis@0 817 if ~isempty(errormsg) % e.g. limits exceeded
rmeddis@0 818 errormsg
rmeddis@0 819 return
rmeddis@0 820 end
rmeddis@0 821
rmeddis@0 822 switch experiment.ear
rmeddis@0 823 case {'MAPmodel' , 'MAPmodelMultiCh', 'MAPmodelSingleCh', 'MAPmodelListen'}
rmeddis@0 824 % model requires no calibration correction;
rmeddis@0 825 % signal is already in Pascals
rmeddis@0 826 globalStimParams.audioOutCorrection=1;
rmeddis@0 827 % use only the targetStimulus for the MAP model
rmeddis@0 828 audio=targetStimulus;
rmeddis@0 829
rmeddis@0 830 otherwise % left, right diotic dichotic
rmeddis@0 831 if stimulusParameters.includeCue
rmeddis@0 832 audio= [cueStimulus; targetStimulus];
rmeddis@0 833 else % no cue
rmeddis@0 834 audio=targetStimulus;
rmeddis@0 835 end
rmeddis@0 836 end
rmeddis@0 837
rmeddis@0 838 % playtime
rmeddis@0 839 % order of the cue and test stimuli varies for 2AFC
rmeddis@0 840 switch experiment.threshEstMethod
rmeddis@0 841 case {'2I2AFC++', '2I2AFC+++'}
rmeddis@0 842 % intervening silence (currently none; masking delay serves this purpose)
rmeddis@0 843 IAFCinterveningSilence=zeros(round(AFCsilenceDuration/dt),2);
rmeddis@0 844 if rand>0.5 % put test stimulus first
rmeddis@0 845 stimulusParameters.testTargetBegins=targetDelay ;
rmeddis@0 846 stimulusParameters.testTargetEnds= ...
rmeddis@0 847 targetDelay+targetDuration;
rmeddis@0 848 stimulusParameters.testNonTargetBegins=...
rmeddis@0 849 length(cueStimulus)*dt ...
rmeddis@0 850 + AFCsilenceDuration +targetDelay ;
rmeddis@0 851 stimulusParameters.testNonTargetEnds=...
rmeddis@0 852 length(cueStimulus)*dt ...
rmeddis@0 853 + AFCsilenceDuration+targetDelay+targetDuration;
rmeddis@0 854
rmeddis@0 855 set(handles.pushbutton1,'backgroundcolor','r'), drawnow
rmeddis@0 856 y=audioplayer(targetStimulus, globalStimParams.FS, 24);
rmeddis@0 857 playblocking(y)
rmeddis@0 858 set(handles.pushbutton1,'backgroundcolor',...
rmeddis@0 859 get(0,'defaultUicontrolBackgroundColor')), drawnow
rmeddis@0 860 y=audioplayer(IAFCinterveningSilence, ...
rmeddis@0 861 globalStimParams.FS, 24);
rmeddis@0 862 playblocking(y)
rmeddis@0 863 set(handles.pushbutton2,'backgroundcolor','r'), drawnow
rmeddis@0 864 y=audioplayer(cueStimulus, globalStimParams.FS, 24);
rmeddis@0 865 playblocking(y)
rmeddis@0 866 set(handles.pushbutton2,'backgroundcolor',...
rmeddis@0 867 get(0,'defaultUicontrolBackgroundColor')), drawnow
rmeddis@0 868 withinRuns.stimulusOrder='targetFirst';
rmeddis@0 869 audio= [targetStimulus; IAFCinterveningSilence; ...
rmeddis@0 870 cueStimulus]; % for plotting purposes later
rmeddis@0 871
rmeddis@0 872 else % put test stimulus second
rmeddis@0 873 stimulusParameters.testTargetBegins=...
rmeddis@0 874 length(cueStimulus)*dt ...
rmeddis@0 875 + AFCsilenceDuration +targetDelay ;
rmeddis@0 876 stimulusParameters.testTargetEnds=...
rmeddis@0 877 length(cueStimulus)*dt ...
rmeddis@0 878 + AFCsilenceDuration+targetDelay+targetDuration;
rmeddis@0 879 stimulusParameters.testNonTargetBegins=targetDelay ;
rmeddis@0 880 stimulusParameters.testNonTargetEnds=...
rmeddis@0 881 targetDelay+targetDuration;
rmeddis@0 882
rmeddis@0 883 set(handles.pushbutton1,'backgroundcolor','r'),drawnow
rmeddis@0 884 y=audioplayer(cueStimulus, globalStimParams.FS, 24);
rmeddis@0 885 playblocking(y)
rmeddis@0 886 set(handles.pushbutton1,'backgroundcolor',...
rmeddis@0 887 get(0,'defaultUicontrolBackgroundColor')), drawnow
rmeddis@0 888 y=audioplayer(IAFCinterveningSilence, ...
rmeddis@0 889 globalStimParams.FS, 24);
rmeddis@0 890 playblocking(y)
rmeddis@0 891 set(handles.pushbutton2,'backgroundcolor','r'), drawnow
rmeddis@0 892 y=audioplayer(targetStimulus, globalStimParams.FS, 24);
rmeddis@0 893 playblocking(y)
rmeddis@0 894 set(handles.pushbutton2,'backgroundcolor',...
rmeddis@0 895 get(0,'defaultUicontrolBackgroundColor')), drawnow
rmeddis@0 896 withinRuns.stimulusOrder='targetSecond';
rmeddis@0 897 audio= [cueStimulus; IAFCinterveningSilence; ...
rmeddis@0 898 targetStimulus]; % for plotting purposes later
rmeddis@0 899 end
rmeddis@0 900 otherwise % singleInterval
rmeddis@0 901 if strcmp(experiment.ear,'MAPmodel') ...
rmeddis@0 902 || strcmp(experiment.ear,'MAPmodelMultiCh') ...
rmeddis@0 903 || strcmp(experiment.ear,'MAPmodelSingleCh') ...
rmeddis@0 904 ||strcmp(experiment.ear,'MAPmodelListen')
rmeddis@0 905 % don't play for MAPmodel
rmeddis@0 906 switch experiment.ear
rmeddis@0 907 % except on special request
rmeddis@0 908 case {'MAPmodelListen'}
rmeddis@0 909 y=audioplayer(audio, globalStimParams.FS, 24);
rmeddis@0 910 playblocking(y) % suspends operations until completed
rmeddis@0 911 end
rmeddis@0 912 else
rmeddis@0 913 y=audioplayer(audio, globalStimParams.FS, 24);
rmeddis@0 914 playblocking(y)
rmeddis@0 915 end % if experiment.ear
rmeddis@0 916 end % switch experiment.threshEstMethod
rmeddis@0 917 end % switch experiment.ear
rmeddis@0 918
rmeddis@0 919
rmeddis@0 920 % switch experiment.ear
rmeddis@0 921 % case {'MAPmodel', 'MAPmodelListen', 'MAPmodelMultiCh','MAPmodelSingleCh'}
rmeddis@0 922 % % save audio for later reference or for input to MAP model
rmeddis@0 923 % wavwrite(audio/max(audio), globalStimParams.FS,32,'stimulus')
rmeddis@0 924 % end
rmeddis@0 925
rmeddis@0 926 % Panel 1
rmeddis@0 927 % graphical presentation of the stimulus
rmeddis@0 928 % NB shown *after* the stimulus has been presented
rmeddis@0 929 axes(expGUIhandles.axes1), cla
rmeddis@0 930 % plot is HW rectified and plotted as dB re 28e-6
rmeddis@0 931 % calibration is ignored
rmeddis@0 932 t=dt:dt:dt*length(audio);
rmeddis@0 933 plot(t,stimulusParameters.calibrationdB+20*log10((abs(audio)+1e-10)/28e-6))
rmeddis@0 934 % set(gca,'xtick',[])
rmeddis@0 935 ylim([-20 100])
rmeddis@0 936 ylabel('stimulus (dB SPL)')
rmeddis@0 937 xlim([0 t(end)])
rmeddis@0 938 grid on
rmeddis@0 939 header=[betweenRuns.variableName1 ': ' ...
rmeddis@0 940 num2str(betweenRuns.var1Sequence(betweenRuns.runNumber))];
rmeddis@0 941 header=[header ' ' num2str(...
rmeddis@0 942 betweenRuns.var2Sequence(betweenRuns.runNumber)) ':' ...
rmeddis@0 943 betweenRuns.variableName2 ];
rmeddis@0 944 title(header)
rmeddis@0 945