This file is indexed.

/usr/share/psychtoolbox-3/PsychDemos/SimpleVoiceTriggerDemo.m is in psychtoolbox-3-common 3.0.9+svn2579.dfsg1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
function SimpleVoiceTriggerDemo(triggerlevel)
% SimpleVoiceTriggerDemo(triggerlevel)
%
% Demonstrates very basic usage of the new Psychtoolbox sound driver
% PsychPortAudio() for implementation of a "voice trigger". This really
% only collects the "voice response time" it doesn't actually store the
% resonse itself. Have a look at BasicSoundInputDemo for how one can
% actually retrieve and save the sound vector with the response itself.
%
% The script relies on well working sound cards and drivers. It should
% "just work" on most MacOS/X and Linux systems with standard hardware, but
% it will need special ASIO capable sound hardware on MS-Windows for
% accurate timing! See "help InitializePsychSound" for details.
%
% In any case you *must* verify correct timing of your sound hardware with
% some external measurement equipment, e.g., in conjunction with the
% PsychPortAudioTimingTest script (or the AudioFeedbackLatencyTest for a
% crude test). You only need to do this once after major changes to your
% systems software, hardware or Psychtoolbox installation, but there isn't
% any sane way to avoid such a validation!
%
% There are two different methods demonstrated to do so. Please read the
% source code of this file for details.
%
% In method I:
%
% The "response window" is fixed to 5 seconds. A trial will always last 5
% seconds, regardless if you respond early, late, or not at all.
%
%
% In method II:
%
% Sound is captured from the default recording device, waiting
% until the amplitude exceeds some 'triggerlevel'.
%
% If the triggerlevel is exceeded, sound capture stops, returning the
% estimated time of "voice onset" in system time.
%

% History:
% 08/10/2008 Written (MK)

if nargin < 1
    triggerlevel = 0.1;
    fprintf('No "triggerlevel" argument in range 0.0 to 1.0 provided: Will use default of 0.1...\n\n');
end

% Perform basic initialization of the sound driver, initialize for
% low-latency, high timing precision mode:
InitializePsychSound(1);

% Open the default audio device [], with mode 2 (== Only audio capture),
% and a required latencyclass of two 2 == low-latency mode, as well as
% a frequency of 44100 Hz and 2 sound channels for stereo capture. We also
% set the required latency to a pretty high 20 msecs. Why? Because we don't
% actually need low-latency here, we only need low-latency mode of
% operation so we get maximum timing precision -- Therefore we request
% low-latency mode, but loosen our requirement to 20 msecs.
%
% This returns a handle to the audio device:
freq = 44100;
pahandle = PsychPortAudio('Open', [], 2, 2, freq, 2, [], 0.02);

fprintf('\n\nPART I - Simple "offline" response collection at end of trial.\n');
fprintf('Each trials response period lasts 5 seconds...\n\n');

% FIRST METHOD: Supersimple
% This is suitable if the duration of the response collection period / the
% duration of a trial is fixed and if the script does not need to respond
% in any way to voice onset -- if the "voice trigger" is actually not
% triggering anything, but just the onset timestamp is of interest.
%
% In this case we simply start sound recording at the beginning of the
% trial - into a sound buffer of fixed and sufficient capacity.
% At the end of a trial (or a response period), we stop recording, fetch
% all audio data from the buffer (as well as a timestamp of when exactly
% recording was started), then use some simple Matlab thresholding code to
% find the first sample in the sound data vector which is above threshold,
% ie., the sample of response onset. Then we translate that samples index
% into a relative time to start of recording, add that to the absolute
% start time of recording, and get the absolute system time of voice onset,
% which we can log, or compare to other timestamps from Screen('Flip'),
% GetSecs, whatever to compute reaction times.

% Preallocate an internal audio recording  buffer with a generous capacity
% of 10 seconds: We only need about 5 seconds, but let's be generous...
PsychPortAudio('GetAudioData', pahandle, 10);


% Do five trials:
for trial = 1:5
    % Start audio capture immediately and wait for the capture to start.
    % We set the number of 'repetitions' to zero, i.e. record until recording
    % is manually stopped.
    PsychPortAudio('Start', pahandle, 0, 0, 1);

    % Tell user to shout:
    fprintf('Make noise! Make noise!          ');
    tStim = GetSecs;
    
    % Wait for about 5 seconds, so user has time to shout:
    WaitSecs(5);
    
    % Stop sound capture: End of response period.
    PsychPortAudio('Stop', pahandle);

    % Fetch all about 5 seconds of audiodata at once:
    [audiodata offset overflow tCaptureStart]= PsychPortAudio('GetAudioData', pahandle);

    % Ok, last fetched chunk was above threshold!
    % Find exact location of first above threshold sample.
    idx = min(find(abs(audiodata(1,:)) >= triggerlevel)); %#ok<MXFND>
        
    % Any response?
    if isempty(idx)
        fprintf('No response at all within 5 seconds?!?\n\n');
    else
        % Compute absolute event time:
        tOnset = tCaptureStart + ((offset + idx - 1) / freq);

        % Print RT:
        fprintf('---> Reaction time is %f milliseconds.\n', (tOnset - tStim)*1000);
    end
        
    % Next trial after 2 seconds:
    WaitSecs(2);
end

% Done with method I. You'd now close the audio device, but we'll do that
% at the end of this script instead...

% =========================================================================

% SECOND METHOD: Slightly more elaborate
% The principle is the same as in method I, but now we don't analyze the
% whole chunk of audio data at the end of trial, but we implement some
% polling loop which periodically fetches small consecutive chunks of sound
% data and does the analysis. This way, response collection / stimulus
% presentation / whatever can be stopped as soon as we have our voice onset
% timestamp --> The voice trigger can actually really trigger some action
% in our script! This also allows for "infinite" response collection -- as
% we're only chewing on small chunks of audio data, the total duration of
% response collection is not in any way limited by available memory or
% such.

fprintf('\n\nPART II - The saga continues... This time with a polling method.\n\n');

% Do ten trials:
for trial = 1:10
    % Preallocate an internal audio recording  buffer with a generous capacity
    % of 10 seconds:
    PsychPortAudio('GetAudioData', pahandle, 10);

    % Start audio capture immediately and wait for the capture to start.
    % We set the number of 'repetitions' to zero, i.e. record until recording
    % is manually stopped.
    PsychPortAudio('Start', pahandle, 0, 0, 1);

    % Tell user to shout:
    fprintf('Make noise! Make noise!          ');
    tStim = GetSecs;
    
    % Wait in a polling loop until some sound event of sufficient loudness
    % is captured:
    level = 0;
    
    % Repeat as long as below trigger-threshold:
    while level < triggerlevel
        % Fetch current audiodata:
        [audiodata offset overflow tCaptureStart]= PsychPortAudio('GetAudioData', pahandle);

        % Compute maximum signal amplitude in this chunk of data:
        if ~isempty(audiodata)
            level = max(abs(audiodata(1,:)));
        else
            level = 0;
        end
        
        % Below trigger-threshold?
        if level < triggerlevel
            % Wait for five milliseconds before next scan:
            WaitSecs(0.005);
        end
    end

    % Ok, last fetched chunk was above threshold!
    % Find exact location of first above threshold sample.
    idx = min(find(abs(audiodata(1,:)) >= triggerlevel)); %#ok<MXFND>
        
    % Compute absolute event time:
    tOnset = tCaptureStart + ((offset + idx - 1) / freq);
    
    % Stop sound capture:
    PsychPortAudio('Stop', pahandle);
    
    % Fetch all remaining audio data out of the buffer - Needs to be empty
    % before next trial:
    PsychPortAudio('GetAudioData', pahandle);
    
    % Print RT:
    fprintf('---> Reaction time is %f milliseconds.\n', (tOnset - tStim)*1000);
    
    % Next trial after 2 seconds:
    WaitSecs(2);
end

% Close the audio device:
PsychPortAudio('Close', pahandle);

% Done.
fprintf('Demo finished, bye!\n');

return;