/usr/share/psychtoolbox-3/PsychBasic/Snd.m is in psychtoolbox-3-common 3.0.14.20170103+git6-g605ff5c.dfsg1-1build1.
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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | function err = Snd(command,signal,rate,sampleSize)
% err = Snd(command,[signal],[rate],[sampleSize])
%
% Old Sound driver for Psychtoolbox. USE OF THIS DRIVER IS DEPRECATED FOR
% ALL BUT THE MOST TRIVIAL PURPOSES!
%
% Have a look at the help for PsychPortAudio ("help PsychPortAudio" and
% "help InitializePsychSound") for an introduction into the new sound
% driver, which is recommended for most purposes.
%
% Snd() is a rather dumb and primitive wrapper around the PsychPortAudio()
% driver. It uses PsychPortAudio's most basic functionality to achieve
% "sort of ok" sound playback. The driver is used in high-latency,
% low-timing precision mode, so Snd()'s audio playback timing will likely
% be very unreliable.
%
% Alternatively you can create an empty file named 'Snd_use_oldstyle.txt' in
% the PsychtoolboxConfigDir() folder, ie., [PsychtoolboxConfigDir 'Snd_use_oldstyle.txt']
% This will enable the old-style implementation of Snd(), which is equally
% shoddy and works as follows:
%
% While Snd used to use a special purpose low level driver on MacOS-9 which
% was well suited for cognitive science, Snd for all other operating
% systems (Windows, MacOS-X, Linux) just calls into Matlab's Sound()
% function which is of varying - but usually pretty poor - quality in most
% implementations of Matlab. There are many bugs, latency- and timing
% problems associated with the use of Snd.
%
% GNU/OCTAVE: If you don't use the PsychPortAudio based Snd() functin, then
% you must install the optional octave "audio" package from Octave-Forge,
% as of Octave 3.0.5, otherwise the required sound() function won't be
% available and this function will fail!
%
%
% Supported functions:
% --------------------
%
% Snd('Play', signal [, rate][, sampleSize]) plays a sound.
%
% rate=Snd('DefaultRate') returns the default sampling rate in Hz, which
% currently is 22254.5454545454 Hz on all platforms for the old style sound
% implementation, and the default device sampling rate if PsychPortAudio is
% used. This default may change in the future, so please either specify a
% rate, or use this function to get the default rate. (This default is
% suboptimal on any system except MacOS-9, but kept for backwards
% compatibility!)
%
% The optional 'sampleSize' argument used with Snd('Play') is only retained
% for backwards compatibility and has no meaning, unless you opt in to use
% the old-style implementation on Matlab with some operating systems. - It
% is checked for correctness, but other than that it is ignored. Allowable
% values are either 8 or 16.
%
% Snd('Open') opens the channel, which stays open until you call
% Snd('Close'). Snd('Play',...) automatically opens the channel if it isn't
% already open. In reality 'Open' does nothing in the current
% implementation and is silently ignored .
%
% Snd('Close') immediately stops all sound and closes the channel.
%
% Snd('Wait') waits until the sound is done playing.
%
% isPlaying=Snd('IsPlaying') returns true if any sound is playing, and
% false (0) otherwise.
%
% Snd('Quiet') stops the sound currently playing and flushes the queue, but
% leaves the channel open.
%
% "signal" must be a numeric array of samples.
%
% Your "signal" data should lie between -1 and 1 (smaller to play more
% softly). If the "signal" array has one row then it's played monaurally,
% through both speakers. If it has two rows then it's played in stereo.
% (Snd has no provision for changing which speaker(s), or the volume, used
% by a named snd resource, so use READSND to get the snd into an array,
% and supply the appropriately modified array to Snd.)
%
% "rate" is the rate (in Hz) at which the samples in "signal" should be
% played. We suggest you always specify the "rate" parameter. If not
% specified, the sample "rate", on all platforms, defaults to OS9's
% standard hardware sample rate of 22254.5454545454 Hz. That value is
% returned by Snd('DefaultRate'). Other values can be specified.
%
% OSX & WIN: "samplesize". Snd accepts the sampleSize argument and passes
% it to the Matlab SOUND command. SOUND (and therefore Snd also) obeys the
% specified sampleSize value, either 8 or 16, only if it is supported by
% your computer hardware.
%
% Snd('Play',sin(0:10000)); % play 22 KHz/(2*pi)=3.5 kHz tone
% Snd('Play',[sin(1:20000) zeros(1,10000);zeros(1,10000) sin(1:20000)]); % stereo
% Snd('Wait'); % wait until end of all sounds currently in channel
% Snd('Quiet'); % stop the sound and flush the queue
%
% For most of the commands, the returned value is zero when successful, and
% a nonzero error number when Snd fails.
%
% Snd('Play', signal) takes some time to open the channel, if it isn't
% already open, and allocate a snd structure for your sound. This overhead
% of the call to Snd, if you call it in the middle of a movie, may be
% perceptible as a pause in the movie, which would be bad. However, the
% actual playing of the sound, asynchronously, is a background process that
% usually has very little overhead. So, even if you want a sound to begin
% after the movie starts, you should create a soundtrack for your entire
% movie duration (possibly including long silences), and call Snd to set
% the sound going before you start your movie. (Thanks to Liz Ching for
% raising the issue.)
%
% NOTE: We suggest you always specify the "rate" parameter. If not
% specified, the sample rate, on all platforms, defaults to OS9's
% standard hardware sample rate of 22254.5454545454 Hz. That value is returned
% by Snd('DefaultRate').
%
% See also PsychPortAudio, Beeper, AUDIOPLAYER, PLAY, MakeBeep, READSND, and WRITESND.
% 6/6/96 dgp Wrote SndPlay.
% 6/1/97 dgp Polished help text.
% 12/10/97 dhb Updated help.
% 2/4/98 dgp Wrote Snd, based on major update of VideoToolbox SndPlay1.c.
% 3/8/00 emw Added PC notes and code.
% 7/23/00 dgp Added notes about controlling volume of named snd, and updated
% broken link to ResEdit.
% 4/13/02 dgp Warn that the two platforms have different default sampling rate,
% and suggest that everyone routinely specify sampling rate to
% make their programs platform-independent.
% 4/13/02 dgp Enhanced both OS9 and WIN versions so that 'DefaultRate'
% returns the default sampling rate in Hz.
% 4/13/02 dgp Changed WIN code, so that sampling rate is now same on both platforms.
% 4/15/02 awi fixed WIN code.
% 5/30/02 awi Added sampleSize argument and documented.
% SndTest would crash Matlab but the problem mysteriously vanished while editing
% the Snd.m and SndTest.m files. I've been unable to reproduce the error.
% 3/10/05 dgp Make it clear that the Snd mex is only available for OS9.
% Mention AUDIOPLAYER, as suggested by Pascal Mamassian.
% 5/20/08 mk Explain that Snd() is deprecated --> Point to PsychPortAudio!
% 1/12/09 mk Make sure that 'signal' is a 2-row matrix in stereo, not 2
% column.
% 6/01/09 mk Add compatibility with Octave-3.
% 9/03/12 mk Add new implementation via PsychPortAudio(), which is used
% by default unless user opts out. Cleanup online help by
% removal of obsolete and outdated information.
% 7/20/15 mk Make commands case insensitive, white-space cleanup, try to
% make Snd('Open'); Snd('Close'); sequences work to avoid problems
% like in PTB forum message #19284 on Linux or Windows.
% 1/19/16 mk Make more robust against failing InitializePsychSound. Fallback to sound().
persistent ptb_snd_oldstyle;
persistent pahandle;
persistent endTime;
if isempty(endTime)
endTime = 0;
end
% Default return value:
err = 0;
% Already defined if we shall use the new-style or old-style
% implementation?
if isempty(ptb_snd_oldstyle)
% Nope, check if the special "old style" marker file exists:
if exist([PsychtoolboxConfigDir 'Snd_use_oldstyle.txt'], 'file')
% User explicitely wants old-style implementation via
% Matlab/Octave sound() function:
ptb_snd_oldstyle = 1;
fprintf('Snd(): Using Matlab/Octave sound() function for sound output.\n');
else
% User wants new-style PsychPortAudio variant:
ptb_snd_oldstyle = 0;
fprintf('Snd(): Initializing PsychPortAudio driver for sound output.\n');
% Low-Latency preinit. Not that we'd need it, but doesn't hurt:
try
InitializePsychSound(1);
catch
fprintf('Snd(): ERROR!\n');
ple;
psychlasterror('reset');
fprintf('Snd(): PsychPortAudio initialization failed - See error messages above. Trying to use old sound() fallback instead.\n');
ptb_snd_oldstyle = 1;
end
end
end
if nargin == 0
error('Wrong number of arguments: see Snd.');
end
% Don't use PsychPortAudio backend if already a PPA device open on Linux or
% Windows, as that device will often have exclusive access, so we would
% fail here:
if ~(strcmpi(command,'Open') || strcmpi(command,'Quiet') || strcmpi(command,'Close')) && ...
isempty(pahandle) && ~ptb_snd_oldstyle && ~IsOSX && (PsychPortAudio('GetOpenDeviceCount') > 0)
fprintf('Snd(): PsychPortAudio already in use. Using old sound() fallback instead...\n');
ptb_snd_oldstyle = 1;
end
if strcmpi(command,'Play')
if nargin > 4
error('Wrong number of arguments: see Snd.');
end
if nargin == 4
if isempty(sampleSize)
sampleSize = 16;
elseif ~((sampleSize == 8) || (sampleSize == 16))
error('sampleSize must be either 8 or 16.');
end
else
sampleSize = 16;
end
if nargin < 3
rate = [];
end
if nargin < 2
error('Wrong number of arguments: see Snd.');
end
if size(signal,1) > size(signal,2)
error('signal must be a 2 rows by n column matrix for stereo sounds.');
end
if isempty(rate)
if ptb_snd_oldstyle
% Old MacOS-9 style default:
rate = 22254.5454545454;
else
% Let PPA decide itself:
rate = [];
end
end
if ptb_snd_oldstyle
% Old-Style implementation via sound() function:
WaitSecs(endTime-GetSecs); % Wait until any ongoing sound is done.
% Octave special-case:
if IsOctave
if exist('sound') %#ok<EXIST>
sound(signal',rate);
else
% Unavailable: Try to load the package, assuming its
% installed but not auto-loaded:
try
pkg('load','audio');
catch %#ok<CTCH>
end
% Retry...
if exist('sound') %#ok<EXIST>
sound(signal',rate);
else
warning('Required Octave command sound() is not available. Install and "pkg load audio" the "audio" package from Octave-Forge!'); %#ok<WNTAG>
end
end
else
sound(signal',rate,sampleSize);
end
% Estimate 'endTime' for playback:
endTime=GetSecs+length(signal)/rate;
else
% New-Style via PsychPortAudio:
if ~isempty(pahandle)
% PPA playback device already open.
% Wait blocking until end of its playback:
PsychPortAudio('Stop', pahandle, 1, 1);
% Correct sampling rate set?
props = PsychPortAudio('GetStatus', pahandle);
if ~isempty(rate) && (abs(props.SampleRate - rate) > 1.0)
% Device sampleRate not within tolerance of 1 Hz to
% requested samplingrate. Close it, so it can get reopened
% with proper rate:
PsychPortAudio('Close', pahandle);
pahandle = [];
end
end
if isempty(pahandle)
% Be silent during driver/device init:
oldverbosity = PsychPortAudio('Verbosity', 2);
% Open our own 'pahandle' sound device: Auto-Selected output
% device [], playback only (1),
% high-latency/low-timing-precision mode (0), at given
% samplerate (rate), in stereo (2):
pahandle = PsychPortAudio('Open', [], 1, 0, rate, 2);
% Restore standard level of verbosity:
PsychPortAudio('Verbosity', oldverbosity);
if ~IsOSX
fprintf('Snd(): PsychPortAudio will be blocked for use by your own code until you call Snd(''Close'');\n');
fprintf('Snd(): If you want to use PsychPortAudio and Snd in the same session, make sure to open your\n');
fprintf('Snd(): stimulation sound device via calls to PsychPortAudio(''Open'', ...); *before* the first\n');
fprintf('Snd(): call to Snd() or any function that might use Snd(), e.g., Beeper() and the Eyelink functions.\n\n');
end
end
% Make signal stereo if it isn't already:
if size(signal, 1) < 2
sndbuff = [signal ; signal];
else
sndbuff = signal;
end
% Play it:
PsychPortAudio('FillBuffer', pahandle, sndbuff);
PsychPortAudio('Start', pahandle, 1, 0, 1);
end
elseif strcmpi(command,'Wait')
if nargin>1
error('Wrong number of arguments: see Snd.');
end
if ~isempty(pahandle)
% Wait blocking until end of playback:
PsychPortAudio('Stop', pahandle, 1, 1);
else
WaitSecs(endTime-GetSecs); % Wait until any ongoing sound is done.
end
err=0;
elseif strcmpi(command,'IsPlaying')
if nargin>1
error('Wrong number of arguments: see Snd.');
end
if ~isempty(pahandle)
props = PsychPortAudio('GetStatus', pahandle);
err = props.Active;
else
if endTime>GetSecs
err=1;
else
err=0;
end
end
elseif strcmpi(command,'Quiet') || strcmpi(command,'Close')
if nargin>1
error('Wrong number of arguments: see Snd.');
end
if ~isempty(pahandle)
% Stop playback asap, wait for stop:
PsychPortAudio('Stop', pahandle, 2, 1);
% Close command?
if strcmpi(command,'Close')
% Close it:
PsychPortAudio('Close', pahandle);
pahandle = [];
end
else
if ~IsOctave
clear playsnd; % Stop any ongoing sound.
end
end
endTime=0;
err=0;
elseif strcmpi(command,'DefaultRate')
if nargin>1
error('Wrong number of arguments: see Snd.');
end
if ptb_snd_oldstyle
% Old style - old hard-coded default:
err = 22254.5454545454; % default sampling rate in Hz.
else
% Audio device open?
if isempty(pahandle)
% No: Fake it - Use the most common sampling rate:
err = 44100;
else
% Yes: Query its default sampling rate:
s = PsychPortAudio('GetStatus', pahandle);
di = PsychPortAudio('GetDevices', [], s.OutDeviceIndex);
err = di.DefaultSampleRate;
end
end
elseif strcmpi(command,'Open')
endTime=0;
else
PsychPortAudio('Close');
pahandle = [];
error(['unknown command "' command '"']);
end
return;
|