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