function NoiseDemo
% NoiseDemo. Make and show a movie consisting of dynamic white noise.
% You can adjust check size, check duration, and choose any of several amplitude 
% distributions: binary, uniform, or gaussian. All in 56 lines plus comments.
%
% See also MovieDemo, GratingDemo, and DriftDemo.

% 2/22/02	dgp	 Wrote it.
% 2/26/02	dgp	 Shorter.
% 9/25/03   dhb  Open max screen, not explicit screen 1.

fprintf('NoiseDemo\n');

% Open a window 
screenNumber=max(Screen('Screens'));
noiseKind='gaussian';
imageSize=256; % width & height of displayed image, in pixels
checkSize=4; % width & height of each noise check, in pixels
checkFrames=1; % duration of each noise check, in frames
frames=4*FrameRate(screenNumber); % 4 second's worth
imageSize=round(imageSize/checkSize)*checkSize;
frames=round(frames/checkFrames)*checkFrames;
black=BlackIndex(screenNumber);
white=WhiteIndex(screenNumber);
gray=round((white+black)/2);
window=Screen(screenNumber,'OpenWindow',gray);

% noiseList
rand('state',getsecs); % random seed
switch noiseKind
case 'gaussian', %clipped at +-2 standard deviations.
	noiseBound=2;
	temp=randn([1,20000]);
	noiseList=find(sign(temp.^2-noiseBound^2)-1);
	noiseList=temp(noiseList);
	clear temp;
	noiseList=noiseList/noiseBound;
case 'uniform',
	noiseList=-1:1/1024:1;
case 'binary',
	noiseList=[-1 1];
otherwise,
	fprintf('Unknown noiseKind "%s".\n',noiseKind);
	return;
end
noiseListPower=std(noiseList,1)^2;

% Make the movie.
inc=white-gray;
checks=imageSize/checkSize;
rect=round([0 0 imageSize imageSize]);
noise=zeros(checks,checks);
for i=1:frames
	if checkFrames==1 | mod(i,checkFrames)==1
		noise=gray+inc*randsample(noiseList,size(noise)); % one sample per check
	end
    w(i)=Screen(screenNumber,'OpenOffscreenWindow',gray,rect);
    Screen(w(i),'PutImage',noise,rect); % expand each sample to make a check
end;
w(frames+1)=Screen(screenNumber,'OpenOffscreenWindow',gray,rect);

% Show the movie, using Rush to minimize interruptions.
rect2=CenterRect(rect,Screen(window,'Rect'));
loop={
	'for i=1:frames+1;'
		'Screen(window,''WaitBlanking'');'
		'Screen(''CopyWindow'',w(i),window,rect,rect2);'
	'end;'
};
HideCursor;
priorityLevel=MaxPriority(screenNumber,'WaitBlanking');
Rush(loop,priorityLevel);
ShowCursor;
Screen('CloseAll');

% Report the power spectal density of the noise.
fprintf('Dynamic white noise, drawn from a %s distribution.\n',noiseKind);
fprintf('The rms contrast is\n');
fprintf('crms = %g\n', noiseListPower^0.5*(inc/gray));
fprintf('However, the rms contrast (and its squared value, the contrast power) is\n');
fprintf('of little relevance in specifying this as a visual stimulus. Usually\n');
fprintf('your noise will be white, i.e. have a flat spectrum out to a bandwidth\n');
fprintf('that exceeds that of the mechanism (visual channel) under study. The\n');
fprintf('total power reflects the noise bandwidth, most of which is invisible to\n');
fprintf('the channel. The proper statistic to specify the noise as a visual\n');
fprintf('stimulus is the power spectral density N. It is the contrast power per\n');
fprintf('unit frequency interval (i.e. 1 c/deg c/deg Hz). For white noise made\n');
fprintf('up of independent checks, N equals the product of the contrast power\n');
fprintf('and the area*duration of one check.\n');
fprintf('N = %g sec pixel^2\n',noiseListPower*(inc/gray)^2*checkSize*checkSize*checkFrames/FrameRate(screenNumber));
fprintf('Once you know the viewing distance you should convert "pixel" to "deg"\n');
fprintf('of visual angle.\n\n');
fprintf('See Pelli, D.G. and Farell, B. (1999) Why use noise? J Opt Soc Am A Opt Image Sci Vis, 16 (3), 647-53.\n');
fprintf('PDF file available at:\n');
fprintf('web http://psych.nyu.edu/pelli/ ;\n');
